From e9743a2df1638f77f0cd7e223566e5496d4680f5 Mon Sep 17 00:00:00 2001 From: Christian Alfoni Date: Wed, 14 Jan 2015 10:15:49 +0100 Subject: [PATCH] Cross input validation, invalidateForm and bug fix --- Gulpfile.js | 8 +- README.md | 22 +- bower.json | 2 +- package.json | 2 +- releases/0.1.0/formsy-react-0.1.0.js | 341 ---------------- releases/0.1.0/formsy-react-0.1.0.min.js | 1 - releases/0.1.1/formsy-react-0.1.1.js | 346 ---------------- releases/0.1.1/formsy-react-0.1.1.min.js | 1 - releases/0.1.2/formsy-react-0.1.2.js | 346 ---------------- releases/0.1.2/formsy-react-0.1.2.min.js | 1 - releases/0.1.3/formsy-react-0.1.3.js | 348 ---------------- releases/0.1.3/formsy-react-0.1.3.min.js | 1 - releases/0.2.0/formsy-react-0.2.0.js | 351 ---------------- releases/0.2.0/formsy-react-0.2.0.min.js | 1 - releases/0.2.1/formsy-react-0.2.1.js | 351 ---------------- releases/0.2.1/formsy-react-0.2.1.min.js | 1 - releases/0.2.3/formsy-react-0.2.3.js | 358 ---------------- releases/0.2.3/formsy-react-0.2.3.min.js | 1 - releases/0.3.0/formsy-react-0.3.0.js | 362 ----------------- releases/0.3.0/formsy-react-0.3.0.min.js | 1 - releases/0.4.0/formsy-react-0.4.0.js | 381 ------------------ releases/0.4.0/formsy-react-0.4.0.min.js | 1 - releases/0.4.1/formsy-react-0.4.1.min.js | 1 - .../formsy-react-0.4.1.js => formsy-react.js} | 109 +++-- releases/formsy-react.min.js | 1 + src/main.js | 109 +++-- 26 files changed, 177 insertions(+), 3270 deletions(-) delete mode 100755 releases/0.1.0/formsy-react-0.1.0.js delete mode 100755 releases/0.1.0/formsy-react-0.1.0.min.js delete mode 100755 releases/0.1.1/formsy-react-0.1.1.js delete mode 100755 releases/0.1.1/formsy-react-0.1.1.min.js delete mode 100755 releases/0.1.2/formsy-react-0.1.2.js delete mode 100755 releases/0.1.2/formsy-react-0.1.2.min.js delete mode 100755 releases/0.1.3/formsy-react-0.1.3.js delete mode 100755 releases/0.1.3/formsy-react-0.1.3.min.js delete mode 100755 releases/0.2.0/formsy-react-0.2.0.js delete mode 100755 releases/0.2.0/formsy-react-0.2.0.min.js delete mode 100755 releases/0.2.1/formsy-react-0.2.1.js delete mode 100755 releases/0.2.1/formsy-react-0.2.1.min.js delete mode 100755 releases/0.2.3/formsy-react-0.2.3.js delete mode 100755 releases/0.2.3/formsy-react-0.2.3.min.js delete mode 100755 releases/0.3.0/formsy-react-0.3.0.js delete mode 100755 releases/0.3.0/formsy-react-0.3.0.min.js delete mode 100755 releases/0.4.0/formsy-react-0.4.0.js delete mode 100755 releases/0.4.0/formsy-react-0.4.0.min.js delete mode 100755 releases/0.4.1/formsy-react-0.4.1.min.js rename releases/{0.4.1/formsy-react-0.4.1.js => formsy-react.js} (85%) create mode 100755 releases/formsy-react.min.js diff --git a/Gulpfile.js b/Gulpfile.js index 2d3191f..39cce4f 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -73,18 +73,18 @@ gulp.task('deploy', function () { runBrowserifyTask({ watch: false, - dest: './releases/' + package.version, + dest: './releases', uglify: true, debug: false, - name: 'formsy-react-' + package.version + '.min.js' + name: 'formsy-react.min.js' }); runBrowserifyTask({ watch: false, - dest: './releases/' + package.version, + dest: './releases', uglify: false, debug: false, - name: 'formsy-react-' + package.version + '.js' + name: 'formsy-react.js' }); }); diff --git a/README.md b/README.md index ea603c2..4ab4913 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,11 @@ The main concept is that forms, inputs and validation is done very differently a ## Changes +**0.5.0** + - Added [cross input validation](#formsyaddvalidationrule) + - Fixed bug where validation rule refers to a string + - Added "invalidateForm" function when manually submitting the form + **0.4.1** - Fixed bug where form element is required, but no validations @@ -198,11 +203,11 @@ Supports **json** (default) and **urlencoded** (x-www-form-urlencoded). ``` Takes a function to run when the server has responded with a success http status code. -#### onSubmit(data, resetForm) +#### onSubmit(data, resetForm, invalidateForm) ```html ``` -Takes a function to run when the submit button has been clicked. The first argument is the data of the form. The second argument will reset the form. +Takes a function to run when the submit button has been clicked. The first argument is the data of the form. The second argument will reset the form. The third argument will invalidate the form by taking an object that maps to inputs. E.g. `{email: "This email is taken"}`. **note!** When resetting the form the form elements needs to bind its current value using the *getValue* method. That will empty for example an input. @@ -441,6 +446,19 @@ Formsy.addValidationRule('isIn', function (value, array) { ```html ``` +Cross input validation: +```javascript +Formsy.addValidationRule('isMoreThan', function (value, otherField) { + // The this context points to an object containing the values + // {childAge: "", parentAge: "5"} + // otherField argument is from the validations rule ("childAge") + return Number(value) > Number(this[otherField]); +}); +``` +```html + + +``` ## Validators **isValue** ```html diff --git a/bower.json b/bower.json index ade2367..f4434d4 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "formsy-react", - "version": "0.4.1", + "version": "0.5.0", "main": "src/main.js", "dependencies": { "react": "^0.11.2" diff --git a/package.json b/package.json index d74ce77..7715f2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "formsy-react", - "version": "0.4.1", + "version": "0.5.0", "description": "A form input builder and validator for React JS", "main": "src/main.js", "scripts": { diff --git a/releases/0.1.0/formsy-react-0.1.0.js b/releases/0.1.0/formsy-react-0.1.0.js deleted file mode 100755 index df5601d..0000000 --- a/releases/0.1.0/formsy-react-0.1.0.js +++ /dev/null @@ -1,341 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Formsy=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= min && value.length <= max; - } - return value.length >= min; - }, - equals: function (value, eql) { - return value == eql; - } -}; -var toURLEncoded = function (element,key,list){ - var list = list || []; - if(typeof(element)=='object'){ - for (var idx in element) - toURLEncoded(element[idx],key?key+'['+idx+']':idx,list); - } else { - list.push(key+'='+encodeURIComponent(element)); - } - return list.join('&'); -}; - -var request = function (method, url, data, contentType) { - - var contentType = contentType === 'urlencoded' ? 'application/' + contentType.replace('urlencoded', 'x-www-form-urlencoded') : 'application/json'; - data = contentType === 'application/json' ? JSON.stringify(data) : toURLEncoded(data); - - return new Promise(function (resolve, reject) { - try { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader('Content-Type', contentType); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } else { - reject(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } - - } - }; - xhr.send(data); - } catch (e) { - reject(e); - } - }); - -}; -var ajax = { - post: request.bind(null, 'POST'), - put: request.bind(null, 'PUT') -}; -var options = {}; - -Formsy.defaults = function (passedOptions) { - options = passedOptions; -}; - -Formsy.Mixin = { - getInitialState: function () { - return { - _value: this.props.value ? this.props.value : '', - _isValid: true - }; - }, - componentWillMount: function () { - - if (!this.props.name) { - throw new Error('Form Input requires a name property when used'); - } - - if (!this.props._attachToForm) { - throw new Error('Form Mixin requires component to be nested in a Form'); - } - - if (this.props.required) { - this.props.validations = this.props.validations ? this.props.validations + ',' : ''; - this.props.validations += 'isValue'; - } - this.props._attachToForm(this); - }, - - // Detach it when component unmounts - componentWillUnmount: function () { - this.props._detachFromForm(this); - }, - - // We validate after the value has been set - setValue: function (value) { - this.setState({ - _value: value - }, function () { - this.props._validate(this); - }.bind(this)); - }, - getValue: function () { - return this.state._value; - }, - getErrorMessage: function () { - return this.isValid() || this.showRequired() ? null : this.state._serverError || this.props.validationError; - }, - isValid: function () { - return this.state._isValid; - }, - isRequired: function () { - return this.props.required; - }, - showRequired: function () { - return this.props.required && !this.state._value.length; - }, - showError: function () { - return !this.showRequired() && !this.state._isValid; - } -}; - -Formsy.addValidationRule = function (name, func) { - validationRules[name] = func; -}; - -Formsy.Form = React.createClass({ - getInitialState: function () { - return { - isValid: true, - isSubmitting: false - }; - }, - getDefaultProps: function () { - return { - onSuccess: function () {}, - onError: function () {}, - onSubmit: function () {}, - onSubmitted: function () {} - } - }, - - // Add a map to store the inputs of the form, a model to store - // the values of the form and register child inputs - componentWillMount: function () { - this.inputs = {}; - this.model = {}; - this.registerInputs(this.props.children); - }, - - componentDidMount: function () { - this.validateForm(); - }, - - // Update model, submit to url prop and send the model - submit: function (event) { - event.preventDefault(); - - if (!this.props.url) { - throw new Error('Formsy Form needs a url property to post the form'); - } - - this.updateModel(); - this.setState({ - isSubmitting: true - }); - this.props.onSubmit(); - ajax[this.props.method || 'post'](this.props.url, this.model, this.props.contentType || options.contentType || 'json') - .then(function (response) { - this.onSuccess(response); - this.onSubmitted(); - }.bind(this)) - .catch(this.updateInputsWithError); - }, - - // Goes through all registered components and - // updates the model values - updateModel: function () { - Object.keys(this.inputs).forEach(function (name) { - var component = this.inputs[name]; - this.model[name] = component.state._value; - }.bind(this)); - }, - - // Go through errors from server and grab the components - // stored in the inputs map. Change their state to invalid - // and set the serverError message - updateInputsWithError: function (errors) { - Object.keys(errors).forEach(function (name, index) { - var component = this.inputs[name]; - var args = [{ - _isValid: false, - _serverError: errors[name] - }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } - component.setState.apply(component, args); - }.bind(this)); - this.setState({ - isSubmitting: false - }); - this.props.onError(errors); - this.props.onSubmitted(); - }, - - // Traverse the children and children of children to find - // all inputs by checking the name prop. Maybe do a better - // check here - registerInputs: function (children) { - React.Children.forEach(children, function (child) { - - if (child.props.name) { - child.props._attachToForm = this.attachToForm; - child.props._detachFromForm = this.detachFromForm; - child.props._validate = this.validate; - } - - if (child.props.children) { - this.registerInputs(child.props.children); - } - - }.bind(this)); - }, - - // Use the binded values and the actual input value to - // validate the input and set its state. Then check the - // state of the form itself - validate: function (component) { - - if (!component.props.validations) { - return; - } - - // Run through the validations, split them up and call - // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value) { - component.props.validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { return JSON.parse(arg); }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } - - component.setState({ - _isValid: isValid, - _serverError: null - }, this.validateForm); - - }, - - // Validate the form by going through all child input components - // and check their state - validateForm: function () { - var allIsValid = true; - var inputs = this.inputs; - - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); - - this.setState({ - isValid: allIsValid - }); - }, - - // Method put on each input component to register - // itself to the form - attachToForm: function (component) { - this.inputs[component.props.name] = component; - this.model[component.props.name] = component.state._value; - this.validate(component); - }, - - // Method put on each input component to unregister - // itself from the form - detachFromForm: function (component) { - delete this.inputs[component.props.name]; - delete this.model[component.props.name]; - }, - render: function () { - var submitButton = React.DOM.button({ - className: this.props.submitButtonClass || options.submitButtonClass, - disabled: this.state.isSubmitting || !this.state.isValid - }, this.props.submitLabel || 'Submit'); - - var cancelButton = React.DOM.button({ - onClick: this.props.onCancel, - disabled: this.state.isSubmitting, - className: this.props.resetButtonClass || options.resetButtonClass - }, this.props.cancelLabel || 'Cancel'); - - return React.DOM.form({ - onSubmit: this.submit, - className: this.props.className - }, - this.props.children, - React.DOM.div({ - className: this.props.buttonWrapperClass || options.buttonWrapperClass - }, - this.props.showCancel || options.showCancel ? cancelButton : null, - this.props.hideSubmit || options.hideSubmit ? null : submitButton - ) - ); - - } -}); - -if (!global.exports && !global.module && (!global.define || !global.define.amd)) { - global.Formsy = Formsy; -} - -module.exports = Formsy; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"react":"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js") -}); \ No newline at end of file diff --git a/releases/0.1.0/formsy-react-0.1.0.min.js b/releases/0.1.0/formsy-react-0.1.0.min.js deleted file mode 100755 index 984d46b..0000000 --- a/releases/0.1.0/formsy-react-0.1.0.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,n){function s(o,u){if(!i[o]){if(!e[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(r)return r(o,!0);var p=new Error("Cannot find module '"+o+"'");throw p.code="MODULE_NOT_FOUND",p}var l=i[o]={exports:{}};e[o][0].call(l.exports,function(t){var i=e[o][1][t];return s(i?i:t)},l,l.exports,t,e,i,n)}return i[o].exports}for(var r="function"==typeof require&&require,o=0;o=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},o=function(t,e,i){var i=i||[];if("object"==typeof t)for(var n in t)o(t[n],e?e+"["+n+"]":n,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,n){var n="urlencoded"===n?"application/"+n.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===n?JSON.stringify(i):o(i),new Promise(function(s,r){try{var o=new XMLHttpRequest;o.open(t,e,!0),o.setRequestHeader("Accept","application/json"),o.setRequestHeader("Content-Type",n),o.onreadystatechange=function(){4===o.readyState&&(o.status>=200&&o.status<300?s(o.responseText?JSON.parse(o.responseText):null):r(o.responseText?JSON.parse(o.responseText):null))},o.send(i)}catch(u){r(u)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};s.defaults=function(t){p=t},s.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this.props.required&&(this.props.validations=this.props.validations?this.props.validations+",":"",this.props.validations+="isValue"),this.props._attachToForm(this)},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},getValue:function(){return this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&!this.state._value.length},showError:function(){return!this.showRequired()&&!this.state._isValid}},s.addValidationRule=function(t,e){r[t]=e},s.Form=n.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)throw new Error("Formsy Form needs a url property to post the form");this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit(),a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json").then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var n=this.inputs[e],s=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&s.push(this.validateForm),n.setState.apply(n,s)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){n.Children.forEach(t,function(t){t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.validations){var e=!0;(t.props.required||t.state._value)&&t.props.validations.split(",").forEach(function(i){var n=i.split(":"),s=n.shift();if(n=n.map(function(t){return JSON.parse(t)}),n=[t.state._value].concat(n),!r[s])throw new Error("Formsy does not have the validation rule: "+s);r[s].apply(null,n)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t})},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){var t=n.DOM.button({className:this.props.submitButtonClass||p.submitButtonClass,disabled:this.state.isSubmitting||!this.state.isValid},this.props.submitLabel||"Submit"),e=n.DOM.button({onClick:this.props.onCancel,disabled:this.state.isSubmitting,className:this.props.resetButtonClass||p.resetButtonClass},this.props.cancelLabel||"Cancel");return n.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children,n.DOM.div({className:this.props.buttonWrapperClass||p.buttonWrapperClass},this.props.showCancel||p.showCancel?e:null,this.props.hideSubmit||p.hideSubmit?null:t))}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=s),e.exports=s}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js")}); \ No newline at end of file diff --git a/releases/0.1.1/formsy-react-0.1.1.js b/releases/0.1.1/formsy-react-0.1.1.js deleted file mode 100755 index 37e21ed..0000000 --- a/releases/0.1.1/formsy-react-0.1.1.js +++ /dev/null @@ -1,346 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Formsy=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= min && value.length <= max; - } - return value.length >= min; - }, - equals: function (value, eql) { - return value == eql; - } -}; -var toURLEncoded = function (element,key,list){ - var list = list || []; - if(typeof(element)=='object'){ - for (var idx in element) - toURLEncoded(element[idx],key?key+'['+idx+']':idx,list); - } else { - list.push(key+'='+encodeURIComponent(element)); - } - return list.join('&'); -}; - -var request = function (method, url, data, contentType) { - - var contentType = contentType === 'urlencoded' ? 'application/' + contentType.replace('urlencoded', 'x-www-form-urlencoded') : 'application/json'; - data = contentType === 'application/json' ? JSON.stringify(data) : toURLEncoded(data); - - return new Promise(function (resolve, reject) { - try { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader('Content-Type', contentType); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } else { - reject(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } - - } - }; - xhr.send(data); - } catch (e) { - reject(e); - } - }); - -}; -var ajax = { - post: request.bind(null, 'POST'), - put: request.bind(null, 'PUT') -}; -var options = {}; - -Formsy.defaults = function (passedOptions) { - options = passedOptions; -}; - -Formsy.Mixin = { - getInitialState: function () { - return { - _value: this.props.value ? this.props.value : '', - _isValid: true - }; - }, - componentWillMount: function () { - - if (!this.props.name) { - throw new Error('Form Input requires a name property when used'); - } - - if (!this.props._attachToForm) { - throw new Error('Form Mixin requires component to be nested in a Form'); - } - - if (this.props.required) { - this.props.validations = this.props.validations ? this.props.validations + ',' : ''; - this.props.validations += 'isValue'; - } - this.props._attachToForm(this); - }, - - // Detach it when component unmounts - componentWillUnmount: function () { - this.props._detachFromForm(this); - }, - - // We validate after the value has been set - setValue: function (value) { - this.setState({ - _value: value - }, function () { - this.props._validate(this); - }.bind(this)); - }, - resetValue: function () { - this.setState({ - _value: '' - }); - }, - getValue: function () { - return this.state._value; - }, - getErrorMessage: function () { - return this.isValid() || this.showRequired() ? null : this.state._serverError || this.props.validationError; - }, - isValid: function () { - return this.state._isValid; - }, - isRequired: function () { - return this.props.required; - }, - showRequired: function () { - return this.props.required && this.state._value === ''; - }, - showError: function () { - return !this.showRequired() && !this.state._isValid; - } -}; - -Formsy.addValidationRule = function (name, func) { - validationRules[name] = func; -}; - -Formsy.Form = React.createClass({ - getInitialState: function () { - return { - isValid: true, - isSubmitting: false - }; - }, - getDefaultProps: function () { - return { - onSuccess: function () {}, - onError: function () {}, - onSubmit: function () {}, - onSubmitted: function () {} - } - }, - - // Add a map to store the inputs of the form, a model to store - // the values of the form and register child inputs - componentWillMount: function () { - this.inputs = {}; - this.model = {}; - this.registerInputs(this.props.children); - }, - - componentDidMount: function () { - this.validateForm(); - }, - - // Update model, submit to url prop and send the model - submit: function (event) { - event.preventDefault(); - - if (!this.props.url) { - throw new Error('Formsy Form needs a url property to post the form'); - } - - this.updateModel(); - this.setState({ - isSubmitting: true - }); - this.props.onSubmit(); - ajax[this.props.method || 'post'](this.props.url, this.model, this.props.contentType || options.contentType || 'json') - .then(function (response) { - this.onSuccess(response); - this.onSubmitted(); - }.bind(this)) - .catch(this.updateInputsWithError); - }, - - // Goes through all registered components and - // updates the model values - updateModel: function () { - Object.keys(this.inputs).forEach(function (name) { - var component = this.inputs[name]; - this.model[name] = component.state._value; - }.bind(this)); - }, - - // Go through errors from server and grab the components - // stored in the inputs map. Change their state to invalid - // and set the serverError message - updateInputsWithError: function (errors) { - Object.keys(errors).forEach(function (name, index) { - var component = this.inputs[name]; - var args = [{ - _isValid: false, - _serverError: errors[name] - }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } - component.setState.apply(component, args); - }.bind(this)); - this.setState({ - isSubmitting: false - }); - this.props.onError(errors); - this.props.onSubmitted(); - }, - - // Traverse the children and children of children to find - // all inputs by checking the name prop. Maybe do a better - // check here - registerInputs: function (children) { - React.Children.forEach(children, function (child) { - - if (child.props.name) { - child.props._attachToForm = this.attachToForm; - child.props._detachFromForm = this.detachFromForm; - child.props._validate = this.validate; - } - - if (child.props.children) { - this.registerInputs(child.props.children); - } - - }.bind(this)); - }, - - // Use the binded values and the actual input value to - // validate the input and set its state. Then check the - // state of the form itself - validate: function (component) { - - if (!component.props.validations) { - return; - } - - // Run through the validations, split them up and call - // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value) { - component.props.validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { return JSON.parse(arg); }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } - - component.setState({ - _isValid: isValid, - _serverError: null - }, this.validateForm); - - }, - - // Validate the form by going through all child input components - // and check their state - validateForm: function () { - var allIsValid = true; - var inputs = this.inputs; - - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); - - this.setState({ - isValid: allIsValid - }); - }, - - // Method put on each input component to register - // itself to the form - attachToForm: function (component) { - this.inputs[component.props.name] = component; - this.model[component.props.name] = component.state._value; - this.validate(component); - }, - - // Method put on each input component to unregister - // itself from the form - detachFromForm: function (component) { - delete this.inputs[component.props.name]; - delete this.model[component.props.name]; - }, - render: function () { - var submitButton = React.DOM.button({ - className: this.props.submitButtonClass || options.submitButtonClass, - disabled: this.state.isSubmitting || !this.state.isValid - }, this.props.submitLabel || 'Submit'); - - var cancelButton = React.DOM.button({ - onClick: this.props.onCancel, - disabled: this.state.isSubmitting, - className: this.props.resetButtonClass || options.resetButtonClass - }, this.props.cancelLabel || 'Cancel'); - - return React.DOM.form({ - onSubmit: this.submit, - className: this.props.className - }, - this.props.children, - React.DOM.div({ - className: this.props.buttonWrapperClass || options.buttonWrapperClass - }, - this.props.showCancel || options.showCancel ? cancelButton : null, - this.props.hideSubmit || options.hideSubmit ? null : submitButton - ) - ); - - } -}); - -if (!global.exports && !global.module && (!global.define || !global.define.amd)) { - global.Formsy = Formsy; -} - -module.exports = Formsy; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"react":"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js") -}); \ No newline at end of file diff --git a/releases/0.1.1/formsy-react-0.1.1.min.js b/releases/0.1.1/formsy-react-0.1.1.min.js deleted file mode 100755 index 2d8728b..0000000 --- a/releases/0.1.1/formsy-react-0.1.1.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,n){function s(o,u){if(!i[o]){if(!e[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(r)return r(o,!0);var p=new Error("Cannot find module '"+o+"'");throw p.code="MODULE_NOT_FOUND",p}var l=i[o]={exports:{}};e[o][0].call(l.exports,function(t){var i=e[o][1][t];return s(i?i:t)},l,l.exports,t,e,i,n)}return i[o].exports}for(var r="function"==typeof require&&require,o=0;o=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},o=function(t,e,i){var i=i||[];if("object"==typeof t)for(var n in t)o(t[n],e?e+"["+n+"]":n,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,n){var n="urlencoded"===n?"application/"+n.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===n?JSON.stringify(i):o(i),new Promise(function(s,r){try{var o=new XMLHttpRequest;o.open(t,e,!0),o.setRequestHeader("Accept","application/json"),o.setRequestHeader("Content-Type",n),o.onreadystatechange=function(){4===o.readyState&&(o.status>=200&&o.status<300?s(o.responseText?JSON.parse(o.responseText):null):r(o.responseText?JSON.parse(o.responseText):null))},o.send(i)}catch(u){r(u)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};s.defaults=function(t){p=t},s.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this.props.required&&(this.props.validations=this.props.validations?this.props.validations+",":"",this.props.validations+="isValue"),this.props._attachToForm(this)},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""})},getValue:function(){return this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},s.addValidationRule=function(t,e){r[t]=e},s.Form=n.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)throw new Error("Formsy Form needs a url property to post the form");this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit(),a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json").then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var n=this.inputs[e],s=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&s.push(this.validateForm),n.setState.apply(n,s)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){n.Children.forEach(t,function(t){t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.validations){var e=!0;(t.props.required||t.state._value)&&t.props.validations.split(",").forEach(function(i){var n=i.split(":"),s=n.shift();if(n=n.map(function(t){return JSON.parse(t)}),n=[t.state._value].concat(n),!r[s])throw new Error("Formsy does not have the validation rule: "+s);r[s].apply(null,n)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t})},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){var t=n.DOM.button({className:this.props.submitButtonClass||p.submitButtonClass,disabled:this.state.isSubmitting||!this.state.isValid},this.props.submitLabel||"Submit"),e=n.DOM.button({onClick:this.props.onCancel,disabled:this.state.isSubmitting,className:this.props.resetButtonClass||p.resetButtonClass},this.props.cancelLabel||"Cancel");return n.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children,n.DOM.div({className:this.props.buttonWrapperClass||p.buttonWrapperClass},this.props.showCancel||p.showCancel?e:null,this.props.hideSubmit||p.hideSubmit?null:t))}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=s),e.exports=s}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js")}); \ No newline at end of file diff --git a/releases/0.1.2/formsy-react-0.1.2.js b/releases/0.1.2/formsy-react-0.1.2.js deleted file mode 100755 index 6030de7..0000000 --- a/releases/0.1.2/formsy-react-0.1.2.js +++ /dev/null @@ -1,346 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Formsy=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= min && value.length <= max; - } - return value.length >= min; - }, - equals: function (value, eql) { - return value == eql; - } -}; -var toURLEncoded = function (element,key,list){ - var list = list || []; - if(typeof(element)=='object'){ - for (var idx in element) - toURLEncoded(element[idx],key?key+'['+idx+']':idx,list); - } else { - list.push(key+'='+encodeURIComponent(element)); - } - return list.join('&'); -}; - -var request = function (method, url, data, contentType) { - - var contentType = contentType === 'urlencoded' ? 'application/' + contentType.replace('urlencoded', 'x-www-form-urlencoded') : 'application/json'; - data = contentType === 'application/json' ? JSON.stringify(data) : toURLEncoded(data); - - return new Promise(function (resolve, reject) { - try { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader('Content-Type', contentType); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } else { - reject(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } - - } - }; - xhr.send(data); - } catch (e) { - reject(e); - } - }); - -}; -var ajax = { - post: request.bind(null, 'POST'), - put: request.bind(null, 'PUT') -}; -var options = {}; - -Formsy.defaults = function (passedOptions) { - options = passedOptions; -}; - -Formsy.Mixin = { - getInitialState: function () { - return { - _value: this.props.value ? this.props.value : '', - _isValid: true - }; - }, - componentWillMount: function () { - - if (!this.props.name) { - throw new Error('Form Input requires a name property when used'); - } - - if (!this.props._attachToForm) { - throw new Error('Form Mixin requires component to be nested in a Form'); - } - - if (this.props.required) { - this.props.validations = this.props.validations ? this.props.validations + ',' : ''; - this.props.validations += 'isValue'; - } - this.props._attachToForm(this); - }, - - // Detach it when component unmounts - componentWillUnmount: function () { - this.props._detachFromForm(this); - }, - - // We validate after the value has been set - setValue: function (value) { - this.setState({ - _value: value - }, function () { - this.props._validate(this); - }.bind(this)); - }, - resetValue: function () { - this.setState({ - _value: '' - }); - }, - getValue: function () { - return this.state._value; - }, - getErrorMessage: function () { - return this.isValid() || this.showRequired() ? null : this.state._serverError || this.props.validationError; - }, - isValid: function () { - return this.state._isValid; - }, - isRequired: function () { - return this.props.required; - }, - showRequired: function () { - return this.props.required && this.state._value === ''; - }, - showError: function () { - return !this.showRequired() && !this.state._isValid; - } -}; - -Formsy.addValidationRule = function (name, func) { - validationRules[name] = func; -}; - -Formsy.Form = React.createClass({ - getInitialState: function () { - return { - isValid: true, - isSubmitting: false - }; - }, - getDefaultProps: function () { - return { - onSuccess: function () {}, - onError: function () {}, - onSubmit: function () {}, - onSubmitted: function () {} - } - }, - - // Add a map to store the inputs of the form, a model to store - // the values of the form and register child inputs - componentWillMount: function () { - this.inputs = {}; - this.model = {}; - this.registerInputs(this.props.children); - }, - - componentDidMount: function () { - this.validateForm(); - }, - - // Update model, submit to url prop and send the model - submit: function (event) { - event.preventDefault(); - - if (!this.props.url) { - throw new Error('Formsy Form needs a url property to post the form'); - } - - this.updateModel(); - this.setState({ - isSubmitting: true - }); - this.props.onSubmit(); - ajax[this.props.method || 'post'](this.props.url, this.model, this.props.contentType || options.contentType || 'json') - .then(function (response) { - this.onSuccess(response); - this.onSubmitted(); - }.bind(this)) - .catch(this.updateInputsWithError); - }, - - // Goes through all registered components and - // updates the model values - updateModel: function () { - Object.keys(this.inputs).forEach(function (name) { - var component = this.inputs[name]; - this.model[name] = component.state._value; - }.bind(this)); - }, - - // Go through errors from server and grab the components - // stored in the inputs map. Change their state to invalid - // and set the serverError message - updateInputsWithError: function (errors) { - Object.keys(errors).forEach(function (name, index) { - var component = this.inputs[name]; - var args = [{ - _isValid: false, - _serverError: errors[name] - }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } - component.setState.apply(component, args); - }.bind(this)); - this.setState({ - isSubmitting: false - }); - this.props.onError(errors); - this.props.onSubmitted(); - }, - - // Traverse the children and children of children to find - // all inputs by checking the name prop. Maybe do a better - // check here - registerInputs: function (children) { - React.Children.forEach(children, function (child) { - - if (child.props.name) { - child.props._attachToForm = this.attachToForm; - child.props._detachFromForm = this.detachFromForm; - child.props._validate = this.validate; - } - - if (child.props.children) { - this.registerInputs(child.props.children); - } - - }.bind(this)); - }, - - // Use the binded values and the actual input value to - // validate the input and set its state. Then check the - // state of the form itself - validate: function (component) { - - if (!component.props.validations) { - return; - } - - // Run through the validations, split them up and call - // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value !== '') { - component.props.validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { return JSON.parse(arg); }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } - - component.setState({ - _isValid: isValid, - _serverError: null - }, this.validateForm); - - }, - - // Validate the form by going through all child input components - // and check their state - validateForm: function () { - var allIsValid = true; - var inputs = this.inputs; - - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); - - this.setState({ - isValid: allIsValid - }); - }, - - // Method put on each input component to register - // itself to the form - attachToForm: function (component) { - this.inputs[component.props.name] = component; - this.model[component.props.name] = component.state._value; - this.validate(component); - }, - - // Method put on each input component to unregister - // itself from the form - detachFromForm: function (component) { - delete this.inputs[component.props.name]; - delete this.model[component.props.name]; - }, - render: function () { - var submitButton = React.DOM.button({ - className: this.props.submitButtonClass || options.submitButtonClass, - disabled: this.state.isSubmitting || !this.state.isValid - }, this.props.submitLabel || 'Submit'); - - var cancelButton = React.DOM.button({ - onClick: this.props.onCancel, - disabled: this.state.isSubmitting, - className: this.props.resetButtonClass || options.resetButtonClass - }, this.props.cancelLabel || 'Cancel'); - - return React.DOM.form({ - onSubmit: this.submit, - className: this.props.className - }, - this.props.children, - React.DOM.div({ - className: this.props.buttonWrapperClass || options.buttonWrapperClass - }, - this.props.showCancel || options.showCancel ? cancelButton : null, - this.props.hideSubmit || options.hideSubmit ? null : submitButton - ) - ); - - } -}); - -if (!global.exports && !global.module && (!global.define || !global.define.amd)) { - global.Formsy = Formsy; -} - -module.exports = Formsy; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"react":"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js") -}); \ No newline at end of file diff --git a/releases/0.1.2/formsy-react-0.1.2.min.js b/releases/0.1.2/formsy-react-0.1.2.min.js deleted file mode 100755 index cee7a0c..0000000 --- a/releases/0.1.2/formsy-react-0.1.2.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,n){function s(o,u){if(!i[o]){if(!e[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(r)return r(o,!0);var p=new Error("Cannot find module '"+o+"'");throw p.code="MODULE_NOT_FOUND",p}var l=i[o]={exports:{}};e[o][0].call(l.exports,function(t){var i=e[o][1][t];return s(i?i:t)},l,l.exports,t,e,i,n)}return i[o].exports}for(var r="function"==typeof require&&require,o=0;o=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},o=function(t,e,i){var i=i||[];if("object"==typeof t)for(var n in t)o(t[n],e?e+"["+n+"]":n,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,n){var n="urlencoded"===n?"application/"+n.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===n?JSON.stringify(i):o(i),new Promise(function(s,r){try{var o=new XMLHttpRequest;o.open(t,e,!0),o.setRequestHeader("Accept","application/json"),o.setRequestHeader("Content-Type",n),o.onreadystatechange=function(){4===o.readyState&&(o.status>=200&&o.status<300?s(o.responseText?JSON.parse(o.responseText):null):r(o.responseText?JSON.parse(o.responseText):null))},o.send(i)}catch(u){r(u)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};s.defaults=function(t){p=t},s.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this.props.required&&(this.props.validations=this.props.validations?this.props.validations+",":"",this.props.validations+="isValue"),this.props._attachToForm(this)},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""})},getValue:function(){return this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},s.addValidationRule=function(t,e){r[t]=e},s.Form=n.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)throw new Error("Formsy Form needs a url property to post the form");this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit(),a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json").then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var n=this.inputs[e],s=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&s.push(this.validateForm),n.setState.apply(n,s)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){n.Children.forEach(t,function(t){t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.validations){var e=!0;(t.props.required||""!==t.state._value)&&t.props.validations.split(",").forEach(function(i){var n=i.split(":"),s=n.shift();if(n=n.map(function(t){return JSON.parse(t)}),n=[t.state._value].concat(n),!r[s])throw new Error("Formsy does not have the validation rule: "+s);r[s].apply(null,n)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t})},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){var t=n.DOM.button({className:this.props.submitButtonClass||p.submitButtonClass,disabled:this.state.isSubmitting||!this.state.isValid},this.props.submitLabel||"Submit"),e=n.DOM.button({onClick:this.props.onCancel,disabled:this.state.isSubmitting,className:this.props.resetButtonClass||p.resetButtonClass},this.props.cancelLabel||"Cancel");return n.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children,n.DOM.div({className:this.props.buttonWrapperClass||p.buttonWrapperClass},this.props.showCancel||p.showCancel?e:null,this.props.hideSubmit||p.hideSubmit?null:t))}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=s),e.exports=s}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js")}); \ No newline at end of file diff --git a/releases/0.1.3/formsy-react-0.1.3.js b/releases/0.1.3/formsy-react-0.1.3.js deleted file mode 100755 index b19f55c..0000000 --- a/releases/0.1.3/formsy-react-0.1.3.js +++ /dev/null @@ -1,348 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Formsy=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= min && value.length <= max; - } - return value.length >= min; - }, - equals: function (value, eql) { - return value == eql; - } -}; -var toURLEncoded = function (element,key,list){ - var list = list || []; - if(typeof(element)=='object'){ - for (var idx in element) - toURLEncoded(element[idx],key?key+'['+idx+']':idx,list); - } else { - list.push(key+'='+encodeURIComponent(element)); - } - return list.join('&'); -}; - -var request = function (method, url, data, contentType) { - - var contentType = contentType === 'urlencoded' ? 'application/' + contentType.replace('urlencoded', 'x-www-form-urlencoded') : 'application/json'; - data = contentType === 'application/json' ? JSON.stringify(data) : toURLEncoded(data); - - return new Promise(function (resolve, reject) { - try { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader('Content-Type', contentType); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } else { - reject(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } - - } - }; - xhr.send(data); - } catch (e) { - reject(e); - } - }); - -}; -var ajax = { - post: request.bind(null, 'POST'), - put: request.bind(null, 'PUT') -}; -var options = {}; - -Formsy.defaults = function (passedOptions) { - options = passedOptions; -}; - -Formsy.Mixin = { - getInitialState: function () { - return { - _value: this.props.value ? this.props.value : '', - _isValid: true - }; - }, - componentWillMount: function () { - - if (!this.props.name) { - throw new Error('Form Input requires a name property when used'); - } - - if (!this.props._attachToForm) { - throw new Error('Form Mixin requires component to be nested in a Form'); - } - - if (this.props.required) { - this.props.validations = this.props.validations ? this.props.validations + ',' : ''; - this.props.validations += 'isValue'; - } - this.props._attachToForm(this); - }, - - // Detach it when component unmounts - componentWillUnmount: function () { - this.props._detachFromForm(this); - }, - - // We validate after the value has been set - setValue: function (value) { - this.setState({ - _value: value - }, function () { - this.props._validate(this); - }.bind(this)); - }, - resetValue: function () { - this.setState({ - _value: '' - }, function () { - this.props._validate(this); - }); - }, - getValue: function () { - return this.state._value; - }, - getErrorMessage: function () { - return this.isValid() || this.showRequired() ? null : this.state._serverError || this.props.validationError; - }, - isValid: function () { - return this.state._isValid; - }, - isRequired: function () { - return this.props.required; - }, - showRequired: function () { - return this.props.required && this.state._value === ''; - }, - showError: function () { - return !this.showRequired() && !this.state._isValid; - } -}; - -Formsy.addValidationRule = function (name, func) { - validationRules[name] = func; -}; - -Formsy.Form = React.createClass({ - getInitialState: function () { - return { - isValid: true, - isSubmitting: false - }; - }, - getDefaultProps: function () { - return { - onSuccess: function () {}, - onError: function () {}, - onSubmit: function () {}, - onSubmitted: function () {} - } - }, - - // Add a map to store the inputs of the form, a model to store - // the values of the form and register child inputs - componentWillMount: function () { - this.inputs = {}; - this.model = {}; - this.registerInputs(this.props.children); - }, - - componentDidMount: function () { - this.validateForm(); - }, - - // Update model, submit to url prop and send the model - submit: function (event) { - event.preventDefault(); - - if (!this.props.url) { - throw new Error('Formsy Form needs a url property to post the form'); - } - - this.updateModel(); - this.setState({ - isSubmitting: true - }); - this.props.onSubmit(); - ajax[this.props.method || 'post'](this.props.url, this.model, this.props.contentType || options.contentType || 'json') - .then(function (response) { - this.onSuccess(response); - this.onSubmitted(); - }.bind(this)) - .catch(this.updateInputsWithError); - }, - - // Goes through all registered components and - // updates the model values - updateModel: function () { - Object.keys(this.inputs).forEach(function (name) { - var component = this.inputs[name]; - this.model[name] = component.state._value; - }.bind(this)); - }, - - // Go through errors from server and grab the components - // stored in the inputs map. Change their state to invalid - // and set the serverError message - updateInputsWithError: function (errors) { - Object.keys(errors).forEach(function (name, index) { - var component = this.inputs[name]; - var args = [{ - _isValid: false, - _serverError: errors[name] - }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } - component.setState.apply(component, args); - }.bind(this)); - this.setState({ - isSubmitting: false - }); - this.props.onError(errors); - this.props.onSubmitted(); - }, - - // Traverse the children and children of children to find - // all inputs by checking the name prop. Maybe do a better - // check here - registerInputs: function (children) { - React.Children.forEach(children, function (child) { - - if (child.props.name) { - child.props._attachToForm = this.attachToForm; - child.props._detachFromForm = this.detachFromForm; - child.props._validate = this.validate; - } - - if (child.props.children) { - this.registerInputs(child.props.children); - } - - }.bind(this)); - }, - - // Use the binded values and the actual input value to - // validate the input and set its state. Then check the - // state of the form itself - validate: function (component) { - - if (!component.props.validations) { - return; - } - - // Run through the validations, split them up and call - // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value !== '') { - component.props.validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { return JSON.parse(arg); }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } - - component.setState({ - _isValid: isValid, - _serverError: null - }, this.validateForm); - - }, - - // Validate the form by going through all child input components - // and check their state - validateForm: function () { - var allIsValid = true; - var inputs = this.inputs; - - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); - - this.setState({ - isValid: allIsValid - }); - }, - - // Method put on each input component to register - // itself to the form - attachToForm: function (component) { - this.inputs[component.props.name] = component; - this.model[component.props.name] = component.state._value; - this.validate(component); - }, - - // Method put on each input component to unregister - // itself from the form - detachFromForm: function (component) { - delete this.inputs[component.props.name]; - delete this.model[component.props.name]; - }, - render: function () { - var submitButton = React.DOM.button({ - className: this.props.submitButtonClass || options.submitButtonClass, - disabled: this.state.isSubmitting || !this.state.isValid - }, this.props.submitLabel || 'Submit'); - - var cancelButton = React.DOM.button({ - onClick: this.props.onCancel, - disabled: this.state.isSubmitting, - className: this.props.resetButtonClass || options.resetButtonClass - }, this.props.cancelLabel || 'Cancel'); - - return React.DOM.form({ - onSubmit: this.submit, - className: this.props.className - }, - this.props.children, - React.DOM.div({ - className: this.props.buttonWrapperClass || options.buttonWrapperClass - }, - this.props.showCancel || options.showCancel ? cancelButton : null, - this.props.hideSubmit || options.hideSubmit ? null : submitButton - ) - ); - - } -}); - -if (!global.exports && !global.module && (!global.define || !global.define.amd)) { - global.Formsy = Formsy; -} - -module.exports = Formsy; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"react":"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js") -}); \ No newline at end of file diff --git a/releases/0.1.3/formsy-react-0.1.3.min.js b/releases/0.1.3/formsy-react-0.1.3.min.js deleted file mode 100755 index 71f7ecf..0000000 --- a/releases/0.1.3/formsy-react-0.1.3.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,s){function n(o,u){if(!i[o]){if(!e[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(r)return r(o,!0);var p=new Error("Cannot find module '"+o+"'");throw p.code="MODULE_NOT_FOUND",p}var l=i[o]={exports:{}};e[o][0].call(l.exports,function(t){var i=e[o][1][t];return n(i?i:t)},l,l.exports,t,e,i,s)}return i[o].exports}for(var r="function"==typeof require&&require,o=0;o=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},o=function(t,e,i){var i=i||[];if("object"==typeof t)for(var s in t)o(t[s],e?e+"["+s+"]":s,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,s){var s="urlencoded"===s?"application/"+s.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===s?JSON.stringify(i):o(i),new Promise(function(n,r){try{var o=new XMLHttpRequest;o.open(t,e,!0),o.setRequestHeader("Accept","application/json"),o.setRequestHeader("Content-Type",s),o.onreadystatechange=function(){4===o.readyState&&(o.status>=200&&o.status<300?n(o.responseText?JSON.parse(o.responseText):null):r(o.responseText?JSON.parse(o.responseText):null))},o.send(i)}catch(u){r(u)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};n.defaults=function(t){p=t},n.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this.props.required&&(this.props.validations=this.props.validations?this.props.validations+",":"",this.props.validations+="isValue"),this.props._attachToForm(this)},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""},function(){this.props._validate(this)})},getValue:function(){return this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},n.addValidationRule=function(t,e){r[t]=e},n.Form=s.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)throw new Error("Formsy Form needs a url property to post the form");this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit(),a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json").then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var s=this.inputs[e],n=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&n.push(this.validateForm),s.setState.apply(s,n)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){s.Children.forEach(t,function(t){t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.validations){var e=!0;(t.props.required||""!==t.state._value)&&t.props.validations.split(",").forEach(function(i){var s=i.split(":"),n=s.shift();if(s=s.map(function(t){return JSON.parse(t)}),s=[t.state._value].concat(s),!r[n])throw new Error("Formsy does not have the validation rule: "+n);r[n].apply(null,s)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t})},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){var t=s.DOM.button({className:this.props.submitButtonClass||p.submitButtonClass,disabled:this.state.isSubmitting||!this.state.isValid},this.props.submitLabel||"Submit"),e=s.DOM.button({onClick:this.props.onCancel,disabled:this.state.isSubmitting,className:this.props.resetButtonClass||p.resetButtonClass},this.props.cancelLabel||"Cancel");return s.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children,s.DOM.div({className:this.props.buttonWrapperClass||p.buttonWrapperClass},this.props.showCancel||p.showCancel?e:null,this.props.hideSubmit||p.hideSubmit?null:t))}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=n),e.exports=n}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js")}); \ No newline at end of file diff --git a/releases/0.2.0/formsy-react-0.2.0.js b/releases/0.2.0/formsy-react-0.2.0.js deleted file mode 100755 index 0594b6a..0000000 --- a/releases/0.2.0/formsy-react-0.2.0.js +++ /dev/null @@ -1,351 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Formsy=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= min && value.length <= max; - } - return value.length >= min; - }, - equals: function (value, eql) { - return value == eql; - } -}; -var toURLEncoded = function (element,key,list){ - var list = list || []; - if(typeof(element)=='object'){ - for (var idx in element) - toURLEncoded(element[idx],key?key+'['+idx+']':idx,list); - } else { - list.push(key+'='+encodeURIComponent(element)); - } - return list.join('&'); -}; - -var request = function (method, url, data, contentType) { - - var contentType = contentType === 'urlencoded' ? 'application/' + contentType.replace('urlencoded', 'x-www-form-urlencoded') : 'application/json'; - data = contentType === 'application/json' ? JSON.stringify(data) : toURLEncoded(data); - - return new Promise(function (resolve, reject) { - try { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader('Content-Type', contentType); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } else { - reject(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } - - } - }; - xhr.send(data); - } catch (e) { - reject(e); - } - }); - -}; -var ajax = { - post: request.bind(null, 'POST'), - put: request.bind(null, 'PUT') -}; -var options = {}; - -Formsy.defaults = function (passedOptions) { - options = passedOptions; -}; - -Formsy.Mixin = { - getInitialState: function () { - return { - _value: this.props.value ? this.props.value : '', - _isValid: true - }; - }, - componentWillMount: function () { - - if (!this.props.name) { - throw new Error('Form Input requires a name property when used'); - } - - if (!this.props._attachToForm) { - throw new Error('Form Mixin requires component to be nested in a Form'); - } - - if (this.props.required) { - this.props.validations = this.props.validations ? this.props.validations + ',' : ''; - this.props.validations += 'isValue'; - } - this.props._attachToForm(this); - }, - - // Detach it when component unmounts - componentWillUnmount: function () { - this.props._detachFromForm(this); - }, - - // We validate after the value has been set - setValue: function (value) { - this.setState({ - _value: value - }, function () { - this.props._validate(this); - }.bind(this)); - }, - resetValue: function () { - this.setState({ - _value: '' - }, function () { - this.props._validate(this); - }); - }, - getValue: function () { - return this.state._value; - }, - hasValue: function () { - return this.state._value !== ''; - }, - getErrorMessage: function () { - return this.isValid() || this.showRequired() ? null : this.state._serverError || this.props.validationError; - }, - isValid: function () { - return this.state._isValid; - }, - isRequired: function () { - return this.props.required; - }, - showRequired: function () { - return this.props.required && this.state._value === ''; - }, - showError: function () { - return !this.showRequired() && !this.state._isValid; - } -}; - -Formsy.addValidationRule = function (name, func) { - validationRules[name] = func; -}; - -Formsy.Form = React.createClass({ - getInitialState: function () { - return { - isValid: true, - isSubmitting: false - }; - }, - getDefaultProps: function () { - return { - onSuccess: function () {}, - onError: function () {}, - onSubmit: function () {}, - onSubmitted: function () {} - } - }, - - // Add a map to store the inputs of the form, a model to store - // the values of the form and register child inputs - componentWillMount: function () { - this.inputs = {}; - this.model = {}; - this.registerInputs(this.props.children); - }, - - componentDidMount: function () { - this.validateForm(); - }, - - // Update model, submit to url prop and send the model - submit: function (event) { - event.preventDefault(); - - if (!this.props.url) { - throw new Error('Formsy Form needs a url property to post the form'); - } - - this.updateModel(); - this.setState({ - isSubmitting: true - }); - this.props.onSubmit(); - ajax[this.props.method || 'post'](this.props.url, this.model, this.props.contentType || options.contentType || 'json') - .then(function (response) { - this.onSuccess(response); - this.onSubmitted(); - }.bind(this)) - .catch(this.updateInputsWithError); - }, - - // Goes through all registered components and - // updates the model values - updateModel: function () { - Object.keys(this.inputs).forEach(function (name) { - var component = this.inputs[name]; - this.model[name] = component.state._value; - }.bind(this)); - }, - - // Go through errors from server and grab the components - // stored in the inputs map. Change their state to invalid - // and set the serverError message - updateInputsWithError: function (errors) { - Object.keys(errors).forEach(function (name, index) { - var component = this.inputs[name]; - var args = [{ - _isValid: false, - _serverError: errors[name] - }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } - component.setState.apply(component, args); - }.bind(this)); - this.setState({ - isSubmitting: false - }); - this.props.onError(errors); - this.props.onSubmitted(); - }, - - // Traverse the children and children of children to find - // all inputs by checking the name prop. Maybe do a better - // check here - registerInputs: function (children) { - React.Children.forEach(children, function (child) { - - if (child.props.name) { - child.props._attachToForm = this.attachToForm; - child.props._detachFromForm = this.detachFromForm; - child.props._validate = this.validate; - } - - if (child.props.children) { - this.registerInputs(child.props.children); - } - - }.bind(this)); - }, - - // Use the binded values and the actual input value to - // validate the input and set its state. Then check the - // state of the form itself - validate: function (component) { - - if (!component.props.validations) { - return; - } - - // Run through the validations, split them up and call - // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value !== '') { - component.props.validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { return JSON.parse(arg); }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } - - component.setState({ - _isValid: isValid, - _serverError: null - }, this.validateForm); - - }, - - // Validate the form by going through all child input components - // and check their state - validateForm: function () { - var allIsValid = true; - var inputs = this.inputs; - - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); - - this.setState({ - isValid: allIsValid - }); - }, - - // Method put on each input component to register - // itself to the form - attachToForm: function (component) { - this.inputs[component.props.name] = component; - this.model[component.props.name] = component.state._value; - this.validate(component); - }, - - // Method put on each input component to unregister - // itself from the form - detachFromForm: function (component) { - delete this.inputs[component.props.name]; - delete this.model[component.props.name]; - }, - render: function () { - var submitButton = React.DOM.button({ - className: this.props.submitButtonClass || options.submitButtonClass, - disabled: this.state.isSubmitting || !this.state.isValid - }, this.props.submitLabel || 'Submit'); - - var cancelButton = React.DOM.button({ - onClick: this.props.onCancel, - disabled: this.state.isSubmitting, - className: this.props.resetButtonClass || options.resetButtonClass - }, this.props.cancelLabel || 'Cancel'); - - return React.DOM.form({ - onSubmit: this.submit, - className: this.props.className - }, - this.props.children, - React.DOM.div({ - className: this.props.buttonWrapperClass || options.buttonWrapperClass - }, - this.props.showCancel || options.showCancel ? cancelButton : null, - this.props.hideSubmit || options.hideSubmit ? null : submitButton - ) - ); - - } -}); - -if (!global.exports && !global.module && (!global.define || !global.define.amd)) { - global.Formsy = Formsy; -} - -module.exports = Formsy; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"react":"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js") -}); \ No newline at end of file diff --git a/releases/0.2.0/formsy-react-0.2.0.min.js b/releases/0.2.0/formsy-react-0.2.0.min.js deleted file mode 100755 index 4c3fb00..0000000 --- a/releases/0.2.0/formsy-react-0.2.0.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,s){function n(o,u){if(!i[o]){if(!e[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(r)return r(o,!0);var p=new Error("Cannot find module '"+o+"'");throw p.code="MODULE_NOT_FOUND",p}var l=i[o]={exports:{}};e[o][0].call(l.exports,function(t){var i=e[o][1][t];return n(i?i:t)},l,l.exports,t,e,i,s)}return i[o].exports}for(var r="function"==typeof require&&require,o=0;o=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},o=function(t,e,i){var i=i||[];if("object"==typeof t)for(var s in t)o(t[s],e?e+"["+s+"]":s,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,s){var s="urlencoded"===s?"application/"+s.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===s?JSON.stringify(i):o(i),new Promise(function(n,r){try{var o=new XMLHttpRequest;o.open(t,e,!0),o.setRequestHeader("Accept","application/json"),o.setRequestHeader("Content-Type",s),o.onreadystatechange=function(){4===o.readyState&&(o.status>=200&&o.status<300?n(o.responseText?JSON.parse(o.responseText):null):r(o.responseText?JSON.parse(o.responseText):null))},o.send(i)}catch(u){r(u)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};n.defaults=function(t){p=t},n.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this.props.required&&(this.props.validations=this.props.validations?this.props.validations+",":"",this.props.validations+="isValue"),this.props._attachToForm(this)},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""},function(){this.props._validate(this)})},getValue:function(){return this.state._value},hasValue:function(){return""!==this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},n.addValidationRule=function(t,e){r[t]=e},n.Form=s.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)throw new Error("Formsy Form needs a url property to post the form");this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit(),a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json").then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var s=this.inputs[e],n=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&n.push(this.validateForm),s.setState.apply(s,n)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){s.Children.forEach(t,function(t){t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.validations){var e=!0;(t.props.required||""!==t.state._value)&&t.props.validations.split(",").forEach(function(i){var s=i.split(":"),n=s.shift();if(s=s.map(function(t){return JSON.parse(t)}),s=[t.state._value].concat(s),!r[n])throw new Error("Formsy does not have the validation rule: "+n);r[n].apply(null,s)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t})},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){var t=s.DOM.button({className:this.props.submitButtonClass||p.submitButtonClass,disabled:this.state.isSubmitting||!this.state.isValid},this.props.submitLabel||"Submit"),e=s.DOM.button({onClick:this.props.onCancel,disabled:this.state.isSubmitting,className:this.props.resetButtonClass||p.resetButtonClass},this.props.cancelLabel||"Cancel");return s.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children,s.DOM.div({className:this.props.buttonWrapperClass||p.buttonWrapperClass},this.props.showCancel||p.showCancel?e:null,this.props.hideSubmit||p.hideSubmit?null:t))}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=n),e.exports=n}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js")}); \ No newline at end of file diff --git a/releases/0.2.1/formsy-react-0.2.1.js b/releases/0.2.1/formsy-react-0.2.1.js deleted file mode 100755 index 455d635..0000000 --- a/releases/0.2.1/formsy-react-0.2.1.js +++ /dev/null @@ -1,351 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Formsy=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= min && value.length <= max; - } - return value.length >= min; - }, - equals: function (value, eql) { - return value == eql; - } -}; -var toURLEncoded = function (element,key,list){ - var list = list || []; - if(typeof(element)=='object'){ - for (var idx in element) - toURLEncoded(element[idx],key?key+'['+idx+']':idx,list); - } else { - list.push(key+'='+encodeURIComponent(element)); - } - return list.join('&'); -}; - -var request = function (method, url, data, contentType) { - - var contentType = contentType === 'urlencoded' ? 'application/' + contentType.replace('urlencoded', 'x-www-form-urlencoded') : 'application/json'; - data = contentType === 'application/json' ? JSON.stringify(data) : toURLEncoded(data); - - return new Promise(function (resolve, reject) { - try { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader('Content-Type', contentType); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } else { - reject(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } - - } - }; - xhr.send(data); - } catch (e) { - reject(e); - } - }); - -}; -var ajax = { - post: request.bind(null, 'POST'), - put: request.bind(null, 'PUT') -}; -var options = {}; - -Formsy.defaults = function (passedOptions) { - options = passedOptions; -}; - -Formsy.Mixin = { - getInitialState: function () { - return { - _value: this.props.value ? this.props.value : '', - _isValid: true - }; - }, - componentWillMount: function () { - - if (!this.props.name) { - throw new Error('Form Input requires a name property when used'); - } - - if (!this.props._attachToForm) { - throw new Error('Form Mixin requires component to be nested in a Form'); - } - - if (this.props.required) { - this.props.validations = this.props.validations ? this.props.validations + ',' : ''; - this.props.validations += 'isValue'; - } - this.props._attachToForm(this); - }, - - // Detach it when component unmounts - componentWillUnmount: function () { - this.props._detachFromForm(this); - }, - - // We validate after the value has been set - setValue: function (value) { - this.setState({ - _value: value - }, function () { - this.props._validate(this); - }.bind(this)); - }, - resetValue: function () { - this.setState({ - _value: '' - }, function () { - this.props._validate(this); - }); - }, - getValue: function () { - return this.state._value; - }, - hasValue: function () { - return this.state._value !== ''; - }, - getErrorMessage: function () { - return this.isValid() || this.showRequired() ? null : this.state._serverError || this.props.validationError; - }, - isValid: function () { - return this.state._isValid; - }, - isRequired: function () { - return this.props.required; - }, - showRequired: function () { - return this.props.required && this.state._value === ''; - }, - showError: function () { - return !this.showRequired() && !this.state._isValid; - } -}; - -Formsy.addValidationRule = function (name, func) { - validationRules[name] = func; -}; - -Formsy.Form = React.createClass({ - getInitialState: function () { - return { - isValid: true, - isSubmitting: false - }; - }, - getDefaultProps: function () { - return { - onSuccess: function () {}, - onError: function () {}, - onSubmit: function () {}, - onSubmitted: function () {} - } - }, - - // Add a map to store the inputs of the form, a model to store - // the values of the form and register child inputs - componentWillMount: function () { - this.inputs = {}; - this.model = {}; - this.registerInputs(this.props.children); - }, - - componentDidMount: function () { - this.validateForm(); - }, - - // Update model, submit to url prop and send the model - submit: function (event) { - event.preventDefault(); - - if (!this.props.url) { - throw new Error('Formsy Form needs a url property to post the form'); - } - - this.updateModel(); - this.setState({ - isSubmitting: true - }); - this.props.onSubmit(); - ajax[this.props.method || 'post'](this.props.url, this.model, this.props.contentType || options.contentType || 'json') - .then(function (response) { - this.onSuccess(response); - this.onSubmitted(); - }.bind(this)) - .catch(this.updateInputsWithError); - }, - - // Goes through all registered components and - // updates the model values - updateModel: function () { - Object.keys(this.inputs).forEach(function (name) { - var component = this.inputs[name]; - this.model[name] = component.state._value; - }.bind(this)); - }, - - // Go through errors from server and grab the components - // stored in the inputs map. Change their state to invalid - // and set the serverError message - updateInputsWithError: function (errors) { - Object.keys(errors).forEach(function (name, index) { - var component = this.inputs[name]; - var args = [{ - _isValid: false, - _serverError: errors[name] - }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } - component.setState.apply(component, args); - }.bind(this)); - this.setState({ - isSubmitting: false - }); - this.props.onError(errors); - this.props.onSubmitted(); - }, - - // Traverse the children and children of children to find - // all inputs by checking the name prop. Maybe do a better - // check here - registerInputs: function (children) { - React.Children.forEach(children, function (child) { - - if (child.props.name) { - child.props._attachToForm = this.attachToForm; - child.props._detachFromForm = this.detachFromForm; - child.props._validate = this.validate; - } - - if (child.props.children) { - this.registerInputs(child.props.children); - } - - }.bind(this)); - }, - - // Use the binded values and the actual input value to - // validate the input and set its state. Then check the - // state of the form itself - validate: function (component) { - - if (!component.props.validations) { - return; - } - - // Run through the validations, split them up and call - // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value !== '') { - component.props.validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { return JSON.parse(arg); }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } - - component.setState({ - _isValid: isValid, - _serverError: null - }, this.validateForm); - - }, - - // Validate the form by going through all child input components - // and check their state - validateForm: function () { - var allIsValid = true; - var inputs = this.inputs; - - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); - - this.setState({ - isValid: allIsValid - }); - }, - - // Method put on each input component to register - // itself to the form - attachToForm: function (component) { - this.inputs[component.props.name] = component; - this.model[component.props.name] = component.state._value; - this.validate(component); - }, - - // Method put on each input component to unregister - // itself from the form - detachFromForm: function (component) { - delete this.inputs[component.props.name]; - delete this.model[component.props.name]; - }, - render: function () { - var submitButton = React.DOM.button({ - className: this.props.submitButtonClass || options.submitButtonClass, - disabled: this.state.isSubmitting || !this.state.isValid - }, this.props.submitLabel || 'Submit'); - - var cancelButton = React.DOM.button({ - onClick: this.props.onCancel, - disabled: this.state.isSubmitting, - className: this.props.cancelButtonClass || options.cancelButtonClass - }, this.props.cancelLabel || 'Cancel'); - - return React.DOM.form({ - onSubmit: this.submit, - className: this.props.className - }, - this.props.children, - React.DOM.div({ - className: this.props.buttonWrapperClass || options.buttonWrapperClass - }, - this.props.onCancel ? cancelButton : null, - this.props.hideSubmit || options.hideSubmit ? null : submitButton - ) - ); - - } -}); - -if (!global.exports && !global.module && (!global.define || !global.define.amd)) { - global.Formsy = Formsy; -} - -module.exports = Formsy; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"react":"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js") -}); \ No newline at end of file diff --git a/releases/0.2.1/formsy-react-0.2.1.min.js b/releases/0.2.1/formsy-react-0.2.1.min.js deleted file mode 100755 index 055416f..0000000 --- a/releases/0.2.1/formsy-react-0.2.1.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,n){function s(o,u){if(!i[o]){if(!e[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(r)return r(o,!0);var p=new Error("Cannot find module '"+o+"'");throw p.code="MODULE_NOT_FOUND",p}var l=i[o]={exports:{}};e[o][0].call(l.exports,function(t){var i=e[o][1][t];return s(i?i:t)},l,l.exports,t,e,i,n)}return i[o].exports}for(var r="function"==typeof require&&require,o=0;o=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},o=function(t,e,i){var i=i||[];if("object"==typeof t)for(var n in t)o(t[n],e?e+"["+n+"]":n,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,n){var n="urlencoded"===n?"application/"+n.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===n?JSON.stringify(i):o(i),new Promise(function(s,r){try{var o=new XMLHttpRequest;o.open(t,e,!0),o.setRequestHeader("Accept","application/json"),o.setRequestHeader("Content-Type",n),o.onreadystatechange=function(){4===o.readyState&&(o.status>=200&&o.status<300?s(o.responseText?JSON.parse(o.responseText):null):r(o.responseText?JSON.parse(o.responseText):null))},o.send(i)}catch(u){r(u)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};s.defaults=function(t){p=t},s.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this.props.required&&(this.props.validations=this.props.validations?this.props.validations+",":"",this.props.validations+="isValue"),this.props._attachToForm(this)},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""},function(){this.props._validate(this)})},getValue:function(){return this.state._value},hasValue:function(){return""!==this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},s.addValidationRule=function(t,e){r[t]=e},s.Form=n.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)throw new Error("Formsy Form needs a url property to post the form");this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit(),a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json").then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var n=this.inputs[e],s=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&s.push(this.validateForm),n.setState.apply(n,s)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){n.Children.forEach(t,function(t){t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.validations){var e=!0;(t.props.required||""!==t.state._value)&&t.props.validations.split(",").forEach(function(i){var n=i.split(":"),s=n.shift();if(n=n.map(function(t){return JSON.parse(t)}),n=[t.state._value].concat(n),!r[s])throw new Error("Formsy does not have the validation rule: "+s);r[s].apply(null,n)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t})},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){var t=n.DOM.button({className:this.props.submitButtonClass||p.submitButtonClass,disabled:this.state.isSubmitting||!this.state.isValid},this.props.submitLabel||"Submit"),e=n.DOM.button({onClick:this.props.onCancel,disabled:this.state.isSubmitting,className:this.props.cancelButtonClass||p.cancelButtonClass},this.props.cancelLabel||"Cancel");return n.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children,n.DOM.div({className:this.props.buttonWrapperClass||p.buttonWrapperClass},this.props.onCancel?e:null,this.props.hideSubmit||p.hideSubmit?null:t))}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=s),e.exports=s}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js")}); \ No newline at end of file diff --git a/releases/0.2.3/formsy-react-0.2.3.js b/releases/0.2.3/formsy-react-0.2.3.js deleted file mode 100755 index 79feb3f..0000000 --- a/releases/0.2.3/formsy-react-0.2.3.js +++ /dev/null @@ -1,358 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Formsy=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= min && value.length <= max; - } - return value.length >= min; - }, - equals: function (value, eql) { - return value == eql; - } -}; -var toURLEncoded = function (element,key,list){ - var list = list || []; - if(typeof(element)=='object'){ - for (var idx in element) - toURLEncoded(element[idx],key?key+'['+idx+']':idx,list); - } else { - list.push(key+'='+encodeURIComponent(element)); - } - return list.join('&'); -}; - -var request = function (method, url, data, contentType) { - - var contentType = contentType === 'urlencoded' ? 'application/' + contentType.replace('urlencoded', 'x-www-form-urlencoded') : 'application/json'; - data = contentType === 'application/json' ? JSON.stringify(data) : toURLEncoded(data); - - return new Promise(function (resolve, reject) { - try { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader('Content-Type', contentType); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } else { - reject(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } - - } - }; - xhr.send(data); - } catch (e) { - reject(e); - } - }); - -}; -var ajax = { - post: request.bind(null, 'POST'), - put: request.bind(null, 'PUT') -}; -var options = {}; - -Formsy.defaults = function (passedOptions) { - options = passedOptions; -}; - -Formsy.Mixin = { - getInitialState: function () { - return { - _value: this.props.value ? this.props.value : '', - _isValid: true - }; - }, - componentWillMount: function () { - - if (!this.props.name) { - throw new Error('Form Input requires a name property when used'); - } - - if (!this.props._attachToForm) { - throw new Error('Form Mixin requires component to be nested in a Form'); - } - - if (this.props.required) { - this.props.validations = this.props.validations ? this.props.validations + ',' : ''; - this.props.validations += 'isValue'; - } - this.props._attachToForm(this); - }, - - // We have to make the validate method is kept when new props are added - componentWillReceiveProps: function (nextProps) { - nextProps._attachToForm = this.props._attachToForm; - nextProps._detachFromForm = this.props._detachFromForm; - nextProps._validate = this.props._validate; - }, - - // Detach it when component unmounts - componentWillUnmount: function () { - this.props._detachFromForm(this); - }, - - // We validate after the value has been set - setValue: function (value) { - this.setState({ - _value: value - }, function () { - this.props._validate(this); - }.bind(this)); - }, - resetValue: function () { - this.setState({ - _value: '' - }, function () { - this.props._validate(this); - }); - }, - getValue: function () { - return this.state._value; - }, - hasValue: function () { - return this.state._value !== ''; - }, - getErrorMessage: function () { - return this.isValid() || this.showRequired() ? null : this.state._serverError || this.props.validationError; - }, - isValid: function () { - return this.state._isValid; - }, - isRequired: function () { - return this.props.required; - }, - showRequired: function () { - return this.props.required && this.state._value === ''; - }, - showError: function () { - return !this.showRequired() && !this.state._isValid; - } -}; - -Formsy.addValidationRule = function (name, func) { - validationRules[name] = func; -}; - -Formsy.Form = React.createClass({ - getInitialState: function () { - return { - isValid: true, - isSubmitting: false - }; - }, - getDefaultProps: function () { - return { - onSuccess: function () {}, - onError: function () {}, - onSubmit: function () {}, - onSubmitted: function () {} - } - }, - - // Add a map to store the inputs of the form, a model to store - // the values of the form and register child inputs - componentWillMount: function () { - this.inputs = {}; - this.model = {}; - this.registerInputs(this.props.children); - }, - - componentDidMount: function () { - this.validateForm(); - }, - - // Update model, submit to url prop and send the model - submit: function (event) { - event.preventDefault(); - - if (!this.props.url) { - throw new Error('Formsy Form needs a url property to post the form'); - } - - this.updateModel(); - this.setState({ - isSubmitting: true - }); - this.props.onSubmit(); - ajax[this.props.method || 'post'](this.props.url, this.model, this.props.contentType || options.contentType || 'json') - .then(function (response) { - this.onSuccess(response); - this.onSubmitted(); - }.bind(this)) - .catch(this.updateInputsWithError); - }, - - // Goes through all registered components and - // updates the model values - updateModel: function () { - Object.keys(this.inputs).forEach(function (name) { - var component = this.inputs[name]; - this.model[name] = component.state._value; - }.bind(this)); - }, - - // Go through errors from server and grab the components - // stored in the inputs map. Change their state to invalid - // and set the serverError message - updateInputsWithError: function (errors) { - Object.keys(errors).forEach(function (name, index) { - var component = this.inputs[name]; - var args = [{ - _isValid: false, - _serverError: errors[name] - }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } - component.setState.apply(component, args); - }.bind(this)); - this.setState({ - isSubmitting: false - }); - this.props.onError(errors); - this.props.onSubmitted(); - }, - - // Traverse the children and children of children to find - // all inputs by checking the name prop. Maybe do a better - // check here - registerInputs: function (children) { - React.Children.forEach(children, function (child) { - - if (child.props && child.props.name) { - child.props._attachToForm = this.attachToForm; - child.props._detachFromForm = this.detachFromForm; - child.props._validate = this.validate; - } - - if (child.props && child.props.children) { - this.registerInputs(child.props.children); - } - - }.bind(this)); - }, - - // Use the binded values and the actual input value to - // validate the input and set its state. Then check the - // state of the form itself - validate: function (component) { - - if (!component.props.validations) { - return; - } - - // Run through the validations, split them up and call - // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value !== '') { - component.props.validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { return JSON.parse(arg); }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } - - component.setState({ - _isValid: isValid, - _serverError: null - }, this.validateForm); - - }, - - // Validate the form by going through all child input components - // and check their state - validateForm: function () { - var allIsValid = true; - var inputs = this.inputs; - - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); - - this.setState({ - isValid: allIsValid - }); - }, - - // Method put on each input component to register - // itself to the form - attachToForm: function (component) { - this.inputs[component.props.name] = component; - this.model[component.props.name] = component.state._value; - this.validate(component); - }, - - // Method put on each input component to unregister - // itself from the form - detachFromForm: function (component) { - delete this.inputs[component.props.name]; - delete this.model[component.props.name]; - }, - render: function () { - var submitButton = React.DOM.button({ - className: this.props.submitButtonClass || options.submitButtonClass, - disabled: this.state.isSubmitting || !this.state.isValid - }, this.props.submitLabel || 'Submit'); - - var cancelButton = React.DOM.button({ - onClick: this.props.onCancel, - disabled: this.state.isSubmitting, - className: this.props.cancelButtonClass || options.cancelButtonClass - }, this.props.cancelLabel || 'Cancel'); - - return React.DOM.form({ - onSubmit: this.submit, - className: this.props.className - }, - this.props.children, - React.DOM.div({ - className: this.props.buttonWrapperClass || options.buttonWrapperClass - }, - this.props.onCancel ? cancelButton : null, - this.props.hideSubmit || options.hideSubmit ? null : submitButton - ) - ); - - } -}); - -if (!global.exports && !global.module && (!global.define || !global.define.amd)) { - global.Formsy = Formsy; -} - -module.exports = Formsy; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"react":"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js") -}); \ No newline at end of file diff --git a/releases/0.2.3/formsy-react-0.2.3.min.js b/releases/0.2.3/formsy-react-0.2.3.min.js deleted file mode 100755 index 8f21743..0000000 --- a/releases/0.2.3/formsy-react-0.2.3.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,n){function s(r,u){if(!i[r]){if(!e[r]){var a="function"==typeof require&&require;if(!u&&a)return a(r,!0);if(o)return o(r,!0);var p=new Error("Cannot find module '"+r+"'");throw p.code="MODULE_NOT_FOUND",p}var l=i[r]={exports:{}};e[r][0].call(l.exports,function(t){var i=e[r][1][t];return s(i?i:t)},l,l.exports,t,e,i,n)}return i[r].exports}for(var o="function"==typeof require&&require,r=0;r=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},r=function(t,e,i){var i=i||[];if("object"==typeof t)for(var n in t)r(t[n],e?e+"["+n+"]":n,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,n){var n="urlencoded"===n?"application/"+n.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===n?JSON.stringify(i):r(i),new Promise(function(s,o){try{var r=new XMLHttpRequest;r.open(t,e,!0),r.setRequestHeader("Accept","application/json"),r.setRequestHeader("Content-Type",n),r.onreadystatechange=function(){4===r.readyState&&(r.status>=200&&r.status<300?s(r.responseText?JSON.parse(r.responseText):null):o(r.responseText?JSON.parse(r.responseText):null))},r.send(i)}catch(u){o(u)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};s.defaults=function(t){p=t},s.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this.props.required&&(this.props.validations=this.props.validations?this.props.validations+",":"",this.props.validations+="isValue"),this.props._attachToForm(this)},componentWillReceiveProps:function(t){t._attachToForm=this.props._attachToForm,t._detachFromForm=this.props._detachFromForm,t._validate=this.props._validate},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""},function(){this.props._validate(this)})},getValue:function(){return this.state._value},hasValue:function(){return""!==this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},s.addValidationRule=function(t,e){o[t]=e},s.Form=n.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)throw new Error("Formsy Form needs a url property to post the form");this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit(),a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json").then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var n=this.inputs[e],s=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&s.push(this.validateForm),n.setState.apply(n,s)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){n.Children.forEach(t,function(t){t.props&&t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props&&t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.validations){var e=!0;(t.props.required||""!==t.state._value)&&t.props.validations.split(",").forEach(function(i){var n=i.split(":"),s=n.shift();if(n=n.map(function(t){return JSON.parse(t)}),n=[t.state._value].concat(n),!o[s])throw new Error("Formsy does not have the validation rule: "+s);o[s].apply(null,n)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t})},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){var t=n.DOM.button({className:this.props.submitButtonClass||p.submitButtonClass,disabled:this.state.isSubmitting||!this.state.isValid},this.props.submitLabel||"Submit"),e=n.DOM.button({onClick:this.props.onCancel,disabled:this.state.isSubmitting,className:this.props.cancelButtonClass||p.cancelButtonClass},this.props.cancelLabel||"Cancel");return n.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children,n.DOM.div({className:this.props.buttonWrapperClass||p.buttonWrapperClass},this.props.onCancel?e:null,this.props.hideSubmit||p.hideSubmit?null:t))}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=s),e.exports=s}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},["/Users/christianalfoni/Documents/dev/formsy-react/src/main.js"])("/Users/christianalfoni/Documents/dev/formsy-react/src/main.js")}); \ No newline at end of file diff --git a/releases/0.3.0/formsy-react-0.3.0.js b/releases/0.3.0/formsy-react-0.3.0.js deleted file mode 100755 index 582f758..0000000 --- a/releases/0.3.0/formsy-react-0.3.0.js +++ /dev/null @@ -1,362 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Formsy=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= min && value.length <= max; - } - return value.length >= min; - }, - equals: function (value, eql) { - return value == eql; - } -}; - -var toURLEncoded = function (element, key, list) { - var list = list || []; - if (typeof (element) == 'object') { - for (var idx in element) - toURLEncoded(element[idx], key ? key + '[' + idx + ']' : idx, list); - } else { - list.push(key + '=' + encodeURIComponent(element)); - } - return list.join('&'); -}; - -var request = function (method, url, data, contentType, headers) { - - var contentType = contentType === 'urlencoded' ? 'application/' + contentType.replace('urlencoded', 'x-www-form-urlencoded') : 'application/json'; - data = contentType === 'application/json' ? JSON.stringify(data) : toURLEncoded(data); - - return new Promise(function (resolve, reject) { - try { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader('Content-Type', contentType); - - // Add passed headers - Object.keys(headers).forEach(function (header) { - xhr.setRequestHeader(header, headers[header]); - }); - - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } else { - reject(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } - - } - }; - xhr.send(data); - } catch (e) { - reject(e); - } - }); - -}; -var ajax = { - post: request.bind(null, 'POST'), - put: request.bind(null, 'PUT') -}; -var options = {}; - -Formsy.defaults = function (passedOptions) { - options = passedOptions; -}; - -Formsy.Mixin = { - getInitialState: function () { - return { - _value: this.props.value ? this.props.value : '', - _isValid: true - }; - }, - componentWillMount: function () { - - if (!this.props.name) { - throw new Error('Form Input requires a name property when used'); - } - - if (!this.props._attachToForm) { - throw new Error('Form Mixin requires component to be nested in a Form'); - } - - if (this.props.required) { - this.props.validations = this.props.validations ? this.props.validations + ',' : ''; - this.props.validations += 'isValue'; - } - this.props._attachToForm(this); - }, - - // We have to make the validate method is kept when new props are added - componentWillReceiveProps: function (nextProps) { - nextProps._attachToForm = this.props._attachToForm; - nextProps._detachFromForm = this.props._detachFromForm; - nextProps._validate = this.props._validate; - }, - - // Detach it when component unmounts - componentWillUnmount: function () { - this.props._detachFromForm(this); - }, - - // We validate after the value has been set - setValue: function (value) { - this.setState({ - _value: value - }, function () { - this.props._validate(this); - }.bind(this)); - }, - resetValue: function () { - this.setState({ - _value: '' - }, function () { - this.props._validate(this); - }); - }, - getValue: function () { - return this.state._value; - }, - hasValue: function () { - return this.state._value !== ''; - }, - getErrorMessage: function () { - return this.isValid() || this.showRequired() ? null : this.state._serverError || this.props.validationError; - }, - isValid: function () { - return this.state._isValid; - }, - isRequired: function () { - return this.props.required; - }, - showRequired: function () { - return this.props.required && this.state._value === ''; - }, - showError: function () { - return !this.showRequired() && !this.state._isValid; - } -}; - -Formsy.addValidationRule = function (name, func) { - validationRules[name] = func; -}; - -Formsy.Form = React.createClass({ - getInitialState: function () { - return { - isValid: true, - isSubmitting: false - }; - }, - getDefaultProps: function () { - return { - headers: {}, - onSuccess: function () {}, - onError: function () {}, - onSubmit: function () {}, - onSubmitted: function () {}, - onValid: function () {}, - onInvalid: function () {} - }; - }, - - // Add a map to store the inputs of the form, a model to store - // the values of the form and register child inputs - componentWillMount: function () { - this.inputs = {}; - this.model = {}; - this.registerInputs(this.props.children); - }, - - componentDidMount: function () { - this.validateForm(); - }, - - // Update model, submit to url prop and send the model - submit: function (event) { - event.preventDefault(); - - if (!this.props.url) { - throw new Error('Formsy Form needs a url property to post the form'); - } - - this.updateModel(); - this.setState({ - isSubmitting: true - }); - - this.props.onSubmit(); - - var headers = (Object.keys(this.props.headers).length && this.props.headers) || options.headers; - console.log('headers', headers); - ajax[this.props.method || 'post'](this.props.url, this.model, this.props.contentType || options.contentType || 'json', headers) - .then(function (response) { - this.onSuccess(response); - this.onSubmitted(); - }.bind(this)) - .catch(this.updateInputsWithError); - }, - - // Goes through all registered components and - // updates the model values - updateModel: function () { - Object.keys(this.inputs).forEach(function (name) { - var component = this.inputs[name]; - this.model[name] = component.state._value; - }.bind(this)); - }, - - // Go through errors from server and grab the components - // stored in the inputs map. Change their state to invalid - // and set the serverError message - updateInputsWithError: function (errors) { - Object.keys(errors).forEach(function (name, index) { - var component = this.inputs[name]; - var args = [{ - _isValid: false, - _serverError: errors[name] - }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } - component.setState.apply(component, args); - }.bind(this)); - this.setState({ - isSubmitting: false - }); - this.props.onError(errors); - this.props.onSubmitted(); - }, - - // Traverse the children and children of children to find - // all inputs by checking the name prop. Maybe do a better - // check here - registerInputs: function (children) { - React.Children.forEach(children, function (child) { - - if (child.props && child.props.name) { - child.props._attachToForm = this.attachToForm; - child.props._detachFromForm = this.detachFromForm; - child.props._validate = this.validate; - } - - if (child.props && child.props.children) { - this.registerInputs(child.props.children); - } - - }.bind(this)); - }, - - // Use the binded values and the actual input value to - // validate the input and set its state. Then check the - // state of the form itself - validate: function (component) { - - if (!component.props.validations) { - return; - } - - // Run through the validations, split them up and call - // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value !== '') { - component.props.validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { - return JSON.parse(arg); - }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } - - component.setState({ - _isValid: isValid, - _serverError: null - }, this.validateForm); - - }, - - // Validate the form by going through all child input components - // and check their state - validateForm: function () { - var allIsValid = true; - var inputs = this.inputs; - - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); - - this.setState({ - isValid: allIsValid - }); - - allIsValid && this.props.onValid(); - !allIsValid && this.props.onInvalid(); - }, - - // Method put on each input component to register - // itself to the form - attachToForm: function (component) { - this.inputs[component.props.name] = component; - this.model[component.props.name] = component.state._value; - this.validate(component); - }, - - // Method put on each input component to unregister - // itself from the form - detachFromForm: function (component) { - delete this.inputs[component.props.name]; - delete this.model[component.props.name]; - }, - render: function () { - - return React.DOM.form({ - onSubmit: this.submit, - className: this.props.className - }, - this.props.children - ); - - } -}); - -if (!global.exports && !global.module && (!global.define || !global.define.amd)) { - global.Formsy = Formsy; -} - -module.exports = Formsy; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"react":"react"}]},{},[1])(1) -}); \ No newline at end of file diff --git a/releases/0.3.0/formsy-react-0.3.0.min.js b/releases/0.3.0/formsy-react-0.3.0.min.js deleted file mode 100755 index 2ae5aed..0000000 --- a/releases/0.3.0/formsy-react-0.3.0.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,n){function o(s,u){if(!i[s]){if(!e[s]){var a="function"==typeof require&&require;if(!u&&a)return a(s,!0);if(r)return r(s,!0);var p=new Error("Cannot find module '"+s+"'");throw p.code="MODULE_NOT_FOUND",p}var F=i[s]={exports:{}};e[s][0].call(F.exports,function(t){var i=e[s][1][t];return o(i?i:t)},F,F.exports,t,e,i,n)}return i[s].exports}for(var r="function"==typeof require&&require,s=0;s=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},s=function(t,e,i){var i=i||[];if("object"==typeof t)for(var n in t)s(t[n],e?e+"["+n+"]":n,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,n,o){var n="urlencoded"===n?"application/"+n.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===n?JSON.stringify(i):s(i),new Promise(function(r,s){try{var u=new XMLHttpRequest;u.open(t,e,!0),u.setRequestHeader("Accept","application/json"),u.setRequestHeader("Content-Type",n),Object.keys(o).forEach(function(t){u.setRequestHeader(t,o[t])}),u.onreadystatechange=function(){4===u.readyState&&(u.status>=200&&u.status<300?r(u.responseText?JSON.parse(u.responseText):null):s(u.responseText?JSON.parse(u.responseText):null))},u.send(i)}catch(a){s(a)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};o.defaults=function(t){p=t},o.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this.props.required&&(this.props.validations=this.props.validations?this.props.validations+",":"",this.props.validations+="isValue"),this.props._attachToForm(this)},componentWillReceiveProps:function(t){t._attachToForm=this.props._attachToForm,t._detachFromForm=this.props._detachFromForm,t._validate=this.props._validate},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""},function(){this.props._validate(this)})},getValue:function(){return this.state._value},hasValue:function(){return""!==this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},o.addValidationRule=function(t,e){r[t]=e},o.Form=n.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{headers:{},onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){},onValid:function(){},onInvalid:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)throw new Error("Formsy Form needs a url property to post the form");this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit();var e=Object.keys(this.props.headers).length&&this.props.headers||p.headers;console.log("headers",e),a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json",e).then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var n=this.inputs[e],o=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&o.push(this.validateForm),n.setState.apply(n,o)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){n.Children.forEach(t,function(t){t.props&&t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props&&t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.validations){var e=!0;(t.props.required||""!==t.state._value)&&t.props.validations.split(",").forEach(function(i){var n=i.split(":"),o=n.shift();if(n=n.map(function(t){return JSON.parse(t)}),n=[t.state._value].concat(n),!r[o])throw new Error("Formsy does not have the validation rule: "+o);r[o].apply(null,n)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t}),t&&this.props.onValid(),!t&&this.props.onInvalid()},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){return n.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children)}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=o),e.exports=o}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},[1])(1)}); \ No newline at end of file diff --git a/releases/0.4.0/formsy-react-0.4.0.js b/releases/0.4.0/formsy-react-0.4.0.js deleted file mode 100755 index a1ffb1a..0000000 --- a/releases/0.4.0/formsy-react-0.4.0.js +++ /dev/null @@ -1,381 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Formsy=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= min && value.length <= max; - } - return value.length >= min; - }, - equals: function (value, eql) { - return value == eql; - } -}; - -var toURLEncoded = function (element, key, list) { - var list = list || []; - if (typeof (element) == 'object') { - for (var idx in element) - toURLEncoded(element[idx], key ? key + '[' + idx + ']' : idx, list); - } else { - list.push(key + '=' + encodeURIComponent(element)); - } - return list.join('&'); -}; - -var request = function (method, url, data, contentType, headers) { - - var contentType = contentType === 'urlencoded' ? 'application/' + contentType.replace('urlencoded', 'x-www-form-urlencoded') : 'application/json'; - data = contentType === 'application/json' ? JSON.stringify(data) : toURLEncoded(data); - - return new Promise(function (resolve, reject) { - try { - var xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader('Accept', 'application/json'); - xhr.setRequestHeader('Content-Type', contentType); - - // Add passed headers - Object.keys(headers).forEach(function (header) { - xhr.setRequestHeader(header, headers[header]); - }); - - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - - if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } else { - reject(xhr.responseText ? JSON.parse(xhr.responseText) : null); - } - - } - }; - xhr.send(data); - } catch (e) { - reject(e); - } - }); - -}; -var ajax = { - post: request.bind(null, 'POST'), - put: request.bind(null, 'PUT') -}; -var options = {}; - -Formsy.defaults = function (passedOptions) { - options = passedOptions; -}; - -Formsy.Mixin = { - getInitialState: function () { - return { - _value: this.props.value ? this.props.value : '', - _isValid: true - }; - }, - componentWillMount: function () { - - if (!this.props.name) { - throw new Error('Form Input requires a name property when used'); - } - - if (!this.props._attachToForm) { - throw new Error('Form Mixin requires component to be nested in a Form'); - } - - if (this.props.required) { - this.props.validations = this.props.validations ? this.props.validations + ',' : ''; - this.props.validations += 'isValue'; - } - this.props._attachToForm(this); - }, - - // We have to make the validate method is kept when new props are added - componentWillReceiveProps: function (nextProps) { - nextProps._attachToForm = this.props._attachToForm; - nextProps._detachFromForm = this.props._detachFromForm; - nextProps._validate = this.props._validate; - }, - - // Detach it when component unmounts - componentWillUnmount: function () { - this.props._detachFromForm(this); - }, - - // We validate after the value has been set - setValue: function (value) { - this.setState({ - _value: value - }, function () { - this.props._validate(this); - }.bind(this)); - }, - resetValue: function () { - this.setState({ - _value: '' - }, function () { - this.props._validate(this); - }); - }, - getValue: function () { - return this.state._value; - }, - hasValue: function () { - return this.state._value !== ''; - }, - getErrorMessage: function () { - return this.isValid() || this.showRequired() ? null : this.state._serverError || this.props.validationError; - }, - isValid: function () { - return this.state._isValid; - }, - isRequired: function () { - return this.props.required; - }, - showRequired: function () { - return this.props.required && this.state._value === ''; - }, - showError: function () { - return !this.showRequired() && !this.state._isValid; - } -}; - -Formsy.addValidationRule = function (name, func) { - validationRules[name] = func; -}; - -Formsy.Form = React.createClass({ - getInitialState: function () { - return { - isValid: true, - isSubmitting: false - }; - }, - getDefaultProps: function () { - return { - headers: {}, - onSuccess: function () {}, - onError: function () {}, - onSubmit: function () {}, - onSubmitted: function () {}, - onValid: function () {}, - onInvalid: function () {} - }; - }, - - // Add a map to store the inputs of the form, a model to store - // the values of the form and register child inputs - componentWillMount: function () { - this.inputs = {}; - this.model = {}; - this.registerInputs(this.props.children); - }, - - componentDidMount: function () { - this.validateForm(); - }, - - // Update model, submit to url prop and send the model - submit: function (event) { - event.preventDefault(); - - // To support use cases where no async or request operation is needed. - // The "onSubmit" callback is called with the model e.g. {fieldName: "myValue"}, - // if wanting to reset the entire form to original state, the second param is a callback for this. - if (!this.props.url) { - this.updateModel(); - this.props.onSubmit(this.model, this.resetModel); - return; - } - - this.updateModel(); - this.setState({ - isSubmitting: true - }); - - this.props.onSubmit(); - - var headers = (Object.keys(this.props.headers).length && this.props.headers) || options.headers; - - ajax[this.props.method || 'post'](this.props.url, this.model, this.props.contentType || options.contentType || 'json', headers) - .then(function (response) { - this.onSuccess(response); - this.onSubmitted(); - }.bind(this)) - .catch(this.updateInputsWithError); - }, - - // Goes through all registered components and - // updates the model values - updateModel: function () { - Object.keys(this.inputs).forEach(function (name) { - var component = this.inputs[name]; - this.model[name] = component.state._value; - }.bind(this)); - }, - - // Reset each key in the model to the original / initial value - resetModel: function() { - Object.keys(this.inputs).forEach(function (name) { - this.inputs[name].resetValue(); - }.bind(this)); - this.validateForm(); - }, - - // Go through errors from server and grab the components - // stored in the inputs map. Change their state to invalid - // and set the serverError message - updateInputsWithError: function (errors) { - Object.keys(errors).forEach(function (name, index) { - var component = this.inputs[name]; - var args = [{ - _isValid: false, - _serverError: errors[name] - }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } - component.setState.apply(component, args); - }.bind(this)); - this.setState({ - isSubmitting: false - }); - this.props.onError(errors); - this.props.onSubmitted(); - }, - - // Traverse the children and children of children to find - // all inputs by checking the name prop. Maybe do a better - // check here - registerInputs: function (children) { - React.Children.forEach(children, function (child) { - - if (child.props && child.props.name) { - child.props._attachToForm = this.attachToForm; - child.props._detachFromForm = this.detachFromForm; - child.props._validate = this.validate; - } - - if (child.props && child.props.children) { - this.registerInputs(child.props.children); - } - - }.bind(this)); - }, - - // Use the binded values and the actual input value to - // validate the input and set its state. Then check the - // state of the form itself - validate: function (component) { - - if (!component.props.validations) { - return; - } - - // Run through the validations, split them up and call - // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value !== '') { - component.props.validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { - return JSON.parse(arg); - }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } - - component.setState({ - _isValid: isValid, - _serverError: null - }, this.validateForm); - - }, - - // Validate the form by going through all child input components - // and check their state - validateForm: function () { - var allIsValid = true; - var inputs = this.inputs; - - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); - - this.setState({ - isValid: allIsValid - }); - - allIsValid && this.props.onValid(); - !allIsValid && this.props.onInvalid(); - }, - - // Method put on each input component to register - // itself to the form - attachToForm: function (component) { - this.inputs[component.props.name] = component; - this.model[component.props.name] = component.state._value; - this.validate(component); - }, - - // Method put on each input component to unregister - // itself from the form - detachFromForm: function (component) { - delete this.inputs[component.props.name]; - delete this.model[component.props.name]; - }, - render: function () { - - return React.DOM.form({ - onSubmit: this.submit, - className: this.props.className - }, - this.props.children - ); - - } -}); - -if (!global.exports && !global.module && (!global.define || !global.define.amd)) { - global.Formsy = Formsy; -} - -module.exports = Formsy; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"react":"react"}]},{},[1])(1) -}); \ No newline at end of file diff --git a/releases/0.4.0/formsy-react-0.4.0.min.js b/releases/0.4.0/formsy-react-0.4.0.min.js deleted file mode 100755 index 78f6338..0000000 --- a/releases/0.4.0/formsy-react-0.4.0.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,n){function o(r,u){if(!i[r]){if(!e[r]){var a="function"==typeof require&&require;if(!u&&a)return a(r,!0);if(s)return s(r,!0);var p=new Error("Cannot find module '"+r+"'");throw p.code="MODULE_NOT_FOUND",p}var d=i[r]={exports:{}};e[r][0].call(d.exports,function(t){var i=e[r][1][t];return o(i?i:t)},d,d.exports,t,e,i,n)}return i[r].exports}for(var s="function"==typeof require&&require,r=0;r=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},r=function(t,e,i){var i=i||[];if("object"==typeof t)for(var n in t)r(t[n],e?e+"["+n+"]":n,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,n,o){var n="urlencoded"===n?"application/"+n.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===n?JSON.stringify(i):r(i),new Promise(function(s,r){try{var u=new XMLHttpRequest;u.open(t,e,!0),u.setRequestHeader("Accept","application/json"),u.setRequestHeader("Content-Type",n),Object.keys(o).forEach(function(t){u.setRequestHeader(t,o[t])}),u.onreadystatechange=function(){4===u.readyState&&(u.status>=200&&u.status<300?s(u.responseText?JSON.parse(u.responseText):null):r(u.responseText?JSON.parse(u.responseText):null))},u.send(i)}catch(a){r(a)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};o.defaults=function(t){p=t},o.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this.props.required&&(this.props.validations=this.props.validations?this.props.validations+",":"",this.props.validations+="isValue"),this.props._attachToForm(this)},componentWillReceiveProps:function(t){t._attachToForm=this.props._attachToForm,t._detachFromForm=this.props._detachFromForm,t._validate=this.props._validate},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""},function(){this.props._validate(this)})},getValue:function(){return this.state._value},hasValue:function(){return""!==this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},o.addValidationRule=function(t,e){s[t]=e},o.Form=n.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{headers:{},onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){},onValid:function(){},onInvalid:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)return this.updateModel(),void this.props.onSubmit(this.model,this.resetModel);this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit();var e=Object.keys(this.props.headers).length&&this.props.headers||p.headers;a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json",e).then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},resetModel:function(){Object.keys(this.inputs).forEach(function(t){this.inputs[t].resetValue()}.bind(this)),this.validateForm()},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var n=this.inputs[e],o=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&o.push(this.validateForm),n.setState.apply(n,o)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){n.Children.forEach(t,function(t){t.props&&t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props&&t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.validations){var e=!0;(t.props.required||""!==t.state._value)&&t.props.validations.split(",").forEach(function(i){var n=i.split(":"),o=n.shift();if(n=n.map(function(t){return JSON.parse(t)}),n=[t.state._value].concat(n),!s[o])throw new Error("Formsy does not have the validation rule: "+o);s[o].apply(null,n)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t}),t&&this.props.onValid(),!t&&this.props.onInvalid()},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){return n.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children)}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=o),e.exports=o}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},[1])(1)}); \ No newline at end of file diff --git a/releases/0.4.1/formsy-react-0.4.1.min.js b/releases/0.4.1/formsy-react-0.4.1.min.js deleted file mode 100755 index 9f4041c..0000000 --- a/releases/0.4.1/formsy-react-0.4.1.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,n){function o(r,u){if(!i[r]){if(!e[r]){var a="function"==typeof require&&require;if(!u&&a)return a(r,!0);if(s)return s(r,!0);var p=new Error("Cannot find module '"+r+"'");throw p.code="MODULE_NOT_FOUND",p}var d=i[r]={exports:{}};e[r][0].call(d.exports,function(t){var i=e[r][1][t];return o(i?i:t)},d,d.exports,t,e,i,n)}return i[r].exports}for(var s="function"==typeof require&&require,r=0;r=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},r=function(t,e,i){var i=i||[];if("object"==typeof t)for(var n in t)r(t[n],e?e+"["+n+"]":n,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,n,o){var n="urlencoded"===n?"application/"+n.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===n?JSON.stringify(i):r(i),new Promise(function(s,r){try{var u=new XMLHttpRequest;u.open(t,e,!0),u.setRequestHeader("Accept","application/json"),u.setRequestHeader("Content-Type",n),Object.keys(o).forEach(function(t){u.setRequestHeader(t,o[t])}),u.onreadystatechange=function(){4===u.readyState&&(u.status>=200&&u.status<300?s(u.responseText?JSON.parse(u.responseText):null):r(u.responseText?JSON.parse(u.responseText):null))},u.send(i)}catch(a){r(a)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};o.defaults=function(t){p=t},o.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this._validations=this.props.validations||"",this.props.required&&(this._validations=this.props.validations?this.props.validations+",":"",this._validations+="isValue"),this.props._attachToForm(this)},componentWillReceiveProps:function(t){t._attachToForm=this.props._attachToForm,t._detachFromForm=this.props._detachFromForm,t._validate=this.props._validate},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""},function(){this.props._validate(this)})},getValue:function(){return this.state._value},hasValue:function(){return""!==this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},o.addValidationRule=function(t,e){s[t]=e},o.Form=n.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{headers:{},onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){},onValid:function(){},onInvalid:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)return this.updateModel(),void this.props.onSubmit(this.model,this.resetModel);this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit();var e=Object.keys(this.props.headers).length&&this.props.headers||p.headers;a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json",e).then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.updateInputsWithError)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},resetModel:function(){Object.keys(this.inputs).forEach(function(t){this.inputs[t].resetValue()}.bind(this)),this.validateForm()},updateInputsWithError:function(t){Object.keys(t).forEach(function(e,i){var n=this.inputs[e],o=[{_isValid:!1,_serverError:t[e]}];i===Object.keys(t).length-1&&o.push(this.validateForm),n.setState.apply(n,o)}.bind(this)),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){n.Children.forEach(t,function(t){t.props&&t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props&&t.props.children&&this.registerInputs(t.props.children)}.bind(this))},validate:function(t){if(t.props.required||t._validations){var e=!0;(t.props.required||""!==t.state._value)&&t._validations.split(",").forEach(function(i){var n=i.split(":"),o=n.shift();if(n=n.map(function(t){return JSON.parse(t)}),n=[t.state._value].concat(n),!s[o])throw new Error("Formsy does not have the validation rule: "+o);s[o].apply(null,n)||(e=!1)}),t.setState({_isValid:e,_serverError:null},this.validateForm)}},validateForm:function(){var t=!0,e=this.inputs;Object.keys(e).forEach(function(i){e[i].state._isValid||(t=!1)}),this.setState({isValid:t}),t&&this.props.onValid(),!t&&this.props.onInvalid()},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){return n.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children)}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=o),e.exports=o}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},[1])(1)}); \ No newline at end of file diff --git a/releases/0.4.1/formsy-react-0.4.1.js b/releases/formsy-react.js similarity index 85% rename from releases/0.4.1/formsy-react-0.4.1.js rename to releases/formsy-react.js index 5267682..e6a97b7 100755 --- a/releases/0.4.1/formsy-react-0.4.1.js +++ b/releases/formsy-react.js @@ -212,7 +212,7 @@ Formsy.Form = React.createClass({ // if wanting to reset the entire form to original state, the second param is a callback for this. if (!this.props.url) { this.updateModel(); - this.props.onSubmit(this.model, this.resetModel); + this.props.onSubmit(this.model, this.resetModel, this.updateInputsWithError); return; } @@ -230,7 +230,7 @@ Formsy.Form = React.createClass({ this.onSuccess(response); this.onSubmitted(); }.bind(this)) - .catch(this.updateInputsWithError); + .catch(this.failSubmit); }, // Goes through all registered components and @@ -241,9 +241,9 @@ Formsy.Form = React.createClass({ this.model[name] = component.state._value; }.bind(this)); }, - + // Reset each key in the model to the original / initial value - resetModel: function() { + resetModel: function () { Object.keys(this.inputs).forEach(function (name) { this.inputs[name].resetValue(); }.bind(this)); @@ -256,15 +256,21 @@ Formsy.Form = React.createClass({ updateInputsWithError: function (errors) { Object.keys(errors).forEach(function (name, index) { var component = this.inputs[name]; + + if (!component) { + throw new Error('You are trying to update an input that does not exists. Verify errors object with input names. ' + JSON.stringify(errors)); + } + var args = [{ _isValid: false, _serverError: errors[name] }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } component.setState.apply(component, args); }.bind(this)); + }, + + failSubmit: function (errors) { + this.updateInputsWithError(errors); this.setState({ isSubmitting: false }); @@ -291,6 +297,14 @@ Formsy.Form = React.createClass({ }.bind(this)); }, + getCurrentValues: function () { + return Object.keys(this.inputs).reduce(function (data, name) { + var component = this.inputs[name]; + data[name] = component.state._value; + return data; + }.bind(this), {}); + }, + // Use the binded values and the actual input value to // validate the input and set its state. Then check the // state of the form itself @@ -302,23 +316,7 @@ Formsy.Form = React.createClass({ // Run through the validations, split them up and call // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value !== '') { - component._validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { - return JSON.parse(arg); - }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } + var isValid = this.runValidation(component); component.setState({ _isValid: isValid, @@ -327,24 +325,67 @@ Formsy.Form = React.createClass({ }, + runValidation: function (component) { + var isValid = true; + if (component.props.required || component.state._value !== '') { + component._validations.split(',').forEach(function (validation) { + var args = validation.split(':'); + var validateMethod = args.shift(); + args = args.map(function (arg) { + try { + return JSON.parse(arg); + } catch (e) { + return arg; // It is a string if it can not parse it + } + }); + args = [component.state._value].concat(args); + if (!validationRules[validateMethod]) { + throw new Error('Formsy does not have the validation rule: ' + validateMethod); + } + if (!validationRules[validateMethod].apply(this.getCurrentValues(), args)) { + isValid = false; + } + }.bind(this)); + } + return isValid; + }, + // Validate the form by going through all child input components // and check their state validateForm: function () { var allIsValid = true; var inputs = this.inputs; + var inputKeys = Object.keys(inputs); - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); + // We need a callback as we are validating all inputs again. This will + // run when the last component has set its state + var onValidationComplete = function () { + inputKeys.forEach(function (name) { + if (!inputs[name].state._isValid) { + allIsValid = false; + } + }.bind(this)); - this.setState({ - isValid: allIsValid - }); + this.setState({ + isValid: allIsValid + }); + + allIsValid && this.props.onValid(); + !allIsValid && this.props.onInvalid(); + + }.bind(this); + + // Run validation again in case affected by other inputs. The + // last component validated will run the onValidationComplete callback + inputKeys.forEach(function (name, index) { + var component = inputs[name]; + var isValid = this.runValidation(component); + component.setState({ + _isValid: isValid, + _serverError: null + }, index === inputKeys.length - 1 ? onValidationComplete : null); + }.bind(this)); - allIsValid && this.props.onValid(); - !allIsValid && this.props.onInvalid(); }, // Method put on each input component to register diff --git a/releases/formsy-react.min.js b/releases/formsy-react.min.js new file mode 100755 index 0000000..9fbdaa5 --- /dev/null +++ b/releases/formsy-react.min.js @@ -0,0 +1 @@ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Formsy=t()}}(function(){return function t(e,i,n){function r(o,u){if(!i[o]){if(!e[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(s)return s(o,!0);var p=new Error("Cannot find module '"+o+"'");throw p.code="MODULE_NOT_FOUND",p}var h=i[o]={exports:{}};e[o][0].call(h.exports,function(t){var i=e[o][1][t];return r(i?i:t)},h,h.exports,t,e,i,n)}return i[o].exports}for(var s="function"==typeof require&&require,o=0;o=e&&t.length<=i:t.length>=e},equals:function(t,e){return t==e}},o=function(t,e,i){var i=i||[];if("object"==typeof t)for(var n in t)o(t[n],e?e+"["+n+"]":n,i);else i.push(e+"="+encodeURIComponent(t));return i.join("&")},u=function(t,e,i,n,r){var n="urlencoded"===n?"application/"+n.replace("urlencoded","x-www-form-urlencoded"):"application/json";return i="application/json"===n?JSON.stringify(i):o(i),new Promise(function(s,o){try{var u=new XMLHttpRequest;u.open(t,e,!0),u.setRequestHeader("Accept","application/json"),u.setRequestHeader("Content-Type",n),Object.keys(r).forEach(function(t){u.setRequestHeader(t,r[t])}),u.onreadystatechange=function(){4===u.readyState&&(u.status>=200&&u.status<300?s(u.responseText?JSON.parse(u.responseText):null):o(u.responseText?JSON.parse(u.responseText):null))},u.send(i)}catch(a){o(a)}})},a={post:u.bind(null,"POST"),put:u.bind(null,"PUT")},p={};r.defaults=function(t){p=t},r.Mixin={getInitialState:function(){return{_value:this.props.value?this.props.value:"",_isValid:!0}},componentWillMount:function(){if(!this.props.name)throw new Error("Form Input requires a name property when used");if(!this.props._attachToForm)throw new Error("Form Mixin requires component to be nested in a Form");this._validations=this.props.validations||"",this.props.required&&(this._validations=this.props.validations?this.props.validations+",":"",this._validations+="isValue"),this.props._attachToForm(this)},componentWillReceiveProps:function(t){t._attachToForm=this.props._attachToForm,t._detachFromForm=this.props._detachFromForm,t._validate=this.props._validate},componentWillUnmount:function(){this.props._detachFromForm(this)},setValue:function(t){this.setState({_value:t},function(){this.props._validate(this)}.bind(this))},resetValue:function(){this.setState({_value:""},function(){this.props._validate(this)})},getValue:function(){return this.state._value},hasValue:function(){return""!==this.state._value},getErrorMessage:function(){return this.isValid()||this.showRequired()?null:this.state._serverError||this.props.validationError},isValid:function(){return this.state._isValid},isRequired:function(){return this.props.required},showRequired:function(){return this.props.required&&""===this.state._value},showError:function(){return!this.showRequired()&&!this.state._isValid}},r.addValidationRule=function(t,e){s[t]=e},r.Form=n.createClass({getInitialState:function(){return{isValid:!0,isSubmitting:!1}},getDefaultProps:function(){return{headers:{},onSuccess:function(){},onError:function(){},onSubmit:function(){},onSubmitted:function(){},onValid:function(){},onInvalid:function(){}}},componentWillMount:function(){this.inputs={},this.model={},this.registerInputs(this.props.children)},componentDidMount:function(){this.validateForm()},submit:function(t){if(t.preventDefault(),!this.props.url)return this.updateModel(),void this.props.onSubmit(this.model,this.resetModel,this.updateInputsWithError);this.updateModel(),this.setState({isSubmitting:!0}),this.props.onSubmit();var e=Object.keys(this.props.headers).length&&this.props.headers||p.headers;a[this.props.method||"post"](this.props.url,this.model,this.props.contentType||p.contentType||"json",e).then(function(t){this.onSuccess(t),this.onSubmitted()}.bind(this)).catch(this.failSubmit)},updateModel:function(){Object.keys(this.inputs).forEach(function(t){var e=this.inputs[t];this.model[t]=e.state._value}.bind(this))},resetModel:function(){Object.keys(this.inputs).forEach(function(t){this.inputs[t].resetValue()}.bind(this)),this.validateForm()},updateInputsWithError:function(t){Object.keys(t).forEach(function(e){var i=this.inputs[e];if(!i)throw new Error("You are trying to update an input that does not exists. Verify errors object with input names. "+JSON.stringify(t));var n=[{_isValid:!1,_serverError:t[e]}];i.setState.apply(i,n)}.bind(this))},failSubmit:function(t){this.updateInputsWithError(t),this.setState({isSubmitting:!1}),this.props.onError(t),this.props.onSubmitted()},registerInputs:function(t){n.Children.forEach(t,function(t){t.props&&t.props.name&&(t.props._attachToForm=this.attachToForm,t.props._detachFromForm=this.detachFromForm,t.props._validate=this.validate),t.props&&t.props.children&&this.registerInputs(t.props.children)}.bind(this))},getCurrentValues:function(){return Object.keys(this.inputs).reduce(function(t,e){var i=this.inputs[e];return t[e]=i.state._value,t}.bind(this),{})},validate:function(t){if(t.props.required||t._validations){var e=this.runValidation(t);t.setState({_isValid:e,_serverError:null},this.validateForm)}},runValidation:function(t){var e=!0;return(t.props.required||""!==t.state._value)&&t._validations.split(",").forEach(function(i){var n=i.split(":"),r=n.shift();if(n=n.map(function(t){try{return JSON.parse(t)}catch(e){return t}}),n=[t.state._value].concat(n),!s[r])throw new Error("Formsy does not have the validation rule: "+r);s[r].apply(this.getCurrentValues(),n)||(e=!1)}.bind(this)),e},validateForm:function(){var t=!0,e=this.inputs,i=Object.keys(e),n=function(){i.forEach(function(i){e[i].state._isValid||(t=!1)}.bind(this)),this.setState({isValid:t}),t&&this.props.onValid(),!t&&this.props.onInvalid()}.bind(this);i.forEach(function(t,r){var s=e[t],o=this.runValidation(s);s.setState({_isValid:o,_serverError:null},r===i.length-1?n:null)}.bind(this))},attachToForm:function(t){this.inputs[t.props.name]=t,this.model[t.props.name]=t.state._value,this.validate(t)},detachFromForm:function(t){delete this.inputs[t.props.name],delete this.model[t.props.name]},render:function(){return n.DOM.form({onSubmit:this.submit,className:this.props.className},this.props.children)}}),i.exports||i.module||i.define&&i.define.amd||(i.Formsy=r),e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{react:"react"}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/main.js b/src/main.js index d0721f8..18e952d 100644 --- a/src/main.js +++ b/src/main.js @@ -210,7 +210,7 @@ Formsy.Form = React.createClass({ // if wanting to reset the entire form to original state, the second param is a callback for this. if (!this.props.url) { this.updateModel(); - this.props.onSubmit(this.model, this.resetModel); + this.props.onSubmit(this.model, this.resetModel, this.updateInputsWithError); return; } @@ -228,7 +228,7 @@ Formsy.Form = React.createClass({ this.onSuccess(response); this.onSubmitted(); }.bind(this)) - .catch(this.updateInputsWithError); + .catch(this.failSubmit); }, // Goes through all registered components and @@ -239,9 +239,9 @@ Formsy.Form = React.createClass({ this.model[name] = component.state._value; }.bind(this)); }, - + // Reset each key in the model to the original / initial value - resetModel: function() { + resetModel: function () { Object.keys(this.inputs).forEach(function (name) { this.inputs[name].resetValue(); }.bind(this)); @@ -254,15 +254,21 @@ Formsy.Form = React.createClass({ updateInputsWithError: function (errors) { Object.keys(errors).forEach(function (name, index) { var component = this.inputs[name]; + + if (!component) { + throw new Error('You are trying to update an input that does not exists. Verify errors object with input names. ' + JSON.stringify(errors)); + } + var args = [{ _isValid: false, _serverError: errors[name] }]; - if (index === Object.keys(errors).length - 1) { - args.push(this.validateForm); - } component.setState.apply(component, args); }.bind(this)); + }, + + failSubmit: function (errors) { + this.updateInputsWithError(errors); this.setState({ isSubmitting: false }); @@ -289,6 +295,14 @@ Formsy.Form = React.createClass({ }.bind(this)); }, + getCurrentValues: function () { + return Object.keys(this.inputs).reduce(function (data, name) { + var component = this.inputs[name]; + data[name] = component.state._value; + return data; + }.bind(this), {}); + }, + // Use the binded values and the actual input value to // validate the input and set its state. Then check the // state of the form itself @@ -300,23 +314,7 @@ Formsy.Form = React.createClass({ // Run through the validations, split them up and call // the validator IF there is a value or it is required - var isValid = true; - if (component.props.required || component.state._value !== '') { - component._validations.split(',').forEach(function (validation) { - var args = validation.split(':'); - var validateMethod = args.shift(); - args = args.map(function (arg) { - return JSON.parse(arg); - }); - args = [component.state._value].concat(args); - if (!validationRules[validateMethod]) { - throw new Error('Formsy does not have the validation rule: ' + validateMethod); - } - if (!validationRules[validateMethod].apply(null, args)) { - isValid = false; - } - }); - } + var isValid = this.runValidation(component); component.setState({ _isValid: isValid, @@ -325,24 +323,67 @@ Formsy.Form = React.createClass({ }, + runValidation: function (component) { + var isValid = true; + if (component.props.required || component.state._value !== '') { + component._validations.split(',').forEach(function (validation) { + var args = validation.split(':'); + var validateMethod = args.shift(); + args = args.map(function (arg) { + try { + return JSON.parse(arg); + } catch (e) { + return arg; // It is a string if it can not parse it + } + }); + args = [component.state._value].concat(args); + if (!validationRules[validateMethod]) { + throw new Error('Formsy does not have the validation rule: ' + validateMethod); + } + if (!validationRules[validateMethod].apply(this.getCurrentValues(), args)) { + isValid = false; + } + }.bind(this)); + } + return isValid; + }, + // Validate the form by going through all child input components // and check their state validateForm: function () { var allIsValid = true; var inputs = this.inputs; + var inputKeys = Object.keys(inputs); - Object.keys(inputs).forEach(function (name) { - if (!inputs[name].state._isValid) { - allIsValid = false; - } - }); + // We need a callback as we are validating all inputs again. This will + // run when the last component has set its state + var onValidationComplete = function () { + inputKeys.forEach(function (name) { + if (!inputs[name].state._isValid) { + allIsValid = false; + } + }.bind(this)); - this.setState({ - isValid: allIsValid - }); + this.setState({ + isValid: allIsValid + }); + + allIsValid && this.props.onValid(); + !allIsValid && this.props.onInvalid(); + + }.bind(this); + + // Run validation again in case affected by other inputs. The + // last component validated will run the onValidationComplete callback + inputKeys.forEach(function (name, index) { + var component = inputs[name]; + var isValid = this.runValidation(component); + component.setState({ + _isValid: isValid, + _serverError: null + }, index === inputKeys.length - 1 ? onValidationComplete : null); + }.bind(this)); - allIsValid && this.props.onValid(); - !allIsValid && this.props.onInvalid(); }, // Method put on each input component to register