PageSourceSearch

https://gardenclub.org/libraries/select/jquery.select.js?v=10.6.16

js gardenclub.org collected 2026-10-01 10:37:49 UTC 20,156 bytes, 482 lines download raw bytes

1/*
2  Select customization v 1.70 (09.03.25) <- v 1.60 (05.29.20)
3  Author: Pavlo Tkach
4*/
5(function($){
6
7  function handClickLi(event) {
8    var e = event || window.event,
9    $sb = e.data.elm, onSelectChanged = e.data.fun,
10    al = e.data.options.allLabel, label = e.data.label, ip = e.data.ip;
11    if ( !e.target.closest('.selectBox') ) return true;
12    e.stopPropagation();
13    //e.preventDefault();
14    
15
16    if (e.data.options.selSelect) {
17      var $se = $(e.data.options.selSelect), $w = $sb;
18    } else {
19      var $w = $(this).closest('.wrap-sb'), $se = $w.children('select');
20    };
21    var $u = $w.find('.list'),$lb = $w.find('.label'),
22      $inp = $w.find('input'), $val = $lb.find('.value'),
23      $li = $(this).parent().children().not('.group'),
24      ind = $li.index(this);
25      t = $u.attr('data-label')?$u.attr('data-label'):$se.children('option').eq(0).text();
26
27    if ($se.attr('multiple')) {
28      var lastChecked = $se.data('lastChecked');
29
30      if ( event.ctrlKey || ( window.navigator.userAgent.indexOf("Mac") !== -1 && event.metaKey ) || e.shiftKey ) {
31      //if ( event.ctrlKey || ( window.navigator.userAgent.indexOf("Mac") && event.metaKey ) || e.shiftKey ) {
32        //$se[0].options[$(this).index()+1].selected = true;
33        if(!lastChecked) lastChecked = this;
34        // with shift
35        if(event.shiftKey) {
36          var start = $li.index(this),
37          end = $li.index(lastChecked);
38          if (start >= 0 && start === end) {
39            if ($li.hasClass('selected')) {
40              $(this).removeClass('selected');
41              $se[0].options[start].selected = false;
42              $lb.children('[data-value="'+$se[0].options[start].value+'"]').remove();
43            } else {
44              $(this).addClass('selected');
45              $se[0].options[start].selected = true;
46              if ($inp.length && ip == 'after') {
47                $('<span class="item" data-value="'+$se[0].options[start].value+'">'+$se[0].options[start].text+'</span>').insertBefore($inp);
48              } else {
49                $('<span class="item" data-value="'+$se[0].options[start].value+'">'+$se[0].options[start].text+'</span>').appendTo($lb);
50              };
51            }
52          } else {
53            var sel = ($(lastChecked).hasClass('selected') && $(this).hasClass('selected'))?true:false,
54            min = Math.min(start,end), max = Math.max(start,end);
55            for (var i = min; i <= max; i++) {
56              if (sel) {
57                if (i != start) {
58                  $li.eq(i).removeClass('selected');
59                  $se[0].options[i+1].selected = false;
60                  $lb.children('[data-value="'+$se[0].options[i+1].value+'"]').remove();
61                }
62              } else {
63                $li.eq(i).addClass('selected');
64                $se[0].options[i+1].selected = true;
65                if (!$lb.children('[data-value="'+$se[0].options[i+1].value+'"]').length) {
66                  if ($inp.length && ip == 'after') {
67                    $('<span class="item" data-value="'+$se[0].options[i+1].value+'">'+$se[0].options[i+1].text+'</span>').insertBefore($inp);
68                  } else {
69                    $('<span class="item" data-value="'+$se[0].options[i+1].value+'">'+$se[0].options[i+1].text+'</span>').appendTo($lb);
70                  };
71                };
72              };
73            };
74          }
75        } else {
76          var i = $li.index(this);
77          if ($(this).hasClass('selected')) {
78            $(this).removeClass('selected');
79            $se[0].options[i+1].selected = false;
80            $lb.children('[data-value="'+$se[0].options[i+1].value+'"]').remove();
81          } else {
82            $(this).addClass('selected');
83            $se[0].options[i+1].selected = true;
84            if ($inp.length && ip == 'after') {
85              $('<span class="item" data-value="'+$se[0].options[i+1].value+'">'+$se[0].options[i+1].text+'</span>').insertBefore($inp);
86            } else {
87              $('<span class="item" data-value="'+$se[0].options[i+1].value+'">'+$se[0].options[i+1].text+'</span>').appendTo($lb);
88            };
89          }
90        };
91        $se.data('lastChecked',this);
92      } else {
93        for (var i = 0; i < $se[0].options.length; i++) {
94          $se[0].options[i].selected = false;
95        }
96        $se[0].options[$(this).index()+1].selected = true;
97        $(this).siblings().removeClass('selected');
98        $lb.children('.item').remove();
99        $(this).addClass('selected');
100        if ($inp.length && ip == 'after') {
101          $('<span class="item" data-value="'+$se[0].options[$li.index(this)+1].value+'">'+$se[0].options[$li.index(this)+1].text+'</span>').insertBefore($inp);
102        } else {
103          $('<span class="item" data-value="'+$se[0].options[$li.index(this)+1].value+'">'+$se[0].options[$li.index(this)+1].text+'</span>').appendTo($lb);
104        };
105
106        //$sb.removeClass('open').find('.ddbox').fadeOut(200);
107        $se.data('lastChecked',this);
108      };
109      if ($sb.find('.item').length) {
110        $val.css('display','none');
111      } else {
112        $val.css('display','inline-block');
113      };
114      if ($inp.length) $inp.focus();
115    } else {
116      if ( ind == 0 ) {
117        var str = '';
118        $lb.addClass('placeholder');
119        if (typeof al == 'string') {
120          str = al;
121        } else str = label;
122      } else {
123        $lb.removeClass('placeholder');
124        var $v = $(this).children('.val');
125        str = $(this).text();
126        if ($v.length) str = str.slice(0,str.length-$v.text().length);
127      };
128      $(this).addClass('selected').siblings().removeClass('selected');
129      $val.html(str);
130      //$se[0].options.selected = false;
131      $se[0].options[ind].selected = true;
132      $se[0].value = $(this).attr('data-value');
133      $se[0].selectedIndex = ind;
134      $se[0].dispatchEvent(new Event("input", { bubbles: true }));
135      $se[0].dispatchEvent(new Event("change", { bubbles: true }));
136      if ($inp.length) {
137        $inp.css('display','none');
138        $val.css('display','inline-block');
139      };
140      if (typeof $sb == 'object') $sb.removeClass('open').find('.ddbox').fadeOut(200);
141    };
142    if ($inp.length) $inp.focus();
143    //$se.children().attr("selected",false);
144    //$se.children().eq($(this).index()).attr("selected",true);
145    $se.change();
146    if ($.isFunction(onSelectChanged)) {
147      onSelectChanged.call(this);
148    };
149  };
150
151  var methods = {
152    init : function( options ) {
153      var options = $.extend({
154          selectBox:  '.selectBox',
155          addClasses: '',
156          addValue: false,
157          classCopy: '',
158          addWrapClasses: '',
159          selSelect: '',
160          allLabel: false, //default text: false - selected option or option[0], true - label, otherwise - html code
161          arrangeLabel: false,
162          hideselect: true,
163          filestyle: false,
164          height: 'auto',
165          eventContainer: 'html',
166          multiple: false,
167          search: false, //false,true,'filter'
168          inputPlace: 'after', //'default','before','after'
169          onOpenDDBoxBefore: function() {},
170          onCloseDDBoxAfter: function() {},
171          onSelectChanged: function() {},
172      }, options);
173
174      // restore/save options
175      if ( this.data('select') ) {
176        options = this.data('select');
177      } else {
178        this.data('select',options);
179      };
180
181      var selectBox = options.selectBox, ec = options.eventContainer, allLabel = options.allLabel, $u,
182      listc  = options.classCopy.split(" "),
183      onOpenDDBoxBefore = options.onOpenDDBoxBefore,
184      onCloseDDBoxAfter = options.onCloseDDBoxAfter,
185      onSelectChanged = options.onSelectChanged,
186      hide = options.hideselect, ov = 'auto', $wo;
187
188      function handClickEC(event) {
189        var ec = event.data.elm, selectBox = event.data.sb,
190        e = event || window.event, $o = $(e.target || e.srcElement);
191        $os = $o.parents(selectBox).length?$o.parents(selectBox):$o;
192        if ( !e.target.closest('.selectBox') ) return true;
193        e.stopPropagation();
194        //e.preventDefault();
195        if ($o.closest(ec).length > 0 && !$os.is($(selectBox,ec))) {
196          $(selectBox,ec).each(function() {
197            var $val = $(this).find('.value'), $it = $(this).find('.item'),
198            $inp = $(this).find('input');
199            if (!$it.length) $val.css('display','inline-block');
200            if ($inp.length) $inp.css('display','none');
201            $(this).removeClass('open').find('.ddbox').fadeOut(0);
202          });
203        }
204      };
205      function handClickSB(event) {
206        var e = event || window.event,
207        $sb = event.data.elm, op = event.data.se[0].options, $inp, $val;
208        if ( !e.target.closest('.selectBox') ) return true;
209        if ( $sb.hasClass('disabled')) return;
210        e.stopPropagation();
211        //e.preventDefault();
212        $(selectBox,options.eventContainer).each(function() {
213          if ($(this).is($sb)) {
214            $inp = $(this).find('input');
215            $val = $(this).find('.value');
216            if ($(e.target).hasClass('item')) {
217              var $it = $(e.target), v = $it.attr('data-value'),
218              $li = $sb.find('.ddbox li'), $l = $li.filter('[data-value="'+v+'"]');
219              if ($l.length) {
220                i = $li.index($l);
221                $l.removeClass('selected');
222                op[i+1].selected = false;
223                $it.remove();
224                if ( !$(this).find('.item').length && (!$inp.length || !$(this).hasClass('open')) ) {
225                  $val.css('display','inline-block');
226                };
227                if ($(this).hasClass('open') && $inp.length) $inp.focus();
228              };
229            } else if ( !$(e.target).hasClass('group')) {
230              if ($(this).hasClass('open')) {
231                $(this).removeClass('open').find('.ddbox').fadeOut(200);
232                if (!$sb.find('.item').length) $val.css('display','inline-block');
233                if ($inp.length) $inp.css('display','none');
234                if ($.isFunction(onCloseDDBoxAfter)) {
235                  onCloseDDBoxAfter.call(this);
236                };
237              } else {
238                if ($.isFunction(onOpenDDBoxBefore)) {
239                  onOpenDDBoxBefore.call(this);
240                };
241                $(this).addClass('open').find('.ddbox').fadeIn(200);//animate({height:'toggle'},200)
242                if ($inp.length) {
243                  $inp.css('display','inline-block');
244                  $val.css('display','none');
245                }
246              };
247            };
248            if ($inp.length) $inp.focus();
249          } else $(this).removeClass('open').find('.ddbox').fadeOut(0);
250        });
251      };
252      function handKeyupINP(event) {
253        var e = event || window.event,
254        $sb = event.data.elm, $li = $sb.find('li'), $db = $sb.find('.ddbox'),
255        filter = this.value,$elm,txt,fl = false,val;
256        for (i = 0; i < $li.length; i++) {
257          $elm = $li.eq(i), txt = $elm.text().replace($elm.children('.val').text(),'');
258          val = options.addValue?($elm.children('.val').length?'<span class="val">'+$elm.children('.val').html()+'</span>':''):'';
259          start = txt.toUpperCase().indexOf(filter.toUpperCase());
260          if (options.search == 'filter') {
261            if (start > -1) {
262              $elm.html(txt.slice(0,start)+'<em>'+txt.slice(start,start+filter.length)+'</em>'+txt.slice(start+filter.length)+val);
263              $elm.css('display', "");
264            } else {
265              $elm.remove('em');
266              $elm.css('display', "none");
267            }
268          } else {
269            if (start == 0) {
270              if (!fl) $db.scrollTop($elm[0].offsetTop-5);
271              $elm.html(txt.slice(0,start)+'<em>'+txt.slice(start,start+filter.length)+'</em>'+txt.slice(start+filter.length)+val);
272              fl = true;
273            } else {
274              $elm.remove('em');
275            }
276          }
277        }
278      };
279
280      // add file list style
281      if (typeof options.filestyle == 'string' && !$('link[href="'+options.filestyle+'"]').length) {
282        var css = $("<link>", {
283          "rel" : "stylesheet",
284          "type" :  "text/css",
285          "href" : options.filestyle
286        })[0];
287        css.onerror = function(event) {
288          console.log('The file "'+this.href+'" not found!');
289        };
290        document.getElementsByTagName("head")[0].appendChild(css);
291      }
292
293      // transform select to selectbox
294      function addItem($el,gr,dis) {
295        $el.children('option').each(function(i) {
296          let $li;
297          if (!$el.attr('multiple') || ( $el.attr('multiple') && i != 0 )) {
298            $li = $('<li '+(this.disabled||dis?'class="disabled"':'')+' data-value="'+$
298(this).val()+'"'+ (gr!==false?' data-group="group-'+gr+'"':'') +'>'+$(this).text()+'</li>').appendTo($u);
299            if ( gr!==false ) $li.addClass('group-item');
300            if ( i!=0 &&  options.addValue && options.addValue != $(this).val()) $li.append('<span class="val">'+$(this).val()+'</span>');
301          };
302        });
303      };
304      $(this).each(function(i) {
305        var $se = $(this), $w = $(this).parent(), $inp;
306        if ( $w && !$w.hasClass('wrap-sb') ) {
307          var $lbs = $(this).parent().children('label'),l = '';
308          if (!$lbs.length) $lbs = $('label[for="'+$(this).attr('id')+'"]');
309          l = $lbs.length? $lbs.text().trim():'';
310          // arrange label
311          if ($lbs.length && options.arrangeLabel) $lbs.insertBefore($se);
312          // set multiple option
313          if (options.multiple) $(this).attr('multiple',true);
314          // do selectBox base structure
315          $(this).add($lbs).wrapAll('<div class="wrap-sb"></div>');
316          $w = $(this).parent('.wrap-sb');
317          var $sb = $('<div class="'+selectBox.replace('.','')+'"><span class="label"></span><div class="ddbox"><ul class="list"></ul></div></div>').insertAfter($(this)),
318          $lb = $sb.children('.label'), $dd = $sb.find('.ddbox');
319          if ($se.attr('disabled')) $sb.addClass('disabled'); 
320          // add classes to .selectBox & wrapper
321          $sb.addClass(options.addClasses);
322          for (var i = 0; i < listc.length; i++) {
323            if ($se.hasClass(listc[i])) $sb.addClass(listc[i]);
324          };
325          $w.addClass(options.addWrapClasses);
326
327          // do dropdown list
328          $u = $sb.find('ul'), gr = false, dis = false, $ol = $(this).children('option').eq(0);
329          if ( $(this).children('optgroup').length>0 ) {
330            $li = $('<li '+' data-value="'+$ol.val()+'">'+$ol.text()+'</li>').appendTo($u);
331            $(this).children('optgroup').each(function(i) {
332              var  dis = this.disabled?true:false, $li;
333              gr = i;
334              $li = $('<li class="group'+(dis?' disabled"':'"')+'>'+$(this).attr('label')+'</li>').appendTo($u);
335              $li.addClass('group-'+gr);
336              addItem($(this),gr,dis);
337            });
338          } else addItem($(this),gr,dis);
339
340          $li = $u.find('li').not('.group');
341
342          // set default label value
343          var i = 0,  str = '';
344          if (typeof options.allLabel == 'string') {
345            str = allLabel;
346          } else if (options.allLabel){
347            str = l;
348          } else {
349            str = this.options[0].text;
350          };
351          l = str;
352          i = this.selectedIndex;
353          if (!$se.attr('multiple')) {
354            if (i > 0) {
355              $lb.removeClass('placeholder');
356              $lb.html('<span class="value">'+this.options[i].text+'</span>');
357            } else {
358              $lb.addClass('placeholder');
359              $lb.html('<span class="value">'+str+'</span>');
360            };
361            $li.eq(i).addClass('selected');
362          } else {
363            $sb.addClass('multiple');
364            if (i > 0) {
365              $lb.removeClass('placeholder');
366              $li.eq(i-1).addClass('selected');
367            } else {
368              $lb.addClass('placeholder');
369            }
370            $se.data('lastChecked',$li.eq(i));
371            $lb.html('<span class="value">'+str+'</span>');
372          };
373
374          // search
375          if ( options.search ) {
376            $sb.addClass('search');
377            if (options.inputPlace == 'after') {
378              $inp = $('<input type="text" autocomplete="off">').appendTo($lb);
379            } else {
380              $inp = $('<input type="text" autocomplete="off">').prependTo($lb);
381            };
382          };
383
384         // max dropbox height
385          if(typeof options.height == 'number') $dd.css({'max-height':options.height+'px','overflow':'auto'});
386
387          // hide select & label
388          $(this).css(hide?{'display':'none'}:{});
389          $lbs.css((hide === 'all')?{'display':'none'}:{});
390
391          // add events
392          if ( !$w.is($wo) ){
393            $sb = $w.find(selectBox);
394            $(ec).off('click.EC'+selectBox+'.select');
395            $(ec).on('click.EC'+selectBox+'.select',{elm: $(ec),sb: selectBox}, handClickEC);
396            $sb.off('click.SB.select');
397            $sb.on('click.SB.select',{elm: $sb, se: $se}, handClickSB);
398            if ( options.search ) $inp.on('keyup.INP.select',{elm: $sb, se: $se}, handKeyupINP);
399            $wo = !$wo?$w:$wo.add($w);
400          };
401        };
402
403        // relation to select (change select value)
404        $li.not('.disabled').on('click.Li.select', {elm: $sb, options: options, label: l, fun: onSelectChanged, ip: options.inputPlace}, handClickLi);
405
406      });
407
408      return $(this);
409    },
410    refresh : function(options) {
411      this.each(function(i){
412        var options = $(this).data('select'),
413          selectBox = options.selectBox,
414          ec = options.eventContainer,
415          $se = $(this);
416        $w = $(this).closest('.wrap-sb');
417        if ( $w && $w.hasClass('wrap-sb') ) {
418          var $sb = $w.find(selectBox),
419            $lbs = $w.find('label'),
420            $lb = $sb.find('.label'), $u = $sb.find('ul'),
421            l = $lbs.length? $lbs.text().trim():'';
422          $lb.children().remove();
423          $u.find('li').remove();
424          $se.children('option').each(function(i) {
425            this.selected = false;
426            $('<li data-value='+$(this).val()+'>'+$(this).text()+'</li>').appendTo($u);
427            if ( !$se.attr('multiple') && i==0 ) {
428              this.selected = true;
429              this.selectedIndex = 0;
430              $se[0].value = $(this).text();
431            } else this.selected = false;
432          });
433          var $li = $u.find('li');
434          // set default label value
435          var i = 0;
436          if (!$se.attr('multiple')) {
437            if (typeof options.allLabel == 'string') {
438              $lb.html(allLabel);
439            } else if (options.allLabel){
440              $lb.text(l);
441            } else {
442              l = this.options[0].text;
443              $lb.text(this.options[0].text);
444            }
445          } else {
446            $se.data('lastChecked',$li.eq(-1));
447          };
448        };
449        // relation to select (change select value)
450        if ( $li.length )  $li.on('click.Li.select', {elm: $sb, options: options, label: l}, handClickLi);
451      });
452    },
453    remove : function(options) {
454      this.each(function(i){
455        var options = $(this).data('select'),
456          selectBox = options.selectBox,
457          ec = options.eventContainer,
458          $se = $(this), $w = $(this).closest('.wrap-sb');
459        if ( $w && $w.hasClass('wrap-sb') ) {
460          var $lbs = $w.find('label'),
461            $sb = $w.find(selectBox),$inp = $sb.find('input');
462          if ($inp.length) $inp.off('keyup.INP.select');
463          $sb.off('click.SB.select').remove();
464          $se.add($lbs).unwrap();
465          $(ec).off('click.EC'+selectBox+'.select');
466
467        }
468      });
469    }
470  };
471
472  $.fn.select = function( method ) {
473    if ( methods[method] ) {
474      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
475    } else if ( typeof method === 'object' || ! method ) {
476      return methods.init.apply( this, arguments );
477    } else {
478      $.error( 'Method with the name ' +  method + ' does not exist for jQuery.select.js' );
479    }
480  };
481
482})(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.