// FluxValidator - Ajax Form Validation for Rails // Copyright (c) 2007 Peter Gumeson // Contributors: // // FluxValidator is freely distributable under the terms of an MIT license // Project Home: http://fluxvalidator.googlecode.com if (typeof Prototype == 'undefined' || parseFloat(Prototype.Version) < 1.5) { alert('FluxValidator requires the Prototype javascript library version 1.5.0 or greater. ' + 'Check to make sure prototype.js is loaded before flux_validator.js'); } if (typeof LowPro == 'undefined' || parseFloat(LowPro.Version) < 0.4) { alert('FluxValidator requires the LowPro javascript library version 0.4 or greater. ' + 'Check to make sure lowpro.js is loaded before flux_validator.js'); } if (typeof Effect == 'undefined') { alert('FluxValidator requires the Scriptaculous javascript library. ' + 'Check to make sure effects.js is loaded before flux_validator.js'); } FluxValidator = { form: null, source: null, Base: { initialize : function(options) { this.options = Object.extend({ evaluateScripts: true }, options || {}); }, makeRequest : function(options) { if (options.update) new Ajax.Updater(options.update, options.url, options); else new Ajax.Request(options.url, options); return false; } } }; // Handle form validation FluxValidator.Validate = Behavior.create({ onchange : function(e) { FluxValidator.form = this.element; FluxValidator.source = Event.element(e).id.replace(/_([0-9]+)i$/, ''); var fieldSpan = $(FluxValidator.source+'_field'); if (fieldSpan != null) { if (!fieldSpan.hasClassName('fieldWithErrors') && !fieldSpan.hasClassName('fieldWithoutErrors')) { fieldSpan.addClassName('fieldWithoutErrors'); } } var errorSpan = $(FluxValidator.source+'_errors'); if (errorSpan != null) { if (!errorSpan.hasClassName('formErrors')) { errorSpan.addClassName('formErrors'); errorSpan.setStyle({display: 'none'}); } } var errorSpanHtml = ''; var elementType = Event.element(e).type; if (elementType == 'radio' || elementType == 'checkbox') { if (errorSpan == null) { nextSibling = Event.element(e).up().next(); if (elementType == 'checkbox' && nextSibling.type == 'hidden') { nextSibling = nextSibling.next(); } if (nextSibling != undefined ) { if( nextSibling.tagName == 'BR') { new Insertion.After(nextSibling, errorSpanHtml); } else { new Insertion.Before(nextSibling, errorSpanHtml); } } else { new Insertion.Bottom(Event.element(e).up(1), errorSpanHtml); } } if (elementType == 'radio') { radioPrefix = Event.element(e).name.sub(/^([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]$/, "#{1}_#{2}"); errorSpan = $(radioPrefix+'_errors'); if (errorSpan != null) { if (!errorSpan.hasClassName('formErrors')) { errorSpan.addClassName('formErrors'); errorSpan.setStyle({display: 'none'}); } } else { errorSpanHtml = ''; lastRadio = FluxValidator.form.getInputs('radio', Event.element(e).name).last(); nextSibling = lastRadio.up().next('span'); if (nextSibling != undefined) { new Insertion.Before(nextSibling, errorSpanHtml); } else { new Insertion.Bottom(lastRadio.up(1), errorSpanHtml); } } } } else if (errorSpan == null) { new Insertion.After(fieldSpan, errorSpanHtml); } var path = $F(FluxValidator.form['_validation']); var queryString = Form.serializeElements(Form.getElements(FluxValidator.form), false); queryString = queryString.replace(/(_?)method=([a-z]+)&/, ''); var options = Object.extend({ url: path, method: 'post', parameters: queryString }, this.options); return this.makeRequest(options); } }); Object.extend(FluxValidator.Validate.prototype, FluxValidator.Base); // Define some new Element methods Element.addMethods({ wrap: function(element, tagName) { element = $(element); var wrapper = document.createElement(tagName); element.up().replaceChild(wrapper, element); wrapper.appendChild(element); return Element.extend(wrapper); }, equals: function(element, html) { element = $(element).innerHTML.stripScripts().stripTags(); html = html.stripScripts().stripTags(); return (element == html); } }); // Override Scriptaculous Shake Effect.Shake = function(element,valx) { element = $(element); valx = $(valx); nvalx = $(valx * (-1)); var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left') }; return new Effect.Move(element, { x: (valx * 2) , y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: (nvalx * 2), y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: (valx * 2), y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: (nvalx * 2), y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: (valx), y: 0, duration: 0.1, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: valx, y: 0, duration: 0.08, afterFinishInternal: function(effect) { effect.element.undoPositioned(); effect.element.setStyle(oldStyle); valx = 0; nvalx = 0; }}) }}) }}) }}) }}) }}); }