less-rails-semantic_ui 2.1.8.2 → 2.2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +15 -0
  3. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.eot +0 -0
  4. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.svg +146 -26
  5. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.ttf +0 -0
  6. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.woff +0 -0
  7. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.woff2 +0 -0
  8. data/assets/javascripts/semantic_ui/definitions/behaviors/api.js +41 -16
  9. data/assets/javascripts/semantic_ui/definitions/behaviors/colorize.js +233 -227
  10. data/assets/javascripts/semantic_ui/definitions/behaviors/form.js +58 -23
  11. data/assets/javascripts/semantic_ui/definitions/behaviors/state.js +20 -7
  12. data/assets/javascripts/semantic_ui/definitions/behaviors/visibility.js +89 -22
  13. data/assets/javascripts/semantic_ui/definitions/behaviors/visit.js +13 -5
  14. data/assets/javascripts/semantic_ui/definitions/globals/site.js +2 -2
  15. data/assets/javascripts/semantic_ui/definitions/modules/accordion.js +20 -6
  16. data/assets/javascripts/semantic_ui/definitions/modules/checkbox.js +31 -9
  17. data/assets/javascripts/semantic_ui/definitions/modules/dimmer.js +27 -9
  18. data/assets/javascripts/semantic_ui/definitions/modules/dropdown.js +482 -207
  19. data/assets/javascripts/semantic_ui/definitions/modules/embed.js +50 -13
  20. data/assets/javascripts/semantic_ui/definitions/modules/modal.js +28 -13
  21. data/assets/javascripts/semantic_ui/definitions/modules/nag.js +28 -7
  22. data/assets/javascripts/semantic_ui/definitions/modules/popup.js +136 -76
  23. data/assets/javascripts/semantic_ui/definitions/modules/progress.js +177 -62
  24. data/assets/javascripts/semantic_ui/definitions/modules/rating.js +41 -8
  25. data/assets/javascripts/semantic_ui/definitions/modules/search.js +109 -56
  26. data/assets/javascripts/semantic_ui/definitions/modules/shape.js +52 -19
  27. data/assets/javascripts/semantic_ui/definitions/modules/sidebar.js +21 -7
  28. data/assets/javascripts/semantic_ui/definitions/modules/sticky.js +48 -19
  29. data/assets/javascripts/semantic_ui/definitions/modules/tab.js +57 -27
  30. data/assets/javascripts/semantic_ui/definitions/modules/transition.js +24 -8
  31. data/assets/stylesheets/semantic_ui/definitions/collections/breadcrumb.less +1 -2
  32. data/assets/stylesheets/semantic_ui/definitions/collections/form.less +42 -36
  33. data/assets/stylesheets/semantic_ui/definitions/collections/grid.less +12 -5
  34. data/assets/stylesheets/semantic_ui/definitions/collections/menu.less +50 -6
  35. data/assets/stylesheets/semantic_ui/definitions/collections/message.less +20 -1
  36. data/assets/stylesheets/semantic_ui/definitions/collections/table.less +16 -3
  37. data/assets/stylesheets/semantic_ui/definitions/elements/button.less +184 -40
  38. data/assets/stylesheets/semantic_ui/definitions/elements/container.less +1 -2
  39. data/assets/stylesheets/semantic_ui/definitions/elements/divider.less +1 -3
  40. data/assets/stylesheets/semantic_ui/definitions/elements/flag.less +1 -2
  41. data/assets/stylesheets/semantic_ui/definitions/elements/header.less +2 -2
  42. data/assets/stylesheets/semantic_ui/definitions/elements/icon.less +1 -2
  43. data/assets/stylesheets/semantic_ui/definitions/elements/image.less +6 -1
  44. data/assets/stylesheets/semantic_ui/definitions/elements/input.less +14 -14
  45. data/assets/stylesheets/semantic_ui/definitions/elements/label.less +3 -3
  46. data/assets/stylesheets/semantic_ui/definitions/elements/list.less +29 -16
  47. data/assets/stylesheets/semantic_ui/definitions/elements/loader.less +72 -9
  48. data/assets/stylesheets/semantic_ui/definitions/elements/rail.less +21 -2
  49. data/assets/stylesheets/semantic_ui/definitions/elements/reveal.less +2 -3
  50. data/assets/stylesheets/semantic_ui/definitions/elements/segment.less +44 -3
  51. data/assets/stylesheets/semantic_ui/definitions/elements/step.less +28 -8
  52. data/assets/stylesheets/semantic_ui/definitions/globals/reset.less +1 -2
  53. data/assets/stylesheets/semantic_ui/definitions/globals/site.less +0 -1
  54. data/assets/stylesheets/semantic_ui/definitions/modules/accordion.less +0 -1
  55. data/assets/stylesheets/semantic_ui/definitions/modules/checkbox.less +9 -10
  56. data/assets/stylesheets/semantic_ui/definitions/modules/dimmer.less +1 -2
  57. data/assets/stylesheets/semantic_ui/definitions/modules/dropdown.less +39 -21
  58. data/assets/stylesheets/semantic_ui/definitions/modules/embed.less +0 -1
  59. data/assets/stylesheets/semantic_ui/definitions/modules/modal.less +0 -1
  60. data/assets/stylesheets/semantic_ui/definitions/modules/nag.less +1 -2
  61. data/assets/stylesheets/semantic_ui/definitions/modules/popup.less +344 -2
  62. data/assets/stylesheets/semantic_ui/definitions/modules/progress.less +0 -1
  63. data/assets/stylesheets/semantic_ui/definitions/modules/rating.less +0 -1
  64. data/assets/stylesheets/semantic_ui/definitions/modules/search.less +1 -1
  65. data/assets/stylesheets/semantic_ui/definitions/modules/shape.less +1 -2
  66. data/assets/stylesheets/semantic_ui/definitions/modules/sidebar.less +1 -2
  67. data/assets/stylesheets/semantic_ui/definitions/modules/sticky.less +1 -2
  68. data/assets/stylesheets/semantic_ui/definitions/modules/tab.less +1 -2
  69. data/assets/stylesheets/semantic_ui/definitions/modules/transition.less +1 -2
  70. data/assets/stylesheets/semantic_ui/definitions/views/card.less +20 -2
  71. data/assets/stylesheets/semantic_ui/definitions/views/comment.less +1 -2
  72. data/assets/stylesheets/semantic_ui/definitions/views/feed.less +0 -1
  73. data/assets/stylesheets/semantic_ui/definitions/views/item.less +1 -2
  74. data/assets/stylesheets/semantic_ui/definitions/views/statistic.less +18 -19
  75. data/assets/stylesheets/semantic_ui/themes/basic/globals/reset.overrides +1 -1
  76. data/assets/stylesheets/semantic_ui/themes/default/collections/form.variables +4 -5
  77. data/assets/stylesheets/semantic_ui/themes/default/collections/menu.variables +13 -0
  78. data/assets/stylesheets/semantic_ui/themes/default/collections/message.variables +47 -1
  79. data/assets/stylesheets/semantic_ui/themes/default/collections/table.variables +7 -2
  80. data/assets/stylesheets/semantic_ui/themes/default/elements/button.variables +14 -0
  81. data/assets/stylesheets/semantic_ui/themes/default/elements/icon.overrides +263 -76
  82. data/assets/stylesheets/semantic_ui/themes/default/elements/icon.variables +3 -1
  83. data/assets/stylesheets/semantic_ui/themes/default/elements/input.variables +2 -4
  84. data/assets/stylesheets/semantic_ui/themes/default/elements/list.variables +2 -1
  85. data/assets/stylesheets/semantic_ui/themes/default/elements/loader.variables +17 -5
  86. data/assets/stylesheets/semantic_ui/themes/default/elements/rail.variables +2 -2
  87. data/assets/stylesheets/semantic_ui/themes/default/elements/step.variables +1 -1
  88. data/assets/stylesheets/semantic_ui/themes/default/globals/reset.overrides +1 -6
  89. data/assets/stylesheets/semantic_ui/themes/default/globals/site.variables +170 -46
  90. data/assets/stylesheets/semantic_ui/themes/default/modules/dropdown.variables +15 -12
  91. data/assets/stylesheets/semantic_ui/themes/default/modules/popup.variables +41 -3
  92. data/assets/stylesheets/semantic_ui/themes/default/modules/rating.overrides +2 -2
  93. data/assets/stylesheets/semantic_ui/themes/default/modules/sticky.variables +1 -1
  94. data/assets/stylesheets/semantic_ui/themes/default/views/card.variables +11 -0
  95. data/assets/stylesheets/semantic_ui/themes/material/collections/menu.variables +1 -1
  96. data/lib/less/rails/semantic_ui/version.rb +1 -1
  97. metadata +4 -3
@@ -3,7 +3,6 @@
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2015 Contributors
7
6
  * Released under the MIT license
8
7
  * http://opensource.org/licenses/MIT
9
8
  *
@@ -13,6 +12,13 @@
13
12
 
14
13
  "use strict";
15
14
 
15
+ window = (typeof window != 'undefined' && window.Math == Math)
16
+ ? window
17
+ : (typeof self != 'undefined' && self.Math == Math)
18
+ ? self
19
+ : Function('return this')()
20
+ ;
21
+
16
22
  $.visit = $.fn.visit = function(parameters) {
17
23
  var
18
24
  $allModules = $.isFunction(this)
@@ -322,7 +328,7 @@ $.visit = $.fn.visit = function(parameters) {
322
328
  }
323
329
  },
324
330
  debug: function() {
325
- if(settings.debug) {
331
+ if(!settings.silent && settings.debug) {
326
332
  if(settings.performance) {
327
333
  module.performance.log(arguments);
328
334
  }
@@ -333,7 +339,7 @@ $.visit = $.fn.visit = function(parameters) {
333
339
  }
334
340
  },
335
341
  verbose: function() {
336
- if(settings.verbose && settings.debug) {
342
+ if(!settings.silent && settings.verbose && settings.debug) {
337
343
  if(settings.performance) {
338
344
  module.performance.log(arguments);
339
345
  }
@@ -344,8 +350,10 @@ $.visit = $.fn.visit = function(parameters) {
344
350
  }
345
351
  },
346
352
  error: function() {
347
- module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
348
- module.error.apply(console, arguments);
353
+ if(!settings.silent) {
354
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
355
+ module.error.apply(console, arguments);
356
+ }
349
357
  },
350
358
  performance: {
351
359
  log: function(message) {
@@ -3,12 +3,12 @@
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2015 Contributors
7
6
  * Released under the MIT license
8
7
  * http://opensource.org/licenses/MIT
9
8
  *
10
9
  */
11
- ;(function ( $, window, document, undefined ) {
10
+
11
+ ;(function ($, window, document, undefined) {
12
12
 
13
13
  $.site = $.fn.site = function(parameters) {
14
14
  var
@@ -3,7 +3,6 @@
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2015 Contributors
7
6
  * Released under the MIT license
8
7
  * http://opensource.org/licenses/MIT
9
8
  *
@@ -13,6 +12,13 @@
13
12
 
14
13
  "use strict";
15
14
 
15
+ window = (typeof window != 'undefined' && window.Math == Math)
16
+ ? window
17
+ : (typeof self != 'undefined' && self.Math == Math)
18
+ ? self
19
+ : Function('return this')()
20
+ ;
21
+
16
22
  $.fn.accordion = function(parameters) {
17
23
  var
18
24
  $allModules = $(this),
@@ -367,7 +373,12 @@ $.fn.accordion = function(parameters) {
367
373
  $.extend(true, settings, name);
368
374
  }
369
375
  else if(value !== undefined) {
370
- settings[name] = value;
376
+ if($.isPlainObject(settings[name])) {
377
+ $.extend(true, settings[name], value);
378
+ }
379
+ else {
380
+ settings[name] = value;
381
+ }
371
382
  }
372
383
  else {
373
384
  return settings[name];
@@ -388,7 +399,7 @@ $.fn.accordion = function(parameters) {
388
399
  }
389
400
  },
390
401
  debug: function() {
391
- if(settings.debug) {
402
+ if(!settings.silent && settings.debug) {
392
403
  if(settings.performance) {
393
404
  module.performance.log(arguments);
394
405
  }
@@ -399,7 +410,7 @@ $.fn.accordion = function(parameters) {
399
410
  }
400
411
  },
401
412
  verbose: function() {
402
- if(settings.verbose && settings.debug) {
413
+ if(!settings.silent && settings.verbose && settings.debug) {
403
414
  if(settings.performance) {
404
415
  module.performance.log(arguments);
405
416
  }
@@ -410,8 +421,10 @@ $.fn.accordion = function(parameters) {
410
421
  }
411
422
  },
412
423
  error: function() {
413
- module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
414
- module.error.apply(console, arguments);
424
+ if(!settings.silent) {
425
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
426
+ module.error.apply(console, arguments);
427
+ }
415
428
  },
416
429
  performance: {
417
430
  log: function(message) {
@@ -544,6 +557,7 @@ $.fn.accordion.settings = {
544
557
  name : 'Accordion',
545
558
  namespace : 'accordion',
546
559
 
560
+ silent : false,
547
561
  debug : false,
548
562
  verbose : false,
549
563
  performance : true,
@@ -3,16 +3,22 @@
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2015 Contributors
7
6
  * Released under the MIT license
8
7
  * http://opensource.org/licenses/MIT
9
8
  *
10
9
  */
11
10
 
12
- ;(function ( $, window, document, undefined ) {
11
+ ;(function ($, window, document, undefined) {
13
12
 
14
13
  "use strict";
15
14
 
15
+ window = (typeof window != 'undefined' && window.Math == Math)
16
+ ? window
17
+ : (typeof self != 'undefined' && self.Math == Math)
18
+ ? self
19
+ : Function('return this')()
20
+ ;
21
+
16
22
  $.fn.checkbox = function(parameters) {
17
23
  var
18
24
  $allModules = $(this),
@@ -120,13 +126,13 @@ $.fn.checkbox = function(parameters) {
120
126
 
121
127
  hide: {
122
128
  input: function() {
123
- module.verbose('Modfying <input> z-index to be unselectable');
129
+ module.verbose('Modifying <input> z-index to be unselectable');
124
130
  $input.addClass(className.hidden);
125
131
  }
126
132
  },
127
133
  show: {
128
134
  input: function() {
129
- module.verbose('Modfying <input> z-index to be selectable');
135
+ module.verbose('Modifying <input> z-index to be selectable');
130
136
  $input.removeClass(className.hidden);
131
137
  }
132
138
  },
@@ -268,6 +274,8 @@ $.fn.checkbox = function(parameters) {
268
274
  }
269
275
  module.debug('Enabling checkbox');
270
276
  module.set.enabled();
277
+ settings.onEnable.call(input);
278
+ // preserve legacy callbacks
271
279
  settings.onEnabled.call(input);
272
280
  },
273
281
 
@@ -278,6 +286,8 @@ $.fn.checkbox = function(parameters) {
278
286
  }
279
287
  module.debug('Disabling checkbox');
280
288
  module.set.disabled();
289
+ settings.onDisable.call(input);
290
+ // preserve legacy callbacks
281
291
  settings.onDisabled.call(input);
282
292
  },
283
293
 
@@ -584,7 +594,12 @@ $.fn.checkbox = function(parameters) {
584
594
  $.extend(true, settings, name);
585
595
  }
586
596
  else if(value !== undefined) {
587
- settings[name] = value;
597
+ if($.isPlainObject(settings[name])) {
598
+ $.extend(true, settings[name], value);
599
+ }
600
+ else {
601
+ settings[name] = value;
602
+ }
588
603
  }
589
604
  else {
590
605
  return settings[name];
@@ -602,7 +617,7 @@ $.fn.checkbox = function(parameters) {
602
617
  }
603
618
  },
604
619
  debug: function() {
605
- if(settings.debug) {
620
+ if(!settings.silent && settings.debug) {
606
621
  if(settings.performance) {
607
622
  module.performance.log(arguments);
608
623
  }
@@ -613,7 +628,7 @@ $.fn.checkbox = function(parameters) {
613
628
  }
614
629
  },
615
630
  verbose: function() {
616
- if(settings.verbose && settings.debug) {
631
+ if(!settings.silent && settings.verbose && settings.debug) {
617
632
  if(settings.performance) {
618
633
  module.performance.log(arguments);
619
634
  }
@@ -624,8 +639,10 @@ $.fn.checkbox = function(parameters) {
624
639
  }
625
640
  },
626
641
  error: function() {
627
- module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
628
- module.error.apply(console, arguments);
642
+ if(!settings.silent) {
643
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
644
+ module.error.apply(console, arguments);
645
+ }
629
646
  },
630
647
  performance: {
631
648
  log: function(message) {
@@ -760,6 +777,7 @@ $.fn.checkbox.settings = {
760
777
  name : 'Checkbox',
761
778
  namespace : 'checkbox',
762
779
 
780
+ silent : false,
763
781
  debug : false,
764
782
  verbose : true,
765
783
  performance : true,
@@ -784,6 +802,10 @@ $.fn.checkbox.settings = {
784
802
  onEnable : function(){},
785
803
  onDisable : function(){},
786
804
 
805
+ // preserve misspelled callbacks (will be removed in 3.0)
806
+ onEnabled : function(){},
807
+ onDisabled : function(){},
808
+
787
809
  className : {
788
810
  checked : 'checked',
789
811
  indeterminate : 'indeterminate',
@@ -3,16 +3,22 @@
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2015 Contributors
7
6
  * Released under the MIT license
8
7
  * http://opensource.org/licenses/MIT
9
8
  *
10
9
  */
11
10
 
12
- ;(function ( $, window, document, undefined ) {
11
+ ;(function ($, window, document, undefined) {
13
12
 
14
13
  "use strict";
15
14
 
15
+ window = (typeof window != 'undefined' && window.Math == Math)
16
+ ? window
17
+ : (typeof self != 'undefined' && self.Math == Math)
18
+ ? self
19
+ : Function('return this')()
20
+ ;
21
+
16
22
  $.fn.dimmer = function(parameters) {
17
23
  var
18
24
  $allModules = $(this),
@@ -137,6 +143,9 @@ $.fn.dimmer = function(parameters) {
137
143
  $module
138
144
  .removeData(moduleNamespace)
139
145
  ;
146
+ $dimmable
147
+ .off(eventNamespace)
148
+ ;
140
149
  }
141
150
  },
142
151
 
@@ -383,10 +392,11 @@ $.fn.dimmer = function(parameters) {
383
392
  var
384
393
  color = $dimmer.css('background-color'),
385
394
  colorArray = color.split(','),
395
+ isRGB = (colorArray && colorArray.length == 3),
386
396
  isRGBA = (colorArray && colorArray.length == 4)
387
397
  ;
388
398
  opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
389
- if(isRGBA) {
399
+ if(isRGB || isRGBA) {
390
400
  colorArray[3] = opacity + ')';
391
401
  color = colorArray.join(',');
392
402
  }
@@ -445,7 +455,12 @@ $.fn.dimmer = function(parameters) {
445
455
  $.extend(true, settings, name);
446
456
  }
447
457
  else if(value !== undefined) {
448
- settings[name] = value;
458
+ if($.isPlainObject(settings[name])) {
459
+ $.extend(true, settings[name], value);
460
+ }
461
+ else {
462
+ settings[name] = value;
463
+ }
449
464
  }
450
465
  else {
451
466
  return settings[name];
@@ -463,7 +478,7 @@ $.fn.dimmer = function(parameters) {
463
478
  }
464
479
  },
465
480
  debug: function() {
466
- if(settings.debug) {
481
+ if(!settings.silent && settings.debug) {
467
482
  if(settings.performance) {
468
483
  module.performance.log(arguments);
469
484
  }
@@ -474,7 +489,7 @@ $.fn.dimmer = function(parameters) {
474
489
  }
475
490
  },
476
491
  verbose: function() {
477
- if(settings.verbose && settings.debug) {
492
+ if(!settings.silent && settings.verbose && settings.debug) {
478
493
  if(settings.performance) {
479
494
  module.performance.log(arguments);
480
495
  }
@@ -485,8 +500,10 @@ $.fn.dimmer = function(parameters) {
485
500
  }
486
501
  },
487
502
  error: function() {
488
- module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
489
- module.error.apply(console, arguments);
503
+ if(!settings.silent) {
504
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
505
+ module.error.apply(console, arguments);
506
+ }
490
507
  },
491
508
  performance: {
492
509
  log: function(message) {
@@ -626,6 +643,7 @@ $.fn.dimmer.settings = {
626
643
  name : 'Dimmer',
627
644
  namespace : 'dimmer',
628
645
 
646
+ silent : false,
629
647
  debug : false,
630
648
  verbose : false,
631
649
  performance : true,
@@ -690,4 +708,4 @@ $.fn.dimmer.settings = {
690
708
 
691
709
  };
692
710
 
693
- })( jQuery, window, document );
711
+ })( jQuery, window, document );
@@ -3,16 +3,22 @@
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2015 Contributors
7
6
  * Released under the MIT license
8
7
  * http://opensource.org/licenses/MIT
9
8
  *
10
9
  */
11
10
 
12
- ;(function ( $, window, document, undefined ) {
11
+ ;(function ($, window, document, undefined) {
13
12
 
14
13
  "use strict";
15
14
 
15
+ window = (typeof window != 'undefined' && window.Math == Math)
16
+ ? window
17
+ : (typeof self != 'undefined' && self.Math == Math)
18
+ ? self
19
+ : Function('return this')()
20
+ ;
21
+
16
22
  $.fn.dropdown = function(parameters) {
17
23
  var
18
24
  $allModules = $(this),
@@ -55,6 +61,7 @@ $.fn.dropdown = function(parameters) {
55
61
  $context = $(settings.context),
56
62
  $text = $module.find(selector.text),
57
63
  $search = $module.find(selector.search),
64
+ $sizer = $module.find(selector.sizer),
58
65
  $input = $module.find(selector.input),
59
66
  $icon = $module.find(selector.icon),
60
67
 
@@ -73,6 +80,7 @@ $.fn.dropdown = function(parameters) {
73
80
 
74
81
  initialLoad,
75
82
  pageLostFocus,
83
+ willRefocus,
76
84
  elementNamespace,
77
85
  id,
78
86
  selectObserver,
@@ -125,37 +133,48 @@ $.fn.dropdown = function(parameters) {
125
133
  $document
126
134
  .off(elementNamespace)
127
135
  ;
128
- if(selectObserver) {
129
- selectObserver.disconnect();
130
- }
131
- if(menuObserver) {
132
- menuObserver.disconnect();
133
- }
136
+ module.disconnect.menuObserver();
137
+ module.disconnect.selectObserver();
134
138
  },
135
139
 
136
140
  observeChanges: function() {
137
141
  if('MutationObserver' in window) {
138
- selectObserver = new MutationObserver(function(mutations) {
139
- module.debug('<select> modified, recreating menu');
140
- module.setup.select();
141
- });
142
- menuObserver = new MutationObserver(function(mutations) {
143
- module.debug('Menu modified, updating selector cache');
144
- module.refresh();
145
- });
142
+ selectObserver = new MutationObserver(module.event.select.mutation);
143
+ menuObserver = new MutationObserver(module.event.menu.mutation);
144
+ module.debug('Setting up mutation observer', selectObserver, menuObserver);
145
+ module.observe.select();
146
+ module.observe.menu();
147
+ }
148
+ },
149
+
150
+ disconnect: {
151
+ menuObserver: function() {
152
+ if(menuObserver) {
153
+ menuObserver.disconnect();
154
+ }
155
+ },
156
+ selectObserver: function() {
157
+ if(menuObserver) {
158
+ menuObserver.disconnect();
159
+ }
160
+ }
161
+ },
162
+ observe: {
163
+ select: function() {
146
164
  if(module.has.input()) {
147
165
  selectObserver.observe($input[0], {
148
166
  childList : true,
149
167
  subtree : true
150
168
  });
151
169
  }
170
+ },
171
+ menu: function() {
152
172
  if(module.has.menu()) {
153
173
  menuObserver.observe($menu[0], {
154
174
  childList : true,
155
175
  subtree : true
156
176
  });
157
177
  }
158
- module.debug('Setting up mutation observer', selectObserver, menuObserver);
159
178
  }
160
179
  },
161
180
 
@@ -190,6 +209,9 @@ $.fn.dropdown = function(parameters) {
190
209
  .addClass(className.addition)
191
210
  .addClass(className.item)
192
211
  ;
212
+ if(settings.hideAdditions) {
213
+ $userChoice.addClass(className.hidden);
214
+ }
193
215
  $userChoices = ($userChoices === undefined)
194
216
  ? $userChoice
195
217
  : $userChoices.add($userChoice)
@@ -216,6 +238,12 @@ $.fn.dropdown = function(parameters) {
216
238
  .addClass(className.menu)
217
239
  .appendTo($module)
218
240
  ;
241
+ },
242
+ sizer: function() {
243
+ $sizer = $('<span />')
244
+ .addClass(className.sizer)
245
+ .insertAfter($search)
246
+ ;
219
247
  }
220
248
  },
221
249
 
@@ -225,7 +253,12 @@ $.fn.dropdown = function(parameters) {
225
253
  : module.get.query()
226
254
  ;
227
255
  module.verbose('Searching for query', query);
228
- module.filter(query);
256
+ if(module.has.minCharacters(query)) {
257
+ module.filter(query);
258
+ }
259
+ else {
260
+ module.hide();
261
+ }
229
262
  },
230
263
 
231
264
  select: {
@@ -234,6 +267,7 @@ $.fn.dropdown = function(parameters) {
234
267
  module.remove.selectedItem();
235
268
  $item
236
269
  .not(selector.unselectable)
270
+ .not(selector.addition + selector.hidden)
237
271
  .eq(0)
238
272
  .addClass(className.selected)
239
273
  ;
@@ -260,7 +294,11 @@ $.fn.dropdown = function(parameters) {
260
294
  api: function() {
261
295
  var
262
296
  apiSettings = {
263
- debug : settings.debug,
297
+ debug : settings.debug,
298
+ urlData : {
299
+ value : module.get.value(),
300
+ query : module.get.query()
301
+ },
264
302
  on : false
265
303
  }
266
304
  ;
@@ -285,6 +323,9 @@ $.fn.dropdown = function(parameters) {
285
323
  .insertBefore($text)
286
324
  ;
287
325
  }
326
+ if( module.is.multiple() && module.is.searchSelection() && !module.has.sizer()) {
327
+ module.create.sizer();
328
+ }
288
329
  if(settings.allowTab) {
289
330
  module.set.tabbable();
290
331
  }
@@ -324,8 +365,8 @@ $.fn.dropdown = function(parameters) {
324
365
  module.set.multiple();
325
366
  }
326
367
  if ($input.prop('disabled')) {
327
- module.debug('Disabling dropdown')
328
- $module.addClass(className.disabled)
368
+ module.debug('Disabling dropdown');
369
+ $module.addClass(className.disabled);
329
370
  }
330
371
  $input
331
372
  .removeAttr('class')
@@ -366,6 +407,10 @@ $.fn.dropdown = function(parameters) {
366
407
  module.refreshData();
367
408
  },
368
409
 
410
+ refreshItems: function() {
411
+ $item = $menu.find(selector.item);
412
+ },
413
+
369
414
  refreshSelectors: function() {
370
415
  module.verbose('Refreshing selector cache');
371
416
  $text = $module.find(selector.text);
@@ -386,6 +431,14 @@ $.fn.dropdown = function(parameters) {
386
431
  .removeData(metadata.text)
387
432
  .removeData(metadata.value)
388
433
  ;
434
+ },
435
+
436
+ clearData: function() {
437
+ module.verbose('Clearing metadata');
438
+ $item
439
+ .removeData(metadata.text)
440
+ .removeData(metadata.value)
441
+ ;
389
442
  $module
390
443
  .removeData(metadata.defaultText)
391
444
  .removeData(metadata.defaultValue)
@@ -410,17 +463,20 @@ $.fn.dropdown = function(parameters) {
410
463
  ;
411
464
  if( module.can.show() && !module.is.active() ) {
412
465
  module.debug('Showing dropdown');
413
- if(module.is.multiple() && !module.has.search() && module.is.allFiltered()) {
414
- return true;
415
- }
416
466
  if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
417
467
  module.remove.message();
418
468
  }
469
+ if(module.is.allFiltered()) {
470
+ return true;
471
+ }
419
472
  if(settings.onShow.call(element) !== false) {
420
473
  module.animate.show(function() {
421
474
  if( module.can.click() ) {
422
475
  module.bind.intent();
423
476
  }
477
+ if(module.has.menuSearch()) {
478
+ module.focusSearch();
479
+ }
424
480
  module.set.visible();
425
481
  callback.call(element);
426
482
  });
@@ -523,11 +579,13 @@ $.fn.dropdown = function(parameters) {
523
579
  }
524
580
  if( module.is.searchSelection() ) {
525
581
  $module
582
+ .on('mousedown' + eventNamespace, module.event.mousedown)
583
+ .on('mouseup' + eventNamespace, module.event.mouseup)
526
584
  .on('mousedown' + eventNamespace, selector.menu, module.event.menu.mousedown)
527
585
  .on('mouseup' + eventNamespace, selector.menu, module.event.menu.mouseup)
528
586
  .on('click' + eventNamespace, selector.icon, module.event.icon.click)
529
- .on('click' + eventNamespace, selector.search, module.show)
530
587
  .on('focus' + eventNamespace, selector.search, module.event.search.focus)
588
+ .on('click' + eventNamespace, selector.search, module.event.search.focus)
531
589
  .on('blur' + eventNamespace, selector.search, module.event.search.blur)
532
590
  .on('click' + eventNamespace, selector.text, module.event.text.focus)
533
591
  ;
@@ -609,7 +667,14 @@ $.fn.dropdown = function(parameters) {
609
667
  module.select.firstUnfiltered();
610
668
  if( module.has.allResultsFiltered() ) {
611
669
  if( settings.onNoResults.call(element, searchTerm) ) {
612
- if(!settings.allowAdditions) {
670
+ if(settings.allowAdditions) {
671
+ if(settings.hideAdditions) {
672
+ module.verbose('User addition with no menu, setting empty style');
673
+ module.set.empty();
674
+ module.hideMenu();
675
+ }
676
+ }
677
+ else {
613
678
  module.verbose('All items filtered, showing message', searchTerm);
614
679
  module.add.message(message.noResults);
615
680
  }
@@ -620,6 +685,7 @@ $.fn.dropdown = function(parameters) {
620
685
  }
621
686
  }
622
687
  else {
688
+ module.remove.empty();
623
689
  module.remove.message();
624
690
  }
625
691
  if(settings.allowAdditions) {
@@ -652,9 +718,10 @@ $.fn.dropdown = function(parameters) {
652
718
  queryRemote: function(query, callback) {
653
719
  var
654
720
  apiSettings = {
655
- errorDuration : false,
656
- throttle : settings.throttle,
657
- urlData : {
721
+ errorDuration : false,
722
+ cache : 'local',
723
+ throttle : settings.throttle,
724
+ urlData : {
658
725
  query: query
659
726
  },
660
727
  onError: function() {
@@ -711,7 +778,11 @@ $.fn.dropdown = function(parameters) {
711
778
  results.push(this);
712
779
  return true;
713
780
  }
714
- else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, text)) {
781
+ else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, text)) {
782
+ results.push(this);
783
+ return true;
784
+ }
785
+ else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, text)) {
715
786
  results.push(this);
716
787
  return true;
717
788
  }
@@ -767,7 +838,14 @@ $.fn.dropdown = function(parameters) {
767
838
  }
768
839
  return true;
769
840
  },
770
-
841
+ exactSearch: function (query, term) {
842
+ query = query.toLowerCase();
843
+ term = term.toLowerCase();
844
+ if(term.indexOf(query) > -1) {
845
+ return true;
846
+ }
847
+ return false;
848
+ },
771
849
  filterActive: function() {
772
850
  if(settings.useLabels) {
773
851
  $item.filter('.' + className.active)
@@ -776,9 +854,16 @@ $.fn.dropdown = function(parameters) {
776
854
  }
777
855
  },
778
856
 
779
- focusSearch: function() {
780
- if( module.is.search() && !module.is.focusedOnSearch() ) {
781
- $search[0].focus();
857
+ focusSearch: function(skipHandler) {
858
+ if( module.has.search() && !module.is.focusedOnSearch() ) {
859
+ if(skipHandler) {
860
+ $module.off('focus' + eventNamespace, selector.search);
861
+ $search.focus();
862
+ $module.on('focus' + eventNamespace, selector.search, module.event.search.focus);
863
+ }
864
+ else {
865
+ $search.focus();
866
+ }
782
867
  }
783
868
  },
784
869
 
@@ -789,19 +874,22 @@ $.fn.dropdown = function(parameters) {
789
874
  $selectedItem = ($currentlySelected.length > 0)
790
875
  ? $currentlySelected
791
876
  : $activeItem,
792
- hasSelected = ($selectedItem.size() > 0)
877
+ hasSelected = ($selectedItem.length > 0)
793
878
  ;
794
- if( module.has.query() ) {
795
- if(hasSelected) {
796
- module.debug('Forcing partial selection to selected item', $selectedItem);
797
- module.event.item.click.call($selectedItem);
798
- return;
879
+ if(hasSelected) {
880
+ module.debug('Forcing partial selection to selected item', $selectedItem);
881
+ module.event.item.click.call($selectedItem, {}, true);
882
+ return;
883
+ }
884
+ else {
885
+ if(settings.allowAdditions) {
886
+ module.set.selected(module.get.query());
887
+ module.remove.searchTerm();
799
888
  }
800
889
  else {
801
890
  module.remove.searchTerm();
802
891
  }
803
892
  }
804
- module.hide();
805
893
  },
806
894
 
807
895
  event: {
@@ -816,15 +904,6 @@ $.fn.dropdown = function(parameters) {
816
904
  module.show();
817
905
  }
818
906
  },
819
- click: function(event) {
820
- var
821
- $target = $(event.target)
822
- ;
823
- // focus search
824
- if($target.is($module) && !module.is.focusedOnSearch()) {
825
- module.focusSearch();
826
- }
827
- },
828
907
  blur: function(event) {
829
908
  pageLostFocus = (document.activeElement === this);
830
909
  if(!activated && !pageLostFocus) {
@@ -832,12 +911,38 @@ $.fn.dropdown = function(parameters) {
832
911
  module.hide();
833
912
  }
834
913
  },
835
- // prevents focus callback from occurring on mousedown
836
914
  mousedown: function() {
837
- activated = true;
915
+ if(module.is.searchSelection()) {
916
+ // prevent menu hiding on immediate re-focus
917
+ willRefocus = true;
918
+ }
919
+ else {
920
+ // prevents focus callback from occurring on mousedown
921
+ activated = true;
922
+ }
838
923
  },
839
924
  mouseup: function() {
840
- activated = false;
925
+ if(module.is.searchSelection()) {
926
+ // prevent menu hiding on immediate re-focus
927
+ willRefocus = false;
928
+ }
929
+ else {
930
+ activated = false;
931
+ }
932
+ },
933
+ click: function(event) {
934
+ var
935
+ $target = $(event.target)
936
+ ;
937
+ // focus search
938
+ if($target.is($module)) {
939
+ if(!module.is.focusedOnSearch()) {
940
+ module.focusSearch();
941
+ }
942
+ else {
943
+ module.show();
944
+ }
945
+ }
841
946
  },
842
947
  search: {
843
948
  focus: function() {
@@ -847,28 +952,19 @@ $.fn.dropdown = function(parameters) {
847
952
  }
848
953
  if(settings.showOnFocus) {
849
954
  module.search();
850
- module.show();
851
955
  }
852
956
  },
853
957
  blur: function(event) {
854
958
  pageLostFocus = (document.activeElement === this);
855
- if(!itemActivated && !pageLostFocus) {
856
- if(module.is.multiple()) {
857
- module.remove.activeLabel();
858
- module.hide();
859
- }
860
- else if(settings.forceSelection) {
861
- module.forceSelection();
862
- }
863
- else {
959
+ if(!willRefocus) {
960
+ if(!itemActivated && !pageLostFocus) {
961
+ if(settings.forceSelection && module.has.query()) {
962
+ module.forceSelection();
963
+ }
864
964
  module.hide();
865
965
  }
866
966
  }
867
- else if(pageLostFocus) {
868
- if(settings.forceSelection) {
869
- module.forceSelection();
870
- }
871
- }
967
+ willRefocus = false;
872
968
  }
873
969
  },
874
970
  icon: {
@@ -938,6 +1034,9 @@ $.fn.dropdown = function(parameters) {
938
1034
  ? module.show
939
1035
  : module.toggle
940
1036
  ;
1037
+ if(module.is.bubbledLabelClick(event)) {
1038
+ return;
1039
+ }
941
1040
  if( module.determine.eventOnElement(event, toggleBehavior) ) {
942
1041
  event.preventDefault();
943
1042
  }
@@ -959,7 +1058,35 @@ $.fn.dropdown = function(parameters) {
959
1058
  module.determine.eventInModule(event, module.hide);
960
1059
  }
961
1060
  },
1061
+ select: {
1062
+ mutation: function(mutations) {
1063
+ module.debug('<select> modified, recreating menu');
1064
+ module.setup.select();
1065
+ }
1066
+ },
962
1067
  menu: {
1068
+ mutation: function(mutations) {
1069
+ var
1070
+ mutation = mutations[0],
1071
+ $addedNode = mutation.addedNodes
1072
+ ? $(mutation.addedNodes[0])
1073
+ : $(false),
1074
+ $removedNode = mutation.removedNodes
1075
+ ? $(mutation.removedNodes[0])
1076
+ : $(false),
1077
+ $changedNodes = $addedNode.add($removedNode),
1078
+ isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0,
1079
+ isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0
1080
+ ;
1081
+ if(isUserAddition || isMessage) {
1082
+ module.debug('Updating item selector cache');
1083
+ module.refreshItems();
1084
+ }
1085
+ else {
1086
+ module.debug('Menu modified, updating selector cache');
1087
+ module.refresh();
1088
+ }
1089
+ },
963
1090
  mousedown: function() {
964
1091
  itemActivated = true;
965
1092
  },
@@ -970,17 +1097,21 @@ $.fn.dropdown = function(parameters) {
970
1097
  item: {
971
1098
  mouseenter: function(event) {
972
1099
  var
973
- $subMenu = $(this).children(selector.menu),
974
- $otherMenus = $(this).siblings(selector.item).children(selector.menu)
1100
+ $target = $(event.target),
1101
+ $item = $(this),
1102
+ $subMenu = $item.children(selector.menu),
1103
+ $otherMenus = $item.siblings(selector.item).children(selector.menu),
1104
+ hasSubMenu = ($subMenu.length > 0),
1105
+ isBubbledEvent = ($subMenu.find($target).length > 0)
975
1106
  ;
976
- if( $subMenu.length > 0 ) {
1107
+ if( !isBubbledEvent && hasSubMenu ) {
977
1108
  clearTimeout(module.itemTimer);
978
1109
  module.itemTimer = setTimeout(function() {
979
1110
  module.verbose('Showing sub-menu', $subMenu);
980
1111
  $.each($otherMenus, function() {
981
1112
  module.animate.hide(false, $(this));
982
1113
  });
983
- module.animate.show(false, $subMenu);
1114
+ module.animate.show(false, $subMenu);
984
1115
  }, settings.delay.show);
985
1116
  event.preventDefault();
986
1117
  }
@@ -993,13 +1124,11 @@ $.fn.dropdown = function(parameters) {
993
1124
  clearTimeout(module.itemTimer);
994
1125
  module.itemTimer = setTimeout(function() {
995
1126
  module.verbose('Hiding sub-menu', $subMenu);
996
- module.animate.hide(false, $subMenu);
1127
+ module.animate.hide(false, $subMenu);
997
1128
  }, settings.delay.hide);
998
1129
  }
999
1130
  },
1000
- touchend: function() {
1001
- },
1002
- click: function (event) {
1131
+ click: function (event, skipRefocus) {
1003
1132
  var
1004
1133
  $choice = $(this),
1005
1134
  $target = (event)
@@ -1012,9 +1141,17 @@ $.fn.dropdown = function(parameters) {
1012
1141
  isBubbledEvent = ($subMenu.find($target).length > 0)
1013
1142
  ;
1014
1143
  if(!isBubbledEvent && (!hasSubMenu || settings.allowCategorySelection)) {
1144
+ if(module.is.searchSelection()) {
1145
+ if(settings.allowAdditions) {
1146
+ module.remove.userAddition();
1147
+ }
1148
+ module.remove.searchTerm();
1149
+ if(!module.is.focusedOnSearch() && !(skipRefocus == true)) {
1150
+ module.focusSearch(true);
1151
+ }
1152
+ }
1015
1153
  if(!settings.useLabels) {
1016
1154
  module.remove.filteredItem();
1017
- module.remove.searchTerm();
1018
1155
  module.set.scrollPosition($choice);
1019
1156
  }
1020
1157
  module.determine.selectAction.call(this, text, value);
@@ -1150,19 +1287,29 @@ $.fn.dropdown = function(parameters) {
1150
1287
  ? $currentlySelected
1151
1288
  : $activeItem,
1152
1289
  $visibleItems = ($selectedItem.length > 0)
1153
- ? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf()
1290
+ ? $selectedItem.siblings(':not(.' + className.filtered +')').addBack()
1154
1291
  : $menu.children(':not(.' + className.filtered +')'),
1155
- $subMenu = $selectedItem.children(selector.menu),
1156
- $parentMenu = $selectedItem.closest(selector.menu),
1157
- inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
1158
- hasSubMenu = ($subMenu.length> 0),
1159
- hasSelectedItem = ($selectedItem.length > 0),
1160
- selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
1161
- delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
1292
+ $subMenu = $selectedItem.children(selector.menu),
1293
+ $parentMenu = $selectedItem.closest(selector.menu),
1294
+ inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating) || $parentMenu.parent(selector.menu).length > 0),
1295
+ hasSubMenu = ($subMenu.length> 0),
1296
+ hasSelectedItem = ($selectedItem.length > 0),
1297
+ selectedIsSelectable = ($selectedItem.not(selector.unselectable).length > 0),
1298
+ delimiterPressed = (pressedKey == keys.delimiter && settings.allowAdditions && module.is.multiple()),
1299
+ isAdditionWithoutMenu = (settings.allowAdditions && settings.hideAdditions && (pressedKey == keys.enter || delimiterPressed) && selectedIsSelectable),
1162
1300
  $nextItem,
1163
1301
  isSubMenuItem,
1164
1302
  newIndex
1165
1303
  ;
1304
+ // allow selection with menu closed
1305
+ if(isAdditionWithoutMenu) {
1306
+ module.verbose('Selecting item from keyboard shortcut', $selectedItem);
1307
+ module.event.item.click.call($selectedItem, event);
1308
+ if(module.is.searchSelection()) {
1309
+ module.remove.searchTerm();
1310
+ }
1311
+ }
1312
+
1166
1313
  // visible menu keyboard shortcuts
1167
1314
  if( module.is.visible() ) {
1168
1315
 
@@ -1182,38 +1329,41 @@ $.fn.dropdown = function(parameters) {
1182
1329
  event.preventDefault();
1183
1330
  }
1184
1331
 
1185
- // left arrow (hide sub-menu)
1186
- if(pressedKey == keys.leftArrow) {
1332
+ // sub-menu actions
1333
+ if(hasSelectedItem) {
1187
1334
 
1188
- isSubMenuItem = ($parentMenu[0] !== $menu[0]);
1335
+ if(pressedKey == keys.leftArrow) {
1189
1336
 
1190
- if(isSubMenuItem) {
1191
- module.verbose('Left key pressed, closing sub-menu');
1192
- module.animate.hide(false, $parentMenu);
1193
- $selectedItem
1194
- .removeClass(className.selected)
1195
- ;
1196
- $parentMenu
1197
- .closest(selector.item)
1198
- .addClass(className.selected)
1199
- ;
1200
- event.preventDefault();
1337
+ isSubMenuItem = ($parentMenu[0] !== $menu[0]);
1338
+
1339
+ if(isSubMenuItem) {
1340
+ module.verbose('Left key pressed, closing sub-menu');
1341
+ module.animate.hide(false, $parentMenu);
1342
+ $selectedItem
1343
+ .removeClass(className.selected)
1344
+ ;
1345
+ $parentMenu
1346
+ .closest(selector.item)
1347
+ .addClass(className.selected)
1348
+ ;
1349
+ event.preventDefault();
1350
+ }
1201
1351
  }
1202
- }
1203
1352
 
1204
- // right arrow (show sub-menu)
1205
- if(pressedKey == keys.rightArrow) {
1206
- if(hasSubMenu) {
1207
- module.verbose('Right key pressed, opening sub-menu');
1208
- module.animate.show(false, $subMenu);
1209
- $selectedItem
1210
- .removeClass(className.selected)
1211
- ;
1212
- $subMenu
1213
- .find(selector.item).eq(0)
1214
- .addClass(className.selected)
1215
- ;
1216
- event.preventDefault();
1353
+ // right arrow (show sub-menu)
1354
+ if(pressedKey == keys.rightArrow) {
1355
+ if(hasSubMenu) {
1356
+ module.verbose('Right key pressed, opening sub-menu');
1357
+ module.animate.show(false, $subMenu);
1358
+ $selectedItem
1359
+ .removeClass(className.selected)
1360
+ ;
1361
+ $subMenu
1362
+ .find(selector.item).eq(0)
1363
+ .addClass(className.selected)
1364
+ ;
1365
+ event.preventDefault();
1366
+ }
1217
1367
  }
1218
1368
  }
1219
1369
 
@@ -1237,6 +1387,9 @@ $.fn.dropdown = function(parameters) {
1237
1387
  .addClass(className.selected)
1238
1388
  ;
1239
1389
  module.set.scrollPosition($nextItem);
1390
+ if(settings.selectOnKeydown && module.is.single()) {
1391
+ module.set.selectedItem($nextItem);
1392
+ }
1240
1393
  }
1241
1394
  event.preventDefault();
1242
1395
  }
@@ -1261,6 +1414,10 @@ $.fn.dropdown = function(parameters) {
1261
1414
  .addClass(className.selected)
1262
1415
  ;
1263
1416
  module.set.scrollPosition($nextItem);
1417
+ if(settings.selectOnKeydown && module.is.single()) {
1418
+ module.set.activeItem($nextItem);
1419
+ module.set.selected(module.get.choiceValue($nextItem), $nextItem);
1420
+ }
1264
1421
  }
1265
1422
  event.preventDefault();
1266
1423
  }
@@ -1288,15 +1445,16 @@ $.fn.dropdown = function(parameters) {
1288
1445
  event.preventDefault();
1289
1446
  }
1290
1447
  // down arrow (open menu)
1291
- if(pressedKey == keys.downArrow) {
1448
+ if(pressedKey == keys.downArrow && !module.is.visible()) {
1292
1449
  module.verbose('Down key pressed, showing dropdown');
1450
+ module.select.firstUnfiltered();
1293
1451
  module.show();
1294
1452
  event.preventDefault();
1295
1453
  }
1296
1454
  }
1297
1455
  }
1298
1456
  else {
1299
- if( module.is.selection() && !module.is.search() ) {
1457
+ if( !module.has.search() ) {
1300
1458
  module.set.selectedLetter( String.fromCharCode(pressedKey) );
1301
1459
  }
1302
1460
  }
@@ -1322,11 +1480,11 @@ $.fn.dropdown = function(parameters) {
1322
1480
  module.verbose('Determining action', settings.action);
1323
1481
  if( $.isFunction( module.action[settings.action] ) ) {
1324
1482
  module.verbose('Triggering preset action', settings.action, text, value);
1325
- module.action[ settings.action ].call(this, text, value);
1483
+ module.action[ settings.action ].call(element, text, value, this);
1326
1484
  }
1327
1485
  else if( $.isFunction(settings.action) ) {
1328
1486
  module.verbose('Triggering user action', settings.action, text, value);
1329
- settings.action.call(this, text, value);
1487
+ settings.action.call(element, text, value, this);
1330
1488
  }
1331
1489
  else {
1332
1490
  module.error(error.action, settings.action);
@@ -1354,16 +1512,17 @@ $.fn.dropdown = function(parameters) {
1354
1512
  },
1355
1513
  eventOnElement: function(event, callback) {
1356
1514
  var
1357
- $target = $(event.target),
1358
- $label = $target.closest(selector.siblingLabel),
1359
- notOnLabel = ($module.find($label).length === 0),
1360
- notInMenu = ($target.closest($menu).length === 0)
1515
+ $target = $(event.target),
1516
+ $label = $target.closest(selector.siblingLabel),
1517
+ inVisibleDOM = document.body.contains(event.target),
1518
+ notOnLabel = ($module.find($label).length === 0),
1519
+ notInMenu = ($target.closest($menu).length === 0)
1361
1520
  ;
1362
1521
  callback = $.isFunction(callback)
1363
1522
  ? callback
1364
1523
  : function(){}
1365
1524
  ;
1366
- if(notOnLabel && notInMenu) {
1525
+ if(inVisibleDOM && notOnLabel && notInMenu) {
1367
1526
  module.verbose('Triggering event', callback);
1368
1527
  callback();
1369
1528
  return true;
@@ -1379,13 +1538,13 @@ $.fn.dropdown = function(parameters) {
1379
1538
 
1380
1539
  nothing: function() {},
1381
1540
 
1382
- activate: function(text, value) {
1541
+ activate: function(text, value, element) {
1383
1542
  value = (value !== undefined)
1384
1543
  ? value
1385
1544
  : text
1386
1545
  ;
1387
- if( module.can.activate( $(this) ) ) {
1388
- module.set.selected(value, $(this));
1546
+ if( module.can.activate( $(element) ) ) {
1547
+ module.set.selected(value, $(element));
1389
1548
  if(module.is.multiple() && !module.is.allFiltered()) {
1390
1549
  return;
1391
1550
  }
@@ -1395,22 +1554,22 @@ $.fn.dropdown = function(parameters) {
1395
1554
  }
1396
1555
  },
1397
1556
 
1398
- select: function(text, value) {
1557
+ select: function(text, value, element) {
1399
1558
  // mimics action.activate but does not select text
1400
- module.action.activate.call(this);
1559
+ module.action.activate.call(element);
1401
1560
  },
1402
1561
 
1403
- combo: function(text, value) {
1562
+ combo: function(text, value, element) {
1404
1563
  value = (value !== undefined)
1405
1564
  ? value
1406
1565
  : text
1407
1566
  ;
1408
- module.set.selected(value, $(this));
1567
+ module.set.selected(value, $(element));
1409
1568
  module.hideAndClear();
1410
1569
  },
1411
1570
 
1412
- hide: function(text, value) {
1413
- module.set.value(value);
1571
+ hide: function(text, value, element) {
1572
+ module.set.value(value, text);
1414
1573
  module.hideAndClear();
1415
1574
  }
1416
1575
 
@@ -1435,8 +1594,14 @@ $.fn.dropdown = function(parameters) {
1435
1594
  query: function() {
1436
1595
  return $.trim($search.val());
1437
1596
  },
1438
- searchWidth: function(characterCount) {
1439
- return (characterCount * settings.glyphWidth) + 'em';
1597
+ searchWidth: function(value) {
1598
+ value = (value !== undefined)
1599
+ ? value
1600
+ : $search.val()
1601
+ ;
1602
+ $sizer.text(value);
1603
+ // prevent rounding issues
1604
+ return Math.ceil( $sizer.width() + 1);
1440
1605
  },
1441
1606
  selectionCount: function() {
1442
1607
  var
@@ -1502,13 +1667,14 @@ $.fn.dropdown = function(parameters) {
1502
1667
  var
1503
1668
  value = ($input.length > 0)
1504
1669
  ? $input.val()
1505
- : $module.data(metadata.value)
1670
+ : $module.data(metadata.value),
1671
+ isEmptyMultiselect = ($.isArray(value) && value.length === 1 && value[0] === '')
1506
1672
  ;
1507
1673
  // prevents placeholder element from being selected when multiple
1508
- if($.isArray(value) && value.length === 1 && value[0] === '') {
1509
- return '';
1510
- }
1511
- return value;
1674
+ return (value === undefined || isEmptyMultiselect)
1675
+ ? ''
1676
+ : value
1677
+ ;
1512
1678
  },
1513
1679
  values: function() {
1514
1680
  var
@@ -1533,16 +1699,17 @@ $.fn.dropdown = function(parameters) {
1533
1699
  if(typeof values == 'string') {
1534
1700
  values = [values];
1535
1701
  }
1536
- remoteValues = {};
1537
1702
  $.each(values, function(index, value) {
1538
1703
  var
1539
1704
  name = module.read.remoteData(value)
1540
1705
  ;
1541
1706
  module.verbose('Restoring value from session data', name, value);
1542
- remoteValues[value] = (name)
1543
- ? name
1544
- : value
1545
- ;
1707
+ if(name) {
1708
+ if(!remoteValues) {
1709
+ remoteValues = {};
1710
+ }
1711
+ remoteValues[value] = name;
1712
+ }
1546
1713
  });
1547
1714
  }
1548
1715
  return remoteValues;
@@ -1554,7 +1721,7 @@ $.fn.dropdown = function(parameters) {
1554
1721
  ;
1555
1722
  if($choice) {
1556
1723
  if($choice.find(selector.menu).length > 0) {
1557
- module.verbose('Retreiving text of element with sub-menu');
1724
+ module.verbose('Retrieving text of element with sub-menu');
1558
1725
  $choice = $choice.clone();
1559
1726
  $choice.find(selector.menu).remove();
1560
1727
  $choice.find(selector.menuIcon).remove();
@@ -1635,7 +1802,7 @@ $.fn.dropdown = function(parameters) {
1635
1802
  module.debug('Retrieved and sorted values from select', select);
1636
1803
  }
1637
1804
  else {
1638
- module.debug('Retreived values from select', select);
1805
+ module.debug('Retrieved values from select', select);
1639
1806
  }
1640
1807
  return select;
1641
1808
  },
@@ -1776,6 +1943,9 @@ $.fn.dropdown = function(parameters) {
1776
1943
  module.set.text(defaultText);
1777
1944
  }
1778
1945
  },
1946
+ placeholderText: function() {
1947
+ module.set.placeholderText();
1948
+ },
1779
1949
  defaultValue: function() {
1780
1950
  var
1781
1951
  defaultValue = module.get.defaultValue()
@@ -1814,15 +1984,10 @@ $.fn.dropdown = function(parameters) {
1814
1984
  }
1815
1985
  },
1816
1986
  values: function() {
1817
- // prevents callbacks from occuring on initial load
1987
+ // prevents callbacks from occurring on initial load
1818
1988
  module.set.initialLoad();
1819
- if(settings.apiSettings) {
1820
- if(settings.saveRemoteData) {
1821
- module.restore.remoteValues();
1822
- }
1823
- else {
1824
- module.clearValue();
1825
- }
1989
+ if(settings.apiSettings && settings.saveRemoteData && module.get.remoteValues()) {
1990
+ module.restore.remoteValues();
1826
1991
  }
1827
1992
  else {
1828
1993
  module.set.selected();
@@ -1961,6 +2126,9 @@ $.fn.dropdown = function(parameters) {
1961
2126
  $nextSelectedItem
1962
2127
  .addClass(className.selected)
1963
2128
  ;
2129
+ if(settings.selectOnKeydown && module.is.single()) {
2130
+ module.set.selectedItem($nextSelectedItem);
2131
+ }
1964
2132
  $menu
1965
2133
  .scrollTop(newScroll)
1966
2134
  ;
@@ -1977,7 +2145,7 @@ $.fn.dropdown = function(parameters) {
1977
2145
  ? module.get.query()
1978
2146
  : '',
1979
2147
  hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0),
1980
- searchWidth = module.get.searchWidth(searchValue.length),
2148
+ searchWidth = module.get.searchWidth(),
1981
2149
  valueIsSet = searchValue !== ''
1982
2150
  ;
1983
2151
  if(isMultiple && hasSearchValue) {
@@ -1993,6 +2161,9 @@ $.fn.dropdown = function(parameters) {
1993
2161
  $text.removeClass(className.filtered);
1994
2162
  }
1995
2163
  },
2164
+ empty: function() {
2165
+ $module.addClass(className.empty);
2166
+ },
1996
2167
  loading: function() {
1997
2168
  $module.addClass(className.loading);
1998
2169
  },
@@ -2107,6 +2278,12 @@ $.fn.dropdown = function(parameters) {
2107
2278
  }
2108
2279
  }
2109
2280
  },
2281
+ selectedItem: function($item) {
2282
+ module.debug('Setting user selection to item', $item);
2283
+ module.remove.activeItem();
2284
+ module.set.activeItem($item);
2285
+ module.set.selected(module.get.choiceValue($item), $item);
2286
+ },
2110
2287
  selectedLetter: function(letter) {
2111
2288
  var
2112
2289
  $selectedItem = $item.filter('.' + className.selected),
@@ -2138,6 +2315,9 @@ $.fn.dropdown = function(parameters) {
2138
2315
  module.set.scrollPosition($nextValue);
2139
2316
  $selectedItem.removeClass(className.selected);
2140
2317
  $nextValue.addClass(className.selected);
2318
+ if(settings.selectOnKeydown && module.is.single()) {
2319
+ module.set.selectedItem($nextValue);
2320
+ }
2141
2321
  }
2142
2322
  },
2143
2323
  direction: function($menu) {
@@ -2159,6 +2339,7 @@ $.fn.dropdown = function(parameters) {
2159
2339
  },
2160
2340
  value: function(value, text, $selected) {
2161
2341
  var
2342
+ escapedValue = module.escape.value(value),
2162
2343
  hasInput = ($input.length > 0),
2163
2344
  isAddition = !module.has.value(value),
2164
2345
  currentValue = module.get.values(),
@@ -2168,7 +2349,7 @@ $.fn.dropdown = function(parameters) {
2168
2349
  newValue
2169
2350
  ;
2170
2351
  if(hasInput) {
2171
- if(stringValue == currentValue) {
2352
+ if(!settings.allowReselection && stringValue == currentValue) {
2172
2353
  module.verbose('Skipping value update already same value', value, currentValue);
2173
2354
  if(!module.is.initialLoad()) {
2174
2355
  return;
@@ -2179,10 +2360,10 @@ $.fn.dropdown = function(parameters) {
2179
2360
  module.debug('Adding user option', value);
2180
2361
  module.add.optionValue(value);
2181
2362
  }
2182
- module.debug('Updating input value', value, currentValue);
2363
+ module.debug('Updating input value', escapedValue, currentValue);
2183
2364
  internalChange = true;
2184
2365
  $input
2185
- .val(value)
2366
+ .val(escapedValue)
2186
2367
  ;
2187
2368
  if(settings.fireOnInit === false && module.is.initialLoad()) {
2188
2369
  module.debug('Input native change event ignored on initial load');
@@ -2193,8 +2374,8 @@ $.fn.dropdown = function(parameters) {
2193
2374
  internalChange = false;
2194
2375
  }
2195
2376
  else {
2196
- module.verbose('Storing value in metadata', value, $input);
2197
- if(value !== currentValue) {
2377
+ module.verbose('Storing value in metadata', escapedValue, $input);
2378
+ if(escapedValue !== currentValue) {
2198
2379
  $module.data(metadata.value, stringValue);
2199
2380
  }
2200
2381
  }
@@ -2234,6 +2415,9 @@ $.fn.dropdown = function(parameters) {
2234
2415
  return;
2235
2416
  }
2236
2417
  module.debug('Setting selected menu item to', $selectedItem);
2418
+ if(module.is.multiple()) {
2419
+ module.remove.searchWidth();
2420
+ }
2237
2421
  if(module.is.single()) {
2238
2422
  module.remove.activeItem();
2239
2423
  module.remove.selectedItem();
@@ -2299,17 +2483,18 @@ $.fn.dropdown = function(parameters) {
2299
2483
  $next = module.is.searchSelection()
2300
2484
  ? $search
2301
2485
  : $text,
2486
+ escapedValue = module.escape.value(value),
2302
2487
  $label
2303
2488
  ;
2304
2489
  $label = $('<a />')
2305
2490
  .addClass(className.label)
2306
- .attr('data-value', value)
2307
- .html(templates.label(value, text))
2491
+ .attr('data-value', escapedValue)
2492
+ .html(templates.label(escapedValue, text))
2308
2493
  ;
2309
- $label = settings.onLabelCreate.call($label, value, text);
2494
+ $label = settings.onLabelCreate.call($label, escapedValue, text);
2310
2495
 
2311
2496
  if(module.has.label(value)) {
2312
- module.debug('Label already exists, skipping', value);
2497
+ module.debug('Label already exists, skipping', escapedValue);
2313
2498
  return;
2314
2499
  }
2315
2500
  if(settings.label.variation) {
@@ -2350,34 +2535,27 @@ $.fn.dropdown = function(parameters) {
2350
2535
  },
2351
2536
  optionValue: function(value) {
2352
2537
  var
2353
- $option = $input.find('option[value="' + value + '"]'),
2354
- hasOption = ($option.length > 0)
2538
+ escapedValue = module.escape.value(value),
2539
+ $option = $input.find('option[value="' + escapedValue + '"]'),
2540
+ hasOption = ($option.length > 0)
2355
2541
  ;
2356
2542
  if(hasOption) {
2357
2543
  return;
2358
2544
  }
2359
2545
  // temporarily disconnect observer
2360
- if(selectObserver) {
2361
- selectObserver.disconnect();
2362
- module.verbose('Temporarily disconnecting mutation observer', value);
2363
- }
2546
+ module.disconnect.selectObserver();
2364
2547
  if( module.is.single() ) {
2365
2548
  module.verbose('Removing previous user addition');
2366
2549
  $input.find('option.' + className.addition).remove();
2367
2550
  }
2368
2551
  $('<option/>')
2369
- .prop('value', value)
2552
+ .prop('value', escapedValue)
2370
2553
  .addClass(className.addition)
2371
2554
  .html(value)
2372
2555
  .appendTo($input)
2373
2556
  ;
2374
2557
  module.verbose('Adding user addition as an <option>', value);
2375
- if(selectObserver) {
2376
- selectObserver.observe($input[0], {
2377
- childList : true,
2378
- subtree : true
2379
- });
2380
- }
2558
+ module.observe.select();
2381
2559
  },
2382
2560
  userSuggestion: function(value) {
2383
2561
  var
@@ -2394,28 +2572,37 @@ $.fn.dropdown = function(parameters) {
2394
2572
  $addition.remove();
2395
2573
  return;
2396
2574
  }
2397
- $item
2398
- .removeClass(className.selected)
2399
- ;
2400
2575
  if(hasUserSuggestion) {
2401
- html = settings.templates.addition( module.add.variables(message.addResult, value) );
2402
2576
  $addition
2403
- .html(html)
2577
+ .data(metadata.value, value)
2578
+ .data(metadata.text, value)
2404
2579
  .attr('data-' + metadata.value, value)
2405
2580
  .attr('data-' + metadata.text, value)
2406
2581
  .removeClass(className.filtered)
2407
- .addClass(className.selected)
2408
2582
  ;
2583
+ if(!settings.hideAdditions) {
2584
+ html = settings.templates.addition( module.add.variables(message.addResult, value) );
2585
+ $addition
2586
+ .html(html)
2587
+ ;
2588
+ }
2409
2589
  module.verbose('Replacing user suggestion with new value', $addition);
2410
2590
  }
2411
2591
  else {
2412
2592
  $addition = module.create.userChoice(value);
2413
2593
  $addition
2414
2594
  .prependTo($menu)
2415
- .addClass(className.selected)
2416
2595
  ;
2417
2596
  module.verbose('Adding item choice to menu corresponding with user choice addition', $addition);
2418
2597
  }
2598
+ if(!settings.hideAdditions || module.is.allFiltered()) {
2599
+ $addition
2600
+ .addClass(className.selected)
2601
+ .siblings()
2602
+ .removeClass(className.selected)
2603
+ ;
2604
+ }
2605
+ module.refreshItems();
2419
2606
  },
2420
2607
  variables: function(message, term) {
2421
2608
  var
@@ -2488,6 +2675,9 @@ $.fn.dropdown = function(parameters) {
2488
2675
  activeLabel: function() {
2489
2676
  $module.find(selector.label).removeClass(className.active);
2490
2677
  },
2678
+ empty: function() {
2679
+ $module.removeClass(className.empty);
2680
+ },
2491
2681
  loading: function() {
2492
2682
  $module.removeClass(className.loading);
2493
2683
  },
@@ -2514,11 +2704,13 @@ $.fn.dropdown = function(parameters) {
2514
2704
  else {
2515
2705
  $item.removeClass(className.filtered);
2516
2706
  }
2707
+ module.remove.empty();
2517
2708
  },
2518
2709
  optionValue: function(value) {
2519
2710
  var
2520
- $option = $input.find('option[value="' + value + '"]'),
2521
- hasOption = ($option.length > 0)
2711
+ escapedValue = module.escape.value(value),
2712
+ $option = $input.find('option[value="' + escapedValue + '"]'),
2713
+ hasOption = ($option.length > 0)
2522
2714
  ;
2523
2715
  if(!hasOption || !$option.hasClass(className.addition)) {
2524
2716
  return;
@@ -2526,10 +2718,10 @@ $.fn.dropdown = function(parameters) {
2526
2718
  // temporarily disconnect observer
2527
2719
  if(selectObserver) {
2528
2720
  selectObserver.disconnect();
2529
- module.verbose('Temporarily disconnecting mutation observer', value);
2721
+ module.verbose('Temporarily disconnecting mutation observer');
2530
2722
  }
2531
2723
  $option.remove();
2532
- module.verbose('Removing user addition as an <option>', value);
2724
+ module.verbose('Removing user addition as an <option>', escapedValue);
2533
2725
  if(selectObserver) {
2534
2726
  selectObserver.observe($input[0], {
2535
2727
  childList : true,
@@ -2540,11 +2732,17 @@ $.fn.dropdown = function(parameters) {
2540
2732
  message: function() {
2541
2733
  $menu.children(selector.message).remove();
2542
2734
  },
2735
+ searchWidth: function() {
2736
+ $search.css('width', '');
2737
+ },
2543
2738
  searchTerm: function() {
2544
2739
  module.verbose('Cleared search term');
2545
2740
  $search.val('');
2546
2741
  module.set.filtered();
2547
2742
  },
2743
+ userAddition: function() {
2744
+ $item.filter(selector.addition).remove();
2745
+ },
2548
2746
  selected: function(value, $selectedItem) {
2549
2747
  $selectedItem = (settings.allowAdditions)
2550
2748
  ? $selectedItem || module.get.itemWithAdditions(value)
@@ -2657,6 +2855,7 @@ $.fn.dropdown = function(parameters) {
2657
2855
  module.debug('Label remove callback cancelled removal');
2658
2856
  return;
2659
2857
  }
2858
+ module.remove.message();
2660
2859
  if(isUserValue) {
2661
2860
  module.remove.value(stringValue);
2662
2861
  module.remove.label(stringValue);
@@ -2691,12 +2890,28 @@ $.fn.dropdown = function(parameters) {
2691
2890
  },
2692
2891
 
2693
2892
  has: {
2893
+ menuSearch: function() {
2894
+ return (module.has.search() && $search.closest($menu).length > 0);
2895
+ },
2694
2896
  search: function() {
2695
2897
  return ($search.length > 0);
2696
2898
  },
2899
+ sizer: function() {
2900
+ return ($sizer.length > 0);
2901
+ },
2697
2902
  selectInput: function() {
2698
2903
  return ( $input.is('select') );
2699
2904
  },
2905
+ minCharacters: function(searchTerm) {
2906
+ if(settings.minCharacters) {
2907
+ searchTerm = (searchTerm !== undefined)
2908
+ ? String(searchTerm)
2909
+ : String(module.get.query())
2910
+ ;
2911
+ return (searchTerm.length >= settings.minCharacters);
2912
+ }
2913
+ return true;
2914
+ },
2700
2915
  firstLetter: function($item, letter) {
2701
2916
  var
2702
2917
  text,
@@ -2724,15 +2939,22 @@ $.fn.dropdown = function(parameters) {
2724
2939
  },
2725
2940
  label: function(value) {
2726
2941
  var
2727
- $labels = $module.find(selector.label)
2942
+ escapedValue = module.escape.value(value),
2943
+ $labels = $module.find(selector.label)
2728
2944
  ;
2729
- return ($labels.filter('[data-value="' + value +'"]').length > 0);
2945
+ return ($labels.filter('[data-value="' + escapedValue +'"]').length > 0);
2730
2946
  },
2731
2947
  maxSelections: function() {
2732
2948
  return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
2733
2949
  },
2734
2950
  allResultsFiltered: function() {
2735
- return ($item.filter(selector.unselectable).length === $item.length);
2951
+ var
2952
+ $normalResults = $item.not(selector.addition)
2953
+ ;
2954
+ return ($normalResults.filter(selector.unselectable).length === $normalResults.length);
2955
+ },
2956
+ userSuggestion: function() {
2957
+ return ($menu.children(selector.addition).length > 0);
2736
2958
  },
2737
2959
  query: function() {
2738
2960
  return (module.get.query() !== '');
@@ -2755,6 +2977,9 @@ $.fn.dropdown = function(parameters) {
2755
2977
  active: function() {
2756
2978
  return $module.hasClass(className.active);
2757
2979
  },
2980
+ bubbledLabelClick: function(event) {
2981
+ return $(event.target).is('select, input') && $module.closest('label').length > 0;
2982
+ },
2758
2983
  alreadySetup: function() {
2759
2984
  return ($module.is('select') && $module.parent(selector.dropdown).length > 0 && $module.prev().length === 0);
2760
2985
  },
@@ -2774,7 +2999,7 @@ $.fn.dropdown = function(parameters) {
2774
2999
  return (document.activeElement === $search[0]);
2775
3000
  },
2776
3001
  allFiltered: function() {
2777
- return( (module.is.multiple() || module.has.search()) && !module.has.message() && module.has.allResultsFiltered() );
3002
+ return( (module.is.multiple() || module.has.search()) && !(settings.hideAdditions == false && module.has.userSuggestion()) && !module.has.message() && module.has.allResultsFiltered() );
2778
3003
  },
2779
3004
  hidden: function($subMenu) {
2780
3005
  return !module.is.visible($subMenu);
@@ -3031,6 +3256,26 @@ $.fn.dropdown = function(parameters) {
3031
3256
  },
3032
3257
 
3033
3258
  escape: {
3259
+ value: function(value) {
3260
+ var
3261
+ multipleValues = $.isArray(value),
3262
+ stringValue = (typeof value === 'string'),
3263
+ isUnparsable = (!stringValue && !multipleValues),
3264
+ hasQuotes = (stringValue && value.search(regExp.quote) !== -1),
3265
+ values = []
3266
+ ;
3267
+ if(!module.has.selectInput() || isUnparsable || !hasQuotes) {
3268
+ return value;
3269
+ }
3270
+ module.debug('Encoding quote values for use in select', value);
3271
+ if(multipleValues) {
3272
+ $.each(value, function(index, value){
3273
+ values.push(value.replace(regExp.quote, '&quot;'));
3274
+ });
3275
+ return values;
3276
+ }
3277
+ return value.replace(regExp.quote, '&quot;');
3278
+ },
3034
3279
  regExp: function(text) {
3035
3280
  text = String(text);
3036
3281
  return text.replace(regExp.escape, '\\$&');
@@ -3043,7 +3288,12 @@ $.fn.dropdown = function(parameters) {
3043
3288
  $.extend(true, settings, name);
3044
3289
  }
3045
3290
  else if(value !== undefined) {
3046
- settings[name] = value;
3291
+ if($.isPlainObject(settings[name])) {
3292
+ $.extend(true, settings[name], value);
3293
+ }
3294
+ else {
3295
+ settings[name] = value;
3296
+ }
3047
3297
  }
3048
3298
  else {
3049
3299
  return settings[name];
@@ -3061,7 +3311,7 @@ $.fn.dropdown = function(parameters) {
3061
3311
  }
3062
3312
  },
3063
3313
  debug: function() {
3064
- if(settings.debug) {
3314
+ if(!settings.silent && settings.debug) {
3065
3315
  if(settings.performance) {
3066
3316
  module.performance.log(arguments);
3067
3317
  }
@@ -3072,7 +3322,7 @@ $.fn.dropdown = function(parameters) {
3072
3322
  }
3073
3323
  },
3074
3324
  verbose: function() {
3075
- if(settings.verbose && settings.debug) {
3325
+ if(!settings.silent && settings.verbose && settings.debug) {
3076
3326
  if(settings.performance) {
3077
3327
  module.performance.log(arguments);
3078
3328
  }
@@ -3083,8 +3333,10 @@ $.fn.dropdown = function(parameters) {
3083
3333
  }
3084
3334
  },
3085
3335
  error: function() {
3086
- module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
3087
- module.error.apply(console, arguments);
3336
+ if(!settings.silent) {
3337
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
3338
+ module.error.apply(console, arguments);
3339
+ }
3088
3340
  },
3089
3341
  performance: {
3090
3342
  log: function(message) {
@@ -3215,6 +3467,7 @@ $.fn.dropdown = function(parameters) {
3215
3467
 
3216
3468
  $.fn.dropdown.settings = {
3217
3469
 
3470
+ silent : false,
3218
3471
  debug : false,
3219
3472
  verbose : false,
3220
3473
  performance : true,
@@ -3224,28 +3477,33 @@ $.fn.dropdown.settings = {
3224
3477
 
3225
3478
 
3226
3479
  apiSettings : false,
3227
- saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
3228
- throttle : 200, // How long to wait after last user input to search remotely
3480
+ selectOnKeydown : true, // Whether selection should occur automatically when keyboard shortcuts used
3481
+ minCharacters : 0, // Minimum characters required to trigger API call
3482
+ saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
3483
+ throttle : 200, // How long to wait after last user input to search remotely
3229
3484
 
3230
- context : window, // Context to use when determining if on screen
3485
+ context : window, // Context to use when determining if on screen
3231
3486
  direction : 'auto', // Whether dropdown should always open in one direction
3232
3487
  keepOnScreen : true, // Whether dropdown should check whether it is on screen before showing
3233
3488
 
3234
3489
  match : 'both', // what to match against with search selection (both, text, or label)
3235
- fullTextSearch : false, // search anywhere in value
3490
+ fullTextSearch : false, // search anywhere in value (set to 'exact' to require exact matches)
3236
3491
 
3237
3492
  placeholder : 'auto', // whether to convert blank <select> values to placeholder text
3238
3493
  preserveHTML : true, // preserve html when selecting value
3239
3494
  sortSelect : false, // sort selection on init
3240
3495
 
3241
3496
  forceSelection : true, // force a choice on blur with search selection
3497
+
3242
3498
  allowAdditions : false, // whether multiple select should allow user added values
3499
+ hideAdditions : true, // whether or not to hide special message prompting a user they can enter a value
3243
3500
 
3244
3501
  maxSelections : false, // When set to a number limits the number of selections to this count
3245
3502
  useLabels : true, // whether multiple select should filter currently active selections from choices
3246
3503
  delimiter : ',', // when multiselect uses normal <input> the values will be delimited with this character
3247
3504
 
3248
3505
  showOnFocus : true, // show menu on focus
3506
+ allowReselection : false, // whether current value should trigger callbacks when reselected
3249
3507
  allowTab : true, // add tabindex to element
3250
3508
  allowCategorySelection : false, // allow elements with sub-menus to be selected
3251
3509
 
@@ -3254,7 +3512,7 @@ $.fn.dropdown.settings = {
3254
3512
  transition : 'auto', // auto transition will slide down or up based on direction
3255
3513
  duration : 200, // duration of transition
3256
3514
 
3257
- glyphWidth : 1.0714, // widest glyph width in em (W is 1.0714 em) used to calculate multiselect input width
3515
+ glyphWidth : 1.037, // widest glyph width in em (W is 1.037 em) used to calculate multiselect input width
3258
3516
 
3259
3517
  // label settings on multi-select
3260
3518
  label: {
@@ -3308,6 +3566,7 @@ $.fn.dropdown.settings = {
3308
3566
 
3309
3567
  regExp : {
3310
3568
  escape : /[-[\]{}()*+?.,\\^$|#\s]/g,
3569
+ quote : /"/g
3311
3570
  },
3312
3571
 
3313
3572
  metadata : {
@@ -3320,10 +3579,12 @@ $.fn.dropdown.settings = {
3320
3579
 
3321
3580
  // property names for remote query
3322
3581
  fields: {
3323
- remoteValues : 'results', // grouping for api results
3324
- values : 'values', // grouping for all dropdown values
3325
- name : 'name', // displayed dropdown text
3326
- value : 'value' // actual dropdown value
3582
+ remoteValues : 'results', // grouping for api results
3583
+ values : 'values', // grouping for all dropdown values
3584
+ disabled : 'disabled', // whether value should be disabled
3585
+ name : 'name', // displayed dropdown text
3586
+ value : 'value', // actual dropdown value
3587
+ text : 'text' // displayed text when selected
3327
3588
  },
3328
3589
 
3329
3590
  keys : {
@@ -3343,6 +3604,7 @@ $.fn.dropdown.settings = {
3343
3604
  selector : {
3344
3605
  addition : '.addition',
3345
3606
  dropdown : '.ui.dropdown',
3607
+ hidden : '.hidden',
3346
3608
  icon : '> .dropdown.icon',
3347
3609
  input : '> input[type="hidden"], > select',
3348
3610
  item : '.item',
@@ -3352,7 +3614,8 @@ $.fn.dropdown.settings = {
3352
3614
  menu : '.menu',
3353
3615
  message : '.message',
3354
3616
  menuIcon : '.dropdown.icon',
3355
- search : 'input.search, .menu > .search > input',
3617
+ search : 'input.search, .menu > .search > input, .menu input.search',
3618
+ sizer : '> input.sizer',
3356
3619
  text : '> .text:not(.icon)',
3357
3620
  unselectable : '.disabled, .filtered'
3358
3621
  },
@@ -3362,6 +3625,7 @@ $.fn.dropdown.settings = {
3362
3625
  addition : 'addition',
3363
3626
  animating : 'animating',
3364
3627
  disabled : 'disabled',
3628
+ empty : 'empty',
3365
3629
  dropdown : 'ui dropdown',
3366
3630
  filtered : 'filtered',
3367
3631
  hidden : 'hidden transition',
@@ -3372,6 +3636,7 @@ $.fn.dropdown.settings = {
3372
3636
  message : 'message',
3373
3637
  multiple : 'multiple',
3374
3638
  placeholder : 'default',
3639
+ sizer : 'sizer',
3375
3640
  search : 'search',
3376
3641
  selected : 'selected',
3377
3642
  selection : 'selection',
@@ -3416,7 +3681,17 @@ $.fn.dropdown.settings.templates = {
3416
3681
  html = ''
3417
3682
  ;
3418
3683
  $.each(values, function(index, option) {
3419
- html += '<div class="item" data-value="' + option[fields.value] + '">' + option[fields.name] + '</div>';
3684
+ var
3685
+ maybeText = (option[fields.text])
3686
+ ? 'data-text="' + option[fields.text] + '"'
3687
+ : '',
3688
+ maybeDisabled = (option[fields.disabled])
3689
+ ? 'disabled '
3690
+ : ''
3691
+ ;
3692
+ html += '<div class="'+ maybeDisabled +'item" data-value="' + option[fields.value] + '"' + maybeText + '>'
3693
+ html += option[fields.name];
3694
+ html += '</div>';
3420
3695
  });
3421
3696
  return html;
3422
3697
  },