fomantic-ui-sass 2.9.2 → 2.9.3.1

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile +2 -0
  4. data/Rakefile +2 -0
  5. data/app/assets/javascripts/semantic-ui/accordion.js +1 -5
  6. data/app/assets/javascripts/semantic-ui/api.js +22 -15
  7. data/app/assets/javascripts/semantic-ui/calendar.js +1 -6
  8. data/app/assets/javascripts/semantic-ui/checkbox.js +4 -6
  9. data/app/assets/javascripts/semantic-ui/dimmer.js +1 -5
  10. data/app/assets/javascripts/semantic-ui/dropdown.js +56 -33
  11. data/app/assets/javascripts/semantic-ui/embed.js +1 -6
  12. data/app/assets/javascripts/semantic-ui/flyout.js +40 -58
  13. data/app/assets/javascripts/semantic-ui/form.js +102 -53
  14. data/app/assets/javascripts/semantic-ui/modal.js +45 -33
  15. data/app/assets/javascripts/semantic-ui/nag.js +17 -9
  16. data/app/assets/javascripts/semantic-ui/popup.js +27 -19
  17. data/app/assets/javascripts/semantic-ui/progress.js +1 -6
  18. data/app/assets/javascripts/semantic-ui/rating.js +1 -5
  19. data/app/assets/javascripts/semantic-ui/search.js +4 -7
  20. data/app/assets/javascripts/semantic-ui/shape.js +1 -5
  21. data/app/assets/javascripts/semantic-ui/sidebar.js +15 -38
  22. data/app/assets/javascripts/semantic-ui/site.js +1 -1
  23. data/app/assets/javascripts/semantic-ui/slider.js +130 -34
  24. data/app/assets/javascripts/semantic-ui/state.js +23 -20
  25. data/app/assets/javascripts/semantic-ui/sticky.js +17 -16
  26. data/app/assets/javascripts/semantic-ui/tab.js +18 -8
  27. data/app/assets/javascripts/semantic-ui/toast.js +17 -9
  28. data/app/assets/javascripts/semantic-ui/transition.js +2 -6
  29. data/app/assets/javascripts/semantic-ui/visibility.js +15 -6
  30. data/app/assets/stylesheets/semantic-ui/collections/_breadcrumb.scss +1 -1
  31. data/app/assets/stylesheets/semantic-ui/collections/_form.scss +53 -20
  32. data/app/assets/stylesheets/semantic-ui/collections/_grid.scss +107 -107
  33. data/app/assets/stylesheets/semantic-ui/collections/_menu.scss +13 -7
  34. data/app/assets/stylesheets/semantic-ui/collections/_message.scss +1 -1
  35. data/app/assets/stylesheets/semantic-ui/collections/_table.scss +65 -1
  36. data/app/assets/stylesheets/semantic-ui/elements/_button.scss +2 -2
  37. data/app/assets/stylesheets/semantic-ui/elements/_container.scss +62 -1
  38. data/app/assets/stylesheets/semantic-ui/elements/_divider.scss +1 -1
  39. data/app/assets/stylesheets/semantic-ui/elements/_emoji.scss +697 -249
  40. data/app/assets/stylesheets/semantic-ui/elements/_flag.scss +3 -2
  41. data/app/assets/stylesheets/semantic-ui/elements/_header.scss +1 -1
  42. data/app/assets/stylesheets/semantic-ui/elements/_icon.scss +62 -62
  43. data/app/assets/stylesheets/semantic-ui/elements/_image.scss +1 -1
  44. data/app/assets/stylesheets/semantic-ui/elements/_input.scss +3 -27
  45. data/app/assets/stylesheets/semantic-ui/elements/_label.scss +21 -2
  46. data/app/assets/stylesheets/semantic-ui/elements/_list.scss +13 -13
  47. data/app/assets/stylesheets/semantic-ui/elements/_loader.scss +282 -282
  48. data/app/assets/stylesheets/semantic-ui/elements/_placeholder.scss +1 -1
  49. data/app/assets/stylesheets/semantic-ui/elements/_rail.scss +1 -1
  50. data/app/assets/stylesheets/semantic-ui/elements/_reveal.scss +1 -1
  51. data/app/assets/stylesheets/semantic-ui/elements/_segment.scss +161 -34
  52. data/app/assets/stylesheets/semantic-ui/elements/_step.scss +1 -1
  53. data/app/assets/stylesheets/semantic-ui/elements/_text.scss +1 -1
  54. data/app/assets/stylesheets/semantic-ui/globals/_reset.scss +1 -1
  55. data/app/assets/stylesheets/semantic-ui/globals/_site.scss +1 -1
  56. data/app/assets/stylesheets/semantic-ui/modules/_accordion.scss +1 -1
  57. data/app/assets/stylesheets/semantic-ui/modules/_calendar.scss +145 -8
  58. data/app/assets/stylesheets/semantic-ui/modules/_checkbox.scss +50 -6
  59. data/app/assets/stylesheets/semantic-ui/modules/_dimmer.scss +3 -3
  60. data/app/assets/stylesheets/semantic-ui/modules/_dropdown.scss +119 -26
  61. data/app/assets/stylesheets/semantic-ui/modules/_embed.scss +1 -1
  62. data/app/assets/stylesheets/semantic-ui/modules/_flyout.scss +1 -1
  63. data/app/assets/stylesheets/semantic-ui/modules/_modal.scss +10 -3
  64. data/app/assets/stylesheets/semantic-ui/modules/_nag.scss +1 -1
  65. data/app/assets/stylesheets/semantic-ui/modules/_popup.scss +41 -40
  66. data/app/assets/stylesheets/semantic-ui/modules/_progress.scss +1 -1
  67. data/app/assets/stylesheets/semantic-ui/modules/_rating.scss +1 -1
  68. data/app/assets/stylesheets/semantic-ui/modules/_search.scss +26 -1
  69. data/app/assets/stylesheets/semantic-ui/modules/_shape.scss +1 -1
  70. data/app/assets/stylesheets/semantic-ui/modules/_sidebar.scss +1 -1
  71. data/app/assets/stylesheets/semantic-ui/modules/_slider.scss +1 -1
  72. data/app/assets/stylesheets/semantic-ui/modules/_sticky.scss +1 -1
  73. data/app/assets/stylesheets/semantic-ui/modules/_tab.scss +1 -1
  74. data/app/assets/stylesheets/semantic-ui/modules/_toast.scss +6 -1
  75. data/app/assets/stylesheets/semantic-ui/modules/_transition.scss +1 -1
  76. data/app/assets/stylesheets/semantic-ui/views/_ad.scss +1 -1
  77. data/app/assets/stylesheets/semantic-ui/views/_card.scss +1 -1
  78. data/app/assets/stylesheets/semantic-ui/views/_comment.scss +6 -1
  79. data/app/assets/stylesheets/semantic-ui/views/_feed.scss +486 -5
  80. data/app/assets/stylesheets/semantic-ui/views/_item.scss +6 -1
  81. data/app/assets/stylesheets/semantic-ui/views/_statistic.scss +1 -1
  82. data/app/helpers/semantic_breadcrumbs_helper.rb +2 -0
  83. data/app/helpers/semantic_flash_helper.rb +2 -0
  84. data/app/helpers/semantic_icon_helper.rb +2 -0
  85. data/fomantic-ui-sass.gemspec +4 -2
  86. data/gemfiles/rails_5.0.gemfile +2 -0
  87. data/gemfiles/rails_5.1.gemfile +2 -0
  88. data/gemfiles/rails_5.2.gemfile +2 -0
  89. data/lib/fomantic/ui/sass/breadcrumbs.rb +2 -0
  90. data/lib/fomantic/ui/sass/engine.rb +5 -3
  91. data/lib/fomantic/ui/sass/version.rb +4 -2
  92. data/lib/fomantic-ui-sass.rb +2 -6
  93. data/spec/dummy/Rakefile +2 -0
  94. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  95. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  96. data/spec/dummy/bin/bundle +2 -0
  97. data/spec/dummy/bin/rails +2 -0
  98. data/spec/dummy/bin/rake +2 -0
  99. data/spec/dummy/config/application.rb +3 -1
  100. data/spec/dummy/config/boot.rb +2 -0
  101. data/spec/dummy/config/environment.rb +2 -0
  102. data/spec/dummy/config/environments/development.rb +3 -1
  103. data/spec/dummy/config/environments/production.rb +2 -0
  104. data/spec/dummy/config/environments/test.rb +3 -1
  105. data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
  106. data/spec/dummy/config/initializers/filter_parameter_logging.rb +2 -0
  107. data/spec/dummy/config/initializers/inflections.rb +2 -0
  108. data/spec/dummy/config/initializers/mime_types.rb +2 -0
  109. data/spec/dummy/config/initializers/secret_token.rb +2 -0
  110. data/spec/dummy/config/initializers/session_store.rb +2 -0
  111. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
  112. data/spec/dummy/config/routes.rb +2 -0
  113. data/spec/dummy/config.ru +3 -1
  114. data/spec/helpers/semantic_breadcrumbs_helper_spec.rb +2 -0
  115. data/spec/helpers/semantic_flash_helper_spec.rb +2 -0
  116. data/spec/helpers/semantic_icon_helper_spec.rb +2 -0
  117. data/spec/spec_helper.rb +2 -0
  118. data/tasks/converter.rb +9 -19
  119. data/templates/project/manifest.rb +2 -0
  120. metadata +12 -26
@@ -28,15 +28,25 @@
28
28
  $head = $('head'),
29
29
  $body = $('body'),
30
30
 
31
- moduleSelector = $allModules.selector || '',
32
-
33
31
  time = Date.now(),
34
32
  performance = [],
35
33
 
36
34
  query = arguments[0],
37
35
  methodInvoked = typeof query === 'string',
38
36
  queryArguments = [].slice.call(arguments, 1),
37
+ contextCheck = function (context, win) {
38
+ var $context;
39
+ if ([window, document].indexOf(context) >= 0) {
40
+ $context = $body;
41
+ } else {
42
+ $context = $(win.document).find(context);
43
+ if ($context.length === 0) {
44
+ $context = win.frameElement ? contextCheck(context, win.parent) : $body;
45
+ }
46
+ }
39
47
 
48
+ return $context;
49
+ },
40
50
  returnedValue
41
51
  ;
42
52
 
@@ -57,7 +67,7 @@
57
67
  moduleNamespace = 'module-' + namespace,
58
68
 
59
69
  $module = $(this),
60
- $context = [window, document].indexOf(settings.context) < 0 ? $document.find(settings.context) : $body,
70
+ $context = contextCheck(settings.context, window),
61
71
  $closeIcon = $module.find(selector.close),
62
72
  $inputs,
63
73
  $focusedElement,
@@ -76,6 +86,7 @@
76
86
  initialBodyMargin = '',
77
87
  tempBodyMargin = '',
78
88
  hadScrollbar = false,
89
+ windowRefocused = false,
79
90
 
80
91
  elementNamespace,
81
92
  id,
@@ -222,9 +233,6 @@
222
233
  .off(eventNamespace)
223
234
  .removeData(moduleNamespace)
224
235
  ;
225
- if (module.is.ios()) {
226
- module.remove.ios();
227
- }
228
236
  $closeIcon.off(elementNamespace);
229
237
  if ($inputs) {
230
238
  $inputs.off(elementNamespace);
@@ -254,9 +262,13 @@
254
262
  module.setup.heights();
255
263
  },
256
264
  focus: function () {
257
- if (module.is.visible() && settings.autofocus && settings.dimPage) {
265
+ windowRefocused = true;
266
+ },
267
+ click: function (event) {
268
+ if (windowRefocused && document.activeElement !== event.target && module.is.visible() && settings.autofocus && settings.dimPage && $(document.activeElement).closest(selector.flyout).length === 0) {
258
269
  requestAnimationFrame(module.set.autofocus);
259
270
  }
271
+ windowRefocused = false;
260
272
  },
261
273
  clickaway: function (event) {
262
274
  if (settings.closable) {
@@ -363,6 +375,9 @@
363
375
  $window
364
376
  .on('focus' + elementNamespace, module.event.focus)
365
377
  ;
378
+ $context
379
+ .on('click' + elementNamespace, module.event.click)
380
+ ;
366
381
  },
367
382
  clickaway: function () {
368
383
  module.verbose('Adding clickaway events to context', $context);
@@ -492,11 +507,12 @@
492
507
 
493
508
  return nodes;
494
509
  },
495
- shouldRefreshInputs = false
510
+ shouldRefreshInputs = false,
511
+ ignoreAutofocus = true
496
512
  ;
497
513
  mutations.every(function (mutation) {
498
514
  if (mutation.type === 'attributes') {
499
- if (observeAttributes && (mutation.attributeName === 'disabled' || $(mutation.target).find(':input').addBack(':input').length > 0)) {
515
+ if (observeAttributes && (mutation.attributeName === 'disabled' || $(mutation.target).find(':input').addBack(':input').filter(':visible').length > 0)) {
500
516
  shouldRefreshInputs = true;
501
517
  }
502
518
  } else {
@@ -506,6 +522,9 @@
506
522
  $removedInputs = $(collectNodes(mutation.removedNodes)).filter('a[href], [tabindex], :input');
507
523
  if ($addedInputs.length > 0 || $removedInputs.length > 0) {
508
524
  shouldRefreshInputs = true;
525
+ if ($addedInputs.filter(':input').length > 0 || $removedInputs.filter(':input').length > 0) {
526
+ ignoreAutofocus = false;
527
+ }
509
528
  }
510
529
  }
511
530
 
@@ -513,7 +532,7 @@
513
532
  });
514
533
 
515
534
  if (shouldRefreshInputs) {
516
- module.refreshInputs();
535
+ module.refreshInputs(ignoreAutofocus);
517
536
  }
518
537
  });
519
538
  observer.observe(element, {
@@ -527,7 +546,7 @@
527
546
  },
528
547
  refresh: function () {
529
548
  module.verbose('Refreshing selector cache');
530
- $context = [window, document].indexOf(settings.context) < 0 ? $document.find(settings.context) : $body;
549
+ $context = contextCheck(settings.context, window);
531
550
  module.refreshFlyouts();
532
551
  $pusher = $context.children(selector.pusher);
533
552
  module.clear.cache();
@@ -538,7 +557,7 @@
538
557
  $flyouts = $context.children(selector.flyout);
539
558
  },
540
559
 
541
- refreshInputs: function () {
560
+ refreshInputs: function (ignoreAutofocus) {
542
561
  if ($inputs) {
543
562
  $inputs
544
563
  .off('keydown' + elementNamespace)
@@ -550,8 +569,8 @@
550
569
  $inputs = $module.find('a[href], [tabindex], :input:enabled').filter(':visible').filter(function () {
551
570
  return $(this).closest('.disabled').length === 0;
552
571
  });
553
- if ($inputs.length === 0) {
554
- $inputs = $module;
572
+ if ($inputs.filter(':input').length === 0) {
573
+ $inputs = $module.add($inputs);
555
574
  $module.attr('tabindex', -1);
556
575
  } else {
557
576
  $module.removeAttr('tabindex');
@@ -562,7 +581,7 @@
562
581
  $inputs.last()
563
582
  .on('keydown' + elementNamespace, module.event.inputKeyDown.last)
564
583
  ;
565
- if (settings.autofocus && $inputs.filter(':focus').length === 0) {
584
+ if (!ignoreAutofocus && settings.autofocus && $inputs.filter(':focus').length === 0) {
566
585
  module.set.autofocus();
567
586
  }
568
587
  },
@@ -840,20 +859,14 @@
840
859
  var
841
860
  $autofocus = $inputs.filter('[autofocus]'),
842
861
  $rawInputs = $inputs.filter(':input'),
843
- $input = $autofocus.length > 0
844
- ? $autofocus.first()
862
+ $input = ($autofocus.length > 0
863
+ ? $autofocus
845
864
  : ($rawInputs.length > 0
846
865
  ? $rawInputs
847
- : $inputs.filter(':not(i.close)')
848
- ).first()
866
+ : $module)
867
+ ).first()
849
868
  ;
850
- // check if only the close icon is remaining
851
- if ($input.length === 0 && $inputs.length > 0) {
852
- $input = $inputs.first();
853
- }
854
- if ($input.length > 0) {
855
- $input.trigger('focus');
856
- }
869
+ $input.trigger('focus');
857
870
  },
858
871
  dimmerStyles: function () {
859
872
  if (settings.blurring) {
@@ -874,12 +887,6 @@
874
887
  });
875
888
  },
876
889
 
877
- // ios only (scroll on html not document). This prevent auto-resize canvas/scroll in ios
878
- // (This is no longer necessary in latest iOS)
879
- ios: function () {
880
- $html.addClass(className.ios);
881
- },
882
-
883
890
  // container
884
891
  pushed: function () {
885
892
  $context.addClass(className.pushed);
@@ -929,11 +936,6 @@
929
936
  ;
930
937
  },
931
938
 
932
- // ios scroll on html not document
933
- ios: function () {
934
- $html.removeClass(className.ios);
935
- },
936
-
937
939
  // context
938
940
  pushed: function () {
939
941
  $context.removeClass(className.pushed);
@@ -1055,20 +1057,6 @@
1055
1057
 
1056
1058
  return module.cache.isIE;
1057
1059
  },
1058
- ios: function () {
1059
- var
1060
- userAgent = navigator.userAgent,
1061
- isIOS = userAgent.match(regExp.ios),
1062
- isMobileChrome = userAgent.match(regExp.mobileChrome)
1063
- ;
1064
- if (isIOS && !isMobileChrome) {
1065
- module.verbose('Browser was found to be iOS', userAgent);
1066
-
1067
- return true;
1068
- }
1069
-
1070
- return false;
1071
- },
1072
1060
  mobile: function () {
1073
1061
  var
1074
1062
  userAgent = navigator.userAgent,
@@ -1231,7 +1219,7 @@
1231
1219
  });
1232
1220
  }
1233
1221
  clearTimeout(module.performance.timer);
1234
- module.performance.timer = setTimeout(module.performance.display, 500);
1222
+ module.performance.timer = setTimeout(function () { module.performance.display(); }, 500);
1235
1223
  },
1236
1224
  display: function () {
1237
1225
  var
@@ -1244,9 +1232,6 @@
1244
1232
  totalTime += data['Execution Time'];
1245
1233
  });
1246
1234
  title += ' ' + totalTime + 'ms';
1247
- if (moduleSelector) {
1248
- title += ' \'' + moduleSelector + '\'';
1249
- }
1250
1235
  if (performance.length > 0) {
1251
1236
  console.groupCollapsed(title);
1252
1237
  if (console.table) {
@@ -1418,7 +1403,6 @@
1418
1403
  blurring: 'blurring',
1419
1404
  closing: 'closing',
1420
1405
  dimmed: 'dimmed',
1421
- ios: 'ios',
1422
1406
  locked: 'locked',
1423
1407
  pushable: 'pushable',
1424
1408
  pushed: 'pushed',
@@ -1451,8 +1435,6 @@
1451
1435
  },
1452
1436
 
1453
1437
  regExp: {
1454
- ios: /(iPad|iPhone|iPod)/g,
1455
- mobileChrome: /(CriOS)/g,
1456
1438
  mobile: /Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/g,
1457
1439
  },
1458
1440
 
@@ -22,7 +22,7 @@
22
22
  $.fn.form = function (parameters) {
23
23
  var
24
24
  $allModules = $(this),
25
- moduleSelector = $allModules.selector || '',
25
+ $window = $(window),
26
26
 
27
27
  time = Date.now(),
28
28
  performance = [],
@@ -61,6 +61,8 @@
61
61
  namespace,
62
62
  moduleNamespace,
63
63
  eventNamespace,
64
+ attachEventsSelector,
65
+ attachEventsAction,
64
66
 
65
67
  submitting = false,
66
68
  dirty = false,
@@ -75,6 +77,7 @@
75
77
  initialize: function () {
76
78
  // settings grabbed at run time
77
79
  module.get.settings();
80
+ $module.addClass(className.initial);
78
81
  if (methodInvoked) {
79
82
  if (instance === undefined) {
80
83
  module.instantiate();
@@ -128,10 +131,13 @@
128
131
  module.bindEvents();
129
132
  },
130
133
 
131
- submit: function () {
134
+ submit: function (event) {
132
135
  module.verbose('Submitting form', $module);
133
136
  submitting = true;
134
137
  $module.trigger('submit');
138
+ if (event) {
139
+ event.preventDefault();
140
+ }
135
141
  },
136
142
 
137
143
  attachEvents: function (selector, action) {
@@ -143,6 +149,9 @@
143
149
  module[action]();
144
150
  event.preventDefault();
145
151
  });
152
+
153
+ attachEventsSelector = selector;
154
+ attachEventsAction = action;
146
155
  },
147
156
 
148
157
  bindEvents: function () {
@@ -154,6 +163,7 @@
154
163
  .on('click' + eventNamespace, selector.reset, module.reset)
155
164
  .on('click' + eventNamespace, selector.clear, module.clear)
156
165
  ;
166
+ $field.on('invalid' + eventNamespace, module.event.field.invalid);
157
167
  if (settings.keyboardShortcuts) {
158
168
  $module.on('keydown' + eventNamespace, selector.field, module.event.field.keydown);
159
169
  }
@@ -168,10 +178,14 @@
168
178
 
169
179
  // Dirty events
170
180
  if (settings.preventLeaving) {
171
- $(window).on('beforeunload' + eventNamespace, module.event.beforeUnload);
181
+ $window.on('beforeunload' + eventNamespace, module.event.beforeUnload);
172
182
  }
173
183
 
174
- $field.on('change click keyup keydown blur', function (e) {
184
+ $field.on('change' + eventNamespace
185
+ + ' click' + eventNamespace
186
+ + ' keyup' + eventNamespace
187
+ + ' keydown' + eventNamespace
188
+ + ' blur' + eventNamespace, function (e) {
175
189
  module.determine.isDirty();
176
190
  });
177
191
 
@@ -182,6 +196,9 @@
182
196
  $module.on('clean' + eventNamespace, function (e) {
183
197
  settings.onClean.call();
184
198
  });
199
+ if (attachEventsSelector) {
200
+ module.attachEvents(attachEventsSelector, attachEventsAction);
201
+ }
185
202
  },
186
203
 
187
204
  clear: function () {
@@ -230,6 +247,7 @@
230
247
  isCheckbox = $field.is(selector.checkbox),
231
248
  isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
232
249
  isCalendar = $calendar.length > 0 && module.can.useElement('calendar'),
250
+ isFile = $field.is(selector.file),
233
251
  isErrored = $fieldGroup.hasClass(className.error)
234
252
  ;
235
253
  if (defaultValue === undefined) {
@@ -250,7 +268,7 @@
250
268
  $calendar.calendar('set date', defaultValue);
251
269
  } else {
252
270
  module.verbose('Resetting field value', $field, defaultValue);
253
- $field.val(defaultValue);
271
+ $field.val(isFile ? '' : defaultValue);
254
272
  }
255
273
  });
256
274
  module.remove.states();
@@ -261,8 +279,12 @@
261
279
  var
262
280
  allValid = true
263
281
  ;
264
- $.each(validation, function (fieldName, field) {
265
- if (!module.validate.field(field, fieldName, true)) {
282
+ $field.each(function (index, el) {
283
+ var $el = $(el),
284
+ validation = module.get.validation($el) || {},
285
+ identifier = module.get.identifier(validation, $el)
286
+ ;
287
+ if (!module.validate.field(validation, identifier, true)) {
266
288
  allValid = false;
267
289
  }
268
290
  });
@@ -386,6 +408,13 @@
386
408
  $module.off(eventNamespace);
387
409
  $field.off(eventNamespace);
388
410
  $submit.off(eventNamespace);
411
+ if (settings.preventLeaving) {
412
+ $window.off(eventNamespace);
413
+ }
414
+ if (attachEventsSelector) {
415
+ $(attachEventsSelector).off(eventNamespace);
416
+ attachEventsSelector = undefined;
417
+ }
389
418
  },
390
419
 
391
420
  event: {
@@ -411,9 +440,8 @@
411
440
  if (!event.ctrlKey && key === keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
412
441
  if (!keyHeldDown) {
413
442
  $field.one('keyup' + eventNamespace, module.event.field.keyup);
414
- module.submit();
443
+ module.submit(event);
415
444
  module.debug('Enter pressed on input submitting form');
416
- event.preventDefault();
417
445
  }
418
446
  keyHeldDown = true;
419
447
  }
@@ -421,15 +449,18 @@
421
449
  keyup: function () {
422
450
  keyHeldDown = false;
423
451
  },
452
+ invalid: function (event) {
453
+ event.preventDefault();
454
+ },
424
455
  blur: function (event) {
425
456
  var
426
457
  $field = $(this),
427
- $fieldGroup = $field.closest($group),
428
- validationRules = module.get.validation($field)
458
+ validationRules = module.get.validation($field) || {},
459
+ identifier = module.get.identifier(validationRules, $field)
429
460
  ;
430
- if (validationRules && (settings.on === 'blur' || ($fieldGroup.hasClass(className.error) && settings.revalidate))) {
461
+ if (settings.on === 'blur' || (!$module.hasClass(className.initial) && settings.revalidate)) {
431
462
  module.debug('Revalidating field', $field, validationRules);
432
- module.validate.field(validationRules);
463
+ module.validate.field(validationRules, identifier);
433
464
  if (!settings.inline) {
434
465
  module.validate.form(false, true);
435
466
  }
@@ -438,14 +469,14 @@
438
469
  change: function (event) {
439
470
  var
440
471
  $field = $(this),
441
- $fieldGroup = $field.closest($group),
442
- validationRules = module.get.validation($field)
472
+ validationRules = module.get.validation($field) || {},
473
+ identifier = module.get.identifier(validationRules, $field)
443
474
  ;
444
- if (validationRules && (settings.on === 'change' || ($fieldGroup.hasClass(className.error) && settings.revalidate))) {
475
+ if (settings.on === 'change' || (!$module.hasClass(className.initial) && settings.revalidate)) {
445
476
  clearTimeout(module.timer);
446
477
  module.timer = setTimeout(function () {
447
478
  module.debug('Revalidating field', $field, validationRules);
448
- module.validate.field(validationRules);
479
+ module.validate.field(validationRules, identifier);
449
480
  if (!settings.inline) {
450
481
  module.validate.form(false, true);
451
482
  }
@@ -487,18 +518,7 @@
487
518
  return rule.type;
488
519
  },
489
520
  changeEvent: function (type, $input) {
490
- if (type === 'checkbox' || type === 'radio' || type === 'hidden' || $input.is('select')) {
491
- return 'change';
492
- }
493
-
494
- return module.get.inputEvent();
495
- },
496
- inputEvent: function () {
497
- return document.createElement('input').oninput !== undefined
498
- ? 'input'
499
- : (document.createElement('input').onpropertychange !== undefined
500
- ? 'propertychange'
501
- : 'keyup');
521
+ return ['file', 'checkbox', 'radio', 'hidden'].indexOf(type) >= 0 || $input.is('select') ? 'change' : 'input';
502
522
  },
503
523
  fieldsFromShorthand: function (fields) {
504
524
  var
@@ -522,6 +542,9 @@
522
542
 
523
543
  return fullFields;
524
544
  },
545
+ identifier: function (validation, $el) {
546
+ return validation.identifier || $el.attr('id') || $el.attr('name') || $el.data(metadata.validate);
547
+ },
525
548
  prompt: function (rule, field) {
526
549
  var
527
550
  ruleName = module.get.ruleName(rule),
@@ -634,7 +657,7 @@
634
657
  var $field = typeof identifier === 'string'
635
658
  ? module.get.field(identifier)
636
659
  : identifier,
637
- $label = $field.closest(selector.group).find('label').eq(0)
660
+ $label = $field.closest(selector.group).find('label:not(:empty)').eq(0)
638
661
  ;
639
662
 
640
663
  return $label.length === 1
@@ -888,7 +911,8 @@
888
911
  $field = module.get.field(identifier),
889
912
  $fieldGroup = $field.closest($group),
890
913
  $prompt = $fieldGroup.children(selector.prompt),
891
- promptExists = $prompt.length > 0
914
+ promptExists = $prompt.length > 0,
915
+ canTransition = settings.transition && module.can.useElement('transition')
892
916
  ;
893
917
  module.verbose('Adding field error state', identifier);
894
918
  if (!internal) {
@@ -897,8 +921,22 @@
897
921
  ;
898
922
  }
899
923
  if (settings.inline) {
924
+ if (promptExists) {
925
+ if (canTransition) {
926
+ if ($prompt.transition('is animating')) {
927
+ $prompt.transition('stop all');
928
+ }
929
+ } else if ($prompt.is(':animated')) {
930
+ $prompt.stop(true, true);
931
+ }
932
+ $prompt = $fieldGroup.children(selector.prompt);
933
+ promptExists = $prompt.length > 0;
934
+ }
900
935
  if (!promptExists) {
901
936
  $prompt = $('<div/>').addClass(className.label);
937
+ if (!canTransition) {
938
+ $prompt.css('display', 'none');
939
+ }
902
940
  $prompt
903
941
  .appendTo($fieldGroup)
904
942
  ;
@@ -907,7 +945,7 @@
907
945
  .html(settings.templates.prompt(errors))
908
946
  ;
909
947
  if (!promptExists) {
910
- if (settings.transition && module.can.useElement('transition')) {
948
+ if (canTransition) {
911
949
  module.verbose('Displaying error with css transition', settings.transition);
912
950
  $prompt.transition(settings.transition + ' in', settings.duration);
913
951
  } else {
@@ -916,9 +954,9 @@
916
954
  .fadeIn(settings.duration)
917
955
  ;
918
956
  }
919
- } else {
920
- module.verbose('Inline errors are disabled, no inline error added', identifier);
921
957
  }
958
+ } else {
959
+ module.verbose('Inline errors are disabled, no inline error added', identifier);
922
960
  }
923
961
  },
924
962
  errors: function (errors) {
@@ -965,7 +1003,7 @@
965
1003
  $message.empty();
966
1004
  },
967
1005
  states: function () {
968
- $module.removeClass(className.error).removeClass(className.success);
1006
+ $module.removeClass(className.error).removeClass(className.success).addClass(className.initial);
969
1007
  if (!settings.inline) {
970
1008
  module.remove.errors();
971
1009
  }
@@ -1103,6 +1141,7 @@
1103
1141
  $field = module.get.field(key),
1104
1142
  $element = $field.parent(),
1105
1143
  $calendar = $field.closest(selector.uiCalendar),
1144
+ isFile = $field.is(selector.file),
1106
1145
  isMultiple = Array.isArray(value),
1107
1146
  isCheckbox = $element.is(selector.uiCheckbox) && module.can.useElement('checkbox'),
1108
1147
  isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
@@ -1145,7 +1184,7 @@
1145
1184
  $calendar.calendar('set date', value);
1146
1185
  } else {
1147
1186
  module.verbose('Setting field value', value, $field);
1148
- $field.val(value);
1187
+ $field.val(isFile ? '' : value);
1149
1188
  }
1150
1189
  }
1151
1190
  });
@@ -1201,7 +1240,7 @@
1201
1240
  return rule.type === 'empty';
1202
1241
  }) !== 0
1203
1242
  : false,
1204
- identifier = validation.identifier || $el.attr('id') || $el.attr('name') || $el.data(metadata.validate)
1243
+ identifier = module.get.identifier(validation, $el)
1205
1244
  ;
1206
1245
  if (isRequired && !isDisabled && !hasEmptyRule && identifier !== undefined) {
1207
1246
  if (isCheckbox) {
@@ -1233,7 +1272,7 @@
1233
1272
  if (keyHeldDown) {
1234
1273
  return false;
1235
1274
  }
1236
-
1275
+ $module.removeClass(className.initial);
1237
1276
  // reset errors
1238
1277
  formErrors = [];
1239
1278
  if (module.determine.isValid()) {
@@ -1305,13 +1344,25 @@
1305
1344
  ? module.get.field(field.depends)
1306
1345
  : false,
1307
1346
  fieldValid = true,
1308
- fieldErrors = []
1347
+ fieldErrors = [],
1348
+ isDisabled = $field.filter(':not(:disabled)').length === 0,
1349
+ validationMessage = $field[0].validationMessage,
1350
+ errorLimit
1309
1351
  ;
1310
1352
  if (!field.identifier) {
1311
1353
  module.debug('Using field name as identifier', identifier);
1312
1354
  field.identifier = identifier;
1313
1355
  }
1314
- var isDisabled = $field.filter(':not(:disabled)').length === 0;
1356
+ if (validationMessage) {
1357
+ module.debug('Field is natively invalid', identifier);
1358
+ fieldErrors.push(validationMessage);
1359
+ fieldValid = false;
1360
+ if (showErrors) {
1361
+ $field.closest($group).addClass(className.error);
1362
+ }
1363
+ } else if (showErrors) {
1364
+ $field.closest($group).removeClass(className.error);
1365
+ }
1315
1366
  if (isDisabled) {
1316
1367
  module.debug('Field is disabled. Skipping', identifier);
1317
1368
  } else if (field.optional && module.is.blank($field)) {
@@ -1319,11 +1370,9 @@
1319
1370
  } else if (field.depends && module.is.empty($dependsField)) {
1320
1371
  module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
1321
1372
  } else if (field.rules !== undefined) {
1322
- if (showErrors) {
1323
- $field.closest($group).removeClass(className.error);
1324
- }
1373
+ errorLimit = field.errorLimit || settings.errorLimit;
1325
1374
  $.each(field.rules, function (index, rule) {
1326
- if (module.has.field(identifier)) {
1375
+ if (module.has.field(identifier) && (!errorLimit || fieldErrors.length < errorLimit)) {
1327
1376
  var invalidFields = module.validate.rule(field, rule, true) || [];
1328
1377
  if (invalidFields.length > 0) {
1329
1378
  module.debug('Field is invalid', identifier, rule.type);
@@ -1338,7 +1387,7 @@
1338
1387
  }
1339
1388
  if (fieldValid) {
1340
1389
  if (showErrors) {
1341
- module.remove.prompt(identifier, fieldErrors);
1390
+ module.remove.prompt(identifier);
1342
1391
  settings.onValid.call($field);
1343
1392
  }
1344
1393
  } else {
@@ -1460,7 +1509,7 @@
1460
1509
  });
1461
1510
  }
1462
1511
  clearTimeout(module.performance.timer);
1463
- module.performance.timer = setTimeout(module.performance.display, 500);
1512
+ module.performance.timer = setTimeout(function () { module.performance.display(); }, 500);
1464
1513
  },
1465
1514
  display: function () {
1466
1515
  var
@@ -1473,9 +1522,6 @@
1473
1522
  totalTime += data['Execution Time'];
1474
1523
  });
1475
1524
  title += ' ' + totalTime + 'ms';
1476
- if (moduleSelector) {
1477
- title += ' \'' + moduleSelector + '\'';
1478
- }
1479
1525
  if ($allModules.length > 1) {
1480
1526
  title += ' (' + $allModules.length + ')';
1481
1527
  }
@@ -1578,6 +1624,7 @@
1578
1624
  preventLeaving: false,
1579
1625
  errorFocus: true,
1580
1626
  dateHandling: 'date', // 'date', 'input', 'formatter'
1627
+ errorLimit: 0,
1581
1628
 
1582
1629
  onValid: function () {},
1583
1630
  onInvalid: function () {},
@@ -1631,8 +1678,8 @@
1631
1678
  isExactly: '{name} must be exactly "{ruleValue}"',
1632
1679
  not: '{name} cannot be set to "{ruleValue}"',
1633
1680
  notExactly: '{name} cannot be set to exactly "{ruleValue}"',
1634
- contain: '{name} must contain "{ruleValue}"',
1635
- containExactly: '{name} must contain exactly "{ruleValue}"',
1681
+ contains: '{name} must contain "{ruleValue}"',
1682
+ containsExactly: '{name} must contain exactly "{ruleValue}"',
1636
1683
  doesntContain: '{name} cannot contain "{ruleValue}"',
1637
1684
  doesntContainExactly: '{name} cannot contain exactly "{ruleValue}"',
1638
1685
  minLength: '{name} must be at least {ruleValue} characters',
@@ -1651,9 +1698,10 @@
1651
1698
  selector: {
1652
1699
  checkbox: 'input[type="checkbox"], input[type="radio"]',
1653
1700
  clear: '.clear',
1654
- field: 'input:not(.search):not([type="file"]):not([type="reset"]):not([type="button"]):not([type="submit"]), textarea, select',
1701
+ field: 'input:not(.search):not([type="reset"]):not([type="button"]):not([type="submit"]), textarea, select',
1702
+ file: 'input[type="file"]',
1655
1703
  group: '.field',
1656
- input: 'input:not([type="file"])',
1704
+ input: 'input',
1657
1705
  message: '.error.message',
1658
1706
  prompt: '.prompt.label',
1659
1707
  radio: 'input[type="radio"]',
@@ -1665,6 +1713,7 @@
1665
1713
  },
1666
1714
 
1667
1715
  className: {
1716
+ initial: 'initial',
1668
1717
  error: 'error',
1669
1718
  label: 'ui basic red pointing prompt label',
1670
1719
  pressed: 'down',