Commit 78d5e5c8 authored by Sven Franck's avatar Sven Franck

added form validation

parent 56ef7949
...@@ -1387,80 +1387,10 @@ var priv = {}; ...@@ -1387,80 +1387,10 @@ var priv = {};
// form = document.getElementById(e.target.getAttribute("data-form"));
// target = e.target.href;
//
// e.preventDefault();
//
// if (util.testForClass(form.className), "validate") {
// valid = $(form).triggerHandler( "submitForm" );
// } else {
// valid = $(form).serialize();
// }
//
// // // TODO: how to update status?
// // if (valid !== false) {
// // jIO.util.ajax({
// // "url": "data/" + attachment + ".json", "dataType":"json"
// // })
// // }
// //
// // target = e.target.href,
// // id = form.id,
// // pointer = "response:" + id,
// // proceed = function (data, target) {
// // // changePage with fragment_cache pointer
// // $.mobile.changePage(target, {"transition": "slide", "data": data});
// // };
// //
// // // stop
// // // fetch and proceed
// // if (valid !== false) {
// // $.ajax({
// // "type":"POST",
// // "url": "foo.php",
// // "data": valid
// // }).done(function(data) {
// // // overwrite cache
// // // NOTE: FAKE data until working
// // priv.fragment_cache[id] = priv.getFakeRecords["payment"];
// // proceed(pointer, target);
// // }).fail(function(jqXHR) {
// // // fake it
// // priv.fragment_cache[id] = priv.getFakeRecords["payment"];
// // proceed(pointer, target);
// // });
// // }
// // });
// // }
// // });
// PAGE BINDINGS
.end()
// form validation initializer
.find("form")
// .filter(function () {
// return this.getAttribute("data-bound") !== true;
// })
// .each(function (i, element) {
// element.setAttribute("data-bound", true);
// // TODO: how to add custom validations here?
// // TODO: async?
// $(element).validVal({
// validate: {
// onKeyup: "valid",
// onBlur: "valid"
// },
// form: {
// onInvalid: function() { return;}
// }
// });
// })
// .end()
......
...@@ -43,6 +43,14 @@ ...@@ -43,6 +43,14 @@
// TODO: remove duplicate code for pagination // TODO: remove duplicate code for pagination
erp5.map_actions = { erp5.map_actions = {
/**
* submit a form
* @method submit
* @param {object} obj Action Object
*/
submit: function (obj) {
init.submit(obj);
},
/** /**
* show jumps popup * show jumps popup
* @method jump * @method jump
...@@ -246,7 +254,7 @@ ...@@ -246,7 +254,7 @@
// TODO: how to get count? run query on underlying_portal_type with // TODO: how to get count? run query on underlying_portal_type with
// category? Lot of queries // category? Lot of queries
// TODO: add remaining mapping! // TODO: add remaining mapping!
// TODO: still bad, although "categories_" is out! // TODO: bad because not generic! Try!!!
mapListItems: function (items, replace) { mapListItems: function (items, replace) {
var property, obj, i, item, clean, value, store, split, host, arr = []; var property, obj, i, item, clean, value, store, split, host, arr = [];
...@@ -290,13 +298,13 @@ ...@@ -290,13 +298,13 @@
obj.left = {}; obj.left = {};
obj.left[item[property]] = (store !== undefined ? store : false); obj.left[item[property]] = (store !== undefined ? store : false);
break; break;
case "image": case "image_url":
if (obj.left !== undefined) { if (obj.left !== undefined) {
if (!obj.left["image"]) { if (obj.left["image"] === false) {
obj.left["image"] = item[property]; obj.left["image"] = item[property];
obj.left["alt"] = item["title"]; obj.left["alt"] = item["title"];
} }
if (!obj.left["icon"]) { if (obj.left["icon"] === false) {
obj.left["icon"] = item[property]; obj.left["icon"] = item[property];
} }
} else { } else {
...@@ -363,15 +371,13 @@ ...@@ -363,15 +371,13 @@
spec.properties.maximum_length) { spec.properties.maximum_length) {
validation_list += "|max_length:" + validation_list += "|max_length:" +
(prevail.properties.maximum_length || (prevail.properties.maximum_length ||
spec.properties.maximum_length) + "&truncate" + spec.properties.maximum_length) + "&truncate:" +
(prevail.properties.truncate || spec.properties.truncate); (prevail.properties.truncate || spec.properties.truncate);
} }
// unknown selection? // unknown selection?
// type-related validation, element and type definition // type-related validation, element and type definition
console.log("MAPPING")
console.log(spec.type)
switch (spec.type) { switch (spec.type) {
case "StringField": case "StringField":
case "RelationStringField": case "RelationStringField":
...@@ -385,6 +391,10 @@ ...@@ -385,6 +391,10 @@
type = "password"; type = "password";
clear = true; clear = true;
break; break;
case "CheckboxField":
element = "input";
type = "checkbox";
break;
case "MultiListField": case "MultiListField":
case "ListField": case "ListField":
case "ParallelListField": case "ParallelListField":
...@@ -735,6 +745,11 @@ ...@@ -735,6 +745,11 @@
* @return {object} fragment HTML object containing the elements * @return {object} fragment HTML object containing the elements
*/ */
// TODO: refactor. Remove hack!!!! // TODO: refactor. Remove hack!!!!
// TODO: this is crap because it adds first/last which in case of
// wrapping elements ends up on the wrong element, so do it either before
// or after!
// TODO: this function is crap, either do all looping here (listview...)
// or nothing
// NOTE: this can only handle fully described elements in an array (no li!) // NOTE: this can only handle fully described elements in an array (no li!)
factory.util.generateFromArray = function (spec, type, hack, reference) { factory.util.generateFromArray = function (spec, type, hack, reference) {
var i, var i,
...@@ -757,7 +772,8 @@ ...@@ -757,7 +772,8 @@
} }
// class string // class string
if (element.direct && type !== "controlbar") { if ((element.type !== "input" && element.type !== "select")
&& element.direct && type !== "controlbar") {
order = i === 0 ? " ui-first-child " : order = i === 0 ? " ui-first-child " :
(i === (spec.length - 1) ? " ui-last-child " : " "); (i === (spec.length - 1) ? " ui-last-child " : " ");
...@@ -1216,10 +1232,13 @@ ...@@ -1216,10 +1232,13 @@
* @param {object} spec Configuration for controlgroup * @param {object} spec Configuration for controlgroup
* @return controlgroup * @return controlgroup
*/ */
// TODO: crap to use both layout and children!
factory.generateForm = function (spec) { factory.generateForm = function (spec) {
var i, var i,
j, j,
k,
layout, layout,
element,
container, container,
area, area,
field, field,
...@@ -1228,24 +1247,22 @@ ...@@ -1228,24 +1247,22 @@
doc, doc,
id, id,
config, config,
fragment = factory.util.wrapInForm(spec.form); fragment = factory.util.wrapInForm(spec.form),
wrap = function (area) {
return factory.generateElement(
"div", {"className": "span_" + area}
);
};
// form fields = layout
for (i = 0; i < spec.layout.length; i += 1) { for (i = 0; i < spec.layout.length; i += 1) {
layout = spec.layout[i]; layout = spec.layout[i];
area = layout.position === "center" ? 2 : 1; area = layout.position === "center" ? 2 : 1;
container = factory.generateElement( container = wrap(area);
"div", {"className": "span_" + area}
);
for (j = 0; j < layout.fieldlist.length; j += 1) { for (j = 0; j < layout.fieldlist.length; j += 1) {
console.log(j)
console.log(layout)
field = layout.fieldlist[j]; field = layout.fieldlist[j];
console.log(field)
console.log(spec.fields)
config = spec.fields[field.title]; config = spec.fields[field.title];
console.log("so config is")
console.log(config)
overrides = field.overrides; overrides = field.overrides;
doc = spec.data || undefined; doc = spec.data || undefined;
value = doc ? (doc[field.title]) : undefined; value = doc ? (doc[field.title]) : undefined;
...@@ -1259,8 +1276,7 @@ ...@@ -1259,8 +1276,7 @@
default: position = undefined; default: position = undefined;
break; break;
} }
console.log("this should be a proper config")
console.log(config)
// generate and append // generate and append
container.appendChild(factory.generateFormElement( container.appendChild(factory.generateFormElement(
factory.map_utils.mapFormField(config, overrides, value), factory.map_utils.mapFormField(config, overrides, value),
...@@ -1271,7 +1287,17 @@ ...@@ -1271,7 +1287,17 @@
} }
fragment.appendChild(container); fragment.appendChild(container);
} }
console.log(fragment)
// children (default to fullscreen)
for (k = 0; k < spec.children.length; k += 1) {
// pass reference
element = spec.children[k];
element.reference = spec.form;
container = wrap(2);
container.appendChild(factory.util.forward(element));
}
fragment.appendChild(container);
return fragment; return fragment;
}; };
...@@ -1525,8 +1551,8 @@ ...@@ -1525,8 +1551,8 @@
list = factory.generateElement( list = factory.generateElement(
config.numbered ? "ol" : "ul", config.numbered ? "ol" : "ul",
{ {
"className": "ui-listview " + spec.class_list + " " + "className": "ui-listview " + (spec.class_list || "") +
(config.inset ? "ui-listview-inset ui-corner-all ui-shadow " : "") (config.inset ? " ui-listview-inset ui-corner-all ui-shadow " : "")
}, },
{ {
"data-role":"listview", "data-role":"listview",
...@@ -1569,7 +1595,6 @@ ...@@ -1569,7 +1595,6 @@
last = auto; last = auto;
} }
} }
// list item // list item
item = factory.generateElement( item = factory.generateElement(
"li", "li",
...@@ -2246,16 +2271,23 @@ ...@@ -2246,16 +2271,23 @@
action, action,
clear, clear,
map, map,
theme,
icon_string, icon_string,
input_type, input_type,
container_classes = "", need_text_node,
label_classes = "", container_class_list = "",
label_class_list = "",
index = "", index = "",
disabled = "", disabled = "",
readonly = "", readonly = "",
active = "off", active = "off",
text = "text"; text = "text";
// shim missing logic
if (config.logic === undefined) {
config.logic = {};
}
// first/last in group of elements // first/last in group of elements
if (position) { if (position) {
switch (position) { switch (position) {
...@@ -2268,6 +2300,11 @@ ...@@ -2268,6 +2300,11 @@
}; };
} }
// theme
if (config.attributes["data-theme"] !== undefined) {
theme = " ui-btn-" + config.attributes["data-theme"];
}
// enhanced! // enhanced!
config.attributes["data-enhanced"] = true; config.attributes["data-enhanced"] = true;
...@@ -2320,22 +2357,27 @@ ...@@ -2320,22 +2357,27 @@
if (input_type) { if (input_type) {
switch (input_type) { switch (input_type) {
case "radio": case "radio":
container_classes = "ui-" + config.attributes.type; container_class_list = "ui-" + config.attributes.type;
label_inside = true; label_inside = true;
label_classes = "ui-btn ui-corner-all ui-btn-inherit" + label_class_list = "ui-btn ui-corner-all ui-btn-inherit" +
" ui-btn-icon-left ui-icon-radio-" + active + " ui-radio-" + " ui-btn-icon-left ui-icon-radio-" + active + " ui-radio-" +
active + index + disabled + readonly; active + index + disabled + readonly;
config.attributes["data-cacheval"] = true; config.attributes["data-cacheval"] = true;
break; break;
case "checkbox": case "checkbox":
icon_string = factory.generateIconClassString(config, "checkbox"); icon_string = factory.generateIconClassString(config, "checkbox");
container_classes = "ui-"+ config.attributes.type; container_class_list = "ui-"+ config.attributes.type;
label_inside = true; label_inside = true;
label_classes = "ui-btn ui-corner-all ui-btn-inherit " + label_class_list = "ui-btn ui-corner-all ui-btn-inherit " +
icon_string + " ui-checkbox-" + active + index + disabled icon_string + " ui-checkbox-" + active + index + disabled
+ readonly; + readonly;
config.attributes["data-cacheval"] = false; config.attributes["data-cacheval"] = false;
break; break;
case "submit":
case "reset":
container_class_list = "ui-btn ui-input-btn";
need_text_node = true;
break;
// covers all JQM text input types and excludes select/textarea... // covers all JQM text input types and excludes select/textarea...
default: default:
if (input_type !== "hidden") { if (input_type !== "hidden") {
...@@ -2344,13 +2386,14 @@ ...@@ -2344,13 +2386,14 @@
config.attributes["data-type"] = "search"; config.attributes["data-type"] = "search";
text = "search"; text = "search";
} }
container_classes = "ui-input-" + text + " ui-body-inherit " + container_class_list = "ui-input-" + text + " ui-body-inherit ";
" ui-corner-all ui-shadow-inset" + disabled + readonly +
(action || "") + (clear || "");
} }
break; break;
} }
} }
// assemble
container_class_list += " ui-corner-all ui-shadow-inset" +
disabled + readonly + (action || "") + (clear || "") + (theme || "");
// container // container
if (config.type === "textarea" || config.logic.type === "hidden") { if (config.type === "textarea" || config.logic.type === "hidden") {
...@@ -2362,22 +2405,23 @@ ...@@ -2362,22 +2405,23 @@
// select // select
if (config.type === "select") { if (config.type === "select") {
icon_string = factory.generateIconClassString(config); icon_string = factory.generateIconClassString(config);
container_classes = "ui-" + config.type; container_class_list = "ui-" + config.type;
element_target = factory.generateElement( element_target = factory.generateElement(
"div", "div",
{ {
"id": config.direct.id + "-button", "id": config.direct.id + "-button",
"className":"ui-btn ui-corner-all ui-shadow " + icon_string "className":icon_string + " ui-btn ui-corner-all ui-shadow " +
(config.logic.wrapper_class_list || "")
}, },
{"data-enhanced":"true"} {"data-enhanced":"true"}
); );
element_reverse = true; element_reverse = true;
} }
// queued commands (need container_classes to be set) // queued commands (need container_class_list to be set)
if (wrap_in_container) { if (wrap_in_container) {
container = factory.generateElement( container = factory.generateElement(
"div", {"className": container_classes} "div", {"className": container_class_list}
); );
} }
if (label_inside) { if (label_inside) {
...@@ -2386,17 +2430,21 @@ ...@@ -2386,17 +2430,21 @@
label_target = wrapper; label_target = wrapper;
} }
// label - always label for validatiy, no label means "hide" not "skip"! // label - always label for validity, no label means "hide" not "skip"!
label_target.appendChild(factory.generateElement( // NOTE: for submit and reset buttons don't add a label because we don't
"label", // need an id/name
{ if (need_text_node === undefined) {
"className": label_classes + " translate" + label_target.appendChild(factory.generateElement(
((label === undefined || config.logic.text === "") ? "label",
" ui-hidden-accessible" : "") {
}, "className": label_class_list + " translate" +
{"for": config.direct.id, "data-i18n": config.logic.label_i18n || ""}, ((label === undefined || config.logic.text === "") ?
{"text": config.logic.label || ""} " ui-hidden-accessible" : "")
)); },
{"for": config.direct.id, "data-i18n": config.logic.label_i18n || ""},
{"text": config.logic.label || ""}
));
}
// target // target
if (element_reverse) { if (element_reverse) {
...@@ -2405,6 +2453,11 @@ ...@@ -2405,6 +2453,11 @@
element_target = container; element_target = container;
} }
// text node
if (need_text_node) {
element_target.appendChild(document.createTextNode(config.direct.value));
}
// ELEMENT // ELEMENT
element_target.appendChild(factory.generateElement( element_target.appendChild(factory.generateElement(
config.type, config.type,
...@@ -2623,6 +2676,80 @@ ...@@ -2623,6 +2676,80 @@
/* UTILS */ /* UTILS */
/* ====================================================================== */ /* ====================================================================== */
/**
* IE8 compatible custom event listener
* @method listenToEvent
* @param {object} element Element to attach listener to
* @param {string} eventName Event to listen for
* @param {method} callback Method to run on event
* @param {boolean} custom Flag for custom event
*/
// WARNING: make sure this works in IE8!
util.listenToEvent = function (element, event_name, callback, custom) {
var old_ie = document.addEventListener,
target = element || ((custom && old_ie) ?
(document.documentElement) : document);
if (old_ie) {
if (custom) {
target.attachEvent('onpropertychange', function (e) {
if(e.propertyName == event_name) {
callback();
}
});
} else {
target.attachEvent("on" + event, attachHandler);
}
} else {
console.log("adding listener")
console.log(target)
target.addEventListener(event_name, callback, false);
}
};
/**
* IE8 compatible custom event trigger
* @method triggerEvent
* @param {object} element Element to attach listener to
* @param {string} event_name Event to trigger
* @param {boolean} custom Flag for custom event
*/
util.triggerEvent = function (element, event_name, custom) {
var event,
old_ie = document.addEventListener,
target = element || ((custom && old_ie) ?
(document.documentElement) : document);
if (document.createEvent) {
event = document.createEvent('Event');
event.initEvent(event_name, true, true);
target.dispatchEvent(event);
} else {
event = target[event_name];
event += 1;
}
};
/**
* IE8 compatible removal of event listeners
* @method removeEvent
* @param {object} element Element to attach listener to
* @param {string} eventName Event to listen for
* @param {method} callback Method to run on event
* @param {boolean} custom Flag for custom event
*/
util.removeEvent = function (element, event_name, callback, custom) {
var old_ie = document.addEventListener,
target = element || ((custom && old_ie) ?
(document.documentElement) : document);
if (target.removeEventListener) {
target.removeEventListener(event_name, callback, false);
} else {
target.detachEvent('onpropertychange', callback);
}
};
/** /**
* Load content into a global or local popup * Load content into a global or local popup
* @method loadPopupContents * @method loadPopupContents
...@@ -3270,7 +3397,8 @@ ...@@ -3270,7 +3397,8 @@
if (type === "click" && e.target.getAttribute("data-rel") === null) { if (type === "click" && e.target.getAttribute("data-rel") === null) {
e.preventDefault(); e.preventDefault();
if (type === "click" && (tag === "SELECT" || tag === "INPUT")) { if (type === "click" && (tag === "SELECT" ||
(tag === "INPUT" && e.target.type !== "submit"))) {
return; return;
} }
} }
...@@ -3432,6 +3560,56 @@ ...@@ -3432,6 +3560,56 @@
.fail(util.errorHandler); .fail(util.errorHandler);
}; };
/**
* Handler for form submission
* @method submit
* @param {object} config Action Object
*/
// NOTE: we always validate! to skip validation test for class on form
init.submit = function (config) {
var form_element = document.getElementById(config.id),
valid = $(form_element).triggerHandler( "submitForm" );
// // TODO: how to update status?
// if (valid !== false) {
// jIO.util.ajax({
// "url": "data/" + attachment + ".json", "dataType":"json"
// })
// }
//
// target = e.target.href,
// id = form.id,
// pointer = "response:" + id,
// proceed = function (data, target) {
// // changePage with fragment_cache pointer
// $.mobile.changePage(target, {"transition": "slide", "data": data});
// };
//
// // stop
//
// // fetch and proceed
// if (valid !== false) {
// $.ajax({
// "type":"POST",
// "url": "foo.php",
// "data": valid
// }).done(function(data) {
// // overwrite cache
// // NOTE: FAKE data until working
// priv.fragment_cache[id] = priv.getFakeRecords["payment"];
// proceed(pointer, target);
// }).fail(function(jqXHR) {
// // fake it
// priv.fragment_cache[id] = priv.getFakeRecords["payment"];
// proceed(pointer, target);
// });
// }
// });
// }
};
/** /**
* Handler for pagination * Handler for pagination
* @method paginate * @method paginate
...@@ -3534,27 +3712,81 @@ ...@@ -3534,27 +3712,81 @@
}; };
/** /**
* Set page bindings * Set bindings on page specific elements after content has been appended
* @method setPageBindings * @method setPageBindings
* @param {object} e Custom event object
*/ */
init.setPageBindings = function (e) {
$(document) // TODO: add local popups!
// disable JQM filters init.setPageBindings = function () {
.find("[data-filter='true']") var i,
.filter(function () { j,
return this.getAttribute("data-bound") !== true; form_element,
}) filterable,
.each(function (i, element) { form_list = document.getElementsByTagName("form"),
element.setAttribute("data-bound", true); filter_list = document.querySelectorAll("[data-filter]");
$(element).on("filterablebeforefilter", function (e) { // disable default filtering of JQM filterable
for (i = 0; i < filter_list.length; i += 1) {
filterable = filter_list[i];
if (filterable.getAttribute("data-bound") === null) {
filterable.setAttribute("data-bound", true);
// TODO: javascript-able?
$(filterable).on("filterablebeforefilter", function (e) {
e.preventDefault(); e.preventDefault();
}); });
}); }
}
// add validation to all forms
for (j = 0; j < form_list.length; j += 1) {
form_element = form_list[j];
if (form_element.getAttribute("data-bound") === null) {
form_element.setAttribute("data-bound", true);
// TODO: javascript-able?
// NOTE: the script is mapped to validval, so replacing it
// requires it to add a different plugin here as well as
// updating all data-vv fields being set in mapFormField() and
// generateFormElement
$(form_element).validVal({
validate: {
onKeyup: "valid",
onBlur: "valid"
},
form: {
onInvalid: function(invalid_field_list) {
console.log("CALLING oninvalid")
var i,
invalid_field,
invalid_field_label,
undo = function (element) {
util.removeEvent(element, "click", undo);
};
for (i = 0; i < invalid_field_list.length; i += 1) {
invalid_field = invalid_field_list[i];
switch (invalid_field.type) {
case "checkbox":
case "radio":
// console.log("FOUND A CHECKBOX OR RADIO")
// invalid_field_label = invalid_field.previousSibling;
// invalid_field_label.className += " invalid";
// util.listenToEvent(
// invalid_field_label, "click", undo(invalid_field_label)
// );
break;
}
}
return;
}
}
});
}
}
// TODO: FIND local popups!
}; };
...@@ -3589,15 +3821,15 @@ ...@@ -3589,15 +3821,15 @@
if (document.getElementById(raw_url.split("#").pop()) || if (document.getElementById(raw_url.split("#").pop()) ||
raw_url === $.mobile.getDocumentUrl() || raw_url === $.mobile.getDocumentUrl() ||
data.options.role === "popup") { data.options.role === "popup") {
console.log("let JQM go") // console.log("let JQM go")
return; return;
} }
if (document.getElementById(config.id)) { if (document.getElementById(config.id)) {
console.log("stop JQM") // console.log("stop JQM")
e.preventDefault(); e.preventDefault();
return; return;
} else { } else {
console.log("HIJACK and stop JQM") // console.log("HIJACK and stop JQM")
handle = true; handle = true;
e.preventDefault(); e.preventDefault();
} }
...@@ -3614,7 +3846,7 @@ ...@@ -3614,7 +3846,7 @@
} }
init.fetchPageLayouts("settings", config.layout_identifier) init.fetchPageLayouts("settings", config.layout_identifier)
.then(function (reply) { .then(function (reply) {
init.setPageElements(config, util.parseIfNeeded(reply), create); return init.setPageElements(config, util.parseIfNeeded(reply), create);
}) })
.then(init.setPageBindings) .then(init.setPageBindings)
.fail(util.errorHandler); .fail(util.errorHandler);
...@@ -3839,8 +4071,7 @@ ...@@ -3839,8 +4071,7 @@
delete baggage.constructor; delete baggage.constructor;
baggage.state.selected = create === false ? (baggage.state.selected) : undefined; baggage.state.selected = create === false ? (baggage.state.selected) : undefined;
selector.state = baggage.state; selector.state = baggage.state;
console.log("DONE generating")
console.log(selector)
// TODO: not working - element is fragment or html element // TODO: not working - element is fragment or html element
init.updateInfoFields( init.updateInfoFields(
element, baggage.state.query, baggage.state.total element, baggage.state.query, baggage.state.total
...@@ -3874,11 +4105,9 @@ ...@@ -3874,11 +4105,9 @@
} else { } else {
document.body.appendChild(page); document.body.appendChild(page);
} }
console.log("let's go to")
console.log(config.id)
// JQM treatment // JQM treatment
$(document).enhanceWithin(); $(document).enhanceWithin();
console.log("CHANGING PAGE")
$.mobile.changePage("#" + config.id); $.mobile.changePage("#" + config.id);
} else { } else {
...@@ -4080,6 +4309,12 @@ ...@@ -4080,6 +4309,12 @@
}; };
}) })
// block form submits
.on("submit", "form", function (e) {
e.preventDefault();
return false;
})
// global actions // global actions
.on("click change keyup input", ".action", function (e) { .on("click change keyup input", ".action", function (e) {
var val, last, var val, last,
...@@ -4089,7 +4324,6 @@ ...@@ -4089,7 +4324,6 @@
// delay all input field actions allowing user to type/select // delay all input field actions allowing user to type/select
if (element.tagName === "INPUT" && if (element.tagName === "INPUT" &&
(type !== "button" && type !== "checkbox")) { (type !== "button" && type !== "checkbox")) {
val = element.value, val = element.value,
last = element.getAttribute("data-last") last = element.getAttribute("data-last")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment