1(function($) { 2 3 4 /** ---------------------------------------------------------------------------------- 5 * WPCS SELECT 6 */ 7 $.fn.wpcsselect = function(options) { 8 9 var defaults = { 10 onRefresh: function() {}, 11 onSelect: function() {}, 12 handle_selector: '.wpcs_select_handle', 13 loading_selector: '.wpcs_select_loading', 14 clear_selector: '.wpcs_select_delete', 15 arrow_selector: '.wpcs_select_arrow', 16 value_selector: null, 17 list_selector: '#wpcs_select_list', 18 target: null, 19 }; 20 21 var settings = $.extend({}, defaults, options); 22 23 if (settings.target !== null) { 24 settings.value_selector = settings.target; 25 } else { 26 settings.value_selector = ".wpcs_select_value"; 27 //settings.value_selector = "#wpcs_select_value_" + $(this).data('field'); 28 } 29 30 31 /** 32 * 33 * @param element 34 * @returns {*} 35 * @private 36 */ 37 function _create(select) { 38 let element = $(select); 39 40 // Guard: bereits initialisiert â keine neuen Handler registrieren 41 if (element.data('wpcsselect-init')) { 42 return element; 43 } 44 element.data('wpcsselect-init', true); 45 46 let ul; 47 ul = $('ul' + settings.list_selector); 48 if (ul.length < 1) { 49 ul = $('<ul id="wpcs_select_list"><li class="wpcs_search_li"><input type="text" class="wpcs_select_search" /></li></ul>'); 50 $('body').append(ul); 51 } 52 53 _initSearch(element); 54 _initialize(element); 55 _initClear(element); 56 57 return element; 58 } 59 60 function _initClear(element) { 61 $(settings.clear_selector, element).click(function() { 62 _unset_value(element); 63 }); 64 } 65 66 67 function _initSearch(element) { 68 69 $(settings.list_selector + ' li input.wpcs_select_search').keyup(function() { 70 let text = $(this).val().toLowerCase(); 71 72 $(settings.list_selector + ' li.wpcs_select_option').each(function() { 73 let dataValue = $(this).data("value").toString().toLowerCase(); 74 if (!dataValue || !dataValue.includes(text)) { 75 $(this).hide(); // Ausblenden des LI-Elements 76 } else { 77 $(this).show(); 78 } 79 }); 80 }); 81 82 } 83 84 /** 85 * 86 * @param element 87 * @private 88 */ 89 function _initialize(element) { 90 $(settings.handle_selector + ', ' + settings.arrow_selector, element) 91 .click(function() { 92 if ($(element).hasClass('open')) { 93 _close(element); 94 } else { 95 _close($('div.wpcsselect.open')); 96 _open(element); 97 } 98 }) 99 .keydown(function(e) { 100 if(e.key === 'Enter' || e.key === ' ' ) { 101 e.preventDefault(); 102 $(this).trigger('click'); 103 } 104 }) 105 ; 106 107 108 } 109 110 /** 111 * 112 * @param select 113 * @private 114 */ 115 function _init_options(element) { 116 let multiple = element.data('multiple'); 117 118 // Kein auto-focus beim Ãffnen â Focus nur bei Keyboard-Navigation 119 120 $(settings.list_selector + ' li') 121 .click(function() { 122 123 if($(this).data('optgroup')) { 124 let group = $(this).data('value'); 125 let li = $(settings.list_selector + ' li[data-group="'+group+'"]'); 126 127 let set_active = true; 128 129 li.each(function() { 130 if($(this).hasClass('active')) { 131 $(this).removeClass('active'); 132 set_active = false; 133 } 134 }); 135 136 if(set_active) li.addClass('active'); 137 138 _set_multiple_value(element); 139 } 140 141 else if (multiple > 0 && $(this).hasClass('wpcs_select_option')) { 142 $(this).toggleClass('active'); 143 _set_multiple_value(element); 144 } 145 146 else if($(this).hasClass('wpcs_select_option')) { 147 // Always set value, no toggle behavior (clicking same option keeps it selected) 148 _set_value(element, $(this).attr('data-index')); 149 _close(element); 150 } 151 152 settings.onSelect.call(); 153 }) 154 .keydown(function(e) { 155 156 if(e.key === "Tab") { 157 if(parseInt($(this).data('index')) === $(settings.list_selector + ' li.wpcs_select_option').length - 1) { 158 _close(element); 159 $('.wpcs_select_arrow',element).trigger('focus'); 160 } 161 } 162 163 if(e.key === "Enter" || e.key === " ") { 164 $(this).trigger('click'); 165 } 166 }) 167 ; 168 169 } 170 171 function _open_now(element) { 172 let multiple = parseInt($(element).data('multiple')); 173 174 $(element).addClass('open'); 175 176 _calculate_position(); 177 178 let ul = $('ul' + settings.list_selector); 179 ul.addClass('open'); 180 181 let search = $('.wpcs_search_li', ul); 182 // empty search 183 $('.wpcs_select_search', search).val(""); 184 185 // toggle search 186 let hasSearch = element.data('search') || 0; 187 if(hasSearch < 1) search.hide(); 188 else search.show(); 189 190 if (multiple > 0) ul.addClass('multiple'); 191 else ul.removeClass('multiple'); 192 193 } 194 195 /** 196 * 197 * @param select 198 * @private 199 */ 200 function _open(element) { 201 202 // fülle auswahlliste 203 if (settings.ajax) { _createListFromAjax(element); } else { _createListFromDataDiv(element); } 204 205 window.setTimeout(function(){ 206 $(document).bind('click', _close_current); 207 $(window).bind('resize', _calculate_position); 208 }, 10); 209 } 210 211 function _calculate_position() { 212 let element = $('div.wpcsselect.open'); 213 let handle = $(settings.handle_selector, element); 214 let handlePos = $(settings.handle_selector, element).offset(); 215 216 // positioniere auswahlliste 217 let ul = $('ul' + settings.list_selector); 218 ul.css({ 219 top: handlePos.top + handle.height(), 220 left: handlePos.left, 221 width: handle.outerWidth() 222 }); 223 224 } 225 226 /** 227 * 228 * @private 229 */ 230 function _close_current(e) { 231 if ( 232 !$(e.target).hasClass('wpcs_select_option') && 233 !$(e.target).hasClass('wpcs_select_search') && 234 !$(e.target).hasClass('wpcs_select_handle') && 235 !$(e.target).hasClass('wpcs_select_arrow') && 236 !$(e.target).hasClass('wpcs_select_multiple_checkbox')) { 237 _close($('div.wpcsselect.open')); 238 } 239 240 241 } 242 243 /** 244 * 245 * @param select 246 * @private 247 */ 248 function _close(element) { 249 $(element).removeClass('open'); 250 $('ul' + settings.list_selector).removeClass('open'); 251 $(document).unbind('click', _close_current); 252 $(window).unbind('resize', _calculate_position); 253 254 $('.wpcs_select_arrow',element).trigger('focus'); 255 } 256 257 /** 258 * 259 * @param select 260 * @param list 261 * @private 262 */ 263 function _refresh(element, list, sel) { 264 265 _open_now(element); 266 267 // selected value kann übergeben werden, 268 // alternativ wird nach aktuellem Value gesucht 269 // ansonstem keine vorselektierung 270 let selected = sel || null; 271 let selected_value; 272 let multiple = element.data('multiple'); 273 274 if (selected !== null) selected_value = selected; 275 else selected_value = $(settings.value_selector, element).val() || ''; 276 277 if (multiple > 0) { 278 selected_value = selected_value.split(","); 279 if (!Array.isArray(selected_value)) selected_value = []; 280 } 281 282 let ul = $('ul' + settings.list_selector); 283 let selected_index = ""; 284 $('li.wpcs_select_option', ul).remove(); 285 286 let i = 0; 287 for (let [index, obj] of list) { 288 289 if (obj.value == "#" && multiple > 0 && list.size != 1) continue; 290 291 let active_class = ''; 292 if (multiple > 0 && obj.value != "#") { 293 let active = selected_value.some(function(array_element) { 294 return array_element == obj.value; 295 }); 296 active_class = active > 0 ? 'active' : ''; 297 } 298 299 let elementHtml = '<li class="wpcs_select_option ' + active_class + '" ' + 300 'data-value="' + obj.value + '" ' + 301 'data-label="' + obj.label + '" ' + 302 'data-optgroup="' + obj.is_group + '" ' + 303 'data-group="' + obj.group + '" ' + 304 'data-index="' + obj.index + '"' + 305 'tabindex="0"' + 306 'role="button"' + 307 '>'; 308 elementHtml += obj.label; 309 elementHtml += '</li>'; 310 311 let option = $(elementHtml); 312 if (selected_value == obj.value) { 313 selected_index = i; 314 } 315 ul.append(option); 316 i++; 317 } 318 319 _init_options(element); 320 321 if (multiple > 0) _set_multiple_value(element); 322 else _set_value(element, selected_index); 323 324 settings.onRefresh.call(); 325 } 326 327 328 function _unset_value(element) { 329 330 // unset old 331 $(settings.list_selector + ' li.selected').removeClass('selected'); 332 333 // refresh handle label 334 $(settings.handle_selector, element).html(element.data('nothing-selected')); 335 336 // set value to form element 337 $(settings.value_selector, element).val(""); 338 339 $(settings.clear_selector, element).hide(); 340 341 settings.onSelect.call(); 342 343 } 344 345 /** 346 * 347 * @param select 348 * @param index 349 * @private 350 */ 351 function _set_value(element, index) { 352 if(index === "") return; 353 354 let li = $(settings.list_selector + ' li.wpcs_select_option').eq(index); 355 let value = li.data('value') 356 let label = li.data('label'); 357 358 // unset old 359 $(settings.list_selector + ' li.selected').removeClass('selected'); 360 361 li.addClass('selected'); 362 363 // refresh handle label 364 $(settings.handle_selector, element).html(label); 365 366 // set value to form element 367 $(settings.value_selector, element).val(value).trigger('change'); 368 369 $(settings.clear_selector,element).show(); 370 } 371 372 373 /** 374 * 375 * @param element 376 * @private 377 */ 378 function _set_multiple_value(element) { 379 let value = ''; 380 let count = 0; 381 let labelValue = ''; 382 let labelTmp = ''; 383 let valueTmp = ''; 384 385 386 // build value string 387 $(settings.list_selector + ' li').each(function() { 388 if ($(this).hasClass('active')) { 389 labelTmp = $(this).data('label'); 390 valueTmp = $(this).data('value'); 391 if (value != "") value += ','; 392 value += valueTmp; 393 labelValue = labelTmp; 394 count++; 395 } 396 }); 397 398 // set label 399 let label = ''; 400 if (count == 0) label = $(element).data('nothing-selected'); 401 else if (count == 1) label = labelValue; 402 else if (count > 1) label = count + ' ausgewählt'; 403 $(settings.handle_selector, element).html(label); 404 405 // set value 406 $(settings.value_selector, element).val(value).trigger('change'); 407 408 if(count == 0) $(settings.clear_selector,element).hide(); 409 else $(settings.clear_selector,element).show(); 410 } 411 412 /** 413 * 414 * @param element 415 * @private 416 */ 417 function _createListFromDataDiv(element) { 418 let list = new Map(); 419 $('.data div', element).each(function(i){ 420 let value = $(this).attr('data-value'); 421 let label = $(this).html(); 422 let is_group = $(this).data('is-group') ?? false; 423 let group = $(this).data('group') ?? null; 424 list.set(i, { value: value, label: label, is_group:is_group, group:group, index: i }); 425 }); 426 427 _refresh(element, list); 428 } 429 430 /** 431 * 432 * @param select 433 * @private 434 */ 435 function _createListFromAjax(element) { 436 if (!settings.ajax) return; 437 let ajax = Object.assign({}, settings.ajax); 438 ajax.data = settings.ajax.data(); 439 440 let multiple = parseInt(element.data('multiple')); 441 442 $(settings.loading_selector, element).show(); 443 $(settings.arrow_selector, element).hide(); 444 445 446 $.ajax(ajax).done(function(data) { 447 let list = new Map(); 448 let z = 0; 449 450 for (let index in data) { 451 //index = parseInt(index); 452 let value = data[index]['id']; 453 let label = data[index]['text']; 454 let is_group = data[index]['is_group'] ?? false; 455 let group = data[index]['group'] ?? null; 456 list.set(z, { value: value, label: label, is_group:is_group, group:group, index: z }); 457 z++; 458 } 459 460 $(settings.loading_selector, element).hide(); 461 $(settings.arrow_selector, element).show(); 462 463 _refresh(element, list); 464 }); 465 466 } 467 468 /** 469 * 470 */ 471 return this.each(function() { 472 select = this; 473 _create(select); 474 }); 475 }; 476 477})(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.