semantic-ui-sass 0.19.3.1 → 1.7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +5 -6
  4. data/app/assets/fonts/semantic-ui/icons.eot +0 -0
  5. data/app/assets/fonts/semantic-ui/icons.otf +0 -0
  6. data/app/assets/fonts/semantic-ui/icons.svg +472 -367
  7. data/app/assets/fonts/semantic-ui/icons.ttf +0 -0
  8. data/app/assets/fonts/semantic-ui/icons.woff +0 -0
  9. data/app/assets/images/semantic-ui/flags.png +0 -0
  10. data/app/assets/javascripts/semantic-ui.js +9 -5
  11. data/app/assets/javascripts/semantic-ui/accordion.js +169 -102
  12. data/app/assets/javascripts/semantic-ui/api.js +840 -0
  13. data/app/assets/javascripts/semantic-ui/checkbox.js +203 -46
  14. data/app/assets/javascripts/semantic-ui/{behavior/colorize.js → colorize.js} +4 -2
  15. data/app/assets/javascripts/semantic-ui/dimmer.js +110 -76
  16. data/app/assets/javascripts/semantic-ui/dropdown.js +897 -285
  17. data/app/assets/javascripts/semantic-ui/{behavior/form.js → form.js} +127 -42
  18. data/app/assets/javascripts/semantic-ui/modal.js +294 -219
  19. data/app/assets/javascripts/semantic-ui/nag.js +120 -186
  20. data/app/assets/javascripts/semantic-ui/popup.js +491 -223
  21. data/app/assets/javascripts/semantic-ui/progress.js +779 -0
  22. data/app/assets/javascripts/semantic-ui/rating.js +66 -22
  23. data/app/assets/javascripts/semantic-ui/search.js +219 -99
  24. data/app/assets/javascripts/semantic-ui/shape.js +72 -29
  25. data/app/assets/javascripts/semantic-ui/sidebar.js +678 -142
  26. data/app/assets/javascripts/semantic-ui/site.js +487 -0
  27. data/app/assets/javascripts/semantic-ui/{behavior/state.js → state.js} +116 -151
  28. data/app/assets/javascripts/semantic-ui/sticky.js +771 -0
  29. data/app/assets/javascripts/semantic-ui/tab.js +680 -603
  30. data/app/assets/javascripts/semantic-ui/transition.js +269 -158
  31. data/app/assets/javascripts/semantic-ui/video.js +113 -32
  32. data/app/assets/javascripts/semantic-ui/visibility.js +970 -0
  33. data/app/assets/javascripts/semantic-ui/visit.js +513 -0
  34. data/app/assets/stylesheets/semantic-ui.scss +2 -0
  35. data/app/assets/stylesheets/semantic-ui/collections/_breadcrumb.scss +58 -14
  36. data/app/assets/stylesheets/semantic-ui/collections/_form.scss +464 -372
  37. data/app/assets/stylesheets/semantic-ui/collections/_grid.scss +1385 -533
  38. data/app/assets/stylesheets/semantic-ui/collections/_menu.scss +482 -655
  39. data/app/assets/stylesheets/semantic-ui/collections/_message.scss +238 -139
  40. data/app/assets/stylesheets/semantic-ui/collections/_table.scss +631 -280
  41. data/app/assets/stylesheets/semantic-ui/elements/_all.scss +3 -2
  42. data/app/assets/stylesheets/semantic-ui/elements/_button.scss +1614 -657
  43. data/app/assets/stylesheets/semantic-ui/elements/_divider.scss +143 -80
  44. data/app/assets/stylesheets/semantic-ui/elements/_flag.scss +1018 -0
  45. data/app/assets/stylesheets/semantic-ui/elements/_header.scss +302 -145
  46. data/app/assets/stylesheets/semantic-ui/elements/_icon.scss +1653 -1365
  47. data/app/assets/stylesheets/semantic-ui/elements/_image.scss +160 -59
  48. data/app/assets/stylesheets/semantic-ui/elements/_input.scss +247 -118
  49. data/app/assets/stylesheets/semantic-ui/elements/_label.scss +501 -470
  50. data/app/assets/stylesheets/semantic-ui/elements/_list.scss +888 -0
  51. data/app/assets/stylesheets/semantic-ui/elements/_loader.scss +189 -98
  52. data/app/assets/stylesheets/semantic-ui/elements/_rail.scss +125 -0
  53. data/app/assets/stylesheets/semantic-ui/elements/_reveal.scss +147 -212
  54. data/app/assets/stylesheets/semantic-ui/elements/_segment.scss +328 -190
  55. data/app/assets/stylesheets/semantic-ui/elements/_step.scss +261 -185
  56. data/app/assets/stylesheets/semantic-ui/globals/_all.scss +2 -0
  57. data/app/assets/stylesheets/semantic-ui/globals/_reset.scss +430 -0
  58. data/app/assets/stylesheets/semantic-ui/globals/_site.scss +128 -0
  59. data/app/assets/stylesheets/semantic-ui/modules/_accordion.scss +190 -106
  60. data/app/assets/stylesheets/semantic-ui/modules/_all.scss +2 -1
  61. data/app/assets/stylesheets/semantic-ui/modules/_checkbox.scss +303 -201
  62. data/app/assets/stylesheets/semantic-ui/modules/_dimmer.scss +72 -63
  63. data/app/assets/stylesheets/semantic-ui/modules/_dropdown.scss +711 -331
  64. data/app/assets/stylesheets/semantic-ui/modules/_modal.scss +262 -140
  65. data/app/assets/stylesheets/semantic-ui/modules/_nag.scss +82 -71
  66. data/app/assets/stylesheets/semantic-ui/modules/_popup.scss +163 -119
  67. data/app/assets/stylesheets/semantic-ui/modules/_progress.scss +435 -0
  68. data/app/assets/stylesheets/semantic-ui/modules/_rating.scss +163 -68
  69. data/app/assets/stylesheets/semantic-ui/modules/_search.scss +223 -150
  70. data/app/assets/stylesheets/semantic-ui/modules/_shape.scss +39 -40
  71. data/app/assets/stylesheets/semantic-ui/modules/_sidebar.scss +413 -147
  72. data/app/assets/stylesheets/semantic-ui/modules/_sticky.scss +80 -0
  73. data/app/assets/stylesheets/semantic-ui/modules/_tab.scss +49 -20
  74. data/app/assets/stylesheets/semantic-ui/modules/_transition.scss +542 -568
  75. data/app/assets/stylesheets/semantic-ui/modules/_video.scss +69 -37
  76. data/app/assets/stylesheets/semantic-ui/views/_ad.scss +265 -0
  77. data/app/assets/stylesheets/semantic-ui/views/_all.scss +1 -1
  78. data/app/assets/stylesheets/semantic-ui/views/_card.scss +758 -0
  79. data/app/assets/stylesheets/semantic-ui/views/_comment.scss +133 -92
  80. data/app/assets/stylesheets/semantic-ui/views/_feed.scss +200 -87
  81. data/app/assets/stylesheets/semantic-ui/views/_item.scss +298 -523
  82. data/app/assets/stylesheets/semantic-ui/views/_statistic.scss +390 -12
  83. data/lib/semantic/ui/sass/version.rb +2 -2
  84. data/tasks/converter.rb +99 -216
  85. metadata +22 -27
  86. data/app/assets/fonts/semantic-ui/basic.icons.eot +0 -0
  87. data/app/assets/fonts/semantic-ui/basic.icons.svg +0 -450
  88. data/app/assets/fonts/semantic-ui/basic.icons.ttf +0 -0
  89. data/app/assets/fonts/semantic-ui/basic.icons.woff +0 -0
  90. data/app/assets/images/semantic-ui/loader-large-inverted.gif +0 -0
  91. data/app/assets/images/semantic-ui/loader-large.gif +0 -0
  92. data/app/assets/images/semantic-ui/loader-medium-inverted.gif +0 -0
  93. data/app/assets/images/semantic-ui/loader-medium.gif +0 -0
  94. data/app/assets/images/semantic-ui/loader-mini-inverted.gif +0 -0
  95. data/app/assets/images/semantic-ui/loader-mini.gif +0 -0
  96. data/app/assets/images/semantic-ui/loader-small-inverted.gif +0 -0
  97. data/app/assets/images/semantic-ui/loader-small.gif +0 -0
  98. data/app/assets/javascripts/semantic-ui/behavior/api.js +0 -634
  99. data/app/assets/javascripts/semantic-ui/chatroom.js +0 -772
  100. data/app/assets/stylesheets/semantic-ui/depends/_basic.icon.scss +0 -4
  101. data/app/assets/stylesheets/semantic-ui/depends/_icon.scss +0 -4
  102. data/app/assets/stylesheets/semantic-ui/depends/_loader.scss +0 -8
  103. data/app/assets/stylesheets/semantic-ui/elements/_basic.icon.scss +0 -1124
  104. data/app/assets/stylesheets/semantic-ui/elements/_progress.scss +0 -280
  105. data/app/assets/stylesheets/semantic-ui/modules/_chatroom.scss +0 -299
  106. data/app/assets/stylesheets/semantic-ui/modules/_reveal.scss +0 -322
  107. data/app/assets/stylesheets/semantic-ui/views/_list.scss +0 -700
@@ -1,17 +1,20 @@
1
1
  /*
2
2
  * # Semantic - Dropdown
3
- * http://github.com/jlukic/semantic-ui/
3
+ * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2014 Contributors
6
+ * Copyright 2014 Contributor
7
7
  * Released under the MIT license
8
8
  * http://opensource.org/licenses/MIT
9
9
  *
10
10
  */
11
+
11
12
  ;(function ( $, window, document, undefined ) {
12
13
 
14
+ "use strict";
15
+
13
16
  $.fn.dropdown = function(parameters) {
14
- var
17
+ var
15
18
  $allModules = $(this),
16
19
  $document = $(document),
17
20
 
@@ -44,15 +47,25 @@ $.fn.dropdown = function(parameters) {
44
47
  moduleNamespace = 'module-' + namespace,
45
48
 
46
49
  $module = $(this),
47
- $item = $module.find(selector.item),
48
50
  $text = $module.find(selector.text),
51
+ $search = $module.find(selector.search),
49
52
  $input = $module.find(selector.input),
50
53
 
51
- $menu = $module.children(selector.menu),
54
+ $combo = ($module.prev().find(selector.text).size() > 0)
55
+ ? $module.prev().find(selector.text)
56
+ : $module.prev(),
52
57
 
58
+ $menu = $module.children(selector.menu),
59
+ $item = $menu.find(selector.item),
53
60
 
61
+ activated = false,
62
+ itemActivated = false,
54
63
  element = this,
55
64
  instance = $module.data(moduleNamespace),
65
+
66
+ elementNamespace,
67
+ id,
68
+ observer,
56
69
  module
57
70
  ;
58
71
 
@@ -60,15 +73,19 @@ $.fn.dropdown = function(parameters) {
60
73
 
61
74
  initialize: function() {
62
75
  module.debug('Initializing dropdown', settings);
63
-
76
+ module.setup.layout();
64
77
  module.save.defaults();
65
78
  module.set.selected();
66
79
 
80
+ module.create.id();
81
+
67
82
  if(hasTouch) {
68
83
  module.bind.touchEvents();
69
84
  }
70
85
  module.bind.mouseEvents();
71
86
  module.bind.keyboardEvents();
87
+
88
+ module.observeChanges();
72
89
  module.instantiate();
73
90
  },
74
91
 
@@ -82,69 +99,251 @@ $.fn.dropdown = function(parameters) {
82
99
 
83
100
  destroy: function() {
84
101
  module.verbose('Destroying previous dropdown for', $module);
85
- $item
86
- .off(eventNamespace)
87
- ;
102
+ module.remove.tabbable();
88
103
  $module
89
104
  .off(eventNamespace)
90
105
  .removeData(moduleNamespace)
91
106
  ;
107
+ $document
108
+ .off(elementNamespace)
109
+ ;
110
+ },
111
+
112
+ observeChanges: function() {
113
+ if('MutationObserver' in window) {
114
+ observer = new MutationObserver(function(mutations) {
115
+ module.debug('DOM tree modified, updating selector cache');
116
+ module.refresh();
117
+ });
118
+ observer.observe(element, {
119
+ childList : true,
120
+ subtree : true
121
+ });
122
+ module.debug('Setting up mutation observer', observer);
123
+ }
124
+ },
125
+
126
+ create: {
127
+ id: function() {
128
+ module.verbose('Creating unique id for element');
129
+ id = module.get.uniqueID();
130
+ elementNamespace = '.' + id;
131
+ }
132
+ },
133
+
134
+ search: function() {
135
+ var
136
+ query
137
+ ;
138
+ query = $search.val();
139
+
140
+ module.verbose('Searching for query', query);
141
+
142
+ if(module.is.searchSelection()) {
143
+ module.filter(query);
144
+ if( module.can.show() ) {
145
+ module.show();
146
+ }
147
+ }
148
+ },
149
+
150
+ setup: {
151
+
152
+ layout: function() {
153
+ if( $module.is('select') ) {
154
+ module.setup.select();
155
+ }
156
+ if( module.is.search() && !module.is.searchable() ) {
157
+ $search = $('<input />')
158
+ .addClass(className.search)
159
+ .insertBefore($text)
160
+ ;
161
+ }
162
+ if(settings.allowTab) {
163
+ module.set.tabbable();
164
+ }
165
+ },
166
+ select: function() {
167
+ var
168
+ selectValues = module.get.selectValues()
169
+ ;
170
+ module.debug('Dropdown initialized on a select', selectValues);
171
+ // see if select exists inside a dropdown
172
+ $input = $module;
173
+ if($input.parents(selector.dropdown).size() > 0) {
174
+ module.debug('Creating dropdown menu only from template');
175
+ $module = $input.closest(selector.dropdown);
176
+ if($module.find('.' + className.dropdown).size() === 0) {
177
+ $('<div />')
178
+ .addClass(className.menu)
179
+ .html( settings.templates.menu( selectValues ))
180
+ .appendTo($module)
181
+ ;
182
+ }
183
+ }
184
+ else {
185
+ module.debug('Creating entire dropdown from template');
186
+ $module = $('<div />')
187
+ .attr('class', $input.attr('class') )
188
+ .addClass(className.selection)
189
+ .addClass(className.dropdown)
190
+ .html( settings.templates.dropdown(selectValues) )
191
+ .insertBefore($input)
192
+ ;
193
+ $input
194
+ .removeAttr('class')
195
+ .prependTo($module)
196
+ ;
197
+ }
198
+ module.refresh();
199
+ }
200
+ },
201
+
202
+ refresh: function() {
203
+ $text = $module.find(selector.text);
204
+ $search = $module.find(selector.search);
205
+ $input = $module.find(selector.input);
206
+ $menu = $module.children(selector.menu);
207
+ $item = $menu.find(selector.item);
208
+ },
209
+
210
+ toggle: function() {
211
+ module.verbose('Toggling menu visibility');
212
+ if( !module.is.active() ) {
213
+ module.show();
214
+ }
215
+ else {
216
+ module.hide();
217
+ }
218
+ },
219
+
220
+ show: function(callback) {
221
+ callback = $.isFunction(callback)
222
+ ? callback
223
+ : function(){}
224
+ ;
225
+ if( !module.is.active() && !module.is.allFiltered() ) {
226
+ module.debug('Showing dropdown');
227
+ module.animate.show(function() {
228
+ if( module.can.click() ) {
229
+ module.bind.intent();
230
+ }
231
+ module.set.visible();
232
+ $.proxy(callback, element)();
233
+ });
234
+ $.proxy(settings.onShow, element)();
235
+ }
236
+ },
237
+
238
+ hide: function(callback) {
239
+ callback = $.isFunction(callback)
240
+ ? callback
241
+ : function(){}
242
+ ;
243
+ if( module.is.active() ) {
244
+ module.debug('Hiding dropdown');
245
+ module.animate.hide(function() {
246
+ module.remove.visible();
247
+ $.proxy(callback, element)();
248
+ });
249
+ $.proxy(settings.onHide, element)();
250
+ }
251
+ },
252
+
253
+ hideOthers: function() {
254
+ module.verbose('Finding other dropdowns to hide');
255
+ $allModules
256
+ .not($module)
257
+ .has(selector.menu + ':visible:not(.' + className.animating + ')')
258
+ .dropdown('hide')
259
+ ;
260
+ },
261
+
262
+ hideSubMenus: function() {
263
+ var
264
+ $subMenus = $menu.find(selector.menu)
265
+ ;
266
+ $subMenus.transition('hide');
92
267
  },
93
268
 
94
269
  bind: {
95
270
  keyboardEvents: function() {
96
271
  module.debug('Binding keyboard events');
97
272
  $module
98
- .on('keydown' + eventNamespace, module.handleKeyboard)
99
- ;
100
- $module
101
- .on('focus' + eventNamespace, module.show)
273
+ .on('keydown' + eventNamespace, module.event.keydown)
102
274
  ;
275
+ if( module.is.searchable() ) {
276
+ $module
277
+ .on(module.get.inputEvent(), selector.search, module.event.input)
278
+ ;
279
+ }
103
280
  },
104
281
  touchEvents: function() {
105
- module.debug('Touch device detected binding touch events');
106
- $module
107
- .on('touchstart' + eventNamespace, module.event.test.toggle)
108
- ;
109
- $item
110
- .on('touchstart' + eventNamespace, module.event.item.mouseenter)
111
- .on('touchstart' + eventNamespace, module.event.item.click)
282
+ module.debug('Touch device detected binding additional touch events');
283
+ if( module.is.searchSelection() ) {
284
+ // do nothing special yet
285
+ }
286
+ else {
287
+ $module
288
+ .on('touchstart' + eventNamespace, module.event.test.toggle)
289
+ ;
290
+ }
291
+ $menu
292
+ .on('touchstart' + eventNamespace, selector.item, module.event.item.mouseenter)
112
293
  ;
113
294
  },
114
295
  mouseEvents: function() {
115
296
  module.verbose('Mouse detected binding mouse events');
116
- if(settings.on == 'click') {
117
- $module
118
- .on('click' + eventNamespace, module.event.test.toggle)
119
- ;
120
- }
121
- else if(settings.on == 'hover') {
297
+
298
+ if( module.is.searchSelection() ) {
122
299
  $module
123
- .on('mouseenter' + eventNamespace, module.delay.show)
124
- .on('mouseleave' + eventNamespace, module.delay.hide)
300
+ .on('mousedown' + eventNamespace, selector.menu, module.event.menu.activate)
301
+ .on('mouseup' + eventNamespace, selector.menu, module.event.menu.deactivate)
302
+ .on('click' + eventNamespace, selector.search, module.show)
303
+ .on('focus' + eventNamespace, selector.search, module.event.searchFocus)
304
+ .on('blur' + eventNamespace, selector.search, module.event.searchBlur)
125
305
  ;
126
306
  }
127
307
  else {
308
+ if(settings.on == 'click') {
309
+ $module
310
+ .on('click' + eventNamespace, module.event.test.toggle)
311
+ ;
312
+ }
313
+ else if(settings.on == 'hover') {
314
+ $module
315
+ .on('mouseenter' + eventNamespace, module.delay.show)
316
+ .on('mouseleave' + eventNamespace, module.delay.hide)
317
+ ;
318
+ }
319
+ else {
320
+ $module
321
+ .on(settings.on + eventNamespace, module.toggle)
322
+ ;
323
+ }
128
324
  $module
129
- .on(settings.on + eventNamespace, module.toggle)
325
+ .on('mousedown' + eventNamespace, module.event.mousedown)
326
+ .on('mouseup' + eventNamespace, module.event.mouseup)
327
+ .on('focus' + eventNamespace, module.event.focus)
328
+ .on('blur' + eventNamespace, module.event.blur)
130
329
  ;
131
330
  }
132
- $item
133
- .on('mouseenter' + eventNamespace, module.event.item.mouseenter)
134
- .on('mouseleave' + eventNamespace, module.event.item.mouseleave)
135
- .on('click' + eventNamespace, module.event.item.click)
331
+ $menu
332
+ .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
333
+ .on('mouseleave' + eventNamespace, selector.item, module.event.item.mouseleave)
334
+ .on('click' + eventNamespace, selector.item, module.event.item.click)
136
335
  ;
137
336
  },
138
337
  intent: function() {
139
338
  module.verbose('Binding hide intent event to document');
140
339
  if(hasTouch) {
141
340
  $document
142
- .on('touchstart' + eventNamespace, module.event.test.touch)
143
- .on('touchmove' + eventNamespace, module.event.test.touch)
341
+ .on('touchstart' + elementNamespace, module.event.test.touch)
342
+ .on('touchmove' + elementNamespace, module.event.test.touch)
144
343
  ;
145
344
  }
146
345
  $document
147
- .on('click' + eventNamespace, module.event.test.hide)
346
+ .on('click' + elementNamespace, module.event.test.hide)
148
347
  ;
149
348
  }
150
349
  },
@@ -154,88 +353,202 @@ $.fn.dropdown = function(parameters) {
154
353
  module.verbose('Removing hide intent event from document');
155
354
  if(hasTouch) {
156
355
  $document
157
- .off('touchstart' + eventNamespace)
158
- .off('touchmove' + eventNamespace)
356
+ .off('touchstart' + elementNamespace)
357
+ .off('touchmove' + elementNamespace)
159
358
  ;
160
359
  }
161
360
  $document
162
- .off('click' + eventNamespace)
361
+ .off('click' + elementNamespace)
163
362
  ;
164
363
  }
165
364
  },
166
365
 
167
- handleKeyboard: function(event) {
366
+ filter: function(searchTerm) {
168
367
  var
169
- $selectedItem = $item.filter('.' + className.selected),
170
- pressedKey = event.which,
171
- keys = {
172
- enter : 13,
173
- escape : 27,
174
- upArrow : 38,
175
- downArrow : 40
176
- },
177
- selectedClass = className.selected,
178
- currentIndex = $item.index( $selectedItem ),
179
- hasSelectedItem = ($selectedItem.size() > 0),
180
- resultSize = $item.size(),
181
- newIndex
368
+ $results = $(),
369
+ exactRegExp = new RegExp('^' + searchTerm, 'igm'),
370
+ fullTextRegExp = new RegExp(searchTerm, 'ig'),
371
+ allItemsFiltered
372
+ ;
373
+ module.verbose('Searching for matching values');
374
+ $item
375
+ .each(function(){
376
+ var
377
+ $choice = $(this),
378
+ text = module.get.choiceText($choice, false),
379
+ value = module.get.choiceValue($choice, text)
380
+ ;
381
+ if( text.match(exactRegExp) || value.match(exactRegExp) ) {
382
+ $results = $results.add($choice);
383
+ }
384
+ else if(settings.fullTextSearch) {
385
+ if( text.match(fullTextRegExp) || value.match(fullTextRegExp) ) {
386
+ $results = $results.add($choice);
387
+ }
388
+ }
389
+ })
182
390
  ;
183
- // close shortcuts
184
- if(pressedKey == keys.escape) {
185
- module.verbose('Escape key pressed, closing dropdown');
391
+
392
+ module.debug('Setting filter', searchTerm);
393
+ module.remove.filteredItem();
394
+ $item
395
+ .not($results)
396
+ .addClass(className.filtered)
397
+ ;
398
+
399
+ module.verbose('Selecting first non-filtered element');
400
+ module.remove.selectedItem();
401
+ $item
402
+ .not('.' + className.filtered)
403
+ .eq(0)
404
+ .addClass(className.selected)
405
+ ;
406
+ if( module.is.allFiltered() ) {
407
+ module.debug('All items filtered, hiding dropdown', searchTerm);
186
408
  module.hide();
409
+ $.proxy(settings.onNoResults, element)(searchTerm);
187
410
  }
188
- // result shortcuts
189
- if(module.is.visible()) {
190
- if(pressedKey == keys.enter && hasSelectedItem) {
191
- module.verbose('Enter key pressed, choosing selected item');
192
- $.proxy(module.event.item.click, $item.filter('.' + selectedClass) )(event);
193
- event.preventDefault();
194
- return false;
411
+ },
412
+
413
+ focusSearch: function() {
414
+ if( module.is.search() ) {
415
+ $search
416
+ .focus()
417
+ ;
418
+ }
419
+ },
420
+
421
+ event: {
422
+ // prevents focus callback from occuring on mousedown
423
+ mousedown: function() {
424
+ activated = true;
425
+ },
426
+ mouseup: function() {
427
+ activated = false;
428
+ },
429
+ focus: function() {
430
+ if(!activated && module.is.hidden()) {
431
+ module.show();
195
432
  }
196
- else if(pressedKey == keys.upArrow) {
197
- module.verbose('Up key pressed, changing active item');
198
- newIndex = (currentIndex - 1 < 0)
199
- ? currentIndex
200
- : currentIndex - 1
201
- ;
202
- $item
203
- .removeClass(selectedClass)
204
- .eq(newIndex)
205
- .addClass(selectedClass)
206
- ;
207
- event.preventDefault();
433
+ },
434
+ blur: function(event) {
435
+ var
436
+ pageLostFocus = (document.activeElement === this)
437
+ ;
438
+ if(!activated && !pageLostFocus) {
439
+ module.hide();
208
440
  }
209
- else if(pressedKey == keys.downArrow) {
210
- module.verbose('Down key pressed, changing active item');
211
- newIndex = (currentIndex + 1 >= resultSize)
212
- ? currentIndex
213
- : currentIndex + 1
214
- ;
215
- $item
216
- .removeClass(selectedClass)
217
- .eq(newIndex)
218
- .addClass(selectedClass)
219
- ;
220
- event.preventDefault();
441
+ },
442
+ searchFocus: function() {
443
+ activated = true;
444
+ module.show();
445
+ },
446
+ searchBlur: function(event) {
447
+ var
448
+ pageLostFocus = (document.activeElement === this)
449
+ ;
450
+ if(!itemActivated && !pageLostFocus) {
451
+ module.hide();
221
452
  }
222
- }
223
- else {
224
- if(pressedKey == keys.enter) {
453
+ },
454
+ input: function(event) {
455
+ module.set.filtered();
456
+ clearTimeout(module.timer);
457
+ module.timer = setTimeout(module.search, settings.delay.search);
458
+ },
459
+ keydown: function(event) {
460
+ var
461
+ $selectedItem = $item.not(className.filtered).filter('.' + className.selected).eq(0),
462
+ $visibleItems = $item.not('.' + className.filtered),
463
+ pressedKey = event.which,
464
+ keys = {
465
+ enter : 13,
466
+ escape : 27,
467
+ upArrow : 38,
468
+ downArrow : 40
469
+ },
470
+ selectedClass = className.selected,
471
+ currentIndex = $visibleItems.index( $selectedItem ),
472
+ hasSelectedItem = ($selectedItem.size() > 0),
473
+ $nextItem,
474
+ newIndex
475
+ ;
476
+ // default to activated choice if no selection present
477
+ if(!hasSelectedItem) {
478
+ $selectedItem = $item.filter('.' + className.active).eq(0);
479
+ hasSelectedItem = ($selectedItem.size() > 0);
480
+ }
481
+ // close shortcuts
482
+ if(pressedKey == keys.escape) {
483
+ module.verbose('Escape key pressed, closing dropdown');
484
+ module.hide();
485
+ }
486
+ // open menu
487
+ if(pressedKey == keys.downArrow) {
488
+ module.verbose('Down key pressed, showing dropdown');
225
489
  module.show();
226
490
  }
227
- }
228
- },
229
-
230
- event: {
491
+ // result shortcuts
492
+ if(module.is.visible()) {
493
+ if(pressedKey == keys.enter && hasSelectedItem) {
494
+ module.verbose('Enter key pressed, choosing selected item');
495
+ $.proxy(module.event.item.click, $selectedItem)(event);
496
+ event.preventDefault();
497
+ return false;
498
+ }
499
+ else if(pressedKey == keys.upArrow) {
500
+ if(!hasSelectedItem) {
501
+ $nextItem = $visibleItems.eq(0);
502
+ }
503
+ else {
504
+ $nextItem = $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0);
505
+ }
506
+ if(currentIndex !== 0) {
507
+ module.verbose('Up key pressed, changing active item');
508
+ $item
509
+ .removeClass(selectedClass)
510
+ ;
511
+ $nextItem
512
+ .addClass(selectedClass)
513
+ ;
514
+ module.set.scrollPosition($nextItem);
515
+ }
516
+ event.preventDefault();
517
+ }
518
+ else if(pressedKey == keys.downArrow) {
519
+ if(!hasSelectedItem) {
520
+ $nextItem = $visibleItems.eq(0);
521
+ }
522
+ else {
523
+ $nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0);
524
+ }
525
+ if(currentIndex + 1 < $visibleItems.size() ) {
526
+ module.verbose('Down key pressed, changing active item');
527
+ $item
528
+ .removeClass(selectedClass)
529
+ ;
530
+ $nextItem
531
+ .addClass(selectedClass)
532
+ ;
533
+ module.set.scrollPosition($nextItem);
534
+ }
535
+ event.preventDefault();
536
+ }
537
+ }
538
+ else {
539
+ if(pressedKey == keys.enter) {
540
+ module.show();
541
+ }
542
+ }
543
+ },
231
544
  test: {
232
545
  toggle: function(event) {
233
- if( module.determine.intent(event, module.toggle) ) {
546
+ if( module.determine.eventInMenu(event, module.toggle) ) {
234
547
  event.preventDefault();
235
548
  }
236
549
  },
237
550
  touch: function(event) {
238
- module.determine.intent(event, function() {
551
+ module.determine.eventInMenu(event, function() {
239
552
  if(event.type == 'touchstart') {
240
553
  module.timer = setTimeout(module.hide, settings.delay.touch);
241
554
  }
@@ -246,36 +559,40 @@ $.fn.dropdown = function(parameters) {
246
559
  event.stopPropagation();
247
560
  },
248
561
  hide: function(event) {
249
- module.determine.intent(event, module.hide);
562
+ module.determine.eventInModule(event, module.hide);
250
563
  }
251
564
  },
252
565
 
566
+ menu: {
567
+ activate: function() {
568
+ itemActivated = true;
569
+ },
570
+ deactivate: function() {
571
+ itemActivated = false;
572
+ }
573
+ },
253
574
  item: {
254
-
255
575
  mouseenter: function(event) {
256
576
  var
257
- $currentMenu = $(this).find(selector.submenu),
577
+ $currentMenu = $(this).children(selector.menu),
258
578
  $otherMenus = $(this).siblings(selector.item).children(selector.menu)
259
579
  ;
260
- if($currentMenu.length > 0 || $otherMenus.length > 0) {
580
+ if( $currentMenu.size() > 0 ) {
261
581
  clearTimeout(module.itemTimer);
262
- module.itemTimer = setTimeout(function() {
263
- if($otherMenus.length > 0) {
264
- module.animate.hide(false, $otherMenus.filter(':visible'));
265
- }
266
- if($currentMenu.length > 0) {
267
- module.verbose('Showing sub-menu', $currentMenu);
268
- module.animate.show(false, $currentMenu);
269
- }
270
- }, settings.delay.show * 2);
582
+ module.itemTimer = setTimeout(function() {
583
+ $.each($otherMenus, function() {
584
+ module.animate.hide(false, $(this));
585
+ });
586
+ module.verbose('Showing sub-menu', $currentMenu);
587
+ module.animate.show(false, $currentMenu);
588
+ }, settings.delay.show);
271
589
  event.preventDefault();
272
- event.stopPropagation();
273
590
  }
274
591
  },
275
592
 
276
593
  mouseleave: function(event) {
277
594
  var
278
- $currentMenu = $(this).find(selector.menu)
595
+ $currentMenu = $(this).children(selector.menu)
279
596
  ;
280
597
  if($currentMenu.size() > 0) {
281
598
  clearTimeout(module.itemTimer);
@@ -288,27 +605,23 @@ $.fn.dropdown = function(parameters) {
288
605
 
289
606
  click: function (event) {
290
607
  var
291
- $choice = $(this),
292
- text = ( $choice.data(metadata.text) !== undefined )
293
- ? $choice.data(metadata.text)
294
- : $choice.text(),
295
- value = ( $choice.data(metadata.value) !== undefined)
296
- ? $choice.data(metadata.value)
297
- : (typeof text === 'string')
298
- ? text.toLowerCase()
299
- : text,
608
+ $choice = $(this),
609
+ $target = $(event.target),
610
+ $subMenu = $choice.find(selector.menu),
611
+ text = module.get.choiceText($choice),
612
+ value = module.get.choiceValue($choice, text),
300
613
  callback = function() {
614
+ module.remove.searchTerm();
301
615
  module.determine.selectAction(text, value);
302
- $.proxy(settings.onChange, element)(value, text);
303
- }
616
+ },
617
+ openingSubMenu = ($subMenu.size() > 0),
618
+ isSubItem = ($subMenu.find($target).size() > 0)
304
619
  ;
305
- if( $choice.find(selector.menu).size() === 0 ) {
306
- if(event.type == 'touchstart') {
307
- $choice.one('click', callback);
308
- }
309
- else {
310
- callback();
311
- }
620
+ if(isSubItem) {
621
+ return false;
622
+ }
623
+ if(!openingSubMenu || settings.allowCategorySelection) {
624
+ callback();
312
625
  }
313
626
  }
314
627
 
@@ -335,10 +648,12 @@ $.fn.dropdown = function(parameters) {
335
648
  module.error(error.action, settings.action);
336
649
  }
337
650
  },
338
- intent: function(event, callback) {
339
- module.debug('Determining whether event occurred in dropdown', event.target);
340
- callback = callback || function(){};
341
- if( $(event.target).closest($menu).size() === 0 ) {
651
+ eventInModule: function(event, callback) {
652
+ callback = $.isFunction(callback)
653
+ ? callback
654
+ : function(){}
655
+ ;
656
+ if( $(event.target).closest($module).size() === 0 ) {
342
657
  module.verbose('Triggering event', callback);
343
658
  callback();
344
659
  return true;
@@ -347,6 +662,21 @@ $.fn.dropdown = function(parameters) {
347
662
  module.verbose('Event occurred in dropdown, canceling callback');
348
663
  return false;
349
664
  }
665
+ },
666
+ eventInMenu: function(event, callback) {
667
+ callback = $.isFunction(callback)
668
+ ? callback
669
+ : function(){}
670
+ ;
671
+ if( $(event.target).closest($menu).size() === 0 ) {
672
+ module.verbose('Triggering event', callback);
673
+ callback();
674
+ return true;
675
+ }
676
+ else {
677
+ module.verbose('Event occurred in dropdown menu, canceling callback');
678
+ return false;
679
+ }
350
680
  }
351
681
  },
352
682
 
@@ -355,49 +685,45 @@ $.fn.dropdown = function(parameters) {
355
685
  nothing: function() {},
356
686
 
357
687
  hide: function() {
358
- module.hide();
688
+ module.hide(function() {
689
+ module.remove.filteredItem();
690
+ });
359
691
  },
360
692
 
361
- activate: function(text, value) {
693
+ select: function(text, value) {
362
694
  value = (value !== undefined)
363
695
  ? value
364
696
  : text
365
697
  ;
366
698
  module.set.selected(value);
367
699
  module.set.value(value);
368
- module.hide();
700
+ module.hide(function() {
701
+ module.remove.filteredItem();
702
+ });
369
703
  },
370
704
 
371
- /* Deprecated */
372
- auto: function(text, value) {
705
+ activate: function(text, value) {
373
706
  value = (value !== undefined)
374
707
  ? value
375
708
  : text
376
709
  ;
377
710
  module.set.selected(value);
378
711
  module.set.value(value);
379
- module.hide();
380
- },
381
-
382
- /* Deprecated */
383
- changeText: function(text, value) {
384
- value = (value !== undefined)
385
- ? value
386
- : text
387
- ;
388
- module.set.selected(value);
389
- module.hide();
712
+ module.hide(function() {
713
+ module.remove.filteredItem();
714
+ });
390
715
  },
391
716
 
392
- /* Deprecated */
393
- updateForm: function(text, value) {
717
+ combo: function(text, value) {
394
718
  value = (value !== undefined)
395
719
  ? value
396
720
  : text
397
721
  ;
398
722
  module.set.selected(value);
399
723
  module.set.value(value);
400
- module.hide();
724
+ module.hide(function() {
725
+ module.remove.filteredItem();
726
+ });
401
727
  }
402
728
 
403
729
  },
@@ -412,6 +738,96 @@ $.fn.dropdown = function(parameters) {
412
738
  : $module.data(metadata.value)
413
739
  ;
414
740
  },
741
+ choiceText: function($choice, preserveHTML) {
742
+ preserveHTML = (preserveHTML !== undefined)
743
+ ? preserveHTML
744
+ : settings.preserveHTML
745
+ ;
746
+ if($choice !== undefined) {
747
+ if($choice.find(selector.menu).size() > 0) {
748
+ module.verbose('Retreiving text of element with sub-menu');
749
+ $choice = $choice.clone();
750
+ $choice.find(selector.menu).remove();
751
+ $choice.find(selector.menuIcon).remove();
752
+ }
753
+ return ($choice.data(metadata.text) !== undefined)
754
+ ? $choice.data(metadata.text)
755
+ : (preserveHTML)
756
+ ? $choice.html()
757
+ : $choice.text()
758
+ ;
759
+ }
760
+ },
761
+ choiceValue: function($choice, choiceText) {
762
+ choiceText = choiceText || module.get.choiceText($text);
763
+ return ($choice.data(metadata.value) !== undefined)
764
+ ? $choice.data(metadata.value)
765
+ : (typeof choiceText === 'string')
766
+ ? choiceText.toLowerCase()
767
+ : choiceText
768
+ ;
769
+ },
770
+ inputEvent: function() {
771
+ var
772
+ input = $search[0]
773
+ ;
774
+ if(input) {
775
+ return (input.oninput !== undefined)
776
+ ? 'input'
777
+ : (input.onpropertychange !== undefined)
778
+ ? 'propertychange'
779
+ : 'keyup'
780
+ ;
781
+ }
782
+ return false;
783
+ },
784
+ selectValues: function() {
785
+ var
786
+ select = {}
787
+ ;
788
+ select.values = (settings.sortSelect)
789
+ ? {} // properties will be sorted in object when re-accessed
790
+ : [] // properties will keep original order in array
791
+ ;
792
+ $module
793
+ .find('option')
794
+ .each(function() {
795
+ var
796
+ name = $(this).html(),
797
+ value = ( $(this).attr('value') !== undefined )
798
+ ? $(this).attr('value')
799
+ : name
800
+ ;
801
+ if(value === '') {
802
+ select.placeholder = name;
803
+ }
804
+ else {
805
+ if(settings.sortSelect) {
806
+ select.values[value] = {
807
+ name : name,
808
+ value : value
809
+ };
810
+ }
811
+ else {
812
+ select.values.push({
813
+ name: name,
814
+ value: value
815
+ });
816
+ }
817
+ }
818
+ })
819
+ ;
820
+ if(settings.sortSelect) {
821
+ module.debug('Retrieved and sorted values from select', select);
822
+ }
823
+ else {
824
+ module.debug('Retreived values from select', select);
825
+ }
826
+ return select;
827
+ },
828
+ activeItem: function() {
829
+ return $item.filter('.' + className.active);
830
+ },
415
831
  item: function(value, strict) {
416
832
  var
417
833
  $selectedItem = false
@@ -422,28 +838,20 @@ $.fn.dropdown = function(parameters) {
422
838
  ? module.get.value()
423
839
  : module.get.text()
424
840
  ;
425
- if(strict === undefined && value === '') {
426
- module.debug('Ambiguous dropdown value using strict type check', value);
427
- strict = true;
428
- }
429
- else {
430
- strict = strict || false;
431
- }
841
+ strict = (value === '' || value === 0)
842
+ ? true
843
+ : strict || false
844
+ ;
432
845
  if(value !== undefined) {
433
846
  $item
434
847
  .each(function() {
435
848
  var
436
849
  $choice = $(this),
437
- optionText = ( $choice.data(metadata.text) !== undefined )
438
- ? $choice.data(metadata.text)
439
- : $choice.text(),
440
- optionValue = ( $choice.data(metadata.value) !== undefined )
441
- ? $choice.data(metadata.value)
442
- : (typeof optionText === 'string')
443
- ? optionText.toLowerCase()
444
- : optionText
850
+ optionText = module.get.choiceText($choice),
851
+ optionValue = module.get.choiceValue($choice, optionText)
445
852
  ;
446
853
  if(strict) {
854
+ module.verbose('Ambiguous dropdown value using strict type check', $choice, value);
447
855
  if( optionValue === value ) {
448
856
  $selectedItem = $(this);
449
857
  }
@@ -453,9 +861,11 @@ $.fn.dropdown = function(parameters) {
453
861
  }
454
862
  else {
455
863
  if( optionValue == value ) {
864
+ module.verbose('Found select item by value', optionValue, value);
456
865
  $selectedItem = $(this);
457
866
  }
458
867
  else if( !$selectedItem && optionText == value ) {
868
+ module.verbose('Found select item by text', optionText, value);
459
869
  $selectedItem = $(this);
460
870
  }
461
871
  }
@@ -466,6 +876,9 @@ $.fn.dropdown = function(parameters) {
466
876
  value = module.get.text();
467
877
  }
468
878
  return $selectedItem || false;
879
+ },
880
+ uniqueID: function() {
881
+ return (Math.random().toString(16) + '000000000').substr(2,8);
469
882
  }
470
883
  },
471
884
 
@@ -507,10 +920,108 @@ $.fn.dropdown = function(parameters) {
507
920
  },
508
921
 
509
922
  set: {
923
+ filtered: function() {
924
+ var
925
+ searchValue = $search.val(),
926
+ hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0)
927
+ ;
928
+ if(hasSearchValue) {
929
+ $text.addClass(className.filtered);
930
+ }
931
+ else {
932
+ $text.removeClass(className.filtered);
933
+ }
934
+ },
935
+ tabbable: function() {
936
+ if( module.is.searchable() ) {
937
+ module.debug('Searchable dropdown initialized');
938
+ $search
939
+ .val('')
940
+ .attr('tabindex', 0)
941
+ ;
942
+ $menu
943
+ .attr('tabindex', '-1')
944
+ ;
945
+ }
946
+ else {
947
+ module.debug('Simple selection dropdown initialized');
948
+ if(!$module.attr('tabindex') ) {
949
+ $module
950
+ .attr('tabindex', 0)
951
+ ;
952
+ $menu
953
+ .attr('tabindex', '-1')
954
+ ;
955
+ }
956
+ }
957
+ },
958
+ scrollPosition: function($item, forceScroll) {
959
+ var
960
+ edgeTolerance = 5,
961
+ hasActive,
962
+ offset,
963
+ itemHeight,
964
+ itemOffset,
965
+ menuOffset,
966
+ menuScroll,
967
+ menuHeight,
968
+ abovePage,
969
+ belowPage
970
+ ;
971
+
972
+ $item = $item || module.get.activeItem();
973
+ hasActive = ($item && $item.size() > 0);
974
+ forceScroll = (forceScroll !== undefined)
975
+ ? forceScroll
976
+ : false
977
+ ;
978
+
979
+ if($item && hasActive) {
980
+
981
+ if(!$menu.hasClass(className.visible)) {
982
+ $menu.addClass(className.loading);
983
+ }
984
+
985
+ menuHeight = $menu.height();
986
+ itemHeight = $item.height();
987
+ menuScroll = $menu.scrollTop();
988
+ menuOffset = $menu.offset().top;
989
+ itemOffset = $item.offset().top;
990
+ offset = menuScroll - menuOffset + itemOffset;
991
+ belowPage = menuScroll + menuHeight < (offset + edgeTolerance);
992
+ abovePage = ((offset - edgeTolerance) < menuScroll);
993
+ module.debug('Scrolling to active item', offset);
994
+ if(abovePage || belowPage || forceScroll) {
995
+ $menu
996
+ .scrollTop(offset)
997
+ .removeClass(className.loading)
998
+ ;
999
+ }
1000
+ }
1001
+ },
510
1002
  text: function(text) {
511
- module.debug('Changing text', text, $text);
512
- $text.removeClass(className.placeholder);
513
- $text.text(text);
1003
+ if(settings.action == 'combo') {
1004
+ module.debug('Changing combo button text', text, $combo);
1005
+ if(settings.preserveHTML) {
1006
+ $combo.html(text);
1007
+ }
1008
+ else {
1009
+ $combo.text(text);
1010
+ }
1011
+ }
1012
+ else if(settings.action !== 'select') {
1013
+ module.debug('Changing text', text, $text);
1014
+ $text
1015
+ .removeClass(className.filtered)
1016
+ .removeClass(className.placeholder)
1017
+ ;
1018
+ if(settings.preserveHTML) {
1019
+ $text.html(text);
1020
+ }
1021
+ else {
1022
+ $text.text(text);
1023
+ }
1024
+ }
514
1025
  },
515
1026
  value: function(value) {
516
1027
  module.debug('Adding selected value to hidden input', value, $input);
@@ -525,7 +1036,9 @@ $.fn.dropdown = function(parameters) {
525
1036
  }
526
1037
  },
527
1038
  active: function() {
528
- $module.addClass(className.active);
1039
+ $module
1040
+ .addClass(className.active)
1041
+ ;
529
1042
  },
530
1043
  visible: function() {
531
1044
  $module.addClass(className.visible);
@@ -537,17 +1050,17 @@ $.fn.dropdown = function(parameters) {
537
1050
  ;
538
1051
  if($selectedItem) {
539
1052
  module.debug('Setting selected menu item to', $selectedItem);
540
- selectedText = ($selectedItem.data(metadata.text) !== undefined)
541
- ? $selectedItem.data(metadata.text)
542
- : $selectedItem.text()
543
- ;
544
- $item
545
- .removeClass(className.active)
546
- ;
1053
+
1054
+ module.remove.activeItem();
1055
+ module.remove.selectedItem();
547
1056
  $selectedItem
548
1057
  .addClass(className.active)
1058
+ .addClass(className.selected)
549
1059
  ;
1060
+
1061
+ selectedText = module.get.choiceText($selectedItem);
550
1062
  module.set.text(selectedText);
1063
+ $.proxy(settings.onChange, element)(value, selectedText, $selectedItem);
551
1064
  }
552
1065
  }
553
1066
  },
@@ -558,29 +1071,76 @@ $.fn.dropdown = function(parameters) {
558
1071
  },
559
1072
  visible: function() {
560
1073
  $module.removeClass(className.visible);
1074
+ },
1075
+ activeItem: function() {
1076
+ $item.removeClass(className.active);
1077
+ },
1078
+ filteredItem: function() {
1079
+ $item.removeClass(className.filtered);
1080
+ },
1081
+ searchTerm: function() {
1082
+ $search.val('');
1083
+ },
1084
+ selectedItem: function() {
1085
+ $item.removeClass(className.selected);
1086
+ },
1087
+ tabbable: function() {
1088
+ if( module.is.searchable() ) {
1089
+ module.debug('Searchable dropdown initialized');
1090
+ $search
1091
+ .attr('tabindex', '-1')
1092
+ ;
1093
+ $menu
1094
+ .attr('tabindex', '-1')
1095
+ ;
1096
+ }
1097
+ else {
1098
+ module.debug('Simple selection dropdown initialized');
1099
+ $module
1100
+ .attr('tabindex', '-1')
1101
+ ;
1102
+ $menu
1103
+ .attr('tabindex', '-1')
1104
+ ;
1105
+ }
561
1106
  }
562
1107
  },
563
1108
 
564
1109
  is: {
565
- selection: function() {
566
- return $module.hasClass(className.selection);
1110
+ active: function() {
1111
+ return $module.hasClass(className.active);
567
1112
  },
568
- animated: function($subMenu) {
1113
+ animating: function($subMenu) {
569
1114
  return ($subMenu)
570
1115
  ? $subMenu.is(':animated') || $subMenu.transition && $subMenu.transition('is animating')
571
1116
  : $menu.is(':animated') || $menu.transition && $menu.transition('is animating')
572
1117
  ;
573
1118
  },
574
- visible: function($subMenu) {
1119
+ allFiltered: function() {
1120
+ return ($item.filter('.' + className.filtered).size() === $item.size());
1121
+ },
1122
+ hidden: function($subMenu) {
575
1123
  return ($subMenu)
576
- ? $subMenu.is(':visible')
577
- : $menu.is(':visible')
1124
+ ? $subMenu.is(':hidden')
1125
+ : $menu.is(':hidden')
578
1126
  ;
579
1127
  },
580
- hidden: function($subMenu) {
1128
+ search: function() {
1129
+ return $module.hasClass(className.search);
1130
+ },
1131
+ searchable: function() {
1132
+ return ($search.size() > 0);
1133
+ },
1134
+ searchSelection: function() {
1135
+ return ( module.is.searchable() && $search.parent().is($module) );
1136
+ },
1137
+ selection: function() {
1138
+ return $module.hasClass(className.selection);
1139
+ },
1140
+ visible: function($subMenu) {
581
1141
  return ($subMenu)
582
- ? $subMenu.is(':not(:visible)')
583
- : $menu.is(':not(:visible)')
1142
+ ? $subMenu.is(':visible')
1143
+ : $menu.is(':visible')
584
1144
  ;
585
1145
  }
586
1146
  },
@@ -597,25 +1157,42 @@ $.fn.dropdown = function(parameters) {
597
1157
  animate: {
598
1158
  show: function(callback, $subMenu) {
599
1159
  var
600
- $currentMenu = $subMenu || $menu
1160
+ $currentMenu = $subMenu || $menu,
1161
+ start = ($subMenu)
1162
+ ? function() {}
1163
+ : function() {
1164
+ module.hideSubMenus();
1165
+ module.hideOthers();
1166
+ module.set.active();
1167
+ }
1168
+ ;
1169
+ callback = $.isFunction(callback)
1170
+ ? callback
1171
+ : function(){}
601
1172
  ;
602
- callback = callback || function(){};
603
- if( module.is.hidden($currentMenu) ) {
604
- module.verbose('Doing menu show animation', $currentMenu);
1173
+ module.set.scrollPosition(module.get.activeItem(), true);
1174
+ module.verbose('Doing menu show animation', $currentMenu);
1175
+ if( module.is.hidden($currentMenu) || module.is.animating($currentMenu) ) {
605
1176
  if(settings.transition == 'none') {
606
- callback();
1177
+ $.proxy(callback, element)();
607
1178
  }
608
1179
  else if($.fn.transition !== undefined && $module.transition('is supported')) {
609
1180
  $currentMenu
610
1181
  .transition({
611
- animation : settings.transition + ' in',
612
- duration : settings.duration,
613
- complete : callback,
614
- queue : false
1182
+ animation : settings.transition + ' in',
1183
+ debug : settings.debug,
1184
+ verbose : settings.verbose,
1185
+ duration : settings.duration,
1186
+ queue : true,
1187
+ onStart : start,
1188
+ onComplete : function() {
1189
+ $.proxy(callback, element)();
1190
+ }
615
1191
  })
616
1192
  ;
617
1193
  }
618
1194
  else if(settings.transition == 'slide down') {
1195
+ start();
619
1196
  $currentMenu
620
1197
  .hide()
621
1198
  .clearQueue()
@@ -629,17 +1206,18 @@ $.fn.dropdown = function(parameters) {
629
1206
  .end()
630
1207
  .slideDown(100, 'easeOutQuad', function() {
631
1208
  $.proxy(module.event.resetStyle, this)();
632
- callback();
1209
+ $.proxy(callback, element)();
633
1210
  })
634
1211
  ;
635
1212
  }
636
1213
  else if(settings.transition == 'fade') {
1214
+ start();
637
1215
  $currentMenu
638
1216
  .hide()
639
1217
  .clearQueue()
640
1218
  .fadeIn(settings.duration, function() {
641
1219
  $.proxy(module.event.resetStyle, this)();
642
- callback();
1220
+ $.proxy(callback, element)();
643
1221
  })
644
1222
  ;
645
1223
  }
@@ -650,25 +1228,47 @@ $.fn.dropdown = function(parameters) {
650
1228
  },
651
1229
  hide: function(callback, $subMenu) {
652
1230
  var
653
- $currentMenu = $subMenu || $menu
1231
+ $currentMenu = $subMenu || $menu,
1232
+ duration = ($subMenu)
1233
+ ? (settings.duration * 0.9)
1234
+ : settings.duration,
1235
+ start = ($subMenu)
1236
+ ? function() {}
1237
+ : function() {
1238
+ if( module.can.click() ) {
1239
+ module.unbind.intent();
1240
+ }
1241
+ module.focusSearch();
1242
+ module.remove.active();
1243
+ }
654
1244
  ;
655
- callback = callback || function(){};
656
- if(module.is.visible($currentMenu) ) {
1245
+ callback = $.isFunction(callback)
1246
+ ? callback
1247
+ : function(){}
1248
+ ;
1249
+ if( module.is.visible($currentMenu) || module.is.animating($currentMenu) ) {
657
1250
  module.verbose('Doing menu hide animation', $currentMenu);
658
- if($.fn.transition !== undefined && $module.transition('is supported')) {
1251
+
1252
+ if(settings.transition == 'none') {
1253
+ $.proxy(callback, element)();
1254
+ }
1255
+ else if($.fn.transition !== undefined && $module.transition('is supported')) {
659
1256
  $currentMenu
660
1257
  .transition({
661
- animation : settings.transition + ' out',
662
- duration : settings.duration,
663
- complete : callback,
664
- queue : false
1258
+ animation : settings.transition + ' out',
1259
+ duration : settings.duration,
1260
+ debug : settings.debug,
1261
+ verbose : settings.verbose,
1262
+ queue : true,
1263
+ onStart : start,
1264
+ onComplete : function() {
1265
+ $.proxy(callback, element)();
1266
+ }
665
1267
  })
666
1268
  ;
667
1269
  }
668
- else if(settings.transition == 'none') {
669
- callback();
670
- }
671
1270
  else if(settings.transition == 'slide down') {
1271
+ start();
672
1272
  $currentMenu
673
1273
  .show()
674
1274
  .clearQueue()
@@ -682,17 +1282,18 @@ $.fn.dropdown = function(parameters) {
682
1282
  .delay(50)
683
1283
  .slideUp(100, 'easeOutQuad', function() {
684
1284
  $.proxy(module.event.resetStyle, this)();
685
- callback();
1285
+ $.proxy(callback, element)();
686
1286
  })
687
1287
  ;
688
1288
  }
689
1289
  else if(settings.transition == 'fade') {
1290
+ start();
690
1291
  $currentMenu
691
1292
  .show()
692
1293
  .clearQueue()
693
1294
  .fadeOut(150, function() {
694
1295
  $.proxy(module.event.resetStyle, this)();
695
- callback();
1296
+ $.proxy(callback, element)();
696
1297
  })
697
1298
  ;
698
1299
  }
@@ -703,33 +1304,6 @@ $.fn.dropdown = function(parameters) {
703
1304
  }
704
1305
  },
705
1306
 
706
- show: function() {
707
- module.debug('Checking if dropdown can show');
708
- if( module.is.hidden() ) {
709
- module.hideOthers();
710
- module.set.active();
711
- module.animate.show(function() {
712
- if( module.can.click() ) {
713
- module.bind.intent();
714
- }
715
- module.set.visible();
716
- });
717
- $.proxy(settings.onShow, element)();
718
- }
719
- },
720
-
721
- hide: function() {
722
- if( !module.is.animated() && module.is.visible() ) {
723
- module.debug('Hiding dropdown');
724
- if( module.can.click() ) {
725
- module.unbind.intent();
726
- }
727
- module.remove.active();
728
- module.animate.hide(module.remove.visible);
729
- $.proxy(settings.onHide, element)();
730
- }
731
- },
732
-
733
1307
  delay: {
734
1308
  show: function() {
735
1309
  module.verbose('Delaying show event to ensure user intent');
@@ -743,26 +1317,8 @@ $.fn.dropdown = function(parameters) {
743
1317
  }
744
1318
  },
745
1319
 
746
- hideOthers: function() {
747
- module.verbose('Finding other dropdowns to hide');
748
- $allModules
749
- .not($module)
750
- .has(selector.menu + ':visible')
751
- .dropdown('hide')
752
- ;
753
- },
754
-
755
- toggle: function() {
756
- module.verbose('Toggling menu visibility');
757
- if( module.is.hidden() ) {
758
- module.show();
759
- }
760
- else {
761
- module.hide();
762
- }
763
- },
764
-
765
1320
  setting: function(name, value) {
1321
+ module.debug('Changing setting', name, value);
766
1322
  if( $.isPlainObject(name) ) {
767
1323
  $.extend(true, settings, name);
768
1324
  }
@@ -823,9 +1379,9 @@ $.fn.dropdown = function(parameters) {
823
1379
  executionTime = currentTime - previousTime;
824
1380
  time = currentTime;
825
1381
  performance.push({
826
- 'Element' : element,
827
1382
  'Name' : message[0],
828
1383
  'Arguments' : [].slice.call(message, 1) || '',
1384
+ 'Element' : element,
829
1385
  'Execution Time' : executionTime
830
1386
  });
831
1387
  }
@@ -940,32 +1496,44 @@ $.fn.dropdown = function(parameters) {
940
1496
 
941
1497
  $.fn.dropdown.settings = {
942
1498
 
943
- name : 'Dropdown',
944
- namespace : 'dropdown',
1499
+ debug : false,
1500
+ verbose : true,
1501
+ performance : true,
1502
+
1503
+ on : 'click',
1504
+ action : 'activate',
945
1505
 
946
- debug : false,
947
- verbose : true,
948
- performance : true,
1506
+ allowTab : true,
1507
+ fullTextSearch : false,
1508
+ preserveHTML : true,
1509
+ sortSelect : false,
949
1510
 
950
- on : 'click',
951
- action : 'activate',
1511
+ allowCategorySelection : false,
952
1512
 
953
- delay: {
954
- show : 200,
955
- hide : 300,
956
- touch : 50
1513
+ delay : {
1514
+ hide : 300,
1515
+ show : 200,
1516
+ search : 50,
1517
+ touch : 50
957
1518
  },
958
1519
 
959
1520
  transition : 'slide down',
960
1521
  duration : 250,
961
1522
 
962
- onChange : function(value, text){},
963
- onShow : function(){},
964
- onHide : function(){},
1523
+ /* Callbacks */
1524
+ onNoResults : function(searchTerm){},
1525
+ onChange : function(value, text){},
1526
+ onShow : function(){},
1527
+ onHide : function(){},
1528
+
1529
+ /* Component */
1530
+
1531
+ name : 'Dropdown',
1532
+ namespace : 'dropdown',
965
1533
 
966
1534
  error : {
967
- action : 'You called a dropdown action that was not defined',
968
- method : 'The method you called is not defined.',
1535
+ action : 'You called a dropdown action that was not defined',
1536
+ method : 'The method you called is not defined.',
969
1537
  transition : 'The requested transition was not found'
970
1538
  },
971
1539
 
@@ -977,30 +1545,74 @@ $.fn.dropdown.settings = {
977
1545
  },
978
1546
 
979
1547
  selector : {
980
- menu : '.menu',
981
- submenu : '> .menu',
982
- item : '.menu > .item',
983
- text : '> .text',
984
- input : '> input[type="hidden"]'
1548
+ dropdown : '.ui.dropdown',
1549
+ input : '> input[type="hidden"], > select',
1550
+ item : '.item',
1551
+ menu : '.menu',
1552
+ menuIcon : '.dropdown.icon',
1553
+ search : '> input.search, .menu > .search > input, .menu > input.search',
1554
+ text : '> .text:not(.icon)'
985
1555
  },
986
1556
 
987
1557
  className : {
988
1558
  active : 'active',
989
- placeholder : 'default',
1559
+ animating : 'animating',
990
1560
  disabled : 'disabled',
991
- visible : 'visible',
1561
+ dropdown : 'ui dropdown',
1562
+ filtered : 'filtered',
1563
+ loading : 'loading',
1564
+ menu : 'menu',
1565
+ placeholder : 'default',
1566
+ search : 'search',
992
1567
  selected : 'selected',
993
- selection : 'selection'
1568
+ selection : 'selection',
1569
+ visible : 'visible'
994
1570
  }
995
1571
 
996
1572
  };
997
1573
 
998
- // Adds easing
1574
+ /* Templates */
1575
+ $.fn.dropdown.settings.templates = {
1576
+ menu: function(select) {
1577
+ var
1578
+ placeholder = select.placeholder || false,
1579
+ values = select.values || {},
1580
+ html = ''
1581
+ ;
1582
+ $.each(select.values, function(index, option) {
1583
+ html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>';
1584
+ });
1585
+ return html;
1586
+ },
1587
+ dropdown: function(select) {
1588
+ var
1589
+ placeholder = select.placeholder || false,
1590
+ values = select.values || {},
1591
+ html = ''
1592
+ ;
1593
+ html += '<i class="dropdown icon"></i>';
1594
+ if(select.placeholder) {
1595
+ html += '<div class="default text">' + placeholder + '</div>';
1596
+ }
1597
+ else {
1598
+ html += '<div class="text"></div>';
1599
+ }
1600
+ html += '<div class="menu">';
1601
+ $.each(select.values, function(index, option) {
1602
+ html += '<div class="item" data-value="' + option.value + '">' + option.name + '</div>';
1603
+ });
1604
+ html += '</div>';
1605
+ return html;
1606
+ }
1607
+ };
1608
+
1609
+
1610
+ /* Dependencies */
999
1611
  $.extend( $.easing, {
1000
1612
  easeOutQuad: function (x, t, b, c, d) {
1001
1613
  return -c *(t/=d)*(t-2) + b;
1002
- }
1614
+ },
1003
1615
  });
1004
1616
 
1005
1617
 
1006
- })( jQuery, window , document );
1618
+ })( jQuery, window , document );