can-stache-bindings
Advanced tools
Comparing version 3.0.0-pre.21 to 3.0.0-pre.22
@@ -29,3 +29,2 @@ // # can/view/bindings/bindings.js | ||
var dev = require('can-util/js/dev/dev'); | ||
var isArray = require('can-util/js/is-array/is-array'); | ||
var types = require('can-util/js/types/types'); | ||
@@ -517,144 +516,36 @@ var last = require('can-util/js/last/last'); | ||
if(!event) { | ||
if(prop === "innerHTML") { | ||
event = ["blur","change"]; | ||
} | ||
else { | ||
if(attr.special[prop] && attr.special[prop].addEventListener) { | ||
event = prop; | ||
} else { | ||
event = "change"; | ||
} | ||
} | ||
if(!isArray(event)) { | ||
event = [event]; | ||
} | ||
var hasChildren = el.nodeName.toLowerCase() === "select", | ||
isMultiselectValue = prop === "value" && hasChildren && el.multiple, | ||
isStringValue, | ||
lastSet, | ||
scheduledAsyncSet = false, | ||
timer, | ||
// Sets the element property or attribute. | ||
set = function(newVal){ | ||
// Templates write parent's out before children. This should probably change. | ||
// But it means we don't do a set immediately. | ||
if(hasChildren && !scheduledAsyncSet) { | ||
clearTimeout(timer); | ||
timer = setTimeout(function(){ | ||
set(newVal); | ||
},1); | ||
} | ||
lastSet = newVal; | ||
if(isMultiselectValue) { | ||
if (newVal && typeof newVal === 'string') { | ||
newVal = newVal.split(";"); | ||
isStringValue = true; | ||
} | ||
// When given something else, try to make it an array and deal with it | ||
else if (newVal) { | ||
newVal = makeArray(newVal); | ||
} else { | ||
newVal = []; | ||
} | ||
// Make an object containing all the options passed in for convenient lookup | ||
var isSelected = {}; | ||
each(newVal, function (val) { | ||
isSelected[val] = true; | ||
}); | ||
// Go through each <option/> element, if it has a value and selected property (its a valid option), then | ||
// set its selected property if it was in the list of vals that were just set. | ||
each(el.childNodes, function (option) { | ||
if (('value' in option) && ('selected' in option)) { | ||
option.selected = !! isSelected[option.value]; | ||
} | ||
}); | ||
if(bindingData.legacyBindings && hasChildren && | ||
("selectedIndex" in el) && prop === "value") { | ||
attr.setAttrOrProp(el, prop, newVal == null ? "" : newVal); | ||
} else { | ||
if(!bindingData.legacyBindings && hasChildren && ("selectedIndex" in el) && prop === "value" ) { | ||
attr.setSelectValue(el, newVal); | ||
} else { | ||
attr.setAttrOrProp(el, prop, newVal == null ? "" : newVal); | ||
} | ||
attr.setAttrOrProp(el, prop, newVal); | ||
} | ||
return newVal; | ||
}, | ||
// Returns the value of the element property or attribute. | ||
get = function(){ | ||
if(isMultiselectValue) { | ||
var values = [], | ||
children = el.childNodes; | ||
each(children, function (child) { | ||
if (child.selected && child.value) { | ||
values.push(child.value); | ||
} | ||
}); | ||
return isStringValue ? values.join(";"): values; | ||
} else if(hasChildren && ("selectedIndex" in el) && el.selectedIndex === -1) { | ||
return undefined; | ||
} | ||
return attr.get(el, prop); | ||
}; | ||
// If the element has children like `<select>`, those | ||
// elements are hydrated (by can.view.target) after the select and only then | ||
// get their `value`s set. This make sure that when the value is set, | ||
// it will happen after the children are setup. | ||
if(hasChildren) { | ||
// have to set later | ||
setTimeout(function(){ | ||
scheduledAsyncSet = true; | ||
},1); | ||
// The following would allow a select's value | ||
// to be undefined. | ||
// el.selectedIndex = -1; | ||
if(isMultiselectValue) { | ||
prop = "values"; | ||
} | ||
var observer; | ||
return compute(get(),{ | ||
return compute(get(), { | ||
on: function(updater){ | ||
each(event, function(eventName){ | ||
canEvent.on.call(el,eventName, updater); | ||
}); | ||
if(hasChildren) { | ||
var onMutation = function (mutations) { | ||
if(stickyCompute) { | ||
set(stickyCompute()); | ||
} | ||
updater(); | ||
}; | ||
var MO = getMutationObserver(); | ||
if(MO) { | ||
observer = new MO(onMutation); | ||
observer.observe(el, { | ||
childList: true, | ||
subtree: true | ||
}); | ||
} else { | ||
// TODO: Remove in 3.0. Can't store a function b/c Zepto doesn't support it. | ||
domData.set.call(el, "canBindingCallback", {onMutation: onMutation}); | ||
} | ||
} | ||
canEvent.on.call(el,event, updater); | ||
}, | ||
off: function(updater){ | ||
each(event, function(eventName){ | ||
canEvent.off.call(el,eventName, updater); | ||
}); | ||
if(hasChildren) { | ||
if(getMutationObserver()) { | ||
observer.disconnect(); | ||
} else { | ||
domData.clean.call(el, "canBindingCallback"); | ||
} | ||
} | ||
canEvent.off.call(el,event, updater); | ||
}, | ||
@@ -661,0 +552,0 @@ get: get, |
{ | ||
"name": "can-stache-bindings", | ||
"version": "3.0.0-pre.21", | ||
"version": "3.0.0-pre.22", | ||
"description": "Default binding syntaxes for can-stache", | ||
@@ -27,12 +27,2 @@ "homepage": "http://canjs.com", | ||
"main": "dist/cjs/can-stache-bindings", | ||
"browser": { | ||
"transform": [ | ||
"cssify" | ||
] | ||
}, | ||
"browserify": { | ||
"transform": [ | ||
"cssify" | ||
] | ||
}, | ||
"keywords": [ | ||
@@ -44,12 +34,2 @@ "canjs", | ||
"main": "can-stache-bindings", | ||
"configDependencies": [ | ||
"live-reload" | ||
], | ||
"npmIgnore": [ | ||
"documentjs", | ||
"testee", | ||
"generator-donejs", | ||
"donejs-cli", | ||
"steal-tools" | ||
], | ||
"npmAlgorithm": "flat" | ||
@@ -61,3 +41,3 @@ }, | ||
"can-observation": "^3.0.0-pre.8", | ||
"can-util": "^3.0.0-pre.34", | ||
"can-util": "^3.0.0-pre.44", | ||
"can-view-callbacks": "^3.0.0-pre.4", | ||
@@ -74,3 +54,2 @@ "can-view-live": "^3.0.0-pre.1", | ||
"can-view-nodelist": "^3.0.0-pre.2 ", | ||
"cssify": "^1.0.2", | ||
"bit-docs": "0.0.7", | ||
@@ -77,0 +56,0 @@ "done-serve": "^0.2.0", |
@@ -12,3 +12,5 @@ var stacheBindings = require('can-stache-bindings'); | ||
var domAttr = require("can-util/dom/attr/attr"); | ||
var domData = require('can-util/dom/data/data'); | ||
var domDispatch = require("can-util/dom/dispatch/dispatch"); | ||
var domMutate = require('can-util/dom/mutate/mutate'); | ||
@@ -202,1 +204,80 @@ | ||
}); | ||
test("Binding to a special property - values", function(){ | ||
var template = stache("<select multiple {($values)}='values'><option value='one'>One</option><option value='two'></option></select>"); | ||
var map = new DefineMap({ | ||
values: [] | ||
}); | ||
var slice = [].slice; | ||
var select = template(map).firstChild; | ||
var option1 = select.firstChild; | ||
var option2 = option1.nextSibling; | ||
option2.selected = true; | ||
canEvent.trigger.call(select, "change"); | ||
deepEqual(slice.call(map.values), ["two"], "two is chosen"); | ||
map.values = ["one"]; | ||
equal(option1.selected, true, "option1 selected"); | ||
equal(option2.selected, false, "option2 not selected"); | ||
}); | ||
test("Binding to a special property - option's selected", function(){ | ||
var template = stache("<select><option {($selected)}='a' value='one'>One</option><option {($selected)}='b' value='two'>Two</option></select>"); | ||
var map = new DefineMap({ | ||
a: true, | ||
b: false | ||
}); | ||
var select = template(map).firstChild; | ||
var option1 = select.firstChild; | ||
var option2 = option1.nextSibling; | ||
option2.selected = true; | ||
canEvent.trigger.call(select, "change"); | ||
equal(map.a, false, "map.a false"); | ||
equal(map.b, true, "map.b true"); | ||
}); | ||
test("Can two way bind to focused", function(){ | ||
var template = stache("<input {($focused)}='show' type='text'/>"); | ||
var map = new DefineMap({ | ||
show: false | ||
}); | ||
var ta = document.getElementById("qunit-fixture"); | ||
var frag = template(map); | ||
var input = frag.firstChild; | ||
ta.appendChild(frag); | ||
map.show = true; | ||
if(!document.hasFocus()) { | ||
domDispatch.call(input, "focus"); | ||
} | ||
ok(input === document.activeElement, "now focused"); | ||
domAttr.set(input, "focused", false); | ||
if(!document.hasFocus()) { | ||
domDispatch.call(input, "blur"); | ||
} | ||
ok(input !== document.activeElement, "not focused"); | ||
equal(map.show, false, "set the boolean"); | ||
}); | ||
test("Can listed to the 'focused' event", function(){ | ||
var template = stache("<input ($focused)='changed()' type='text'/>"); | ||
var map = new DefineMap({ | ||
changed: function(){ | ||
ok(true, "this was called"); | ||
} | ||
}); | ||
var ta = document.getElementById("qunit-fixture"); | ||
var frag = template(map); | ||
var input = frag.firstChild; | ||
ta.appendChild(frag); | ||
domAttr.set(input, "focused", true); | ||
if(!document.hasFocus()) { | ||
domDispatch.call(input, "focus"); | ||
} | ||
}); |
@@ -597,54 +597,2 @@ require("./bindings-define-test"); | ||
test("can-value select multiple with values seperated by a ;", function () { | ||
var template = stache( | ||
"<select can-value='color' multiple>" + | ||
"<option value='red'>Red</option>" + | ||
"<option value='green'>Green</option>" + | ||
"<option value='ultraviolet'>Ultraviolet</option>" + | ||
"</select>"); | ||
var map = new CanMap({ | ||
color: "red" | ||
}); | ||
stop(); | ||
var frag = template(map); | ||
var ta = document.getElementById("qunit-fixture"); | ||
ta.appendChild(frag); | ||
var inputs = ta.getElementsByTagName("select"), | ||
options = inputs[0].getElementsByTagName('option'); | ||
// Wait for Multiselect.set() to be called. | ||
setTimeout(function() { | ||
equal(inputs[0].value, 'red', "default value set"); | ||
map.attr("color", "green"); | ||
equal(inputs[0].value, 'green', "alternate value set"); | ||
options[0].selected = true; | ||
equal(map.attr("color"), "green", "not yet updated from input"); | ||
canEvent.trigger.call(inputs[0], "change"); | ||
equal(map.attr("color"), "red;green", "updated from input"); | ||
map.removeAttr("color"); | ||
equal(inputs[0].value, '', "attribute removed from map"); | ||
options[1].selected = true; | ||
canEvent.trigger.call(inputs[0], "change"); | ||
equal(map.attr("color"), "green", "updated from input"); | ||
map.attr("color", "red;green"); | ||
ok(options[0].selected, 'red option selected from map'); | ||
ok(options[1].selected, 'green option selected from map'); | ||
ok(!options[2].selected, 'ultraviolet option NOT selected from map'); | ||
ta.removeChild(ta.firstChild); | ||
start(); | ||
}, 1); | ||
}); | ||
test("can-value select multiple with values cross bound to an array", function () { | ||
@@ -1560,4 +1508,2 @@ var template = stache( | ||
test("two-way element empty value (1996)", function(){ | ||
var template = stache("<input can-value='age'/>"); | ||
@@ -1564,0 +1510,0 @@ |
Sorry, the diff of this file is not supported yet
13
154852
2884
Updatedcan-util@^3.0.0-pre.44