diff --git a/src/jquery.jsForm.js b/src/jquery.jsForm.js
index a7a7755..eb14ab8 100644
--- a/src/jquery.jsForm.js
+++ b/src/jquery.jsForm.js
@@ -36,6 +36,12 @@
* the prefix used to annotate theinput fields
*/
prefix: "data",
+ /**
+ * set to null to discourage the tracking of "changed" fields.
+ * Disabling this will increase performance, but disabled the "changed" functionality.
+ * This will add the given css class to changed fields.
+ */
+ trackChanges: "changed",
/**
* set to false to only validate visible fields.
* This is discouraged especially when you have tabs or similar elements in your form.
@@ -344,6 +350,12 @@
$(line).data().pojo = {};
$(this).append(line);
+ // init controls
+ that._enableTracking($("input,textarea,select", line));
+ // ne wline always has changes
+ if(that.options.trackChanges)
+ $("input,textarea,select", line).addClass(that.options.trackChanges);
+
that._addCollectionControls(line);
// trigger a callback
@@ -504,93 +516,6 @@
});
-
- // 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", true);
- }
- });
- });
- 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();
- });
- });
- });
- });
};
/**
@@ -905,6 +830,23 @@
return pojo;
};
+ /**
+ * helper function to enable tracking on fields
+ * @param ele the element to track
+ */
+ JsForm.prototype._enableTracking = function(ele) {
+ var that = this;
+ if(that.options.trackChanges && !$(ele).data().track) {
+ $(ele).data().track = true;
+ $(ele).change(function(){
+ if($(this).val() !== $(this).data().orig) {
+ $(this).addClass(that.options.trackChanges);
+ }else {
+ $(this).removeClass(that.options.trackChanges);
+ }
+ });
+ }
+ };
/**
* fill a dom subtree with data.
@@ -982,6 +924,7 @@
if(!name) {
return;
}
+ that._enableTracking(this);
// ignore file inputs - they cannot be "prefilled"
if($(this).attr("type") == "file") {
@@ -1058,6 +1001,7 @@
$(this).val(cdata);
}
+ $(this).data().orig = $(this).val();
$(this).change();
$(this).trigger("fill");
}
@@ -1074,6 +1018,9 @@
if (prefix) {
cname = cname.substring(prefix.length + 1);
}
+
+ that._enableTracking(this);
+
// remove "old" selected options
$(this).children("option:selected").prop("selected", false);
var pk = $(this).attr("data-key");
@@ -1093,6 +1040,7 @@
}
$(this).children("option[value='"+value+"']").prop("selected", true);
+ $(this).data().orig = value;
$(this).val(value).change();
$(this).trigger("fill");
}
@@ -1886,8 +1834,20 @@
*
* @returns {Boolean} true if the form has changed since the last fill
*/
- JsForm.prototype.changed = function(idField) {
- return this.equals(this.options.data, idField) === false;
+ JsForm.prototype.changed = function() {
+ if(!this.options.trackChanges)
+ return false;
+
+ var changed = false;
+ var that = this;
+ $.each(this._getForm(), function(){
+ if($("." + that.options.trackChanges, this).size() > 0) {
+ changed = true;
+ return false;
+ }
+ });
+
+ return changed;
};
JsForm.prototype._equalsCollection = function(form, prefix, pojo) {
diff --git a/test/jquery.jsForm.test.js b/test/jquery.jsForm.test.js
index 76569ac..618ae45 100644
--- a/test/jquery.jsForm.test.js
+++ b/test/jquery.jsForm.test.js
@@ -343,17 +343,18 @@ test("direct access simple arrays", function(){
equal($("#list1", basicForm).children().length, 5, "5 items in list1");
equal($("#list2", basicForm).children().length, 5, "5 items in list2");
- equal(basicForm.jsForm("equals", original), true, "form has not changed");
+ equal(basicForm.jsForm("changed"), false, "form has not changed");
+ equal(basicForm.jsForm("equals", original), true, "form data has not changed");
// add an item in each list
$("#add1", basicForm).click();
$("#add2", basicForm).click();
equal($("#list1", basicForm).children().length, 6, "6 items in list1");
equal($("#list2", basicForm).children().length, 6, "6 items in list2");
- $("#list1", basicForm).children().first().find("input").val("1111");
- $("#list1", basicForm).children().last().find("input").val("1112");
- $("#list2", basicForm).children().first().find("input").val("2221");
- $("#list2", basicForm).children().last().find("input").val("2222");
+ $("#list1", basicForm).children().first().find("input").val("1111").change();
+ $("#list1", basicForm).children().last().find("input").val("1112").change();
+ $("#list2", basicForm).children().first().find("input").val("2221").change();
+ $("#list2", basicForm).children().last().find("input").val("2222").change();
var updated = basicForm.jsForm("get");
equal(updated.steps.length, 6, "6 steps");
equal(updated.steps[0], 1111, "first element: 1111");
@@ -361,7 +362,15 @@ test("direct access simple arrays", function(){
equal(updated.test.steps.length, 6, "6 steps in test");
equal(updated.test.steps[0], 2221, "first element: 2221");
equal(updated.test.steps[5], 2222, "last element: 2222");
-
- equal(basicForm.jsForm("equals", original), false, "form has changed");
+
+ equal($("#list1", basicForm).children().first().find("input").hasClass("changed"), true, "first input changed");
+ equal($("#list1", basicForm).children().eq(2).find("input").hasClass("changed"), false, "second input not changed");
+ equal($("#list1", basicForm).children().last().find("input").hasClass("changed"), true, "last input changed");
+ equal($("#list2", basicForm).children().first().find("input").hasClass("changed"), true, "first input changed");
+ equal($("#list2", basicForm).children().last().find("input").hasClass("changed"), true, "last input changed");
+
+ equal(basicForm.jsForm("changed"), true, "form has changed");
+ equal(basicForm.jsForm("equals", original), false, "form data has changed");
+ // clean up
basicForm.remove();
});
\ No newline at end of file