From 23892b662539b4aa6fec2252d0aae8bb2e01bc47 Mon Sep 17 00:00:00 2001 From: elclanrs Date: Thu, 3 Oct 2013 20:45:36 -0400 Subject: [PATCH] initial commit --- .gitignore | 3 + README.md | 647 +++++++++ ajax.php | 9 + compile.sh | 4 + css/jquery.idealforms.css | 91 ++ img/datepicker.png | Bin 0 -> 1861 bytes img/loading.gif | Bin 0 -> 1737 bytes img/logo.png | Bin 0 -> 5583 bytes img/logo.svg | 140 ++ img/radiocheck.png | Bin 0 -> 4223 bytes img/validation.png | Bin 0 -> 774 bytes index.php | 208 +++ js/errors.js | 28 + js/extensions/ajax/ajax.ext.js | 61 + .../custom-inputs/custom-inputs.ext.js | 25 + js/extensions/custom-inputs/idealfile.js | 97 ++ .../custom-inputs/idealradiocheck.js | 48 + js/extensions/datepicker/datepicker.ext.js | 52 + .../dynamic-fields/dynamic-fields.ext.js | 125 ++ js/extensions/steps/idealsteps.js | 104 ++ js/extensions/steps/steps.ext.js | 111 ++ js/main.js | 61 + js/out/jquery.idealforms.js | 1209 +++++++++++++++++ js/out/jquery.idealforms.min.js | 7 + js/plugin.js | 124 ++ js/private.js | 174 +++ js/public.js | 66 + js/rules.js | 102 ++ package.json | 7 + styl/datepicker.styl | 72 + styl/idealfile.styl | 31 + styl/idealradiocheck.styl | 42 + styl/idealsteps.styl | 91 ++ styl/jquery.idealforms.styl | 13 + styl/main.styl | 175 +++ styl/vars.styl | 42 + 36 files changed, 3969 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 ajax.php create mode 100644 compile.sh create mode 100644 css/jquery.idealforms.css create mode 100644 img/datepicker.png create mode 100644 img/loading.gif create mode 100644 img/logo.png create mode 100644 img/logo.svg create mode 100644 img/radiocheck.png create mode 100644 img/validation.png create mode 100644 index.php create mode 100644 js/errors.js create mode 100644 js/extensions/ajax/ajax.ext.js create mode 100644 js/extensions/custom-inputs/custom-inputs.ext.js create mode 100644 js/extensions/custom-inputs/idealfile.js create mode 100644 js/extensions/custom-inputs/idealradiocheck.js create mode 100644 js/extensions/datepicker/datepicker.ext.js create mode 100644 js/extensions/dynamic-fields/dynamic-fields.ext.js create mode 100644 js/extensions/steps/idealsteps.js create mode 100644 js/extensions/steps/steps.ext.js create mode 100644 js/main.js create mode 100644 js/out/jquery.idealforms.js create mode 100644 js/out/jquery.idealforms.min.js create mode 100644 js/plugin.js create mode 100644 js/private.js create mode 100644 js/public.js create mode 100644 js/rules.js create mode 100644 package.json create mode 100644 styl/datepicker.styl create mode 100644 styl/idealfile.styl create mode 100644 styl/idealradiocheck.styl create mode 100644 styl/idealsteps.styl create mode 100644 styl/jquery.idealforms.styl create mode 100644 styl/main.styl create mode 100644 styl/vars.styl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e8da70 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +*.swp +node_modules/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d43ec1 --- /dev/null +++ b/README.md @@ -0,0 +1,647 @@ +![Ideal Forms logo](http://i.imgur.com/F9erFXl.png) + +The best forms just got better! Ideal Forms 3 is smaller, faster, and more extensible. + +**Support:** IE9+ and all modern browsers. +**Demo:** + +### Major changes since version 2 + +Ideal Forms 3 is **not** compatible with version 2. Here's what's new: + +- New architecture, more modularity +- Custom markup +- Extensions +- Improved custom checkbox, radio and file inputs +- Improved built-in theme +- Switch to Stylus +- Drop custom select menu +- Drop support for IE8 + +## Table of Contents + +- [Setup](#setup) +- [Options](#options) +- [Markup](#markup) + - [Custom Markup](#custom-markup) +- [Adding Rules](#adding-rules) +- [Built-in Rules](#built-in-rules) +- [Methods](#methods) +- [Built-in Extensions](#built-in-extensions) + - [Dynamic Fields](#extension-dynamic-fields) + - [Steps](#extension:-steps) + - [Custom Inputs](#extension-custom-inputs) + - [Ajax](#extension-ajax) + - [Datepicker](#extension-datepicker) +- [Custom Rules](#custom-rules) +- [Custom Extensions](#custom-extensions) +- [Themes](#themes) +- [Build & Share](#build--share) + +## Setup + +- Load latest [jQuery](http://code.jquery.com/jquery-2.0.3.min.js) library +- Load `css/jquery.idealforms.css` stylesheet +- Load `js/out/jquery.idealforms.min.js` plugin +- For better IE support, replace the opening `html` tag with: + +```html + + +``` + +- Call Ideal Forms on your form: + +```javascript +$('form').idealforms({ options }); +``` + +## Options + +```javascript +defaults = { + field: '.field', + error: '.error', + iconHtml: '', + iconClass: 'icon', + invalidClass: 'invalid', + validClass: 'valid', + silentLoad: true, + onValidate: $.noop, + onSubmit: $.noop, + rules: {} +} +``` + +### field + +The field container for [custom markup](#custom-markup). + +### error + +The error container for custom markup. + +### iconHtml + +The element to use as icon. Set to `false` to disable icons. + +### iconClass + +The class for the icon element. + +### invalidClass + +The class that will be added to invalid fields. + +### validClass + +The class that will be added to valid fields. + +### silentLoad + +Initialize the form silently, otherwise focus the first invalid input. + +### onValidate(input, rule, valid) + +Callback that runs after an input attempts to validate. + +- **input:** The input being validated +- **rule:** The rule that the input is validating. +- **valid:** Boolean. Did it validate? + +### onSubmit(invalid, event) + +Callback that runs when the form is submitted. + +- **invalid:** The number of invalid fields if any. +- **event:** The submit event (prevented by default). + +## Markup + +You can get started quickly using Ideal Forms' default markup: + +```html +
+ + +
+ + + +
+ + +
+ + + +
+ + +
+ +

+ + +

+ +
+ + +
+ +

+ + + +

+ +
+ + +
+ + + +
+ + +
+ + + +
+ + + + +
+``` + +### Custom Markup + +Ideal Forms 3 has been built from scratch with flexibility in mind. The markup is no longer tied to the plugin. If the default markup doesn't work for you, you can create your own markup. Ideal Forms will look for the following: + +- **A field:** A field must contain at least a label, an input and an error. +- **A label:** The label to identify the field. +- **An input or group of inputs:** Must be a single input or multiple related inputs such as checkboxes or radios. A field _cannot_ contain inputs with different `name` attributes; this is a limitation by design. +- **An error container:** An element to hold the error. + +Then you have to tell Ideal Forms that you want to use custom markup. You can specify these options when initializing the plugin: + +```javascript +$('form').idealforms({ + field: '.myfield', // selector + error: '.myerror', // selector + validClass: 'myvalid', // class name + invalidClass: 'myinvalid' // class name +}); +``` + +## Adding Rules + +Pass an object to the `rules` option, where each key corresponds to a `name` attribute and each value is a string of rules assigned to that input. Always quote keys for consistency: + +```javascript +$('form').idealforms({ + rules: { + 'username': 'required username', + 'password': 'required password', + 'sex': 'minoption:1', + 'hobbies[]': 'minoption:1 maxoption:2', + 'options': 'select:default' + } +}); +``` + +You can also add rules after initializing the plugin: + +```javascript +$('form').idealforms('addRules', { + 'comments': 'required minmax:50:200' +}); +``` + +## Built-in Rules + +A rule must be in this format `rule:param` where `rule` is the name of the `rule` and `param` is a rule parameter, for example `minmax:10:50` will use the `minmax` rule with two arguments, `10` and `50`. + +- **required:** The field is required. Only works with text inputs. +- **digits:** Only digits. +- **number:** Must be a number. +- **username:** Must be between 4 and 32 characters long and start with a letter. You may use letters, numbers, underscores, and one dot. +- **email:** Must be a valid email. +- **pass:** Must be at least 6 characters long, and contain at least one number, one uppercase and one lowercase letter. +- **strongpass:** Must be at least 8 characters long and contain at least one uppercase and one lowercase letter and one number or special character. +- **phone:** Must be a valid US phone number. +- **zip:** Must be a valid US zip code +- **url:** Must be a valid URL. +- **range:min:max:** Must be a number between `min` and `max`. Usually combined with `number` or `digits`. +- **min:min:** Must be at least `min` characters long. +- **max:max:** Must be no more that `max` characters long. +- **minmax:min:max:** Must be between `min` and `max` characters long. +- **minoption:min:** Must have at least `min` checkboxes or radios selected. +- **maxoption:max:** Must have no more than `max` checkboxes or radios selected. +- **select:default:** Make a select required, where `default` is the value of the default option. +- **extension:ext:** Validates file inputs. You can have as many `ext` as you want. +- **equalto:name:** Must be equal to another field where `name` is the name of the field. +- **ajax:** See the built-in [Ajax Extension](#ajax). + +## Methods + +To call a method run `idealforms` on the form and pass the method and arguments: + +```javascript +$('form').idealforms('method', arg1, arg2, ...); +``` + +### .idealforms('addRules', rules) + +See [Adding Rules](#adding-rules) + +### .idealforms('get:invalid') + +Returns a jQuery collection of all invalid fields. Access the `length` to check how many fields are invalid. + +### .idealforms('focusFirstInvalid') + +Focus the first invalid field. + +### .idealforms('is:valid', name) + +Check if the input with `name` attribute is valid. + +### .idealforms('reset') + +Reset all onputs to zero. That means emptying all the values of text inputs, unchecking all checkboxes and radios, and reverting selects to their default option. + +## Built-in Extensions + +Ideal Forms 3 has been re-designed to be able to extend the core easily. Read on [Custom Extensions](#custom-extensions) to learn more. + +Ideal Forms comes with a few built-in extensions. Extensions can be disabled with the `disabledExtensions` option by passing a space separated string of extensions. + +```javascript +$('form').idealforms({ + disabledExtensions: 'dynamicFields steps customInputs ajax' +}); +``` + +### Extension: Dynamic Fields + +Dynamic Fields extends core with the following methods: + +#### .idealforms('addFields', fields) + +Add fields to the form. + +- **fields:** And object where each key corresponds to the `name` attribute. The value of the object is another object that can contain any of the following options (* are required): + +```javascript +{ + type*: 'text:subtype | file | group:subtype | select', + label*: 'Label', + value: 'value', + attrs: 'attr="value"', + after: 'name', + before: 'name', + list: [ + { value: 'value', text: 'text' } + ... + ], + rules: 'rule rule rule' +} +``` + +Text subtypes include all HMTL5 text types, such as `email`, `number`, etc... + +Group subtypes include `radio` and `checkbox`. + +If `before` or `after` are not set, the field will be added at the end of the form. + +**Example:** + +```javascript +$('form').idealforms('addFields', { + 'fruits[]': { + type: 'group:checkbox', + label: 'Fruits', + list: [ + { value: 'apple', text: 'Apple', attrs: 'checked' }, + { value: 'orange', text: 'Orange' }, + { value: 'banana', text: 'Banana' } + ], + rules: 'minoption:1 maxoption:2' + } +}); +``` + +The HTML is generated according to built-in templates. If you're using your own custom markup you may need custom templates. Ideal Forms provides a simple templating system to easy the pain. These are the default templates that you may change in the options when calling the plugin. They are listed as real HTML for convenience but you must pass a string in the options (you can get the HTML from a script tag for example): + +```html + +
+ + {field} + +
+ + + + + + + + + + + +

+ {@list} + + {/list} +

+ + + +``` + +```javascript +$('form').idealforms('templates', { + + templates: { + base: '...', + text: '...', + file: '...', + textarea: '...', + group: '...', + select: '...' + } +}); +``` + +The templating rules are: + +- **{var}:** A variable or property. +- **{@list} html {/list}:** A loop. +- **{#var}:** A loop variable (inside the loop). + +#### .idealforms('removeFields', names) + +Remove fields from the form. + +- **names:** A space separated string of `name` attributes. + +**Example:** + +```javascript +$('form').idealforms('removeFields', 'username password hobbies[]'); +``` + +#### .idealforms('toggleFields', names) + +Show or hide fields. When the fields are hidden they will be excluded from the validation. + +- **names:** A space separated string of `name` attributes. + +**Example:** + +```javascript +$('form').idealforms('toggleFields', 'username password hobbies[]'); +``` + +### Extension: Steps + +Steps let you organize your form in sections. Steps expects a container, navigation, wrapper, and at least one step. Using the default options you may build your form like so: + +```html +
+ + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ +
+``` + +Steps adds the following options to Ideal Forms: + +```javascript +{ + stepsContainer: 'idealsteps-container', // the main container + stepsOptions: { // the options for the Steps extension + nav: '.idealsteps-nav', + navItems: 'li', + // Build nav items as "Step 1", "Step 2"... automatically + // Set to `false` to use your own custom markup + buildNavItems: true, + wrap: '.idealsteps-wrap', + step: '.idealsteps-step', + activeClass: 'idealsteps-step-active', + before: null, // runs before changing steps + after: null, // runs after changing steps + fadeSpeed: 0 + } +} +``` + +Steps provides these methods: + +#### .idealforms('goToStep', index) + +Go to the step number `index`. Indices start at `0`. + +#### .idealforms('prevStep') + +Go to the previous step. It wraps around. + +#### .idealforms('nextStep') + +Go to the next step. It wraps around. + +#### .idealforms('firstStep') + +Go to the first step. + +#### .idealforms('lastStep') + +Go to the last step. + +### Extension: Custom Inputs + +Adds custom checkboxes, radios and file inputs (yes!) seamlessly. The custom select menu has been dropped from Ideal Forms 3; it was proving to be a pain to maintain, and there are much better alternatives, such as [Select2](http://ivaynberg.github.io/select2/) if you need them. + +This extension has no additional options or methods. + +### Extension: Ajax + +Adds an `ajax` rule. First specify a URL on your input: + +```html + +``` + +Then add the rule to the field _always_ at last. + +```javascript +$('form').idealforms({ + rules: { + 'username': 'required username ajax' + } +}); +``` + +The ajax filter will read the URL and send a POST request to the server. The server side script must return a JSON encoded `true` (passes validation) or `false` (fails validation). for example in PHP: + +```php + +``` + +Now you can add the `date` rule: + +```javascript +$('form').idealforms({ + rules: { + 'event': 'date' + } +}); +``` + +The default format is `mm/dd/yyyy` for Ideal Forms and `mm/dd/yy` for the jQuery UI datepicker. Note that Ideal Forms represents years with `yyyy` not `yy`, but the formats are interchangeable. + +```javascript +$('form').idealforms({ + rules: { + 'event': 'date:yyyy-mm-dd' + } +}); + +$('.datepicker').datepicker('option', 'dateFormat', 'yy-mm-dd'); +``` + +## Custom Rules + +You can add rules by extending the global `rules` object: + +```javascript +$.extend($.idealforms.rules, { + + ruleRegex: /abc/g, + + // The rule is added as "ruleFunction:arg1:arg2" + // @param input {Node} + ruleFunction: function(input, value, arg1, arg2, ...) { + + } +}); +``` + +After you add a rule you must add an error for it, by extending the global `errors` object. Don't forget this step: + +```javascript +$.extend($.idealforms.errors, { + ruleRegex: 'Must be a valid value for this rule', + ruleFunction: 'Must be a valid value. {0}, {1}' +}); +``` + +If the rule is a function that takes rule parameters pass the parameters as `{0}`, `{1}`, etc. If you want to print all the parameters use `{*}` where the default separator is a comma but you can use your own like `{*~}` where `~` is the custom separator. + +## Custom Extensions + +```javascript +$.idealforms.addExtension({ + + name: 'extensionName', + + options: { + option: 'default' + }, + + methods: { + + // @extend + _init: function() { + + }, + + newMethod: function() { + + } + } +}); +``` + +## Themes + +## FAQ + +### How to access the Ideal Forms plugin instance + +Ideal Forms attaches an instance of itself to your form(s). To access the instance (prototype) use `data`: + +```javascript +var instance = $('form').data('idealforms'); +``` + +Now you an use methods like so: + +```javascript +instance.reset(); // reset the form +``` + +## Build & Share + +Ideal Forms 3 is built using some popular NodeJS tools. This is what you'll need to install globally: + +- [Stylus](https://github.com/learnboost/stylus) +- [UglifyJS](https://github.com/mishoo/UglifyJS2) +- [Browserify](https://github.com/substack/node-browserify) + +Then clone the repo, `cd` into the folder and run `npm install` to install dependencies. + +Finally run `watch -c sh compile.sh` to watch for changes and compile. Now you're ready to edit files and help make Ideal Forms better, or create your own fork. + +If you want to test ajax make sure to run it on your localhost. + +**Enjoy ;)** \ No newline at end of file diff --git a/ajax.php b/ajax.php new file mode 100644 index 0000000..ef8e727 --- /dev/null +++ b/ajax.php @@ -0,0 +1,9 @@ + js/out/jquery.idealforms.js +cat js/out/jquery.idealforms.js | uglifyjs --comments -m -c warnings=false -o js/out/jquery.idealforms.min.js diff --git a/css/jquery.idealforms.css b/css/jquery.idealforms.css new file mode 100644 index 0000000..ac70f56 --- /dev/null +++ b/css/jquery.idealforms.css @@ -0,0 +1,91 @@ +/* + * jQuery Ideal Forms + * @author: Cedric Ruiz + * @version: 3.0 + * @license GPL or MIT + */ +form.idealforms{zoom:1;line-height:1.5;} +form.idealforms:before,form.idealforms:after{content:"";display:table} +form.idealforms:after{clear:both} +form.idealforms *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} +form.idealforms .field{position:relative;float:left;clear:both;margin:.35em 0} +form.idealforms label.main,form.idealforms .field > input,form.idealforms select,form.idealforms button,form.idealforms textarea,form.idealforms .field .group{float:left} +form.idealforms label.main{width:120px;margin-top:.55em} +form.idealforms input,form.idealforms textarea,form.idealforms select,form.idealforms button,form.idealforms .field .group{margin:0;padding:0;border:0;outline:0;width:290px;padding:.55em;border:1px solid #999;outline:0;background:#fff;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.15)} +form.idealforms input{-webkit-transition:background 0.3s ease-in-out;-moz-transition:background 0.3s ease-in-out;-o-transition:background 0.3s ease-in-out;-ms-transition:background 0.3s ease-in-out;transition:background 0.3s ease-in-out} +form.idealforms textarea{width:435px} +form.idealforms select,form.idealforms button{color:#2b2b2b;background:#eee;background:-webkit-linear-gradient(#fff, #ddd);background:-moz-linear-gradient(#fff, #ddd);background:-o-linear-gradient(#fff, #ddd);background:-ms-linear-gradient(#fff, #ddd);background:linear-gradient(#fff, #ddd);border:1px solid #aaa;border-bottom-color:#919191;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.15);box-shadow:0 1px 2px rgba(0,0,0,0.15);-webkit-border-radius:3px;border-radius:3px;padding:.55em 1.5em;} +form.idealforms select:hover,form.idealforms button:hover{background:-webkit-linear-gradient(#fff, #eaeaea);background:-moz-linear-gradient(#fff, #eaeaea);background:-o-linear-gradient(#fff, #eaeaea);background:-ms-linear-gradient(#fff, #eaeaea);background:linear-gradient(#fff, #eaeaea)} +form.idealforms select:active,form.idealforms button:active{background:#ddd} +form.idealforms button{width:auto} +form.idealforms select{padding:.55em;} +form.idealforms select:focus{border:1px solid #444} +form.idealforms input[type="file"]{padding:0} +form.idealforms .field .group{position:relative;padding:1.25em;-webkit-box-shadow:none;box-shadow:none;} +form.idealforms .field .group label{float:left;clear:both;padding:.15em 0;} +form.idealforms .field .group input,form.idealforms .field .group label{margin:0} +form.idealforms .field .group input{width:auto;margin-right:.5em;-webkit-box-shadow:none;box-shadow:none} +form.idealforms .field .group label{margin-right:1em;} +form.idealforms .field .group label:last-of-type{margin:0} +form.idealforms .field.valid input,form.idealforms .field.valid select,form.idealforms .field.valid textarea,form.idealforms .field.valid .group{color:#18445a;background:#edf7fc;border-color:#3f9dcc} +form.idealforms .field.invalid input,form.idealforms .field.invalid select,form.idealforms .field.invalid textarea,form.idealforms .field.invalid .group{color:#430e08;background:#ffeded;border-color:#cc2a18} +form.idealforms .field.valid .group,form.idealforms .field.invalid .group,form.idealforms .field.valid textarea,form.idealforms .field.invalid textarea,form.idealforms .field.valid select,form.idealforms .field.invalid select{color:inherit;background:none} +form.idealforms .field.valid select,form.idealforms .field.invalid select{background:-webkit-linear-gradient(#fff, #ddd);background:-moz-linear-gradient(#fff, #ddd);background:-o-linear-gradient(#fff, #ddd);background:-ms-linear-gradient(#fff, #ddd);background:linear-gradient(#fff, #ddd)} +form.idealforms .field .icon{position:absolute;width:16px;height:16px;top:50%;left:100%;margin-top:-8px;margin-left:8px;background:url("../img/validation.png") -16px 0 no-repeat;cursor:pointer} +form.idealforms .field.invalid .icon{background-position:-16px 0} +form.idealforms .field.valid .icon{background-position:0 0;cursor:default} +form.idealforms .field.invalid .group input,form.idealforms .field.valid .group input{border:0;outline:0;-webkit-box-shadow:none;box-shadow:none} +form.idealforms .field.ajax input{color:#463a09;background:#faf9e8;border-color:#cfaa19} +form.idealforms .field.ajax .icon{background:url("../img/loading.gif")} +form.idealforms .error{display:none;position:absolute;z-index:1;left:100%;top:50%;padding:1em 1.5em;width:193.33333333333334px;margin-left:40px;background:#285d85;background:-webkit-linear-gradient(#285d85, #3070a0);background:-moz-linear-gradient(#285d85, #3070a0);background:-o-linear-gradient(#285d85, #3070a0);background:-ms-linear-gradient(#285d85, #3070a0);background:linear-gradient(#285d85, #3070a0);color:#fff;font-size:85%;font-weight:bold;text-shadow:0 1px 0 rgba(0,0,0,0.3);line-height:1.35;border:1px solid #1c425e;-webkit-border-radius:0 3px 3px 3px;border-radius:0 3px 3px 3px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.15);box-shadow:0 1px 1px rgba(0,0,0,0.15);} +form.idealforms .error:after{content:"";position:absolute;z-index:-1;top:-1px;left:-.7em;border-width:.7em;border-style:solid;border-color:transparent;border-top-color:#285d85} +form.idealforms .idealforms-field-checkbox .icon,form.idealforms .idealforms-field-radio .icon,form.idealforms .idealforms-field-textarea .icon{top:8px;margin-top:0} +form.idealforms .idealforms-field-checkbox .error,form.idealforms .idealforms-field-radio .error,form.idealforms .idealforms-field-textarea .error{top:20px} +.idealsteps-step{zoom:1} +.idealsteps-step:before,.idealsteps-step:after{content:"";display:table} +.idealsteps-step:after{clear:both} +.idealsteps-nav{color:#2b2b2b;background:#eee;background:-webkit-linear-gradient(#fff, #ddd);background:-moz-linear-gradient(#fff, #ddd);background:-o-linear-gradient(#fff, #ddd);background:-ms-linear-gradient(#fff, #ddd);background:linear-gradient(#fff, #ddd);border:1px solid #aaa;border-bottom-color:#919191;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.15);box-shadow:0 1px 2px rgba(0,0,0,0.15);-webkit-border-radius:3px;border-radius:3px;overflow:hidden;margin-bottom:2em;} +.idealsteps-nav ul{margin:0;padding:0;border:0;outline:0;list-style:none} +.idealsteps-nav li{float:left} +.idealsteps-nav a{position:relative;float:left;padding:0 1.5em 0 2.75em;height:3.5em;line-height:3.5em;text-decoration:none;color:#5e5e5e;background:#ddd;-webkit-transition:padding 0.2s ease-in-out;-moz-transition:padding 0.2s ease-in-out;-o-transition:padding 0.2s ease-in-out;-ms-transition:padding 0.2s ease-in-out;transition:padding 0.2s ease-in-out;} +.idealsteps-nav a:focus{outline:0} +.idealsteps-nav a:hover{background:#eaeaea;} +.idealsteps-nav a:hover:after{border-left-color:#eaeaea} +.idealsteps-nav a:after,.idealsteps-nav a:before{content:"";position:absolute;z-index:1;top:0;right:-2em;margin-right:0;margin-top:-.125em;border-width:2em 1em;border-style:solid;border-color:transparent;border-left-color:#ddd} +.idealsteps-nav a:before{margin-right:-1px;border-left-color:#aaa} +.idealsteps-nav li:first-child a{padding-left:1.75em} +.idealsteps-nav li.idealsteps-step-active a{padding-right:3.5em;background:#fff;color:#3f9dcc;font-weight:bold;} +.idealsteps-nav li.idealsteps-step-active a:after{border-left-color:#fff} +.idealsteps-nav li.idealsteps-step-active .counter{opacity:1;-ms-filter:none;filter:none} +.idealsteps-nav .counter{opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:alpha(opacity=0);position:absolute;top:50%;right:1em;height:20px;width:20px;margin-top:-.75em;line-height:20px !important;text-align:center;line-height:1;color:#cc2a18;border:1px solid #cc2a18;-webkit-border-radius:10em;border-radius:10em;-webkit-transition:opacity 0.2s ease-in-out;-moz-transition:opacity 0.2s ease-in-out;-o-transition:opacity 0.2s ease-in-out;-ms-transition:opacity 0.2s ease-in-out;transition:opacity 0.2s ease-in-out;} +.idealsteps-nav .counter.zero{color:#3f9dcc;border-color:#3f9dcc} +form.idealforms .ideal-radiocheck-label{cursor:pointer;margin:.15em 0 !important;} +form.idealforms .ideal-radiocheck-label input{float:left} +form.idealforms .ideal-check,form.idealforms .ideal-radio{float:left;margin-right:10px !important;width:20px;height:20px;background:url("../img/radiocheck.png") 0 0} +form.idealforms .ideal-check.focus{background-position:-20px 0} +form.idealforms .ideal-check.checked{background-position:-40px 0} +form.idealforms .ideal-check.checked.focus{background-position:-60px 0} +form.idealforms .ideal-radio{background-position:0 bottom} +form.idealforms .ideal-radio.focus{background-position:-20px bottom} +form.idealforms .ideal-radio.checked{background-position:-40px bottom} +form.idealforms .ideal-radio.checked.focus{background-position:-60px bottom} +form.idealforms .ideal-file-wrap{float:left} +form.idealforms .ideal-file-filename{float:left;width:204px;height:100%;-webkit-border-radius:0;border-radius:0;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;} +form.idealforms .ideal-file-upload{color:#2b2b2b;background:#eee;background:-webkit-linear-gradient(#fff, #ddd);background:-moz-linear-gradient(#fff, #ddd);background:-o-linear-gradient(#fff, #ddd);background:-ms-linear-gradient(#fff, #ddd);background:linear-gradient(#fff, #ddd);border:1px solid #aaa;border-bottom-color:#919191;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.15);box-shadow:0 1px 2px rgba(0,0,0,0.15);-webkit-border-radius:3px;border-radius:3px;padding:.55em 1.5em;overflow:visible;position:relative;float:right;left:-1px;width:87px;padding-left:0;padding-right:0;text-align:center;-webkit-border-radius:0;border-radius:0;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;} +form.idealforms .ideal-file-upload:hover{background:-webkit-linear-gradient(#fff, #eaeaea);background:-moz-linear-gradient(#fff, #eaeaea);background:-o-linear-gradient(#fff, #eaeaea);background:-ms-linear-gradient(#fff, #eaeaea);background:linear-gradient(#fff, #eaeaea)} +form.idealforms .ideal-file-upload:active{background:#ddd} +.ie9 .ideal-file-upload{line-height:1.15} +.idealforms input.datepicker.open{border-bottom-color:transparent;-webkit-border-radius:0;border-radius:0;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;} +.ui-datepicker{display:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:290px;margin-top:-2px;padding:.75em;background:#fff;border:1px solid #999;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.2);box-shadow:0 1px 2px rgba(0,0,0,0.2)} +.ui-datepicker-header{position:relative;padding:.2em 0;margin-bottom:.75em;font-weight:bold;} +.ui-datepicker-header .ui-datepicker-title{text-align:center} +.ui-datepicker-header .ui-datepicker-prev,.ui-datepicker-header .ui-datepicker-next{text-indent:-9999px;width:16px;height:16px;position:absolute;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:url("../img/datepicker.png") 0 0;} +.ui-datepicker-header .ui-datepicker-prev:active,.ui-datepicker-header .ui-datepicker-next:active{margin-top:1px} +.ui-datepicker-header .ui-datepicker-next{background-position:-16px 0} +.ui-datepicker-header .ui-datepicker-prev{left:8px} +.ui-datepicker-header .ui-datepicker-next{right:8px} +.ui-datepicker-calendar{width:100%;border-collapse:collapse;table-layout:fixed;} +.ui-datepicker-calendar td{padding:.25em 0;text-align:center} +.ui-datepicker-calendar a{display:block;text-decoration:none;color:#808080;} +.ui-datepicker-calendar a:hover{color:#3f9dcc;font-weight:bold} +.ui-datepicker-calendar .ui-datepicker-today a{margin:0 .25em;background:#eee;-webkit-border-radius:3px;border-radius:3px} diff --git a/img/datepicker.png b/img/datepicker.png new file mode 100644 index 0000000000000000000000000000000000000000..34f944e5abcda29dd54625a5b2284a0cb20b1b2e GIT binary patch literal 1861 zcmaJ?X;2eq7|wtY1Uy7thlFH-1(J=~B?*Us1`#R^ znsQi6MMp&im7<^=PF0{p#(LmrD@Z{ND1wX#NEiyG8!Fl#r8~R(UC;Bp@AtjW&gKbr zY+GdQXpO_+7V-SKLaYU_XQ`DX_EzC`hhdEa>Klp%!m+4IqyTZ=5;z6~cv4XuClSx07+Pc z5IWzLFXw>qkbkNI3{2e-Bu-5fdq@agY`{~^!~~=uDgxBfBpJd~vk0@gOssF3CKG^J z2%5+u{F78DUjT4m1qjedRHE3GLID^I5`{)*FesY=H&==q*%iAPL<)^bXE5E|fp-@H zi>8poGKE~fcd@V$ix7{ZaweIqQmIHPDhXD^ktrS?9wrSpHzI~0A}KOdq$bJ`=Q#x~ zh=>)C9ED&RU{Vytz{x0!fMxp67Nqj`vNGh|F<}QrR*U3h3dz;9r8yv<|Nl^_^gS9u zh2V#L|5F$VN|A$PA&9`q3Nco=SZ7lxIg_IRMJTKYg5jjOQxwF*D2&9za)1-a0M>^< zG6}3gHq7Grd?rtZpdy(Vpfak;QKSqjR~Ij-abmo_igWCf`li_8TTkP?*mDPSouyJaRce=d}H_1&S;r&W91>+tTXk>J4b_#0&z(*x5zGY>2KM!UMZH>Qmljd3>%b_$+9`+At? z>fC>}vhvRa{Z{RXboNfGs4Dm1t}iUS>eI_^;qTnOeY<3EFcExGZPPzEIGCH42W{NE zIS7Iv$6sH+dUa-KNLt&_P;uw(-N)GSPA|dr$Nl~NAr=-E8(FN#QP!G*=bEA-yJV&E zw+&6VXEq(Xa>ZEH)fJKH>$~rp{QMx{OCyd4RNk+vs}mRuh6Dr|y_=Jhvr=R+b*QN5 z?bVAHg}%PN5F5Dm*daM3<*duPbq^;e8=ULQ4)p}+jvhU#EiHA*3=S?LJs%q@EUKui z+{ABc-KHBDNZ5B!-W|I2jpbUT#hx9ZuxFbus%d%k!kdwu{GGI5Uk~wH8rsj!-;e)9(2!yAV>5sw*iut<`GL zTeii;#i&`%5MHm>H`p{y+eI5}3d9FB5tr8zY3=1%Q!OprNC%=>snYq5Ylit(M|8Tq z(^e)BRTI%m%c!}>{lRRkyTk6jFfF^vcJWYQkIj=#qw>0~q7#X4I-YeGkH=3|9Ja2% zL?jZID6b_cCNvd)Jda^9wbIt|?FmsxU2U!1MnXE+*49>jYQ`)n z-I$!^)O&Gy7PQ54aSesd{_Bo)?~V3_No&*e8XA?_oQaP%AV&Ivy5665#~<7064BGr z(o)ji-d@<;+*}qA5RkmjX+5Gcj*t5&6A~&iV)p0cJZNq8iwh5btgo)F=H$(YGBam( zg@t{uH5BegyoExYPPOgZ{QNVuwY5Ec?UUixvWJF-_H=ZF#mVJ@1H;Ao*4CWd5y8u} zTh@3>%LiRurOu_XgZXrWSZg2i)Sg{`lP9Cy`*;WL*^dQZip7Sl9k*IXMijvj5$CEL zHRd&Sb!W=U%L~zpOPD)8?e6S!Y_Qv_&CbqtnJ7&iKXT)fK4KO*@}-V5q0`*d^e&un z!kg_$HzHHqgD)C1dow4-QI#t5vZ2{J`j-yUjJx;Gt1i3PXOpE%j#RC)NM9C>^Kd!W U8vXmD3Db{_=evV@!6$m}-_$Y%hX4Qo literal 0 HcmV?d00001 diff --git a/img/loading.gif b/img/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..e40f19a2818e4c81726bf965fc8dc108d52dc599 GIT binary patch literal 1737 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 literal 0 HcmV?d00001 diff --git a/img/logo.svg b/img/logo.svg new file mode 100644 index 0000000..8d46649 --- /dev/null +++ b/img/logo.svg @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + IDEAL FORMS + + + 3 + + + diff --git a/img/radiocheck.png b/img/radiocheck.png new file mode 100644 index 0000000000000000000000000000000000000000..e95016579109bf653f7dd7a7c0445ed6dbe00c66 GIT binary patch literal 4223 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 Td3ojNmjFuZs%GV7`|$q&J5QVe literal 0 HcmV?d00001 diff --git a/img/validation.png b/img/validation.png new file mode 100644 index 0000000000000000000000000000000000000000..9019634a4e48a43822306cad86b74aaf2e7a2871 GIT binary patch literal 774 zcmV+h1Nr=kP)|!4=@uhcAQpAdB1l)9^gOD z2s7y=%%n&D7N2xR@wsR;@UXB$8D(P3wT;*HHOFx*0I4>qMlH*7&U*6Md$00)Q(vf< z**u`Po_+Vtq^H%zGntI=eP6VK@B1Q?$%tCRklPfWJ{Jv)58Uh`ohlIITrdU!pjsanz@!Hi!%X7z422+Qyqk@kqBiaXHaRG!@eRPL;h|DwG))_g&kl zG!nOq##*^1G8*j(EcRdTysN0vOEc+>)V@E_BkDx#szyiv5-U^oez{PlRE)T`@%A_| zW9%@}>2%Y~7(243K7q0RYg(wpgxog}CSO07o|{RpkLb$di&qEWX!Q1C>@a0 z4)9M|zf{@hk6hb$amsIXve_&+=g>6m)F6aldwUxj8yf&%o$vuO=}nSuWwJLB4p+)T z3Wj9y?c-kQz-Lcg+nE2=#c~`cRVS?@7K>GNuK`bgPrM z(Zmvf+W?j=%er%Xy{QqowlOa_F8rx@4MPB&TK@O&6C?g&S3#Tmh5!Hn07*qoM6N<$ Ef_}wcxc~qF literal 0 HcmV?d00001 diff --git a/index.php b/index.php new file mode 100644 index 0000000..03b8676 --- /dev/null +++ b/index.php @@ -0,0 +1,208 @@ + + + + + + + + + + +Ideal Forms 3 + + + + +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ +

+ + +

+ +
+ +
+ +

+ + + + + +

+ +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ +
+ +
+ + +
+ +
+ +
+ + + + + + + + diff --git a/js/errors.js b/js/errors.js new file mode 100644 index 0000000..0fef924 --- /dev/null +++ b/js/errors.js @@ -0,0 +1,28 @@ +/** + * Errors + */ +module.exports = { + + required: 'This field is required', + digits: 'Must be only digits', + name: 'Must be at least 3 characters long and must only contain letters', + email: 'Must be a valid email', + username: 'Must be at between 4 and 32 characters long and start with a letter. You may use letters, numbers, underscores, and one dot', + pass: 'Must be at least 6 characters long, and contain at least one number, one uppercase and one lowercase letter', + strongpass: 'Must be at least 8 characters long and contain at least one uppercase and one lowercase letter and one number or special character', + phone: 'Must be a valid phone number', + zip: 'Must be a valid zip code', + url: 'Must be a valid URL', + number: 'Must be a number', + range: 'Must be a number between {0} and {1}', + min: 'Must be at least {0} characters long', + max: 'Must be under {0} characters', + minoption: 'Select at least {0} options', + maxoption: 'Select no more than {0} options', + minmax: 'Must be between {0} and {1} characters long', + select: 'Select an option', + extension: 'File(s) must have a valid extension ({*})', + equalto: 'Must have the same value as the "{0}" field', + date: 'Must be a valid date {0}' + +}; diff --git a/js/extensions/ajax/ajax.ext.js b/js/extensions/ajax/ajax.ext.js new file mode 100644 index 0000000..db7ec3f --- /dev/null +++ b/js/extensions/ajax/ajax.ext.js @@ -0,0 +1,61 @@ +module.exports = { + + name: 'idealAjax', + + methods: { + + // @extend + _init: function() { + + $.extend($.idealforms, { _requests: {} }); + + $.extend($.idealforms.errors, { + ajax: 'Loading...' + }); + + $.extend($.idealforms.rules, { + + ajax: function(input) { + + var self = this + , $field = this._getField(input) + , url = $(input).data('idealforms-ajax') + , userError = $.idealforms._getKey('errors.'+ input.name +'.ajaxError', self.opts) + , requests = $.idealforms._requests + , data = {}; + + data[input.name] = input.value; + + $field.addClass('ajax'); + + if (requests[input.name]) requests[input.name].abort(); + + requests[input.name] = $.post(url, data, function(resp) { + + if (resp === true) { + $field.data('idealforms-valid', true); + self._handleError(input); + self._handleStyle(input); + } else { + self._handleError(input, userError); + } + + $field.removeClass('ajax'); + + }, 'json'); + + return false; + } + }); + }, + + // @extend + _validate: function(input, rule) { + if (rule != 'ajax' && $.idealforms._requests[input.name]) { + $.idealforms._requests[input.name].abort(); + this._getField(input).removeClass('ajax'); + } + } + + } +}; diff --git a/js/extensions/custom-inputs/custom-inputs.ext.js b/js/extensions/custom-inputs/custom-inputs.ext.js new file mode 100644 index 0000000..4d67967 --- /dev/null +++ b/js/extensions/custom-inputs/custom-inputs.ext.js @@ -0,0 +1,25 @@ +require('./idealfile'); +require('./idealradiocheck'); + +module.exports = { + + name: 'customInputs', + + methods: { + + // @extend + _init: function() { + this._buildCustomInputs(); + }, + + addFields: function() { + this._buildCustomInputs(); + }, + + _buildCustomInputs: function() { + this.$form.find(':file').idealfile(); + this.$form.find(':checkbox, :radio').idealradiocheck(); + } + + } +}; diff --git a/js/extensions/custom-inputs/idealfile.js b/js/extensions/custom-inputs/idealfile.js new file mode 100644 index 0000000..0103436 --- /dev/null +++ b/js/extensions/custom-inputs/idealfile.js @@ -0,0 +1,97 @@ +/** + * Ideal File + */ +(function($, win, doc, undefined) { + + // Browser supports HTML5 multiple file? + var multipleSupport = typeof $('')[0].multiple !== 'undefined' + , isIE = /msie/i.test(navigator.userAgent) + , plugin = {}; + + plugin.name = 'idealfile'; + + plugin.methods = { + + _init: function() { + + var $file = $(this.el).addClass('ideal-file') // the original file input + , $wrap = $('
') + , $input = $('') + // Button that will be used in non-IE browsers + , $button = $('') + // Hack for IE + , $label = $(''); + + // Hide by shifting to the left so we + // can still trigger events + $file.css({ + position: 'absolute', + left: '-9999px' + }); + + $wrap.append($input, (isIE ? $label : $button)).insertAfter($file); + + // Prevent focus + $file.attr('tabIndex', -1); + $button.attr('tabIndex', -1); + + $button.click(function () { + $file.focus().click(); // Open dialog + }); + + $file.change(function () { + + var files = [] + , fileArr, filename; + + // If multiple is supported then extract + // all filenames from the file array + if (multipleSupport) { + fileArr = $file[0].files; + for (var i = 0, len = fileArr.length; i < len; i++) { + files.push(fileArr[i].name); + } + filename = files.join(', '); + + // If not supported then just take the value + // and remove the path to just show the filename + } else { + filename = $file.val().split('\\').pop(); + } + + $input .val(filename).attr('title', filename); + + }); + + $input.on({ + blur: function () { + $file.trigger('blur'); + }, + keydown: function (e) { + if (e.which === 13) { // Enter + if (!isIE) $file.trigger('click'); + $(this).closest('form').one('keydown', function(e) { + if (e.which === 13) e.preventDefault(); + }); + } else if (e.which === 8 || e.which === 46) { // Backspace & Del + // In IE the value is read-only + // with this trick we remove the old input and add + // a clean clone with all the original events attached + if (isIE) $file.replaceWith($file = $file.clone(true)); + $file.val('').trigger('change'); + $input.val(''); + } else if (e.which === 9) { // TAB + return; + } else { // All other keys + return false; + } + } + }); + + } + + }; + + require('../../plugin')(plugin); + +}(jQuery, window, document)); diff --git a/js/extensions/custom-inputs/idealradiocheck.js b/js/extensions/custom-inputs/idealradiocheck.js new file mode 100644 index 0000000..ad7775f --- /dev/null +++ b/js/extensions/custom-inputs/idealradiocheck.js @@ -0,0 +1,48 @@ +/* + * idealRadioCheck: jQuery plguin for checkbox and radio replacement + * Usage: $('input[type=checkbox], input[type=radio]').idealRadioCheck() + */ +(function($, win, doc, undefined) { + + var plugin = {}; + + plugin.name = 'idealradiocheck'; + + plugin.methods = { + + _init: function() { + + var $input = $(this.el); + var $span = $(''); + + $span.addClass('ideal-'+ ($input.is(':checkbox') ? 'check' : 'radio')); + $input.is(':checked') && $span.addClass('checked'); // init + $span.insertAfter($input); + + $input.parent('label') + .addClass('ideal-radiocheck-label') + .attr('onclick', ''); // Fix clicking label in iOS + + $input.css({ position: 'absolute', left: '-9999px' }); // hide by shifting left + + // Events + $input.on({ + change: function() { + var $input = $(this); + if ( $input.is('input[type="radio"]') ) { + $input.parent().siblings('label').find('.ideal-radio').removeClass('checked'); + } + $span.toggleClass('checked', $input.is(':checked')); + }, + focus: function() { $span.addClass('focus') }, + blur: function() { $span.removeClass('focus') }, + click: function() { $(this).trigger('focus') } + }); + } + + }; + + require('../../plugin')(plugin); + +}(jQuery, window, document)); + diff --git a/js/extensions/datepicker/datepicker.ext.js b/js/extensions/datepicker/datepicker.ext.js new file mode 100644 index 0000000..4716702 --- /dev/null +++ b/js/extensions/datepicker/datepicker.ext.js @@ -0,0 +1,52 @@ +module.exports = { + + name: 'datepicker', + + methods: { + + // @extend + _init: function() { + this._buildDatepicker(); + }, + + _buildDatepicker: function() { + + var $datepicker = this.$form.find('input.datepicker'); + + // Always show datepicker below the input + if (jQuery.ui) { + $.datepicker._checkOffset = function(a,b,c){ return b }; + } + + if (jQuery.ui && $datepicker.length) { + + $datepicker.each(function() { + + $(this).datepicker({ + beforeShow: function(input) { + $(input).addClass('open'); + }, + onChangeMonthYear: function() { + // Hack to fix IE9 not resizing + var $this = $(this) + , width = $this.outerWidth(); // cache first! + setTimeout(function() { + $this.datepicker('widget').css('width', width); + }, 1); + }, + onClose: function() { + $(this).removeClass('open'); + } + }); + }); + + // Adjust width + $datepicker.on('focus keyup', function() { + var t = $(this), w = t.outerWidth(); + t.datepicker('widget').css('width', w); + }); + } + } + + } +}; diff --git a/js/extensions/dynamic-fields/dynamic-fields.ext.js b/js/extensions/dynamic-fields/dynamic-fields.ext.js new file mode 100644 index 0000000..24e2d5e --- /dev/null +++ b/js/extensions/dynamic-fields/dynamic-fields.ext.js @@ -0,0 +1,125 @@ +function template(html, data) { + + var loop = /\{@([^}]+)\}(.+?)\{\/\1\}/g + , loopVariable = /\{#([^}]+)\}/g + , variable = /\{([^}]+)\}/g; + + return html + .replace(loop, function(_, key, list) { + return $.map(data[key], function(item) { + return list.replace(loopVariable, function(_, k) { + return item[k]; + }); + }).join(''); + }) + .replace(variable, function(_, key) { + return data[key] || ''; + }); +} + +module.exports = { + + name: 'dynamicFields', + + options: { + + templates: { + + base:'\ +
\ + \ + {field}\ + \ +
\ + ', + + text: '', + + file: '', + + textarea: '', + + group: '\ +

\ + {@list}\ + \ + {/list}\ +

\ + ', + + select: '\ + \ + ' + } + }, + + methods: { + + addFields: function(fields) { + + var self = this; + + $.each(fields, function(name, field) { + + var typeArray = field.type.split(':') + , rules = {}; + + field.name = name; + field.type = typeArray[0]; + if (typeArray[1]) field.subtype = typeArray[1]; + + var html = template(self.opts.templates.base, { + label: field.label, + field: template(self.opts.templates[field.type], field) + }); + + if (field.after || field.before) { + self.$form.find('[name='+ (field.after || field.before) +']').each(function() { + self._getField(this)[field.after ? 'after' : 'before'](html); + }); + } else { + self.$form.find(self.opts.field).last().after(html); + } + + if (field.rules) { + rules[name] = field.rules; + self.addRules(rules); + } + }); + + this._inject('addFields'); + }, + + removeFields: function(names) { + + var self = this; + + $.each(names.split(' '), function(i, name) { + var $field = self._getField($('[name="'+ name +'"]')); + self.$fields = self.$fields.filter(function() { + return ! $(this).is($field); + }); + $field.remove(); + }); + + this._inject('removeFields'); + }, + + toggleFields: function(names) { + + var self = this; + + $.each(names.split(' '), function(i, name) { + var $field = self._getField($('[name="'+ name +'"]')); + $field.data('idealforms-valid', $field.is(':visible')).toggle(); + }); + + this._inject('toggleFields'); + } + + } +}; diff --git a/js/extensions/steps/idealsteps.js b/js/extensions/steps/idealsteps.js new file mode 100644 index 0000000..32baa15 --- /dev/null +++ b/js/extensions/steps/idealsteps.js @@ -0,0 +1,104 @@ +/*! + * Ideal Steps +*/ +(function($, win, doc, undefined) { + + var plugin = {}; + + plugin.name = 'idealsteps'; + + plugin.defaults = { + nav: '.idealsteps-nav', + navItems: 'li', + buildNavItems: true, + wrap: '.idealsteps-wrap', + step: '.idealsteps-step', + activeClass: 'idealsteps-step-active', + before: null, + after: null, + fadeSpeed: 0 + }; + + plugin.methods = { + + _init: function() { + + var self = this, + active = this.opts.activeClass; + + this.$el = $(this.el); + + this.$nav = this.$el.find(this.opts.nav); + this.$navItems = this.$nav.find(this.opts.navItems); + + this.$wrap = this.$el.find(this.opts.wrap); + this.$steps = this.$wrap.find(this.opts.step); + + if (this.opts.buildNavItems) this._buildNavItems(); + + this.$steps.hide().first().show(); + this.$navItems.removeClass(active).first().addClass(active); + + this.$navItems.click(function() { + self.go(self.$navItems.index(this)); + }); + }, + + _buildNavItems: function() { + + var self = this, + isCustom = typeof this.opts.buildNavItems == 'function', + item = function(val){ return '
  • '+ val +'
  • '; }, + items; + + items = isCustom ? + this.$steps.map(function(i){ return item(self.opts.buildNavItems.call(self, i)) }).get() : + this.$steps.map(function(i){ return item(++i); }).get(); + + this.$navItems = $(items.join('')); + + this.$nav.append($('
      ').append(this.$navItems)); + }, + + _getCurIdx: function() { + return this.$steps.index(this.$steps.filter(':visible')); + }, + + go: function(idx) { + + var active = this.opts.activeClass, + fadeSpeed = this.opts.fadeSpeed; + + if (typeof idx == 'function') idx = idx.call(this, this._getCurIdx()); + + if (idx >= this.$steps.length) idx = 0; + if (idx < 0) idx = this.$steps.length-1; + + if (this.opts.before) this.opts.before.call(this, idx); + + this.$navItems.removeClass(active).eq(idx).addClass(active); + this.$steps.fadeOut(fadeSpeed).eq(idx).fadeIn(fadeSpeed); + + if (this.opts.after) this.opts.after.call(this, idx); + }, + + prev: function() { + this.go(this._getCurIdx() - 1); + }, + + next: function() { + this.go(this._getCurIdx() + 1); + }, + + first: function() { + this.go(0); + }, + + last: function() { + this.go(this.$steps.length-1); + } + }; + + require('../../plugin')(plugin); + +}(jQuery, window, document)); diff --git a/js/extensions/steps/steps.ext.js b/js/extensions/steps/steps.ext.js new file mode 100644 index 0000000..d3f3475 --- /dev/null +++ b/js/extensions/steps/steps.ext.js @@ -0,0 +1,111 @@ +require('./idealsteps'); + +module.exports = { + + name: 'steps', + + options: { + stepsContainer: '.idealsteps-container', + stepsOptions: {} + }, + + methods: { + + // @extend + _init: function() { + this._buildSteps(); + }, + + // @extend + _validate: function() { + + var self = this; + + this._updateSteps(); + + if ($.idealforms.hasExtension('idealAjax')) { + $.each($.idealforms._requests, function(key, request) { + request.done(function(){ self._updateSteps() }); + }); + } + }, + + // @extend + focusFirstInvalid: function(firstInvalid) { + + var self = this; + + this.$stepsContainer.idealsteps('go', function() { + return this.$steps.filter(function() { + return $(this).find(firstInvalid).length; + }).index(); + }); + }, + + _buildSteps: function() { + + var self = this, options + , hasRules = ! $.isEmptyObject(this.opts.rules) + , counter = hasRules + ? '' + : '0'; + + options = $.extend({}, { + buildNavItems: function(i){ return 'Step '+ (i+1) + counter } + }, this.opts.stepsOptions); + + this.$stepsContainer = this.$form.closest(this.opts.stepsContainer).idealsteps(options); + }, + + _updateSteps: function() { + + var self = this; + + this.$stepsContainer.idealsteps('_inject', function() { + + var idealsteps = this; + + this.$navItems.each(function(i) { + var invalid = idealsteps.$steps.eq(i).find(self.getInvalid()).length; + $(this).find('span').text(invalid).toggleClass('zero', ! invalid); + }); + }); + }, + + // @extend + addRules: function() { + this.firstStep(); + }, + + // @extend + toggleFields: function() { + this._updateSteps(); + }, + + // @extend + removeFields: function() { + this._updateSteps(); + }, + + goToStep: function(idx) { + this.$stepsContainer.idealsteps('go', idx); + }, + + prevStep: function() { + this.$stepsContainer.idealsteps('prev'); + }, + + nextStep: function() { + this.$stepsContainer.idealsteps('next'); + }, + + firstStep: function() { + this.$stepsContainer.idealsteps('first'); + }, + + lastStep: function() { + this.$stepsContainer.idealsteps('last'); + } + } + +}; diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..9cc04d9 --- /dev/null +++ b/js/main.js @@ -0,0 +1,61 @@ +/*! + * jQuery Ideal Forms + * @author: Cedric Ruiz + * @version: 3.0 + * @license GPL or MIT + */ +(function($, win, doc, undefined) { + + var plugin = {}; + + plugin.name = 'idealforms'; + + plugin.defaults = { + field: '.field', + error: '.error', + iconHtml: '', + iconClass: 'icon', + invalidClass: 'invalid', + validClass: 'valid', + silentLoad: true, + onValidate: $.noop, + onSubmit: $.noop + }; + + plugin.global = { + + _format: function(str) { + var args = [].slice.call(arguments, 1); + return str.replace(/\{(\d)\}/g, function(_, match) { + return args[+match] || ''; + }).replace(/\{\*([^*}]*)\}/g, function(_, sep) { + return args.join(sep || ', '); + }); + }, + + _getKey: function(key, obj) { + return key.split('.').reduce(function(a,b) { + return a && a[b]; + }, obj); + }, + + ruleSeparator: ' ', + argSeparator: ':', + + rules: require('./rules'), + errors: require('./errors'), + + extensions: [ + require('./extensions/dynamic-fields/dynamic-fields.ext'), + require('./extensions/ajax/ajax.ext'), + require('./extensions/steps/steps.ext'), + require('./extensions/custom-inputs/custom-inputs.ext'), + require('./extensions/datepicker/datepicker.ext') + ] + }; + + plugin.methods = $.extend({}, require('./private'), require('./public')); + + require('./plugin')(plugin); + +}(jQuery, window, document)); diff --git a/js/out/jquery.idealforms.js b/js/out/jquery.idealforms.js new file mode 100644 index 0000000..ad83374 --- /dev/null +++ b/js/out/jquery.idealforms.js @@ -0,0 +1,1209 @@ +;(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o')[0].multiple !== 'undefined' + , isIE = /msie/i.test(navigator.userAgent) + , plugin = {}; + + plugin.name = 'idealfile'; + + plugin.methods = { + + _init: function() { + + var $file = $(this.el).addClass('ideal-file') // the original file input + , $wrap = $('
      ') + , $input = $('') + // Button that will be used in non-IE browsers + , $button = $('') + // Hack for IE + , $label = $(''); + + // Hide by shifting to the left so we + // can still trigger events + $file.css({ + position: 'absolute', + left: '-9999px' + }); + + $wrap.append($input, (isIE ? $label : $button)).insertAfter($file); + + // Prevent focus + $file.attr('tabIndex', -1); + $button.attr('tabIndex', -1); + + $button.click(function () { + $file.focus().click(); // Open dialog + }); + + $file.change(function () { + + var files = [] + , fileArr, filename; + + // If multiple is supported then extract + // all filenames from the file array + if (multipleSupport) { + fileArr = $file[0].files; + for (var i = 0, len = fileArr.length; i < len; i++) { + files.push(fileArr[i].name); + } + filename = files.join(', '); + + // If not supported then just take the value + // and remove the path to just show the filename + } else { + filename = $file.val().split('\\').pop(); + } + + $input .val(filename).attr('title', filename); + + }); + + $input.on({ + blur: function () { + $file.trigger('blur'); + }, + keydown: function (e) { + if (e.which === 13) { // Enter + if (!isIE) $file.trigger('click'); + $(this).closest('form').one('keydown', function(e) { + if (e.which === 13) e.preventDefault(); + }); + } else if (e.which === 8 || e.which === 46) { // Backspace & Del + // In IE the value is read-only + // with this trick we remove the old input and add + // a clean clone with all the original events attached + if (isIE) $file.replaceWith($file = $file.clone(true)); + $file.val('').trigger('change'); + $input.val(''); + } else if (e.which === 9) { // TAB + return; + } else { // All other keys + return false; + } + } + }); + + } + + }; + + require('../../plugin')(plugin); + +}(jQuery, window, document)); + +},{"../../plugin":11}],5:[function(require,module,exports){ +/* + * idealRadioCheck: jQuery plguin for checkbox and radio replacement + * Usage: $('input[type=checkbox], input[type=radio]').idealRadioCheck() + */ +(function($, win, doc, undefined) { + + var plugin = {}; + + plugin.name = 'idealradiocheck'; + + plugin.methods = { + + _init: function() { + + var $input = $(this.el); + var $span = $(''); + + $span.addClass('ideal-'+ ($input.is(':checkbox') ? 'check' : 'radio')); + $input.is(':checked') && $span.addClass('checked'); // init + $span.insertAfter($input); + + $input.parent('label') + .addClass('ideal-radiocheck-label') + .attr('onclick', ''); // Fix clicking label in iOS + + $input.css({ position: 'absolute', left: '-9999px' }); // hide by shifting left + + // Events + $input.on({ + change: function() { + var $input = $(this); + if ( $input.is('input[type="radio"]') ) { + $input.parent().siblings('label').find('.ideal-radio').removeClass('checked'); + } + $span.toggleClass('checked', $input.is(':checked')); + }, + focus: function() { $span.addClass('focus') }, + blur: function() { $span.removeClass('focus') }, + click: function() { $(this).trigger('focus') } + }); + } + + }; + + require('../../plugin')(plugin); + +}(jQuery, window, document)); + + +},{"../../plugin":11}],6:[function(require,module,exports){ +module.exports = { + + name: 'datepicker', + + methods: { + + // @extend + _init: function() { + this._buildDatepicker(); + }, + + _buildDatepicker: function() { + + var $datepicker = this.$form.find('input.datepicker'); + + // Always show datepicker below the input + if (jQuery.ui) { + $.datepicker._checkOffset = function(a,b,c){ return b }; + } + + if (jQuery.ui && $datepicker.length) { + + $datepicker.each(function() { + + $(this).datepicker({ + beforeShow: function(input) { + $(input).addClass('open'); + }, + onChangeMonthYear: function() { + // Hack to fix IE9 not resizing + var $this = $(this) + , width = $this.outerWidth(); // cache first! + setTimeout(function() { + $this.datepicker('widget').css('width', width); + }, 1); + }, + onClose: function() { + $(this).removeClass('open'); + } + }); + }); + + // Adjust width + $datepicker.on('focus keyup', function() { + var t = $(this), w = t.outerWidth(); + t.datepicker('widget').css('width', w); + }); + } + } + + } +}; + +},{}],7:[function(require,module,exports){ +function template(html, data) { + + var loop = /\{@([^}]+)\}(.+?)\{\/\1\}/g + , loopVariable = /\{#([^}]+)\}/g + , variable = /\{([^}]+)\}/g; + + return html + .replace(loop, function(_, key, list) { + return $.map(data[key], function(item) { + return list.replace(loopVariable, function(_, k) { + return item[k]; + }); + }).join(''); + }) + .replace(variable, function(_, key) { + return data[key] || ''; + }); +} + +module.exports = { + + name: 'dynamicFields', + + options: { + + templates: { + + base:'\ +
      \ + \ + {field}\ + \ +
      \ + ', + + text: '', + + file: '', + + textarea: '', + + group: '\ +

      \ + {@list}\ + \ + {/list}\ +

      \ + ', + + select: '\ + \ + ' + } + }, + + methods: { + + addFields: function(fields) { + + var self = this; + + $.each(fields, function(name, field) { + + var typeArray = field.type.split(':') + , rules = {}; + + field.name = name; + field.type = typeArray[0]; + if (typeArray[1]) field.subtype = typeArray[1]; + + var html = template(self.opts.templates.base, { + label: field.label, + field: template(self.opts.templates[field.type], field) + }); + + if (field.after || field.before) { + self.$form.find('[name='+ (field.after || field.before) +']').each(function() { + self._getField(this)[field.after ? 'after' : 'before'](html); + }); + } else { + self.$form.find(self.opts.field).last().after(html); + } + + if (field.rules) { + rules[name] = field.rules; + self.addRules(rules); + } + }); + + this._inject('addFields'); + }, + + removeFields: function(names) { + + var self = this; + + $.each(names.split(' '), function(i, name) { + var $field = self._getField($('[name="'+ name +'"]')); + self.$fields = self.$fields.filter(function() { + return ! $(this).is($field); + }); + $field.remove(); + }); + + this._inject('removeFields'); + }, + + toggleFields: function(names) { + + var self = this; + + $.each(names.split(' '), function(i, name) { + var $field = self._getField($('[name="'+ name +'"]')); + $field.data('idealforms-valid', $field.is(':visible')).toggle(); + }); + + this._inject('toggleFields'); + } + + } +}; + +},{}],8:[function(require,module,exports){ +/*! + * Ideal Steps +*/ +(function($, win, doc, undefined) { + + var plugin = {}; + + plugin.name = 'idealsteps'; + + plugin.defaults = { + nav: '.idealsteps-nav', + navItems: 'li', + buildNavItems: true, + wrap: '.idealsteps-wrap', + step: '.idealsteps-step', + activeClass: 'idealsteps-step-active', + before: null, + after: null, + fadeSpeed: 0 + }; + + plugin.methods = { + + _init: function() { + + var self = this, + active = this.opts.activeClass; + + this.$el = $(this.el); + + this.$nav = this.$el.find(this.opts.nav); + this.$navItems = this.$nav.find(this.opts.navItems); + + this.$wrap = this.$el.find(this.opts.wrap); + this.$steps = this.$wrap.find(this.opts.step); + + if (this.opts.buildNavItems) this._buildNavItems(); + + this.$steps.hide().first().show(); + this.$navItems.removeClass(active).first().addClass(active); + + this.$navItems.click(function() { + self.go(self.$navItems.index(this)); + }); + }, + + _buildNavItems: function() { + + var self = this, + isCustom = typeof this.opts.buildNavItems == 'function', + item = function(val){ return '
    • '+ val +'
    • '; }, + items; + + items = isCustom ? + this.$steps.map(function(i){ return item(self.opts.buildNavItems.call(self, i)) }).get() : + this.$steps.map(function(i){ return item(++i); }).get(); + + this.$navItems = $(items.join('')); + + this.$nav.append($('
        ').append(this.$navItems)); + }, + + _getCurIdx: function() { + return this.$steps.index(this.$steps.filter(':visible')); + }, + + go: function(idx) { + + var active = this.opts.activeClass, + fadeSpeed = this.opts.fadeSpeed; + + if (typeof idx == 'function') idx = idx.call(this, this._getCurIdx()); + + if (idx >= this.$steps.length) idx = 0; + if (idx < 0) idx = this.$steps.length-1; + + if (this.opts.before) this.opts.before.call(this, idx); + + this.$navItems.removeClass(active).eq(idx).addClass(active); + this.$steps.fadeOut(fadeSpeed).eq(idx).fadeIn(fadeSpeed); + + if (this.opts.after) this.opts.after.call(this, idx); + }, + + prev: function() { + this.go(this._getCurIdx() - 1); + }, + + next: function() { + this.go(this._getCurIdx() + 1); + }, + + first: function() { + this.go(0); + }, + + last: function() { + this.go(this.$steps.length-1); + } + }; + + require('../../plugin')(plugin); + +}(jQuery, window, document)); + +},{"../../plugin":11}],9:[function(require,module,exports){ +require('./idealsteps'); + +module.exports = { + + name: 'steps', + + options: { + stepsContainer: '.idealsteps-container', + stepsOptions: {} + }, + + methods: { + + // @extend + _init: function() { + this._buildSteps(); + }, + + // @extend + _validate: function() { + + var self = this; + + this._updateSteps(); + + if ($.idealforms.hasExtension('idealAjax')) { + $.each($.idealforms._requests, function(key, request) { + request.done(function(){ self._updateSteps() }); + }); + } + }, + + // @extend + focusFirstInvalid: function(firstInvalid) { + + var self = this; + + this.$stepsContainer.idealsteps('go', function() { + return this.$steps.filter(function() { + return $(this).find(firstInvalid).length; + }).index(); + }); + }, + + _buildSteps: function() { + + var self = this, options + , hasRules = ! $.isEmptyObject(this.opts.rules) + , counter = hasRules + ? '' + : '0'; + + options = $.extend({}, { + buildNavItems: function(i){ return 'Step '+ (i+1) + counter } + }, this.opts.stepsOptions); + + this.$stepsContainer = this.$form.closest(this.opts.stepsContainer).idealsteps(options); + }, + + _updateSteps: function() { + + var self = this; + + this.$stepsContainer.idealsteps('_inject', function() { + + var idealsteps = this; + + this.$navItems.each(function(i) { + var invalid = idealsteps.$steps.eq(i).find(self.getInvalid()).length; + $(this).find('span').text(invalid).toggleClass('zero', ! invalid); + }); + }); + }, + + // @extend + addRules: function() { + this.firstStep(); + }, + + // @extend + toggleFields: function() { + this._updateSteps(); + }, + + // @extend + removeFields: function() { + this._updateSteps(); + }, + + goToStep: function(idx) { + this.$stepsContainer.idealsteps('go', idx); + }, + + prevStep: function() { + this.$stepsContainer.idealsteps('prev'); + }, + + nextStep: function() { + this.$stepsContainer.idealsteps('next'); + }, + + firstStep: function() { + this.$stepsContainer.idealsteps('first'); + }, + + lastStep: function() { + this.$stepsContainer.idealsteps('last'); + } + } + +}; + +},{"./idealsteps":8}],10:[function(require,module,exports){ +/*! + * jQuery Ideal Forms + * @author: Cedric Ruiz + * @version: 3.0 + * @license GPL or MIT + */ +(function($, win, doc, undefined) { + + var plugin = {}; + + plugin.name = 'idealforms'; + + plugin.defaults = { + field: '.field', + error: '.error', + iconHtml: '', + iconClass: 'icon', + invalidClass: 'invalid', + validClass: 'valid', + silentLoad: true, + onValidate: $.noop, + onSubmit: $.noop + }; + + plugin.global = { + + _format: function(str) { + var args = [].slice.call(arguments, 1); + return str.replace(/\{(\d)\}/g, function(_, match) { + return args[+match] || ''; + }).replace(/\{\*([^*}]*)\}/g, function(_, sep) { + return args.join(sep || ', '); + }); + }, + + _getKey: function(key, obj) { + return key.split('.').reduce(function(a,b) { + return a && a[b]; + }, obj); + }, + + ruleSeparator: ' ', + argSeparator: ':', + + rules: require('./rules'), + errors: require('./errors'), + + extensions: [ + require('./extensions/dynamic-fields/dynamic-fields.ext'), + require('./extensions/ajax/ajax.ext'), + require('./extensions/steps/steps.ext'), + require('./extensions/custom-inputs/custom-inputs.ext'), + require('./extensions/datepicker/datepicker.ext') + ] + }; + + plugin.methods = $.extend({}, require('./private'), require('./public')); + + require('./plugin')(plugin); + +}(jQuery, window, document)); + +},{"./errors":1,"./extensions/ajax/ajax.ext":2,"./extensions/custom-inputs/custom-inputs.ext":3,"./extensions/datepicker/datepicker.ext":6,"./extensions/dynamic-fields/dynamic-fields.ext":7,"./extensions/steps/steps.ext":9,"./plugin":11,"./private":12,"./public":13,"./rules":14}],11:[function(require,module,exports){ +/** + * Plugin boilerplate + */ +module.exports = (function() { + + var AP = Array.prototype; + + return function(plugin) { + + $.extend({ + name: 'plugin', + defaults: {}, + methods: {}, + global: {}, + }, plugin); + + $[plugin.name] = $.extend({ + + addExtension: function(extension) { + plugin.global.extensions.push(extension); + }, + + hasExtension: function(extension) { + return plugin.global.extensions.filter(function(ext) { + return ext.name == extension; + }).length; + } + }, plugin.global); + + function Plugin(element, options) { + + this.opts = $.extend({}, plugin.defaults, options); + this.el = element; + + this._name = plugin.name; + + this._init(); + } + + Plugin._extended = {}; + + Plugin.prototype._extend = function(extensions) { + + var self = this + , disabled = self.opts.disabledExtensions || 'none'; + + $.each(extensions, function(i, extension) { + + $.extend(self.opts, $.extend(true, extension.options, self.opts)); + + $.each(extension.methods, function(method, fn) { + + if (disabled.indexOf(extension.name) > -1) { + return; + } + + if (Plugin.prototype[method]) { + Plugin._extended[method] = Plugin._extended[method] || []; + Plugin._extended[method].push({ name: extension.name, fn: fn }); + } else { + Plugin.prototype[method] = fn; + } + }); + + }); + }; + + Plugin.prototype._inject = function(method) { + + var args = [].slice.call(arguments, 1); + + if (typeof method == 'function') return method.call(this); + + var self = this; + + if (Plugin._extended[method]) { + $.each(Plugin._extended[method], function(i, plugin) { + plugin.fn.apply(self, args); + }); + } + }; + + Plugin.prototype._init = $.noop; + + Plugin.prototype[plugin.name] = function(method) { + if (!method) return this; + try { return this[method].apply(this, AP.slice.call(arguments, 1)); } + catch(e) {} + }; + + $.extend(Plugin.prototype, plugin.methods); + + $.fn[plugin.name] = function() { + + var args = AP.slice.call(arguments) + , methodArray = typeof args[0] == 'string' && args[0].split(':') + , method = methodArray[methodArray.length > 1 ? 1 : 0] + , prefix = methodArray.length > 1 && methodArray[0] + , opts = typeof args[0] == 'object' && args[0] + , params = args.slice(1) + , ret; + + if (prefix) { + method = prefix + method.substr(0,1).toUpperCase() + method.substr(1,method.length-1); + } + + this.each(function() { + + var instance = $.data(this, plugin.name); + + // Method + if (instance) { + return ret = instance[plugin.name].apply(instance, [method].concat(params)); + } + + // Init + return $.data(this, plugin.name, new Plugin(this, opts)); + }); + + return prefix ? ret : this; + }; + }; + +}()); + +},{}],12:[function(require,module,exports){ +/** + * Private methods + */ +module.exports = { + + _init: function() { + + var self = this; + + this._extend($.idealforms.extensions); + + this.$form = $(this.el); + this.$fields = $(); + this.$inputs = $(); + + this.$form.submit(function(e) { + e.preventDefault(); + self.focusFirstInvalid(); + self.opts.onSubmit.call(this, self.getInvalid().length, e); + }); + + this._inject('_init'); + + this.addRules(this.opts.rules || {}); + + if (! this.opts.silentLoad) this.focusFirstInvalid(); + }, + + _buildField: function(input) { + + var self = this + , $field = this._getField(input) + , $icon; + + $icon = $(this.opts.iconHtml, { + class: this.opts.iconClass, + click: function(){ $(input).focus() } + }); + + if (! this.$fields.filter($field).length) { + this.$fields = this.$fields.add($field); + if (this.opts.iconHtml) $field.append($icon); + $field.addClass('idealforms-field idealforms-field-'+ input.type); + } + + this._addEvents(input); + + this._inject('_buildField', input); + }, + + _addEvents: function(input) { + + var self = this + , $field = this._getField(input); + + $(input) + .on('change keyup', function(e) { + + var oldValue = $field.data('idealforms-value'); + + if (e.which == 9 || e.which == 16) return; + if (! $(this).is(':checkbox, :radio') && oldValue == this.value) return; + + $field.data('idealforms-value', this.value); + + self._validate(this, true, true); + }) + .focus(function() { + + if (self.isValid(this.name)) return false; + + if (self._isRequired(this) || this.value) { + $field.find(self.opts.error).show(); + } + }) + .blur(function() { + $field.find(self.opts.error).hide(); + }); + }, + + _isRequired: function(input) { + // We assume non-text inputs with rules are required + if ($(input).is(':checkbox, :radio, select')) return true; + return this.opts.rules[input.name].indexOf('required') > -1; + }, + + _getRelated: function(input) { + return this._getField(input).find('[name="'+ input.name +'"]'); + }, + + _getField: function(input) { + return $(input).closest(this.opts.field); + }, + + _getFirstInvalid: function() { + return this.getInvalid().first().find('input:first, textarea, select'); + }, + + _handleError: function(input, error, valid) { + valid = valid || this.isValid(input.name); + var $error = this._getField(input).find(this.opts.error); + this.$form.find(this.opts.error).hide(); + if (error) $error.text(error); + $error.toggle(!valid); + }, + + _handleStyle: function(input, valid) { + valid = valid || this.isValid(input.name); + this._getField(input) + .removeClass(this.opts.validClass +' '+ this.opts.invalidClass) + .addClass(valid ? this.opts.validClass : this.opts.invalidClass) + .find('.'+ this.opts.iconClass).show(); + }, + + _fresh: function(input) { + this._getField(input) + .removeClass(this.opts.validClass +' '+ this.opts.invalidClass) + .find(this.opts.error).hide() + .end() + .find('.'+ this.opts.iconClass).toggle(this._isRequired(input)); + }, + + _validate: function(input, handleError, handleStyle) { + + var self = this + , $field = this._getField(input) + , userRules = this.opts.rules[input.name].split($.idealforms.ruleSeparator) + , valid = true + , rule; + + // Non-required input with empty value must pass validation + if (! input.value && ! this._isRequired(input)) { + $field.removeData('idealforms-valid'); + this._fresh(input); + + // Required inputs + } else { + + $.each(userRules, function(i, userRule) { + + userRule = userRule.split($.idealforms.argSeparator); + + rule = userRule[0]; + + var theRule = $.idealforms.rules[rule] + , args = userRule.slice(1) + , error; + + error = $.idealforms._format.apply(null, [ + $.idealforms._getKey('errors.'+ input.name +'.'+ rule, self.opts) || + $.idealforms.errors[rule] + ].concat(args)); + + valid = typeof theRule == 'function' + ? theRule.apply(self, [input, input.value].concat(args)) + : theRule.test(input.value); + + $field.data('idealforms-valid', valid); + + if (handleError) self._handleError(input, error, valid); + if (handleStyle) self._handleStyle(input, valid); + + self.opts.onValidate.call(self, input, rule, valid); + + return valid; + }); + } + + this._inject('_validate', input, rule, valid); + + return valid; + } + +}; + +},{}],13:[function(require,module,exports){ +/** + * Public methods + */ +module.exports = { + + addRules: function(rules) { + + var self = this; + + var $inputs = this.$form.find($.map(rules, function(_, name) { + return '[name="'+ name +'"]'; + }).join(',')); + + $.extend(this.opts.rules, rules); + + $inputs.each(function(){ self._buildField(this) }); + + this.$inputs = this.$inputs + .add($inputs) + .each(function(){ self._validate(this, true) }); + + this.$fields.find(this.opts.error).hide(); + + this._inject('addRules'); + }, + + getInvalid: function() { + return this.$fields.filter(function() { + return $(this).data('idealforms-valid') === false; + }); + }, + + focusFirstInvalid: function() { + + var firstInvalid = this._getFirstInvalid()[0]; + + if (firstInvalid) { + this._handleError(firstInvalid); + this._handleStyle(firstInvalid); + this._inject('focusFirstInvalid', firstInvalid); + firstInvalid.focus(); + } + }, + + isValid: function(name) { + if (name) return ! this.getInvalid().find('[name="'+ name +'"]').length; + return ! this.getInvalid().length; + }, + + reset: function(name) { + + var self = this + , $inputs = this.$inputs; + + if (name) $inputs = $inputs.filter('[name="'+ name +'"]'); + + $inputs.filter('input:not(:checkbox, :radio)').val(''); + $inputs.filter(':checkbox, :radio').prop('checked', false); + $inputs.filter('select').find('option').prop('selected', function() { + return this.defaultSelected; + }); + + $inputs.change().each(function(){ self._resetErrorAndStyle(this) }); + } + +}; + +},{}],14:[function(require,module,exports){ +/** + * Rules + */ +module.exports = { + + required: /.+/, + digits: /^\d+$/, + email: /^[^@]+@[^@]+\..{2,6}$/, + username: /^[a-z](?=[\w.]{3,31}$)\w*\.?\w*$/i, + pass: /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/, + strongpass: /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/, + phone: /^[2-9]\d{2}-\d{3}-\d{4}$/, + zip: /^\d{5}$|^\d{5}-\d{4}$/, + url: /^(?:(ftp|http|https):\/\/)?(?:[\w\-]+\.)+[a-z]{2,6}([\:\/?#].*)?$/i, + + number: function(input, value) { + return !isNaN(value); + }, + + range: function(input, value, mix, max) { + return Number(value) >= min && Number(value) <= max; + }, + + min: function(input, value, min) { + return value.length >= min; + }, + + max: function(input, value, max) { + return value.length <= max; + }, + + minoption: function(input, value, min) { + return this._getRelated(input).filter(':checked').length >= min; + }, + + maxoption: function(input, value, max) { + return this._getRelated(input).filter(':checked').length <= max; + }, + + minmax: function(input, value, min, max) { + return value.length >= min && value.length <= max; + }, + + select: function(input, value, def) { + return value != def; + }, + + extension: function(input) { + + var extensions = [].slice.call(arguments, 1) + , valid = false; + + $.each(input.files || [{name: input.value}], function(i, file) { + valid = $.inArray(file.name.match(/\.(.+)$/)[1], extensions) > -1; + }); + + return valid; + }, + + equalto: function(input, value, target) { + + var self = this + , $target = $('[name="'+ target +'"]'); + + if (this.getInvalid().find($target).length) return false; + + $target.off('keyup.equalto').on('keyup.equalto', function() { + self._validate(input, false, true); + }); + + return input.value == $target.val(); + }, + + date: function(input, value, format) { + + format = format || 'mm/dd/yyyy'; + + var delimiter = /[^mdy]/.exec(format)[0] + , theFormat = format.split(delimiter) + , theDate = value.split(delimiter); + + function isDate(date, format) { + + var m, d, y; + + for (var i = 0, len = format.length; i < len; i++) { + if (/m/.test(format[i])) m = date[i]; + if (/d/.test(format[i])) d = date[i]; + if (/y/.test(format[i])) y = date[i]; + } + + if (!m || !d || !y) return false; + + return m > 0 && m < 13 && + y && y.length == 4 && + d > 0 && d <= (new Date(y, m, 0)).getDate(); + } + + return isDate(theDate, theFormat); + } + +}; + +},{}]},{},[10]) +//@ sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlcyI6WyIvdmFyL3d3dy9pZGVhbGZvcm1zL2pzL2Vycm9ycy5qcyIsIi92YXIvd3d3L2lkZWFsZm9ybXMvanMvZXh0ZW5zaW9ucy9hamF4L2FqYXguZXh0LmpzIiwiL3Zhci93d3cvaWRlYWxmb3Jtcy9qcy9leHRlbnNpb25zL2N1c3RvbS1pbnB1dHMvY3VzdG9tLWlucHV0cy5leHQuanMiLCIvdmFyL3d3dy9pZGVhbGZvcm1zL2pzL2V4dGVuc2lvbnMvY3VzdG9tLWlucHV0cy9pZGVhbGZpbGUuanMiLCIvdmFyL3d3dy9pZGVhbGZvcm1zL2pzL2V4dGVuc2lvbnMvY3VzdG9tLWlucHV0cy9pZGVhbHJhZGlvY2hlY2suanMiLCIvdmFyL3d3dy9pZGVhbGZvcm1zL2pzL2V4dGVuc2lvbnMvZGF0ZXBpY2tlci9kYXRlcGlja2VyLmV4dC5qcyIsIi92YXIvd3d3L2lkZWFsZm9ybXMvanMvZXh0ZW5zaW9ucy9keW5hbWljLWZpZWxkcy9keW5hbWljLWZpZWxkcy5leHQuanMiLCIvdmFyL3d3dy9pZGVhbGZvcm1zL2pzL2V4dGVuc2lvbnMvc3RlcHMvaWRlYWxzdGVwcy5qcyIsIi92YXIvd3d3L2lkZWFsZm9ybXMvanMvZXh0ZW5zaW9ucy9zdGVwcy9zdGVwcy5leHQuanMiLCIvdmFyL3d3dy9pZGVhbGZvcm1zL2pzL21haW4uanMiLCIvdmFyL3d3dy9pZGVhbGZvcm1zL2pzL3BsdWdpbi5qcyIsIi92YXIvd3d3L2lkZWFsZm9ybXMvanMvcHJpdmF0ZS5qcyIsIi92YXIvd3d3L2lkZWFsZm9ybXMvanMvcHVibGljLmpzIiwiL3Zhci93d3cvaWRlYWxmb3Jtcy9qcy9ydWxlcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRXJyb3JzXG4gKi9cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gIHJlcXVpcmVkOiAnVGhpcyBmaWVsZCBpcyByZXF1aXJlZCcsXG4gIGRpZ2l0czogJ011c3QgYmUgb25seSBkaWdpdHMnLFxuICBuYW1lOiAnTXVzdCBiZSBhdCBsZWFzdCAzIGNoYXJhY3RlcnMgbG9uZyBhbmQgbXVzdCBvbmx5IGNvbnRhaW4gbGV0dGVycycsXG4gIGVtYWlsOiAnTXVzdCBiZSBhIHZhbGlkIGVtYWlsJyxcbiAgdXNlcm5hbWU6ICdNdXN0IGJlIGF0IGJldHdlZW4gNCBhbmQgMzIgY2hhcmFjdGVycyBsb25nIGFuZCBzdGFydCB3aXRoIGEgbGV0dGVyLiBZb3UgbWF5IHVzZSBsZXR0ZXJzLCBudW1iZXJzLCB1bmRlcnNjb3JlcywgYW5kIG9uZSBkb3QnLFxuICBwYXNzOiAnTXVzdCBiZSBhdCBsZWFzdCA2IGNoYXJhY3RlcnMgbG9uZywgYW5kIGNvbnRhaW4gYXQgbGVhc3Qgb25lIG51bWJlciwgb25lIHVwcGVyY2FzZSBhbmQgb25lIGxvd2VyY2FzZSBsZXR0ZXInLFxuICBzdHJvbmdwYXNzOiAnTXVzdCBiZSBhdCBsZWFzdCA4IGNoYXJhY3RlcnMgbG9uZyBhbmQgY29udGFpbiBhdCBsZWFzdCBvbmUgdXBwZXJjYXNlIGFuZCBvbmUgbG93ZXJjYXNlIGxldHRlciBhbmQgb25lIG51bWJlciBvciBzcGVjaWFsIGNoYXJhY3RlcicsXG4gIHBob25lOiAnTXVzdCBiZSBhIHZhbGlkIHBob25lIG51bWJlcicsXG4gIHppcDogJ011c3QgYmUgYSB2YWxpZCB6aXAgY29kZScsXG4gIHVybDogJ011c3QgYmUgYSB2YWxpZCBVUkwnLFxuICBudW1iZXI6ICdNdXN0IGJlIGEgbnVtYmVyJyxcbiAgcmFuZ2U6ICdNdXN0IGJlIGEgbnVtYmVyIGJldHdlZW4gezB9IGFuZCB7MX0nLFxuICBtaW46ICdNdXN0IGJlIGF0IGxlYXN0IHswfSBjaGFyYWN0ZXJzIGxvbmcnLFxuICBtYXg6ICdNdXN0IGJlIHVuZGVyIHswfSBjaGFyYWN0ZXJzJyxcbiAgbWlub3B0aW9uOiAnU2VsZWN0IGF0IGxlYXN0IHswfSBvcHRpb25zJyxcbiAgbWF4b3B0aW9uOiAnU2VsZWN0IG5vIG1vcmUgdGhhbiB7MH0gb3B0aW9ucycsXG4gIG1pbm1heDogJ011c3QgYmUgYmV0d2VlbiB7MH0gYW5kIHsxfSBjaGFyYWN0ZXJzIGxvbmcnLFxuICBzZWxlY3Q6ICdTZWxlY3QgYW4gb3B0aW9uJyxcbiAgZXh0ZW5zaW9uOiAnRmlsZShzKSBtdXN0IGhhdmUgYSB2YWxpZCBleHRlbnNpb24gKHsqfSknLFxuICBlcXVhbHRvOiAnTXVzdCBoYXZlIHRoZSBzYW1lIHZhbHVlIGFzIHRoZSBcInswfVwiIGZpZWxkJyxcbiAgZGF0ZTogJ011c3QgYmUgYSB2YWxpZCBkYXRlIHswfSdcblxufTtcbiIsIm1vZHVsZS5leHBvcnRzID0ge1xuXG4gIG5hbWU6ICdpZGVhbEFqYXgnLFxuXG4gIG1ldGhvZHM6IHtcblxuICAgIC8vIEBleHRlbmRcbiAgICBfaW5pdDogZnVuY3Rpb24oKSB7XG5cbiAgICAgICQuZXh0ZW5kKCQuaWRlYWxmb3JtcywgeyBfcmVxdWVzdHM6IHt9IH0pO1xuXG4gICAgICAkLmV4dGVuZCgkLmlkZWFsZm9ybXMuZXJyb3JzLCB7XG4gICAgICAgIGFqYXg6ICdMb2FkaW5nLi4uJ1xuICAgICAgfSk7XG5cbiAgICAgICQuZXh0ZW5kKCQuaWRlYWxmb3Jtcy5ydWxlcywge1xuXG4gICAgICAgIGFqYXg6IGZ1bmN0aW9uKGlucHV0KSB7XG5cbiAgICAgICAgICB2YXIgc2VsZiA9IHRoaXNcbiAgICAgICAgICAgICwgJGZpZWxkID0gdGhpcy5fZ2V0RmllbGQoaW5wdXQpXG4gICAgICAgICAgICAsIHVybCA9ICQoaW5wdXQpLmRhdGEoJ2lkZWFsZm9ybXMtYWpheCcpXG4gICAgICAgICAgICAsIHVzZXJFcnJvciA9ICQuaWRlYWxmb3Jtcy5fZ2V0S2V5KCdlcnJvcnMuJysgaW5wdXQubmFtZSArJy5hamF4RXJyb3InLCBzZWxmLm9wdHMpXG4gICAgICAgICAgICAsIHJlcXVlc3RzID0gJC5pZGVhbGZvcm1zLl9yZXF1ZXN0c1xuICAgICAgICAgICAgLCBkYXRhID0ge307XG5cbiAgICAgICAgICBkYXRhW2lucHV0Lm5hbWVdID0gaW5wdXQudmFsdWU7XG5cbiAgICAgICAgICAkZmllbGQuYWRkQ2xhc3MoJ2FqYXgnKTtcblxuICAgICAgICAgIGlmIChyZXF1ZXN0c1tpbnB1dC5uYW1lXSkgcmVxdWVzdHNbaW5wdXQubmFtZV0uYWJvcnQoKTtcblxuICAgICAgICAgIHJlcXVlc3RzW2lucHV0Lm5hbWVdID0gJC5wb3N0KHVybCwgZGF0YSwgZnVuY3Rpb24ocmVzcCkge1xuXG4gICAgICAgICAgICBpZiAocmVzcCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAkZmllbGQuZGF0YSgnaWRlYWxmb3Jtcy12YWxpZCcsIHRydWUpO1xuICAgICAgICAgICAgICBzZWxmLl9oYW5kbGVFcnJvcihpbnB1dCk7XG4gICAgICAgICAgICAgIHNlbGYuX2hhbmRsZVN0eWxlKGlucHV0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHNlbGYuX2hhbmRsZUVycm9yKGlucHV0LCB1c2VyRXJyb3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkZmllbGQucmVtb3ZlQ2xhc3MoJ2FqYXgnKTtcblxuICAgICAgICAgIH0sICdqc29uJyk7XG5cbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICAvLyBAZXh0ZW5kXG4gICAgX3ZhbGlkYXRlOiBmdW5jdGlvbihpbnB1dCwgcnVsZSkge1xuICAgICAgaWYgKHJ1bGUgIT0gJ2FqYXgnICYmICQuaWRlYWxmb3Jtcy5fcmVxdWVzdHNbaW5wdXQubmFtZV0pIHtcbiAgICAgICAgJC5pZGVhbGZvcm1zLl9yZXF1ZXN0c1tpbnB1dC5uYW1lXS5hYm9ydCgpO1xuICAgICAgICB0aGlzLl9nZXRGaWVsZChpbnB1dCkucmVtb3ZlQ2xhc3MoJ2FqYXgnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgfVxufTtcbiIsInJlcXVpcmUoJy4vaWRlYWxmaWxlJyk7XG5yZXF1aXJlKCcuL2lkZWFscmFkaW9jaGVjaycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuICBuYW1lOiAnY3VzdG9tSW5wdXRzJyxcblxuICBtZXRob2RzOiB7XG5cbiAgICAvLyBAZXh0ZW5kXG4gICAgX2luaXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5fYnVpbGRDdXN0b21JbnB1dHMoKTtcbiAgICB9LFxuXG4gICAgYWRkRmllbGRzOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuX2J1aWxkQ3VzdG9tSW5wdXRzKCk7XG4gICAgfSxcblxuICAgIF9idWlsZEN1c3RvbUlucHV0czogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLiRmb3JtLmZpbmQoJzpmaWxlJykuaWRlYWxmaWxlKCk7XG4gICAgICB0aGlzLiRmb3JtLmZpbmQoJzpjaGVja2JveCwgOnJhZGlvJykuaWRlYWxyYWRpb2NoZWNrKCk7XG4gICAgfVxuXG4gIH1cbn07XG4iLCIvKipcbiAqIElkZWFsIEZpbGVcbiAqL1xuKGZ1bmN0aW9uKCQsIHdpbiwgZG9jLCB1bmRlZmluZWQpIHtcblxuICAvLyBCcm93c2VyIHN1cHBvcnRzIEhUTUw1IG11bHRpcGxlIGZpbGU/XG4gIHZhciBtdWx0aXBsZVN1cHBvcnQgPSB0eXBlb2YgJCgnPGlucHV0Lz4nKVswXS5tdWx0aXBsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAsIGlzSUUgPSAvbXNpZS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudClcbiAgICAsIHBsdWdpbiA9IHt9O1xuXG4gIHBsdWdpbi5uYW1lID0gJ2lkZWFsZmlsZSc7XG5cbiAgcGx1Z2luLm1ldGhvZHMgPSB7XG4gIFxuICAgICAgX2luaXQ6IGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIHZhciAkZmlsZSA9ICQodGhpcy5lbCkuYWRkQ2xhc3MoJ2lkZWFsLWZpbGUnKSAvLyB0aGUgb3JpZ2luYWwgZmlsZSBpbnB1dFxuICAgICAgICAgICwgJHdyYXAgPSAkKCc8ZGl2IGNsYXNzPVwiaWRlYWwtZmlsZS13cmFwXCI+JylcbiAgICAgICAgICAsICRpbnB1dCA9ICQoJzxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiaWRlYWwtZmlsZS1maWxlbmFtZVwiIC8+JylcbiAgICAgICAgICAgIC8vIEJ1dHRvbiB0aGF0IHdpbGwgYmUgdXNlZCBpbiBub24tSUUgYnJvd3NlcnNcbiAgICAgICAgICAsICRidXR0b24gPSAkKCc8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImlkZWFsLWZpbGUtdXBsb2FkXCI+T3BlbjwvYnV0dG9uPicpXG4gICAgICAgICAgICAvLyBIYWNrIGZvciBJRVxuICAgICAgICAgICwgJGxhYmVsID0gJCgnPGxhYmVsIGNsYXNzPVwiaWRlYWwtZmlsZS11cGxvYWRcIiBmb3I9XCInICsgJGZpbGVbMF0uaWQgKyAnXCI+T3BlbjwvbGFiZWw+Jyk7XG5cbiAgICAgICAgLy8gSGlkZSBieSBzaGlmdGluZyB0byB0aGUgbGVmdCBzbyB3ZVxuICAgICAgICAvLyBjYW4gc3RpbGwgdHJpZ2dlciBldmVudHNcbiAgICAgICAgJGZpbGUuY3NzKHtcbiAgICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgICBsZWZ0OiAnLTk5OTlweCdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgJHdyYXAuYXBwZW5kKCRpbnB1dCwgKGlzSUUgPyAkbGFiZWwgOiAkYnV0dG9uKSkuaW5zZXJ0QWZ0ZXIoJGZpbGUpO1xuXG4gICAgICAgIC8vIFByZXZlbnQgZm9jdXNcbiAgICAgICAgJGZpbGUuYXR0cigndGFiSW5kZXgnLCAtMSk7XG4gICAgICAgICRidXR0b24uYXR0cigndGFiSW5kZXgnLCAtMSk7XG5cbiAgICAgICAgJGJ1dHRvbi5jbGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgJGZpbGUuZm9jdXMoKS5jbGljaygpOyAvLyBPcGVuIGRpYWxvZ1xuICAgICAgICB9KTtcblxuICAgICAgICAkZmlsZS5jaGFuZ2UoZnVuY3Rpb24gKCkge1xuXG4gICAgICAgICAgdmFyIGZpbGVzID0gW11cbiAgICAgICAgICAgICwgZmlsZUFyciwgZmlsZW5hbWU7XG5cbiAgICAgICAgICAgIC8vIElmIG11bHRpcGxlIGlzIHN1cHBvcnRlZCB0aGVuIGV4dHJhY3RcbiAgICAgICAgICAgIC8vIGFsbCBmaWxlbmFtZXMgZnJvbSB0aGUgZmlsZSBhcnJheVxuICAgICAgICAgIGlmIChtdWx0aXBsZVN1cHBvcnQpIHtcbiAgICAgICAgICAgIGZpbGVBcnIgPSAkZmlsZVswXS5maWxlcztcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBmaWxlQXJyLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgIGZpbGVzLnB1c2goZmlsZUFycltpXS5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbGVuYW1lID0gZmlsZXMuam9pbignLCAnKTtcblxuICAgICAgICAgICAgLy8gSWYgbm90IHN1cHBvcnRlZCB0aGVuIGp1c3QgdGFrZSB0aGUgdmFsdWVcbiAgICAgICAgICAgIC8vIGFuZCByZW1vdmUgdGhlIHBhdGggdG8ganVzdCBzaG93IHRoZSBmaWxlbmFtZVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmaWxlbmFtZSA9ICRmaWxlLnZhbCgpLnNwbGl0KCdcXFxcJykucG9wKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgJGlucHV0IC52YWwoZmlsZW5hbWUpLmF0dHIoJ3RpdGxlJywgZmlsZW5hbWUpO1xuXG4gICAgICAgIH0pO1xuXG4gICAgICAgICRpbnB1dC5vbih7XG4gICAgICAgICAgYmx1cjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJGZpbGUudHJpZ2dlcignYmx1cicpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAga2V5ZG93bjogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmIChlLndoaWNoID09PSAxMykgeyAvLyBFbnRlclxuICAgICAgICAgICAgICBpZiAoIWlzSUUpICRmaWxlLnRyaWdnZXIoJ2NsaWNrJyk7XG4gICAgICAgICAgICAgICQodGhpcykuY2xvc2VzdCgnZm9ybScpLm9uZSgna2V5ZG93bicsIGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoZS53aGljaCA9PT0gMTMpIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGUud2hpY2ggPT09IDggfHwgZS53aGljaCA9PT0gNDYpIHsgLy8gQmFja3NwYWNlICYgRGVsXG4gICAgICAgICAgICAgIC8vIEluIElFIHRoZSB2YWx1ZSBpcyByZWFkLW9ubHlcbiAgICAgICAgICAgICAgLy8gd2l0aCB0aGlzIHRyaWNrIHdlIHJlbW92ZSB0aGUgb2xkIGlucHV0IGFuZCBhZGRcbiAgICAgICAgICAgICAgLy8gYSBjbGVhbiBjbG9uZSB3aXRoIGFsbCB0aGUgb3JpZ2luYWwgZXZlbnRzIGF0dGFjaGVkXG4gICAgICAgICAgICAgIGlmIChpc0lFKSAkZmlsZS5yZXBsYWNlV2l0aCgkZmlsZSA9ICRmaWxlLmNsb25lKHRydWUpKTtcbiAgICAgICAgICAgICAgJGZpbGUudmFsKCcnKS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICAgICAgJGlucHV0LnZhbCgnJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGUud2hpY2ggPT09IDkpIHsgLy8gVEFCXG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7IC8vIEFsbCBvdGhlciBrZXlzXG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICB9XG4gIFxuICB9O1xuXG4gIHJlcXVpcmUoJy4uLy4uL3BsdWdpbicpKHBsdWdpbik7XG5cbn0oalF1ZXJ5LCB3aW5kb3csIGRvY3VtZW50KSk7XG4iLCIvKlxuICogaWRlYWxSYWRpb0NoZWNrOiBqUXVlcnkgcGxndWluIGZvciBjaGVja2JveCBhbmQgcmFkaW8gcmVwbGFjZW1lbnRcbiAqIFVzYWdlOiAkKCdpbnB1dFt0eXBlPWNoZWNrYm94XSwgaW5wdXRbdHlwZT1yYWRpb10nKS5pZGVhbFJhZGlvQ2hlY2soKVxuICovXG4oZnVuY3Rpb24oJCwgd2luLCBkb2MsIHVuZGVmaW5lZCkge1xuXG4gIHZhciBwbHVnaW4gPSB7fTtcblxuICBwbHVnaW4ubmFtZSA9ICdpZGVhbHJhZGlvY2hlY2snO1xuXG4gIHBsdWdpbi5tZXRob2RzID0ge1xuXG4gICAgX2luaXQ6IGZ1bmN0aW9uKCkge1xuXG4gICAgICB2YXIgJGlucHV0ID0gJCh0aGlzLmVsKTtcbiAgICAgIHZhciAkc3BhbiA9ICQoJzxzcGFuLz4nKTtcblxuICAgICAgJHNwYW4uYWRkQ2xhc3MoJ2lkZWFsLScrICgkaW5wdXQuaXMoJzpjaGVja2JveCcpID8gJ2NoZWNrJyA6ICdyYWRpbycpKTtcbiAgICAgICRpbnB1dC5pcygnOmNoZWNrZWQnKSAmJiAkc3Bhbi5hZGRDbGFzcygnY2hlY2tlZCcpOyAvLyBpbml0XG4gICAgICAkc3Bhbi5pbnNlcnRBZnRlcigkaW5wdXQpO1xuXG4gICAgICAkaW5wdXQucGFyZW50KCdsYWJlbCcpXG4gICAgICAgIC5hZGRDbGFzcygnaWRlYWwtcmFkaW9jaGVjay1sYWJlbCcpXG4gICAgICAgIC5hdHRyKCdvbmNsaWNrJywgJycpOyAvLyBGaXggY2xpY2tpbmcgbGFiZWwgaW4gaU9TXG5cbiAgICAgICRpbnB1dC5jc3MoeyBwb3NpdGlvbjogJ2Fic29sdXRlJywgbGVmdDogJy05OTk5cHgnIH0pOyAvLyBoaWRlIGJ5IHNoaWZ0aW5nIGxlZnRcblxuICAgICAgLy8gRXZlbnRzXG4gICAgICAkaW5wdXQub24oe1xuICAgICAgICBjaGFuZ2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciAkaW5wdXQgPSAkKHRoaXMpO1xuICAgICAgICAgIGlmICggJGlucHV0LmlzKCdpbnB1dFt0eXBlPVwicmFkaW9cIl0nKSApIHtcbiAgICAgICAgICAgICRpbnB1dC5wYXJlbnQoKS5zaWJsaW5ncygnbGFiZWwnKS5maW5kKCcuaWRlYWwtcmFkaW8nKS5yZW1vdmVDbGFzcygnY2hlY2tlZCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAkc3Bhbi50b2dnbGVDbGFzcygnY2hlY2tlZCcsICRpbnB1dC5pcygnOmNoZWNrZWQnKSk7XG4gICAgICAgIH0sXG4gICAgICAgIGZvY3VzOiBmdW5jdGlvbigpIHsgJHNwYW4uYWRkQ2xhc3MoJ2ZvY3VzJykgfSxcbiAgICAgICAgYmx1cjogZnVuY3Rpb24oKSB7ICRzcGFuLnJlbW92ZUNsYXNzKCdmb2N1cycpIH0sXG4gICAgICAgIGNsaWNrOiBmdW5jdGlvbigpIHsgJCh0aGlzKS50cmlnZ2VyKCdmb2N1cycpIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICB9O1xuXG4gIHJlcXVpcmUoJy4uLy4uL3BsdWdpbicpKHBsdWdpbik7XG5cbn0oalF1ZXJ5LCB3aW5kb3csIGRvY3VtZW50KSk7XG5cbiIsIm1vZHVsZS5leHBvcnRzID0ge1xuXG4gIG5hbWU6ICdkYXRlcGlja2VyJyxcblxuICBtZXRob2RzOiB7XG5cbiAgICAvLyBAZXh0ZW5kXG4gICAgX2luaXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5fYnVpbGREYXRlcGlja2VyKCk7XG4gICAgfSxcblxuICAgX2J1aWxkRGF0ZXBpY2tlcjogZnVuY3Rpb24oKSB7XG5cbiAgICAgIHZhciAkZGF0ZXBpY2tlciA9IHRoaXMuJGZvcm0uZmluZCgnaW5wdXQuZGF0ZXBpY2tlcicpO1xuXG4gICAgICAvLyBBbHdheXMgc2hvdyBkYXRlcGlja2VyIGJlbG93IHRoZSBpbnB1dFxuICAgICAgaWYgKGpRdWVyeS51aSkge1xuICAgICAgICAkLmRhdGVwaWNrZXIuX2NoZWNrT2Zmc2V0ID0gZnVuY3Rpb24oYSxiLGMpeyByZXR1cm4gYiB9O1xuICAgICAgfVxuXG4gICAgICBpZiAoalF1ZXJ5LnVpICYmICRkYXRlcGlja2VyLmxlbmd0aCkge1xuXG4gICAgICAgICRkYXRlcGlja2VyLmVhY2goZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgICAkKHRoaXMpLmRhdGVwaWNrZXIoe1xuICAgICAgICAgICAgYmVmb3JlU2hvdzogZnVuY3Rpb24oaW5wdXQpIHtcbiAgICAgICAgICAgICAgJChpbnB1dCkuYWRkQ2xhc3MoJ29wZW4nKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkNoYW5nZU1vbnRoWWVhcjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIC8vIEhhY2sgdG8gZml4IElFOSBub3QgcmVzaXppbmdcbiAgICAgICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKVxuICAgICAgICAgICAgICAgICwgd2lkdGggPSAkdGhpcy5vdXRlcldpZHRoKCk7IC8vIGNhY2hlIGZpcnN0IVxuICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICR0aGlzLmRhdGVwaWNrZXIoJ3dpZGdldCcpLmNzcygnd2lkdGgnLCB3aWR0aCk7XG4gICAgICAgICAgICAgIH0sIDEpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uQ2xvc2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAkKHRoaXMpLnJlbW92ZUNsYXNzKCdvcGVuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEFkanVzdCB3aWR0aFxuICAgICAgICAkZGF0ZXBpY2tlci5vbignZm9jdXMga2V5dXAnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2YXIgdCA9ICQodGhpcyksIHcgPSB0Lm91dGVyV2lkdGgoKTtcbiAgICAgICAgICB0LmRhdGVwaWNrZXIoJ3dpZGdldCcpLmNzcygnd2lkdGgnLCB3KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cbn07XG4iLCJmdW5jdGlvbiB0ZW1wbGF0ZShodG1sLCBkYXRhKSB7XG5cbiAgdmFyIGxvb3AgPSAvXFx7QChbXn1dKylcXH0oLis/KVxce1xcL1xcMVxcfS9nXG4gICAgLCBsb29wVmFyaWFibGUgPSAvXFx7IyhbXn1dKylcXH0vZ1xuICAgICwgdmFyaWFibGUgPSAvXFx7KFtefV0rKVxcfS9nO1xuXG4gIHJldHVybiBodG1sXG4gICAgLnJlcGxhY2UobG9vcCwgZnVuY3Rpb24oXywga2V5LCBsaXN0KSB7XG4gICAgICByZXR1cm4gJC5tYXAoZGF0YVtrZXldLCBmdW5jdGlvbihpdGVtKSB7XG4gICAgICAgIHJldHVybiBsaXN0LnJlcGxhY2UobG9vcFZhcmlhYmxlLCBmdW5jdGlvbihfLCBrKSB7XG4gICAgICAgICAgcmV0dXJuIGl0ZW1ba107XG4gICAgICAgIH0pO1xuICAgICAgfSkuam9pbignJyk7XG4gICAgfSlcbiAgICAucmVwbGFjZSh2YXJpYWJsZSwgZnVuY3Rpb24oXywga2V5KSB7XG4gICAgICByZXR1cm4gZGF0YVtrZXldIHx8ICcnO1xuICAgIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuICBuYW1lOiAnZHluYW1pY0ZpZWxkcycsXG5cbiAgb3B0aW9uczoge1xuXG4gICAgdGVtcGxhdGVzOiB7XG5cbiAgICAgIGJhc2U6J1xcXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaWVsZFwiIHtjbGFzc30+XFxcbiAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJtYWluXCI+e2xhYmVsfTwvbGFiZWw+XFxcbiAgICAgICAgICB7ZmllbGR9XFxcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImVycm9yXCI+PC9zcGFuPlxcXG4gICAgICAgIDwvZGl2PlxcXG4gICAgICAnLFxuXG4gICAgICB0ZXh0OiAnPGlucHV0IG5hbWU9XCJ7bmFtZX1cIiB0eXBlPVwie3N1YnR5cGV9XCIgdmFsdWU9XCJ7dmFsdWV9XCIge2F0dHJzfT4nLFxuXG4gICAgICBmaWxlOiAnPGlucHV0IGlkPVwie25hbWV9IFwibmFtZT1cIntuYW1lfVwiIHR5cGU9XCJmaWxlXCIge2F0dHJzfT4nLFxuXG4gICAgICB0ZXh0YXJlYTogJzx0ZXh0YXJlYSBuYW1lPVwie25hbWV9XCIge2F0dHJzfT57dGV4dH08L3RleHRhcmVhPicsXG5cbiAgICAgIGdyb3VwOiAnXFxcbiAgICAgICAgPHAgY2xhc3M9XCJncm91cFwiPlxcXG4gICAgICAgICAge0BsaXN0fVxcXG4gICAgICAgICAgPGxhYmVsPjxpbnB1dCBuYW1lPVwie25hbWV9XCIgdHlwZT1cIntzdWJ0eXBlfVwiIHZhbHVlPVwieyN2YWx1ZX1cIiB7I2F0dHJzfT57I3RleHR9PC9sYWJlbD5cXFxuICAgICAgICAgIHsvbGlzdH1cXFxuICAgICAgICA8L3A+XFxcbiAgICAgICcsXG5cbiAgICAgIHNlbGVjdDogJ1xcXG4gICAgICAgIDxzZWxlY3QgbmFtZT17bmFtZX0+XFxcbiAgICAgICAgICB7QGxpc3R9XFxcbiAgICAgICAgICA8b3B0aW9uIHZhbHVlPVwieyN2YWx1ZX1cIj57I3RleHR9PC9vcHRpb24+XFxcbiAgICAgICAgICB7L2xpc3R9XFxcbiAgICAgICAgPC9zZWxlY3Q+XFxcbiAgICAgICdcbiAgICB9XG4gIH0sXG5cbiAgbWV0aG9kczoge1xuXG4gICAgYWRkRmllbGRzOiBmdW5jdGlvbihmaWVsZHMpIHtcblxuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgICAkLmVhY2goZmllbGRzLCBmdW5jdGlvbihuYW1lLCBmaWVsZCkge1xuXG4gICAgICAgIHZhciB0eXBlQXJyYXkgPSBmaWVsZC50eXBlLnNwbGl0KCc6JylcbiAgICAgICAgICAsIHJ1bGVzID0ge307XG5cbiAgICAgICAgZmllbGQubmFtZSA9IG5hbWU7XG4gICAgICAgIGZpZWxkLnR5cGUgPSB0eXBlQXJyYXlbMF07XG4gICAgICAgIGlmICh0eXBlQXJyYXlbMV0pIGZpZWxkLnN1YnR5cGUgPSB0eXBlQXJyYXlbMV07XG5cbiAgICAgICAgdmFyIGh0bWwgPSB0ZW1wbGF0ZShzZWxmLm9wdHMudGVtcGxhdGVzLmJhc2UsIHtcbiAgICAgICAgICBsYWJlbDogZmllbGQubGFiZWwsXG4gICAgICAgICAgZmllbGQ6IHRlbXBsYXRlKHNlbGYub3B0cy50ZW1wbGF0ZXNbZmllbGQudHlwZV0sIGZpZWxkKVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoZmllbGQuYWZ0ZXIgfHwgZmllbGQuYmVmb3JlKSB7XG4gICAgICAgICAgc2VsZi4kZm9ybS5maW5kKCdbbmFtZT0nKyAoZmllbGQuYWZ0ZXIgfHwgZmllbGQuYmVmb3JlKSArJ10nKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgc2VsZi5fZ2V0RmllbGQodGhpcylbZmllbGQuYWZ0ZXIgPyAnYWZ0ZXInIDogJ2JlZm9yZSddKGh0bWwpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNlbGYuJGZvcm0uZmluZChzZWxmLm9wdHMuZmllbGQpLmxhc3QoKS5hZnRlcihodG1sKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWVsZC5ydWxlcykge1xuICAgICAgICAgIHJ1bGVzW25hbWVdID0gZmllbGQucnVsZXM7XG4gICAgICAgICAgc2VsZi5hZGRSdWxlcyhydWxlcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9pbmplY3QoJ2FkZEZpZWxkcycpO1xuICAgIH0sXG5cbiAgICByZW1vdmVGaWVsZHM6IGZ1bmN0aW9uKG5hbWVzKSB7XG5cbiAgICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgICAgJC5lYWNoKG5hbWVzLnNwbGl0KCcgJyksIGZ1bmN0aW9uKGksIG5hbWUpIHtcbiAgICAgICAgdmFyICRmaWVsZCA9IHNlbGYuX2dldEZpZWxkKCQoJ1tuYW1lPVwiJysgbmFtZSArJ1wiXScpKTtcbiAgICAgICAgc2VsZi4kZmllbGRzID0gc2VsZi4kZmllbGRzLmZpbHRlcihmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gISAkKHRoaXMpLmlzKCRmaWVsZCk7XG4gICAgICAgIH0pO1xuICAgICAgICAkZmllbGQucmVtb3ZlKCk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5faW5qZWN0KCdyZW1vdmVGaWVsZHMnKTtcbiAgICB9LFxuXG4gICAgdG9nZ2xlRmllbGRzOiBmdW5jdGlvbihuYW1lcykge1xuXG4gICAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICAgICQuZWFjaChuYW1lcy5zcGxpdCgnICcpLCBmdW5jdGlvbihpLCBuYW1lKSB7XG4gICAgICAgIHZhciAkZmllbGQgPSBzZWxmLl9nZXRGaWVsZCgkKCdbbmFtZT1cIicrIG5hbWUgKydcIl0nKSk7XG4gICAgICAgICRmaWVsZC5kYXRhKCdpZGVhbGZvcm1zLXZhbGlkJywgJGZpZWxkLmlzKCc6dmlzaWJsZScpKS50b2dnbGUoKTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9pbmplY3QoJ3RvZ2dsZUZpZWxkcycpO1xuICAgIH1cblxuICB9XG59O1xuIiwiLyohXG4gKiBJZGVhbCBTdGVwc1xuKi9cbihmdW5jdGlvbigkLCB3aW4sIGRvYywgdW5kZWZpbmVkKSB7XG5cbiAgdmFyIHBsdWdpbiA9IHt9O1xuXG4gIHBsdWdpbi5uYW1lID0gJ2lkZWFsc3RlcHMnO1xuXG4gIHBsdWdpbi5kZWZhdWx0cyA9IHtcbiAgICBuYXY6ICcuaWRlYWxzdGVwcy1uYXYnLFxuICAgIG5hdkl0ZW1zOiAnbGknLFxuICAgIGJ1aWxkTmF2SXRlbXM6IHRydWUsXG4gICAgd3JhcDogJy5pZGVhbHN0ZXBzLXdyYXAnLFxuICAgIHN0ZXA6ICcuaWRlYWxzdGVwcy1zdGVwJyxcbiAgICBhY3RpdmVDbGFzczogJ2lkZWFsc3RlcHMtc3RlcC1hY3RpdmUnLFxuICAgIGJlZm9yZTogbnVsbCxcbiAgICBhZnRlcjogbnVsbCxcbiAgICBmYWRlU3BlZWQ6IDBcbiAgfTtcblxuICBwbHVnaW4ubWV0aG9kcyA9IHtcblxuICAgIF9pbml0OiBmdW5jdGlvbigpIHtcblxuICAgICAgdmFyIHNlbGYgPSB0aGlzLFxuICAgICAgICAgIGFjdGl2ZSA9IHRoaXMub3B0cy5hY3RpdmVDbGFzcztcblxuICAgICAgdGhpcy4kZWwgPSAkKHRoaXMuZWwpO1xuXG4gICAgICB0aGlzLiRuYXYgPSB0aGlzLiRlbC5maW5kKHRoaXMub3B0cy5uYXYpO1xuICAgICAgdGhpcy4kbmF2SXRlbXMgPSB0aGlzLiRuYXYuZmluZCh0aGlzLm9wdHMubmF2SXRlbXMpO1xuXG4gICAgICB0aGlzLiR3cmFwID0gdGhpcy4kZWwuZmluZCh0aGlzLm9wdHMud3JhcCk7XG4gICAgICB0aGlzLiRzdGVwcyA9IHRoaXMuJHdyYXAuZmluZCh0aGlzLm9wdHMuc3RlcCk7XG5cbiAgICAgIGlmICh0aGlzLm9wdHMuYnVpbGROYXZJdGVtcykgdGhpcy5fYnVpbGROYXZJdGVtcygpO1xuXG4gICAgICB0aGlzLiRzdGVwcy5oaWRlKCkuZmlyc3QoKS5zaG93KCk7XG4gICAgICB0aGlzLiRuYXZJdGVtcy5yZW1vdmVDbGFzcyhhY3RpdmUpLmZpcnN0KCkuYWRkQ2xhc3MoYWN0aXZlKTtcblxuICAgICAgdGhpcy4kbmF2SXRlbXMuY2xpY2soZnVuY3Rpb24oKSB7XG4gICAgICAgIHNlbGYuZ28oc2VsZi4kbmF2SXRlbXMuaW5kZXgodGhpcykpO1xuICAgICAgfSk7XG4gICAgfSxcblxuICAgIF9idWlsZE5hdkl0ZW1zOiBmdW5jdGlvbigpIHtcblxuICAgICAgdmFyIHNlbGYgPSB0aGlzLFxuICAgICAgICAgIGlzQ3VzdG9tID0gdHlwZW9mIHRoaXMub3B0cy5idWlsZE5hdkl0ZW1zID09ICdmdW5jdGlvbicsXG4gICAgICAgICAgaXRlbSA9IGZ1bmN0aW9uKHZhbCl7IHJldHVybiAnPGxpPjxhIGhyZWY9XCIjXCIgdGFiaW5kZXg9XCItMVwiPicrIHZhbCArJzwvYT48L2xpPic7IH0sXG4gICAgICAgICAgaXRlbXM7XG5cbiAgICAgIGl0ZW1zID0gaXNDdXN0b20gP1xuICAgICAgICB0aGlzLiRzdGVwcy5tYXAoZnVuY3Rpb24oaSl7IHJldHVybiBpdGVtKHNlbGYub3B0cy5idWlsZE5hdkl0ZW1zLmNhbGwoc2VsZiwgaSkpIH0pLmdldCgpIDpcbiAgICAgICAgdGhpcy4kc3RlcHMubWFwKGZ1bmN0aW9uKGkpeyByZXR1cm4gaXRlbSgrK2kpOyB9KS5nZXQoKTtcblxuICAgICAgdGhpcy4kbmF2SXRlbXMgPSAkKGl0ZW1zLmpvaW4oJycpKTtcblxuICAgICAgdGhpcy4kbmF2LmFwcGVuZCgkKCc8dWwvPicpLmFwcGVuZCh0aGlzLiRuYXZJdGVtcykpO1xuICAgIH0sXG5cbiAgICBfZ2V0Q3VySWR4OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLiRzdGVwcy5pbmRleCh0aGlzLiRzdGVwcy5maWx0ZXIoJzp2aXNpYmxlJykpO1xuICAgIH0sXG5cbiAgICBnbzogZnVuY3Rpb24oaWR4KSB7XG5cbiAgICAgIHZhciBhY3RpdmUgPSB0aGlzLm9wdHMuYWN0aXZlQ2xhc3MsXG4gICAgICAgICAgZmFkZVNwZWVkID0gdGhpcy5vcHRzLmZhZGVTcGVlZDtcblxuICAgICAgaWYgKHR5cGVvZiBpZHggPT0gJ2Z1bmN0aW9uJykgaWR4ID0gaWR4LmNhbGwodGhpcywgdGhpcy5fZ2V0Q3VySWR4KCkpO1xuXG4gICAgICBpZiAoaWR4ID49IHRoaXMuJHN0ZXBzLmxlbmd0aCkgaWR4ID0gMDtcbiAgICAgIGlmIChpZHggPCAwKSBpZHggPSB0aGlzLiRzdGVwcy5sZW5ndGgtMTtcblxuICAgICAgaWYgKHRoaXMub3B0cy5iZWZvcmUpIHRoaXMub3B0cy5iZWZvcmUuY2FsbCh0aGlzLCBpZHgpO1xuXG4gICAgICB0aGlzLiRuYXZJdGVtcy5yZW1vdmVDbGFzcyhhY3RpdmUpLmVxKGlkeCkuYWRkQ2xhc3MoYWN0aXZlKTtcbiAgICAgIHRoaXMuJHN0ZXBzLmZhZGVPdXQoZmFkZVNwZWVkKS5lcShpZHgpLmZhZGVJbihmYWRlU3BlZWQpO1xuXG4gICAgICBpZiAodGhpcy5vcHRzLmFmdGVyKSB0aGlzLm9wdHMuYWZ0ZXIuY2FsbCh0aGlzLCBpZHgpO1xuICAgIH0sXG5cbiAgICBwcmV2OiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuZ28odGhpcy5fZ2V0Q3VySWR4KCkgLSAxKTtcbiAgICB9LFxuXG4gICAgbmV4dDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLmdvKHRoaXMuX2dldEN1cklkeCgpICsgMSk7XG4gICAgfSxcblxuICAgIGZpcnN0OiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuZ28oMCk7XG4gICAgfSxcblxuICAgIGxhc3Q6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5nbyh0aGlzLiRzdGVwcy5sZW5ndGgtMSk7XG4gICAgfVxuICB9O1xuXG4gIHJlcXVpcmUoJy4uLy4uL3BsdWdpbicpKHBsdWdpbik7XG5cbn0oalF1ZXJ5LCB3aW5kb3csIGRvY3VtZW50KSk7XG4iLCJyZXF1aXJlKCcuL2lkZWFsc3RlcHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cbiAgbmFtZTogJ3N0ZXBzJyxcblxuICBvcHRpb25zOiB7XG4gICAgc3RlcHNDb250YWluZXI6ICcuaWRlYWxzdGVwcy1jb250YWluZXInLFxuICAgIHN0ZXBzT3B0aW9uczoge31cbiAgfSxcblxuICBtZXRob2RzOiB7XG5cbiAgICAvLyBAZXh0ZW5kXG4gICAgX2luaXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5fYnVpbGRTdGVwcygpO1xuICAgIH0sXG5cbiAgICAvLyBAZXh0ZW5kXG4gICAgX3ZhbGlkYXRlOiBmdW5jdGlvbigpIHtcblxuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgICB0aGlzLl91cGRhdGVTdGVwcygpO1xuXG4gICAgICBpZiAoJC5pZGVhbGZvcm1zLmhhc0V4dGVuc2lvbignaWRlYWxBamF4JykpIHtcbiAgICAgICAgJC5lYWNoKCQuaWRlYWxmb3Jtcy5fcmVxdWVzdHMsIGZ1bmN0aW9uKGtleSwgcmVxdWVzdCkge1xuICAgICAgICAgIHJlcXVlc3QuZG9uZShmdW5jdGlvbigpeyBzZWxmLl91cGRhdGVTdGVwcygpIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgLy8gQGV4dGVuZFxuICAgIGZvY3VzRmlyc3RJbnZhbGlkOiBmdW5jdGlvbihmaXJzdEludmFsaWQpIHtcblxuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgICB0aGlzLiRzdGVwc0NvbnRhaW5lci5pZGVhbHN0ZXBzKCdnbycsIGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kc3RlcHMuZmlsdGVyKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJldHVybiAkKHRoaXMpLmZpbmQoZmlyc3RJbnZhbGlkKS5sZW5ndGg7XG4gICAgICAgIH0pLmluZGV4KCk7XG4gICAgICB9KTtcbiAgICB9LFxuXG4gICAgX2J1aWxkU3RlcHM6IGZ1bmN0aW9uKCkge1xuXG4gICAgICB2YXIgc2VsZiA9IHRoaXMsIG9wdGlvbnNcbiAgICAgICAgLCBoYXNSdWxlcyA9ICEgJC5pc0VtcHR5T2JqZWN0KHRoaXMub3B0cy5ydWxlcylcbiAgICAgICAgLCBjb3VudGVyID0gaGFzUnVsZXNcbiAgICAgICAgICA/ICc8c3BhbiBjbGFzcz1cImNvdW50ZXJcIi8+J1xuICAgICAgICAgIDogJzxzcGFuIGNsYXNzPVwiY291bnRlciB6ZXJvXCI+MDwvc3Bhbj4nO1xuXG4gICAgICBvcHRpb25zID0gJC5leHRlbmQoe30sIHtcbiAgICAgICAgYnVpbGROYXZJdGVtczogZnVuY3Rpb24oaSl7IHJldHVybiAnU3RlcCAnKyAoaSsxKSArIGNvdW50ZXIgfVxuICAgICAgfSwgdGhpcy5vcHRzLnN0ZXBzT3B0aW9ucyk7XG5cbiAgICAgIHRoaXMuJHN0ZXBzQ29udGFpbmVyID0gdGhpcy4kZm9ybS5jbG9zZXN0KHRoaXMub3B0cy5zdGVwc0NvbnRhaW5lcikuaWRlYWxzdGVwcyhvcHRpb25zKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZVN0ZXBzOiBmdW5jdGlvbigpIHtcblxuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgICB0aGlzLiRzdGVwc0NvbnRhaW5lci5pZGVhbHN0ZXBzKCdfaW5qZWN0JywgZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgdmFyIGlkZWFsc3RlcHMgPSB0aGlzO1xuXG4gICAgICAgIHRoaXMuJG5hdkl0ZW1zLmVhY2goZnVuY3Rpb24oaSkge1xuICAgICAgICAgIHZhciBpbnZhbGlkID0gaWRlYWxzdGVwcy4kc3RlcHMuZXEoaSkuZmluZChzZWxmLmdldEludmFsaWQoKSkubGVuZ3RoO1xuICAgICAgICAgICQodGhpcykuZmluZCgnc3BhbicpLnRleHQoaW52YWxpZCkudG9nZ2xlQ2xhc3MoJ3plcm8nLCAhIGludmFsaWQpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICAvLyBAZXh0ZW5kXG4gICAgYWRkUnVsZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5maXJzdFN0ZXAoKTtcbiAgICB9LFxuXG4gICAgLy8gQGV4dGVuZFxuICAgIHRvZ2dsZUZpZWxkczogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLl91cGRhdGVTdGVwcygpO1xuICAgIH0sXG5cbiAgICAvLyBAZXh0ZW5kXG4gICAgcmVtb3ZlRmllbGRzOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVN0ZXBzKCk7XG4gICAgfSxcblxuICAgIGdvVG9TdGVwOiBmdW5jdGlvbihpZHgpIHtcbiAgICAgIHRoaXMuJHN0ZXBzQ29udGFpbmVyLmlkZWFsc3RlcHMoJ2dvJywgaWR4KTtcbiAgICB9LFxuXG4gICAgcHJldlN0ZXA6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy4kc3RlcHNDb250YWluZXIuaWRlYWxzdGVwcygncHJldicpO1xuICAgIH0sXG5cbiAgICBuZXh0U3RlcDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLiRzdGVwc0NvbnRhaW5lci5pZGVhbHN0ZXBzKCduZXh0Jyk7XG4gICAgfSxcblxuICAgIGZpcnN0U3RlcDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLiRzdGVwc0NvbnRhaW5lci5pZGVhbHN0ZXBzKCdmaXJzdCcpO1xuICAgIH0sXG5cbiAgICBsYXN0U3RlcDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLiRzdGVwc0NvbnRhaW5lci5pZGVhbHN0ZXBzKCdsYXN0Jyk7XG4gICAgfVxuICB9XG5cbn07XG4iLCIvKiFcbiAqIGpRdWVyeSBJZGVhbCBGb3Jtc1xuICogQGF1dGhvcjogQ2VkcmljIFJ1aXpcbiAqIEB2ZXJzaW9uOiAzLjBcbiAqIEBsaWNlbnNlIEdQTCBvciBNSVRcbiAqL1xuKGZ1bmN0aW9uKCQsIHdpbiwgZG9jLCB1bmRlZmluZWQpIHtcblxuICB2YXIgcGx1Z2luID0ge307XG5cbiAgcGx1Z2luLm5hbWUgPSAnaWRlYWxmb3Jtcyc7XG5cbiAgcGx1Z2luLmRlZmF1bHRzID0ge1xuICAgIGZpZWxkOiAnLmZpZWxkJyxcbiAgICBlcnJvcjogJy5lcnJvcicsXG4gICAgaWNvbkh0bWw6ICc8aS8+JyxcbiAgICBpY29uQ2xhc3M6ICdpY29uJyxcbiAgICBpbnZhbGlkQ2xhc3M6ICdpbnZhbGlkJyxcbiAgICB2YWxpZENsYXNzOiAndmFsaWQnLFxuICAgIHNpbGVudExvYWQ6IHRydWUsXG4gICAgb25WYWxpZGF0ZTogJC5ub29wLFxuICAgIG9uU3VibWl0OiAkLm5vb3BcbiAgfTtcblxuICBwbHVnaW4uZ2xvYmFsID0ge1xuXG4gICAgX2Zvcm1hdDogZnVuY3Rpb24oc3RyKSB7XG4gICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgIHJldHVybiBzdHIucmVwbGFjZSgvXFx7KFxcZClcXH0vZywgZnVuY3Rpb24oXywgbWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIGFyZ3NbK21hdGNoXSB8fCAnJztcbiAgICAgIH0pLnJlcGxhY2UoL1xce1xcKihbXip9XSopXFx9L2csIGZ1bmN0aW9uKF8sIHNlcCkge1xuICAgICAgICByZXR1cm4gYXJncy5qb2luKHNlcCB8fCAnLCAnKTtcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBfZ2V0S2V5OiBmdW5jdGlvbihrZXksIG9iaikge1xuICAgICAgcmV0dXJuIGtleS5zcGxpdCgnLicpLnJlZHVjZShmdW5jdGlvbihhLGIpIHtcbiAgICAgICAgcmV0dXJuIGEgJiYgYVtiXTtcbiAgICAgIH0sIG9iaik7XG4gICAgfSxcblxuICAgIHJ1bGVTZXBhcmF0b3I6ICcgJyxcbiAgICBhcmdTZXBhcmF0b3I6ICc6JyxcblxuICAgIHJ1bGVzOiByZXF1aXJlKCcuL3J1bGVzJyksXG4gICAgZXJyb3JzOiByZXF1aXJlKCcuL2Vycm9ycycpLFxuXG4gICAgZXh0ZW5zaW9uczogW1xuICAgICAgcmVxdWlyZSgnLi9leHRlbnNpb25zL2R5bmFtaWMtZmllbGRzL2R5bmFtaWMtZmllbGRzLmV4dCcpLFxuICAgICAgcmVxdWlyZSgnLi9leHRlbnNpb25zL2FqYXgvYWpheC5leHQnKSxcbiAgICAgIHJlcXVpcmUoJy4vZXh0ZW5zaW9ucy9zdGVwcy9zdGVwcy5leHQnKSxcbiAgICAgIHJlcXVpcmUoJy4vZXh0ZW5zaW9ucy9jdXN0b20taW5wdXRzL2N1c3RvbS1pbnB1dHMuZXh0JyksXG4gICAgICByZXF1aXJlKCcuL2V4dGVuc2lvbnMvZGF0ZXBpY2tlci9kYXRlcGlja2VyLmV4dCcpXG4gICAgXVxuICB9O1xuXG4gIHBsdWdpbi5tZXRob2RzID0gJC5leHRlbmQoe30sIHJlcXVpcmUoJy4vcHJpdmF0ZScpLCByZXF1aXJlKCcuL3B1YmxpYycpKTtcblxuICByZXF1aXJlKCcuL3BsdWdpbicpKHBsdWdpbik7XG5cbn0oalF1ZXJ5LCB3aW5kb3csIGRvY3VtZW50KSk7XG4iLCIvKipcbiAqIFBsdWdpbiBib2lsZXJwbGF0ZVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbigpIHtcblxuICB2YXIgQVAgPSBBcnJheS5wcm90b3R5cGU7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKHBsdWdpbikge1xuXG4gICAgJC5leHRlbmQoe1xuICAgICAgbmFtZTogJ3BsdWdpbicsXG4gICAgICBkZWZhdWx0czoge30sXG4gICAgICBtZXRob2RzOiB7fSxcbiAgICAgIGdsb2JhbDoge30sXG4gICAgfSwgcGx1Z2luKTtcblxuICAgICRbcGx1Z2luLm5hbWVdID0gJC5leHRlbmQoe1xuXG4gICAgICBhZGRFeHRlbnNpb246IGZ1bmN0aW9uKGV4dGVuc2lvbikge1xuICAgICAgICBwbHVnaW4uZ2xvYmFsLmV4dGVuc2lvbnMucHVzaChleHRlbnNpb24pO1xuICAgICAgfSxcblxuICAgICAgaGFzRXh0ZW5zaW9uOiBmdW5jdGlvbihleHRlbnNpb24pIHtcbiAgICAgICAgcmV0dXJuIHBsdWdpbi5nbG9iYWwuZXh0ZW5zaW9ucy5maWx0ZXIoZnVuY3Rpb24oZXh0KSB7XG4gICAgICAgICAgcmV0dXJuIGV4dC5uYW1lID09IGV4dGVuc2lvbjtcbiAgICAgICAgfSkubGVuZ3RoO1xuICAgICAgfVxuICAgIH0sIHBsdWdpbi5nbG9iYWwpO1xuXG4gICAgZnVuY3Rpb24gUGx1Z2luKGVsZW1lbnQsIG9wdGlvbnMpIHtcblxuICAgICAgdGhpcy5vcHRzID0gJC5leHRlbmQoe30sIHBsdWdpbi5kZWZhdWx0cywgb3B0aW9ucyk7XG4gICAgICB0aGlzLmVsID0gZWxlbWVudDtcblxuICAgICAgdGhpcy5fbmFtZSA9IHBsdWdpbi5uYW1lO1xuXG4gICAgICB0aGlzLl9pbml0KCk7XG4gICAgfVxuXG4gICAgUGx1Z2luLl9leHRlbmRlZCA9IHt9O1xuXG4gICAgUGx1Z2luLnByb3RvdHlwZS5fZXh0ZW5kID0gZnVuY3Rpb24oZXh0ZW5zaW9ucykge1xuXG4gICAgICB2YXIgc2VsZiA9IHRoaXNcbiAgICAgICAgLCBkaXNhYmxlZCA9IHNlbGYub3B0cy5kaXNhYmxlZEV4dGVuc2lvbnMgfHwgJ25vbmUnO1xuXG4gICAgICAkLmVhY2goZXh0ZW5zaW9ucywgZnVuY3Rpb24oaSwgZXh0ZW5zaW9uKSB7XG5cbiAgICAgICAgJC5leHRlbmQoc2VsZi5vcHRzLCAkLmV4dGVuZCh0cnVlLCBleHRlbnNpb24ub3B0aW9ucywgc2VsZi5vcHRzKSk7XG5cbiAgICAgICAgJC5lYWNoKGV4dGVuc2lvbi5tZXRob2RzLCBmdW5jdGlvbihtZXRob2QsIGZuKSB7XG5cbiAgICAgICAgICBpZiAoZGlzYWJsZWQuaW5kZXhPZihleHRlbnNpb24ubmFtZSkgPiAtMSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChQbHVnaW4ucHJvdG90eXBlW21ldGhvZF0pIHtcbiAgICAgICAgICAgIFBsdWdpbi5fZXh0ZW5kZWRbbWV0aG9kXSA9IFBsdWdpbi5fZXh0ZW5kZWRbbWV0aG9kXSB8fCBbXTtcbiAgICAgICAgICAgIFBsdWdpbi5fZXh0ZW5kZWRbbWV0aG9kXS5wdXNoKHsgbmFtZTogZXh0ZW5zaW9uLm5hbWUsIGZuOiBmbiB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgUGx1Z2luLnByb3RvdHlwZVttZXRob2RdID0gZm47XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIFBsdWdpbi5wcm90b3R5cGUuX2luamVjdCA9IGZ1bmN0aW9uKG1ldGhvZCkge1xuXG4gICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcblxuICAgICAgaWYgKHR5cGVvZiBtZXRob2QgPT0gJ2Z1bmN0aW9uJykgcmV0dXJuIG1ldGhvZC5jYWxsKHRoaXMpO1xuXG4gICAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICAgIGlmIChQbHVnaW4uX2V4dGVuZGVkW21ldGhvZF0pIHtcbiAgICAgICAgJC5lYWNoKFBsdWdpbi5fZXh0ZW5kZWRbbWV0aG9kXSwgZnVuY3Rpb24oaSwgcGx1Z2luKSB7XG4gICAgICAgICAgcGx1Z2luLmZuLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgUGx1Z2luLnByb3RvdHlwZS5faW5pdCA9ICQubm9vcDtcblxuICAgIFBsdWdpbi5wcm90b3R5cGVbcGx1Z2luLm5hbWVdID0gZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgICBpZiAoIW1ldGhvZCkgcmV0dXJuIHRoaXM7XG4gICAgICB0cnkgeyByZXR1cm4gdGhpc1ttZXRob2RdLmFwcGx5KHRoaXMsIEFQLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7IH1cbiAgICAgIGNhdGNoKGUpIHt9XG4gICAgfTtcblxuICAgICQuZXh0ZW5kKFBsdWdpbi5wcm90b3R5cGUsIHBsdWdpbi5tZXRob2RzKTtcblxuICAgICQuZm5bcGx1Z2luLm5hbWVdID0gZnVuY3Rpb24oKSB7XG5cbiAgICAgIHZhciBhcmdzID0gQVAuc2xpY2UuY2FsbChhcmd1bWVudHMpXG4gICAgICAgICwgbWV0aG9kQXJyYXkgPSB0eXBlb2YgYXJnc1swXSA9PSAnc3RyaW5nJyAmJiBhcmdzWzBdLnNwbGl0KCc6JylcbiAgICAgICAgLCBtZXRob2QgPSBtZXRob2RBcnJheVttZXRob2RBcnJheS5sZW5ndGggPiAxID8gMSA6IDBdXG4gICAgICAgICwgcHJlZml4ID0gbWV0aG9kQXJyYXkubGVuZ3RoID4gMSAmJiBtZXRob2RBcnJheVswXVxuICAgICAgICAsIG9wdHMgPSB0eXBlb2YgYXJnc1swXSA9PSAnb2JqZWN0JyAmJiBhcmdzWzBdXG4gICAgICAgICwgcGFyYW1zID0gYXJncy5zbGljZSgxKVxuICAgICAgICAsIHJldDtcblxuICAgICAgaWYgKHByZWZpeCkge1xuICAgICAgICBtZXRob2QgPSBwcmVmaXggKyBtZXRob2Quc3Vic3RyKDAsMSkudG9VcHBlckNhc2UoKSArIG1ldGhvZC5zdWJzdHIoMSxtZXRob2QubGVuZ3RoLTEpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmVhY2goZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgdmFyIGluc3RhbmNlID0gJC5kYXRhKHRoaXMsIHBsdWdpbi5uYW1lKTtcblxuICAgICAgICAvLyBNZXRob2RcbiAgICAgICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgICAgcmV0dXJuIHJldCA9IGluc3RhbmNlW3BsdWdpbi5uYW1lXS5hcHBseShpbnN0YW5jZSwgW21ldGhvZF0uY29uY2F0KHBhcmFtcykpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSW5pdFxuICAgICAgICByZXR1cm4gJC5kYXRhKHRoaXMsIHBsdWdpbi5uYW1lLCBuZXcgUGx1Z2luKHRoaXMsIG9wdHMpKTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gcHJlZml4ID8gcmV0IDogdGhpcztcbiAgICB9O1xuICB9O1xuXG59KCkpO1xuIiwiLyoqXG4gKiBQcml2YXRlIG1ldGhvZHNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSB7XG5cbiAgX2luaXQ6IGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdGhpcy5fZXh0ZW5kKCQuaWRlYWxmb3Jtcy5leHRlbnNpb25zKTtcblxuICAgIHRoaXMuJGZvcm0gPSAkKHRoaXMuZWwpO1xuICAgIHRoaXMuJGZpZWxkcyA9ICQoKTtcbiAgICB0aGlzLiRpbnB1dHMgPSAkKCk7XG5cbiAgICB0aGlzLiRmb3JtLnN1Ym1pdChmdW5jdGlvbihlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBzZWxmLmZvY3VzRmlyc3RJbnZhbGlkKCk7XG4gICAgICBzZWxmLm9wdHMub25TdWJtaXQuY2FsbCh0aGlzLCBzZWxmLmdldEludmFsaWQoKS5sZW5ndGgsIGUpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5faW5qZWN0KCdfaW5pdCcpO1xuXG4gICAgdGhpcy5hZGRSdWxlcyh0aGlzLm9wdHMucnVsZXMgfHwge30pO1xuXG4gICAgaWYgKCEgdGhpcy5vcHRzLnNpbGVudExvYWQpIHRoaXMuZm9jdXNGaXJzdEludmFsaWQoKTtcbiAgfSxcblxuICBfYnVpbGRGaWVsZDogZnVuY3Rpb24oaW5wdXQpIHtcblxuICAgIHZhciBzZWxmID0gdGhpc1xuICAgICAgLCAkZmllbGQgPSB0aGlzLl9nZXRGaWVsZChpbnB1dClcbiAgICAgICwgJGljb247XG5cbiAgICAkaWNvbiA9ICQodGhpcy5vcHRzLmljb25IdG1sLCB7XG4gICAgICBjbGFzczogdGhpcy5vcHRzLmljb25DbGFzcyxcbiAgICAgIGNsaWNrOiBmdW5jdGlvbigpeyAkKGlucHV0KS5mb2N1cygpIH1cbiAgICB9KTtcblxuICAgIGlmICghIHRoaXMuJGZpZWxkcy5maWx0ZXIoJGZpZWxkKS5sZW5ndGgpIHtcbiAgICAgIHRoaXMuJGZpZWxkcyA9IHRoaXMuJGZpZWxkcy5hZGQoJGZpZWxkKTtcbiAgICAgIGlmICh0aGlzLm9wdHMuaWNvbkh0bWwpICRmaWVsZC5hcHBlbmQoJGljb24pO1xuICAgICAgJGZpZWxkLmFkZENsYXNzKCdpZGVhbGZvcm1zLWZpZWxkIGlkZWFsZm9ybXMtZmllbGQtJysgaW5wdXQudHlwZSk7XG4gICAgfVxuXG4gICAgdGhpcy5fYWRkRXZlbnRzKGlucHV0KTtcblxuICAgIHRoaXMuX2luamVjdCgnX2J1aWxkRmllbGQnLCBpbnB1dCk7XG4gIH0sXG5cbiAgX2FkZEV2ZW50czogZnVuY3Rpb24oaW5wdXQpIHtcblxuICAgIHZhciBzZWxmID0gdGhpc1xuICAgICAgLCAkZmllbGQgPSB0aGlzLl9nZXRGaWVsZChpbnB1dCk7XG5cbiAgICAkKGlucHV0KVxuICAgICAgLm9uKCdjaGFuZ2Uga2V5dXAnLCBmdW5jdGlvbihlKSB7XG5cbiAgICAgICAgdmFyIG9sZFZhbHVlID0gJGZpZWxkLmRhdGEoJ2lkZWFsZm9ybXMtdmFsdWUnKTtcblxuICAgICAgICBpZiAoZS53aGljaCA9PSA5IHx8IGUud2hpY2ggPT0gMTYpIHJldHVybjtcbiAgICAgICAgaWYgKCEgJCh0aGlzKS5pcygnOmNoZWNrYm94LCA6cmFkaW8nKSAmJiBvbGRWYWx1ZSA9PSB0aGlzLnZhbHVlKSByZXR1cm47XG5cbiAgICAgICAgJGZpZWxkLmRhdGEoJ2lkZWFsZm9ybXMtdmFsdWUnLCB0aGlzLnZhbHVlKTtcblxuICAgICAgICBzZWxmLl92YWxpZGF0ZSh0aGlzLCB0cnVlLCB0cnVlKTtcbiAgICAgIH0pXG4gICAgICAuZm9jdXMoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgaWYgKHNlbGYuaXNWYWxpZCh0aGlzLm5hbWUpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgaWYgKHNlbGYuX2lzUmVxdWlyZWQodGhpcykgfHwgdGhpcy52YWx1ZSkge1xuICAgICAgICAgICRmaWVsZC5maW5kKHNlbGYub3B0cy5lcnJvcikuc2hvdygpO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLmJsdXIoZnVuY3Rpb24oKSB7XG4gICAgICAgICRmaWVsZC5maW5kKHNlbGYub3B0cy5lcnJvcikuaGlkZSgpO1xuICAgICAgfSk7XG4gIH0sXG5cbiAgX2lzUmVxdWlyZWQ6IGZ1bmN0aW9uKGlucHV0KSB7XG4gICAgLy8gV2UgYXNzdW1lIG5vbi10ZXh0IGlucHV0cyB3aXRoIHJ1bGVzIGFyZSByZXF1aXJlZFxuICAgIGlmICgkKGlucHV0KS5pcygnOmNoZWNrYm94LCA6cmFkaW8sIHNlbGVjdCcpKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gdGhpcy5vcHRzLnJ1bGVzW2lucHV0Lm5hbWVdLmluZGV4T2YoJ3JlcXVpcmVkJykgPiAtMTtcbiAgfSxcblxuICBfZ2V0UmVsYXRlZDogZnVuY3Rpb24oaW5wdXQpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0RmllbGQoaW5wdXQpLmZpbmQoJ1tuYW1lPVwiJysgaW5wdXQubmFtZSArJ1wiXScpO1xuICB9LFxuXG4gIF9nZXRGaWVsZDogZnVuY3Rpb24oaW5wdXQpIHtcbiAgICByZXR1cm4gJChpbnB1dCkuY2xvc2VzdCh0aGlzLm9wdHMuZmllbGQpO1xuICB9LFxuXG4gIF9nZXRGaXJzdEludmFsaWQ6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmdldEludmFsaWQoKS5maXJzdCgpLmZpbmQoJ2lucHV0OmZpcnN0LCB0ZXh0YXJlYSwgc2VsZWN0Jyk7XG4gIH0sXG5cbiAgX2hhbmRsZUVycm9yOiBmdW5jdGlvbihpbnB1dCwgZXJyb3IsIHZhbGlkKSB7XG4gICAgdmFsaWQgPSB2YWxpZCB8fCB0aGlzLmlzVmFsaWQoaW5wdXQubmFtZSk7XG4gICAgdmFyICRlcnJvciA9IHRoaXMuX2dldEZpZWxkKGlucHV0KS5maW5kKHRoaXMub3B0cy5lcnJvcik7XG4gICAgdGhpcy4kZm9ybS5maW5kKHRoaXMub3B0cy5lcnJvcikuaGlkZSgpO1xuICAgIGlmIChlcnJvcikgJGVycm9yLnRleHQoZXJyb3IpO1xuICAgICRlcnJvci50b2dnbGUoIXZhbGlkKTtcbiAgfSxcblxuICBfaGFuZGxlU3R5bGU6IGZ1bmN0aW9uKGlucHV0LCB2YWxpZCkge1xuICAgIHZhbGlkID0gdmFsaWQgfHwgdGhpcy5pc1ZhbGlkKGlucHV0Lm5hbWUpO1xuICAgIHRoaXMuX2dldEZpZWxkKGlucHV0KVxuICAgICAgLnJlbW92ZUNsYXNzKHRoaXMub3B0cy52YWxpZENsYXNzICsnICcrIHRoaXMub3B0cy5pbnZhbGlkQ2xhc3MpXG4gICAgICAuYWRkQ2xhc3ModmFsaWQgPyB0aGlzLm9wdHMudmFsaWRDbGFzcyA6IHRoaXMub3B0cy5pbnZhbGlkQ2xhc3MpXG4gICAgICAuZmluZCgnLicrIHRoaXMub3B0cy5pY29uQ2xhc3MpLnNob3coKTtcbiAgfSxcblxuICBfZnJlc2g6IGZ1bmN0aW9uKGlucHV0KSB7XG4gICAgdGhpcy5fZ2V0RmllbGQoaW5wdXQpXG4gICAgICAucmVtb3ZlQ2xhc3ModGhpcy5vcHRzLnZhbGlkQ2xhc3MgKycgJysgdGhpcy5vcHRzLmludmFsaWRDbGFzcylcbiAgICAgIC5maW5kKHRoaXMub3B0cy5lcnJvcikuaGlkZSgpXG4gICAgICAuZW5kKClcbiAgICAgIC5maW5kKCcuJysgdGhpcy5vcHRzLmljb25DbGFzcykudG9nZ2xlKHRoaXMuX2lzUmVxdWlyZWQoaW5wdXQpKTtcbiAgfSxcblxuICBfdmFsaWRhdGU6IGZ1bmN0aW9uKGlucHV0LCBoYW5kbGVFcnJvciwgaGFuZGxlU3R5bGUpIHtcblxuICAgIHZhciBzZWxmID0gdGhpc1xuICAgICAgLCAkZmllbGQgPSB0aGlzLl9nZXRGaWVsZChpbnB1dClcbiAgICAgICwgdXNlclJ1bGVzID0gdGhpcy5vcHRzLnJ1bGVzW2lucHV0Lm5hbWVdLnNwbGl0KCQuaWRlYWxmb3Jtcy5ydWxlU2VwYXJhdG9yKVxuICAgICAgLCB2YWxpZCA9IHRydWVcbiAgICAgICwgcnVsZTtcblxuICAgIC8vIE5vbi1yZXF1aXJlZCBpbnB1dCB3aXRoIGVtcHR5IHZhbHVlIG11c3QgcGFzcyB2YWxpZGF0aW9uXG4gICAgaWYgKCEgaW5wdXQudmFsdWUgJiYgISB0aGlzLl9pc1JlcXVpcmVkKGlucHV0KSkge1xuICAgICAgJGZpZWxkLnJlbW92ZURhdGEoJ2lkZWFsZm9ybXMtdmFsaWQnKTtcbiAgICAgIHRoaXMuX2ZyZXNoKGlucHV0KTtcblxuICAgIC8vIFJlcXVpcmVkIGlucHV0c1xuICAgIH0gZWxzZSB7XG5cbiAgICAgICQuZWFjaCh1c2VyUnVsZXMsIGZ1bmN0aW9uKGksIHVzZXJSdWxlKSB7XG5cbiAgICAgICAgdXNlclJ1bGUgPSB1c2VyUnVsZS5zcGxpdCgkLmlkZWFsZm9ybXMuYXJnU2VwYXJhdG9yKTtcblxuICAgICAgICBydWxlID0gdXNlclJ1bGVbMF07XG5cbiAgICAgICAgdmFyIHRoZVJ1bGUgPSAkLmlkZWFsZm9ybXMucnVsZXNbcnVsZV1cbiAgICAgICAgICAsIGFyZ3MgPSB1c2VyUnVsZS5zbGljZSgxKVxuICAgICAgICAgICwgZXJyb3I7XG5cbiAgICAgICAgZXJyb3IgPSAkLmlkZWFsZm9ybXMuX2Zvcm1hdC5hcHBseShudWxsLCBbXG4gICAgICAgICAgJC5pZGVhbGZvcm1zLl9nZXRLZXkoJ2Vycm9ycy4nKyBpbnB1dC5uYW1lICsnLicrIHJ1bGUsIHNlbGYub3B0cykgfHxcbiAgICAgICAgICAkLmlkZWFsZm9ybXMuZXJyb3JzW3J1bGVdXG4gICAgICAgIF0uY29uY2F0KGFyZ3MpKTtcblxuICAgICAgICB2YWxpZCA9IHR5cGVvZiB0aGVSdWxlID09ICdmdW5jdGlvbidcbiAgICAgICAgICA/IHRoZVJ1bGUuYXBwbHkoc2VsZiwgW2lucHV0LCBpbnB1dC52YWx1ZV0uY29uY2F0KGFyZ3MpKVxuICAgICAgICAgIDogdGhlUnVsZS50ZXN0KGlucHV0LnZhbHVlKTtcblxuICAgICAgICAkZmllbGQuZGF0YSgnaWRlYWxmb3Jtcy12YWxpZCcsIHZhbGlkKTtcblxuICAgICAgICBpZiAoaGFuZGxlRXJyb3IpIHNlbGYuX2hhbmRsZUVycm9yKGlucHV0LCBlcnJvciwgdmFsaWQpO1xuICAgICAgICBpZiAoaGFuZGxlU3R5bGUpIHNlbGYuX2hhbmRsZVN0eWxlKGlucHV0LCB2YWxpZCk7XG5cbiAgICAgICAgc2VsZi5vcHRzLm9uVmFsaWRhdGUuY2FsbChzZWxmLCBpbnB1dCwgcnVsZSwgdmFsaWQpO1xuXG4gICAgICAgIHJldHVybiB2YWxpZDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuX2luamVjdCgnX3ZhbGlkYXRlJywgaW5wdXQsIHJ1bGUsIHZhbGlkKTtcblxuICAgIHJldHVybiB2YWxpZDtcbiAgfVxuXG59O1xuIiwiLyoqXG4gKiBQdWJsaWMgbWV0aG9kc1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuICBhZGRSdWxlczogZnVuY3Rpb24ocnVsZXMpIHtcblxuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHZhciAkaW5wdXRzID0gdGhpcy4kZm9ybS5maW5kKCQubWFwKHJ1bGVzLCBmdW5jdGlvbihfLCBuYW1lKSB7XG4gICAgICByZXR1cm4gJ1tuYW1lPVwiJysgbmFtZSArJ1wiXSc7XG4gICAgfSkuam9pbignLCcpKTtcblxuICAgICQuZXh0ZW5kKHRoaXMub3B0cy5ydWxlcywgcnVsZXMpO1xuXG4gICAgJGlucHV0cy5lYWNoKGZ1bmN0aW9uKCl7IHNlbGYuX2J1aWxkRmllbGQodGhpcykgfSk7XG5cbiAgICB0aGlzLiRpbnB1dHMgPSB0aGlzLiRpbnB1dHNcbiAgICAgIC5hZGQoJGlucHV0cylcbiAgICAgIC5lYWNoKGZ1bmN0aW9uKCl7IHNlbGYuX3ZhbGlkYXRlKHRoaXMsIHRydWUpIH0pO1xuXG4gICAgdGhpcy4kZmllbGRzLmZpbmQodGhpcy5vcHRzLmVycm9yKS5oaWRlKCk7XG5cbiAgICB0aGlzLl9pbmplY3QoJ2FkZFJ1bGVzJyk7XG4gIH0sXG5cbiAgZ2V0SW52YWxpZDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuJGZpZWxkcy5maWx0ZXIoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gJCh0aGlzKS5kYXRhKCdpZGVhbGZvcm1zLXZhbGlkJykgPT09IGZhbHNlO1xuICAgIH0pO1xuICB9LFxuXG4gIGZvY3VzRmlyc3RJbnZhbGlkOiBmdW5jdGlvbigpIHtcblxuICAgIHZhciBmaXJzdEludmFsaWQgPSB0aGlzLl9nZXRGaXJzdEludmFsaWQoKVswXTtcblxuICAgIGlmIChmaXJzdEludmFsaWQpIHtcbiAgICAgIHRoaXMuX2hhbmRsZUVycm9yKGZpcnN0SW52YWxpZCk7XG4gICAgICB0aGlzLl9oYW5kbGVTdHlsZShmaXJzdEludmFsaWQpO1xuICAgICAgdGhpcy5faW5qZWN0KCdmb2N1c0ZpcnN0SW52YWxpZCcsIGZpcnN0SW52YWxpZCk7XG4gICAgICBmaXJzdEludmFsaWQuZm9jdXMoKTtcbiAgICB9XG4gIH0sXG5cbiAgaXNWYWxpZDogZnVuY3Rpb24obmFtZSkge1xuICAgIGlmIChuYW1lKSByZXR1cm4gISB0aGlzLmdldEludmFsaWQoKS5maW5kKCdbbmFtZT1cIicrIG5hbWUgKydcIl0nKS5sZW5ndGg7XG4gICAgcmV0dXJuICEgdGhpcy5nZXRJbnZhbGlkKCkubGVuZ3RoO1xuICB9LFxuXG4gIHJlc2V0OiBmdW5jdGlvbihuYW1lKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXNcbiAgICAgICwgJGlucHV0cyA9IHRoaXMuJGlucHV0cztcblxuICAgIGlmIChuYW1lKSAkaW5wdXRzID0gJGlucHV0cy5maWx0ZXIoJ1tuYW1lPVwiJysgbmFtZSArJ1wiXScpO1xuXG4gICAgJGlucHV0cy5maWx0ZXIoJ2lucHV0Om5vdCg6Y2hlY2tib3gsIDpyYWRpbyknKS52YWwoJycpO1xuICAgICRpbnB1dHMuZmlsdGVyKCc6Y2hlY2tib3gsIDpyYWRpbycpLnByb3AoJ2NoZWNrZWQnLCBmYWxzZSk7XG4gICAgJGlucHV0cy5maWx0ZXIoJ3NlbGVjdCcpLmZpbmQoJ29wdGlvbicpLnByb3AoJ3NlbGVjdGVkJywgZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZWZhdWx0U2VsZWN0ZWQ7XG4gICAgfSk7XG5cbiAgICAkaW5wdXRzLmNoYW5nZSgpLmVhY2goZnVuY3Rpb24oKXsgc2VsZi5fcmVzZXRFcnJvckFuZFN0eWxlKHRoaXMpIH0pO1xuICB9XG5cbn07XG4iLCIvKipcbiAqIFJ1bGVzXG4gKi9cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gIHJlcXVpcmVkOiAvLisvLFxuICBkaWdpdHM6IC9eXFxkKyQvLFxuICBlbWFpbDogL15bXkBdK0BbXkBdK1xcLi57Miw2fSQvLFxuICB1c2VybmFtZTogL15bYS16XSg/PVtcXHcuXXszLDMxfSQpXFx3KlxcLj9cXHcqJC9pLFxuICBwYXNzOiAvKD89LipcXGQpKD89LipbYS16XSkoPz0uKltBLVpdKS57Nix9LyxcbiAgc3Ryb25ncGFzczogLyg/PV4uezgsfSQpKCg/PS4qXFxkKXwoPz0uKlxcVyspKSg/IVsuXFxuXSkoPz0uKltBLVpdKSg/PS4qW2Etel0pLiokLyxcbiAgcGhvbmU6IC9eWzItOV1cXGR7Mn0tXFxkezN9LVxcZHs0fSQvLFxuICB6aXA6IC9eXFxkezV9JHxeXFxkezV9LVxcZHs0fSQvLFxuICB1cmw6IC9eKD86KGZ0cHxodHRwfGh0dHBzKTpcXC9cXC8pPyg/OltcXHdcXC1dK1xcLikrW2Etel17Miw2fShbXFw6XFwvPyNdLiopPyQvaSxcblxuICBudW1iZXI6IGZ1bmN0aW9uKGlucHV0LCB2YWx1ZSkge1xuICAgIHJldHVybiAhaXNOYU4odmFsdWUpO1xuICB9LFxuXG4gIHJhbmdlOiBmdW5jdGlvbihpbnB1dCwgdmFsdWUsIG1peCwgbWF4KSB7XG4gICAgcmV0dXJuIE51bWJlcih2YWx1ZSkgPj0gbWluICYmIE51bWJlcih2YWx1ZSkgPD0gbWF4O1xuICB9LFxuXG4gIG1pbjogZnVuY3Rpb24oaW5wdXQsIHZhbHVlLCBtaW4pIHtcbiAgICByZXR1cm4gdmFsdWUubGVuZ3RoID49IG1pbjtcbiAgfSxcblxuICBtYXg6IGZ1bmN0aW9uKGlucHV0LCB2YWx1ZSwgbWF4KSB7XG4gICAgcmV0dXJuIHZhbHVlLmxlbmd0aCA8PSBtYXg7XG4gIH0sXG5cbiAgbWlub3B0aW9uOiBmdW5jdGlvbihpbnB1dCwgdmFsdWUsIG1pbikge1xuICAgIHJldHVybiB0aGlzLl9nZXRSZWxhdGVkKGlucHV0KS5maWx0ZXIoJzpjaGVja2VkJykubGVuZ3RoID49IG1pbjtcbiAgfSxcblxuICBtYXhvcHRpb246IGZ1bmN0aW9uKGlucHV0LCB2YWx1ZSwgbWF4KSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldFJlbGF0ZWQoaW5wdXQpLmZpbHRlcignOmNoZWNrZWQnKS5sZW5ndGggPD0gbWF4O1xuICB9LFxuXG4gIG1pbm1heDogZnVuY3Rpb24oaW5wdXQsIHZhbHVlLCBtaW4sIG1heCkge1xuICAgIHJldHVybiB2YWx1ZS5sZW5ndGggPj0gbWluICYmIHZhbHVlLmxlbmd0aCA8PSBtYXg7XG4gIH0sXG5cbiAgc2VsZWN0OiBmdW5jdGlvbihpbnB1dCwgdmFsdWUsIGRlZikge1xuICAgIHJldHVybiB2YWx1ZSAhPSBkZWY7XG4gIH0sXG5cbiAgZXh0ZW5zaW9uOiBmdW5jdGlvbihpbnB1dCkge1xuXG4gICAgdmFyIGV4dGVuc2lvbnMgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSlcbiAgICAgICwgdmFsaWQgPSBmYWxzZTtcblxuICAgICQuZWFjaChpbnB1dC5maWxlcyB8fCBbe25hbWU6IGlucHV0LnZhbHVlfV0sIGZ1bmN0aW9uKGksIGZpbGUpIHtcbiAgICAgIHZhbGlkID0gJC5pbkFycmF5KGZpbGUubmFtZS5tYXRjaCgvXFwuKC4rKSQvKVsxXSwgZXh0ZW5zaW9ucykgPiAtMTtcbiAgICB9KTtcblxuICAgIHJldHVybiB2YWxpZDtcbiAgfSxcblxuICBlcXVhbHRvOiBmdW5jdGlvbihpbnB1dCwgdmFsdWUsIHRhcmdldCkge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzXG4gICAgICAsICR0YXJnZXQgPSAkKCdbbmFtZT1cIicrIHRhcmdldCArJ1wiXScpO1xuXG4gICAgaWYgKHRoaXMuZ2V0SW52YWxpZCgpLmZpbmQoJHRhcmdldCkubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cbiAgICAkdGFyZ2V0Lm9mZigna2V5dXAuZXF1YWx0bycpLm9uKCdrZXl1cC5lcXVhbHRvJywgZnVuY3Rpb24oKSB7XG4gICAgICBzZWxmLl92YWxpZGF0ZShpbnB1dCwgZmFsc2UsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGlucHV0LnZhbHVlID09ICR0YXJnZXQudmFsKCk7XG4gIH0sXG5cbiAgZGF0ZTogZnVuY3Rpb24oaW5wdXQsIHZhbHVlLCBmb3JtYXQpIHtcblxuICAgIGZvcm1hdCA9IGZvcm1hdCB8fCAnbW0vZGQveXl5eSc7XG5cbiAgICB2YXIgZGVsaW1pdGVyID0gL1tebWR5XS8uZXhlYyhmb3JtYXQpWzBdXG4gICAgICAsIHRoZUZvcm1hdCA9IGZvcm1hdC5zcGxpdChkZWxpbWl0ZXIpXG4gICAgICAsIHRoZURhdGUgPSB2YWx1ZS5zcGxpdChkZWxpbWl0ZXIpO1xuXG4gICAgZnVuY3Rpb24gaXNEYXRlKGRhdGUsIGZvcm1hdCkge1xuXG4gICAgICB2YXIgbSwgZCwgeTtcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGZvcm1hdC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBpZiAoL20vLnRlc3QoZm9ybWF0W2ldKSkgbSA9IGRhdGVbaV07XG4gICAgICAgIGlmICgvZC8udGVzdChmb3JtYXRbaV0pKSBkID0gZGF0ZVtpXTtcbiAgICAgICAgaWYgKC95Ly50ZXN0KGZvcm1hdFtpXSkpIHkgPSBkYXRlW2ldO1xuICAgICAgfVxuXG4gICAgICBpZiAoIW0gfHwgIWQgfHwgIXkpIHJldHVybiBmYWxzZTtcblxuICAgICAgcmV0dXJuIG0gPiAwICYmIG0gPCAxMyAmJlxuICAgICAgICB5ICYmIHkubGVuZ3RoID09IDQgJiZcbiAgICAgICAgZCA+IDAgJiYgZCA8PSAobmV3IERhdGUoeSwgbSwgMCkpLmdldERhdGUoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaXNEYXRlKHRoZURhdGUsIHRoZUZvcm1hdCk7XG4gIH1cblxufTtcbiJdfQ== +; \ No newline at end of file diff --git a/js/out/jquery.idealforms.min.js b/js/out/jquery.idealforms.min.js new file mode 100644 index 0000000..c461bb6 --- /dev/null +++ b/js/out/jquery.idealforms.min.js @@ -0,0 +1,7 @@ +!function e(t,i,n){function s(o,r){if(!i[o]){if(!t[o]){var l="function"==typeof require&&require;if(!r&&l)return l(o,!0);if(a)return a(o,!0);throw new Error("Cannot find module '"+o+"'")}var d=i[o]={exports:{}};t[o][0].call(d.exports,function(e){var i=t[o][1][e];return s(i?i:e)},d,d.exports,e,t,i,n)}return i[o].exports}for(var a="function"==typeof require&&require,o=0;o")[0].multiple,n=/msie/i.test(navigator.userAgent),s={};s.name="idealfile",s.methods={_init:function(){var e=t(this.el).addClass("ideal-file"),s=t('
        '),a=t(''),o=t(''),r=t('');e.css({position:"absolute",left:"-9999px"}),s.append(a,n?r:o).insertAfter(e),e.attr("tabIndex",-1),o.attr("tabIndex",-1),o.click(function(){e.focus().click()}),e.change(function(){var t,n,s=[];if(i){t=e[0].files;for(var o=0,r=t.length;r>o;o++)s.push(t[o].name);n=s.join(", ")}else n=e.val().split("\\").pop();a.val(n).attr("title",n)}),a.on({blur:function(){e.trigger("blur")},keydown:function(i){if(13===i.which)n||e.trigger("click"),t(this).closest("form").one("keydown",function(e){13===e.which&&e.preventDefault()});else{if(8!==i.which&&46!==i.which)return 9===i.which?void 0:!1;n&&e.replaceWith(e=e.clone(!0)),e.val("").trigger("change"),a.val("")}}})}},e("../../plugin")(s)}(jQuery,window,document)},{"../../plugin":11}],5:[function(e){!function(t){var i={};i.name="idealradiocheck",i.methods={_init:function(){var e=t(this.el),i=t("");i.addClass("ideal-"+(e.is(":checkbox")?"check":"radio")),e.is(":checked")&&i.addClass("checked"),i.insertAfter(e),e.parent("label").addClass("ideal-radiocheck-label").attr("onclick",""),e.css({position:"absolute",left:"-9999px"}),e.on({change:function(){var e=t(this);e.is('input[type="radio"]')&&e.parent().siblings("label").find(".ideal-radio").removeClass("checked"),i.toggleClass("checked",e.is(":checked"))},focus:function(){i.addClass("focus")},blur:function(){i.removeClass("focus")},click:function(){t(this).trigger("focus")}})}},e("../../plugin")(i)}(jQuery,window,document)},{"../../plugin":11}],6:[function(e,t){t.exports={name:"datepicker",methods:{_init:function(){this._buildDatepicker()},_buildDatepicker:function(){var e=this.$form.find("input.datepicker");jQuery.ui&&($.datepicker._checkOffset=function(e,t){return t}),jQuery.ui&&e.length&&(e.each(function(){$(this).datepicker({beforeShow:function(e){$(e).addClass("open")},onChangeMonthYear:function(){var e=$(this),t=e.outerWidth();setTimeout(function(){e.datepicker("widget").css("width",t)},1)},onClose:function(){$(this).removeClass("open")}})}),e.on("focus keyup",function(){var e=$(this),t=e.outerWidth();e.datepicker("widget").css("width",t)}))}}}},{}],7:[function(e,t){function i(e,t){var i=/\{@([^}]+)\}(.+?)\{\/\1\}/g,n=/\{#([^}]+)\}/g,s=/\{([^}]+)\}/g;return e.replace(i,function(e,i,s){return $.map(t[i],function(e){return s.replace(n,function(t,i){return e[i]})}).join("")}).replace(s,function(e,i){return t[i]||""})}t.exports={name:"dynamicFields",options:{templates:{base:'
        {field}
        ',text:'',file:'',textarea:'',group:'

        {@list} {/list}

        ',select:' '}},methods:{addFields:function(e){var t=this;$.each(e,function(e,n){var s=n.type.split(":"),a={};n.name=e,n.type=s[0],s[1]&&(n.subtype=s[1]);var o=i(t.opts.templates.base,{label:n.label,field:i(t.opts.templates[n.type],n)});n.after||n.before?t.$form.find("[name="+(n.after||n.before)+"]").each(function(){t._getField(this)[n.after?"after":"before"](o)}):t.$form.find(t.opts.field).last().after(o),n.rules&&(a[e]=n.rules,t.addRules(a))}),this._inject("addFields")},removeFields:function(e){var t=this;$.each(e.split(" "),function(e,i){var n=t._getField($('[name="'+i+'"]'));t.$fields=t.$fields.filter(function(){return!$(this).is(n)}),n.remove()}),this._inject("removeFields")},toggleFields:function(e){var t=this;$.each(e.split(" "),function(e,i){var n=t._getField($('[name="'+i+'"]'));n.data("idealforms-valid",n.is(":visible")).toggle()}),this._inject("toggleFields")}}}},{}],8:[function(e){!function(t){var i={};i.name="idealsteps",i.defaults={nav:".idealsteps-nav",navItems:"li",buildNavItems:!0,wrap:".idealsteps-wrap",step:".idealsteps-step",activeClass:"idealsteps-step-active",before:null,after:null,fadeSpeed:0},i.methods={_init:function(){var e=this,i=this.opts.activeClass;this.$el=t(this.el),this.$nav=this.$el.find(this.opts.nav),this.$navItems=this.$nav.find(this.opts.navItems),this.$wrap=this.$el.find(this.opts.wrap),this.$steps=this.$wrap.find(this.opts.step),this.opts.buildNavItems&&this._buildNavItems(),this.$steps.hide().first().show(),this.$navItems.removeClass(i).first().addClass(i),this.$navItems.click(function(){e.go(e.$navItems.index(this))})},_buildNavItems:function(){var e,i=this,n="function"==typeof this.opts.buildNavItems,s=function(e){return'
      • '+e+"
      • "};e=n?this.$steps.map(function(e){return s(i.opts.buildNavItems.call(i,e))}).get():this.$steps.map(function(e){return s(++e)}).get(),this.$navItems=t(e.join("")),this.$nav.append(t("
          ").append(this.$navItems))},_getCurIdx:function(){return this.$steps.index(this.$steps.filter(":visible"))},go:function(e){var t=this.opts.activeClass,i=this.opts.fadeSpeed;"function"==typeof e&&(e=e.call(this,this._getCurIdx())),e>=this.$steps.length&&(e=0),0>e&&(e=this.$steps.length-1),this.opts.before&&this.opts.before.call(this,e),this.$navItems.removeClass(t).eq(e).addClass(t),this.$steps.fadeOut(i).eq(e).fadeIn(i),this.opts.after&&this.opts.after.call(this,e)},prev:function(){this.go(this._getCurIdx()-1)},next:function(){this.go(this._getCurIdx()+1)},first:function(){this.go(0)},last:function(){this.go(this.$steps.length-1)}},e("../../plugin")(i)}(jQuery,window,document)},{"../../plugin":11}],9:[function(e,t){e("./idealsteps"),t.exports={name:"steps",options:{stepsContainer:".idealsteps-container",stepsOptions:{}},methods:{_init:function(){this._buildSteps()},_validate:function(){var e=this;this._updateSteps(),$.idealforms.hasExtension("idealAjax")&&$.each($.idealforms._requests,function(t,i){i.done(function(){e._updateSteps()})})},focusFirstInvalid:function(e){this.$stepsContainer.idealsteps("go",function(){return this.$steps.filter(function(){return $(this).find(e).length}).index()})},_buildSteps:function(){var e,t=!$.isEmptyObject(this.opts.rules),i=t?'':'0';e=$.extend({},{buildNavItems:function(e){return"Step "+(e+1)+i}},this.opts.stepsOptions),this.$stepsContainer=this.$form.closest(this.opts.stepsContainer).idealsteps(e)},_updateSteps:function(){var e=this;this.$stepsContainer.idealsteps("_inject",function(){var t=this;this.$navItems.each(function(i){var n=t.$steps.eq(i).find(e.getInvalid()).length;$(this).find("span").text(n).toggleClass("zero",!n)})})},addRules:function(){this.firstStep()},toggleFields:function(){this._updateSteps()},removeFields:function(){this._updateSteps()},goToStep:function(e){this.$stepsContainer.idealsteps("go",e)},prevStep:function(){this.$stepsContainer.idealsteps("prev")},nextStep:function(){this.$stepsContainer.idealsteps("next")},firstStep:function(){this.$stepsContainer.idealsteps("first")},lastStep:function(){this.$stepsContainer.idealsteps("last")}}}},{"./idealsteps":8}],10:[function(e){/*! + * jQuery Ideal Forms + * @author: Cedric Ruiz + * @version: 3.0 + * @license GPL or MIT + */ +!function(t){var i={};i.name="idealforms",i.defaults={field:".field",error:".error",iconHtml:"",iconClass:"icon",invalidClass:"invalid",validClass:"valid",silentLoad:!0,onValidate:t.noop,onSubmit:t.noop},i.global={_format:function(e){var t=[].slice.call(arguments,1);return e.replace(/\{(\d)\}/g,function(e,i){return t[+i]||""}).replace(/\{\*([^*}]*)\}/g,function(e,i){return t.join(i||", ")})},_getKey:function(e,t){return e.split(".").reduce(function(e,t){return e&&e[t]},t)},ruleSeparator:" ",argSeparator:":",rules:e("./rules"),errors:e("./errors"),extensions:[e("./extensions/dynamic-fields/dynamic-fields.ext"),e("./extensions/ajax/ajax.ext"),e("./extensions/steps/steps.ext"),e("./extensions/custom-inputs/custom-inputs.ext"),e("./extensions/datepicker/datepicker.ext")]},i.methods=t.extend({},e("./private"),e("./public")),e("./plugin")(i)}(jQuery,window,document)},{"./errors":1,"./extensions/ajax/ajax.ext":2,"./extensions/custom-inputs/custom-inputs.ext":3,"./extensions/datepicker/datepicker.ext":6,"./extensions/dynamic-fields/dynamic-fields.ext":7,"./extensions/steps/steps.ext":9,"./plugin":11,"./private":12,"./public":13,"./rules":14}],11:[function(e,t){t.exports=function(){var e=Array.prototype;return function(t){function i(e,i){this.opts=$.extend({},t.defaults,i),this.el=e,this._name=t.name,this._init()}$.extend({name:"plugin",defaults:{},methods:{},global:{}},t),$[t.name]=$.extend({addExtension:function(e){t.global.extensions.push(e)},hasExtension:function(e){return t.global.extensions.filter(function(t){return t.name==e}).length}},t.global),i._extended={},i.prototype._extend=function(e){var t=this,n=t.opts.disabledExtensions||"none";$.each(e,function(e,s){$.extend(t.opts,$.extend(!0,s.options,t.opts)),$.each(s.methods,function(e,t){n.indexOf(s.name)>-1||(i.prototype[e]?(i._extended[e]=i._extended[e]||[],i._extended[e].push({name:s.name,fn:t})):i.prototype[e]=t)})})},i.prototype._inject=function(e){var t=[].slice.call(arguments,1);if("function"==typeof e)return e.call(this);var n=this;i._extended[e]&&$.each(i._extended[e],function(e,i){i.fn.apply(n,t)})},i.prototype._init=$.noop,i.prototype[t.name]=function(t){if(!t)return this;try{return this[t].apply(this,e.slice.call(arguments,1))}catch(i){}},$.extend(i.prototype,t.methods),$.fn[t.name]=function(){var n,s=e.slice.call(arguments),a="string"==typeof s[0]&&s[0].split(":"),o=a[a.length>1?1:0],r=a.length>1&&a[0],l="object"==typeof s[0]&&s[0],d=s.slice(1);return r&&(o=r+o.substr(0,1).toUpperCase()+o.substr(1,o.length-1)),this.each(function(){var e=$.data(this,t.name);return e?n=e[t.name].apply(e,[o].concat(d)):$.data(this,t.name,new i(this,l))}),r?n:this}}}()},{}],12:[function(e,t){t.exports={_init:function(){var e=this;this._extend($.idealforms.extensions),this.$form=$(this.el),this.$fields=$(),this.$inputs=$(),this.$form.submit(function(t){t.preventDefault(),e.focusFirstInvalid(),e.opts.onSubmit.call(this,e.getInvalid().length,t)}),this._inject("_init"),this.addRules(this.opts.rules||{}),this.opts.silentLoad||this.focusFirstInvalid()},_buildField:function(e){var t,i=this._getField(e);t=$(this.opts.iconHtml,{"class":this.opts.iconClass,click:function(){$(e).focus()}}),this.$fields.filter(i).length||(this.$fields=this.$fields.add(i),this.opts.iconHtml&&i.append(t),i.addClass("idealforms-field idealforms-field-"+e.type)),this._addEvents(e),this._inject("_buildField",e)},_addEvents:function(e){var t=this,i=this._getField(e);$(e).on("change keyup",function(e){var n=i.data("idealforms-value");9!=e.which&&16!=e.which&&($(this).is(":checkbox, :radio")||n!=this.value)&&(i.data("idealforms-value",this.value),t._validate(this,!0,!0))}).focus(function(){return t.isValid(this.name)?!1:((t._isRequired(this)||this.value)&&i.find(t.opts.error).show(),void 0)}).blur(function(){i.find(t.opts.error).hide()})},_isRequired:function(e){return $(e).is(":checkbox, :radio, select")?!0:this.opts.rules[e.name].indexOf("required")>-1},_getRelated:function(e){return this._getField(e).find('[name="'+e.name+'"]')},_getField:function(e){return $(e).closest(this.opts.field)},_getFirstInvalid:function(){return this.getInvalid().first().find("input:first, textarea, select")},_handleError:function(e,t,i){i=i||this.isValid(e.name);var n=this._getField(e).find(this.opts.error);this.$form.find(this.opts.error).hide(),t&&n.text(t),n.toggle(!i)},_handleStyle:function(e,t){t=t||this.isValid(e.name),this._getField(e).removeClass(this.opts.validClass+" "+this.opts.invalidClass).addClass(t?this.opts.validClass:this.opts.invalidClass).find("."+this.opts.iconClass).show()},_fresh:function(e){this._getField(e).removeClass(this.opts.validClass+" "+this.opts.invalidClass).find(this.opts.error).hide().end().find("."+this.opts.iconClass).toggle(this._isRequired(e))},_validate:function(e,t,i){var n,s=this,a=this._getField(e),o=this.opts.rules[e.name].split($.idealforms.ruleSeparator),r=!0;return e.value||this._isRequired(e)?$.each(o,function(o,l){l=l.split($.idealforms.argSeparator),n=l[0];var d,u=$.idealforms.rules[n],c=l.slice(1);return d=$.idealforms._format.apply(null,[$.idealforms._getKey("errors."+e.name+"."+n,s.opts)||$.idealforms.errors[n]].concat(c)),r="function"==typeof u?u.apply(s,[e,e.value].concat(c)):u.test(e.value),a.data("idealforms-valid",r),t&&s._handleError(e,d,r),i&&s._handleStyle(e,r),s.opts.onValidate.call(s,e,n,r),r}):(a.removeData("idealforms-valid"),this._fresh(e)),this._inject("_validate",e,n,r),r}}},{}],13:[function(e,t){t.exports={addRules:function(e){var t=this,i=this.$form.find($.map(e,function(e,t){return'[name="'+t+'"]'}).join(","));$.extend(this.opts.rules,e),i.each(function(){t._buildField(this)}),this.$inputs=this.$inputs.add(i).each(function(){t._validate(this,!0)}),this.$fields.find(this.opts.error).hide(),this._inject("addRules")},getInvalid:function(){return this.$fields.filter(function(){return $(this).data("idealforms-valid")===!1})},focusFirstInvalid:function(){var e=this._getFirstInvalid()[0];e&&(this._handleError(e),this._handleStyle(e),this._inject("focusFirstInvalid",e),e.focus())},isValid:function(e){return e?!this.getInvalid().find('[name="'+e+'"]').length:!this.getInvalid().length},reset:function(e){var t=this,i=this.$inputs;e&&(i=i.filter('[name="'+e+'"]')),i.filter("input:not(:checkbox, :radio)").val(""),i.filter(":checkbox, :radio").prop("checked",!1),i.filter("select").find("option").prop("selected",function(){return this.defaultSelected}),i.change().each(function(){t._resetErrorAndStyle(this)})}}},{}],14:[function(e,t){t.exports={required:/.+/,digits:/^\d+$/,email:/^[^@]+@[^@]+\..{2,6}$/,username:/^[a-z](?=[\w.]{3,31}$)\w*\.?\w*$/i,pass:/(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/,strongpass:/(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/,phone:/^[2-9]\d{2}-\d{3}-\d{4}$/,zip:/^\d{5}$|^\d{5}-\d{4}$/,url:/^(?:(ftp|http|https):\/\/)?(?:[\w\-]+\.)+[a-z]{2,6}([\:\/?#].*)?$/i,number:function(e,t){return!isNaN(t)},range:function(e,t,i,n){return Number(t)>=min&&Number(t)<=n},min:function(e,t,i){return t.length>=i},max:function(e,t,i){return t.length<=i},minoption:function(e,t,i){return this._getRelated(e).filter(":checked").length>=i},maxoption:function(e,t,i){return this._getRelated(e).filter(":checked").length<=i},minmax:function(e,t,i,n){return t.length>=i&&t.length<=n},select:function(e,t,i){return t!=i},extension:function(e){var t=[].slice.call(arguments,1),i=!1;return $.each(e.files||[{name:e.value}],function(e,n){i=$.inArray(n.name.match(/\.(.+)$/)[1],t)>-1}),i},equalto:function(e,t,i){var n=this,s=$('[name="'+i+'"]');return this.getInvalid().find(s).length?!1:(s.off("keyup.equalto").on("keyup.equalto",function(){n._validate(e,!1,!0)}),e.value==s.val())},date:function(e,t,i){function n(e,t){for(var i,n,s,a=0,o=t.length;o>a;a++)/m/.test(t[a])&&(i=e[a]),/d/.test(t[a])&&(n=e[a]),/y/.test(t[a])&&(s=e[a]);return i&&n&&s?i>0&&13>i&&s&&4==s.length&&n>0&&n<=new Date(s,i,0).getDate():!1}i=i||"mm/dd/yyyy";var s=/[^mdy]/.exec(i)[0],a=i.split(s),o=t.split(s);return n(o,a)}}},{}]},{},[10]); \ No newline at end of file diff --git a/js/plugin.js b/js/plugin.js new file mode 100644 index 0000000..04d635e --- /dev/null +++ b/js/plugin.js @@ -0,0 +1,124 @@ +/** + * Plugin boilerplate + */ +module.exports = (function() { + + var AP = Array.prototype; + + return function(plugin) { + + $.extend({ + name: 'plugin', + defaults: {}, + methods: {}, + global: {}, + }, plugin); + + $[plugin.name] = $.extend({ + + addExtension: function(extension) { + plugin.global.extensions.push(extension); + }, + + hasExtension: function(extension) { + return plugin.global.extensions.filter(function(ext) { + return ext.name == extension; + }).length; + } + }, plugin.global); + + function Plugin(element, options) { + + this.opts = $.extend({}, plugin.defaults, options); + this.el = element; + + this._name = plugin.name; + + this._init(); + } + + Plugin._extended = {}; + + Plugin.prototype._extend = function(extensions) { + + var self = this + , disabled = self.opts.disabledExtensions || 'none'; + + $.each(extensions, function(i, extension) { + + $.extend(self.opts, $.extend(true, extension.options, self.opts)); + + $.each(extension.methods, function(method, fn) { + + if (disabled.indexOf(extension.name) > -1) { + return; + } + + if (Plugin.prototype[method]) { + Plugin._extended[method] = Plugin._extended[method] || []; + Plugin._extended[method].push({ name: extension.name, fn: fn }); + } else { + Plugin.prototype[method] = fn; + } + }); + + }); + }; + + Plugin.prototype._inject = function(method) { + + var args = [].slice.call(arguments, 1); + + if (typeof method == 'function') return method.call(this); + + var self = this; + + if (Plugin._extended[method]) { + $.each(Plugin._extended[method], function(i, plugin) { + plugin.fn.apply(self, args); + }); + } + }; + + Plugin.prototype._init = $.noop; + + Plugin.prototype[plugin.name] = function(method) { + if (!method) return this; + try { return this[method].apply(this, AP.slice.call(arguments, 1)); } + catch(e) {} + }; + + $.extend(Plugin.prototype, plugin.methods); + + $.fn[plugin.name] = function() { + + var args = AP.slice.call(arguments) + , methodArray = typeof args[0] == 'string' && args[0].split(':') + , method = methodArray[methodArray.length > 1 ? 1 : 0] + , prefix = methodArray.length > 1 && methodArray[0] + , opts = typeof args[0] == 'object' && args[0] + , params = args.slice(1) + , ret; + + if (prefix) { + method = prefix + method.substr(0,1).toUpperCase() + method.substr(1,method.length-1); + } + + this.each(function() { + + var instance = $.data(this, plugin.name); + + // Method + if (instance) { + return ret = instance[plugin.name].apply(instance, [method].concat(params)); + } + + // Init + return $.data(this, plugin.name, new Plugin(this, opts)); + }); + + return prefix ? ret : this; + }; + }; + +}()); diff --git a/js/private.js b/js/private.js new file mode 100644 index 0000000..264a129 --- /dev/null +++ b/js/private.js @@ -0,0 +1,174 @@ +/** + * Private methods + */ +module.exports = { + + _init: function() { + + var self = this; + + this._extend($.idealforms.extensions); + + this.$form = $(this.el); + this.$fields = $(); + this.$inputs = $(); + + this.$form.submit(function(e) { + e.preventDefault(); + self.focusFirstInvalid(); + self.opts.onSubmit.call(this, self.getInvalid().length, e); + }); + + this._inject('_init'); + + this.addRules(this.opts.rules || {}); + + if (! this.opts.silentLoad) this.focusFirstInvalid(); + }, + + _buildField: function(input) { + + var self = this + , $field = this._getField(input) + , $icon; + + $icon = $(this.opts.iconHtml, { + class: this.opts.iconClass, + click: function(){ $(input).focus() } + }); + + if (! this.$fields.filter($field).length) { + this.$fields = this.$fields.add($field); + if (this.opts.iconHtml) $field.append($icon); + $field.addClass('idealforms-field idealforms-field-'+ input.type); + } + + this._addEvents(input); + + this._inject('_buildField', input); + }, + + _addEvents: function(input) { + + var self = this + , $field = this._getField(input); + + $(input) + .on('change keyup', function(e) { + + var oldValue = $field.data('idealforms-value'); + + if (e.which == 9 || e.which == 16) return; + if (! $(this).is(':checkbox, :radio') && oldValue == this.value) return; + + $field.data('idealforms-value', this.value); + + self._validate(this, true, true); + }) + .focus(function() { + + if (self.isValid(this.name)) return false; + + if (self._isRequired(this) || this.value) { + $field.find(self.opts.error).show(); + } + }) + .blur(function() { + $field.find(self.opts.error).hide(); + }); + }, + + _isRequired: function(input) { + // We assume non-text inputs with rules are required + if ($(input).is(':checkbox, :radio, select')) return true; + return this.opts.rules[input.name].indexOf('required') > -1; + }, + + _getRelated: function(input) { + return this._getField(input).find('[name="'+ input.name +'"]'); + }, + + _getField: function(input) { + return $(input).closest(this.opts.field); + }, + + _getFirstInvalid: function() { + return this.getInvalid().first().find('input:first, textarea, select'); + }, + + _handleError: function(input, error, valid) { + valid = valid || this.isValid(input.name); + var $error = this._getField(input).find(this.opts.error); + this.$form.find(this.opts.error).hide(); + if (error) $error.text(error); + $error.toggle(!valid); + }, + + _handleStyle: function(input, valid) { + valid = valid || this.isValid(input.name); + this._getField(input) + .removeClass(this.opts.validClass +' '+ this.opts.invalidClass) + .addClass(valid ? this.opts.validClass : this.opts.invalidClass) + .find('.'+ this.opts.iconClass).show(); + }, + + _fresh: function(input) { + this._getField(input) + .removeClass(this.opts.validClass +' '+ this.opts.invalidClass) + .find(this.opts.error).hide() + .end() + .find('.'+ this.opts.iconClass).toggle(this._isRequired(input)); + }, + + _validate: function(input, handleError, handleStyle) { + + var self = this + , $field = this._getField(input) + , userRules = this.opts.rules[input.name].split($.idealforms.ruleSeparator) + , valid = true + , rule; + + // Non-required input with empty value must pass validation + if (! input.value && ! this._isRequired(input)) { + $field.removeData('idealforms-valid'); + this._fresh(input); + + // Required inputs + } else { + + $.each(userRules, function(i, userRule) { + + userRule = userRule.split($.idealforms.argSeparator); + + rule = userRule[0]; + + var theRule = $.idealforms.rules[rule] + , args = userRule.slice(1) + , error; + + error = $.idealforms._format.apply(null, [ + $.idealforms._getKey('errors.'+ input.name +'.'+ rule, self.opts) || + $.idealforms.errors[rule] + ].concat(args)); + + valid = typeof theRule == 'function' + ? theRule.apply(self, [input, input.value].concat(args)) + : theRule.test(input.value); + + $field.data('idealforms-valid', valid); + + if (handleError) self._handleError(input, error, valid); + if (handleStyle) self._handleStyle(input, valid); + + self.opts.onValidate.call(self, input, rule, valid); + + return valid; + }); + } + + this._inject('_validate', input, rule, valid); + + return valid; + } + +}; diff --git a/js/public.js b/js/public.js new file mode 100644 index 0000000..18f11dd --- /dev/null +++ b/js/public.js @@ -0,0 +1,66 @@ +/** + * Public methods + */ +module.exports = { + + addRules: function(rules) { + + var self = this; + + var $inputs = this.$form.find($.map(rules, function(_, name) { + return '[name="'+ name +'"]'; + }).join(',')); + + $.extend(this.opts.rules, rules); + + $inputs.each(function(){ self._buildField(this) }); + + this.$inputs = this.$inputs + .add($inputs) + .each(function(){ self._validate(this, true) }); + + this.$fields.find(this.opts.error).hide(); + + this._inject('addRules'); + }, + + getInvalid: function() { + return this.$fields.filter(function() { + return $(this).data('idealforms-valid') === false; + }); + }, + + focusFirstInvalid: function() { + + var firstInvalid = this._getFirstInvalid()[0]; + + if (firstInvalid) { + this._handleError(firstInvalid); + this._handleStyle(firstInvalid); + this._inject('focusFirstInvalid', firstInvalid); + firstInvalid.focus(); + } + }, + + isValid: function(name) { + if (name) return ! this.getInvalid().find('[name="'+ name +'"]').length; + return ! this.getInvalid().length; + }, + + reset: function(name) { + + var self = this + , $inputs = this.$inputs; + + if (name) $inputs = $inputs.filter('[name="'+ name +'"]'); + + $inputs.filter('input:not(:checkbox, :radio)').val(''); + $inputs.filter(':checkbox, :radio').prop('checked', false); + $inputs.filter('select').find('option').prop('selected', function() { + return this.defaultSelected; + }); + + $inputs.change().each(function(){ self._resetErrorAndStyle(this) }); + } + +}; diff --git a/js/rules.js b/js/rules.js new file mode 100644 index 0000000..9c45bf1 --- /dev/null +++ b/js/rules.js @@ -0,0 +1,102 @@ +/** + * Rules + */ +module.exports = { + + required: /.+/, + digits: /^\d+$/, + email: /^[^@]+@[^@]+\..{2,6}$/, + username: /^[a-z](?=[\w.]{3,31}$)\w*\.?\w*$/i, + pass: /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/, + strongpass: /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/, + phone: /^[2-9]\d{2}-\d{3}-\d{4}$/, + zip: /^\d{5}$|^\d{5}-\d{4}$/, + url: /^(?:(ftp|http|https):\/\/)?(?:[\w\-]+\.)+[a-z]{2,6}([\:\/?#].*)?$/i, + + number: function(input, value) { + return !isNaN(value); + }, + + range: function(input, value, mix, max) { + return Number(value) >= min && Number(value) <= max; + }, + + min: function(input, value, min) { + return value.length >= min; + }, + + max: function(input, value, max) { + return value.length <= max; + }, + + minoption: function(input, value, min) { + return this._getRelated(input).filter(':checked').length >= min; + }, + + maxoption: function(input, value, max) { + return this._getRelated(input).filter(':checked').length <= max; + }, + + minmax: function(input, value, min, max) { + return value.length >= min && value.length <= max; + }, + + select: function(input, value, def) { + return value != def; + }, + + extension: function(input) { + + var extensions = [].slice.call(arguments, 1) + , valid = false; + + $.each(input.files || [{name: input.value}], function(i, file) { + valid = $.inArray(file.name.match(/\.(.+)$/)[1], extensions) > -1; + }); + + return valid; + }, + + equalto: function(input, value, target) { + + var self = this + , $target = $('[name="'+ target +'"]'); + + if (this.getInvalid().find($target).length) return false; + + $target.off('keyup.equalto').on('keyup.equalto', function() { + self._validate(input, false, true); + }); + + return input.value == $target.val(); + }, + + date: function(input, value, format) { + + format = format || 'mm/dd/yyyy'; + + var delimiter = /[^mdy]/.exec(format)[0] + , theFormat = format.split(delimiter) + , theDate = value.split(delimiter); + + function isDate(date, format) { + + var m, d, y; + + for (var i = 0, len = format.length; i < len; i++) { + if (/m/.test(format[i])) m = date[i]; + if (/d/.test(format[i])) d = date[i]; + if (/y/.test(format[i])) y = date[i]; + } + + if (!m || !d || !y) return false; + + return m > 0 && m < 13 && + y && y.length == 4 && + d > 0 && d <= (new Date(y, m, 0)).getDate(); + } + + return isDate(theDate, theFormat); + } + +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..a31770b --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "name": "idealforms", + "version": "3.0.0", + "dependencies": { + "nib": "*" + } +} diff --git a/styl/datepicker.styl b/styl/datepicker.styl new file mode 100644 index 0000000..f2a6b53 --- /dev/null +++ b/styl/datepicker.styl @@ -0,0 +1,72 @@ +// Datepicker +//--------------------------------------- + +.idealforms input.datepicker.open + border-bottom-color: transparent + border-radius: 0 + border-radius: top radius + +.ui-datepicker + display: none + box-sizing: border-box + width: input-width + margin-top: -2px + padding: .75em + background: white + border: 1px solid #999 + border-radius: bottom radius + box-shadow: 0 1px 2px rgba(black, .2) + +.ui-datepicker-header + position: relative + padding: .2em 0 + margin-bottom: .75em + font-weight: bold + + .ui-datepicker-title + text-align: center + + .ui-datepicker-prev + .ui-datepicker-next + text-indent: -9999px + width: 16px + height: 16px + position: absolute + cursor: pointer + user-select: none + background: url(../img/datepicker.png) 0 0 + + &:active + margin-top: 1px + + .ui-datepicker-next + background-position: -16px 0 + + .ui-datepicker-prev + left: 8px + + .ui-datepicker-next + right: 8px + +.ui-datepicker-calendar + width: 100% + border-collapse: collapse + table-layout: fixed + + td + padding: .25em 0 + text-align: center + + a + display: block + text-decoration: none + color: gray + + &:hover + color: valid + font-weight: bold + + .ui-datepicker-today a + margin: 0 .25em + background: #eee + border-radius: radius diff --git a/styl/idealfile.styl b/styl/idealfile.styl new file mode 100644 index 0000000..3bedae1 --- /dev/null +++ b/styl/idealfile.styl @@ -0,0 +1,31 @@ +// Ideal File +//--------------------------------------- + +form.idealforms + + .ideal-file-wrap + float: left + + .ideal-file-filename + float: left + width: input-width*.7 + 1px + height: 100% + border-radius: 0 + border-radius: left radius + + .ideal-file-upload + idealbutton() + overflow: visible + position: relative + float: right + left: -1px + width: input-width*.3 + padding-left: 0 + padding-right: 0 + text-align: center + border-radius: 0 + border-radius: right radius + +.ie9 + .ideal-file-upload + line-height: 1.15 diff --git a/styl/idealradiocheck.styl b/styl/idealradiocheck.styl new file mode 100644 index 0000000..e3666d8 --- /dev/null +++ b/styl/idealradiocheck.styl @@ -0,0 +1,42 @@ +// Ideal Radio & Check +//--------------------------------------- + +form.idealforms + + .ideal-radiocheck-label + cursor: pointer + margin: .15em 0 !important + + if group-horizontal + margin: .15em 10px !important + + input + float: left + + .ideal-check, .ideal-radio + float: left + margin-right: 10px !important + width: 20px + height: 20px + background: url(../img/radiocheck.png) 0 0 + + .ideal-check.focus + background-position: -20px 0 + + .ideal-check.checked + background-position: -40px 0 + + .ideal-check.checked.focus + background-position: -60px 0 + + .ideal-radio + background-position: 0 bottom + + .ideal-radio.focus + background-position: -20px bottom + + .ideal-radio.checked + background-position: -40px bottom + + .ideal-radio.checked.focus + background-position: -60px bottom diff --git a/styl/idealsteps.styl b/styl/idealsteps.styl new file mode 100644 index 0000000..891679a --- /dev/null +++ b/styl/idealsteps.styl @@ -0,0 +1,91 @@ +// Ideal Steps +//--------------------------------------- + +.idealsteps-step + clearfix() + +.idealsteps-nav + + ui() + overflow: hidden + margin-bottom: 2em + + ul + reset-box-model() + list-style: none + + li + float: left + + a + position: relative + float: left + padding: 0 1.5em 0 2.75em + height: 3.5em + line-height: 3.5em + text-decoration: none + color: darken(ui-element, 50) + background: ui-element + transition: padding .2s ease-in-out + + &:focus + outline: 0 // Firefox + + &:hover + background: lighten(ui-element, 5) + &:after + border-left-color: lighten(ui-element, 5) + + &:after, &:before + content: "" + position: absolute + z-index: 1 + top: 0 + right: -2em + margin-right: 0 + margin-top: -.125em + border-width: 2em 1em + border-style: solid + border-color: transparent + border-left-color: ui-element + + &:before + margin-right: -1px + border-left-color: darken(ui-element, 20) + + li:first-child a + padding-left: 1.75em + + li.idealsteps-step-active + a + padding-right: 3.5em + background: white + color: valid + font-weight: bold + + &:after + border-left-color: white + + .counter + opacity: 1 + + .counter + opacity: 0 + position: absolute + top: 50% + right: 1em + height: 20px + width: 20px + margin-top: -.75em + line-height: 20px !important + text-align: center + line-height: 1 + color: invalid + border: 1px solid invalid + border-radius: 10em + transition: opacity .2s ease-in-out + + &.zero + color: valid + border-color: valid + diff --git a/styl/jquery.idealforms.styl b/styl/jquery.idealforms.styl new file mode 100644 index 0000000..6f8d360 --- /dev/null +++ b/styl/jquery.idealforms.styl @@ -0,0 +1,13 @@ +/*! + * jQuery Ideal Forms + * @author: Cedric Ruiz + * @version: 3.0 + * @license GPL or MIT + */ +@import '../node_modules/nib' +@import 'vars' +@import 'main' +@import 'idealsteps' +@import 'idealradiocheck' +@import 'idealfile' +@import 'datepicker' diff --git a/styl/main.styl b/styl/main.styl new file mode 100644 index 0000000..80dbf67 --- /dev/null +++ b/styl/main.styl @@ -0,0 +1,175 @@ +// Style +//--------------------------------------- + +form.idealforms + clearfix() + line-height: 1.5 + + * + box-sizing: border-box + + .field + position: relative + float: left + clear: both + margin: .35em 0 + + label.main, .field > input, select, button, textarea, .field .group + float: left + + label.main + width: label-width + margin-top: .55em + + input, textarea, select, button, .field .group + reset-box-model() + width: input-width + padding: .55em + border: 1px solid #999 + outline: 0 + background: white + border-radius: radius + box-shadow: inset 0 1px 2px rgba(black, .15) + + input + transition: background .3s ease-in-out + + textarea + width: input-width*1.5 + + select, button + idealbutton() + + button + width: auto + + select + padding: .55em + + &:focus + border: 1px solid darken(ui-element, 60) + + input[type="file"] + padding: 0 + + .field .group + position: relative + padding: 1.25em + box-shadow: none + + label + float: left + clear: both + padding: .15em 0 + + if group-horizontal + clear: none + + input,label + margin: 0 + + input + width: auto + margin-right: .5em + box-shadow: none + + label + margin-right: 1em + &:last-of-type + margin: 0 + + .field.valid + input, select, textarea, .group + color: darken(valid, 30) + background: valid-bg + border-color: valid + + .field.invalid + input, select, textarea, .group + color: darken(invalid, 30) + background: invalid-bg + border-color: invalid + + .field.valid, .field.invalid + .group, textarea, select + color: inherit + background: none + + select + background: linear-gradient(lighten(ui-element, 15), ui-element) + + .field .icon + position: absolute + width: 16px + height: 16px + top: 50% + left: 100% + margin-top: -8px + margin-left: 8px + background: url(../img/validation.png) -16px 0 no-repeat + cursor: pointer + + .field.invalid .icon + background-position: -16px 0 + + .field.valid .icon + background-position: 0 0 + cursor: default + + .field.invalid, .field.valid + .group input + border: 0 + outline: 0 + box-shadow: none + + .field.ajax + input + color: darken(ajax, 30) + background: ajax-bg + border-color: ajax + + .icon + background: url(../img/loading.gif) + + .error + display: none + position: absolute + z-index: 1 + left: 100% + top: 50% + padding: 1em 1.5em + width: error-width + margin-left: 32 + 8 px + if not icon + margin-left: 1.25em + background: error + background: linear-gradient(error, lighten(error, 7)) + color: lighten(error, 90) + font-size: 85% + font-weight: bold + text-shadow: 0 1px 0 rgba(black, .3) + line-height: 1.35 + border: 1px solid darken(error, 10) + border-radius: 0 radius radius radius + box-shadow: 0 1px 1px rgba(black, .15) + + &:after + content: "" + position: absolute + z-index: -1 + top: -1px + left: -.7em + border-width: .7em + border-style: solid + border-color: transparent + border-top-color: error + + .idealforms-field-checkbox + .idealforms-field-radio + .idealforms-field-textarea + .icon + top: 8px + margin-top: 0 + + .error + top: 20px diff --git a/styl/vars.styl b/styl/vars.styl new file mode 100644 index 0000000..083299b --- /dev/null +++ b/styl/vars.styl @@ -0,0 +1,42 @@ +// Theme +//--------------------------------------- + +valid = #3F9DCC +valid-bg = #EDF7FC +invalid = #CC2A18 +invalid-bg = #FFEDED +ajax = #CFAA19 +ajax-bg = #FAF9E8 +ui-element = #ddd +error = #285d85 + +label-width = 120px +input-width = 290px +error-width = (input-width/1.5) +radius = 3px + +icon = true +group-horizontal = false + +// Mixins +//--------------------------------------- + +ui() + color: darken(ui-element, 70) + background: #eee + background: linear-gradient(lighten(ui-element, 15), ui-element) + border: 1px solid darken(ui-element, 20) + border-bottom-color: darken(ui-element, 30) + box-shadow: 0 1px 2px rgba(black, .15) + border-radius: radius + +idealbutton() + ui() + padding: .55em 1.5em + + &:hover + background: linear-gradient(lighten(ui-element, 20), lighten(ui-element, 5)) + + &:active + background: ui-element +