webshims-rails 1.10.11 → 1.11.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 (53) hide show
  1. checksums.yaml +8 -8
  2. data/lib/webshims-rails/version.rb +2 -2
  3. data/readme.textile +14 -1
  4. data/vendor/assets/javascripts/webshims/polyfiller.js +2 -1
  5. data/vendor/assets/javascripts/webshims/shims/combos/1.js +12 -63
  6. data/vendor/assets/javascripts/webshims/shims/combos/10.js +17 -7
  7. data/vendor/assets/javascripts/webshims/shims/combos/11.js +17 -3
  8. data/vendor/assets/javascripts/webshims/shims/combos/12.js +11 -12
  9. data/vendor/assets/javascripts/webshims/shims/combos/13.js +11 -12
  10. data/vendor/assets/javascripts/webshims/shims/combos/14.js +0 -4
  11. data/vendor/assets/javascripts/webshims/shims/combos/15.js +10 -59
  12. data/vendor/assets/javascripts/webshims/shims/combos/16.js +21 -71
  13. data/vendor/assets/javascripts/webshims/shims/combos/17.js +17 -3
  14. data/vendor/assets/javascripts/webshims/shims/combos/18.js +17 -3
  15. data/vendor/assets/javascripts/webshims/shims/combos/19.js +58 -19
  16. data/vendor/assets/javascripts/webshims/shims/combos/2.js +12 -67
  17. data/vendor/assets/javascripts/webshims/shims/combos/20.js +58 -19
  18. data/vendor/assets/javascripts/webshims/shims/combos/21.js +47 -3
  19. data/vendor/assets/javascripts/webshims/shims/combos/23.js +11 -12
  20. data/vendor/assets/javascripts/webshims/shims/combos/24.js +324 -79
  21. data/vendor/assets/javascripts/webshims/shims/combos/25.js +63 -21
  22. data/vendor/assets/javascripts/webshims/shims/combos/26.js +5 -6
  23. data/vendor/assets/javascripts/webshims/shims/combos/27.js +5 -2
  24. data/vendor/assets/javascripts/webshims/shims/combos/28.js +47 -7
  25. data/vendor/assets/javascripts/webshims/shims/combos/3.js +1 -55
  26. data/vendor/assets/javascripts/webshims/shims/combos/30.js +1 -55
  27. data/vendor/assets/javascripts/webshims/shims/combos/31.js +1 -55
  28. data/vendor/assets/javascripts/webshims/shims/combos/4.js +0 -4
  29. data/vendor/assets/javascripts/webshims/shims/combos/5.js +17 -3
  30. data/vendor/assets/javascripts/webshims/shims/combos/6.js +17 -3
  31. data/vendor/assets/javascripts/webshims/shims/combos/7.js +12 -67
  32. data/vendor/assets/javascripts/webshims/shims/combos/8.js +12 -67
  33. data/vendor/assets/javascripts/webshims/shims/combos/9.js +17 -7
  34. data/vendor/assets/javascripts/webshims/shims/dom-extend.js +0 -4
  35. data/vendor/assets/javascripts/webshims/shims/filereader.js +5 -2
  36. data/vendor/assets/javascripts/webshims/shims/form-core.js +1 -51
  37. data/vendor/assets/javascripts/webshims/shims/form-datalist-lazy.js +24 -15
  38. data/vendor/assets/javascripts/webshims/shims/form-number-date-ui.js +6 -2
  39. data/vendor/assets/javascripts/webshims/shims/form-shim-extend.js +9 -4
  40. data/vendor/assets/javascripts/webshims/shims/form-validation.js +135 -24
  41. data/vendor/assets/javascripts/webshims/shims/form-validators.js +189 -55
  42. data/vendor/assets/javascripts/webshims/shims/forms-picker.js +4 -1
  43. data/vendor/assets/javascripts/webshims/shims/jpicker/jpicker.css +3 -1
  44. data/vendor/assets/javascripts/webshims/shims/mediaelement-core.js +11 -12
  45. data/vendor/assets/javascripts/webshims/shims/mediaelement-jaris.js +47 -3
  46. data/vendor/assets/javascripts/webshims/shims/mediaelement-yt.js +28 -8
  47. data/vendor/assets/javascripts/webshims/shims/mediagroup.js +29 -0
  48. data/vendor/assets/javascripts/webshims/shims/range-ui.js +11 -1
  49. data/vendor/assets/javascripts/webshims/shims/styles/scss/shim.scss +17 -4
  50. data/vendor/assets/javascripts/webshims/shims/styles/shim.css +17 -6
  51. data/vendor/assets/javascripts/webshims/shims/swf/JarisFLVPlayer.swf +0 -0
  52. metadata +3 -3
  53. data/vendor/assets/javascripts/webshims/shims/swf/jwwebshims.swf +0 -0
@@ -476,6 +476,7 @@ var swfmini = function() {
476
476
  if(hasNative){
477
477
  var videoElem = document.createElement('video');
478
478
  Modernizr.videoBuffered = ('buffered' in videoElem);
479
+ Modernizr.mediaDefaultMuted = ('defaultMuted' in videoElem);
479
480
  supportsLoop = ('loop' in videoElem);
480
481
 
481
482
  webshims.capturingEvents(['play', 'playing', 'waiting', 'paused', 'ended', 'durationchange', 'loadedmetadata', 'canplay', 'volumechange']);
@@ -489,20 +490,15 @@ var swfmini = function() {
489
490
 
490
491
  if(!options.preferFlash){
491
492
  var noSwitch = {
492
- 1: 1,
493
- 2: 1
493
+ 1: 1
494
494
  };
495
495
  var switchOptions = function(e){
496
496
  var media, error, parent;
497
497
  if(!options.preferFlash &&
498
498
  ($(e.target).is('audio, video') || ((parent = e.target.parentNode) && $('source:last', parent)[0] == e.target)) &&
499
- (media = $(e.target).closest('audio, video')) && !noSwitch[(error = media.prop('error'))]
499
+ (media = $(e.target).closest('audio, video')) && (error = media.prop('error')) && !noSwitch[error.code]
500
500
  ){
501
- if(error == null){
502
- webshims.warn("There was an unspecified error on a mediaelement");
503
- return;
504
-
505
- }
501
+
506
502
  $(function(){
507
503
  if(hasSwf && !options.preferFlash){
508
504
  loadSwf();
@@ -514,7 +510,7 @@ var swfmini = function() {
514
510
  $('audio, video').each(function(){
515
511
  webshims.mediaelement.selectSource(this);
516
512
  });
517
- webshims.error("switching mediaelements option to 'preferFlash', due to an error with native player: "+e.target.src+" Mediaerror: "+ media.prop('error'));
513
+ webshims.error("switching mediaelements option to 'preferFlash', due to an error with native player: "+e.target.src+" Mediaerror: "+ media.prop('error')+ 'first error: '+ error);
518
514
  }
519
515
  }, 9);
520
516
  });
@@ -720,7 +716,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u
720
716
  if(src.indexOf('rtmp') === 0){
721
717
  return nodeName+'/rtmp';
722
718
  }
723
- src = src.split('?')[0].split('.');
719
+ src = src.split('?')[0].split('#')[0].split('.');
724
720
  src = src[src.length - 1];
725
721
  var mt;
726
722
 
@@ -839,7 +835,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u
839
835
  webshims.error('mediaelementError: '+ message);
840
836
  setTimeout(function(){
841
837
  if($(elem).data('mediaerror')){
842
- $(elem).trigger('mediaerror');
838
+ $(elem).addClass('media-error').trigger('mediaerror');
843
839
  }
844
840
  }, 1);
845
841
  }
@@ -903,6 +899,7 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u
903
899
  var parent = elem.parentNode;
904
900
 
905
901
  clearTimeout(baseData.loadTimer);
902
+ $(elem).removeClass('media-error');
906
903
  $.data(elem, 'mediaerror', false);
907
904
 
908
905
  if(!_srces.length || !parent || parent.nodeType != 1 || stopParent.test(parent.nodeName || '')){return;}
@@ -930,7 +927,9 @@ webshims.register('mediaelement-core', function($, webshims, window, document, u
930
927
  var testFixMedia = function(){
931
928
  if(webshims.implement(this, 'mediaelement')){
932
929
  selectSource(this);
933
-
930
+ if(!Modernizr.mediaDefaultMuted && $.attr(this, 'muted') != null){
931
+ $.prop(this, 'muted', true);
932
+ }
934
933
  //fixes for FF 12 and IE9/10 || does not hurt, if run in other browsers
935
934
  if(hasNative && (!supportsLoop || ('ActiveXObject' in window))){
936
935
  var bufferTimer;
@@ -4,6 +4,10 @@ webshims.register('form-validation', function($, webshims, window, document, und
4
4
  var webkitVersion = chromeBugs && parseFloat((navigator.userAgent.match(/Safari\/([\d\.]+)/) || ['', '999999'])[1], 10);
5
5
  var invalidClass = options.iVal.errorClass || 'user-error';
6
6
  var validClass = options.iVal.successClass || 'user-success';
7
+
8
+ var invalidWrapperClass = options.iVal.errorWrapperClass || 'ws-invalid';
9
+ var successWrapperClass = options.iVal.successWrapperClass || 'ws-success';
10
+ var errorBoxClass = options.iVal.errorBoxClass || 'ws-errorbox';
7
11
  var checkTypes = {checkbox: 1, radio: 1};
8
12
 
9
13
  var emptyJ = $([]);
@@ -93,13 +97,18 @@ webshims.register('form-validation', function($, webshims, window, document, und
93
97
  ){
94
98
  return;
95
99
  }
100
+ if(webshims.refreshCustomValidityRules){
101
+ if(webshims.refreshCustomValidityRules(elem) == 'async'){
102
+ $(elem).one('refreshvalidityui', switchValidityClass);
103
+ return;
104
+ }
105
+ }
106
+
96
107
  var validity = $.prop(elem, 'validity');
97
108
 
98
109
  var addClass, removeClass, trigger, generaltrigger, validityCause;
99
110
 
100
- if(webshims.refreshCustomValidityRules){
101
- webshims.refreshCustomValidityRules(elem);
102
- }
111
+
103
112
 
104
113
  if(validity.valid){
105
114
  if(!shadowElem.hasClass(validClass)){
@@ -457,10 +466,10 @@ webshims.register('form-validation', function($, webshims, window, document, und
457
466
  if(!fieldWrapper){
458
467
  fieldWrapper = this.getFieldWrapper(elem);
459
468
  }
460
- var errorBox = $('div.ws-errorbox', fieldWrapper);
469
+ var errorBox = $('div.'+errorBoxClass, fieldWrapper);
461
470
 
462
471
  if(!errorBox.length){
463
- errorBox = $('<div class="ws-errorbox" hidden="hidden">');
472
+ errorBox = $('<div class="'+ errorBoxClass +'" hidden="hidden">');
464
473
  fieldWrapper.append(errorBox);
465
474
  }
466
475
 
@@ -481,6 +490,48 @@ webshims.register('form-validation', function($, webshims, window, document, und
481
490
  }
482
491
  return fieldWrapper;
483
492
  },
493
+ _createContentMessage: (function(){
494
+ var fields = {};
495
+ var getErrorName = function(elem){
496
+ var ret = $(elem).data('errortype');
497
+ if(!ret){
498
+ $.each(fields, function(errorName, cNames){
499
+ if($(elem).is(cNames)){
500
+ ret = errorName;
501
+ return false;
502
+ }
503
+ });
504
+ }
505
+ return ret || 'defaultMessage';
506
+ };
507
+ $(function(){
508
+ $.each($('<input />').prop('validity'), function(name){
509
+ if(name != 'valid'){
510
+ var cName = name.replace(/[A-Z]/, function(c){
511
+ return '-'+(c).toLowerCase();
512
+ });
513
+ fields[name] = '.'+cName+', .'+name+', .'+(name).toLowerCase()+', [data-errortype="'+ name +'"]';
514
+ }
515
+ });
516
+ });
517
+ return function(elem, errorBox){
518
+ var extended = false;
519
+ var errorMessages = $(elem).data('errormessage') || {};
520
+ if(typeof errorMessages == 'string'){
521
+ errorMessages = {defaultMessage: errorMessages};
522
+ }
523
+ $('> *', errorBox).each(function(){
524
+ var name = getErrorName(this);
525
+ if(!errorMessages[name]){
526
+ extended = true;
527
+ errorMessages[name] = $(this).html();
528
+ }
529
+ });
530
+ if(extended){
531
+ $(elem).data('errormessage', errorMessages);
532
+ }
533
+ };
534
+ })(),
484
535
  get: function(elem, fieldWrapper){
485
536
  if(!fieldWrapper){
486
537
  fieldWrapper = this.getFieldWrapper(elem);
@@ -488,9 +539,11 @@ webshims.register('form-validation', function($, webshims, window, document, und
488
539
  var errorBox = fieldWrapper.data('errorbox');
489
540
  if(!errorBox){
490
541
  errorBox = this.create(elem, fieldWrapper);
542
+ this._createContentMessage(elem, errorBox);
491
543
  } else if(typeof errorBox == 'string'){
492
544
  errorBox = $('#'+errorBox);
493
545
  fieldWrapper.data('errorbox', errorBox);
546
+ this._createContentMessage(elem, errorBox);
494
547
  }
495
548
  return errorBox;
496
549
  },
@@ -498,7 +551,7 @@ webshims.register('form-validation', function($, webshims, window, document, und
498
551
  var type = $.prop(elem, 'type');
499
552
  var check = function(){
500
553
  var hasVal = checkTypes[type] ? $.prop(elem, 'checked') : $(elem).val();
501
- fieldWrapper[hasVal ? 'addClass' : 'removeClass']('ws-success');
554
+ fieldWrapper[hasVal ? 'addClass' : 'removeClass'](successWrapperClass);
502
555
  };
503
556
  var evt = changeTypes[type] ? 'change' : 'blur';
504
557
 
@@ -507,13 +560,13 @@ webshims.register('form-validation', function($, webshims, window, document, und
507
560
  },
508
561
  hideError: function(elem, reset){
509
562
  var fieldWrapper = this.getFieldWrapper(elem);
510
- var errorBox = fieldWrapper.data('errorbox');
563
+ var errorBox = fieldWrapper.hasClass(invalidWrapperClass) ? this.get(elem, fieldWrapper) : fieldWrapper.data('errorbox');
511
564
 
512
565
  if(errorBox && errorBox.jquery){
513
- fieldWrapper.removeClass('ws-invalid');
566
+ fieldWrapper.removeClass(invalidWrapperClass);
514
567
  errorBox.message = '';
515
568
  $(elem).filter('input').off('.recheckinvalid');
516
- errorBox.slideUp(function(){
569
+ errorBox[fx[options.iVal.fx].hide](function(){
517
570
  $(this).attr({hidden: 'hidden'});
518
571
  });
519
572
  }
@@ -528,21 +581,28 @@ webshims.register('form-validation', function($, webshims, window, document, und
528
581
  var throttle = function(){
529
582
  switchValidityClass({type: 'input', target: input});
530
583
  };
531
- $(input).filter('input:not([type="checkbox"], [type="radio"])').off('.recheckinvalid').on('input.recheckinvalid', function(){
532
- clearTimeout(timer);
533
- timer = setTimeout(throttle, options.iVal.recheckDelay);
534
- });
584
+ $(input)
585
+ .filter('input:not([type="checkbox"], [type="radio"])')
586
+ .off('.recheckinvalid')
587
+ .on('input.recheckinvalid', function(){
588
+ clearTimeout(timer);
589
+ timer = setTimeout(throttle, options.iVal.recheckDelay);
590
+ })
591
+ .on('focusout.recheckinvalid', function(){
592
+ clearTimeout(timer);
593
+ })
594
+ ;
535
595
  }
536
596
  },
537
- showError: function(elem, message){
597
+ showError: function(elem){
538
598
  var fieldWrapper = this.getFieldWrapper(elem);
539
599
  var box = this.get(elem, fieldWrapper);
540
-
600
+ var message = $(elem).getErrorMessage();
541
601
  if(box.message != message){
542
602
  box.stop(true, true).html('<p>'+ message +'</p>');
543
603
  box.message = message;
544
- fieldWrapper.addClass('ws-invalid').removeClass('ws-success');
545
- if(box.is('[hidden]')){
604
+ fieldWrapper.addClass(invalidWrapperClass).removeClass(successWrapperClass);
605
+ if(box.is('[hidden]') || box.css('display') == 'none'){
546
606
  this.recheckInvalidInput(elem);
547
607
  box
548
608
  .css({display: 'none'})
@@ -551,20 +611,19 @@ webshims.register('form-validation', function($, webshims, window, document, und
551
611
  ;
552
612
  }
553
613
  }
554
- fieldWrapper.removeClass('ws-success');
614
+ fieldWrapper.removeClass(successWrapperClass);
555
615
  $(elem).off('.recheckvalid');
556
616
 
557
617
  return fieldWrapper;
558
618
  },
559
619
  reset: function(elem){
560
- this.hideError(elem, true).removeClass('ws-success');
620
+ this.hideError(elem, true).removeClass(successWrapperClass);
561
621
  },
562
622
  toggle: function(elem){
563
- var message = $(elem).getErrorMessage();
564
- if(message){
565
- this.showError(elem, message);
623
+ if($(elem).is(':invalid')){
624
+ this.showError(elem);
566
625
  } else {
567
- this.hideError(elem, message);
626
+ this.hideError(elem);
568
627
  }
569
628
  }
570
629
  };
@@ -599,7 +658,7 @@ webshims.register('form-validation', function($, webshims, window, document, und
599
658
  }
600
659
  },
601
660
  submit: function(e){
602
- if(options.iVal.sel && $(e.target).is(options.iVal.sel) && $.prop(e.target, 'noValidate') && !$(e.target).checkValidity()){
661
+ if(options.iVal.sel && !options.iVal.noSubmitCheck &&$(e.target).is(options.iVal.sel) && $.prop(e.target, 'noValidate') && !$(e.target).checkValidity()){
603
662
  e.stopImmediatePropagation();
604
663
  return false;
605
664
  }
@@ -609,6 +668,58 @@ webshims.register('form-validation', function($, webshims, window, document, und
609
668
 
610
669
  webshims.modules["form-core"].getGroupElements = getGroupElements;
611
670
 
671
+
672
+ if(options.replaceValidationUI){
673
+ webshims.ready('DOM forms', function(){
674
+ $(document).on('firstinvalid', function(e){
675
+ if(!e.isInvalidUIPrevented()){
676
+ e.preventDefault();
677
+ webshims.validityAlert.showFor( e.target );
678
+ }
679
+ });
680
+ });
681
+ }
682
+
683
+ /* extension, but also used to fix native implementation workaround/bugfixes */
684
+ (function(){
685
+ var firstEvent,
686
+ invalids = [],
687
+ stopSubmitTimer,
688
+ form
689
+ ;
690
+
691
+ $(document).on('invalid', function(e){
692
+ if(e.wrongWebkitInvalid){return;}
693
+ var jElm = $(e.target);
694
+
695
+
696
+ if(!firstEvent){
697
+ //trigger firstinvalid
698
+ firstEvent = $.Event('firstinvalid');
699
+ firstEvent.isInvalidUIPrevented = e.isDefaultPrevented;
700
+ var firstSystemInvalid = $.Event('firstinvalidsystem');
701
+ $(document).triggerHandler(firstSystemInvalid, {element: e.target, form: e.target.form, isInvalidUIPrevented: e.isDefaultPrevented});
702
+ jElm.trigger(firstEvent);
703
+ }
704
+
705
+ //if firstinvalid was prevented all invalids will be also prevented
706
+ if( firstEvent && firstEvent.isDefaultPrevented() ){
707
+ e.preventDefault();
708
+ }
709
+ invalids.push(e.target);
710
+ e.extraData = 'fix';
711
+ clearTimeout(stopSubmitTimer);
712
+ stopSubmitTimer = setTimeout(function(){
713
+ var lastEvent = {type: 'lastinvalid', cancelable: false, invalidlist: $(invalids)};
714
+ //reset firstinvalid
715
+ firstEvent = false;
716
+ invalids = [];
717
+ $(e.target).trigger(lastEvent, [lastEvent]);
718
+ }, 9);
719
+ jElm = null;
720
+ });
721
+ })();
722
+
612
723
  //see: https://bugs.webkit.org/show_bug.cgi?id=113377
613
724
  if (chromeBugs && webkitVersion < 540) {
614
725
  (function(){
@@ -649,7 +760,16 @@ webshims.register('form-validators', function($, webshims, window, document, und
649
760
  var onEventTest = function(e){
650
761
  webshims.refreshCustomValidityRules(e.target);
651
762
  };
652
-
763
+ var noValidate = function(){
764
+ return !noValidate.types[this.type];
765
+ };
766
+ noValidate.types = {
767
+ hidden: 1,
768
+ image: 1,
769
+ button: 1,
770
+ reset: 1,
771
+ submit: 1
772
+ };
653
773
 
654
774
  webshims.customErrorMessages = {};
655
775
  webshims.addCustomValidityRule = function(name, test, defaultMessage){
@@ -658,68 +778,78 @@ webshims.register('form-validators', function($, webshims, window, document, und
658
778
  webshims.customErrorMessages[name] = [];
659
779
  webshims.customErrorMessages[name][''] = defaultMessage || name;
660
780
  }
661
- if($.isReady && formReady){
662
- $('input, select, textarea').each(function(){
663
- testValidityRules(this);
664
- });
781
+ if(formReady){
782
+ $('input, select, textarea')
783
+ .filter(noValidate)
784
+ .each(function(){
785
+ testValidityRules(this);
786
+ })
787
+ ;
665
788
  }
666
789
  };
667
790
  webshims.refreshCustomValidityRules = function(elem){
668
- if(!elem.form || (!initTest && !$.prop(elem, 'willValidate')) ){return;}
669
- blockCustom = true;
670
- var customMismatchedRule = $.data(elem, 'customMismatchedRule');
791
+ if(!initTest){return;}
792
+
793
+ var data = $(elem).data() || $.data(elem, {});
794
+ var customMismatchedRule = data.customMismatchedRule;
671
795
  var validity = $.prop(elem, 'validity') || {};
672
796
  var message = '';
673
- if(customMismatchedRule || !validity.customError){
797
+ var setMessage = function(message, errorType){
798
+ blockCustom = true;
799
+ data.customMismatchedRule = message ? errorType : '';
800
+
801
+ if(typeof message != 'string'){
802
+ message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || webshims.customErrorMessages[errorType][webshims.activeLang()] || webshims.customErrorMessages[errorType][''];
803
+ }
804
+
805
+ if(typeof message == 'object'){
806
+ message = message[errorType] || message.customError || message.defaultMessage;
807
+ }
808
+ $(elem).setCustomValidity(message);
809
+ blockCustom = false;
810
+ };
811
+ if(customMismatchedRule || validity.valid || (data.dependentValidation && !data.dependentValidation._init)){
674
812
  var val = $(elem).val();
675
813
  $.each(customValidityRules, function(name, test){
676
- message = test(elem, val) || '';
814
+ message = test(elem, val, data, setMessage) || '';
677
815
  customMismatchedRule = name;
678
816
  if(message){
679
-
680
- if(typeof message != 'string'){
681
- message = $(elem).data('errormessage') || elem.getAttribute('x-moz-errormessage') || webshims.customErrorMessages[name][webshims.activeLang()] || webshims.customErrorMessages[name][''];
682
- }
683
-
684
- if(typeof message == 'object'){
685
- message = message[name] || message.customError || message.defaultMessage;
686
- }
687
817
  return false;
688
818
  }
689
819
  });
690
-
691
- if(message){
692
- $.data(elem, 'customMismatchedRule', customMismatchedRule);
820
+ if(message != 'async'){
821
+ setMessage(message, customMismatchedRule);
693
822
  }
694
- $(elem).setCustomValidity(message);
695
823
  }
696
- blockCustom = false;
824
+ return message;
697
825
  };
698
826
  var testValidityRules = webshims.refreshCustomValidityRules;
699
827
 
700
828
  webshims.ready('forms form-validation', function(){
701
829
 
702
-
703
- var oldCustomValidity = $.fn.setCustomValidity;
704
-
705
-
706
- $.fn.setCustomValidity = function(message){
707
- if(!blockCustom){
708
- this.data('customMismatchedRule', '');
830
+ $.propHooks.setCustomValidity = {
831
+ get: function(elem){
832
+ if(!blockCustom){
833
+ $.data(elem, 'customMismatchedRule', '');
834
+ }
835
+ return null;
709
836
  }
710
- return oldCustomValidity.apply(this, arguments);
711
837
  };
712
838
 
839
+
713
840
  setTimeout(function(){
714
841
  webshims.addReady(function(context, selfElement){
715
842
  initTest = true;
716
- $('input, select, textarea', context).add(selfElement.filter('input, select, textarea')).each(function(){
717
- testValidityRules(this);
718
- });
719
- initTest = false;
843
+ $('input, select, textarea', context).add(selfElement.filter('input, select, textarea'))
844
+ .filter(noValidate)
845
+ .each(function(){
846
+ testValidityRules(this);
847
+ })
848
+ ;
849
+
720
850
  formReady = true;
721
851
  });
722
- $(document).on('refreshCustomValidityRules change', onEventTest);
852
+ $(document).on('refreshCustomValidityRules', onEventTest);
723
853
  }, 9);
724
854
 
725
855
  });
@@ -737,17 +867,20 @@ webshims.register('form-validators', function($, webshims, window, document, und
737
867
  */
738
868
  (function(){
739
869
 
740
- var addCustomValidityRule = $.webshims.addCustomValidityRule;
741
- addCustomValidityRule('partialPattern', function(elem, val){
742
- if(!val || !elem.getAttribute('data-partial-pattern')){return;}
743
- var pattern = $(elem).data('partial-pattern');
744
- if(!pattern){return;}
870
+ var addCustomValidityRule = webshims.addCustomValidityRule;
871
+ var getId = function(name){
872
+ return document.getElementById(name);
873
+ };
874
+ addCustomValidityRule('partialPattern', function(elem, val, pattern){
875
+ pattern = pattern.partialPattern;
876
+ if(!val || !pattern){return;}
745
877
  return !(new RegExp('(' + pattern + ')', 'i').test(val));
746
878
  }, 'This format is not allowed here.');
747
879
 
748
- addCustomValidityRule('tooShort', function(elem, val){
749
- if(!val || !elem.getAttribute('data-minlength')){return;}
750
- return $(elem).data('minlength') > val.length;
880
+
881
+ addCustomValidityRule('tooShort', function(elem, val, data){
882
+ if(!val || !data.minlength){return;}
883
+ return data.minlength > val.length;
751
884
  }, 'Entered value is too short.');
752
885
 
753
886
  var groupTimer = {};
@@ -765,7 +898,7 @@ webshims.register('form-validators', function($, webshims, window, document, und
765
898
  .unbind('click.groupRequired')
766
899
  .bind('click.groupRequired', function(){
767
900
  checkboxes.filter('.group-required').each(function(){
768
- $.webshims.refreshCustomValidityRules(this);
901
+ webshims.refreshCustomValidityRules(this);
769
902
  });
770
903
  })
771
904
  ;
@@ -804,19 +937,16 @@ webshims.register('form-validators', function($, webshims, window, document, und
804
937
  var getGroupElements = function(elem) {
805
938
  return $(elem.form[elem.name]).filter('[type="radio"]');
806
939
  };
807
- $.webshims.ready('form-validation', function(){
808
- if($.webshims.modules){
809
- getGroupElements = $.webshims.modules["form-core"].getGroupElements || getGroupElements;
940
+ webshims.ready('form-validation', function(){
941
+ if(webshims.modules){
942
+ getGroupElements = webshims.modules["form-core"].getGroupElements || getGroupElements;
810
943
  }
811
944
  });
812
945
 
813
- addCustomValidityRule('dependent', function(elem, val){
814
-
815
- if( !elem.getAttribute('data-dependent-validation') ){return;}
816
-
817
- var data = $(elem).data('dependentValidation');
946
+ addCustomValidityRule('dependent', function(elem, val, data){
947
+ data = data.dependentValidation;
948
+ if( !data ){return;}
818
949
  var specialVal;
819
- if(!data){return;}
820
950
  var depFn = function(e){
821
951
  var val = $.prop(data.masterElement, data["from-prop"]);
822
952
  if(specialVal){
@@ -865,7 +995,7 @@ webshims.register('form-validators', function($, webshims, window, document, und
865
995
  $(data.masterElement.type === 'radio' && getGroupElements(data.masterElement) || data.masterElement).bind('change', depFn);
866
996
  } else {
867
997
  $(data.masterElement).bind('change', function(){
868
- $.webshims.refreshCustomValidityRules(elem);
998
+ webshims.refreshCustomValidityRules(elem);
869
999
  $(elem).getShadowElement().filter('.user-error, .user-success').trigger('refreshvalidityui');
870
1000
  });
871
1001
  }
@@ -879,6 +1009,121 @@ webshims.register('form-validators', function($, webshims, window, document, und
879
1009
  }
880
1010
 
881
1011
  }, 'The value of this field does not repeat the value of the other field');
1012
+
1013
+
1014
+ if(window.JSON){
1015
+ addCustomValidityRule('ajaxvalidate', function(elem, val, data){
1016
+ if(!val || !data.ajaxvalidate){return;}
1017
+ var opts;
1018
+ if(!data.remoteValidate){
1019
+ if(typeof data.ajaxvalidate == 'string'){
1020
+ data.ajaxvalidate = {url: data.ajaxvalidate, depends: $([])};
1021
+ } else {
1022
+ data.ajaxvalidate.depends = data.ajaxvalidate.depends ? $(data.ajaxvalidate.depends).map(getId) : $([]);
1023
+ }
1024
+
1025
+ data.ajaxvalidate.depends.on('refreshCustomValidityRules', function(){
1026
+ webshims.refreshCustomValidityRules(elem);
1027
+ });
1028
+
1029
+ opts = data.ajaxvalidate;
1030
+
1031
+ var remoteValidate = {
1032
+ ajaxLoading: false,
1033
+ restartAjax: false,
1034
+ message: 'async',
1035
+ cache: {},
1036
+ update: function(remoteData){
1037
+ if(this.ajaxLoading){
1038
+ this.restartAjax = remoteData;
1039
+ } else {
1040
+ this.restartAjax = false;
1041
+ this.ajaxLoading = true;
1042
+ $.ajax(
1043
+ $.extend({}, opts, {
1044
+ url: opts.url,
1045
+ dataType: 'json',
1046
+ depData: remoteData,
1047
+ data: opts.fullForm ?
1048
+ $(elem).jProp('form').serializeArray() :
1049
+ remoteData,
1050
+ success: this.getResponse,
1051
+ complete: this._complete
1052
+ })
1053
+ );
1054
+ }
1055
+ },
1056
+ _complete: function(){
1057
+ remoteValidate.ajaxLoading = false;
1058
+ if(remoteValidate.restartAjax){
1059
+ this.update(remoteValidate.restartAjax);
1060
+ }
1061
+ remoteValidate.restartAjax = false;
1062
+ },
1063
+ getResponse: function(data){
1064
+ var old = webshims.refreshCustomValidityRules;
1065
+ if(!data){
1066
+ data = {message: '', valid: true};
1067
+ } else if(typeof data == 'string'){
1068
+ data = JSON.parse(data);
1069
+ }
1070
+
1071
+ remoteValidate.message = ('message' in data) ? data.message : !data.valid;
1072
+ remoteValidate.lastMessage = remoteValidate.message;
1073
+ remoteValidate.blockUpdate = true;
1074
+ $(elem).triggerHandler('refreshvalidityui');
1075
+ remoteValidate.message = 'async';
1076
+ remoteValidate.blockUpdate = false;
1077
+ },
1078
+ getData: function(){
1079
+ var data;
1080
+ data = {};
1081
+ data[$.prop(elem, 'name') || $.prop(elem, 'id')] = $(elem).val();
1082
+ opts.depends.each(function(){
1083
+ if($(this).is(':invalid')){
1084
+ data = false;
1085
+ return false;
1086
+ }
1087
+ data[$.prop(this, 'name') || $.prop(this, 'id')] = $(this).val();
1088
+ });
1089
+ return data;
1090
+ },
1091
+ getTempMessage: function(){
1092
+ var message = 'async';
1093
+ var remoteData, dataStr;
1094
+ if(!data.remoteValidate.blockUpdate){
1095
+ remoteData = this.getData();
1096
+ if(!remoteData){
1097
+ message = '';
1098
+ } else {
1099
+ try {
1100
+ dataStr = JSON.stringify(remoteData);
1101
+ } catch(er){}
1102
+
1103
+ if(dataStr === this.lastString){
1104
+ message = this.ajaxLoading ? 'async' : this.lastMessage;
1105
+ } else {
1106
+ this.lastString = dataStr;
1107
+ this.lastMessage = 'async';
1108
+ clearTimeout(data.remoteValidate.timer);
1109
+ data.remoteValidate.timer = setTimeout(function(){
1110
+ data.remoteValidate.update(remoteData);
1111
+ }, 9);
1112
+ }
1113
+
1114
+ }
1115
+ } else {
1116
+ message = remoteValidate.message;
1117
+ }
1118
+ return message;
1119
+ }
1120
+ };
1121
+ data.remoteValidate = remoteValidate;
1122
+ }
1123
+
1124
+ return data.remoteValidate.getTempMessage();
1125
+ }, 'remote error');
1126
+ }
882
1127
  })();
883
1128
 
884
1129
  });