Skip to content

Commit

Permalink
more rebust method for "changed" fields
Browse files Browse the repository at this point in the history
  • Loading branch information
corinis committed Jan 14, 2014
1 parent c10dbf3 commit 94d82b6
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 96 deletions.
138 changes: 49 additions & 89 deletions src/jquery.jsForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 multiple="multiple"></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 = $('<option value="' + optionDisplay + '">' + optionDisplay + '</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();
});
});
});
});
};

/**
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -982,6 +924,7 @@
if(!name) {
return;
}
that._enableTracking(this);

// ignore file inputs - they cannot be "prefilled"
if($(this).attr("type") == "file") {
Expand Down Expand Up @@ -1058,6 +1001,7 @@
$(this).val(cdata);
}

$(this).data().orig = $(this).val();
$(this).change();
$(this).trigger("fill");
}
Expand All @@ -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");
Expand All @@ -1093,6 +1040,7 @@
}

$(this).children("option[value='"+value+"']").prop("selected", true);
$(this).data().orig = value;
$(this).val(value).change();
$(this).trigger("fill");
}
Expand Down Expand Up @@ -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) {
Expand Down
23 changes: 16 additions & 7 deletions test/jquery.jsForm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,25 +343,34 @@ 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");
equal(updated.steps[5], 1112, "last element: 1112");
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();
});

0 comments on commit 94d82b6

Please sign in to comment.