-1) {
+ if (entry.names.indexOf(name) > -1 && (typeof entry.tags === "undefined" || entry.tags.indexOf(tag) > -1)) {
results.push(entry);
}
}
diff --git a/hsp/rt/$root.js b/hsp/rt/$root.js
index e637f2e..5f6595b 100644
--- a/hsp/rt/$root.js
+++ b/hsp/rt/$root.js
@@ -114,7 +114,6 @@ var $RootNode = klass({
}
this.childNodes = ch;
this.argNames = argnames;
- this.afterNodeCreation();
},
$dispose : function () {
@@ -618,7 +617,6 @@ var $CptNode = klass({
this.adirty = false;
}
TNode.refresh.call(this);
- this.afterNodeCreation();
},
/**
diff --git a/hsp/rt/attributes/class.js b/hsp/rt/attributes/class.js
index 1a82db6..652b5dc 100644
--- a/hsp/rt/attributes/class.js
+++ b/hsp/rt/attributes/class.js
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2014 Amadeus s.a.s.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
var klass = require("../../klass");
var ClassHandler = klass({
@@ -6,7 +21,7 @@ var ClassHandler = klass({
this.previousClasses = null;
},
- setValue: function (name, newClasses) {
+ $setValue: function (name, newClasses) {
var currentClasses = this.nodeInstance.node.className;
var results = currentClasses? currentClasses.split(' '): [];
if (this.previousClasses) {
diff --git a/hsp/rt/attributes/modelvalue.js b/hsp/rt/attributes/modelvalue.js
new file mode 100644
index 0000000..3e25aa0
--- /dev/null
+++ b/hsp/rt/attributes/modelvalue.js
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2014 Amadeus s.a.s.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ var klass = require("../../klass");
+
+var ModelValueHandler = klass({
+ $constructor : function (nodeInstance) {
+ this.nodeInstance = nodeInstance;
+ this.node = nodeInstance.node;
+ this._lastValues = {};
+ // 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
+ this._inputEvents = ["click", "focus", "input", "keyup"];
+ nodeInstance.registerEventListeners(this._inputEvents);
+ },
+
+ $setValue: function (name, value) {
+ if (name === "value") {
+ // value attribute must be changed directly as the node attribute is only used for the default value
+ if (this.node.type === "radio") {
+ this.node.value = value;
+ }
+ }
+ this._lastValues[name] = value;
+ },
+
+ $afterRefreshAttributes: function() {
+ var lastValue = typeof this._lastValues["model"] === "undefined"? this._lastValues["value"]: this._lastValues["model"];
+ var lastValueAsString = '' + lastValue;
+ if (this.node.type === "radio") {
+ var currentValueAsString = '' + this.node.value;
+ this.node.checked = (lastValueAsString === currentValueAsString);
+ } else if (this.node.type === "checkbox") {
+ var currentValueAsString = '' + this.node.checked;
+ if (lastValueAsString !== currentValueAsString) {
+ this.node.checked = !this.node.checked;
+ }
+ } else if (lastValueAsString != this.node.value) {
+ //only update if value is changing
+ this.node.value = lastValue;
+ }
+ },
+
+ $handleEvent : function (evt) {
+ if (this._inputEvents.indexOf(evt.type) > -1) {
+ // push the field value to the data model
+ var value = this.node.value;
+ var type = this.node.type;
+ if (type === "checkbox") {
+ value = this.node.checked;
+ }
+ var isSet = this.nodeInstance.setAttributeValueInDataModel("model", value);
+ if (!isSet) {
+ this.nodeInstance.setAttributeValueInDataModel("value", value);
+ }
+ }
+ },
+
+ $dispose: function() {
+ this._inputEvents.length = 0;
+ }
+});
+
+module.exports = ModelValueHandler;
\ No newline at end of file
diff --git a/hsp/rt/eltnode.js b/hsp/rt/eltnode.js
index 4f9f550..24e16f8 100644
--- a/hsp/rt/eltnode.js
+++ b/hsp/rt/eltnode.js
@@ -25,6 +25,8 @@ var log = require("./log");
//Loads internal custom attributes
var ClassHandler = require('./attributes/class');
hsp.registerCustomAttributes("class", ClassHandler);
+var ModelValueHandler = require('./attributes/modelvalue');
+hsp.registerCustomAttributes(["model", "value"], ModelValueHandler, 0, ["input", "textarea"]);
var booleanAttributes = {
async: true,
@@ -70,32 +72,28 @@ var EltNode = klass({
$constructor : function (tag, exps, attcfg, ehcfg, children, needSubScope) {
TNode.$constructor.call(this, exps);
this.tag = tag;
- this.isInput = (this.tag === "input" || this.tag === "textarea");
this.createAttList(attcfg, ehcfg);
if (children && children !== 0) {
this.children = children;
}
this.needSubScope = (needSubScope===1);
- this._lastValue = null;
},
$dispose : function () {
var evh = this.evtHandlers, nd = this.node;
- if (this.isInput) {
- this.inputModelExpIdx = null;
- }
if (evh) {
// remove all event handlers
var rmEL = (nd.removeEventListener !== undefined); // tells if removeEventListener is supported
- for (var i = 0, sz = evh.length; sz > i; i++) {
+ for (var i = 0; i < this._allEventListerners.length; i++) {
if (rmEL) {
- nd.removeEventListener(evh[i].evtType, this, false);
+ nd.removeEventListener(this._allEventListerners[i], this, false);
} else {
- nd.detachEvent("on" + evh[i].evtType, this._attachEventFn);
+ nd.detachEvent("on" + this._allEventListerners[i], this._attachEventFn);
}
}
}
+ this._allEventListerners.length = 0;
if (this._customAttributesHandlers) {
for (var key in this._customAttributesHandlers) {
var customHandlers = this._customAttributesHandlers[key];
@@ -103,11 +101,13 @@ var EltNode = klass({
if (customHandlers[i].instance.$dispose) {
customHandlers[i].instance.$dispose();
}
- delete customHandlers[i];
+ delete this._customAttributesHandlers[key];
+ delete this._customAttributesData[key];
}
}
this._customAttributesHandlers = null;
- this._customAttributesValues = null;
+ this._customAttributesData = null;
+ this._allCustomAttributesHandlers.length = 0;
}
this._attachEventFn = null;
TNode.$dispose.call(this);
@@ -122,8 +122,16 @@ var EltNode = klass({
var nd, docFragment;
//Holds the list of custonm attributes handlers instantiated for the current EltNode instance
this._customAttributesHandlers = {};
+ this._allCustomAttributesHandlers = [];
//Holds the values of the custonm attributes of the current EltNode instance
- this._customAttributesValues = {};
+ this._customAttributesData = {};
+ //Holds the list of all events for which listeners have been added to this node
+ this._allEventListerners = [];
+ if (this.evtHandlers) {
+ for (var i = 0; i < this.evtHandlers.length; i++) {
+ this._allEventListerners.push(this.evtHandlers[i].evtType);
+ }
+ }
if (this.tag === "svg") {
if (browser.supportsSvg()) {
@@ -137,7 +145,6 @@ var EltNode = klass({
nd = doc.createElementNS(this.nodeNS, this.tag);
} else {
if (this.atts && this.atts.length > 0) {
-
nd = doc.createElement(this.tag);
for (var i = 0; i < this.atts.length; i++) {
if (this.atts[i].name === "type") {
@@ -168,107 +175,57 @@ var EltNode = klass({
}
}
this.node = nd;
- this.refreshAttributes(true);
- //The eltNode is made adirty if it contains custom attributes. This way they can be refreshed with the full instance tree built.
- for (var item in this._customAttributesHandlers) {
- if(this._customAttributesHandlers.hasOwnProperty(item)) {
- this.adirty = true;
- break;
- }
- }
-
+ var addEL = (nd.addEventListener !== undefined); // tells if addEventListener is supported
+ if (!addEL) {
+ // create a callback function if addEventListener is not supported
+ var self = this;
+ this._attachEventFn = function (evt) {
+ self.handleEvent(evt);
+ };
+ }
+ this.refreshAttributes(true);
// attach event listener
var evh = this.evtHandlers, hnd;
- var addEL = (nd.addEventListener !== undefined); // tells if addEventListener is supported
- if (evh || this.isInput) {
- if (!addEL) {
- // create a callback function if addEventListener is not supported
- var self = this;
- this._attachEventFn = function (evt) {
- self.handleEvent(evt);
- };
- }
-
- var evts = {};
- // set or updates the event handlers
- if (evh) {
- for (var i = 0, sz = evh.length; sz > i; i++) {
- hnd = evh[i];
- var fullEvtType = "on" + hnd.evtType;
- //Adds custom event handlers (e.g. ontap)
- var customHandlers = hsp.getCustomAttributes(fullEvtType);
- if (customHandlers && customHandlers.length > 0) {
- for (var j = 0; j < customHandlers.length; j++) {
- var handler = this._createCustomAttributeHandler(fullEvtType, customHandlers[j], this.handleEvent.bind(this));
- if (handler.instance.setValue) {
- handler.instance.setValue(fullEvtType, fullEvtType);
- }
- }
- } else {
- evts[hnd.evtType] = true;
- if (addEL) {
- nd.addEventListener(hnd.evtType, this, false);
- } else {
- nd.attachEvent("on" + hnd.evtType, this._attachEventFn);
+ // set or updates the event handlers
+ if (evh) {
+ for (var i = 0, sz = evh.length; sz > i; i++) {
+ hnd = evh[i];
+ var fullEvtType = "on" + hnd.evtType;
+ //Adds custom event handlers (e.g. ontap)
+ var customHandlers = hsp.getCustomAttributeHandlers(fullEvtType, this.tag);
+ if (customHandlers && customHandlers.length > 0) {
+ for (var j = 0; j < customHandlers.length; j++) {
+ var handler = this._createCustomAttributeHandler(fullEvtType, customHandlers[j], this.handleEvent.bind(this));
+ if (handler.instance.$setValue) {
+ handler.instance.$setValue(fullEvtType, fullEvtType);
}
}
- }
- }
-
- if (this.isInput) {
- // 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]) {
- if (addEL) {
- nd.addEventListener(et, this, false);
- } else {
- nd.attachEvent("on" + et, this._attachEventFn);
- }
+ } else {
+ this._allEventListerners.push(hnd.evtType);
+ if (addEL) {
+ nd.addEventListener(hnd.evtType, this, false);
+ } else {
+ nd.attachEvent("on" + hnd.evtType, this._attachEventFn);
}
}
}
}
-
},
/**
* Event Listener callback
*/
handleEvent : function (evt) {
- var evh = this.evtHandlers, et = evt.type, result = null;
-
- // if the element is an input tag we synchronize the value
- if (this.isInput && this.inputModelExpIdx) {
- var exp = this.eh.getExpr(this.inputModelExpIdx);
- if (exp.setValue) {
- 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;
- }
- if (v!==this._lastValue) {
- // only set the value in the data model if the value in the field changed
- this._lastValue = v;
- 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();
- }
- }
- }
+ for (var i = 0; i < this._allCustomAttributesHandlers.length; i++) {
+ var handler = this._allCustomAttributesHandlers[i].instance;
+ if (handler.$handleEvent) {
+ handler.$handleEvent(evt);
}
}
+ var evh = this.evtHandlers, et = evt.type, result = null;
if (evh) {
for (var i = 0, sz = evh.length; sz > i; i++) {
if (evh[i].evtType === et) {
@@ -294,17 +251,6 @@ var EltNode = klass({
TNode.refresh.call(this);
},
- /**
- * After node creation process (i.e. after init or after refresh)
- */
- afterNodeCreation : function () {
- TNode.afterNodeCreation.call(this);
- if (this.adirty) {
- this.refreshAttributes();
- this.adirty = false;
- }
- },
-
/**
* Creates a custom attribute handler.
* @param {String} name the name of the custom attributes.
@@ -333,14 +279,14 @@ var EltNode = klass({
}
//Instantiates the handler and associate it to all attributes of the group
if (!alreadyInstantiated) {
- entry = {klass: customHandler.handler, instance: new customHandler.handler(this, callback), handledOnce: false};
+ entry = {klass: customHandler.handler, instance: new customHandler.handler(this, callback)};
for (var l = 0; l < customHandler.names.length; l++) {
if (typeof this._customAttributesHandlers[customHandler.names[l]] == "undefined") {
this._customAttributesHandlers[customHandler.names[l]] = [];
}
this._customAttributesHandlers[customHandler.names[l]].push(entry);
- this._customAttributesValues[customHandler.names[l]] = null;
}
+ this._allCustomAttributesHandlers.push(entry);
}
return entry;
},
@@ -350,61 +296,45 @@ var EltNode = klass({
* @param {Boolean} isEltCreation a flag indicating if it is the initial attributes refresh
*/
refreshAttributes : function (isEltCreation) {
- var nd = this.node, atts = this.atts, att, eh = this.eh, vs = this.vscope, nm, modelRefs = null;
+ var nd = this.node, atts = this.atts, att, eh = this.eh, vs = this.vscope, nm;
if (atts) {
for (var i = 0, sz = this.atts.length; sz > i; i++) {
att = atts[i];
- if (this.isInput && !this.inputModelExpIdx && (att.name === "value" || att.name === "model")) {
- if (att.textcfg && att.textcfg.length === 2 && att.textcfg[0] === '') {
- if (!modelRefs) {
- modelRefs = [];
- }
- modelRefs[att.name] = att.textcfg[1];
- }
- }
nm = att.name;
if (isEltCreation) {
//Adds custom attribute handlers (e.g. dropdown)
- var customHandlers = hsp.getCustomAttributes(nm);
+ var customHandlers = hsp.getCustomAttributeHandlers(nm, this.tag);
if (customHandlers && customHandlers.length > 0) {
for (var j = 0; j < customHandlers.length; j++) {
this._createCustomAttributeHandler(nm, customHandlers[j]);
}
+ this._customAttributesData[nm] = {};
+ if (att.textcfg && att.textcfg.length === 2 && att.textcfg[0] === '') {
+ this._customAttributesData[nm].exprIndex = att.textcfg[1];
+ }
}
}
- else {
- //During custom attribute refresh, execute setValue() on the handler only if the value of the attribute has changed.
- var customHandlers = this._customAttributesHandlers[nm];
- for (var j = 0; customHandlers && j < customHandlers.length; j++) {
- var customHandler = customHandlers[j];
- var newValue = att.getValue(eh, vs, null);
- if (!customHandler.handledOnce || this._customAttributesValues[nm] !== newValue) {
- if (customHandler.instance.setValue) {
- customHandler.instance.setValue(nm, newValue);
+ //During custom attribute refresh, execute setValue() on the handler only if the value of the attribute has changed.
+ var customHandlers = this._customAttributesHandlers[nm];
+ if (customHandlers) {
+ var newValue = att.getValue(eh, vs, null);
+ if (this._customAttributesData[nm].value !== newValue) {
+ for (var j = 0; customHandlers && j < customHandlers.length; j++) {
+ var customHandler = customHandlers[j];
+ if (customHandler.instance.$setValue) {
+ customHandler.instance.$setValue(nm, newValue);
}
- this._customAttributesValues[nm] = newValue;
- customHandler.handledOnce = true;
}
}
+ this._customAttributesData[nm].value = newValue;
}
- if (nm === "model") {
- // this is an hashspace extension attribute
- continue;
- } else if (isBooleanAttribute(nm)) {
+ else if (isBooleanAttribute(nm)) {
//this is equivalent to calling sth like: node.required = truthy / falsy;
//a browser will remove this attribute if a provided value is falsy
//http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#boolean-attributes
nd[nm] = att.getValue(eh, vs, "");
- } else if (nm === "class") {
- //this is a custom attribute
- continue;
-
- } else if (nm === "value") {
- // value attribute must be changed directly as the node attribute is only used for the default value
- if (!this.isInput || nd.type === "radio") {
- nd.value = att.getValue(eh, vs, "");
- }
- } else {
+ }
+ else {
try {
nd.setAttribute(att.name, att.getValue(eh, vs, null));
}
@@ -421,38 +351,90 @@ var EltNode = klass({
}
}
- if (modelRefs) {
- // set the inputModelExpIdx property that reference the expression index to use for the model binding
- var ref = modelRefs["model"];
- if (!ref) {
- ref = modelRefs["value"];
- }
- if (ref) {
- this.inputModelExpIdx = ref;
+ for (var i = 0; i < this._allCustomAttributesHandlers.length; i++) {
+ var handler = this._allCustomAttributesHandlers[i].instance;
+ if (handler.$afterRefreshAttributes) {
+ handler.$afterRefreshAttributes();
}
}
+ },
+
+ /** API methods for custom attributes **/
- if (this.inputModelExpIdx) {
- // update the checked state (must be done at the end as the value attribute may not have been set)
- var exp = this.eh.getExpr(this.inputModelExpIdx), v1 = '' + exp.getValue(vs, this.eh, "");
- if (v1 !== this._lastValue) {
- // only set the value if it changed in the model since last sync
- this._lastValue = v1;
- if (nd.type === "radio") {
- var v2 = '' + nd.value;
- nd.checked = (v1 === v2);
- } else if (nd.type === "checkbox") {
- var v2 = '' + nd.checked;
- if (v1 !== v2) {
- nd.checked = !nd.checked;
+ /**
+ * Sets the attribute value in the data model.
+ * @param {String} name the name of the attribute
+ * @param {String} value the value of the attribute.
+ * @return {Boolean} true if the value was successfully set
+ */
+ setAttributeValueInDataModel: function (name, value) {
+ if (this._customAttributesData[name]) {
+ var exprIndex = this._customAttributesData[name].exprIndex;
+ if (this.eh && typeof exprIndex !== "undefined") {
+ var expression = this.eh.getExpr(exprIndex);
+ if (expression.setValue && this._customAttributesData[name].value !== value ) {
+ var currentValue = expression.getValue(this.vscope, this.eh);
+ if (value !== currentValue) {
+ expression.setValue(this.vscope, value);
+ // force refresh to resync other fields linked to the same data immediately
+ hsp.refresh();
+ return true;
}
- } else if (v1!=nd.value) {
- //only update if value is changing
- //log("[EltNode] Node value update: current value:["+nd.value+"] new value:["+v1+"]");
- nd.value = v1;
}
}
}
+ return false;
+ },
+
+ /**
+ * Registers a list of event listeners, they are added to the current element if not already part of the evtHandlers.
+ * @param {Array} eventNames the list of events
+ */
+ registerEventListeners: function(eventNames) {
+ var isAddEL = (this.node.addEventListener !== undefined);
+ for (var i = 0; i < eventNames.length; i++) {
+ var eventName = eventNames[i];
+ if (this._allEventListerners.indexOf(eventName) === -1) {
+ this._allEventListerners.push(eventName);
+ if (isAddEL) {
+ this.node.addEventListener(eventName, this, false);
+ } else {
+ this.node.attachEvent("on" + eventName, this._attachEventFn);
+ }
+ }
+ }
+ },
+
+ /**
+ * Returns the first ancestor with the given custom attribute.
+ * @param {String} name of the custom attribute
+ * @return {EltNode} the node instance.
+ */
+ getAncestorByCustomAttribute: function(name) {
+ var parent = this.parent;
+ while (parent) {
+ if (parent._customAttributesHandlers[name]) {
+ break;
+ }
+ else {
+ parent = parent.parent;
+ }
+ }
+ return parent;
+ },
+
+ /**
+ * Returns the an array of the custom attribute handler instances for a given custom attribute.
+ * @param {String} name of the custom attribute
+ * @return {EltNode} the node instance.
+ */
+ getCustomAttributeHandlerInstances: function(name) {
+ var result = [];
+ var handlers = this._customAttributesHandlers[name];
+ for (var i = 0; i < handlers.length; i++) {
+ result.push(handlers[i].instance);
+ }
+ return result;
}
});
diff --git a/hsp/rt/tnode.js b/hsp/rt/tnode.js
index 5cee9d7..d697d6a 100644
--- a/hsp/rt/tnode.js
+++ b/hsp/rt/tnode.js
@@ -223,18 +223,6 @@ var TNode = klass({
}
},
- /**
- * After node creation process, started at the end of the init() or refresh() of $root, once the node instance tree is full created.
- */
- afterNodeCreation : function () {
- var cn = this.childNodes;
- if (cn) {
- for (var i = 0, sz = cn.length; sz > i; i++) {
- cn[i].afterNodeCreation();
- }
- }
- },
-
/**
* Abstract function that should be implemented by sub-classes
*/
diff --git a/test/gestures/doubleTap.spec.hsp b/test/gestures/doubleTap.spec.hsp
index 3d70427..48acc18 100644
--- a/test/gestures/doubleTap.spec.hsp
+++ b/test/gestures/doubleTap.spec.hsp
@@ -17,7 +17,7 @@
* Taken from Aria Templates: https://github.com/ariatemplates/ariatemplates/blob/master/test/aria/touch/gestures/DoubleTap.js
*/
-require("hsp/gestures/doubleTap");
+require("hsp/gestures/doubleTap").register();
var fireEvent=require("hsp/utils/eventgenerator").fireEvent,
touchEventMap = require("hsp/gestures/touchEvent").touchEventMap;
diff --git a/test/gestures/drag.spec.hsp b/test/gestures/drag.spec.hsp
index 14a8f70..9d1f1ff 100644
--- a/test/gestures/drag.spec.hsp
+++ b/test/gestures/drag.spec.hsp
@@ -17,7 +17,7 @@
* Taken from Aria Templates: https://github.com/ariatemplates/ariatemplates/blob/master/test/aria/touch/gestures/Drag.js
*/
-require("hsp/gestures/drag");
+require("hsp/gestures/drag").register();
var fireEvent=require("hsp/utils/eventgenerator").fireEvent,
touchEventMap = require("hsp/gestures/touchEvent").touchEventMap;
diff --git a/test/gestures/longPress.spec.hsp b/test/gestures/longPress.spec.hsp
index 06adf53..1239c83 100644
--- a/test/gestures/longPress.spec.hsp
+++ b/test/gestures/longPress.spec.hsp
@@ -17,7 +17,7 @@
* Taken from Aria Templates: https://github.com/ariatemplates/ariatemplates/blob/master/test/aria/touch/gestures/LongPress.js
*/
-require("hsp/gestures/longPress");
+require("hsp/gestures/longPress").register();
var fireEvent=require("hsp/utils/eventgenerator").fireEvent,
touchEventMap = require("hsp/gestures/touchEvent").touchEventMap;
diff --git a/test/gestures/pinch.spec.hsp b/test/gestures/pinch.spec.hsp
index 9871528..502afd9 100644
--- a/test/gestures/pinch.spec.hsp
+++ b/test/gestures/pinch.spec.hsp
@@ -17,7 +17,7 @@
* Taken from Aria Templates: https://github.com/ariatemplates/ariatemplates/blob/master/test/aria/touch/gestures/Pinch.js
*/
-require("hsp/gestures/pinch");
+require("hsp/gestures/pinch").register();
var fireEvent=require("hsp/utils/eventgenerator").fireEvent,
touchEventMap = require("hsp/gestures/touchEvent").touchEventMap;
diff --git a/test/gestures/singleTap.spec.hsp b/test/gestures/singleTap.spec.hsp
index 0a0acf2..77863e8 100644
--- a/test/gestures/singleTap.spec.hsp
+++ b/test/gestures/singleTap.spec.hsp
@@ -17,7 +17,7 @@
* Taken from Aria Templates: https://github.com/ariatemplates/ariatemplates/blob/master/test/aria/touch/gestures/SingleTap.js
*/
-require("hsp/gestures/singleTap");
+require("hsp/gestures/singleTap").register();
var fireEvent=require("hsp/utils/eventgenerator").fireEvent,
touchEventMap = require("hsp/gestures/touchEvent").touchEventMap;
diff --git a/test/gestures/swipe.spec.hsp b/test/gestures/swipe.spec.hsp
index 2de2f92..1c00cee 100644
--- a/test/gestures/swipe.spec.hsp
+++ b/test/gestures/swipe.spec.hsp
@@ -17,7 +17,7 @@
* Taken from Aria Templates: https://github.com/ariatemplates/ariatemplates/blob/master/test/aria/touch/gestures/Swipe.js
*/
-require("hsp/gestures/swipe");
+require("hsp/gestures/swipe").register();
var fireEvent=require("hsp/utils/eventgenerator").fireEvent,
touchEventMap = require("hsp/gestures/touchEvent").touchEventMap;
diff --git a/test/gestures/tap.spec.hsp b/test/gestures/tap.spec.hsp
index 9fa38d7..2fde4e4 100644
--- a/test/gestures/tap.spec.hsp
+++ b/test/gestures/tap.spec.hsp
@@ -17,7 +17,7 @@
* Taken from Aria Templates: https://github.com/ariatemplates/ariatemplates/blob/master/test/aria/touch/gestures/Tap.js
*/
-require("hsp/gestures/tap");
+require("hsp/gestures/tap").register();
var fireEvent=require("hsp/utils/eventgenerator").fireEvent,
touchEventMap = require("hsp/gestures/touchEvent").touchEventMap;
diff --git a/test/rt/attributes/class.spec.hsp b/test/rt/attributes/class.spec.hsp
index 821d04d..fc12e0e 100644
--- a/test/rt/attributes/class.spec.hsp
+++ b/test/rt/attributes/class.spec.hsp
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2014 Amadeus s.a.s.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
var hsp = require("hsp/rt");
var $set = require('hsp/$set');
diff --git a/test/rt/input.spec.hsp b/test/rt/attributes/modelvalue.spec.hsp
similarity index 89%
rename from test/rt/input.spec.hsp
rename to test/rt/attributes/modelvalue.spec.hsp
index adc31a1..fd8a64f 100644
--- a/test/rt/input.spec.hsp
+++ b/test/rt/attributes/modelvalue.spec.hsp
@@ -1,6 +1,5 @@
-
/*
- * Copyright 2012 Amadeus s.a.s.
+ * Copyright 2014 Amadeus s.a.s.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -16,7 +15,8 @@
var hsp=require("hsp/rt"),
fireEvent=require("hsp/utils/eventgenerator").fireEvent,
- json=require("hsp/json");
+ json=require("hsp/json"),
+ ht=require("hsp/utils/hashtester");
{template inputSample(data)}
All the following inputs are synchronized:
@@ -234,3 +234,32 @@ describe("Input Elements", function () {
var n = html5NumberInput({value: 5});
});
});
+
+{template test1(data)}
+
+{/template}
+
+// normalize carriage returns to avoid OS discrepancies
+function normalizeCR(s) {
+ return s.replace(/\r\n|[\r\n]/gi,"\n");
+}
+
+describe("Textarea Elements", function () {
+ it("validates model synchronization", function () {
+ var h=ht.newTestContext();
+ var model={text:"line 1\nline2"};
+
+ test1(model).render(h.container);
+ expect(normalizeCR(h("textarea").value())).to.equal("line 1\nline2");
+
+ // change value from the DOM
+ h("textarea").type("AAA\nBBB\nCCC");
+ expect(normalizeCR(model.text)).to.equal("AAA\nBBB\nCCC");
+
+ // change value from the model
+ h.$set(model,"text","Hello\nWorld!");
+ expect(normalizeCR(h("textarea").value())).to.equal("Hello\nWorld!");
+
+ h.$dispose();
+ });
+});
diff --git a/test/rt/customAttributes.spec.hsp b/test/rt/customAttributes.spec.hsp
index c576abf..2927ddc 100644
--- a/test/rt/customAttributes.spec.hsp
+++ b/test/rt/customAttributes.spec.hsp
@@ -26,35 +26,30 @@ var klass = klass=require("hsp/klass");
{/template}
{template test5()}
-