Skip to content

Commit

Permalink
Merge 90d4b85 into a4c31c2
Browse files Browse the repository at this point in the history
  • Loading branch information
Bertrand Laporte committed Apr 2, 2014
2 parents a4c31c2 + 90d4b85 commit 9daabb7
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 24 deletions.
44 changes: 34 additions & 10 deletions hsp/rt/eltnode.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var doc = require("../document");
var TNode = require("./tnode").TNode;
var hsp = require("../rt");
var gestures = require("../gestures/gestures");
//var log = require("./log");

var booleanAttributes = {
async: true,
Expand Down Expand Up @@ -71,6 +72,7 @@ var EltNode = klass({
}
this.gesturesEventHandlers = null;
this.needSubScope = (needSubScope===1);
this.preventRefresh=false; // if true will prevent the field from being refreshed during the typing sequence
},

$dispose : function () {
Expand Down Expand Up @@ -179,8 +181,8 @@ var EltNode = klass({
}

if (this.isInput) {
// ensure we listen to click, keydown and keyup
var et, inputEvts = ["click", "keydown", "keyup"];
// ensure we listen to click, focus and keyup
var et, inputEvts = ["click","focus","input","keyup"];
for (var idx in inputEvts) {
et = inputEvts[idx];
if (!evts[et]) {
Expand All @@ -204,15 +206,32 @@ var EltNode = klass({

// if the element is an input tag we synchronize the value
if (this.isInput && this.inputModelExpIdx) {
this.preventRefresh=false;
var exp = this.eh.getExpr(this.inputModelExpIdx);
if (exp.setValue) {
var v = this.node.value, tp = this.node.type;
if (tp === "checkbox") {
v = this.node.checked;
if (et==="keydown") {
// value is updated on keyup - so we must no refresh the field if the model
// is updated during keydown, otherwise the value is lost
this.preventRefresh=true;
} else if (et==="input" || et==="keyup" || et==="click" || et==="focus") {
// push the field value to the data model
// note: when the input event is properly implemented we don't need to listen to keyup
// but IE8 and IE9 don't implement it completely - thus the need for keyup
var v = this.node.value, tp = this.node.type;
if (tp === "checkbox") {
v = this.node.checked;
}

this._lastValue = v; // to avoid refreshing the field and move the cursor
var currentValue=exp.getValue(this.vscope,this.eh);
//log("[EltNode] handleEvent("+et+"): previous model value:["+currentValue+"] new value (from input):["+v+"]");
// if the value is already set no need to set it again and force a resync
if (v!==currentValue) {
exp.setValue(this.vscope, v);
// force refresh to resync other fields linked to the same data immediately
hsp.refresh();
}
}
this._lastValue = v; // to avoid refreshing the field and move the cursor
exp.setValue(this.vscope, v);
hsp.refresh(); // to force synchronous change
}
}

Expand Down Expand Up @@ -320,12 +339,17 @@ var EltNode = klass({
}
} else {
if (this._lastValue !== v1) {
nd.value = v1;
// value change has not been triggered by typing in this field

if (!this.preventRefresh && v1!=nd.value) {
//only update if value is changing and if we are not between 'onkeydown' and 'onkeyup'
//log("[EltNode] Node value update: current value:["+nd.value+"] new value:["+v1+"]");
nd.value = v1;
}
}
this._lastValue = null;
}
}

}

});
Expand Down
16 changes: 11 additions & 5 deletions hsp/rt/exphandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,17 @@ var DataRefExpr = klass({
if (ppl < 1) {
return; // this case should not occur
}
for (var i = 0; ppl - 1 > i; i++) {
v = v[this.path[i]];
if (v === undefined) {
goahead = false;
break;
if (ppl===1) {
if (!this.isLiteral) {
v=ExpHandler.getScopeOwner(this.path[0], vscope);
}
} else {
for (var i = 0; ppl - 1 > i; i++) {
v = v[this.path[i]];
if (v === undefined) {
goahead = false;
break;
}
}
}
if (goahead) {
Expand Down
6 changes: 3 additions & 3 deletions public/samples/inputsample/description.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

Hashspace automatically listens to the main change events of its input elements (*click*, *keypress* and *keyup*) in order to transparently synchronize the input values with the data referenced through the value expression.
Hashspace automatically listens to the main change events of its input elements (*click*, *focus* and *keyup*) in order to transparently synchronize the input values with the data referenced through the value expression.

The following example shows the same value referenced by two several text fields and a read-only span:

[#output]

For the time being, only simple path expressions are supported to reference input values in a bi-directional way.

You can note that *radio* inputs have to use a **model** attribute in order to be bind their selection to the data-model. All radio buttons referencing the same model property will automatically belong the same group - and they don't need to have the same *name* attribute as in classical HTML forms.

For the sake of consistency the **model** attribute can also be used on all input types, even if the *value* attribute can be used as well, as shown in the previous example.

**Note:** When users type in an input field, **hashspace synchronizes the data model on the keyup event**. As a consequence, applications that need to validate (and potentially change) user inputs should listen to this **keyup** event, and not to the *keydown* event as text fields are not updated yet at this stage.
6 changes: 3 additions & 3 deletions public/test/rt/input.spec.hsp
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,17 @@ describe("Input Elements", function () {
expect(input2.node.value).to.equal(v2);

// change the value from input1 (value attribute)
var v3 = "bar";
var v3 = "bar2";
input1.node.value = v3;
fireEvent("click",input1.node); // to simulate change
fireEvent("keyup",input1.node); // to simulate change
expect(input1.node.value).to.equal(v3);
expect(input2.node.value).to.equal(v3);
expect(d.comment).to.equal(v3);

// change the value from input2 (model attribute)
var v4 = "blah";
input2.node.value = v4;
fireEvent("click",input2.node); // to simulate change
fireEvent("keyup",input2.node); // to simulate change
expect(input1.node.value).to.equal(v4);
expect(input2.node.value).to.equal(v4);
expect(d.comment).to.equal(v4);
Expand Down
6 changes: 3 additions & 3 deletions public/test/rt/subtemplates1.spec.hsp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ describe("Sub-template insertion", function () {
expect(input.value).to.equal("some text");

input.value = "foo";
fireEvent("keydown",input); // triggers change propagation
fireEvent("keyup",input); // triggers change propagation

// change must have been propagated to parent scope
expect(dm.text).to.equal("foo");
Expand All @@ -223,7 +223,7 @@ describe("Sub-template insertion", function () {
expect(input.value).to.equal("some text");

input.value = "bar";
fireEvent("keydown",input);
fireEvent("keyup",input);

// change must have been propagated to parent scope
expect(dm.attributes.value).to.equal("bar");
Expand Down Expand Up @@ -269,7 +269,7 @@ describe("Sub-template insertion", function () {
expect(input.value).to.equal("new text");

input.value = "bar";
fireEvent("keydown",input);
fireEvent("keyup",input);
expect(dm.value).to.equal("bar");

n.$dispose();
Expand Down

0 comments on commit 9daabb7

Please sign in to comment.