1/** 2 * jquery-select-hierarchy 3 * 4 * Turns a single select containing breadcrumb trails into multiple dynamic selects to allow easy drill-down 5 * 6 * Author: Andrew Ingram ([email protected]) 7 */ 8(function ($) { 9 $.fn.selectHierarchy = function(options) { 10 var defaults = { 11 separator: ' > ', 12 hideOriginal: true, 13 placeholder: '------' 14 }; 15 var options = $.extend(defaults, options); 16 var obj = $(this); 17 var max_depth = 1; 18 19 var choices = obj.find('option').map(function(){ 20 var val = $(this).val(); 21 22 if (val) { 23 var txt = $(this).text(); 24 var segments = txt.split(options.separator); 25 var depth = segments.length; 26 27 if (depth > max_depth) { 28 max_depth = depth; 29 } 30 31 var result = { 32 label: txt, 33 short_label: segments[depth-1], 34 value: val, 35 depth: depth, 36 children: [] 37 }; 38 39 return result; 40 } 41 }); 42 43 var roots = []; 44 45 // Build up child values 46 for (var depth=1; depth<=max_depth; depth++) { 47 $.each(choices, function() { 48 var parent = this; 49 50 if (parent.depth==depth) { 51 if (depth===1) { 52 roots.push(this); 53 } 54 55 $.each(choices, function() { 56 var child = this; 57 if (child.depth == depth+1 && child.label.match("^"+parent.label)==parent.label) { 58 parent.children.push(child); 59 } 60 }); 61 } 62 }); 63 } 64 65 if (options.hideOriginal) { 66 obj.hide(); 67 } 68 obj.wrap('<span class="drilldown-wrapper" />'); 69 obj.after('<select class="drilldown-1"><option value="">' + options.placeholder + '</option></select>'); 70 var root_select = obj.next(); 71 72 root_select.data('depth', 1); 73 74 $.each(roots, function(){ 75 var opt = $('<option>'); 76 opt.val(this.value); 77 opt.text(this.short_label); 78 opt.data('node', this); 79 root_select.append(opt); 80 }); 81 82 var change_handler = function(){ 83 var this_select = $(this); 84 var opt = this_select.find('option:selected'); 85 var node = opt.data('node'); 86 87 if (this_select.val()) { 88 obj.val(this_select.val()); 89 } else if (this_select.data('depth') > 1) { 90 obj.val(this_select.prev().val()); 91 } else { 92 obj.val(''); 93 } 94 95 this_select.nextAll('select').remove(); 96 97 // Check to see if there's any children, if there are we build another select box; 98 if (node && node.children.length > 0) { 99 this_select.after('<select><option value="">' + options.placeholder +'</option></select>'); 100 101 var next_select = this_select.next(); 102 next_select.addClass('drilldown-' + (node.depth + 1)); 103 next_select.data('depth', node.depth + 1); 104 105 $.each(node.children, function(){ 106 var opt = $('<option>'); 107 opt.val(this.value); 108 opt.text(this.short_label); 109 opt.data('node', this); 110 next_select.append(opt); 111 }); 112 next_select.change(change_handler); 113 } 114 } 115 root_select.change(change_handler); 116 117 // After setting up the behavior, set the drilldown select lists to the correct values for 118 // forms with a default value. 119 120 // Build an object of the choices keyed by short_label. 121 var choices_by_short_label = {}; 122 $.each(choices, function() { 123 choices_by_short_label[(this).short_label] = (this); 124 }); 125 126 // Break selected label into segments/short_labels 127 var selected_label = obj.find(' option:selected').text(); 128 var segments = selected_label.split(options.separator); 129 130 // Loop over the segments of the selected value and select the appropriate values on the 131 // drilldown select lists. 132 var counter = 1; 133 $.each(segments, function() { 134 if(choices_by_short_label[(this)]) { 135 $('select.drilldown-' + counter, obj.parent()).val(choices_by_short_label[(this)].value); 136 $('select.drilldown-' + counter, obj.parent()).change(); 137 } 138 counter++; 139 }); 140 }; 141})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.