less-rails-semantic_ui 2.2.6.0 → 2.2.9.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 (24) hide show
  1. checksums.yaml +4 -4
  2. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.eot +0 -0
  3. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.svg +2668 -682
  4. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.ttf +0 -0
  5. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.woff +0 -0
  6. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.woff2 +0 -0
  7. data/assets/javascripts/semantic_ui/definitions/behaviors/form.js +64 -19
  8. data/assets/javascripts/semantic_ui/definitions/behaviors/visibility.js +7 -2
  9. data/assets/javascripts/semantic_ui/definitions/modules/dropdown.js +43 -17
  10. data/assets/javascripts/semantic_ui/definitions/modules/search.js +88 -53
  11. data/assets/javascripts/semantic_ui/definitions/modules/tab.js +12 -6
  12. data/assets/stylesheets/semantic_ui/definitions/elements/button.less +1 -1
  13. data/assets/stylesheets/semantic_ui/definitions/elements/header.less +2 -2
  14. data/assets/stylesheets/semantic_ui/definitions/elements/segment.less +7 -0
  15. data/assets/stylesheets/semantic_ui/definitions/modules/dropdown.less +26 -1
  16. data/assets/stylesheets/semantic_ui/definitions/modules/sidebar.less +0 -4
  17. data/assets/stylesheets/semantic_ui/definitions/views/item.less +17 -7
  18. data/assets/stylesheets/semantic_ui/themes/default/elements/flag.overrides +2 -2
  19. data/assets/stylesheets/semantic_ui/themes/default/elements/icon.overrides +54 -4
  20. data/assets/stylesheets/semantic_ui/themes/default/globals/site.variables +8 -8
  21. data/assets/stylesheets/semantic_ui/themes/default/views/comment.variables +0 -6
  22. data/assets/stylesheets/semantic_ui/themes/default/views/item.variables +5 -2
  23. data/lib/less/rails/semantic_ui/version.rb +1 -1
  24. metadata +7 -7
@@ -57,6 +57,7 @@ $.fn.form = function(parameters) {
57
57
  metadata,
58
58
  selector,
59
59
  className,
60
+ regExp,
60
61
  error,
61
62
 
62
63
  namespace,
@@ -233,6 +234,20 @@ $.fn.form = function(parameters) {
233
234
  ;
234
235
  },
235
236
 
237
+ determine: {
238
+ isValid: function() {
239
+ var
240
+ allValid = true
241
+ ;
242
+ $.each(validation, function(fieldName, field) {
243
+ if( !( module.validate.field(field, fieldName, true) ) ) {
244
+ allValid = false;
245
+ }
246
+ });
247
+ return allValid;
248
+ }
249
+ },
250
+
236
251
  is: {
237
252
  bracketedRule: function(rule) {
238
253
  return (rule.type && rule.type.match(settings.regExp.bracket));
@@ -251,17 +266,23 @@ $.fn.form = function(parameters) {
251
266
  blank: function($field) {
252
267
  return $.trim($field.val()) === '';
253
268
  },
254
- valid: function() {
269
+ valid: function(field) {
255
270
  var
256
271
  allValid = true
257
272
  ;
258
- module.verbose('Checking if form is valid');
259
- $.each(validation, function(fieldName, field) {
260
- if( !( module.validate.field(field, fieldName) ) ) {
261
- allValid = false;
262
- }
263
- });
264
- return allValid;
273
+ if(field) {
274
+ module.verbose('Checking if field is valid', field);
275
+ return module.validate.field(validation[field], field, false);
276
+ }
277
+ else {
278
+ module.verbose('Checking if form is valid');
279
+ $.each(validation, function(fieldName, field) {
280
+ if( !module.is.valid(fieldName) ) {
281
+ allValid = false;
282
+ }
283
+ });
284
+ return allValid;
285
+ }
265
286
  }
266
287
  },
267
288
 
@@ -338,7 +359,7 @@ $.fn.form = function(parameters) {
338
359
  $fieldGroup = $field.closest($group),
339
360
  validationRules = module.get.validation($field)
340
361
  ;
341
- if(settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) ) {
362
+ if(validationRules && (settings.on == 'change' || ( $fieldGroup.hasClass(className.error) && settings.revalidate) )) {
342
363
  clearTimeout(module.timer);
343
364
  module.timer = setTimeout(function() {
344
365
  module.debug('Revalidating field', $field, module.get.validation($field));
@@ -465,6 +486,7 @@ $.fn.form = function(parameters) {
465
486
  metadata = settings.metadata;
466
487
  selector = settings.selector;
467
488
  className = settings.className;
489
+ regExp = settings.regExp;
468
490
  error = settings.error;
469
491
  moduleNamespace = 'module-' + namespace;
470
492
  eventNamespace = '.' + namespace;
@@ -477,7 +499,8 @@ $.fn.form = function(parameters) {
477
499
  },
478
500
  field: function(identifier) {
479
501
  module.verbose('Finding field with identifier', identifier);
480
- if( $field.filter('#' + identifier).length > 0 ) {
502
+ identifier = module.escape.string(identifier);
503
+ if($field.filter('#' + identifier).length > 0 ) {
481
504
  return $field.filter('#' + identifier);
482
505
  }
483
506
  else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
@@ -592,10 +615,11 @@ $.fn.form = function(parameters) {
592
615
 
593
616
  field: function(identifier) {
594
617
  module.verbose('Checking for existence of a field with identifier', identifier);
618
+ identifier = module.escape.string(identifier);
595
619
  if(typeof identifier !== 'string') {
596
620
  module.error(error.identifier, identifier);
597
621
  }
598
- if( $field.filter('#' + identifier).length > 0 ) {
622
+ if($field.filter('#' + identifier).length > 0 ) {
599
623
  return true;
600
624
  }
601
625
  else if( $field.filter('[name="' + identifier +'"]').length > 0 ) {
@@ -609,6 +633,13 @@ $.fn.form = function(parameters) {
609
633
 
610
634
  },
611
635
 
636
+ escape: {
637
+ string: function(text) {
638
+ text = String(text);
639
+ return text.replace(regExp.escape, '\\$&');
640
+ }
641
+ },
642
+
612
643
  add: {
613
644
  prompt: function(identifier, errors) {
614
645
  var
@@ -794,7 +825,7 @@ $.fn.form = function(parameters) {
794
825
 
795
826
  // reset errors
796
827
  formErrors = [];
797
- if( module.is.valid() ) {
828
+ if( module.determine.isValid() ) {
798
829
  module.debug('Form has no validation errors, submitting');
799
830
  module.set.success();
800
831
  if(ignoreCallbacks !== true) {
@@ -818,7 +849,16 @@ $.fn.form = function(parameters) {
818
849
  },
819
850
 
820
851
  // takes a validation object and returns whether field passes validation
821
- field: function(field, fieldName) {
852
+ field: function(field, fieldName, showErrors) {
853
+ showErrors = (showErrors !== undefined)
854
+ ? showErrors
855
+ : true
856
+ ;
857
+ if(typeof field == 'string') {
858
+ module.verbose('Validating field', field);
859
+ fieldName = field;
860
+ field = validation[field];
861
+ }
822
862
  var
823
863
  identifier = field.identifier || fieldName,
824
864
  $field = module.get.field(identifier),
@@ -854,13 +894,17 @@ $.fn.form = function(parameters) {
854
894
  });
855
895
  }
856
896
  if(fieldValid) {
857
- module.remove.prompt(identifier, fieldErrors);
858
- settings.onValid.call($field);
897
+ if(showErrors) {
898
+ module.remove.prompt(identifier, fieldErrors);
899
+ settings.onValid.call($field);
900
+ }
859
901
  }
860
902
  else {
861
- formErrors = formErrors.concat(fieldErrors);
862
- module.add.prompt(identifier, fieldErrors);
863
- settings.onInvalid.call($field, fieldErrors);
903
+ if(showErrors) {
904
+ formErrors = formErrors.concat(fieldErrors);
905
+ module.add.prompt(identifier, fieldErrors);
906
+ settings.onInvalid.call($field, fieldErrors);
907
+ }
864
908
  return false;
865
909
  }
866
910
  return true;
@@ -1090,8 +1134,9 @@ $.fn.form.settings = {
1090
1134
  },
1091
1135
 
1092
1136
  regExp: {
1137
+ htmlID : /^[a-zA-Z][\w:.-]*$/g,
1093
1138
  bracket : /\[(.*)\]/i,
1094
- decimal : /^\d*(\.)\d+/,
1139
+ decimal : /^\d+\.?\d*$/,
1095
1140
  email : /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,
1096
1141
  escape : /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
1097
1142
  flags : /^\/(.*)\/(.*)?/,
@@ -387,7 +387,11 @@ $.fn.visibility = function(parameters) {
387
387
  .attr('src', src)
388
388
  ;
389
389
  if(settings.transition) {
390
- if( $.fn.transition !== undefined ) {
390
+ if( $.fn.transition !== undefined) {
391
+ if($module.hasClass(className.visible)) {
392
+ module.debug('Transition already occurred on this image, skipping animation');
393
+ return;
394
+ }
391
395
  $module.transition(settings.transition, settings.duration, callback);
392
396
  }
393
397
  else {
@@ -1270,7 +1274,8 @@ $.fn.visibility.settings = {
1270
1274
 
1271
1275
  className: {
1272
1276
  fixed : 'fixed',
1273
- placeholder : 'placeholder'
1277
+ placeholder : 'placeholder',
1278
+ visible : 'visible'
1274
1279
  },
1275
1280
 
1276
1281
  error : {
@@ -461,6 +461,10 @@ $.fn.dropdown = function(parameters) {
461
461
  ? callback
462
462
  : function(){}
463
463
  ;
464
+ if(!module.can.show() && module.is.remote()) {
465
+ module.debug('No API results retrieved, searching before show');
466
+ module.queryRemote(module.get.query(), module.show);
467
+ }
464
468
  if( module.can.show() && !module.is.active() ) {
465
469
  module.debug('Showing dropdown');
466
470
  if(module.has.message() && !(module.has.maxSelections() || module.has.allResultsFiltered()) ) {
@@ -617,8 +621,17 @@ $.fn.dropdown = function(parameters) {
617
621
  .on('mousedown' + eventNamespace, module.event.mousedown)
618
622
  .on('mouseup' + eventNamespace, module.event.mouseup)
619
623
  .on('focus' + eventNamespace, module.event.focus)
620
- .on('blur' + eventNamespace, module.event.blur)
621
624
  ;
625
+ if(module.has.menuSearch() ) {
626
+ $module
627
+ .on('blur' + eventNamespace, selector.search, module.event.search.blur)
628
+ ;
629
+ }
630
+ else {
631
+ $module
632
+ .on('blur' + eventNamespace, module.event.blur)
633
+ ;
634
+ }
622
635
  }
623
636
  $menu
624
637
  .on('mouseenter' + eventNamespace, selector.item, module.event.item.mouseenter)
@@ -702,6 +715,9 @@ $.fn.dropdown = function(parameters) {
702
715
  if(settings.apiSettings) {
703
716
  if( module.can.useAPI() ) {
704
717
  module.queryRemote(searchTerm, function() {
718
+ if(settings.filterRemoteData) {
719
+ module.filterItems(searchTerm);
720
+ }
705
721
  afterFiltered();
706
722
  });
707
723
  }
@@ -757,7 +773,7 @@ $.fn.dropdown = function(parameters) {
757
773
  ? query
758
774
  : module.get.query(),
759
775
  results = null,
760
- escapedTerm = module.escape.regExp(searchTerm),
776
+ escapedTerm = module.escape.string(searchTerm),
761
777
  beginsWithRegExp = new RegExp('^' + escapedTerm, 'igm')
762
778
  ;
763
779
  // avoid loop if we're matching nothing
@@ -789,12 +805,15 @@ $.fn.dropdown = function(parameters) {
789
805
  }
790
806
  if(settings.match == 'both' || settings.match == 'value') {
791
807
  value = String(module.get.choiceValue($choice, text));
792
-
793
808
  if(value.search(beginsWithRegExp) !== -1) {
794
809
  results.push(this);
795
810
  return true;
796
811
  }
797
- else if(settings.fullTextSearch && module.fuzzySearch(searchTerm, value)) {
812
+ else if (settings.fullTextSearch === 'exact' && module.exactSearch(searchTerm, value)) {
813
+ results.push(this);
814
+ return true;
815
+ }
816
+ else if (settings.fullTextSearch === true && module.fuzzySearch(searchTerm, value)) {
798
817
  results.push(this);
799
818
  return true;
800
819
  }
@@ -876,7 +895,7 @@ $.fn.dropdown = function(parameters) {
876
895
  : $activeItem,
877
896
  hasSelected = ($selectedItem.length > 0)
878
897
  ;
879
- if(hasSelected) {
898
+ if(hasSelected && !module.is.multiple()) {
880
899
  module.debug('Forcing partial selection to selected item', $selectedItem);
881
900
  module.event.item.click.call($selectedItem, {}, true);
882
901
  return;
@@ -2183,7 +2202,7 @@ $.fn.dropdown = function(parameters) {
2183
2202
  $text.addClass(className.placeholder);
2184
2203
  },
2185
2204
  tabbable: function() {
2186
- if( module.has.search() ) {
2205
+ if( module.is.searchSelection() ) {
2187
2206
  module.debug('Added tabindex to searchable dropdown');
2188
2207
  $search
2189
2208
  .val('')
@@ -2295,12 +2314,13 @@ $.fn.dropdown = function(parameters) {
2295
2314
  },
2296
2315
  selectedItem: function($item) {
2297
2316
  var
2298
- value = module.get.choiceValue($item),
2299
- text = module.get.choiceText($item, false)
2317
+ value = module.get.choiceValue($item),
2318
+ searchText = module.get.choiceText($item, false),
2319
+ text = module.get.choiceText($item, true)
2300
2320
  ;
2301
2321
  module.debug('Setting user selection to item', $item);
2302
2322
  module.remove.activeItem();
2303
- module.set.partialSearch(text);
2323
+ module.set.partialSearch(searchText);
2304
2324
  module.set.activeItem($item);
2305
2325
  module.set.selected(value, $item);
2306
2326
  module.set.text(text);
@@ -2509,7 +2529,7 @@ $.fn.dropdown = function(parameters) {
2509
2529
  ;
2510
2530
  $label = $('<a />')
2511
2531
  .addClass(className.label)
2512
- .attr('data-value', escapedValue)
2532
+ .attr('data-' + metadata.value, escapedValue)
2513
2533
  .html(templates.label(escapedValue, text))
2514
2534
  ;
2515
2535
  $label = settings.onLabelCreate.call($label, escapedValue, text);
@@ -2557,7 +2577,7 @@ $.fn.dropdown = function(parameters) {
2557
2577
  optionValue: function(value) {
2558
2578
  var
2559
2579
  escapedValue = module.escape.value(value),
2560
- $option = $input.find('option[value="' + escapedValue + '"]'),
2580
+ $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
2561
2581
  hasOption = ($option.length > 0)
2562
2582
  ;
2563
2583
  if(hasOption) {
@@ -2730,7 +2750,7 @@ $.fn.dropdown = function(parameters) {
2730
2750
  optionValue: function(value) {
2731
2751
  var
2732
2752
  escapedValue = module.escape.value(value),
2733
- $option = $input.find('option[value="' + escapedValue + '"]'),
2753
+ $option = $input.find('option[value="' + module.escape.string(escapedValue) + '"]'),
2734
2754
  hasOption = ($option.length > 0)
2735
2755
  ;
2736
2756
  if(!hasOption || !$option.hasClass(className.addition)) {
@@ -2849,7 +2869,7 @@ $.fn.dropdown = function(parameters) {
2849
2869
  label: function(value, shouldAnimate) {
2850
2870
  var
2851
2871
  $labels = $module.find(selector.label),
2852
- $removedLabel = $labels.filter('[data-value="' + value +'"]')
2872
+ $removedLabel = $labels.filter('[data-' + metadata.value + '="' + module.escape.string(value) +'"]')
2853
2873
  ;
2854
2874
  module.verbose('Removing label', $removedLabel);
2855
2875
  $removedLabel.remove();
@@ -2889,7 +2909,7 @@ $.fn.dropdown = function(parameters) {
2889
2909
  ;
2890
2910
  },
2891
2911
  tabbable: function() {
2892
- if( module.has.search() ) {
2912
+ if( module.is.searchSelection() ) {
2893
2913
  module.debug('Searchable dropdown initialized');
2894
2914
  $search
2895
2915
  .removeAttr('tabindex')
@@ -2963,7 +2983,7 @@ $.fn.dropdown = function(parameters) {
2963
2983
  escapedValue = module.escape.value(value),
2964
2984
  $labels = $module.find(selector.label)
2965
2985
  ;
2966
- return ($labels.filter('[data-value="' + escapedValue +'"]').length > 0);
2986
+ return ($labels.filter('[data-' + metadata.value + '="' + module.escape.string(escapedValue) +'"]').length > 0);
2967
2987
  },
2968
2988
  maxSelections: function() {
2969
2989
  return (settings.maxSelections && module.get.selectionCount() >= settings.maxSelections);
@@ -3083,6 +3103,9 @@ $.fn.dropdown = function(parameters) {
3083
3103
  multiple: function() {
3084
3104
  return $module.hasClass(className.multiple);
3085
3105
  },
3106
+ remote: function() {
3107
+ return settings.apiSettings && module.can.useAPI();
3108
+ },
3086
3109
  single: function() {
3087
3110
  return !module.is.multiple();
3088
3111
  },
@@ -3288,7 +3311,7 @@ $.fn.dropdown = function(parameters) {
3288
3311
  hasQuotes = (stringValue && value.search(regExp.quote) !== -1),
3289
3312
  values = []
3290
3313
  ;
3291
- if(!module.has.selectInput() || isUnparsable || !hasQuotes) {
3314
+ if(isUnparsable || !hasQuotes) {
3292
3315
  return value;
3293
3316
  }
3294
3317
  module.debug('Encoding quote values for use in select', value);
@@ -3300,7 +3323,7 @@ $.fn.dropdown = function(parameters) {
3300
3323
  }
3301
3324
  return value.replace(regExp.quote, '&quot;');
3302
3325
  },
3303
- regExp: function(text) {
3326
+ string: function(text) {
3304
3327
  text = String(text);
3305
3328
  return text.replace(regExp.escape, '\\$&');
3306
3329
  }
@@ -3503,7 +3526,10 @@ $.fn.dropdown.settings = {
3503
3526
  apiSettings : false,
3504
3527
  selectOnKeydown : true, // Whether selection should occur automatically when keyboard shortcuts used
3505
3528
  minCharacters : 0, // Minimum characters required to trigger API call
3529
+
3530
+ filterRemoteData : false, // Whether API results should be filtered after being returned for query term
3506
3531
  saveRemoteData : true, // Whether remote name/value pairs should be stored in sessionStorage to allow remote data to be restored on page refresh
3532
+
3507
3533
  throttle : 200, // How long to wait after last user input to search remotely
3508
3534
 
3509
3535
  context : window, // Context to use when determining if on screen
@@ -39,28 +39,29 @@ $.fn.search = function(parameters) {
39
39
  ? $.extend(true, {}, $.fn.search.settings, parameters)
40
40
  : $.extend({}, $.fn.search.settings),
41
41
 
42
- className = settings.className,
43
- metadata = settings.metadata,
44
- regExp = settings.regExp,
45
- fields = settings.fields,
46
- selector = settings.selector,
47
- error = settings.error,
48
- namespace = settings.namespace,
49
-
50
- eventNamespace = '.' + namespace,
51
- moduleNamespace = namespace + '-module',
52
-
53
- $module = $(this),
54
- $prompt = $module.find(selector.prompt),
55
- $searchButton = $module.find(selector.searchButton),
56
- $results = $module.find(selector.results),
57
- $result = $module.find(selector.result),
58
- $category = $module.find(selector.category),
59
-
60
- element = this,
61
- instance = $module.data(moduleNamespace),
62
-
63
- disabledBubbled = false,
42
+ className = settings.className,
43
+ metadata = settings.metadata,
44
+ regExp = settings.regExp,
45
+ fields = settings.fields,
46
+ selector = settings.selector,
47
+ error = settings.error,
48
+ namespace = settings.namespace,
49
+
50
+ eventNamespace = '.' + namespace,
51
+ moduleNamespace = namespace + '-module',
52
+
53
+ $module = $(this),
54
+ $prompt = $module.find(selector.prompt),
55
+ $searchButton = $module.find(selector.searchButton),
56
+ $results = $module.find(selector.results),
57
+ $result = $module.find(selector.result),
58
+ $category = $module.find(selector.category),
59
+
60
+ element = this,
61
+ instance = $module.data(moduleNamespace),
62
+
63
+ disabledBubbled = false,
64
+ resultsDismissed = false,
64
65
 
65
66
  module
66
67
  ;
@@ -147,11 +148,12 @@ $.fn.search = function(parameters) {
147
148
  },
148
149
  focus: function() {
149
150
  module.set.focus();
150
- if( module.has.minimumCharacters() ) {
151
- module.query();
152
- if( module.can.show() ) {
153
- module.showResults();
154
- }
151
+ if(settings.searchOnFocus && module.has.minimumCharacters() ) {
152
+ module.query(function() {
153
+ if(module.can.show() ) {
154
+ module.showResults();
155
+ }
156
+ });
155
157
  }
156
158
  },
157
159
  blur: function(event) {
@@ -166,6 +168,7 @@ $.fn.search = function(parameters) {
166
168
  if(pageLostFocus) {
167
169
  return;
168
170
  }
171
+ resultsDismissed = false;
169
172
  if(module.resultsClicked) {
170
173
  module.debug('Determining if user action caused search to close');
171
174
  $module
@@ -258,7 +261,8 @@ $.fn.search = function(parameters) {
258
261
  // search shortcuts
259
262
  if(keyCode == keys.escape) {
260
263
  module.verbose('Escape key pressed, blurring search field');
261
- module.trigger.blur();
264
+ module.hideResults();
265
+ resultsDismissed = true;
262
266
  }
263
267
  if( module.is.visible() ) {
264
268
  if(keyCode == keys.enter) {
@@ -318,7 +322,7 @@ $.fn.search = function(parameters) {
318
322
  },
319
323
 
320
324
  setup: {
321
- api: function(searchTerm) {
325
+ api: function(searchTerm, callback) {
322
326
  var
323
327
  apiSettings = {
324
328
  debug : settings.debug,
@@ -330,11 +334,13 @@ $.fn.search = function(parameters) {
330
334
  },
331
335
  onSuccess : function(response) {
332
336
  module.parse.response.call(element, response, searchTerm);
333
- },
334
- onAbort : function(response) {
337
+ callback();
335
338
  },
336
339
  onFailure : function() {
337
340
  module.displayMessage(error.serverError);
341
+ callback();
342
+ },
343
+ onAbort : function(response) {
338
344
  },
339
345
  onError : module.error
340
346
  },
@@ -386,20 +392,6 @@ $.fn.search = function(parameters) {
386
392
  }
387
393
  },
388
394
 
389
- trigger: {
390
- blur: function() {
391
- var
392
- events = document.createEvent('HTMLEvents'),
393
- promptElement = $prompt[0]
394
- ;
395
- if(promptElement) {
396
- module.verbose('Triggering native blur event');
397
- events.initEvent('blur', false, false);
398
- promptElement.dispatchEvent(events);
399
- }
400
- }
401
- },
402
-
403
395
  get: {
404
396
  inputEvent: function() {
405
397
  var
@@ -497,28 +489,36 @@ $.fn.search = function(parameters) {
497
489
  }
498
490
  },
499
491
 
500
- query: function() {
492
+ query: function(callback) {
493
+ callback = $.isFunction(callback)
494
+ ? callback
495
+ : function(){}
496
+ ;
501
497
  var
502
498
  searchTerm = module.get.value(),
503
499
  cache = module.read.cache(searchTerm)
504
500
  ;
501
+ callback = callback || function() {};
505
502
  if( module.has.minimumCharacters() ) {
506
503
  if(cache) {
507
504
  module.debug('Reading result from cache', searchTerm);
508
505
  module.save.results(cache.results);
509
506
  module.addResults(cache.html);
510
507
  module.inject.id(cache.results);
508
+ callback();
511
509
  }
512
510
  else {
513
511
  module.debug('Querying for', searchTerm);
514
512
  if($.isPlainObject(settings.source) || $.isArray(settings.source)) {
515
513
  module.search.local(searchTerm);
514
+ callback();
516
515
  }
517
516
  else if( module.can.useAPI() ) {
518
- module.search.remote(searchTerm);
517
+ module.search.remote(searchTerm, callback);
519
518
  }
520
519
  else {
521
520
  module.error(error.source);
521
+ callback();
522
522
  }
523
523
  }
524
524
  settings.onSearchQuery.call(element, searchTerm);
@@ -549,11 +549,15 @@ $.fn.search = function(parameters) {
549
549
  results : results
550
550
  });
551
551
  },
552
- remote: function(searchTerm) {
552
+ remote: function(searchTerm, callback) {
553
+ callback = $.isFunction(callback)
554
+ ? callback
555
+ : function(){}
556
+ ;
553
557
  if($module.api('is loading')) {
554
558
  $module.api('abort');
555
559
  }
556
- module.setup.api(searchTerm);
560
+ module.setup.api(searchTerm, callback);
557
561
  $module
558
562
  .api('query')
559
563
  ;
@@ -680,6 +684,15 @@ $.fn.search = function(parameters) {
680
684
  numCharacters = searchTerm.length
681
685
  ;
682
686
  return (numCharacters >= settings.minCharacters);
687
+ },
688
+ results: function() {
689
+ if($results.length === 0) {
690
+ return false;
691
+ }
692
+ var
693
+ html = $results.html()
694
+ ;
695
+ return html != '';
683
696
  }
684
697
  },
685
698
 
@@ -846,12 +859,21 @@ $.fn.search = function(parameters) {
846
859
  module.showResults();
847
860
  }
848
861
  else {
849
- module.hideResults();
862
+ module.hideResults(function() {
863
+ $results.empty();
864
+ });
850
865
  }
851
866
  },
852
867
 
853
- showResults: function() {
854
- if(!module.is.visible()) {
868
+ showResults: function(callback) {
869
+ callback = $.isFunction(callback)
870
+ ? callback
871
+ : function(){}
872
+ ;
873
+ if(resultsDismissed) {
874
+ return;
875
+ }
876
+ if(!module.is.visible() && module.has.results()) {
855
877
  if( module.can.transition() ) {
856
878
  module.debug('Showing results with css animations');
857
879
  $results
@@ -860,6 +882,9 @@ $.fn.search = function(parameters) {
860
882
  debug : settings.debug,
861
883
  verbose : settings.verbose,
862
884
  duration : settings.duration,
885
+ onComplete : function() {
886
+ callback();
887
+ },
863
888
  queue : true
864
889
  })
865
890
  ;
@@ -874,7 +899,11 @@ $.fn.search = function(parameters) {
874
899
  settings.onResultsOpen.call($results);
875
900
  }
876
901
  },
877
- hideResults: function() {
902
+ hideResults: function(callback) {
903
+ callback = $.isFunction(callback)
904
+ ? callback
905
+ : function(){}
906
+ ;
878
907
  if( module.is.visible() ) {
879
908
  if( module.can.transition() ) {
880
909
  module.debug('Hiding results with css animations');
@@ -884,6 +913,9 @@ $.fn.search = function(parameters) {
884
913
  debug : settings.debug,
885
914
  verbose : settings.verbose,
886
915
  duration : settings.duration,
916
+ onComplete : function() {
917
+ callback();
918
+ },
887
919
  queue : true
888
920
  })
889
921
  ;
@@ -1144,6 +1176,9 @@ $.fn.search.settings = {
1144
1176
  // object to search
1145
1177
  source : false,
1146
1178
 
1179
+ // Whether search should query current term on focus
1180
+ searchOnFocus : true,
1181
+
1147
1182
  // fields to search
1148
1183
  searchFields : [
1149
1184
  'title',