1(function ($) { 2 Drupal.behaviors.improved_multi_select = { 3 attach: function(context, settings) { 4 if (settings.improved_multi_select && settings.improved_multi_select.selectors) { 5 var options = settings.improved_multi_select; 6 7 for (var key in options.selectors) { 8 var selector = options.selectors[key]; 9 $(selector, context).once('improvedselect', function() { 10 var $select = $(this), 11 moveButtons = '', 12 improvedselect_id = $select.attr('id'), 13 $cloned_select = null, 14 cloned_select_id = ''; 15 if (options.orderable) { 16 // If the select is orderable then we clone the original select 17 // so that we have the original ordering to use later. 18 $cloned_select = $select.clone(); 19 cloned_select_id = $cloned_select.attr('id'); 20 cloned_select_id += '-cloned'; 21 $cloned_select.attr('id', cloned_select_id); 22 $cloned_select.removeAttr('name'); 23 $cloned_select.appendTo($select.parent()).hide(); 24 // Move button markup to add to the widget. 25 moveButtons = '<span class="move_up" sid="' + $select.attr('id') + '">' + Drupal.checkPlain(options.buttontext_moveup) + '</span>' + 26 '<span class="move_down" sid="' + $select.attr('id') + '">' + Drupal.checkPlain(options.buttontext_movedown) + '</span>'; 27 } 28 $select.parent().append( 29 '<div class="improvedselect" sid="' + $select.attr('id') + '" id="improvedselect-' + $select.attr('id') + '">' + 30 '<div class="improvedselect-text-wrapper">' + 31 '<input type="text" class="improvedselect_filter" sid="' + $select.attr('id') + '" prev="" />' + 32 '</div>' + 33 '<ul class="improvedselect_sel"></ul>' + 34 '<ul class="improvedselect_all"></ul>' + 35 '<div class="improvedselect_control">' + 36 '<span class="add" sid="' + $select.attr('id') + '">' + Drupal.checkPlain(options.buttontext_add) + '</span>' + 37 '<span class="del" sid="' + $select.attr('id') + '">' + Drupal.checkPlain(options.buttontext_del) + '</span>' + 38 '<span class="add_all" sid="' + $select.attr('id') + '">' + Drupal.checkPlain(options.buttontext_addall) + '</span>' + 39 '<span class="del_all" sid="' + $select.attr('id') + '">' + Drupal.checkPlain(options.buttontext_delall) + '</span>' + 40 moveButtons + 41 '</div>' + 42 '<div class="clear"></div>' + 43 '</div>'); 44 if ($select.find('optgroup').has('option').length > 0) { 45 $select.parent().find('.improvedselect').addClass('has_group'); 46 // Build groups. 47 $('#improvedselect-' + improvedselect_id + ' .improvedselect-text-wrapper', context) 48 .after('<div class="improvedselect_tabs-wrapper" sid="' + $select.attr('id') + '"><ul class="improvedselect_tabs"></ul></div>'); 49 $select.find('optgroup').has('option').each(function() { 50 $('#improvedselect-' + improvedselect_id + ' .improvedselect_tabs', context) 51 .append('<li><a href="">' + $(this).attr('label') + '</a></li>'); 52 }); 53 // Show all groups option. 54 $('#improvedselect-' + improvedselect_id + ' .improvedselect_tabs', context) 55 .prepend('<li class="all"><a href="">' + Drupal.t('All') + '</a></li>'); 56 // Select group. 57 $('#improvedselect-' + improvedselect_id + ' .improvedselect_tabs li a', context).click(function(e) { 58 var $group = $(this), 59 sid = $group.parent().parent().parent().attr('sid'); 60 $('#improvedselect-' + improvedselect_id + ' .improvedselect_tabs li.selected', context).removeClass('selected').find('a').unwrap(); 61 $group.wrap('<div>').parents('li').first().addClass('selected'); 62 63 // Any existing selections in the all list need to be unselected 64 // if they aren't part of the newly selected group. 65 if (!$group.hasClass('all')) { 66 $('#improvedselect-' + improvedselect_id + ' .improvedselect_all li.selected[group!=' + $group.text() + ']', context).removeClass('selected'); 67 } 68 69 // Clear the filter if we have to. 70 if (options.groupresetfilter) { 71 // Clear filter box. 72 $('#improvedselect-' + improvedselect_id + ' .improvedselect_filter',
72context).val(''); 73 } 74 // Force re-filtering. 75 $('#improvedselect-' + improvedselect_id + ' .improvedselect_filter', context).attr('prev', ''); 76 // Re-filtering will handle the rest. 77 improvedselectFilter(sid, options, context); 78 e.preventDefault(); 79 }); 80 // Select all to begin. 81 $('#improvedselect-' + improvedselect_id + ' .improvedselect_tabs li.all a', context).click(); 82 } 83 84 $select.find('option, optgroup').each(function() { 85 var $opt = $(this), 86 group = ''; 87 if ($opt.attr('tagName') == 'OPTGROUP') { 88 if ($opt.has('option').length) { 89 $('#improvedselect-'+ improvedselect_id +' .improvedselect_all', context) 90 .append('<li isgroup="isgroup" so="---' + $opt.attr('label') + '---">--- '+ $opt.attr('label') +' ---</li>'); 91 } 92 } 93 else { 94 group = $opt.parent("optgroup").attr("label"); 95 if (group) { 96 group = ' group="' + group + '"'; 97 } 98 if ($opt.attr('value') != "_none") { 99 if ($opt.attr('selected')) { 100 $('#improvedselect-' + improvedselect_id + ' .improvedselect_sel', context) 101 .append('<li so="' + $opt.attr('value') + '"' + group + '>' + $opt.text() + '</li>'); 102 } 103 else { 104 $('#improvedselect-' + improvedselect_id + ' .improvedselect_all', context) 105 .append('<li so="' + $opt.attr('value') + '"' + group + '>' + $opt.text() + '</li>'); 106 } 107 } 108 } 109 }); 110 $('#improvedselect-'+ improvedselect_id + ' .improvedselect_sel li, #improvedselect-' + improvedselect_id + ' .improvedselect_all li[isgroup!="isgroup"]', context).click(function() { 111 $(this).toggleClass('selected'); 112 }); 113 $select.hide(); 114 // Double click feature request. 115 $('#improvedselect-'+ improvedselect_id + ' .improvedselect_sel li, #improvedselect-' + improvedselect_id + ' .improvedselect_all li[isgroup!="isgroup"]', context).dblclick(function() { 116 // Store selected items. 117 var selected = $(this).parent().find('li.selected'), 118 current_class = $(this).parent().attr('class'); 119 // Add item. 120 if (current_class == 'improvedselect_all') { 121 $(this).parent().find('li.selected').removeClass('selected'); 122 $(this).addClass('selected'); 123 $(this).parent().parent().find('.add').click(); 124 } 125 // Remove item. 126 else { 127 $(this).parent().find('li.selected').removeClass('selected'); 128 $(this).addClass('selected'); 129 $(this).parent().parent().find('.del').click(); 130 } 131 // Restore selected items. 132 if (selected.length) { 133 for (var k = 0; k < selected.length; k++) { 134 if ($(selected[k]).parent().attr('class') == current_class) { 135 $(selected[k]).addClass('selected'); 136 } 137 } 138 } 139 }); 140 141 // Set the height of the select fields based on the height of the 142 // parent, otherwise it can end up with a lot of wasted space. 143 $('.improvedselect_sel, .improvedselect_all').each(function() { 144 $(this).height($(this).parent().height() - 35); 145 }); 146 }); 147 } 148 149 $('.improvedselect_filter', context).bind('input', function() { 150 improvedselectFilter($(this).attr('sid'), options, context); 151 }); 152 153 // Add selected items. 154 $('.improvedselect .add', context).click(function() { 155 var sid = $(this).attr('sid'); 156 $('#improvedselect-' + sid + ' .improvedselect_all .selected', context).each(function() { 157 $opt = $(this); 158 $opt.removeClass('selected'); 159 improvedselectUpdateGroupVisibility($opt, 1); 160 $('#improvedselect-' + sid + ' .improvedselect_sel', context).append($opt); 161 }); 162 improvedselectUpdate(sid, context); 163 }); 164 165 // Remove selected items. 166 $('.improvedselect .del', context).click(function() { 167 var sid = $(this).attr('sid'); 168 $('#improvedselect-' + sid + ' .improvedselect_sel .selected', context).each(function() { 169 $opt = $(this); 170 $opt.removeClass('selected'); 171 $('#improvedselect-' + sid + ' .improvedselect_all', context).append($opt); 172 improvedselectUpdateGroupVisibility($opt, 0); 173 }); 174 // Force re-filtering. 175 $('#improvedselect-' + sid + ' .improvedselect_filter',
175context).attr('prev', ''); 176 // Re-filtering will handle the rest. 177 improvedselectFilter(sid, options, context); 178 improvedselectUpdate(sid, context); 179 }); 180 181 // Add all items. 182 $('.improvedselect .add_all', context).click(function() { 183 var sid = $(this).attr('sid'); 184 $('#improvedselect-' + sid + ' .improvedselect_all li[isgroup!=isgroup]', context).each(function() { 185 $opt = $(this); 186 if ($opt.css('display') != 'none') { 187 $opt.removeClass('selected'); 188 improvedselectUpdateGroupVisibility($opt, 1); 189 $('#improvedselect-' + sid + ' .improvedselect_sel', context).append($opt); 190 } 191 }); 192 improvedselectUpdate(sid, context); 193 }); 194 195 // Remove all items. 196 $('.improvedselect .del_all', context).click(function() { 197 var sid = $(this).attr('sid'); 198 $('#improvedselect-' + sid + ' .improvedselect_sel li', context).each(function() { 199 $opt = $(this); 200 $opt.removeClass('selected'); 201 $('#improvedselect-' + sid + ' .improvedselect_all', context).append($opt); 202 improvedselectUpdateGroupVisibility($opt, 0); 203 }); 204 // Force re-filtering. 205 $('#improvedselect-' + sid + ' .improvedselect_filter', context).attr('prev', ''); 206 // Re-filtering will handle the rest. 207 improvedselectFilter(sid, options, context); 208 improvedselectUpdate(sid, context); 209 }); 210 211 // Move selected items up. 212 $('.improvedselect .move_up', context).click(function() { 213 var sid = $(this).attr('sid'); 214 $('#improvedselect-' + sid + ' .improvedselect_sel .selected', context).each(function() { 215 var $selected = $(this); 216 // Don't move selected items past other selected items or there will 217 // be problems when moving multiple items at once. 218 $selected.prev(':not(.selected)').before($selected); 219 }); 220 improvedselectUpdate(sid, context); 221 }); 222 223 // Move selected items down. 224 $('.improvedselect .move_down', context).click(function() { 225 var sid = $(this).attr('sid'); 226 // Run through the selections in reverse, otherwise problems occur 227 // when moving multiple items at once. 228 $($('#improvedselect-' + sid + ' .improvedselect_sel .selected', context).get().reverse()).each(function() { 229 var $selected = $(this); 230 // Don't move selected items past other selected items or there will 231 // be problems when moving multiple items at once. 232 $selected.next(':not(.selected)').after($selected); 233 }); 234 improvedselectUpdate(sid, context); 235 }); 236 // Let other scripts know improvedSelect was initialized 237 $.event.trigger('improvedMultiSelectInitialized', [$(this)]); 238 } 239 // Let other scripts know improvedSelect has been attached 240 $.event.trigger('improvedMultiSelectAttached'); 241 } 242 }; 243 244 /** 245 * Filter the all options list. 246 */ 247 function improvedselectFilter(sid, options, context) { 248 $filter = $('.improvedselect_filter', context); 249 // Get current selected group. 250 var $selectedGroup = $('#improvedselect-' + sid + ' .improvedselect_tabs li.selected:not(.all) a', context), 251 text = $filter.val(), 252 pattern, 253 regex, 254 words; 255 256 if (text.length && text != $filter.attr('prev')) { 257 $filter.attr('prev', text); 258 switch (options.filtertype) { 259 case 'partial': 260 default: 261 pattern = text; 262 break; 263 case 'exact': 264 pattern = '^' + text + '$'; 265 break; 266 case 'anywords': 267 words = text.split(' '); 268 pattern = ''; 269 for (var i = 0; i < words.length; i++) { 270 if (words[i]) { 271 pattern += (pattern) ? '|\\b' + words[i] + '\\b' : '\\b' + words[i] + '\\b'; 272 } 273 } 274 break; 275 case 'anywords_partial': 276 words = text.split(' '); 277 pattern = ''; 278 for (var i = 0; i < words.length; i++) { 279 if (words[i]) { 280 pattern += (pattern) ? '|' + words[i] + '' : words[i]; 281 } 282 } 283 break; 284 case 'allwords': 285 words = text.split(' '); 286 pattern = '^'; 287 // Add a lookahead for each individual word. 288 // Lookahead is used because the words can match in any order 289 // so this makes it simpler and faster. 290 for (var i = 0; i < words.length; i++) { 291 if (words[i]) { 292 pattern += '(?=.*?\\b' + words[i] + '\\b)'; 293 } 294 } 295 break; 296 case 'allwords_partial': 297 words = text.split(' '); 298 pattern = '^'; 299 // Add a lookahead for each individual word. 300 // Lookahead is used because the words can match in any order 301 // so this makes it simpler and faster. 302 for (var i = 0; i < words.length; i++) { 303 if (words[i]) { 304 pattern += '(?=.*?' + words[i] + ')'; 305 } 306 } 307 break; 308 } 309 310 regex = new RegExp(pattern,'i'); 311 $('#improvedselect-' + sid + ' .improvedselect_all li', context).each(function() { 312 $opt = $(this); 313 if ($opt.attr('isgroup') != 'isgroup') { 314 var str = $opt.text(); 315 if (str.match(regex) && (!$selectedGroup.length || $selectedGroup.text() == $opt.attr('group'))) { 316 $opt.show(); 317 if ($opt.attr('group')) { 318 // If a group is selected we don't need to show groups. 319 if (!$selectedGroup.length) { 320 $opt.siblings('li[isgroup="isgroup"][so="---' + $opt.attr('group') + '---"]').show(); 321 } 322 else { 323 $opt.siblings('li[isgroup="isgroup"][so="---' + $opt.attr('group') + '---"]').hide(); 324 } 325 } 326 } 327 else { 328 $opt.hide(); 329 if ($opt.attr('group')) { 330 if ($opt.siblings('li[isgroup!="isgroup"][group="' + $opt.attr('group') + '"]:visible').length == 0) { 331 $opt.siblings('li[isgroup="isgroup"][so="---' + $opt.attr('group') + '---"]').hide(); 332 } 333 } 334 } 335 } 336 }); 337 } 338 else { 339 if (!text.length) { 340 $filter.attr('prev', ''); 341 } 342 $('#improvedselect-' + sid + ' .improvedselect_all li', context).each(function() { 343 var $opt = $(this); 344 if ($opt.attr('isgroup') != 'isgroup') { 345 if (!$selectedGroup.length || $selectedGroup.text() == $opt.attr('group')) { 346 $opt.show(); 347 } 348 else { 349 $opt.hide(); 350 } 351 improvedselectUpdateGroupVisibility($opt, 0); 352 } 353 }); 354 } 355 } 356 357 /** 358 * Update the visibility of an option's group. 359 * 360 * @param $opt 361 * A jQuery object of a select option. 362 * @param numItems 363 * How many items should be considered an empty group. Generally zero or one 364 * depending on if an item has been or is going to be removed or added. 365 */ 366 function improvedselectUpdateGroupVisibility($opt, numItems) { 367 var $selectedGroup = $opt.parents('.improvedselect').first().find('.improvedselect_tabs li.selected:not(.all) a'); 368 369 // Don't show groups if a group is selected. 370 if ($opt.parent().children('li[isgroup!="isgroup"][group="' + $opt.attr('group') + '"]:visible').length <= numItems || $selectedGroup.length) { 371 $opt.siblings('li[isgroup="isgroup"][so="---' + $opt.attr('group') + '---"]').hide(); 372 } 373 else { 374 $opt.siblings('li[isgroup="isgroup"][so="---' + $opt.attr('group') + '---"]').show(); 375 } 376 } 377 378 function improvedselectUpdate(sid, context) { 379 // If we have sorting enabled, make sure we have the results sorted. 380 var $select = $('#' + sid),
381 $cloned_select = $('#' + sid + '-cloned'); 382 383 if ($cloned_select.length) { 384 $select.find('option, optgroup').remove(); 385 $('#improvedselect-' + sid + ' .improvedselect_sel li', context).each(function() { 386 var $li = $(this); 387 $select.append($('<option></option').attr('value', $li.attr('so')).attr('selected', 'selected').text($li.text())); 388 }); 389 } 390 else { 391 $select.find('option:selected').attr("selected", ""); 392 $('#improvedselect-' + sid + ' .improvedselect_sel li', context).each(function() { 393 $('#' + sid + ' [value="' + $(this).attr('so') + '"]', context).attr("selected", "selected"); 394 }); 395 } 396 397 if (!$cloned_select.length) { 398 $select.find('option, optgroup').each(function() { 399 $opt = $(this); 400 if ($opt.attr('tagName') == 'OPTGROUP') { 401 if ($opt.has('option').length) { 402 $('#improvedselect-' + sid + ' .improvedselect_all', context).append($('#improvedselect-' + sid + ' .improvedselect_all [so="---' + $opt.attr('label') + '---"]', context)); 403 } 404 } 405 else { 406 if ($opt.attr("selected")) { 407 $('#improvedselect-' + sid + ' .improvedselect_sel', context).append($('#improvedselect-' + sid + ' .improvedselect_sel [so="' + $opt.attr('value') + '"]', context)); 408 } 409 else { 410 $('#improvedselect-' + sid + ' .improvedselect_all', context).append($('#improvedselect-' + sid + ' .improvedselect_all [so="' + $opt.attr('value') + '"]', context)); 411 } 412 } 413 }); 414 } 415 // Don't use the $select variable here as it might be the clone. 416 // Tell the ajax system the select has changed. 417 $('#' + sid, context).trigger('change'); 418 } 419 420})(jQuery, Drupal); 421;
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.