Skip to content
Browse files

Merge pull request #115 from SteveSanderson/115-expand-css-binding

CSS binding multiple classes in one string not fully supported
  • Loading branch information...
2 parents f0edc52 + 1e67e8b commit e10a189cfa0a1d06f589dc094aeb97876152f0e7 @SteveSanderson SteveSanderson committed May 17, 2012
Showing with 50 additions and 15 deletions.
  1. +26 −0 spec/defaultBindingsBehaviors.js
  2. +9 −3 src/binding/defaultBindings.js
  3. +15 −12 src/utils.js
View
26 spec/defaultBindingsBehaviors.js
@@ -729,6 +729,32 @@ describe('Binding: CSS class name', {
value_of(testNode.childNodes[0].className).should_be("");
observable1(true);
value_of(testNode.childNodes[0].className).should_be("myRule");
+ },
+
+ 'Should toggle multiple CSS classes if specified as a single string separated by spaces': function() {
+ var observable1 = new ko.observable();
+ testNode.innerHTML = "<div class='unrelatedClass1' data-bind='css: { \"myRule _another-Rule123\": someModelProperty }'>Hallo</div>";
+ ko.applyBindings({ someModelProperty: observable1 }, testNode);
+
+ value_of(testNode.childNodes[0].className).should_be("unrelatedClass1");
+ observable1(true);
+ value_of(testNode.childNodes[0].className).should_be("unrelatedClass1 myRule _another-Rule123");
+ observable1(false);
+ value_of(testNode.childNodes[0].className).should_be("unrelatedClass1");
+ },
+
+ 'Should set/change dynamic CSS class(es) if string is specified': function() {
+ var observable1 = new ko.observable("");
+ testNode.innerHTML = "<div class='unrelatedClass1' data-bind='css: someModelProperty'>Hallo</div>";
+ ko.applyBindings({ someModelProperty: observable1 }, testNode);
+
+ value_of(testNode.childNodes[0].className).should_be("unrelatedClass1");
+ observable1("my-Rule");
+ value_of(testNode.childNodes[0].className).should_be("unrelatedClass1 my-Rule");
+ observable1("another_Rule my-Rule");
+ value_of(testNode.childNodes[0].className).should_be("unrelatedClass1 another_Rule my-Rule");
+ observable1(undefined);
+ value_of(testNode.childNodes[0].className).should_be("unrelatedClass1");
}
});
View
12 src/binding/defaultBindings.js
@@ -331,14 +331,20 @@ ko.bindingHandlers['html'] = {
}
};
+var classesWrittenByBindingKey = '__ko__cssValue';
ko.bindingHandlers['css'] = {
'update': function (element, valueAccessor) {
- var value = ko.utils.unwrapObservable(valueAccessor() || {});
- for (var className in value) {
- if (typeof className == "string") {
+ var value = ko.utils.unwrapObservable(valueAccessor());
+ if (typeof value == "object") {
+ for (var className in value) {
var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
}
+ } else {
+ value = String(value || ''); // Make sure we don't try to store or set a non-string value
+ ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
+ element[classesWrittenByBindingKey] = value;
+ ko.utils.toggleDomNodeCssClass(element, value, true);
}
}
};
View
27 src/utils.js
@@ -279,18 +279,21 @@ ko.utils = new (function () {
return ko.isObservable(value) ? value() : value;
},
- toggleDomNodeCssClass: function (node, className, shouldHaveClass) {
- var currentClassNames = (node.className || "").split(/\s+/);
- var hasClass = ko.utils.arrayIndexOf(currentClassNames, className) >= 0;
-
- if (shouldHaveClass && !hasClass) {
- node.className += (currentClassNames[0] ? " " : "") + className;
- } else if (hasClass && !shouldHaveClass) {
- var newClassName = "";
- for (var i = 0; i < currentClassNames.length; i++)
- if (currentClassNames[i] != className)
- newClassName += currentClassNames[i] + " ";
- node.className = ko.utils.stringTrim(newClassName);
+ toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
+ if (classNames) {
+ var cssClassNameRegex = /[\w-]+/g,
+ currentClassNames = node.className.match(cssClassNameRegex) || [];
+ ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
+ var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
+ if (indexOfClass >= 0) {
+ if (!shouldHaveClass)
+ currentClassNames.splice(indexOfClass, 1);
+ } else {
+ if (shouldHaveClass)
+ currentClassNames.push(className);
+ }
+ });
+ node.className = currentClassNames.join(" ");
}
},

0 comments on commit e10a189

Please sign in to comment.
Something went wrong with that request. Please try again.