Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 013881acb6911d772c841252036d88667e2edb7f 0 parents
@akaspin authored
1  .gitignore
@@ -0,0 +1 @@
+/.project
445 jquery.f5.js
@@ -0,0 +1,445 @@
+/**
+ * html5 forms module. Yep it's another bicycle.
+ * Dependencies: jQuery
+ */
+
+(function($) {
+ /**
+ * Test for native host method
+ */
+ var isHostMethod = function(o, m) {
+ var t = typeof o[m], reFeaturedMethod =
+ new RegExp('^function|object$', 'i');
+ return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown');
+ };
+
+ var isTypeSupported = function(o, t) {
+ o.setAttribute('type', t);
+ return o.type !== "text";
+ };
+
+ // All tests here
+ var prey = document.createElement("input"); // Our prey
+ var isNative = {
+ inputType : {
+ email : isTypeSupported(prey, 'email'),
+ url : isTypeSupported(prey, 'url'),
+ number : isTypeSupported(prey, 'number'),
+ date : isTypeSupported(prey, 'date'),
+ date : isTypeSupported(prey, 'range')
+ },
+ inputAttr : {
+ placeholder : !!("placeholder" in prey),
+ required : !!('required' in prey),
+ pattern : !!('pattern' in prey),
+ min : !!('min' in prey),
+ max : !!('max' in prey)
+ },
+ hostMethod : {
+ validity : isHostMethod(prey, 'validity'),
+ checkValidity : isHostMethod(prey, 'checkValidity'),
+ setCustomValidity : isHostMethod(prey, 'setCustomValidity')
+ }
+ };
+
+ /**
+ * Placeholder setup. Sorry it's formely copy-paste from
+ * awesome http://github.com/danielstocks/jQuery-Placeholder.
+ * Thank's Daniel Stocks.
+ * But I don't need many bindings to submit.
+ */
+ var setupPlaceholder = (function() {
+ if (!isNative.inputAttr.placeholder) {
+ /**
+ * Placeholder object.
+ */
+ var Placeholder = function(input) {
+ this.input = input;
+ if (input.attr('type') == 'password') {
+ this.handlePassword();
+ }
+ }
+
+ Placeholder.prototype = {
+ show : function(loading) {
+ // FF and IE saves values when you refresh the page.
+ // If the user refreshes the page with
+ // the placeholders showing they will be the default
+ // values and the input fields won't be empty.
+ if (this.input[0].value === ''
+ || (loading && this.valueIsPlaceholder())) {
+ if (this.isPassword) {
+ try {
+ this.input[0].setAttribute('type', 'text');
+ } catch (e) {
+ this.input.before(this.fakePassword.show())
+ .hide();
+ }
+ }
+ this.input.addClass('placeholder');
+ this.input[0].value = this.input.attr('placeholder');
+ }
+ },
+ hide : function() {
+ if (this.valueIsPlaceholder()
+ && this.input.hasClass('placeholder')) {
+ this.input.removeClass('placeholder');
+ this.input[0].value = '';
+ if (this.isPassword) {
+ try {
+ this.input[0].setAttribute('type', 'password');
+ } catch (e) { }
+ // Restore focus for Opera and IE
+ this.input.show();
+ this.input[0].focus();
+ }
+ }
+ },
+ valueIsPlaceholder : function() {
+ return this.input[0].value ==
+ this.input.attr('placeholder');
+ },
+ handlePassword: function() {
+ var input = this.input;
+ input.attr('realType', 'password');
+ this.isPassword = true;
+ // IE < 9 doesn't allow changing the type
+ // of password inputs
+ if ($.browser.msie && input[0].outerHTML) {
+ var fakeHTML = $(input[0].outerHTML.replace(
+ /type=(['"])?password\1/gi, 'type=$1text$1'));
+ this.fakePassword = fakeHTML.val(
+ input.attr('placeholder'))
+ .addClass('placeholder').focus(function() {
+ input.trigger('focus');
+ $(this).hide();
+ });
+ $(input[0].form).submit(function() {
+ fakeHTML.remove();
+ input.show()
+ });
+ }
+ }
+ };
+
+ // Setup all placeholder bindings if needed
+ return function($$, opts) {
+ var domField = $$.get(0);
+ if ($$.attr('placeholder')) {
+ // Setup
+ domField.control.value = function() {
+ var phVal = $$.attr('placeholder');
+ var val = $$.val();
+ return (!!phVal
+ && $$.hasClass(opts.classes.placeholder)
+ && val === phVal) ? "" : val;
+ }
+
+ var placeholder = new Placeholder($$);
+ placeholder.show(true);
+ $$.focus(function() {
+ placeholder.hide();
+ })
+ .blur(function() {
+ placeholder.show(false);
+ });
+
+ // On page refresh, IE doesn't re-populate user input
+ // until the window.onload event is fired.
+
+ if ($.browser.msie) {
+ $(window).load(function() {
+ if($$.val()) {
+ $$.removeClass("placeholder");
+ }
+ placeholder.show(true);
+ });
+ // What's even worse, the text cursor disappears
+ // when tabbing between text inputs, here's a fix
+ $$.focus(function() {
+ if(this.value == "") {
+ var range = this.createTextRange();
+ range.collapse(true);
+ range.moveStart('character', 0);
+ range.select();
+ }
+ });
+ }
+ } else {
+ domField.control.value = function() {
+ return domField.value;
+ };
+ }
+ }
+ } else {
+ // Ok just setup .control.value() function
+ return function ($$, opts) {
+ $$.get(0).control.value = function() {
+ return $$.get(0).value;
+ };
+ }
+ }
+ })();
+
+ /**
+ * Low level field setup
+ * @returns Setup function
+ */
+ var lowSetupField = (function() {
+ if (!isNative.hostMethod.validity) {
+ // Hard work no HTML5 Forms support
+ var isPattern = function(value, pattern) {
+ return pattern.test(value);
+ };
+
+ var patterns = {
+ 'email' : new RegExp("^[a-z0-9_.%+-]+@[0-9a-z.-]"
+ + "+\\.[a-z.]{2,6}$", "i"),
+ 'url' : new RegExp("[a-z][-\.+a-z]*:\/\/", "i")
+ };
+
+ return function($$, opts) {
+ var domField = $$.get(0);
+ var fieldType = domField.getAttribute('type');
+
+ // Basic validity object and message
+ domField.validationMessage = '';
+ domField.validity = {
+ customError : false,
+ patternMismatch : false,
+ rangeOverflow : false,
+ rangeUnderflow : false,
+ stepMismatch : false,
+ tooLong : false,
+ typeMismatch : false,
+ valid : true,
+ valueMissing : false
+ };
+
+ // All possible checks
+ var all = [
+ { // Custom error
+ check : true,
+ op : function() {
+ if (domField.validity.customError) {
+ return domField.validationMessage;
+ }
+ }
+ },
+ { // Required
+ check : $$.attr('required') !== undefined,
+ op : function() {
+ if (domField.control.value() === "") {
+ domField.validity.valueMissing = true;
+ return opts.messages.required;
+ } else {
+ domField.validity.valueMissing = false;
+ }
+ }
+ },
+ { // E-mail
+ check : fieldType === 'email',
+ op : function() {
+ var val = domField.control.value();
+ if (!isPattern(val, patterns.email) && val !== "") {
+ domField.validity.typeMismatch = true;
+ return opts.messages.email;
+ } else {
+ domField.validity.typeMismatch = false;
+ }
+ }
+ },
+ { // URL
+ check : fieldType === 'url',
+ op : function() {
+ var val = domField.control.value();
+ if (!isPattern(val, patterns.url) && val !== "") {
+ domField.validity.typeMismatch = true;
+ return opts.messages.url;
+ } else {
+ domField.validity.typeMismatch = false;
+ }
+ }
+ },
+ { // Number
+ check : fieldType === 'number',
+ op : function() {
+ var val = domField.control.value();
+ if (isNaN(val) && val !== "") {
+ domField.validity.typeMismatch = true;
+ return opts.messages.number;
+ } else {
+ domField.validity.typeMismatch = false;
+ }
+ }
+ },
+ { // Pattern
+ check : $$.attr('pattern') !== undefined,
+ op : function() {
+ var val = domField.control.value();
+ var pattern = new RegExp($$.attr('pattern'));
+ if (!pattern.test(val) && val !== "") {
+ domField.validity.patternMismatch = true;
+ return opts.messages.pattern;
+ } else {
+ domField.validity.patternMismatch = false;
+ }
+ }
+ }
+ ];
+
+ // Filter checks for field
+ var chain = [];
+ for ( var i = 0; i < all.length; i++) {
+ if (all[i].check)
+ chain.push(all[i].op);
+ }
+
+ /**
+ * Validate function
+ */
+ var validate = domField.control.validate = function() {
+ // Fire all checks
+ var msg = undefined;
+ for ( var i = 0; i < chain.length; i++) {
+ var lastMsg = chain[i]();
+ if (!!lastMsg && !!!msg) {
+ msg = lastMsg;
+ }
+ }
+
+ // Set validity and validation message
+ domField.validationMessage = msg || "";
+ domField.validity.valid = (
+ !domField.validity.customError
+ && !domField.validity.valueMissing
+ && !domField.validity.tooLong
+ && !domField.validity.typeMismatch
+ && !domField.validity.patternMismatch
+ && !domField.validity.rangeOverflow
+ && !domField.validity.rangeUnderflow
+ && !domField.validity.stepMismatch);
+
+ // And set needed classes
+ if (domField.validity.valid) {
+ $$.removeClass(opts.classes.invalid)
+ .addClass(opts.classes.valid);
+ } else {
+ $$.removeClass(opts.classes.valid)
+ .addClass(opts.classes.invalid);
+ }
+ };
+
+ // Bind and validate
+ $$.bind('keyup focus blur', validate);
+ domField.control.validate();
+
+ // Define setCustomValidity method
+ if (!isNative.hostMethod.setCustomValidity) {
+ domField.setCustomValidity = function(msg) {
+ domField.validity.customError = !!msg;
+ domField.validationMessage = msg || '';
+ domField.control.validate();
+ }
+ }
+
+ // Define checkValidity method
+ if (!isNative.hostMethod.checkValidity) {
+ domField.checkValidity = function() {
+ $$.trigger('invalid');
+ return domField.validity.valid;
+ }
+ }
+ };
+ } else {
+ return function() {}
+ }
+ })();
+
+ $.fn.f5 = function(options) {
+ var settings = {
+ submit : function() { // Submit
+ return true;
+ },
+ validators : {}, // Validators
+ poll : 300, // Poll time in milliseconds
+ classes : {
+ valid : 'valid',
+ invalid : 'invalid',
+ required : 'required',
+ placeholder : 'placeholder',
+ pending : 'pending'
+ },
+ messages : {
+ required : "Please fill out this field.",
+ pattern : "Please match the requested format.",
+ email : "Please enter an email address.",
+ url : "Please enter URL",
+ number : "Please enter numeric value",
+ max : "Value too large",
+ min : "Value too small"
+ }
+ };
+
+ if (options) {
+ $.extend(true, settings, options);
+ }
+
+ return this.filter('form').each(function() {
+ var $form = $(this);
+
+ // if already binded - do nothing
+ if ($form.data('f5'))
+ return;
+
+ $form.data('f5', {
+ members : []
+ });
+
+ $(':input:not(:submit):not(:reset)', $form).each( function() {
+ var $field = $(this); // jQuery
+
+ // Control object
+ $field.get(0).control = {};
+
+ setupPlaceholder($field, settings);
+ lowSetupField($field, settings);
+ });
+
+ // Setup form checkValidity
+ if (!isHostMethod($form.get(0), 'checkValidity')) {
+ var domForm = $form.get(0);
+ domForm.checkValidity = function() {
+ var first = true;
+ $(':input:not(:submit):not(:reset)',
+ $form).each(function() {
+ if (!$(this).get(0).checkValidity())
+ all = false;
+ });
+ return all;
+ };
+
+ // And bind on submit
+ $form.bind('submit', function() {
+ // Check states
+ var invalidFields = $(':input:not(:submit):not(:reset)',
+ $form).filter( function() {
+ return !$(this).get(0).validity.valid;
+ });
+ if (invalidFields.length == 0) {
+ $(':input:not(:submit):not(:reset)',
+ $form).each( function() {
+ $this = $(this);
+ $this.val($this.get(0).control.value());
+ });
+ return true;
+ } else {
+ invalidFields.filter(':first').focus();
+ domForm.checkValidity();
+ return false;
+ }
+ });
+ }
+ });
+ };
+})(jQuery);
3  jquery.f51.js
@@ -0,0 +1,3 @@
+(function($) {
+
+})(jQuery);
154 jquery.f52.js
@@ -0,0 +1,154 @@
+(function($) {
+
+ /**
+ * Get field value. Regardless of placeholder.
+ */
+ var getValue = function(el, settings) {
+ if (el.hasClass(settings.options.placeholderClass) &&
+ el.attr('placeholder') == el.val()) {
+ return "";
+ } else {
+ return el.val();
+ }
+ }
+
+ var setupField = function($input, $form, settings) {
+ // Register
+ var formData = $form.data('f5');
+ if ($.inArray($input, formData.members) == -1) {
+ formData.members.push($input);
+ }
+
+ var op = settings.validators[$input.attr('validate')];
+
+ if (typeof op === 'function') {
+ $input.data('f5', {
+ value: undefined,
+ pending: false
+ });
+
+ $input.bind('validate', {op: op}, function(event) {
+ var $this = $(this);
+ var data = $this.data('f5');
+ var op = event.data.op;
+
+ // if validator is present
+ var val = getValue($this, settings);
+
+ if (val != data.value) {
+ // And value changed
+ data.value = val;
+
+ if (data.pending != false) {
+ clearTimeout(data.pending);
+ data.pending = false;
+ }
+
+ // Clear custom errors
+ if ($this.get(0).validity.customError) {
+ $this.get(0).setCustomValidity('');
+ }
+
+ if ($this.get(0).checkValidity()) {
+ $this.addClass(settings.options.pendingClass);
+
+ $this.get(0).setCustomValidity(
+ settings.options.pendingMessage);
+
+ $form.triggerHandler('f5_check');
+
+ data.pending = setTimeout(function() {
+ op(val, function(msg) {
+ if (val == getValue($this, settings)) {
+ data.pending = false;
+ $this.removeClass(
+ settings.options.pendingClass);
+ var message = msg || '';
+ $this.get(0).setCustomValidity(message);
+ $form.triggerHandler('f5_check');
+ }
+ });
+ }, settings.poll);
+ } else {
+ $form.triggerHandler('f5_check');
+ }
+ }
+ });
+ } else {
+ $input.bind('validate', function() {
+ $form.triggerHandler('f5_check');
+ });
+ }
+
+ $input.bind('keyup focus blur', function(event) {
+ $(this).triggerHandler('validate');
+ });
+
+ $input.triggerHandler('validate');
+ }
+
+ $.fn.f5 = function(options) {
+ var settings = {
+ submit: function() { // Submit
+ return true;
+ },
+ validators: {}, // Validators
+ poll: 300, // Poll time in milliseconds
+ options: { // H5F options
+ validClass: "valid",
+ invalidClass: "invalid",
+ requiredClass: "invalid",
+ placeholderClass: "placeholder",
+ pendingClass: "pending",
+ pendingMessage: "Requesting"
+ }
+ };
+
+ if (options) {
+ $.extend(true, settings, options);
+ }
+
+ return this.filter('form').each(function() {
+ var $form = $(this);
+
+ // if already binded - do nothing
+ if ($form.data('f5')) return;
+
+ $form.data('f5', { members: [] })
+
+ // Polyfill form with H5F
+ var formDom = $form.get(0);
+ H5F.setup(formDom, settings.options);
+
+
+ // Bind check events
+ $form.bind('f5_check', function() {
+ var $this = $(this);
+ var data = $this.data('f5');
+
+ for (var i = 0; i < data.members.length; i++) {
+ if (!data.members[i].get(0).checkValidity()) {
+ $(':submit', $this).attr("disabled", "true");
+ return;
+ }
+ }
+ $(':submit', $this).removeAttr("disabled");
+ });
+
+ // Bind submit
+ $form.bind('submit', function() {
+ $(':input:not(:submit):not(:reset)', $form).each(function() {
+ $el = $(this);
+ $el.val(getValue($el, settings));
+ })
+
+ return settings.submit.apply(this);
+ });
+
+ $(':input:not(:submit):not(:reset)', $form).each(function() {
+ var $this = $(this);
+ setupField($this, $form, settings);
+ })
+ });
+ };
+})(jQuery);
6 readme.md
@@ -0,0 +1,6 @@
+# jquery.f5
+
+Yep here is another bicycle for HTML 5 forms validation.
+
+## Features
+
100 test/form.css
@@ -0,0 +1,100 @@
+form {
+}
+
+fieldset {
+ border: 1px solid #CCC;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ width: 30%;
+ float: left;
+}
+
+label {
+ display: block;
+ margin-bottom: .3em;
+}
+
+input:focus {
+ font-weight: bold;
+}
+
+input[type=text],
+input[type=url],
+input[type=tel],
+input[type=number],
+input[type=color],
+input[type=email],
+input[type=password],
+textarea {
+ width: 96%;
+ margin: .3em 0 .3em 0;
+ padding: .3em;
+ border: 1px solid #CCC;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+button,
+input[type=submit],
+input[type=file] {
+ margin: .2em 0;
+ padding: .3em 1em;
+ font-family: sans-serif;
+ float:left;
+ clear: both;
+}
+
+input[type=text].invalid,
+input[type=email].invalid,
+input[type=password].invalid,
+input[type=url].invalid,
+input[type=number].invalid,
+textarea.invalid {
+ border-color: #DCC !important;
+}
+
+input[type=text]:invalid,
+input[type=email]:invalid,
+input[type=password]:invalid,
+input[type=url]:invalid,
+input[type=number]:invalid,
+textarea:invalid {
+ border-color: #DCC !important;
+}
+
+input:focus:invalid,
+textarea:focus:invalid {
+ background-color: #FFF9F9 !important;
+}
+
+input:focus:valid,
+textarea:focus:valid {
+ background-color: #F9FFF9 !important;
+}
+
+input[type=text].valid,
+input[type=email].valid,
+input[type=password].valid,
+input[type=url].valid,
+input[type=number].valid,
+textarea.valid {
+ border-color: #CDC !important;
+}
+
+input[type=text]:valid,
+input[type=email]:valid,
+input[type=password]:valid,
+input[type=url]:valid,
+input[type=number]:valid,
+textarea:valid {
+ border-color: #CDC !important;
+}
+.placeholder {
+ color: #777 !important;
+ background-image: none !important; /* Fix for opera */
+}
+input::-webkit-input-placeholder, input:-moz-placeholder {
+ color: #777 !important;
+}
315 test/lib/h5f.js
@@ -0,0 +1,315 @@
+/*
+ * HTML5 Forms Chapter JavaScript Library
+ * http://thecssninja.com/javascript/H5F
+ *
+ * Copyright (c) 2010 Ryan Seddon - http://thecssninja.com/
+ * Dual-licensed under the BSD and MIT licenses.
+ * http://thecssninja.com/H5F/license.txt
+ */
+
+var H5F = H5F || {};
+
+(function(d){
+
+ var field = d.createElement("input"),
+ emailPatt = new RegExp("^[a-z0-9_.%+-]+@[0-9a-z.-]+\\.[a-z.]{2,6}$","i"),
+ urlPatt = new RegExp("[a-z][-\.+a-z]*:\/\/","i"),
+ nodes = new RegExp("^(input|select|textarea)$","i"),
+ usrPatt, curEvt, args, custMsg = "";
+
+ H5F.setup = function(form,settings) {
+ var isCollection = !form.nodeType || false;
+
+ var opts = {
+ validClass : "valid",
+ invalidClass : "error",
+ requiredClass : "required",
+ placeholderClass : "placeholder"
+ };
+
+ if(typeof settings == "object") {
+ for (var i in opts) {
+ if(typeof settings[i] == "undefined") { settings[i] = opts[i]; }
+ }
+ }
+
+ args = settings || opts;
+
+ if(isCollection) {
+ for(var k=0,len=form.length;k<len;k++) {
+ H5F.validation(form[k]);
+ }
+ } else {
+ H5F.validation(form);
+ }
+ };
+
+ H5F.validation = function(form) {
+ var f = form.elements,
+ flen = f.length,
+ isRequired;
+
+ H5F.listen(form,"invalid",H5F.checkField,true);
+ H5F.listen(form,"blur",H5F.checkField,true);
+ H5F.listen(form,"input",H5F.checkField,true);
+ H5F.listen(form,"keyup",H5F.checkField,true);
+ H5F.listen(form,"focus",H5F.checkField,true);
+
+ if(!H5F.support()) {
+ form.checkValidity = function() { return H5F.checkValidity(form); };
+
+ while(flen--) {
+ isRequired = !!(f[flen].attributes["required"]);
+ // Firefox includes fieldsets inside elements nodelist so we filter it out.
+ if(f[flen].nodeName !== "FIELDSET") {
+ H5F.validity(f[flen]); // Add validity object to field
+ }
+ }
+ }
+ };
+ H5F.validity = function(el) {
+ var elem = el,
+ missing = H5F.valueMissing(elem),
+ type = elem.getAttribute("type"),
+ pattern = elem.getAttribute("pattern"),
+ placeholder = elem.getAttribute("placeholder"),
+ isType = /^(email|url)$/i,
+ evt = /^(input|keyup)$/i,
+ fType = ((isType.test(type)) ? type : ((pattern) ? pattern : false)),
+ patt = H5F.pattern(elem,fType),
+ step = H5F.range(elem,"step"),
+ min = H5F.range(elem,"min"),
+ max = H5F.range(elem,"max"),
+ customError = (custMsg !== "");
+
+ elem.checkValidity = function() { return H5F.checkValidity(elem); };
+ elem.setCustomValidity = function(msg) { H5F.setCustomValidity.call(elem,msg); };
+ elem.validationMessage = custMsg;
+
+ elem.validity = {
+ valueMissing: missing,
+ patternMismatch: patt,
+ rangeUnderflow: min,
+ rangeOverflow: max,
+ stepMismatch: step,
+ customError: customError,
+ valid: (!missing && !patt && !step && !min && !max && !customError)
+ };
+
+ if(placeholder && !evt.test(curEvt)) { H5F.placeholder(elem); }
+ };
+ H5F.checkField = function (e) {
+ var el = H5F.getTarget(e) || e, // checkValidity method passes element not event
+ events = /^(input|keyup|focusin|focus)$/i,
+ ignoredTypes = /^(submit|image|button|reset)$/i,
+ checkForm = true;
+
+ if(nodes.test(el.nodeName) && !(ignoredTypes.test(el.type) || ignoredTypes.test(el.nodeName))) {
+ curEvt = e.type;
+ if(!H5F.support()) { H5F.validity(el); }
+
+ if(el.validity.valid) {
+ H5F.removeClass(el,[args.invalidClass,args.requiredClass]);
+ H5F.addClass(el,args.validClass);
+ } else if(!events.test(curEvt)) {
+ if(el.validity.valueMissing) {
+ H5F.removeClass(el,[args.invalidClass,args.validClass]);
+ H5F.addClass(el,args.requiredClass);
+ } else {
+ H5F.removeClass(el,[args.validClass,args.requiredClass]);
+ H5F.addClass(el,args.invalidClass);
+ }
+ } else if(el.validity.valueMissing) {
+ H5F.removeClass(el,[args.requiredClass,args.invalidClass,args.validClass]);
+ }
+ if(curEvt === "input" && checkForm) {
+ // If input is triggered remove the keyup event
+ H5F.unlisten(el.form,"keyup",H5F.checkField,true);
+ checkForm = false;
+ }
+ }
+ };
+ H5F.checkValidity = function (el) {
+ var f, ff, isRequired, hasPattern, invalid = false;
+
+ if(el.nodeName === "FORM") {
+ f = el.elements;
+
+ for(var i = 0,len = f.length;i < len;i++) {
+ ff = f[i];
+
+ isRequired = !!(ff.attributes["required"]);
+ hasPattern = !!(ff.attributes["pattern"]);
+
+ if(ff.nodeName !== "FIELDSET" && (isRequired || hasPattern)) {
+ H5F.checkField(ff);
+ if(!ff.validity.valid && !invalid) {
+ ff.focus();
+ invalid = true;
+ }
+ }
+ }
+ return !invalid;
+ } else {
+ H5F.checkField(el);
+ return el.validity.valid;
+ }
+ };
+ H5F.setCustomValidity = function (msg) {
+ var el = this;
+ custMsg = msg;
+
+ el.validationMessage = custMsg;
+ };
+
+ H5F.support = function() {
+ return (H5F.isHostMethod(field,"validity") && H5F.isHostMethod(field,"checkValidity"));
+ };
+
+ // Create helper methods to emulate attributes in older browsers
+ H5F.pattern = function(el, type) {
+ if(type === "email") {
+ return !emailPatt.test(el.value);
+ } else if(type === "url") {
+ return !urlPatt.test(el.value);
+ } else if(!type) {
+ return false;
+ } else {
+ var placeholder = el.getAttribute("placeholder"),
+ val = el.value;
+
+ usrPatt = new RegExp('^(?:' + type + ')$');
+
+ if(val === placeholder) {
+ return true;
+ } else if(val === "") {
+ return false;
+ } else {
+ return !usrPatt.test(el.value);
+ }
+ }
+ };
+ H5F.placeholder = function(el) {
+ var placeholder = el.getAttribute("placeholder"),
+ focus = /^(focus|focusin|submit)$/i,
+ node = /^(input|textarea)$/i,
+ ignoredType = /^password$/i,
+ isNative = !!("placeholder" in field);
+
+ if(!isNative && node.test(el.nodeName) && !ignoredType.test(el.type)) {
+ if(el.value === "" && !focus.test(curEvt)) {
+ el.value = placeholder;
+ H5F.listen(el.form,'submit', function () {
+ curEvt = 'submit';
+ H5F.placeholder(el);
+ }, true);
+ H5F.addClass(el,args.placeholderClass);
+ } else if(el.value === placeholder && focus.test(curEvt)) {
+ el.value = "";
+ H5F.removeClass(el,args.placeholderClass);
+ }
+ }
+ };
+ H5F.range = function(el,type) {
+ // Emulate min, max and step
+ var min = parseInt(el.getAttribute("min"),10) || 0,
+ max = parseInt(el.getAttribute("max"),10) || false,
+ step = parseInt(el.getAttribute("step"),10) || 1,
+ val = parseInt(el.value,10),
+ mismatch = (val-min)%step;
+
+ if(!H5F.valueMissing(el) && !isNaN(val)) {
+ if(type === "step") {
+ return (el.getAttribute("step")) ? (mismatch !== 0) : false;
+ } else if(type === "min") {
+ return (el.getAttribute("min")) ? (val < min) : false;
+ } else if(type === "max") {
+ return (el.getAttribute("max")) ? (val > max) : false;
+ }
+ } else if(el.getAttribute("type") === "number") {
+ return true;
+ } else {
+ return false;
+ }
+ };
+ H5F.required = function(el) {
+ var required = !!(el.attributes["required"]);
+
+ return (required) ? H5F.valueMissing(el) : false;
+ };
+ H5F.valueMissing = function(el) {
+ var placeholder = el.getAttribute("placeholder"),
+ isRequired = !!(el.attributes["required"]);
+ return !!(isRequired && (el.value === "" || el.value === placeholder));
+ };
+
+ /* Util methods */
+ H5F.listen = function (node,type,fn,capture) {
+ if(H5F.isHostMethod(window,"addEventListener")) {
+ /* FF & Other Browsers */
+ node.addEventListener( type, fn, capture );
+ } else if(H5F.isHostMethod(window,"attachEvent") && typeof window.event !== "undefined") {
+ /* Internet Explorer way */
+ if(type === "blur") {
+ type = "focusout";
+ } else if(type === "focus") {
+ type = "focusin";
+ }
+ node.attachEvent( "on" + type, fn );
+ }
+ };
+ H5F.unlisten = function (node,type,fn,capture) {
+ if(H5F.isHostMethod(window,"removeEventListener")) {
+ /* FF & Other Browsers */
+ node.removeEventListener( type, fn, capture );
+ } else if(H5F.isHostMethod(window,"detachEvent") && typeof window.event !== "undefined") {
+ /* Internet Explorer way */
+ node.detachEvent( "on" + type, fn );
+ }
+ };
+ H5F.preventActions = function (evt) {
+ evt = evt || window.event;
+
+ if(evt.stopPropagation && evt.preventDefault) {
+ evt.stopPropagation();
+ evt.preventDefault();
+ } else {
+ evt.cancelBubble = true;
+ evt.returnValue = false;
+ }
+ };
+ H5F.getTarget = function (evt) {
+ evt = evt || window.event;
+ return evt.target || evt.srcElement;
+ };
+ H5F.addClass = function (e,c) {
+ var re;
+ if (!e.className) {
+ e.className = c;
+ }
+ else {
+ re = new RegExp('(^|\\s)' + c + '(\\s|$)');
+ if (!re.test(e.className)) { e.className += ' ' + c; }
+ }
+ };
+ H5F.removeClass = function (e,c) {
+ var re, m, arr = (typeof c === "object") ? c.length : 1, len = arr;
+ if (e.className) {
+ if (e.className == c) {
+ e.className = '';
+ }
+ else {
+ while(arr--) {
+ re = new RegExp('(^|\\s)' + ((len > 1) ? c[arr] : c) + '(\\s|$)');
+ m = e.className.match(re);
+ if (m && m.length == 3) { e.className = e.className.replace(re, (m[1] && m[2])?' ':''); }
+ }
+ }
+ }
+ };
+ H5F.isHostMethod = function(o, m) {
+ var t = typeof o[m], reFeaturedMethod = new RegExp('^function|object$', 'i');
+ return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown');
+ };
+
+})(document);
109 test/test.html
@@ -0,0 +1,109 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+
+<!--[if lt IE 9]>
+<script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script>
+<![endif]-->
+
+<link rel="stylesheet" href="form.css">
+
+<script type="text/javascript" src="http://yandex.st/jquery/1.5.2/jquery.min.js"></script>
+<script type="text/javascript" src="../jquery.f5.js"></script>
+
+<title>jquery.f5 Test</title>
+</head>
+
+<body>
+<h1>jquery.f5 Test</h1>
+
+<form id='f'>
+<fieldset><legend>Text</legend>
+ <label><input name='f1_1'
+ type='text'
+ placeholder="Unrestricted"></label>
+ <label>Required<input name='f1_2'
+ type='text'
+ required
+ placeholder="Required"></label>
+ <label>Pattern<input name='f1_3'
+ type='text'
+ pattern="^pattern$"
+ placeholder='Type "pattern"'></label>
+</fieldset>
+
+<fieldset><legend>E-Mail</legend>
+ <label><input name='f2_1'
+ type='email'
+ placeholder="Unrestricted"></label>
+ <label>Required<input name='f2_2'
+ type='email'
+ required
+ placeholder="Required"></label>
+</fieldset>
+
+<fieldset><legend>Password</legend>
+ <label><input name='f3_1'
+ type='password'
+ placeholder="Unrestricted">
+ </label>
+ <label>Required<input name='f3_2'
+ type='password'
+ required
+ placeholder="Required">
+ </label>
+</fieldset>
+
+<fieldset><legend>url</legend>
+ <label><input name='f4_1'
+ type='url'
+ placeholder="Unrestricted"></label>
+ <label>Required<input name='f4_2'
+ type='url'
+ required
+ placeholder="Required"></label>
+</fieldset>
+
+<fieldset><legend>number</legend>
+ <label><input name='f5_1'
+ type='number'
+ placeholder="Unrestricted"></label>
+ <label>required<input name='f5_2'
+ type='number'
+ required
+ placeholder="Required"></label>
+</fieldset>
+
+<fieldset><legend> textarea </legend>
+ <label>Textarea<textarea name='f20_1'
+ placeholder="Textarea"></textarea></label>
+ <label>Textarea, required<textarea name='f20_2'
+ required
+ placeholder="Required"></textarea></label>
+</fieldset>
+
+ <input type="submit" value="Submit">
+</form>
+
+<script type="text/javascript">
+$('#f').ready(function(){
+ $('#f').f5({
+ submit: function() {
+ console.log($(this).serialize());
+ return false;
+ },
+ validators: {
+ async: function(value, callback) {
+ setTimeout(function() {
+ console.log('checkAsync');
+ value == 'async' ? callback() : callback('Type async.')
+ }, 3000);
+ }
+ }
+ });
+});
+</script>
+</body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.