diff --git a/dist/jquery.jsForm-1.1.0.js b/dist/jquery.jsForm-1.1.0.js
deleted file mode 100644
index 14ef3f7..0000000
--- a/dist/jquery.jsForm-1.1.0.js
+++ /dev/null
@@ -1,2657 +0,0 @@
-/**
- * jquery.jsForm
- * -------------
- * JsForm control for handling html UI with json objects
- * @version 1.0
- * @class
- * @author Niko Berger
- * @license MIT License GPL
- */
-;(function( $, window, undefined ){
- "use strict";
-
- var JSFORM_INIT_FUNCTIONS = {}, // remember initialization functions
- JSFORM_MAP = {}; // remember all forms
-
-
- /**
- * @param element {Node} the cotnainer node that should be converted to a jsForm
- * @param options {object} the configuraton object
- * @constructor
- */
- function JsForm (element, options) {
- var $this = $(element);
-
- // create the options
- this.options = $.extend({}, {
- /**
- * enable form control rendering (if jsForm.controls is available) and validation
- */
- controls: true,
- /**
- * the object used to fill/collect data
- */
- data: null,
- /**
- * the prefix used to annotate theinput fields
- */
- prefix: "data",
- /**
- * set to false to only validate visible fields.
- * This is discouraged especially when you have tabs or similar elements in your form.
- */
- validateHidden: true,
- /**
- * skip empty values when getting an object
- */
- skipEmpty: false
- }, options);
-
- // read prefix from dom
- if($this.attr("data-prefix") && (this.options.prefix === "data" || this.options.prefix === "")) {
- if($this.attr("data-prefix") !== "") {
- this.options.prefix = $this.attr("data-prefix");
- }
- }
-
- this.element = element;
-
- this._init();
- }
-
- /**
- * init the portlet - load the config
- * @private
- */
- JsForm.prototype._init = function() {
- // init the basic dom functionality
- this._domInit();
-
- // enable form controls
- if(this.options.controls) {
- if($.jsFormControls) {
- $(this.element).jsFormControls();
- } else {
- try {
- if(typeof console !== "undefined") {
- console.log("jquery.JsForm.controls not available!");
- }
- } catch(ex) {
- // ignore
- }
- }
- }
-
- // fill/init with the first data
- this._fill(this.element, this.options);
- };
-
-
- /**
- * init the dom. This can be called multiple times.
- * this will also enable "add", "insert" and "delete" for collections
- * @private
- */
- JsForm.prototype._domInit = function() {
- var form = $(this.element);
- var that = this;
- var prefix = this.options.prefix;
-
- // collection lists with buttons
- that._initCollection(form, prefix);
- // init conditionals
- that._initConditional(form, prefix, this.options);
- };
-
- /**
- * simple debug helper
- * @param msg the message to pring
- * @private
- */
- JsForm.prototype._debug = function(msg) {
- if(typeof console !== "undefined") {
- console.log("JsForm: " + msg);
- }
- };
-
- /**
- * initialize conditionals.
- * basic rule is:
- * any dom element that has a conditional and either
- * a data-show or data-hide attribute or a data-eval attribute
- *
- * @param form the base dom element
- * @param prefix the prefix to check for
- * @private
- */
- JsForm.prototype._initConditional = function(form, prefix, options) {
- var that = this;
- var showEvaluator = function(ele, data, fields) {
- // if any field has a value -> show
- var show = false;
- $.each(fields, function(){
- var value = that._getValueWithArrays(data, this);
- if(!value || value === "" || value === 0 || value === -1)
- return;
- show = true;
- // skip processing
- return false;
- });
- if(show)
- ele.show();
- else
- ele.hide();
- }, hideEvaluator = function(ele, data, fields) {
- // if any field has a value -> hide
- var show = false;
- $.each(fields, function(){
- var value = that._getValueWithArrays(data, this);
- if(!value || value === "" || value === 0 || value === -1)
- return;
- show = true;
- // skip processing
- return false;
- });
- if(show)
- ele.hide();
- else
- ele.show();
- };
-
- // remember the conditionals for faster dom access
- this.conditionals = $(form).find(".conditional");
-
- this.conditionals.each(function(){
- $(this).data().conditionalEval = [];
- var fields = $(this).attr("data-show");
- if(fields && fields.length > 0) {
- $(this).data().conditionalEval.push({
- func: showEvaluator,
- field: fields.split(" ")
- });
- }
- fields = $(this).attr("data-hide");
- if(fields && fields.length > 0) {
- $(this).data().conditionalEval.push({
- func: hideEvaluator,
- field: fields.split(" ")
- });
- }
- fields = $(this).attr("data-eval");
- if(fields && fields.length > 0) {
- // custom evaluator
- if(options.conditionals[fields])
- $(this).data().conditionalEval.push({
- func: options.conditionals[fields]
- });
- }
- });
- };
-
- /**
- * evaluate conditionals on the form
- * @param form the form to search for conditionals
- * @param data the data
- */
- JsForm.prototype._evaluateConditionals = function(form, data) {
- this.conditionals.each(function(){
- var ele = $(this);
- // go throguh all evaluation functions
- $.each(ele.data().conditionalEval, function() {
- this.func(ele, data, this.field);
- });
- });
- };
-
- /**
- * initialize collections
- * @param form the base dom element
- * @param prefix the prefix to check for
- * @private
- */
- JsForm.prototype._initCollection = function(form, prefix) {
- // all collections
- var collectionMap = {},
- that = this;
- $(form).data().collections = collectionMap;
-
- $(".collection", form).each(function() {
- var colName = $(this).attr("data-field");
- // skip collections without a data-field mapping
- if (!colName || colName.indexOf(prefix + ".") !== 0) {
- return;
- }
-
- var container = $(this);
-
- // remember the collection
- var cols = collectionMap[colName];
- if(cols) {
- cols.push(container);
- } else {
- collectionMap[colName] = [container];
- }
-
- //init the collection
- that._initList(container);
-
- // after adding: check if we want reorder control
- if(!container.hasClass("ui-sortable") && container.hasClass("sortable") && container.sortable) {
- // get the config object
- var config = container.attr("data-sortable");
- if(!config) {
- config = {};
- } else {
- config = JSON.parse(config);
- }
-
- container.sortable(config);
- container.on("sortstop", function( event, ui ) {
- that._reorder(container);
- });
- }
-
- });
-
- $(".add", form).each(function(){
- var fieldName = $(this).attr("data-field");
- if(!fieldName) {
- return;
- }
-
- // only init once
- if($(this).data("collections")) {
- return;
- }
-
- // add the collection
- $(this).data().collections = collectionMap[fieldName];
-
- $(this).click(function(ev){
- ev.preventDefault();
-
- // search for a collection with that name
- $.each($(this).data("collections"), function() {
- var tmpl = $(this).data("template");
- // and has a template
- if(tmpl) {
- var line = tmpl.clone(true);
- $(this).append(line);
- $(line).addClass("POJO");
- $(line).data("pojo", {});
-
- that._addCollectionControls(line);
-
- // trigger a callback
- $(this).trigger("addCollection", [line, $(line).data().pojo]);
-
- // the new entry has as index the count of all "lines"
- var idx = $(this).children(".POJO").length;
-
- // fill the line with data
- that._fillData(line, $(line).data().pojo, fieldName.substring(fieldName.indexOf('.')+1), idx);
-
- // its possible to have "sub" collections
- that._initCollection(line, fieldName.substring(fieldName.indexOf('.')+1));
-
- // trigger a callback after the data has been rendered)
- $(this).trigger("postAddCollection", [line, $(line).data().pojo]);
-
-
- }
- });
- });
- });
-
- // insert: similar to add - but works with events
- $(".insert", form).each(function(){
- var fieldName = $(this).attr("data-field");
- if(!fieldName) {
- return;
- }
-
- // only init once
- if($(this).data("collections")) {
- return;
- }
-
- // remember the collections
- $(this).data("collections", collectionMap[$(this).attr("data-field")]);
-
- $(this).on("insert", function(ev, pojo){
- if(!pojo)
- pojo = $(this).data().pojo;
-
- // insert only works if there is a pojo
- if(!pojo) {
- return;
- }
- var beforeInsertCallback = $(this).data("beforeInsert");
- if(beforeInsertCallback && $.isFunction(beforeInsertCallback)) {
- pojo = beforeInsertCallback(pojo);
-
- // insert only works if there is a pojo
- if(!pojo) {
- return;
- }
- }
-
- // search for a collection with that name
- $.each($(this).data("collections"), function() {
- var tmpl = $(this).data("template");
- // and has a template
- if(tmpl) {
- var line = tmpl.clone(true);
- // mark that this is a pojo
- line.addClass("POJO");
- // add the pojo
- line.data().pojo = pojo;
-
- that._addCollectionControls(line);
-
- // its possible to have "sub" collections
- that._initCollection(line);
-
- // trigger a callback
- $(this).trigger("addCollection", [line, $(line).data().pojo]);
-
- // the new entry has as index the count of all "lines"
- var idx = $(this).children(".POJO").length;
-
- // fill the "information"
- that._fillData(line, pojo, fieldName.substring(fieldName.indexOf('.')+1), idx);
-
- $(this).append(line);
- }
- });
-
- // empty field
- $(this).val("");
- $(this).data().pojo = null;
- $(this).focus();
- });
- });
-
- // insert: helper button (triggers insert)
- $(".insertAction", form).each(function(){
- var fieldName = $(this).attr("data-field");
- if(!fieldName) {
- return;
- }
-
- // only init once
- if($(this).data("inserter")) {
- return;
- }
-
- // find the insert element for this data-field
- var inserter = $(this).parent().find(".insert");
- if(!inserter) {
- return;
- }
-
- // remember the inserter
- $(this).data("inserter", inserter);
-
- $(this).click(function(ev){
- ev.preventDefault();
- $(this).data("inserter").trigger("insert");
- return false;
- });
-
- });
-
- $("input.object", form).each(function(){
- $(this).on("update", function(evt){
- var pojo = $(this).data().pojo;
- if (pojo && $(this).attr("data-display")) {
- $(this).val(that._renderObject(pojo, $(this).attr("data-display")));
- }
- });
- });
-
- // fileupload
- $("input.blob", form).each(function(){
- // only available on input type file
- if($(this).attr("type") !== "file") {
- return;
- }
-
- var blobInput = $(this);
-
- // bind on change
- $(this).on("change", function(evt){
-
- //get file name
- var fileName = $(this).val().split(/\\/).pop();
- blobInput.data("name", fileName);
-
- var files = evt.target.files; // FileList object
- // Loop through the FileList (and render image files as thumbnails.(skip for ie < 9)
- if(files && files.length) {
- $.each(files, function() {
- var reader = new FileReader();
-
- // closure to capture the file information
- reader.onload = function(e) {
- // get the result
- blobInput.data("blob", e.target.result);
- };
-
- // Read in the image file as a data URL.
- reader.readAsDataURL(this);
-
- $(this).trigger("fileChange");
- });
- }
- });
-
-
- });
-
- // manage - obsolete
- $(".manage", form).each(function(){
- var fieldName = $(this).attr("data-field");
- if(!fieldName) {
- return;
- }
-
- // remember the collections
- $(this).data("collections", collectionMap[fieldName]);
-
- // start the multi-select
- $(this).click(function(){
- var dataService = $(this).attr("data-service");
- var collectionList = $(this).data("collections");
-
- var btn = $(this);
- var display = $(this).attr("data-display");
- if(display) {
- display = display.split(",");
- }
-
- DataUtils.run(dataService, function(data){
- var select = $('');
- select.data("collections", collectionList);
- btn.data("select", select);
- $.each(data, function(){
- var cur = this;
- var optionDisplay = "";
- if(!display) {
- optionDisplay = cur;
- } else {
- for(var j = 0; j < display.length; j++) {
- optionDisplay += cur[display[j]] + " ";
- }
- }
- var option = $('');
- // check if we need to "select" that option
- $(collectionList).each(function() {
- $(this).children().each(function(count, ele){
- if(cur.id === $(ele).data("pojo").id) {
- option.prop("selected", "selected");
- }
- });
- });
- select.append(option);
- option.data("pojo", cur);
- });
-
- btn.after(select);
- btn.hide();
-
- select.multiselect({
- autoOpen: true,
- open: function(){
- //reposition
- $(this).multiselect("widget").css("top", $(select).next().offset().top);
- $(this).multiselect("widget").css("left", $(select).next().offset().left);
- // hide button
- $(select).next().hide();
- },
- close: function(){
- btn.show();
- select.remove();
- $(this).multiselect("destroy");
- }
- }).multiselectfilter().bind("multiselectclick multiselectcheckall multiselectuncheckall",
- function( event, ui ){
- var checkedValues = $.map($(this).multiselect("getChecked"), function( input ){
- // we only get the same "value" - so check the option list for the correct pojo
- return $("option[value='"+input.value+"']", select).data("pojo");
- });
-
- // update collection
- $.each($(select).data("collections"), function(){
- that._fillList($(this), checkedValues, fieldName);
- });
- // reposition
- btn.hide();
- $(select).next().show();
- $(this).multiselect("widget").css("top", $(select).next().offset().top);
- $(this).multiselect("widget").css("left", $(select).next().offset().left);
- $(select).next().hide();
- });
- });
- });
- });
- };
-
- /**
- * init a container that has a tempalate child (first child).
- * @param container the contianer element
- * @private
- */
- JsForm.prototype._initList = function(container) {
- // avoid double initialisation
- if(container.data("template")) {
- return;
- }
-
- // get all children
- var tmpl = container.children().detach();
-
- // remove an id if there is one
- tmpl.removeAttr("id");
- container.data("template", tmpl);
- };
-
- /**
- * clear/reset a form. The prefix is normally predefined by init
- * @param form the form
- * @param prefix the optional prefix used to identify fields for this form
- */
- JsForm.prototype._clear = function(form, prefix) {
- // get the prefix from the form if not given
- if(!prefix) {
- prefix = this.options.prefix;
- }
-
- $(form).removeData("pojo");
- $("input,select,textarea", form).each(function(){
- var name = $(this).attr("name");
- // empty name - ignore
- if (!name || name.indexOf(prefix + ".") !== 0) {
- return;
- }
- // cut away the prefix
- name = name.substring((prefix+".").length);
- // skip empty
- if(name.length < 1) {
- return;
- }
-
- // remove all pojos
- $(this).removeData("pojo");
-
- if($(this).attr("type") === "checkbox") {
- $(this).prop("checked", false);
- } else {
- $(this).val("");
- }
- if($(this).hasClass("blob")) {
- $(this).removeData("blob");
- }
- // special type select box: select the FIRST child
- if($(this).is("select")) {
- $('option[selected="selected"]', this).removeAttr('selected');
- $('option:first', this).attr('selected', true);
-
- $(this).val($("option:first", this).val()).change();
- }
- // trigger change
- $(this).change();
- });
-
- $(".collection", form).each(function() {
- var fieldname = $(this).attr("data-field");
- // only collections with the correct prefix
- if(!fieldname || fieldname.indexOf(prefix+".") !== 0) {
- return;
- }
- // get rid of all
- $(this).empty();
- });
-
- };
- /**
- * ceate a pojo from a form. Takes special data definition classes into account:
- *
- * - number|currency: the content will be transformed into a number (default string
- * - transient: will be ignored
- * - prefix.fieldname.value: will create the whole object subtree
- *
- * @param start the element to start from (ie. the form or tr)
- * @param pojo the pojo to write everything to
- * @param prefix a prefix: only fields with the given prefix will be included in the pojo
- * @private
- */
- JsForm.prototype._createPojoFromInput = function (start, prefix, pojo) {
- // check if we have an "original" pojo
- var startObj = null;
- var that = this;
-
- // get it from the starting dom element
- if($(start).data("pojo")) {
- startObj = $(start).data("pojo");
- }
-
- // if we have an object, use this as base and fill the pojo
- if(startObj) {
- $.extend(true, pojo, startObj);
- }
-
- $(start).find("input,select,textarea,.jsobject").each(function(){
- var name = $(this).attr("data-name");
- if(!name) {
- name = $(this).attr("name");
- }
-
- // empty name - ignore
- if (!name) {
- return;
- }
-
- // skip grayed (=calculated) or transient fields
- if($(this).hasClass("transient")) {
- return;
- }
-
- // must start with prefix
- if(name.indexOf(prefix + ".") !== 0) {
- return;
- }
-
- $(this).trigger("validate", true);
-
- // cut away the prefix
- name = name.substring((prefix+".").length);
-
-
- var val = $(this).val();
-
- // jsobject use the pojo data
- if($(this).hasClass("jsobject")) {
- val = $(this).data("pojo");
- }
-
- // ignore empty values when skipEmpty is set
- if(that.options.skipEmpty && (!val || val === "" || val.trim() === "")) {
- return;
- }
-
- if($(this).hasClass("emptynull") && (!val || val === "" || val === "null" || val.trim() === "")) { // nullable fields do not send empty string
- val = null;
- } else if($(this).hasClass("object") || $(this).hasClass("POJO")) {
- if($("option:selected", this).data() && $("option:selected", this).data().pojo) {
- val = $("option:selected", this).data().pojo;
- } else {
- val = $(this).data("pojo");
- }
- } else if($(this).hasClass("blob")) { // file upload blob
- val = $(this).data("blob");
- } else
- // set empty numbers or dates to null
- if(val === "" && ($(this).hasClass("number") || $(this).hasClass("integer") || $(this).hasClass("dateFilter")|| $(this).hasClass("dateTimeFilter"))) {
- val = null;
- }
-
- // check for percentage: this is input / 100
- if ($(this).hasClass("percent")) {
- val = that._getNumber(val);
- if(isNaN(val)) {
- val = 0;
- } else {
- val /= 100;
- }
- }
-
- if ($(this).hasClass("number") || $(this).hasClass("integer") || $(this).hasClass("currency")) {
- val = that._getNumber(val);
- if(isNaN(val)) {
- val = 0;
- }
- }
- else if($(this).attr("type") === "checkbox" || $(this).attr("type") === "CHECKBOX") {
- val = $(this).is(':checked');
- }
- else if($(this).hasClass("bool")) {
- val = ($(this).val() === "true");
- }
-
- // handle simple collection
- if(name.length < 1) {
- pojo = val;
- return false;
- }
-
- // check if we have a . - if so split
- if (name.indexOf(".") === -1)
- {
- pojo[name] = val;
- }
- else
- {
- var parts = name.split(".");
-
- var d0 = pojo[parts[0]];
- var d1, d2;
-
- // multiple parts: make sure its an object
- if (!d0 || !$.isPlainObject(d0)) {
- pojo[parts[0]] = {};
- d0 = pojo[parts[0]];
- }
-
- if (parts.length === 2) {
- d0[parts[1]] = val;
- } else if (parts.length === 3) {
- d1 = d0[parts[1]];
- if(d1 === undefined) {
- d1 = {};
- d0[parts[1]] = d1;
- }
- d1[parts[2]] = val;
- } else if (parts.length === 4)
- {
- d1 = d0[parts[1]];
- d2 = d1[parts[2]];
- if(d2 === undefined) {
- d2 = {};
- d1[parts[2]] = d2;
- }
- d1[parts[2]] = val;
- d2[parts[3]] = val;
- }
- // more should not be necessary
- }
- });
-
- return pojo;
- };
-
-
- /**
- * fill a dom subtree with data.
- *
- * - <span class="field">prefix.fieldname</span>
- *
- <input name="prefix.fieldname"/>
- *
- <a class="field" href="prefix.fieldname">linktest</a>
- *
- <img class="field" src="prefix.fieldname"/>
- *
- * @param parent the root of the subtree
- * @param data the data
- * @param prefix the prefix used to find fields
- * @param idx the index - this is only used for collections
- * @private
- */
- JsForm.prototype._fillData = function (parent, data, prefix, idx) {
- var that = this;
- var $parent = $(parent);
-
- // locate all "fields"
- $parent.find(".field").each(function() {
- var name = $(this).data("name");
- if(!name) {
- if(this.nodeName.toUpperCase() === 'A') {
- name = $(this).attr("href");
- $(this).attr("href", "#");
- }else if(this.nodeName.toUpperCase() === 'IMG') {
- name = $(this).attr("src");
- if(name.indexOf("#") === 0) {
- name = name.substring(1);
- }
- $(this).attr("src", "#");
- }else {
- name = $(this).text();
- }
- $(this).data("name", name);
- $(this).show();
- }
-
- if(!prefix || name.indexOf(prefix + ".") >= 0) {
- var cname = name;
- if (prefix) {
- cname = cname.substring(prefix.length + 1);
- }
- var cdata = that._get(data, cname, false, idx);
-
- if(!cdata) {
- cdata = "";
- }
-
- // check for percentage: this is value * 100
- if ($(this).hasClass("percent") && !isNaN(cdata)) {
- cdata = 100 * Number(cdata);
- }
-
- // format the string
- if($.jsFormControls)
- cdata = $.jsFormControls.Format.format(this, cdata);
-
- if(this.nodeName.toUpperCase() === 'A') {
- $(this).attr("href", cdata);
- } else if(this.nodeName.toUpperCase() === 'IMG') {
- $(this).attr("src", cdata);
- }
- else if(this.nodeName.toUpperCase() === "DIV"){
- $(this).html(cdata);
- } else {
- $(this).text(cdata);
- }
- }
- });
-
- $("input, textarea", $parent).each(function() {
- var name = $(this).attr("name");
- if(!name) {
- return;
- }
-
- // ignore file inputs - they cannot be "prefilled"
- if($(this).attr("type") == "file") {
- return;
- }
-
- if(!prefix || name.indexOf(prefix + ".") >= 0) {
- var cname = name;
- if (prefix) {
- cname = cname.substring(prefix.length + 1);
- }
-
- var cdata = that._get(data, cname, false, idx);
-
- // check for percentage: this is value * 100
- if ($(this).hasClass("percent") && !isNaN(cdata)) {
- cdata = 100 * Number(cdata);
- } else if ($(this).hasClass("object")) {
- $(this).data().pojo = cdata;
- $(this).addClass("POJO");
- if($(this).attr("data-display")) {
- cdata = that._renderObject(cdata, $(this).attr("data-display"));
- }
- } else if($.isPlainObject(cdata)) {
- $(this).data().pojo = cdata;
- $(this).addClass("POJO");
- cdata = that._renderObject(cdata, $(this).attr("data-display"));
- }
-
-
- if($(this).attr("type") === "checkbox") {
- $(this).prop("checked", (cdata === true || cdata === "true"));
- } else {
- if(!cdata) {
- cdata = "";
- }
-
- // format the string
- if($.jsFormControls)
- cdata = $.jsFormControls.Format.format(this, cdata);
-
- $(this).val(cdata);
- }
-
- $(this).change();
- $(this).trigger("fill");
- }
- });
-
- $("select", $parent).each(function() {
- var name = $(this).attr("name");
- if(!name) {
- return;
- }
-
- if(!prefix || name.indexOf(prefix + ".") >= 0) {
- var cname = name;
- if (prefix) {
- cname = cname.substring(prefix.length + 1);
- }
- // remove "old" selected options
- $(this).children("option").removeProp("selected");
- var pk = $(this).attr("data-key");
- if(!pk) {
- pk = "id";
- }
-
- var value = that._get(data, cname, false, idx);
- // try selecting based on the id
- if (value[pk] || !isNaN(value[pk])) {
- $(this).children("option[value='"+value[pk]+"']").prop("selected", "selected");
- // actually set the value and trigger the change
- $(this).val(value[pk]).change();
- return;
- } else if($(this).hasClass("bool")) {
- value = value ? "true" : "false";
- }
-
- $(this).children("option[value='"+value+"']").prop("selected", "selected");
- $(this).val(value).change();
- $(this).trigger("fill");
- }
- });
- };
-
- /**
- * ceate a pojo from a form. Takes special data definition classes into account:
- *
- * - number: the content will be transformed into a number (default string
- * - trueFalse: boolean
- *
- collection: existing collections are replaced if "class=collection" elements exist
- *
- * @param ignoreInvalid return a pojo, even if fields do not pass client side validation
- * @return a new pojo
- */
- JsForm.prototype.get = function(ignoreInvalid) {
- var form = $(this.element);
- var that = this;
- var originalPojo = this.options.data;
- var prefix = this.options.prefix;
-
- // get the pojo
- var pojo = {};
- if(originalPojo && $.isPlainObject(originalPojo)) {
- pojo = originalPojo;
- }
-
- // fill the base
- that._createPojoFromInput(form, prefix, pojo);
-
- // check for invalid fields
- var invalid = false;
- if(!this.options.validateHidden) {
- form.find(".invalid").filter(":visible").each(function(){
- invalid = true;
- $(this).focus();
- if(!ignoreInvalid) {
- that._debug("Found invalid field: " + $(this).attr("name"));
- }
- return false;
- });
- } else {
- form.find(".invalid").each(function(){
- invalid = true;
- $(this).focus();
- return false;
- });
- }
-
- // get the collection
- if(this._getCollection(form, prefix, pojo, ignoreInvalid)) {
- invalid = true;
- }
-
- if(!ignoreInvalid && invalid) {
- return null;
- }
-
- return pojo;
- };
-
- /**
- * fill a pojo based on collections
- * @param form {DOMElement} the base element to start looking for collections
- * @param prefix {string} the prefix used
- * @param pojo {object} the object to fill
- * @param ignoreInvalid {boolean} if true the function will return as soon as an invalid field is found
- * @return true if the colelction encountered an invalid field
- */
- JsForm.prototype._getCollection = function(form, prefix, pojo, ignoreInvalid) {
- var that = this;
- // check for invalid fields
- var invalid = false;
-
- form.find(".collection").each(function() {
- if(!ignoreInvalid && invalid) {
- return;
- }
-
- var fieldname = $(this).attr("data-field");
- // only collections with the correct prefix
- if(!fieldname || fieldname.indexOf(prefix+".") !== 0) {
- return;
- }
-
- fieldname = fieldname.substring((prefix+".").length);
- if(fieldname.length < 1) {
- return;
- }
-
- var colParent = that._getParent(pojo, fieldname, true);
-
- // get only the last part
- if(fieldname.indexOf('.') !== -1) {
- fieldname = fieldname.substring(fieldname.lastIndexOf('.') + 1);
- }
-
- // clear the collection
- colParent[fieldname] = [];
-
- // go through all direct childs - each one is an element
- $(this).children().each(function(){
- if(!ignoreInvalid && invalid) {
- return;
- }
-
- var ele = {};
- ele = that._createPojoFromInput($(this), fieldname, ele);
-
- // also collect sub-collections
- that._getCollection($(this), fieldname, ele, ignoreInvalid);
-
- // check if the pojo is empty
- if(!that._isEmpty(ele)) {
- if($(".invalid", this).length > 0) {
- invalid = true;
- }
- colParent[fieldname].push(ele);
- } else {
- $(".invalid", this).removeClass("invalid");
- }
- });
- });
-
- return invalid;
- };
-
- /**
- * Get the data object used as a base for get().
- * Note that modifying this directly migh result into unwanted results
- * when working with some functions that rely on this object.
- *
- * @returns the original data object
- */
- JsForm.prototype.getData = function() {
- // make srue we do have an object to work with
- if(!this.options.data) {
- this.options.data = {};
- }
- return this.options.data;
- };
-
- /**
- * uses form element and replaces them with "spans" that contain the actual content.
- * the original "inputs" are hidden
- * @param form the form
- * @param enable true: switch inputs with spans, false: switch spans back, undefined: toggle
- */
- JsForm.prototype.preventEditing = function(prevent) {
- var $this = $(this.element);
-
- if(typeof prevent === "undefined") {
- // get the disable from the form itself
- prevent = $this.data("disabled")?false:true;
- } else {
- // already in that state
- if(prevent === $this.data("disabled")) {
- return;
- }
- }
-
- if (prevent)
- {
- $this.find("input, textarea").each(function() {
- if ($(this).closest("span.form")[0])
- return;
- if($(this).attr("type") == "hidden")
- return;
- var val = $(this).val();
- if (val === "null" || val === null || $(this).attr("type") === "submit")
- val = "";
- if($(this).hasClass("trueFalse")) {
- if($(this).is(':checked'))
- val = 'X';
- else
- val = ' ';
- }
-
- // convert \n to brs - escape all other html
- val = val.replace(//g, ">").replace(/\n/g, "
");
- var thespan = $(''+val+'');
- if($(this).parent().hasClass("ui-wrapper"))
- $(this).parent().hide().wrap(thespan);
- else
- $(this).hide().wrap(thespan);
- });
- // selects are handled slightly different
- $this.find("select").each(function() {
- if ($(this).closest("span.form")[0])
- return;
-
- var val = $(this).children(":selected").html();
- if (val === "null" || val === null)
- val = "";
-
- var thespan = $(''+val+'');
-
- // toggle switches work a little different
- if($(this).hasClass("ui-toggle-switch")) {
- $(this).prev().hide().wrap(thespan);
- }
- else {
- $(this).hide().wrap(thespan);
- }
- });
- }
- else
- {
- $this.find("span.form").each(function() {
- // remove text and then unwrap
- var ele = $(this).children("input,select,textarea,.ui-wrapper,.ui-toggle-switch").show().detach();
- $(this).before(ele);
- $(this).remove();
- });
- }
-
- $this.data("disabled", prevent);
- };
-
- /**
- * validate a given form
- * @return true if the form has no invalid fields, false otherwise
- */
- JsForm.prototype.validate = function() {
- // get the prefix from the form if not given
- //var prefix = this.options.prefix;
-
- // validation
- $(".required,.regexp,.date,.mandatory,.number,.validate,.integer", this.element).change();
-
- // check for invalid fields
- if($(".invalid", this.element).length > 0) {
- return false;
- }
-
- return true;
- };
-
- /**
- * fill a form based on a pojo.
- * @param form the form
- * @param options the options used to fill
- * @param prefix the optional prefix used to identify fields for this form
- * @private
- */
- JsForm.prototype._fill = function(form, options) {
-
- this._clear(form, options.prefix);
-
- $(form).addClass("POJO");
- $(form).data("pojo", options.data);
-
- // fill base
- this._fillData(form, options.data, options.prefix);
- this._fillCollection(form, options.data, options.prefix);
- // (re-)evaluate all conditionals
- this._evaluateConditionals(this.element, options.data);
- };
-
- /**
- * @param container the container element
- * @param data an array containing the the data
- * @param prefix a prefix for each line of data
- * @private
- */
- JsForm.prototype._fillCollection = function(container, data, prefix) {
- var that = this;
- // fill collections
- $(".collection", container).each(function() {
- var container = $(this),
- fieldname = $(this).attr("data-field");
- // only collections with the correct prefix
- if(!data || !fieldname || fieldname.indexOf(prefix+".") !== 0) {
- return;
- }
-
- // data for the collection filling
- var colData = null;
-
- var cname = fieldname;
- // remove the prefix
- if (prefix) {
- cname = cname.substring(prefix.length + 1);
- }
- colData = that._get(data, cname);
-
- if(colData) {
- // fill the collection
- that._fillList(container, colData, cname);
- }
- });
- };
-
- /**
- * @param container the container element
- * @param data an array containing the the data
- * @param prefix a prefix for each line of data
- * @param lineFunc function(line,cur) - can return false to skip the line
- * @private
- */
- JsForm.prototype._fillList = function(container, data, prefix, lineFunc) {
- var tmpl = container.data("template"),
- that = this;
- if(!tmpl) {
- return;
- }
- // clean out previous list
- container.empty();
-
- // not an array
- if(!$.isArray(data)) {
- return;
- }
-
- // cut away any prefixes - only the fieldname is used
- if(prefix.indexOf('.') !== -1) {
- prefix = prefix.substring(prefix.lastIndexOf('.')+1);
- }
-
-
- // check if we need to sort the array
- if($(container).hasClass("sort")) {
- var sortField = $(container).attr("data-sort");
- if(sortField) {
- switch($(container).attr("data-sorttype")) {
- case 'alpha':
- data.sort();
- break;
- case 'alphainsensitiv':
- data.sort(function(a,b){
- a = a[sortField];
- b = b[sortField];
- if(a) a = a.toLowerCase();
- if(b) b = b.toLowerCase();
- if(ab)
- return 1;
- return 0;
- });
- break;
- default:
- data.sort(function(a,b){
- return a[sortField] - b[sortField];
- });
- }
- // descending: reverse
- if($(container).attr("data-sortdesc")) {
- data.reverse();
- }
- }
- }
-
- if(!lineFunc) {
- if($.isFunction(prefix)) {
- lineFunc = prefix;
- prefix = null;
- }
- }
-
- for(var i = 0; i < data.length; i++) {
- var cur = data[i];
- var line = tmpl.clone(true);
- // save current line
- line.data().pojo = cur;
- line.addClass("POJO");
-
- if(lineFunc) {
- if(lineFunc(line, cur) === false) {
- continue;
- }
- }
-
- that._addCollectionControls(line);
-
- if(prefix) {
- // fill data - including the index
- that._fillData(line, cur, prefix, i+1);
- // enable collection controls
- that._initCollection(line, prefix);
- // fill with data
- that._fillCollection(line, cur, prefix);
- }
- container.append(line);
-
- }
- };
-
- /**
- * add controls into a collection entry(i.e. delete)
- * @param line the new collection
- * @private
- */
- JsForm.prototype._addCollectionControls = function(line) {
- var that = this;
-
- // enable controls on the line
- if($.jsFormControls) {
- $(line).jsFormControls();
- }
-
- $(".delete", line).click(function(){
- var ele = $(this).closest(".POJO");
- // trigger a callback
- $(this).closest(".collection").trigger("deleteCollection", [ele, $(ele).data().pojo]);
- ele.remove();
- });
- $(".sortUp", line).click(function(){
- // check if there is an up
- var ele = $(this).closest(".POJO");
- var prev = ele.prev(".POJO");
- if(prev.size() === 0) {
- // no previous element - return
- return;
- }
- ele.detach();
- prev.before(ele);
- // reorder (if possible)
- that._reorder(ele);
- });
- $(".sortDown", line).click(function(){
- // check if there is a down
- var ele = $(this).closest(".POJO");
- var next = ele.next(".POJO");
- if(next.size() === 0) {
- // no next element - return
- return;
- }
- ele.detach();
- next.after(ele);
- // reorder (if possible)
- that._reorder(ele);
- });
-
- // if collection is sortable: refresh it
- var container = $(line).closest(".collection");
- if(container.hasClass("sortable")&& $(container).sortable) {
- container.sortable("refresh");
- }
- };
-
- /**
- * Reorder a collection (actually its fields)
- * @param ele one element of the collection or the collection itself
- * @private
- */
- JsForm.prototype._reorder = function(ele) {
- if(!ele.attr("data-sort")) {
- ele = ele.closest(".collection");
- }
-
- // get the field to use for sorting
- var sortField = $(ele).attr("data-sort");
- if(!sortField || ($(ele).attr("data-sorttype") && $(ele).attr("data-sorttype") !== "number") ||
- ($(ele).attr("data-sortdesc") && $(ele).attr("data-sortdesc") !== "false")) {
- return;
- }
-
- // go through each child and get the pojo
- var prio = 0;
- $.each($(ele).children(), function(){
- var data = $(this).data("pojo");
- // no data yet - add one
- if(!data) {
- data = {};
- $(this).data("pojo", data);
- }
-
- data[sortField] = prio++;
- });
- };
-
- /**
- * render an object based on a string.
- * Note: comma is a special char and cannot be used!
- * @param obj the object
- * @param skin the string to render with (i.e. id, ":", test)
- * @private
- */
- JsForm.prototype._renderObject = function(obj, skin) {
- if(!skin || !obj)
- return "";
- var that = this;
- var ret = "";
- $.each(skin.split(","), function(){
- var val = this.trim();
- if(val.indexOf("'") === 0 || val.indexOf('"') === 0) {
- ret += val.substring(1, val.length - 1);
- } else {
- ret += that._get(obj, val);
- }
- });
- return ret;
- };
-
- /**
- * Retrieve a value from a given object by using dot-notation
- * @param obj the object to start with
- * @param expr the child to get (dot notation)
- * @param create set to true and non-existant levels will be created (always returns non-null)
- * @param idx only filles when filling collection - can be access using $idx
- * @private
- */
- JsForm.prototype._get = function(obj, expr, create, idx) {
- var ret, p, prm = "", i;
- if(typeof expr === "function") {
- return expr(obj);
- }
- if (!obj) {
- return "";
- }
- // reference the object itself
- if(expr === "")
- return obj;
-
- // reference to the index
- if(expr === "$idx")
- return idx;
-
- ret = obj[expr];
- if(!ret) {
- try {
- if(typeof expr === "string") {
- prm = expr.split('.');
- }
-
- i = prm.length;
- if(i) {
- ret = obj;
- while(ret && i--) {
- p = prm.shift();
- // create the levels
- if(create && !ret[p]) {
- ret[p] = {};
- }
- ret = ret[p];
- }
- }
- } catch(e) { /* ignore */ }
- }
- if(ret === null || ret === undefined) {
- ret = "";
- }
- // trim the return
- if(ret.trim) {
- return ret.trim();
- }
- return ret;
- };
-
- /**
- * Parse a dot notation that includes arrays
- * http://stackoverflow.com/questions/13355278/javascript-how-to-convert-json-dot-string-into-object-reference
- * @param obj
- * @param path a dot notation path to search for. Use format parent[1].child
- */
- JsForm.prototype._getValueWithArrays = function(obj, path) {
- path = path.split('.');
- var arrayPattern = /(.*)\[(\d+)\]/;
- for (var i = 1; i < path.length; i++) {
- var match = arrayPattern.exec(path[i]);
- try {
- if (match) {
- obj = obj[match[1]][parseInt(match[2], 10)];
- } else {
- obj = obj[path[i]];
- }
- } catch(e) {
- console.log(path + " " + e);
- }
- }
-
- return obj;
- };
-
- /**
- * get the "parent" object of a given dot-notation. this will not return the actual
- * element given in the dot notation but itws parent (i.e.: when using a.b.c -> it will return b)
- * @param obj the object to start with
- * @param the child to get (dot notation)
- * @param create set to true and non-existant levels will be created (always returns non-null)
- * @private
- */
- JsForm.prototype._getParent = function(obj, expr, create) {
- if(expr.indexOf('.') === -1)
- return obj;
-
- expr = expr.substring(0, expr.lastIndexOf('.'));
- return this._get(obj, expr, create);
- };
-
- /**
- * helper function to get the number of a value
- * @param num the string
- * @returns a number or null
- * @private
- */
- JsForm.prototype._getNumber = function(num) {
- if (!num) {
- return null;
- }
-
- if($.format)
- return $.format.number(num);
-
- // either we have , (for komma) or a . and at least 3 following numbers (not a round komma)
- if(num.indexOf(",") != -1 || (num.length - num.indexOf('.') > 3))
- {
- num = num.replace(/\./g, "").replace(",", ".");
- }
- return Number(num);
- };
-
- /**
- * checks if a variable is empty. This will check array, and whole objects. If a json object
- * only contains empty "elements" then it is considered as empty.
- * Empty for a number is 0/-1
- * Empty for a boolena is false
- *
- * @param pojo the pojo to check
- * @returns {Boolean} true if it is empty
- * @private
- */
- JsForm.prototype._isEmpty = function(pojo) {
- // boolean false, null, undefined
- if(!pojo) {
- return true;
- }
-
- // array
- if($.isArray(pojo)) {
- // zero length
- if(pojo.length === 0) {
- return true;
- }
-
- // check each element
- for(var i = 0; i < pojo.length; i++) {
- if(!this._isEmpty()) {
- return false;
- }
- }
- return true;
- }
- // an object
- if($.isPlainObject(pojo)) {
- if($.isEmptyObject(pojo)) {
- return true;
- }
-
- for(var f in pojo){
- if(!this._isEmpty(pojo[f])) {
- return false;
- }
- }
- return true;
- }
-
- // a number
- if(!isNaN(pojo)) {
- if (Number(pojo) === 0 || Number(pojo) === -1) {
- return true;
- }
- return false;
- }
-
- // a string
- return (pojo === "" || pojo === " ");
- };
-
- /**
- * compare a pojo with a form. Takes special data definition classes into account:
- *
- * - number|currency: the content will be transformed into a number (default string
- * - transient: will be ignored
- * - prefix.fieldname.value: will create the whole object subtree
- *
- * @param start the element to start from (ie. the form or tr)
- * @param pojo the pojo to write everything to
- * @param prefix a prefix: only fields with the given prefix will be included in the pojo
- * @private
- */
- JsForm.prototype._pojoDifferFromInput = function (start, prefix, pojo) {
- var differs = false;
- $("input,select,textarea", start).each(function(){
- // skip if we found a dif
- if(differs) {
- return;
- }
-
- var name = $(this).attr("name");
- // empty name - ignore
- if (!name) {
- return;
- }
-
- // skip grayed (=calculated) or transient fields
- if($(this).hasClass("transient")) {
- return;
- }
-
- // must start with prefix
- if(name.indexOf(prefix + ".") !== 0) {
- return;
- }
-
- // cut away the prefix
- name = name.substring((prefix+".").length);
-
- // skip empty
- if(name.length < 1) {
- return;
- }
-
- var val = $(this).val();
- // set empty numbers to null
- if(val === "" && ($(this).hasClass("number") || $(this).hasClass("dateFilter")|| $(this).hasClass("dateTimeFilter"))) {
- val = null;
- }
- if ($(this).hasClass("number") || $(this).hasClass("currency")) {
- val = that._getNumber(val);
- if(isNaN(val)) {
- val = 0;
- }
- }
- if($(this).attr("type") === "checkbox" || $(this).attr("type") === "CHECKBOX") {
- val = $(this).is(':checked');
- }
-
- // check if we have a . - if so split
- if (name.indexOf(".") === -1)
- {
- // the vals differ
- if(pojo[name] !== val) {
- differs = true;
- }
- }
- else
- {
- var parts = name.split(".");
-
- var d0 = pojo[parts[0]];
- var d1, d2;
-
- if (!d0) {
- differs = true;
- return;
- }
-
- if (parts.length === 2) {
- // the vals differ
- if(d0[parts[1]] !== val) {
- differs = true;
- }
- } else if (parts.length === 3) {
- d1 = d0[parts[1]];
- // the vals differ
- if(d1[parts[2]] !== val) {
- differs = true;
- }
- } else if (parts.length === 4)
- {
- d1 = d0[parts[1]];
- d2 = d1[parts[2]];
- // the vals differ
- if(d2[parts[3]] !== val) {
- differs = true;
- }
- }
- // more should not be necessary
- }
- });
- return differs;
- };
-
- /**
- * Compares a pojo with form fields
- * @param pojo the pojo to compare with
- * @return true if any change between formfields and the pojo is found
- */
- JsForm.prototype.equals = function(pojo) {
- var that = this;
- var form = this.element;
- var prefix = this.options.prefix;
-
- // check the base
- if(this._pojoDifferFromInput(form, prefix, pojo)) {
- return false;
- }
-
- var differs = false;
-
- // check for invalid fields
- if($(".invalid", form).length > 0) {
- return false;
- }
-
- $(".collection", form).each(function() {
- if(differs) {
- return;
- }
-
- var fieldname = $(this).attr("data-field");
- // only collections with the correct prefix
- if(!fieldname || fieldname.indexOf(prefix+".") !== 0) {
- return;
- }
-
- fieldname = fieldname.substring((prefix+".").length);
- if(fieldname.length < 1) {
- return;
- }
-
- var childCounter = 0;
- // go through all direct childs - each one is an element
- $(this).children().each(function(){
- if(differs) {
- return;
- }
-
- // check if we have more elements
- if(childCounter >= pojo[fieldname].length) {
- differs = true;
- return;
- }
-
- var ele = pojo[fieldname][childCounter++];
- if(that._pojoDifferFromInput($(this), fieldname, ele)) {
- differs = true;
- }
- });
-
- if(childCounter < pojo[fieldname].length) {
- differs = true;
- }
- });
-
- // we want to know if its equals -> return not
- return !differs;
- };
-
- /**
- * fill the form with data.
- *
- * - <span class="field">prefix.fieldname</span>
- *
- <input name="prefix.fieldname"/>
- *
- <a class="field" href="prefix.fieldname">linktest</a>
- *
- <img class="field" src="prefix.fieldname"/>
- *
- * @param data {object} the data
- */
- JsForm.prototype.fill = function(pojo) {
- // set the new data
- this.options.data = pojo;
- // fill everything
- this._fill(this.element, this.options);
- };
-
- /**
- * re-evaluate the conditionals in the form based on the given data.
- * if no data is given, the form is serialized
- * @param data {object} the data
- */
- JsForm.prototype.applyConditions = function(pojo) {
- // set the new data
- if(!pojo)
- pojo = this.get(true);
-
- // evaluate everything
- this._evaluateConditionals(this.element, pojo);
- };
-
- /**
- * reset a form with the last data, overwriting any changes.
- */
- JsForm.prototype.reset = function() {
- // clear first
- this.clear();
- // fill everything
- this._fill(this.element, this.options);
- };
-
- /**
- * Clear all fields in a form
- */
- JsForm.prototype.clear = function() {
- // clear first
- this._clear(this.element, this.options.prefix);
- };
-
- /**
- * destroy the jsform and its resources.
- * @private
- */
- JsForm.prototype.destroy = function( ) {
- return $(this.element).each(function(){
- $(window).unbind('.jsForm');
- $(this).removeData('jsForm');
- });
- };
-
- // init and call methods
- $.fn.jsForm = function ( method ) {
- // Method calling logic
- if ( typeof method === 'object' || ! method ) {
- return this.each(function () {
- if (!$(this).data('jsForm')) {
- $(this).data('jsForm', new JsForm( this, method ));
- }
- });
- } else {
- var args = Array.prototype.slice.call( arguments, 1 ),
- jsForm;
- // none found
- if(this.length === 0) {
- return null;
- }
- // only one - return directly
- if(this.length === 1) {
- jsForm = $(this).data('jsForm');
- if (jsForm) {
- if(method.indexOf("_") !== 0 && jsForm[method]) {
- var ret = jsForm[method].apply(jsForm, args);
- return ret;
- }
-
- $.error( 'Method ' + method + ' does not exist on jQuery.jsForm' );
- return false;
- }
- }
-
- return this.each(function () {
- jsForm = $.data(this, 'jsForm');
- if (jsForm) {
- if(method.indexOf("_") !== 0 && jsForm[method]) {
- return jsForm[method].apply(jsForm, args);
- } else {
- $.error( 'Method ' + method + ' does not exist on jQuery.jsForm' );
- return false;
- }
- }
- });
- }
- };
-
- /**
- * global jsForm function for intialisation
- */
- $.jsForm = function ( name, initFunc ) {
- var jsForms = JSFORM_MAP[name];
- // initFunc is a function -> initialize
- if($.isFunction(initFunc)) {
- // call init if already initialized
- if(jsForms) {
- $.each(jsForms, function(){
- initFunc(this, $(this.element));
- });
- }
-
- // remember for future initializations
- JSFORM_INIT_FUNCTIONS[name] = initFunc;
- } else {
- // call init if already initialized
- if(jsForms) {
- var method = initFunc;
- var args = Array.prototype.slice.call( arguments, 2 );
- $.each(portlets, function(){
- this[method].apply(this, args);
- });
- }
- }
- };
-
-})( jQuery, window );
-
-/**
- * jquery.jsForm.controls
- * ----------------------
- * UI Controls and Field validation
- * @version 1.0
- * @class
- * @author Niko Berger
- * @license MIT License GPL
- */
-;(function( $, window, undefined ){
- "use strict";
-
- var JSFORM_INIT_FUNCTIONS = {}, // remember initialization functions
- JSFORM_MAP = {}; // remember all forms
-
- /**
- * handlebars extension (+simple date format)
- */
- if(typeof Handlebars !== "undefined") {
- Handlebars.registerHelper("currency", function(data){
- if(!data)
- return "0";
- return $.jsFormControls.Format.currency(data);
- });
- Handlebars.registerHelper("dec", function(data){
- if(!data)
- return "";
- return $.jsFormControls.Format.decimal(data);
- });
- Handlebars.registerHelper("percent", function(data){
- if(!data)
- return "0";
- return $.jsFormControls.Format.decimal(data*100);
- });
- Handlebars.registerHelper("date", function(data){
- if(!data)
- return "";
- return $.jsFormControls.Format.date(data);
- });
- Handlebars.registerHelper("time", function(data){
- if(!data)
- return "";
- return $.jsFormControls.Format.time(data);
- });
- Handlebars.registerHelper("datetime", function(data){
- if(!data)
- return "";
- return $.jsFormControls.Format.dateTime(data);
- });
- Handlebars.registerHelper("dateTime", function(data){
- if(!data)
- return "";
- return $.jsFormControls.Format.dateTime(data);
- });
- Handlebars.registerHelper("timespan", function(data){
- if(!data)
- return "";
- return $.jsFormControls.Format.humanTime(data);
- });
- Handlebars.registerHelper("byte", function(data){
- if(!data)
- return "";
- return $.jsFormControls.Format.byte(data);
- });
- }
-
- function JsFormControls(element) {
- this.element = element;
-
- // init the dom functionality
- this._domInit();
- }
-
- /**
- * init the dom. This can be called multiple times.
- * this will also enable "add", "insert" and "delete" for collections
- * @private
- */
- JsFormControls.prototype._domInit = function() {
- var location = $(this.element);
-
- // validation
- // check required (this is the first check)
- location.find("input.mandatory,textarea.mandatory").on("keyup", function(){
- // check for "null" as value as well
- if($(this).val().length > 0 && $(this).val() !== "null") {
- $(this).addClass("valid").removeClass("invalid");
- } else {
- $(this).removeClass("valid").addClass("invalid");
- }
- });
-
- location.find("input.mandatory,textarea.mandatory").on("change", function(){
- if($(this).hasClass("object")) {
- if($(this).data().pojo) {
- $(this).addClass("valid").removeClass("invalid");
- } else {
- $(this).removeClass("valid").addClass("invalid");
- }
- return;
- }
- // check for "null" as value as well
- if($(this).val().length > 0 && $(this).val() !== "null") {
- $(this).addClass("valid").removeClass("invalid");
- } else {
- $(this).removeClass("valid").addClass("invalid");
- }
- }).change();
-
- location.find("select.mandatory").change(function(){
- // check for "null" as value as well
- if($(this).val() !== null && $(this).val() !== "null" && $(this).val().length > 0) {
- $(this).addClass("valid").removeClass("invalid");
- } else {
- $(this).removeClass("valid").addClass("invalid");
- }
- }).change();
-
- // show datepicker for all inputs
- location.find("input.date").each(function(){
- var format = $(this).attr("data-format");
- // only if jquery ui is available
- if($(this).datepicker) {
- if(format)
- $(this).datepicker({dateFormat: format});
- else
- $(this).datepicker();
- }
- });
-
-
- // input validation (number)
- var numberRegexp = new RegExp("^[0-9.,-]+$");
- location.find("input.number").keyup(function(){
- var val = $(this).val();
- if(val.length > 0) {
- if($(this).hasClass("autoclean")) {
- $(this).val(val.replace(/[^0-9.,-]/g, ""));
- }
- else {
- if(numberRegexp.test($(this).val())) {
- $(this).addClass("valid").removeClass("invalid");
- } else {
- $(this).removeClass("valid").addClass("invalid");
- }
- }
- }
- }).keyup();
-
- var integerRegexp = new RegExp("^[0-9]+$");
- location.find("input.integer").keyup(function(){
- var val = $(this).val();
- if(val.length > 0) {
- if($(this).hasClass("autoclean")) {
- $(this).val(val.replace(/[^0-9]/g, ""));
- }
- else {
- if(integerRegexp.test($(this).val())) {
- $(this).addClass("valid").removeClass("invalid");
- } else {
- $(this).removeClass("valid").addClass("invalid");
- }
- }
- }
- }).keyup();
-
- // regular expression
- location.find("input.regexp").each(function(){
- if($(this).hasClass("autoclean")) {
- $(this).data("regexp", new RegExp($(this).attr("data-regexp"), "g"));
- }
- else {
- $(this).data("regexp", new RegExp($(this).attr("data-regexp")));
- }
-
- $(this).keyup(function(){
- var val = $(this).val();
- if(val.length > 0) {
- var regexp = $(this).data("regexp");
- if($(this).hasClass("autoclean")) {
- $(this).val(val.replace(regexp, ""));
- }
- else {
- if(regexp.test($(this).val())) {
- $(this).addClass("valid").removeClass("invalid");
- } else {
- $(this).removeClass("valid").addClass("invalid");
- }
- }
- } else {
- // if not mandatory: nothing is valid
- if(!$(this).hasClass("mandatory")) {
- $(this).removeClass("invalid").addClass("valid");
- }
- }
- }).keyup();
- $(this).change(function(){
- $(this).keyup();
- });
- });
-
- /* rotatestate stontrol */
- location.find("input.rotatestate").each(function(){
- var states = $(this).attr("data-state-values");
- var defaultClass = $(this).attr("data-state-class");
- // no need to continue if there are no states
- if(!states) {
- return;
- }
-
- try {
- states = JSON.parse(states);
- } catch (ex) {
- // do not need to continue if we cannot parse the states
- return;
- }
-
- var stateControl = $("");
- if($(this).attr("title")) {
- stateControl.attr("title", $(this).attr("title"));
- }
- if($(this).attr("data-state-style")) {
- stateControl.attr("style", $(this).attr("data-state-style"));
- }
- stateControl.data("states", states);
- stateControl.data("control", this);
- stateControl.data("activeState", null);
- $(this).data("control", stateControl);
- if(defaultClass) {
- stateControl.addClass(defaultClass);
- }
-
- // click on the control starts rotating
- stateControl.click(function(){
- var cState = $(this).data().activeState;
- var cStates = $(this).data().states;
- var control = $(this).data().control;
- var newState = null;
-
- if(cState !== null) {
- // go to the 'next' state
- for(var i = 0; i < cStates.length; i++) {
- if(cStates[i].value === cState.value) {
- // last element
- if(i === cStates.length - 1) {
- newState = cStates[0];
- } else {
- newState = cStates[i+1];
- }
- break;
- }
- }
- } else {
- // no state yet - set the first entry as state
- newState = cStates[0];
- }
-
- $(control).attr("value", newState.value);
- // trigger change
- $(control).change();
- });
-
- // make sure to update state if the value is changed
- $(this).change(function(){
- var control = $($(this).data().control);
- var cState = control.data().activeState;
- var cStates = control.data().states;
-
- if(cState !== null) {
- // remove "old state"
- control.removeClass(cState['class']);
- }
-
- // add new State
- var val = $(this).val();
- $.each(cStates, function(){
- if(this.value === val) {
- control.data().activeState = this;
- if(this.title) {
- control.attr("title", this.title);
- }
- control.addClass(this['class']);
- return false;
- }
- });
- });
-
- // trigger initial state
- $(this).change();
- $(this).after(stateControl);
- $(this).hide();
- });
- };
-
-
- /**
- * validate a given form
- * @return true if the form has no invalid fields, false otherwise
- */
- JsFormControls.prototype.validate = function() {
- // validation
- $(".required,.regexp,.date,.mandatory,.number,.validate", this.element).change();
-
- // check for invalid fields
- if($(".invalid", this.element).length > 0) {
- return false;
- }
-
- return true;
- };
-
- // init and call methods
- $.fn.jsFormControls = function ( method ) {
- // Method calling logic
- if ( typeof method === 'object' || ! method ) {
- return this.each(function () {
- if (!$(this).data('jsFormControls')) {
- $(this).data('jsFormControls', new JsFormControls( this, method ));
- }
- });
- } else {
- var args = Array.prototype.slice.call( arguments, 1 );
-
- // only one - return directly
- if(this.length == 1) {
- var jsFormControls = $(this).data('jsFormControls');
- if (jsFormControls) {
- if(method.indexOf("_") !== 0 && jsFormControls[method]) {
- var ret = jsFormControls[method].apply(jsFormControls, args);
- return ret;
- }
-
- $.error( 'Method ' + method + ' does not exist on jQuery.jsFormControls' );
- return false;
- }
- }
-
- return this.each(function () {
- var jsFormControls = $.data(this, 'jsFormControls');
- if (jsFormControls) {
- if(method.indexOf("_") !== 0 && jsFormControls[method]) {
- return jsFormControls[method].apply(jsFormControls, args);
- } else {
- $.error( 'Method ' + method + ' does not exist on jQuery.jsFormControls' );
- return false;
- }
- }
- });
- }
- };
-
- /**
- * global jsForm function for intialisation
- */
- $.jsFormControls = function ( name, initFunc ) {
- var jsForms;
- // initFunc is a function -> initialize
- if($.isFunction(initFunc)) {
- // call init if already initialized
- jsForms = JSFORM_MAP[name];
- if(jsForms) {
- $.each(jsForms, function(){
- initFunc(this, $(this.element));
- });
- }
-
- // remember for future initializations
- JSFORM_INIT_FUNCTIONS[name] = initFunc;
- } else {
- // call init if already initialized
- jsForms = JSFORM_MAP[name];
- if(jsForms) {
- var method = initFunc;
- var args = Array.prototype.slice.call( arguments, 2 );
- $.each(portlets, function(){
- this[method].apply(this, args);
- });
- }
- }
- };
-
- $.jsFormControls.Format = {
- /**
- * format a string based on teh classes in a dom element
- */
- format: function(ele, cdata) {
- if($(ele).hasClass("dateTime")) {
- if(isNaN(cdata))
- return cdata;
- return $.jsFormControls.Format.dateTime(cdata);
- } if($(ele).hasClass("datetime")) {
- if(isNaN(cdata))
- return cdata;
- return $.jsFormControls.Format.dateTime(cdata);
- } else if($(ele).hasClass("date")) {
- if(isNaN(cdata))
- return cdata;
- return $.jsFormControls.Format.date(cdata);
- } else if($(ele).hasClass("currency")) {
- return $.jsFormControls.Format.currency(cdata);
- } else if($(ele).hasClass("byte")) {
- if(isNaN(cdata))
- return cdata;
- return $.jsFormControls.Format.byte(cdata);
- } else if($(ele).hasClass("number")) {
- return $.jsFormControls.Format.decimal(cdata);
- }
-
- return cdata;
- },
-
- /**
- * format boolean into an ui-icon
- * @param value true or false
- * @returns the ui-icon span
- */
- checkBox: function(row, cell, value, columnDef, dataContext) {
- // cleanup parameters (direct call vs. slickgrid)
- if(typeof value === "undefined") {
- value = row;
- row = null;
- }
-
- if(value) {
- return ' ';
- } else {
- return ' ';
- }
-
- return value;
- },
-
-
- /**
- * @private
- */
- _getNumber: function(num) {
- if (!num) {
- return null;
- }
-
- if($.format)
- return $.format.number(num);
-
- // either we have , (for komma) or a . and at least 3 following numbers (not a rounden komma)
- if(num.indexOf(",") !== -1 || (num.length - num.indexOf('.') > 3))
- {
- num = num.replace(/\./g, "").replace(",", ".");
- }
- return Number(num);
- },
-
-
- /**
- * @private
- */
- _pad: function(val) {
- var o = (val < 10) ? "0" : "";
- o += val;
- return o;
- },
-
-
- byte: function(bytes) {
- if (bytes === "" || !bytes || isNaN(bytes)) {
- return bytes;
- }
-
- var unit = 1024;
- if (bytes < unit) return bytes + " B";
- var exp = Math.floor(Math.log(bytes) / Math.log(unit));
- var pre = "KMGTPE".charAt(exp-1) + "B";
- return Math.round(bytes*10 / Math.pow(unit, exp))/10 + pre;
- },
-
- /**
- * @private
- */
- decimal: function(num) {
- if (num === "" || !num || isNaN(num)) {
- return num;
- }
-
- // default number format
- var numberformat = {
- format: "#,##0.###",
- groupingSeparator: ",",
- decimalSeparator: "."
- };
-
- if(typeof i18n !== "undefined")
- numberformat = i18n.number;
- if(typeof $(document).data().i18n !== "undefined")
- numberformat = $(document).data().i18n.number;
-
- if($.format && numberformat) {
- return $.format.number(num, numberformat);
- }
-
- var comma = 0;
- if (Math.abs(num - Math.floor(num)) > 0.001) {
- comma = 2;
- }
- // convert to a nice number for display
- var n = num,
- c = isNaN(c = Math.abs(comma)) ? 2 : comma,
- d = numberformat.decimalSeparator, // decimal d == undefined ? "," : d,
- t = numberformat.groupingSeparator, // thousand: t == undefined ? "." : t,
- i = parseInt(n = Math.abs( +n || 0).toFixed(c), 10) + "",
- j = (j = i.length) > 3 ? j % 3 : 0;
- return (num<0 ? "-" : "") + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
- },
-
-
- /**
- * @private
- */
- currency: function(row, cell, cellvalue, columnDef, dataContext) {
- // cleanup parameters (direct call vs. slickgrid)
- if(!cellvalue || isNaN(cellvalue)) {
- cellvalue = row;
- row = null;
- }
-
- if(!cellvalue) {
- if(cell) {
- return " ";
- }
- return "";
- }
-
- return $.jsFormControls.Format.decimal(cellvalue);
- },
-
- /**
- * @private
- */
- dateTime: function(row, cell, cellvalue, columnDef, dataContext) {
- // cleanup parameters (direct call vs. slickgrid)
- if(!cellvalue || isNaN(cellvalue)) {
- cellvalue = row;
- row = null;
- }
-
- if(!cellvalue) {
- if(cell) {
- return " ";
- }
- return "";
- }
-
- return (this.date(cellvalue) + " " + this.time(cellvalue));
- },
-
- /**
- * @private
- */
- date: function(row, cell, cellvalue, columnDef, dataContext) {
-
- // cleanup parameters (direct call vs. slickgrid)
- if(!cellvalue || isNaN(cellvalue)) {
- cellvalue = row;
- row = null;
- }
-
- if(!cellvalue) {
- if(cell) {
- return " ";
- }
- return "";
- }
-
- var d = new Date();
- d.setTime(cellvalue);
- var year = d.getYear();
- if(year < 1900) {
- year += 1900;
- }
-
- // default number format
- var dateformat = null;
-
- if(typeof i18n !== "undefined")
- dateformat = i18n.date;
- if(typeof $(document).data().i18n !== "undefined")
- dateformat = $(document).data().i18n.date;
-
- if($.format)
- return $.format.date(d, dateformat.shortDateFormat);
- else
- return this._pad(d.getDate()) + "." + this._pad((d.getMonth()+1)) + "." + this._pad(year);
- },
-
- /**
- * @private
- */
- time: function(row, cell, value, columnDef, dataContext) {
- // cleanup parameters (direct call vs. slickgrid)
- if(!value) {
- value = row;
- row = null;
- }
-
- if(!value) {
- if(cell) {
- return " ";
- }
- return "";
- }
-
- var d = new Date();
- d.setTime(value);
- if($.format)
- return $.format.date(d, $(document).data().i18n.date.timeFormat);
- else
- return this._pad(d.getHours()) + ":" + this._pad(d.getMinutes()); // + ":" + pad(d.getSeconds()); don't need seconds
- },
-
- /**
- *
- * @param value a string value to format
- * @param allowms true to allow komma (i.e. 00.00)
- * @return something in the form of 00:00.00
- * @private
- */
- timespan: function(row, cell, value, columnDef, dataContext, allowcomma) {
- // cleanup parameters (direct call vs. slickgrid)
- if(!value) {
- value = row;
- allowcomma = cell;
- row = null;
- cell = null;
- }
-
- var tokens = value.split(":");
- // check each token
- for(var i=0; i 0) {
- out += h + "h ";
- // ignore seconds and milliseconds if we have hours
- s = 0;
- value = 0;
- }
- if (m > 0) {
- out += m + "m ";
- // ignore milliseconds
- value = 0;
- }
- if (s > 0) {
- out += s + "s ";
- value = 0;
- }
-
- if (value > 0) {
- out += value + "ms";
- }
- // trim output
- return out.trim();
- }
- };
-
-})( jQuery, window );
-
-
-/**
- * @returns the trimmed string
- */
-String.prototype.trim = function() {
- return this.replace(/^\s+|\s+$/g, "");
-};
-
-/* check start of a string */
-String.prototype.startsWith = function(str) {
- if((this === null) || (this.length <= 0))
- return false;
- if((str === null) || (str == "null") || (str.length <= 0))
- return false;
- if(this.substr(0, str.length) == str)
- return true;
- return false;
-};
-
-/* check start of a string */
-String.prototype.startsWithIgnoreCase = function(str) {
- if((this === null) || (this.length <= 0))
- return false;
- if((str === null) || (str == "null") || (str.length <= 0))
- return false;
- if(this.substr(0, str.length).toLowerCase() == str.toLowerCase())
- return true;
- return false;
-};
-
-/* check end of a string */
-String.prototype.endsWith = function(str) {
- if((this === null) || (this.length <= 0))
- return false;
- if((str === null) || (str == "null") || (str.length <= 0) || (str.length > this.length))
- return false;
- if(this.substr(this.length - str.length) == str)
- return true;
- return false;
-};
\ No newline at end of file
diff --git a/dist/jquery.jsForm.1.1.0.min.js b/dist/jquery.jsForm.1.1.0.min.js
deleted file mode 100644
index 330d591..0000000
--- a/dist/jquery.jsForm.1.1.0.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*!
- * jQuery.jsForm v1.1.0 | (c) 2013 Niko Berger http://www.gargan.org/
- * Usage: https://github.com/corinis/jsForm
- */
-(function(t,e,a){"use strict";function i(e,a){var i=t(e);this.options=t.extend({},{controls:!0,data:null,prefix:"data",validateHidden:!0,skipEmpty:!1},a),!i.attr("data-prefix")||"data"!==this.options.prefix&&""!==this.options.prefix||""!==i.attr("data-prefix")&&(this.options.prefix=i.attr("data-prefix")),this.element=e,this._init()}var s={},n={};i.prototype._init=function(){if(this._domInit(),this.options.controls)if(t.jsFormControls)t(this.element).jsFormControls();else try{"undefined"!=typeof console&&console.log("jquery.JsForm.controls not available!")}catch(e){}this._fill(this.element,this.options)},i.prototype._domInit=function(){var e=t(this.element),a=this,i=this.options.prefix;a._initCollection(e,i),a._initConditional(e,i,this.options)},i.prototype._debug=function(t){"undefined"!=typeof console&&console.log("JsForm: "+t)},i.prototype._initConditional=function(e,a,i){var s=this,n=function(e,a,i){var n=!1;t.each(i,function(){var t=s._getValueWithArrays(a,this);if(t&&""!==t&&0!==t&&-1!==t)return n=!0,!1}),n?e.show():e.hide()},r=function(e,a,i){var n=!1;t.each(i,function(){var t=s._getValueWithArrays(a,this);if(t&&""!==t&&0!==t&&-1!==t)return n=!0,!1}),n?e.hide():e.show()};this.conditionals=t(e).find(".conditional"),this.conditionals.each(function(){t(this).data().conditionalEval=[];var e=t(this).attr("data-show");e&&e.length>0&&t(this).data().conditionalEval.push({func:n,field:e.split(" ")}),e=t(this).attr("data-hide"),e&&e.length>0&&t(this).data().conditionalEval.push({func:r,field:e.split(" ")}),e=t(this).attr("data-eval"),e&&e.length>0&&i.conditionals[e]&&t(this).data().conditionalEval.push({func:i.conditionals[e]})})},i.prototype._evaluateConditionals=function(e,a){this.conditionals.each(function(){var e=t(this);t.each(e.data().conditionalEval,function(){this.func(e,a,this.field)})})},i.prototype._initCollection=function(e,a){var i={},s=this;t(e).data().collections=i,t(".collection",e).each(function(){var e=t(this).attr("data-field");if(e&&0===e.indexOf(a+".")){var n=t(this),r=i[e];if(r?r.push(n):i[e]=[n],s._initList(n),!n.hasClass("ui-sortable")&&n.hasClass("sortable")&&n.sortable){var o=n.attr("data-sortable");o=o?JSON.parse(o):{},n.sortable(o),n.on("sortstop",function(){s._reorder(n)})}}}),t(".add",e).each(function(){var e=t(this).attr("data-field");e&&(t(this).data("collections")||(t(this).data().collections=i[e],t(this).click(function(a){a.preventDefault(),t.each(t(this).data("collections"),function(){var a=t(this).data("template");if(a){var i=a.clone(!0);t(this).append(i),t(i).addClass("POJO"),t(i).data("pojo",{}),s._addCollectionControls(i),t(this).trigger("addCollection",[i,t(i).data().pojo]);var n=t(this).children(".POJO").length;s._fillData(i,t(i).data().pojo,e.substring(e.indexOf(".")+1),n),s._initCollection(i,e.substring(e.indexOf(".")+1)),t(this).trigger("postAddCollection",[i,t(i).data().pojo])}})})))}),t(".insert",e).each(function(){var e=t(this).attr("data-field");e&&(t(this).data("collections")||(t(this).data("collections",i[t(this).attr("data-field")]),t(this).on("insert",function(a,i){if(i||(i=t(this).data().pojo),i){var n=t(this).data("beforeInsert");n&&t.isFunction(n)&&!(i=n(i))||(t.each(t(this).data("collections"),function(){var a=t(this).data("template");if(a){var n=a.clone(!0);n.addClass("POJO"),n.data().pojo=i,s._addCollectionControls(n),s._initCollection(n),t(this).trigger("addCollection",[n,t(n).data().pojo]);var r=t(this).children(".POJO").length;s._fillData(n,i,e.substring(e.indexOf(".")+1),r),t(this).append(n)}}),t(this).val(""),t(this).data().pojo=null,t(this).focus())}})))}),t(".insertAction",e).each(function(){var e=t(this).attr("data-field");if(e&&!t(this).data("inserter")){var a=t(this).parent().find(".insert");a&&(t(this).data("inserter",a),t(this).click(function(e){return e.preventDefault(),t(this).data("inserter").trigger("insert"),!1}))}}),t("input.object",e).each(function(){t(this).on("update",function(){var e=t(this).data().pojo;e&&t(this).attr("data-display")&&t(this).val(s._renderObject(e,t(this).attr("data-display")))})}),t("input.blob",e).each(function(){if("file"===t(this).attr("type")){var e=t(this);t(this).on("change",function(a){var i=t(this).val().split(/\\/).pop();e.data("name",i);var s=a.target.files;s&&s.length&&t.each(s,function(){var a=new FileReader;a.onload=function(t){e.data("blob",t.target.result)},a.readAsDataURL(this),t(this).trigger("fileChange")})})}}),t(".manage",e).each(function(){var e=t(this).attr("data-field");e&&(t(this).data("collections",i[e]),t(this).click(function(){var a=t(this).attr("data-service"),i=t(this).data("collections"),n=t(this),r=t(this).attr("data-display");r&&(r=r.split(",")),DataUtils.run(a,function(a){var o=t('');o.data("collections",i),n.data("select",o),t.each(a,function(){var e=this,a="";if(r)for(var s=0;r.length>s;s++)a+=e[r[s]]+" ";else a=e;var n=t('");t(i).each(function(){t(this).children().each(function(a,i){e.id===t(i).data("pojo").id&&n.prop("selected","selected")})}),o.append(n),n.data("pojo",e)}),n.after(o),n.hide(),o.multiselect({autoOpen:!0,open:function(){t(this).multiselect("widget").css("top",t(o).next().offset().top),t(this).multiselect("widget").css("left",t(o).next().offset().left),t(o).next().hide()},close:function(){n.show(),o.remove(),t(this).multiselect("destroy")}}).multiselectfilter().bind("multiselectclick multiselectcheckall multiselectuncheckall",function(){var a=t.map(t(this).multiselect("getChecked"),function(e){return t("option[value='"+e.value+"']",o).data("pojo")});t.each(t(o).data("collections"),function(){s._fillList(t(this),a,e)}),n.hide(),t(o).next().show(),t(this).multiselect("widget").css("top",t(o).next().offset().top),t(this).multiselect("widget").css("left",t(o).next().offset().left),t(o).next().hide()})})}))})},i.prototype._initList=function(t){if(!t.data("template")){var e=t.children().detach();e.removeAttr("id"),t.data("template",e)}},i.prototype._clear=function(e,a){a||(a=this.options.prefix),t(e).removeData("pojo"),t("input,select,textarea",e).each(function(){var e=t(this).attr("name");e&&0===e.indexOf(a+".")&&(e=e.substring((a+".").length),1>e.length||(t(this).removeData("pojo"),"checkbox"===t(this).attr("type")?t(this).prop("checked",!1):t(this).val(""),t(this).hasClass("blob")&&t(this).removeData("blob"),t(this).is("select")&&(t('option[selected="selected"]',this).removeAttr("selected"),t("option:first",this).attr("selected",!0),t(this).val(t("option:first",this).val()).change()),t(this).change()))}),t(".collection",e).each(function(){var e=t(this).attr("data-field");e&&0===e.indexOf(a+".")&&t(this).empty()})},i.prototype._createPojoFromInput=function(e,i,s){var n=null,r=this;return t(e).data("pojo")&&(n=t(e).data("pojo")),n&&t.extend(!0,s,n),t(e).find("input,select,textarea,.jsobject").each(function(){var e=t(this).attr("data-name");if(e||(e=t(this).attr("name")),e&&!t(this).hasClass("transient")&&0===e.indexOf(i+".")){t(this).trigger("validate",!0),e=e.substring((i+".").length);var n=t(this).val();if(t(this).hasClass("jsobject")&&(n=t(this).data("pojo")),!r.options.skipEmpty||n&&""!==n&&""!==n.trim()){if(!t(this).hasClass("emptynull")||n&&""!==n&&"null"!==n&&""!==n.trim()?t(this).hasClass("object")||t(this).hasClass("POJO")?n=t("option:selected",this).data()&&t("option:selected",this).data().pojo?t("option:selected",this).data().pojo:t(this).data("pojo"):t(this).hasClass("blob")?n=t(this).data("blob"):""===n&&(t(this).hasClass("number")||t(this).hasClass("integer")||t(this).hasClass("dateFilter")||t(this).hasClass("dateTimeFilter"))&&(n=null):n=null,t(this).hasClass("percent")&&(n=r._getNumber(n),isNaN(n)?n=0:n/=100),t(this).hasClass("number")||t(this).hasClass("integer")||t(this).hasClass("currency")?(n=r._getNumber(n),isNaN(n)&&(n=0)):"checkbox"===t(this).attr("type")||"CHECKBOX"===t(this).attr("type")?n=t(this).is(":checked"):t(this).hasClass("bool")&&(n="true"===t(this).val()),1>e.length)return s=n,!1;if(-1===e.indexOf("."))s[e]=n;else{var o,l,h=e.split("."),d=s[h[0]];d&&t.isPlainObject(d)||(s[h[0]]={},d=s[h[0]]),2===h.length?d[h[1]]=n:3===h.length?(o=d[h[1]],o===a&&(o={},d[h[1]]=o),o[h[2]]=n):4===h.length&&(o=d[h[1]],l=o[h[2]],l===a&&(l={},o[h[2]]=l),o[h[2]]=n,l[h[3]]=n)}}}}),s},i.prototype._fillData=function(e,i,s,n){var r=this,o=t(e);o.find(".field").each(function(){var e=t(this).data("name");if(e||("A"===this.nodeName.toUpperCase()?(e=t(this).attr("href"),t(this).attr("href","#")):"IMG"===this.nodeName.toUpperCase()?(e=t(this).attr("src"),0===e.indexOf("#")&&(e=e.substring(1)),t(this).attr("src","#")):e=t(this).text(),t(this).data("name",e),t(this).show()),!s||e.indexOf(s+".")>=0){var a=e;s&&(a=a.substring(s.length+1));var o=r._get(i,a,!1,n);o||(o=""),t(this).hasClass("percent")&&!isNaN(o)&&(o=100*Number(o)),t.jsFormControls&&(o=t.jsFormControls.Format.format(this,o)),"A"===this.nodeName.toUpperCase()?t(this).attr("href",o):"IMG"===this.nodeName.toUpperCase()?t(this).attr("src",o):"DIV"===this.nodeName.toUpperCase()?t(this).html(o):t(this).text(o)}}),t("input, textarea",o).each(function(){var e=t(this).attr("name");if(e&&"file"!=t(this).attr("type")&&(!s||e.indexOf(s+".")>=0)){var a=e;s&&(a=a.substring(s.length+1));var o=r._get(i,a,!1,n);t(this).hasClass("percent")&&!isNaN(o)?o=100*Number(o):t(this).hasClass("object")?(t(this).data().pojo=o,t(this).addClass("POJO"),t(this).attr("data-display")&&(o=r._renderObject(o,t(this).attr("data-display")))):t.isPlainObject(o)&&(t(this).data().pojo=o,t(this).addClass("POJO"),o=r._renderObject(o,t(this).attr("data-display"))),"checkbox"===t(this).attr("type")?t(this).prop("checked",o===!0||"true"===o):(o||(o=""),t.jsFormControls&&(o=t.jsFormControls.Format.format(this,o)),t(this).val(o)),t(this).change(),t(this).trigger("fill")}}),t("select",o).each(function(){var e=t(this).attr("name");if(e&&(!s||e.indexOf(s+".")>=0)){var o=e;s&&(o=o.substring(s.length+1)),t(this).children("option").removeProp("selected");var l=t(this).attr("data-key");l||(l="id");var h=r._get(i,o,!1,n);if(h[l]||!isNaN(h[l]))return t(this).children("option[value='"+h[l]+"']").prop("selected","selected"),t(this).val(h[l]).change(),a;t(this).hasClass("bool")&&(h=h?"true":"false"),t(this).children("option[value='"+h+"']").prop("selected","selected"),t(this).val(h).change(),t(this).trigger("fill")}})},i.prototype.get=function(e){var a=t(this.element),i=this,s=this.options.data,n=this.options.prefix,r={};s&&t.isPlainObject(s)&&(r=s),i._createPojoFromInput(a,n,r);var o=!1;return this.options.validateHidden?a.find(".invalid").each(function(){return o=!0,t(this).focus(),!1}):a.find(".invalid").filter(":visible").each(function(){return o=!0,t(this).focus(),e||i._debug("Found invalid field: "+t(this).attr("name")),!1}),this._getCollection(a,n,r,e)&&(o=!0),!e&&o?null:r},i.prototype._getCollection=function(e,a,i,s){var n=this,r=!1;return e.find(".collection").each(function(){if(s||!r){var e=t(this).attr("data-field");if(e&&0===e.indexOf(a+".")&&(e=e.substring((a+".").length),!(1>e.length))){var o=n._getParent(i,e,!0);-1!==e.indexOf(".")&&(e=e.substring(e.lastIndexOf(".")+1)),o[e]=[],t(this).children().each(function(){if(s||!r){var a={};a=n._createPojoFromInput(t(this),e,a),n._getCollection(t(this),e,a,s),n._isEmpty(a)?t(".invalid",this).removeClass("invalid"):(t(".invalid",this).length>0&&(r=!0),o[e].push(a))}})}}}),r},i.prototype.getData=function(){return this.options.data||(this.options.data={}),this.options.data},i.prototype.preventEditing=function(e){var i=t(this.element);if(e===a)e=i.data("disabled")?!1:!0;else if(e===i.data("disabled"))return;e?(i.find("input, textarea").each(function(){if(!t(this).closest("span.form")[0]&&"hidden"!=t(this).attr("type")){var e=t(this).val();("null"===e||null===e||"submit"===t(this).attr("type"))&&(e=""),t(this).hasClass("trueFalse")&&(e=t(this).is(":checked")?"X":" "),e=e.replace(//g,">").replace(/\n/g,"
");var a=t(''+e+"");t(this).parent().hasClass("ui-wrapper")?t(this).parent().hide().wrap(a):t(this).hide().wrap(a)}}),i.find("select").each(function(){if(!t(this).closest("span.form")[0]){var e=t(this).children(":selected").html();("null"===e||null===e)&&(e="");var a=t(''+e+"");t(this).hasClass("ui-toggle-switch")?t(this).prev().hide().wrap(a):t(this).hide().wrap(a)}})):i.find("span.form").each(function(){var e=t(this).children("input,select,textarea,.ui-wrapper,.ui-toggle-switch").show().detach();t(this).before(e),t(this).remove()}),i.data("disabled",e)},i.prototype.validate=function(){return t(".required,.regexp,.date,.mandatory,.number,.validate,.integer",this.element).change(),t(".invalid",this.element).length>0?!1:!0},i.prototype._fill=function(e,a){this._clear(e,a.prefix),t(e).addClass("POJO"),t(e).data("pojo",a.data),this._fillData(e,a.data,a.prefix),this._fillCollection(e,a.data,a.prefix),this._evaluateConditionals(this.element,a.data)},i.prototype._fillCollection=function(e,a,i){var s=this;t(".collection",e).each(function(){var e=t(this),n=t(this).attr("data-field");if(a&&n&&0===n.indexOf(i+".")){var r=null,o=n;i&&(o=o.substring(i.length+1)),r=s._get(a,o),r&&s._fillList(e,r,o)}})},i.prototype._fillList=function(e,a,i,s){var n=e.data("template"),r=this;if(n&&(e.empty(),t.isArray(a))){if(-1!==i.indexOf(".")&&(i=i.substring(i.lastIndexOf(".")+1)),t(e).hasClass("sort")){var o=t(e).attr("data-sort");if(o){switch(t(e).attr("data-sorttype")){case"alpha":a.sort();break;case"alphainsensitiv":a.sort(function(t,e){return t=t[o],e=e[o],t&&(t=t.toLowerCase()),e&&(e=e.toLowerCase()),e>t?-1:t>e?1:0});break;default:a.sort(function(t,e){return t[o]-e[o]})}t(e).attr("data-sortdesc")&&a.reverse()}}s||t.isFunction(i)&&(s=i,i=null);for(var l=0;a.length>l;l++){var h=a[l],d=n.clone(!0);d.data().pojo=h,d.addClass("POJO"),s&&s(d,h)===!1||(r._addCollectionControls(d),i&&(r._fillData(d,h,i,l+1),r._initCollection(d,i),r._fillCollection(d,h,i)),e.append(d))}}},i.prototype._addCollectionControls=function(e){var a=this;t.jsFormControls&&t(e).jsFormControls(),t(".delete",e).click(function(){var e=t(this).closest(".POJO");t(this).closest(".collection").trigger("deleteCollection",[e,t(e).data().pojo]),e.remove()}),t(".sortUp",e).click(function(){var e=t(this).closest(".POJO"),i=e.prev(".POJO");0!==i.size()&&(e.detach(),i.before(e),a._reorder(e))}),t(".sortDown",e).click(function(){var e=t(this).closest(".POJO"),i=e.next(".POJO");0!==i.size()&&(e.detach(),i.after(e),a._reorder(e))});var i=t(e).closest(".collection");i.hasClass("sortable")&&t(i).sortable&&i.sortable("refresh")},i.prototype._reorder=function(e){e.attr("data-sort")||(e=e.closest(".collection"));var a=t(e).attr("data-sort");if(!(!a||t(e).attr("data-sorttype")&&"number"!==t(e).attr("data-sorttype")||t(e).attr("data-sortdesc")&&"false"!==t(e).attr("data-sortdesc"))){var i=0;t.each(t(e).children(),function(){var e=t(this).data("pojo");e||(e={},t(this).data("pojo",e)),e[a]=i++})}},i.prototype._renderObject=function(e,a){if(!a||!e)return"";var i=this,s="";return t.each(a.split(","),function(){var t=this.trim();s+=0===t.indexOf("'")||0===t.indexOf('"')?t.substring(1,t.length-1):i._get(e,t)}),s},i.prototype._get=function(t,e,i,s){var n,r,o,l="";if("function"==typeof e)return e(t);if(!t)return"";if(""===e)return t;if("$idx"===e)return s;if(n=t[e],!n)try{if("string"==typeof e&&(l=e.split(".")),o=l.length)for(n=t;n&&o--;)r=l.shift(),i&&!n[r]&&(n[r]={}),n=n[r]}catch(h){}return(null===n||n===a)&&(n=""),n.trim?n.trim():n},i.prototype._getValueWithArrays=function(t,e){e=e.split(".");for(var a=/(.*)\[(\d+)\]/,i=1;e.length>i;i++){var s=a.exec(e[i]);try{t=s?t[s[1]][parseInt(s[2],10)]:t[e[i]]}catch(n){console.log(e+" "+n)}}return t},i.prototype._getParent=function(t,e,a){return-1===e.indexOf(".")?t:(e=e.substring(0,e.lastIndexOf(".")),this._get(t,e,a))},i.prototype._getNumber=function(e){return e?t.format?t.format.number(e):((-1!=e.indexOf(",")||e.length-e.indexOf(".")>3)&&(e=e.replace(/\./g,"").replace(",",".")),Number(e)):null},i.prototype._isEmpty=function(e){if(!e)return!0;if(t.isArray(e)){if(0===e.length)return!0;for(var a=0;e.length>a;a++)if(!this._isEmpty())return!1;return!0}if(t.isPlainObject(e)){if(t.isEmptyObject(e))return!0;for(var i in e)if(!this._isEmpty(e[i]))return!1;return!0}return isNaN(e)?""===e||" "===e:0===Number(e)||-1===Number(e)?!0:!1},i.prototype._pojoDifferFromInput=function(e,i,s){var n=!1;return t("input,select,textarea",e).each(function(){if(!n){var e=t(this).attr("name");if(e&&!(t(this).hasClass("transient")||0!==e.indexOf(i+".")||(e=e.substring((i+".").length),1>e.length))){var r=t(this).val();if(""===r&&(t(this).hasClass("number")||t(this).hasClass("dateFilter")||t(this).hasClass("dateTimeFilter"))&&(r=null),(t(this).hasClass("number")||t(this).hasClass("currency"))&&(r=that._getNumber(r),isNaN(r)&&(r=0)),("checkbox"===t(this).attr("type")||"CHECKBOX"===t(this).attr("type"))&&(r=t(this).is(":checked")),-1===e.indexOf("."))s[e]!==r&&(n=!0);else{var o,l,h=e.split("."),d=s[h[0]];if(!d)return n=!0,a;2===h.length?d[h[1]]!==r&&(n=!0):3===h.length?(o=d[h[1]],o[h[2]]!==r&&(n=!0)):4===h.length&&(o=d[h[1]],l=o[h[2]],l[h[3]]!==r&&(n=!0))}}}}),n},i.prototype.equals=function(e){var i=this,s=this.element,n=this.options.prefix;if(this._pojoDifferFromInput(s,n,e))return!1;var r=!1;return t(".invalid",s).length>0?!1:(t(".collection",s).each(function(){if(!r){var s=t(this).attr("data-field");if(s&&0===s.indexOf(n+".")&&(s=s.substring((n+".").length),!(1>s.length))){var o=0;t(this).children().each(function(){if(!r){if(o>=e[s].length)return r=!0,a;var n=e[s][o++];i._pojoDifferFromInput(t(this),s,n)&&(r=!0)}}),e[s].length>o&&(r=!0)}}}),!r)},i.prototype.fill=function(t){this.options.data=t,this._fill(this.element,this.options)},i.prototype.applyConditions=function(t){t||(t=this.get(!0)),this._evaluateConditionals(this.element,t)},i.prototype.reset=function(){this.clear(),this._fill(this.element,this.options)},i.prototype.clear=function(){this._clear(this.element,this.options.prefix)},i.prototype.destroy=function(){return t(this.element).each(function(){t(e).unbind(".jsForm"),t(this).removeData("jsForm")})},t.fn.jsForm=function(e){if("object"!=typeof e&&e){var s,n=Array.prototype.slice.call(arguments,1);if(0===this.length)return null;if(1===this.length&&(s=t(this).data("jsForm"))){if(0!==e.indexOf("_")&&s[e]){var r=s[e].apply(s,n);return r}return t.error("Method "+e+" does not exist on jQuery.jsForm"),!1}return this.each(function(){return s=t.data(this,"jsForm"),s?0!==e.indexOf("_")&&s[e]?s[e].apply(s,n):(t.error("Method "+e+" does not exist on jQuery.jsForm"),!1):a})}return this.each(function(){t(this).data("jsForm")||t(this).data("jsForm",new i(this,e))})},t.jsForm=function(e,a){var i=n[e];if(t.isFunction(a))i&&t.each(i,function(){a(this,t(this.element))}),s[e]=a;else if(i){var r=a,o=Array.prototype.slice.call(arguments,2);t.each(portlets,function(){this[r].apply(this,o)})}}})(jQuery,window),function(t){"use strict";function e(t){this.element=t,this._domInit()}var a={},i={};"undefined"!=typeof Handlebars&&(Handlebars.registerHelper("currency",function(e){return e?t.jsFormControls.Format.currency(e):"0"}),Handlebars.registerHelper("dec",function(e){return e?t.jsFormControls.Format.decimal(e):""}),Handlebars.registerHelper("percent",function(e){return e?t.jsFormControls.Format.decimal(100*e):"0"}),Handlebars.registerHelper("date",function(e){return e?t.jsFormControls.Format.date(e):""}),Handlebars.registerHelper("time",function(e){return e?t.jsFormControls.Format.time(e):""}),Handlebars.registerHelper("datetime",function(e){return e?t.jsFormControls.Format.dateTime(e):""}),Handlebars.registerHelper("dateTime",function(e){return e?t.jsFormControls.Format.dateTime(e):""}),Handlebars.registerHelper("timespan",function(e){return e?t.jsFormControls.Format.humanTime(e):""}),Handlebars.registerHelper("byte",function(e){return e?t.jsFormControls.Format.byte(e):""})),e.prototype._domInit=function(){var e=t(this.element);e.find("input.mandatory,textarea.mandatory").on("keyup",function(){t(this).val().length>0&&"null"!==t(this).val()?t(this).addClass("valid").removeClass("invalid"):t(this).removeClass("valid").addClass("invalid")}),e.find("input.mandatory,textarea.mandatory").on("change",function(){return t(this).hasClass("object")?(t(this).data().pojo?t(this).addClass("valid").removeClass("invalid"):t(this).removeClass("valid").addClass("invalid"),undefined):(t(this).val().length>0&&"null"!==t(this).val()?t(this).addClass("valid").removeClass("invalid"):t(this).removeClass("valid").addClass("invalid"),undefined)}).change(),e.find("select.mandatory").change(function(){null!==t(this).val()&&"null"!==t(this).val()&&t(this).val().length>0?t(this).addClass("valid").removeClass("invalid"):t(this).removeClass("valid").addClass("invalid")}).change(),e.find("input.date").each(function(){var e=t(this).attr("data-format");t(this).datepicker&&(e?t(this).datepicker({dateFormat:e}):t(this).datepicker())});var a=RegExp("^[0-9.,-]+$");e.find("input.number").keyup(function(){var e=t(this).val();e.length>0&&(t(this).hasClass("autoclean")?t(this).val(e.replace(/[^0-9.,-]/g,"")):a.test(t(this).val())?t(this).addClass("valid").removeClass("invalid"):t(this).removeClass("valid").addClass("invalid"))}).keyup();var i=RegExp("^[0-9]+$");e.find("input.integer").keyup(function(){var e=t(this).val();e.length>0&&(t(this).hasClass("autoclean")?t(this).val(e.replace(/[^0-9]/g,"")):i.test(t(this).val())?t(this).addClass("valid").removeClass("invalid"):t(this).removeClass("valid").addClass("invalid"))}).keyup(),e.find("input.regexp").each(function(){t(this).hasClass("autoclean")?t(this).data("regexp",RegExp(t(this).attr("data-regexp"),"g")):t(this).data("regexp",RegExp(t(this).attr("data-regexp"))),t(this).keyup(function(){var e=t(this).val();if(e.length>0){var a=t(this).data("regexp");t(this).hasClass("autoclean")?t(this).val(e.replace(a,"")):a.test(t(this).val())?t(this).addClass("valid").removeClass("invalid"):t(this).removeClass("valid").addClass("invalid")}else t(this).hasClass("mandatory")||t(this).removeClass("invalid").addClass("valid")}).keyup(),t(this).change(function(){t(this).keyup()})}),e.find("input.rotatestate").each(function(){var e=t(this).attr("data-state-values"),a=t(this).attr("data-state-class");if(e){try{e=JSON.parse(e)}catch(i){return}var s=t("");t(this).attr("title")&&s.attr("title",t(this).attr("title")),t(this).attr("data-state-style")&&s.attr("style",t(this).attr("data-state-style")),s.data("states",e),s.data("control",this),s.data("activeState",null),t(this).data("control",s),a&&s.addClass(a),s.click(function(){var e=t(this).data().activeState,a=t(this).data().states,i=t(this).data().control,s=null;if(null!==e){for(var n=0;a.length>n;n++)if(a[n].value===e.value){s=n===a.length-1?a[0]:a[n+1];break}}else s=a[0];t(i).attr("value",s.value),t(i).change()}),t(this).change(function(){var e=t(t(this).data().control),a=e.data().activeState,i=e.data().states;null!==a&&e.removeClass(a["class"]);var s=t(this).val();t.each(i,function(){return this.value===s?(e.data().activeState=this,this.title&&e.attr("title",this.title),e.addClass(this["class"]),!1):undefined})}),t(this).change(),t(this).after(s),t(this).hide()}})},e.prototype.validate=function(){return t(".required,.regexp,.date,.mandatory,.number,.validate",this.element).change(),t(".invalid",this.element).length>0?!1:!0},t.fn.jsFormControls=function(a){if("object"!=typeof a&&a){var i=Array.prototype.slice.call(arguments,1);if(1==this.length){var s=t(this).data("jsFormControls");if(s){if(0!==a.indexOf("_")&&s[a]){var n=s[a].apply(s,i);return n}return t.error("Method "+a+" does not exist on jQuery.jsFormControls"),!1}}return this.each(function(){var e=t.data(this,"jsFormControls");return e?0!==a.indexOf("_")&&e[a]?e[a].apply(e,i):(t.error("Method "+a+" does not exist on jQuery.jsFormControls"),!1):undefined})}return this.each(function(){t(this).data("jsFormControls")||t(this).data("jsFormControls",new e(this,a))})},t.jsFormControls=function(e,s){var n;if(t.isFunction(s))n=i[e],n&&t.each(n,function(){s(this,t(this.element))}),a[e]=s;else if(n=i[e]){var r=s,o=Array.prototype.slice.call(arguments,2);t.each(portlets,function(){this[r].apply(this,o)})}},t.jsFormControls.Format={format:function(e,a){return t(e).hasClass("dateTime")?isNaN(a)?a:t.jsFormControls.Format.dateTime(a):t(e).hasClass("datetime")?isNaN(a)?a:t.jsFormControls.Format.dateTime(a):t(e).hasClass("date")?isNaN(a)?a:t.jsFormControls.Format.date(a):t(e).hasClass("currency")?t.jsFormControls.Format.currency(a):t(e).hasClass("byte")?isNaN(a)?a:t.jsFormControls.Format.byte(a):t(e).hasClass("number")?t.jsFormControls.Format.decimal(a):a},checkBox:function(t,e,a){return a===undefined&&(a=t,t=null),a?' ':' '},_getNumber:function(e){return e?t.format?t.format.number(e):((-1!==e.indexOf(",")||e.length-e.indexOf(".")>3)&&(e=e.replace(/\./g,"").replace(",",".")),Number(e)):null},_pad:function(t){var e=10>t?"0":"";return e+=t},"byte":function(t){if(""===t||!t||isNaN(t))return t;var e=1024;if(e>t)return t+" B";var a=Math.floor(Math.log(t)/Math.log(e)),i="KMGTPE".charAt(a-1)+"B";return Math.round(10*t/Math.pow(e,a))/10+i},decimal:function(e){if(""===e||!e||isNaN(e))return e;var a={format:"#,##0.###",groupingSeparator:",",decimalSeparator:"."};if("undefined"!=typeof i18n&&(a=i18n.number),t(document).data().i18n!==undefined&&(a=t(document).data().i18n.number),t.format&&a)return t.format.number(e,a);var i=0;Math.abs(e-Math.floor(e))>.001&&(i=2);var s=e,n=isNaN(n=Math.abs(i))?2:i,r=a.decimalSeparator,o=a.groupingSeparator,l=parseInt(s=Math.abs(+s||0).toFixed(n),10)+"",h=(h=l.length)>3?h%3:0;return(0>e?"-":"")+(h?l.substr(0,h)+o:"")+l.substr(h).replace(/(\d{3})(?=\d)/g,"$1"+o)+(n?r+Math.abs(s-l).toFixed(n).slice(2):"")},currency:function(e,a,i){return(!i||isNaN(i))&&(i=e,e=null),i?t.jsFormControls.Format.decimal(i):a?" ":""},dateTime:function(t,e,a){return(!a||isNaN(a))&&(a=t,t=null),a?this.date(a)+" "+this.time(a):e?" ":""},date:function(e,a,i){if((!i||isNaN(i))&&(i=e,e=null),!i)return a?" ":"";var s=new Date;s.setTime(i);var n=s.getYear();1900>n&&(n+=1900);var r=null;return"undefined"!=typeof i18n&&(r=i18n.date),t(document).data().i18n!==undefined&&(r=t(document).data().i18n.date),t.format?t.format.date(s,r.shortDateFormat):this._pad(s.getDate())+"."+this._pad(s.getMonth()+1)+"."+this._pad(n)},time:function(e,a,i){if(i||(i=e,e=null),!i)return a?" ":"";var s=new Date;return s.setTime(i),t.format?t.format.date(s,t(document).data().i18n.date.timeFormat):this._pad(s.getHours())+":"+this._pad(s.getMinutes())},timespan:function(t,e,a,i,s,n){a||(a=t,n=e,t=null,e=null);for(var r=a.split(":"),o=0;r.length>o;o++){var l=Number(r[o]);l&&"NaN"!==l||(l=0),r[o]=this._pad(l)}return 0>=r.length?"0:00":1==r.length?"0:"+this._pad(allowkomma?r[0]:Math.floor(r[0])):2==r.length?allowkomma?r[0]:Math.floor(r[0])+":"+this._pad(allowkomma?r[1]:Math.floor(r[1])):allowkomma?r[0]:Math.floor(r[0])+":"+this._pad(allowkomma?r[1]:Math.floor(r[1]))+":"+pad(allowkomma?r[2]:Math.floor(r[2]))},humanTime:function(t,e,a){if(a||(a=t,t=null),isNaN(a))return a&&0!==a.length?a:"-";var i=Math.floor(a/36e5);a-=36e5*i;var s=Math.floor(a/6e4);a-=6e4*s;var n=Math.floor(a/1e3);a-=1e3*n;var r="";return i>0&&(r+=i+"h ",n=0,a=0),s>0&&(r+=s+"m ",a=0),n>0&&(r+=n+"s ",a=0),a>0&&(r+=a+"ms"),r.trim()}}}(jQuery,window),String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")},String.prototype.startsWith=function(t){return null===this||0>=this.length?!1:null===t||"null"==t||0>=t.length?!1:this.substr(0,t.length)==t?!0:!1},String.prototype.startsWithIgnoreCase=function(t){return null===this||0>=this.length?!1:null===t||"null"==t||0>=t.length?!1:this.substr(0,t.length).toLowerCase()==t.toLowerCase()?!0:!1},String.prototype.endsWith=function(t){return null===this||0>=this.length?!1:null===t||"null"==t||0>=t.length||t.length>this.length?!1:this.substr(this.length-t.length)==t?!0:!1};
-//@ sourceMappingURL=dist/jquery.jsForm.min.map
\ No newline at end of file