views:

73

answers:

3

First up, JavaScript is definitely not my native tongue. Nevertheless, I've been tasked with creating a web page where the user can use a colour picker to change CSS elements. These then need to be sent back to the server to be stored in a database. It's all working so far except the last part, because I'm stuck reading the required elements.

Using the code below works fine for any single word elements, such as color, but fails for any hyphenated ones, such as background-color, which return undefined. I've tested this against a number of other elements for consistency.

Any ideas as to why this fails, preferably with suggestions for fixing it? Alternatively, do you have a code snippet that does work for this purpose?

function Save(form) {
var cssRules;
var Q = "";

for (var S = 0; S < document.styleSheets.length; S++){
    if (document.styleSheets[S]['rules']) {
        cssRules = 'rules';
    } else if (document.styleSheets[S]['cssRules']) {
        cssRules = 'cssRules';
    }

    for (var R = 0; R < document.styleSheets[S][cssRules].length; R++) {
        if (document.styleSheets[S][cssRules][R].selectorText == '.event') {
            Q += "+bc=" + document.styleSheets[S][cssRules][R].style['color'] + "+bb=" + document.styleSheets[S][cssRules][R].style['background-color'];
        }
        // Similar code for other elements goes here
    }
}

form.css.value = Q;
form.submit();
}

Example section of the CSS style sheet:

.event {
    text-align: center;
    font-size: 10px;
    font-weight: bold;
    text-decoration: line-through;
    color: red;
    background-color: #ffff99;
    height:20px;
    width:20px;
}

This is the kind of HTML element I need the style sheet values for:

<td class="event">11</td>
+3  A: 

To set CSS properties in JavaScript you need to use camelCase for hyphened properties. For example:

/* CSS */
background-color: red;

/* JS */
element.style.backgroundColor = 'red';
Jason McCreary
+3  A: 

That's because in Javascript as in other languages the hyphen is not a valid symbol character. When you use strings as indexes, like

style["background-color"]

is the same as doing

style.background-color 

which is not valid, to access hyphened css properties you need to remove the hyphen and uppercase the next character, like

style.backgroundColor; // or style["backgroundColor"];
Francisco Soto
While this is essentially the same as Jason's answer I'll accept yours because of the additional detail, which is a help to me. Thanks.
John Gardeniers
Slightly misleading: the hyphen is an invalid character in an **identifier**. It's not invalid in a property name, as you can see by doing something like `var o = { "%1-2*-3": "test" }; alert(o["%1-2*-3"]);`. However, you are probably correct that the reason CSS property names are different in JavaScript is so that they can be used as identifiers and hence the dot notation can be used to access style properties.
Tim Down
Ah, Anurag has made the same point.
Tim Down
+3  A: 

To add to @Francisco's answer, in JavaScript an object property can contain any string. However, if it contains characters that are illegal for naming variables, then it cannot be accessed with the . operator, and must be accessed with []. An extreme example of using such characters would be:

var o = { "◀▶": "hello!" };
o["◀▶"]; // hello!

However, we cannot write o.◀▶, as that will raise a SyntaxError since these unicode characters are not valid identifiers names. However, note that unicode characters can be used in identifier names and are valid as per ECMAScript 5th ed. but only for certain classes of Unicode categories. So one could write:

var o = {};
o.Π = "hello world";
o.Π; // "hello world"

See section 7.6 Identifier Names and Identifiers in the documentation for 3rd ed. or 5th ed. for more information regarding valid identifier names.

The style property of DOM elements is an object of CSSStyleDeclaration and can be manipulated in a couple of ways. Being a host object, some browsers could provide more functionality than others. On Webkit browsers (Chrome and Safari), you could use the [] notation to set style properties using their CSS2 names.

document.body.style['background-color'] = "#CCC";

The interface for CSSStyleDeclaration contains a setProperty method that can also be used for setting these properties:

interface CSSStyleDeclaration {
    ...
    void setProperty(in DOMString propertyName, 
                     in DOMString value, 
                     in DOMString priority)
            raises(DOMException);
    ...
}

Using setProperty, we could write:

document.body.style.setProperty("background-color", "orange", null);

We can use getPropertyValue to get the current value using it's CSS2 name:

document.body.style.getPropertyValue("background-color");

Finally, as other answers have mentioned, you can always use the CSS2Properties interface for conveniently accessing the CSS properties for a style object. They are equivalent to calling setProperty and getPropertyValue on the style object with the corresponding property name. From the spec (contains names for all properties that should be exposed by this interface):

The CSS2Properties interface represents a convenience mechanism for retrieving and setting properties within a CSSStyleDeclaration. The attributes of this interface correspond to all the properties specified in CSS2. Getting an attribute of this interface is equivalent to calling the getPropertyValue method of the CSSStyleDeclaration interface. Setting an attribute of this interface is equivalent to calling the setProperty method of the CSSStyleDeclaration interface.

In any browser that supports this interface (it's not required), we can query/update the style object such as:

document.body.style.backgroundColor = "black";

or

document.body.style["backgroundColor"] = "black";

See examples for all of the above.

Anurag
Thanks for the excellent information.
Francisco Soto
Indeed, thank you for your answer. Maybe I should just stick to C and Perl. At least those make sense to me. :)
John Gardeniers
@Francisco - you're welcome, I discovered about unicode characters in identifier names myself, so it was a good learning experience :) @John - Thankfully those languages don't suffer from level 1..n specs that come out every other week :)
Anurag