Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactored select<->object mapping out into a separate component call…

…ed "selectExtensions"
  • Loading branch information...
commit 9e561535a90b96478142ff05fa983a2d81b4ebbc 1 parent 5c1340b
@SteveSanderson SteveSanderson authored
View
66 build/output/knockout-latest.js
@@ -614,7 +614,33 @@ ko.dependentObservable = function (evaluatorFunction, evaluatorFunctionTarget, o
evaluate();
return dependentObservable;
};
-ko.dependentObservable.__ko_proto__ = ko.observable;/// <reference path="../utils.js" />
+ko.dependentObservable.__ko_proto__ = ko.observable;(function () {
+ ko.selectExtensions = {
+ readValue : function(element) {
+ if (element.tagName == 'OPTION') {
+ var valueAttributeValue = element.getAttribute("value");
+ if (valueAttributeValue !== null)
+ return valueAttributeValue;
+ return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
+ } else if (element.tagName == 'SELECT')
+ return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
+ else
+ return element.value;
+ },
+
+ writeValue: function(element, value) {
+ if (element.tagName == 'SELECT') {
+ for (var i = element.options.length - 1; i >= 0; i--) {
+ if (ko.selectExtensions.readValue(element.options[i]) == value) {
+ element.selectedIndex = i;
+ break;
+ }
+ }
+ } else
+ element.value = value;
+ }
+ };
+})();/// <reference path="../utils.js" />
ko.jsonExpressionRewriting = (function () {
var restoreCapturedTokensRegex = /\[ko_token_(\d+)\]/g;
@@ -820,39 +846,17 @@ ko.bindingHandlers.enable = {
ko.bindingHandlers.disable = { update: function (element, value) { ko.bindingHandlers.enable.update(element, !ko.utils.unwrapObservable(value)); } };
ko.bindingHandlers.value = {
- readElementValue: function(element) {
- if (element.tagName == 'OPTION') {
- var valueAttributeValue = element.getAttribute("value");
- if (valueAttributeValue !== null)
- return valueAttributeValue;
- return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
- } else if (element.tagName == 'SELECT')
- return element.selectedIndex >= 0 ? ko.bindingHandlers.value.readElementValue(element.options[element.selectedIndex]) : undefined;
- else
- return element.value;
- },
- writeElementValue: function(element, value) {
- if (element.tagName == 'SELECT') {
- for (var i = element.options.length - 1; i >= 0; i--) {
- if (ko.bindingHandlers.value.readElementValue(element.options[i]) == value) {
- element.selectedIndex = i;
- break;
- }
- }
- } else
- element.value = value;
- },
init: function (element, value, allBindings) {
var eventName = allBindings.valueUpdate || "change";
if (ko.isWriteableObservable(value))
- ko.utils.registerEventHandler(element, eventName, function () { value(ko.bindingHandlers.value.readElementValue(this)); });
+ ko.utils.registerEventHandler(element, eventName, function () { value(ko.selectExtensions.readValue(this)); });
else if (allBindings._ko_property_writers && allBindings._ko_property_writers.value)
- ko.utils.registerEventHandler(element, eventName, function () { allBindings._ko_property_writers.value(ko.bindingHandlers.value.readElementValue(this)); });
+ ko.utils.registerEventHandler(element, eventName, function () { allBindings._ko_property_writers.value(ko.selectExtensions.readValue(this)); });
},
update: function (element, value) {
var newValue = ko.utils.unwrapObservable(value);
- if (newValue != ko.bindingHandlers.value.readElementValue(element)) {
- var applyValueAction = function () { ko.bindingHandlers.value.writeElementValue(element, newValue); };
+ if (newValue != ko.selectExtensions.readValue(element)) {
+ var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
applyValueAction();
// Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
@@ -873,7 +877,7 @@ ko.bindingHandlers.options = {
var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
return node.tagName && node.tagName == "OPTION" && node.selected;
}), function (node) {
- return ko.bindingHandlers.value.readElementValue(node) || node.innerText || node.textContent;
+ return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
});
value = ko.utils.unwrapObservable(value);
@@ -904,7 +908,7 @@ ko.bindingHandlers.options = {
var newOptions = element.getElementsByTagName("OPTION");
var countSelectionsRetained = 0;
for (var i = 0, j = newOptions.length; i < j; i++) {
- if (ko.utils.arrayIndexOf(previousSelectedValues, ko.bindingHandlers.value.readElementValue(newOptions[i])) >= 0) {
+ if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
ko.utils.setOptionNodeSelectionState(newOptions[i], true);
countSelectionsRetained++;
}
@@ -921,7 +925,7 @@ ko.bindingHandlers.selectedOptions = {
for (var i = 0, j = nodes.length; i < j; i++) {
var node = nodes[i];
if ((node.tagName == "OPTION") && node.selected)
- result.push(ko.bindingHandlers.value.readElementValue(node));
+ result.push(ko.selectExtensions.readValue(node));
}
return result;
},
@@ -941,7 +945,7 @@ ko.bindingHandlers.selectedOptions = {
for (var i = 0, j = nodes.length; i < j; i++) {
var node = nodes[i];
if (node.tagName == "OPTION")
- ko.utils.setOptionNodeSelectionState(node, ko.utils.arrayIndexOf(newValue, ko.bindingHandlers.value.readElementValue(node)) >= 0);
+ ko.utils.setOptionNodeSelectionState(node, ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0);
}
}
}
View
15 build/output/knockout-latest.min.js
@@ -26,6 +26,8 @@ ko.observableArray=function(e){var a=new ko.observable(e);ko.utils.arrayForEach(
a.removeAll=function(b){if(!b)return[];return a.remove(function(c){return ko.utils.arrayIndexOf(b,c)>=0})};a.destroy=function(b){for(var c=a(),d=typeof b=="function"?b:function(g){return g===b},f=c.length-1;f>=0;f--)if(d(c[f]))c[f]._destroy=true;a.valueHasMutated()};a.destroyAll=function(b){if(!b)return[];return a.destroy(function(c){return ko.utils.arrayIndexOf(b,c)>=0})};a.indexOf=function(b){var c=a();return ko.utils.arrayIndexOf(c,b)};return a};
ko.dependentObservable=function(e,a,b){function c(){ko.utils.arrayForEach(h,function(j){j.dispose()});h=[]}function d(j){c();ko.utils.arrayForEach(j,function(l){h.push(l.subscribe(f))})}function f(){if(!k&&b&&typeof b.disposeWhen=="function")if(b.disposeWhen()){g.dispose();return}try{ko.dependencyDetection.begin();i=a?e.call(a):e()}catch(j){throw j;}finally{var l=ko.utils.arrayGetDistinctValues(ko.dependencyDetection.end());d(l)}g.notifySubscribers(i);k=false}function g(){if(arguments.length>0)throw"Cannot write a value to a dependentObservable. Do not pass any parameters to it";
ko.dependencyDetection.registerDependency(g);return i}if(typeof e!="function")throw"Pass a function that returns the value of the dependentObservable";var h=[],i,k=true;g.__ko_proto__=ko.dependentObservable;g.getDependenciesCount=function(){return h.length};g.dispose=function(){c()};ko.subscribable.call(g);f();return g};ko.dependentObservable.__ko_proto__=ko.observable;
+(function(){ko.selectExtensions={readValue:function(e){if(e.tagName=="OPTION"){var a=e.getAttribute("value");if(a!==null)return a;return ko.utils.domData.get(e,ko.bindingHandlers.options.optionValueDomDataKey)}else return e.tagName=="SELECT"?e.selectedIndex>=0?ko.selectExtensions.readValue(e.options[e.selectedIndex]):undefined:e.value},writeValue:function(e,a){if(e.tagName=="SELECT")for(var b=e.options.length-1;b>=0;b--){if(ko.selectExtensions.readValue(e.options[b])==a){e.selectedIndex=b;break}}else e.value=
+a}}})();
ko.jsonExpressionRewriting=function(){function e(d,f){return d.replace(a,function(g,h){return f[h]})}var a=/\[ko_token_(\d+)\]/g,b=/^[\_$a-z][\_$a-z]*(\[.*?\])*(\.[\_$a-z][\_$a-z]*(\[.*?\])*)*$/i,c=["true","false"];return{parseJson:function(d){d=ko.utils.stringTrim(d);if(d.length<3)return{};for(var f=[],g=null,h,i=d.charAt(0)=="{"?1:0;i<d.length;i++){var k=d.charAt(i);if(g===null)switch(k){case '"':case "'":case "/":g=i;h=k;break;case "{":g=i;h="}";break;case "[":g=i;h="]";break}else if(k==h){k=d.substring(g,
i+1);f.push(k);var j="[ko_token_"+(f.length-1)+"]";d=d.substring(0,g)+j+d.substring(i+1);i-=k.length-j.length;g=null}}g={};d=d.split(",");h=0;for(i=d.length;h<i;h++){j=d[h];var l=j.indexOf(":");if(l>0&&l<j.length-1){k=ko.utils.stringTrim(j.substring(0,l));j=ko.utils.stringTrim(j.substring(l+1));if(k.charAt(0)=="{")k=k.substring(1);if(j.charAt(j.length-1)=="}")j=j.substring(0,j.length-1);k=ko.utils.stringTrim(e(k,f));j=ko.utils.stringTrim(e(j,f));g[k]=j}}return g},insertPropertyAccessorsIntoJson:function(d){var f=
ko.jsonExpressionRewriting.parseJson(d),g=[];for(var h in f){var i=f[h],k;k=i;k=ko.utils.arrayIndexOf(c,ko.utils.stringTrim(k).toLowerCase())>=0?false:k.match(b)!==null;if(k){g.length>0&&g.push(", ");g.push(h+" : function(__ko_value) { "+i+" = __ko_value; }")}}if(g.length>0){f=g.join("");d=d+", '_ko_property_writers' : { "+f+" } "}return d}}}();
@@ -33,14 +35,13 @@ ko.jsonExpressionRewriting.parseJson(d),g=[];for(var h in f){var i=f[h],k;k=i;k=
"function"&&ko.bindingHandlers[i].init(e,d[i],d,b);for(i in d)ko.bindingHandlers[i]&&typeof ko.bindingHandlers[i].update=="function"&&ko.bindingHandlers[i].update(e,d[i],d,b)},null,{disposeWhen:function(){return!ko.utils.domNodeIsAttachedToDocument(e)}});c=false};ko.applyBindings=function(e,a){var b=ko.utils.getElementsHavingAttribute(e,"data-bind");ko.utils.arrayForEach(b,function(c){ko.applyBindingsToNode(c,null,a)})}})();
ko.bindingHandlers.click={init:function(e,a,b,c){ko.utils.registerEventHandler(e,"click",function(d){try{a.call(c)}finally{if(d.preventDefault)d.preventDefault();else d.returnValue=false}})}};ko.bindingHandlers.submit={init:function(e,a,b,c){if(typeof a!="function")throw Error("The value for a submit binding must be a function to invoke on submit");ko.utils.registerEventHandler(e,"submit",function(d){try{a.call(c,e)}finally{if(d.preventDefault)d.preventDefault();else d.returnValue=false}})}};
ko.bindingHandlers.visible={update:function(e,a){a=ko.utils.unwrapObservable(a);var b=e.style.display!="none";if(a&&!b)e.style.display="";else if(!a&&b)e.style.display="none"}};ko.bindingHandlers.enable={update:function(e,a){if((a=ko.utils.unwrapObservable(a))&&e.disabled)e.removeAttribute("disabled");else if(!a&&!e.disabled)e.disabled=true}};ko.bindingHandlers.disable={update:function(e,a){ko.bindingHandlers.enable.update(e,!ko.utils.unwrapObservable(a))}};
-ko.bindingHandlers.value={readElementValue:function(e){if(e.tagName=="OPTION"){var a=e.getAttribute("value");if(a!==null)return a;return ko.utils.domData.get(e,ko.bindingHandlers.options.optionValueDomDataKey)}else return e.tagName=="SELECT"?e.selectedIndex>=0?ko.bindingHandlers.value.readElementValue(e.options[e.selectedIndex]):undefined:e.value},writeElementValue:function(e,a){if(e.tagName=="SELECT")for(var b=e.options.length-1;b>=0;b--){if(ko.bindingHandlers.value.readElementValue(e.options[b])==
-a){e.selectedIndex=b;break}}else e.value=a},init:function(e,a,b){var c=b.valueUpdate||"change";if(ko.isWriteableObservable(a))ko.utils.registerEventHandler(e,c,function(){a(ko.bindingHandlers.value.readElementValue(this))});else b._ko_property_writers&&b._ko_property_writers.value&&ko.utils.registerEventHandler(e,c,function(){b._ko_property_writers.value(ko.bindingHandlers.value.readElementValue(this))})},update:function(e,a){var b=ko.utils.unwrapObservable(a);if(b!=ko.bindingHandlers.value.readElementValue(e)){var c=
-function(){ko.bindingHandlers.value.writeElementValue(e,b)};c();e.tagName=="SELECT"&&setTimeout(c,0)}}};
-ko.bindingHandlers.options={update:function(e,a,b){if(e.tagName!="SELECT")throw Error("options binding applies only to SELECT elements");var c=ko.utils.arrayMap(ko.utils.arrayFilter(e.childNodes,function(i){return i.tagName&&i.tagName=="OPTION"&&i.selected}),function(i){return ko.bindingHandlers.value.readElementValue(i)||i.innerText||i.textContent});a=ko.utils.unwrapObservable(a);ko.utils.emptyDomNode(e);if(a){if(typeof a.length!="number")a=[a];if(b.optionsCaption){var d=document.createElement("OPTION");
-d.innerHTML=b.optionsCaption;e.appendChild(d)}for(var f=0,g=a.length;f<g;f++){d=document.createElement("OPTION");var h=typeof b.optionsValue=="string"?a[f][b.optionsValue]:a[f];if(typeof h=="object")ko.utils.domData.set(d,ko.bindingHandlers.options.optionValueDomDataKey,h);else d.value=h.toString();d.innerHTML=(typeof b.optionsText=="string"?a[f][b.optionsText]:h).toString();e.appendChild(d)}e=e.getElementsByTagName("OPTION");f=a=0;for(g=e.length;f<g;f++)if(ko.utils.arrayIndexOf(c,ko.bindingHandlers.value.readElementValue(e[f]))>=
+ko.bindingHandlers.value={init:function(e,a,b){var c=b.valueUpdate||"change";if(ko.isWriteableObservable(a))ko.utils.registerEventHandler(e,c,function(){a(ko.selectExtensions.readValue(this))});else b._ko_property_writers&&b._ko_property_writers.value&&ko.utils.registerEventHandler(e,c,function(){b._ko_property_writers.value(ko.selectExtensions.readValue(this))})},update:function(e,a){var b=ko.utils.unwrapObservable(a);if(b!=ko.selectExtensions.readValue(e)){var c=function(){ko.selectExtensions.writeValue(e,
+b)};c();e.tagName=="SELECT"&&setTimeout(c,0)}}};
+ko.bindingHandlers.options={update:function(e,a,b){if(e.tagName!="SELECT")throw Error("options binding applies only to SELECT elements");var c=ko.utils.arrayMap(ko.utils.arrayFilter(e.childNodes,function(i){return i.tagName&&i.tagName=="OPTION"&&i.selected}),function(i){return ko.selectExtensions.readValue(i)||i.innerText||i.textContent});a=ko.utils.unwrapObservable(a);ko.utils.emptyDomNode(e);if(a){if(typeof a.length!="number")a=[a];if(b.optionsCaption){var d=document.createElement("OPTION");d.innerHTML=
+b.optionsCaption;e.appendChild(d)}for(var f=0,g=a.length;f<g;f++){d=document.createElement("OPTION");var h=typeof b.optionsValue=="string"?a[f][b.optionsValue]:a[f];if(typeof h=="object")ko.utils.domData.set(d,ko.bindingHandlers.options.optionValueDomDataKey,h);else d.value=h.toString();d.innerHTML=(typeof b.optionsText=="string"?a[f][b.optionsText]:h).toString();e.appendChild(d)}e=e.getElementsByTagName("OPTION");f=a=0;for(g=e.length;f<g;f++)if(ko.utils.arrayIndexOf(c,ko.selectExtensions.readValue(e[f]))>=
0){ko.utils.setOptionNodeSelectionState(e[f],true);a++}}}};ko.bindingHandlers.options.optionValueDomDataKey="__ko.bindingHandlers.options.optionValueDomData__";
-ko.bindingHandlers.selectedOptions={getSelectedValuesFromSelectNode:function(e){var a=[];e=e.childNodes;for(var b=0,c=e.length;b<c;b++){var d=e[b];d.tagName=="OPTION"&&d.selected&&a.push(ko.bindingHandlers.value.readElementValue(d))}return a},init:function(e,a,b){if(ko.isWriteableObservable(a))ko.utils.registerEventHandler(e,"change",function(){a(ko.bindingHandlers.selectedOptions.getSelectedValuesFromSelectNode(this))});else b._ko_property_writers&&b._ko_property_writers.value&&ko.utils.registerEventHandler(e,
-"change",function(){b._ko_property_writers.value(ko.bindingHandlers.selectedOptions.getSelectedValuesFromSelectNode(this))})},update:function(e,a){if(e.tagName!="SELECT")throw Error("values binding applies only to SELECT elements");var b=ko.utils.unwrapObservable(a);if(b&&typeof b.length=="number")for(var c=e.childNodes,d=0,f=c.length;d<f;d++){var g=c[d];g.tagName=="OPTION"&&ko.utils.setOptionNodeSelectionState(g,ko.utils.arrayIndexOf(b,ko.bindingHandlers.value.readElementValue(g))>=0)}}};
+ko.bindingHandlers.selectedOptions={getSelectedValuesFromSelectNode:function(e){var a=[];e=e.childNodes;for(var b=0,c=e.length;b<c;b++){var d=e[b];d.tagName=="OPTION"&&d.selected&&a.push(ko.selectExtensions.readValue(d))}return a},init:function(e,a,b){if(ko.isWriteableObservable(a))ko.utils.registerEventHandler(e,"change",function(){a(ko.bindingHandlers.selectedOptions.getSelectedValuesFromSelectNode(this))});else b._ko_property_writers&&b._ko_property_writers.value&&ko.utils.registerEventHandler(e,
+"change",function(){b._ko_property_writers.value(ko.bindingHandlers.selectedOptions.getSelectedValuesFromSelectNode(this))})},update:function(e,a){if(e.tagName!="SELECT")throw Error("values binding applies only to SELECT elements");var b=ko.utils.unwrapObservable(a);if(b&&typeof b.length=="number")for(var c=e.childNodes,d=0,f=c.length;d<f;d++){var g=c[d];g.tagName=="OPTION"&&ko.utils.setOptionNodeSelectionState(g,ko.utils.arrayIndexOf(b,ko.selectExtensions.readValue(g))>=0)}}};
ko.bindingHandlers.text={update:function(e,a){a=ko.utils.unwrapObservable(a);typeof e.innerText=="string"?e.innerText=a:e.textContent=a}};ko.bindingHandlers.css={update:function(e,a){a=a||{};for(var b in a)if(typeof b=="string"){var c=ko.utils.unwrapObservable(a[b]);ko.utils.toggleDomNodeCssClass(e,b,c)}}};ko.bindingHandlers.style={update:function(e,a){a=ko.utils.unwrapObservable(a||{});for(var b in a)if(typeof b=="string"){var c=ko.utils.unwrapObservable(a[b]);e.style[b]=c||""}}};
ko.bindingHandlers.uniqueName={init:function(e,a){if(a){e.name="ko_unique_"+ ++ko.bindingHandlers.uniqueName.currentIndex;/MSIE 6/i.test(navigator.userAgent)&&e.mergeAttributes(document.createElement("<INPUT name='"+e.name+"'/>"),false)}}};ko.bindingHandlers.uniqueName.currentIndex=0;
ko.bindingHandlers.checked={init:function(e,a,b){if(ko.isWriteableObservable(a)){var c;if(e.type=="checkbox")c=function(){a(this.checked)};else if(e.type=="radio")c=function(){this.checked&&a(this.value)};if(c){ko.utils.registerEventHandler(e,"change",c);ko.utils.registerEventHandler(e,"click",c)}}else if(b._ko_property_writers&&b._ko_property_writers.checked){if(e.type=="checkbox")c=function(){b._ko_property_writers.checked(this.checked)};else if(e.type=="radio")c=function(){this.checked&&b._ko_property_writers.checked(this.value)};
View
1  build/source-references.js
@@ -7,6 +7,7 @@
'src/subscribables/observable.js',
'src/subscribables/observableArray.js',
'src/subscribables/dependentObservable.js',
+ 'src/binding/selectExtensions.js',
'src/binding/jsonExpressionRewriting.js',
'src/binding/bindingAttributeSyntax.js',
'src/binding/defaultBindings.js',
View
2  spec/defaultBindingsBehaviors.js
@@ -11,7 +11,7 @@ function prepareTestNode() {
function getSelectedValuesFromSelectNode(selectNode) {
var selectedNodes = ko.utils.arrayFilter(selectNode.childNodes, function (node) { return node.selected; });
- return ko.utils.arrayMap(selectedNodes, function (node) { return ko.bindingHandlers.value.readElementValue(node); });
+ return ko.utils.arrayMap(selectedNodes, function (node) { return ko.selectExtensions.readValue(node); });
}
describe('Binding: Enable/Disable', {
View
4 spec/runner.html
@@ -5,7 +5,7 @@
<link rel="stylesheet" type="text/css" href="lib/JSSpec.css" />
<script type="text/javascript" src="lib/diff_match_patch.js"></script>
- <script type="text/javascript" src="../lib/JSSpec.js"></script>
+ <script type="text/javascript" src="lib/JSSpec.js"></script>
<script type="text/javascript">
JSSpec.DSL.Subject.prototype.should_be_one_of = function (expectedPossibilities) {
for (var i = 0; i < expectedPossibilities.length; i++) {
@@ -17,7 +17,7 @@
throw JSSpec._assertionFailure;
};
</script>
- <script type="text/javascript" src="lib/json2.js"></script>
+ <script type="text/javascript" src="../lib/json2.js"></script>
<script type="text/javascript" src="../build/knockout-debug.js"></script>
<script type="text/javascript" src="memoizationBehaviors.js"></script>
View
38 src/binding/defaultBindings.js
@@ -54,39 +54,17 @@ ko.bindingHandlers.enable = {
ko.bindingHandlers.disable = { update: function (element, value) { ko.bindingHandlers.enable.update(element, !ko.utils.unwrapObservable(value)); } };
ko.bindingHandlers.value = {
- readElementValue: function(element) {
- if (element.tagName == 'OPTION') {
- var valueAttributeValue = element.getAttribute("value");
- if (valueAttributeValue !== null)
- return valueAttributeValue;
- return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
- } else if (element.tagName == 'SELECT')
- return element.selectedIndex >= 0 ? ko.bindingHandlers.value.readElementValue(element.options[element.selectedIndex]) : undefined;
- else
- return element.value;
- },
- writeElementValue: function(element, value) {
- if (element.tagName == 'SELECT') {
- for (var i = element.options.length - 1; i >= 0; i--) {
- if (ko.bindingHandlers.value.readElementValue(element.options[i]) == value) {
- element.selectedIndex = i;
- break;
- }
- }
- } else
- element.value = value;
- },
init: function (element, value, allBindings) {
var eventName = allBindings.valueUpdate || "change";
if (ko.isWriteableObservable(value))
- ko.utils.registerEventHandler(element, eventName, function () { value(ko.bindingHandlers.value.readElementValue(this)); });
+ ko.utils.registerEventHandler(element, eventName, function () { value(ko.selectExtensions.readValue(this)); });
else if (allBindings._ko_property_writers && allBindings._ko_property_writers.value)
- ko.utils.registerEventHandler(element, eventName, function () { allBindings._ko_property_writers.value(ko.bindingHandlers.value.readElementValue(this)); });
+ ko.utils.registerEventHandler(element, eventName, function () { allBindings._ko_property_writers.value(ko.selectExtensions.readValue(this)); });
},
update: function (element, value) {
var newValue = ko.utils.unwrapObservable(value);
- if (newValue != ko.bindingHandlers.value.readElementValue(element)) {
- var applyValueAction = function () { ko.bindingHandlers.value.writeElementValue(element, newValue); };
+ if (newValue != ko.selectExtensions.readValue(element)) {
+ var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
applyValueAction();
// Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
@@ -107,7 +85,7 @@ ko.bindingHandlers.options = {
var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
return node.tagName && node.tagName == "OPTION" && node.selected;
}), function (node) {
- return ko.bindingHandlers.value.readElementValue(node) || node.innerText || node.textContent;
+ return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
});
value = ko.utils.unwrapObservable(value);
@@ -138,7 +116,7 @@ ko.bindingHandlers.options = {
var newOptions = element.getElementsByTagName("OPTION");
var countSelectionsRetained = 0;
for (var i = 0, j = newOptions.length; i < j; i++) {
- if (ko.utils.arrayIndexOf(previousSelectedValues, ko.bindingHandlers.value.readElementValue(newOptions[i])) >= 0) {
+ if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
ko.utils.setOptionNodeSelectionState(newOptions[i], true);
countSelectionsRetained++;
}
@@ -155,7 +133,7 @@ ko.bindingHandlers.selectedOptions = {
for (var i = 0, j = nodes.length; i < j; i++) {
var node = nodes[i];
if ((node.tagName == "OPTION") && node.selected)
- result.push(ko.bindingHandlers.value.readElementValue(node));
+ result.push(ko.selectExtensions.readValue(node));
}
return result;
},
@@ -175,7 +153,7 @@ ko.bindingHandlers.selectedOptions = {
for (var i = 0, j = nodes.length; i < j; i++) {
var node = nodes[i];
if (node.tagName == "OPTION")
- ko.utils.setOptionNodeSelectionState(node, ko.utils.arrayIndexOf(newValue, ko.bindingHandlers.value.readElementValue(node)) >= 0);
+ ko.utils.setOptionNodeSelectionState(node, ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0);
}
}
}
View
30 src/binding/selectExtensions.js
@@ -0,0 +1,30 @@
+(function () {
+ // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
+ // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
+ // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
+ ko.selectExtensions = {
+ readValue : function(element) {
+ if (element.tagName == 'OPTION') {
+ var valueAttributeValue = element.getAttribute("value");
+ if (valueAttributeValue !== null)
+ return valueAttributeValue;
+ return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
+ } else if (element.tagName == 'SELECT')
+ return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
+ else
+ return element.value;
+ },
+
+ writeValue: function(element, value) {
+ if (element.tagName == 'SELECT') {
+ for (var i = element.options.length - 1; i >= 0; i--) {
+ if (ko.selectExtensions.readValue(element.options[i]) == value) {
+ element.selectedIndex = i;
+ break;
+ }
+ }
+ } else
+ element.value = value;
+ }
+ };
+})();
Please sign in to comment.
Something went wrong with that request. Please try again.