tags:

views:

6123

answers:

8

Dynamically creating a radio button using eg

var radioInput = document.createElement('input');
radioInput.setAttribute('type', 'radio');
radioInput.setAttribute('name', name);

works in Firefox but not in IE. Why not?

+5  A: 

Based on this post and its comments: http://cf-bill.blogspot.com/2006/03/another-ie-gotcha-dynamiclly-created.html

the following works. Apparently the problem is that you can't dynamically set the name property in IE. I also found that you can't dynamically set the checked attribute either.

function createRadioElement( name, checked ) {
    var radioInput;
    try {
        var radioHtml = '<input type="radio" name="' + name + '"';
        if ( checked ) {
            radioHtml += ' checked="checked"';
        }
        radioHtml += '/>';
        radioInput = document.createElement(radioHtml);
    } catch( err ) {
        radioInput = document.createElement('input');
        radioInput.setAttribute('type', 'radio');
        radioInput.setAttribute('name', name);
        if ( checked ) {
            radioInput.setAttribute('checked', 'checked');
        }
    }

    return radioInput;
}
Patrick Wilkes
A: 

My suggestion is not to use document.Create(). Better solution is to construct actual HTML of future control and then assign it like innerHTML to some placeholder - it allows browser to render it itself which is much faster than any JS DOM manipulations.

Cheers.

dimarzionist
A: 

Patrick's answer works, or you can set the "defaultChecked" attribute too (this will work in IE for radio or checkbox elements, and won't cause errors in other browsers.

PS Full list of attributes you can't set in IE is listed here:

http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html

scunliffe
+6  A: 

Taking a step from what Patrick suggests, using a temporary node we can get rid of the try/catch:

function createRadioElement(name, checked) {
    var radioHtml = '<input type="radio" name="' + name + '"';
    if ( checked ) {
        radioHtml += ' checked="checked"';
    }
    radioHtml += '/>';

    var radioFragment = document.createElement('div');
    radioFragment.innerHTML = radioHtml;

    return radioFragment.firstChild;
}
Prestaul
+1  A: 

Here's an example of more general solution which detects IE up front and handles other attributes IE also has problems with, extracted from DOMBuilder:

var createElement = (function()
{
    // Detect IE using conditional compilation
    if (/*@cc_on @*//*@if (@_win32)!/*@end @*/false)
    {
        // Translations for attribute names which IE would otherwise choke on
        var attrTranslations =
        {
            "class": "className",
            "for": "htmlFor"
        };

        var setAttribute = function(element, attr, value)
        {
            if (attrTranslations.hasOwnProperty(attr))
            {
                element[attrTranslations[attr]] = value;
            }
            else if (attr == "style")
            {
                element.style.cssText = value;
            }
            else
            {
                element.setAttribute(attr, value);
            }
        };

        return function(tagName, attributes)
        {
            attributes = attributes || {};

            // See http://channel9.msdn.com/Wiki/InternetExplorerProgrammingBugs
            if (attributes.hasOwnProperty("name") ||
                attributes.hasOwnProperty("checked") ||
                attributes.hasOwnProperty("multiple"))
            {
                var tagParts = ["<" + tagName];
                if (attributes.hasOwnProperty("name"))
                {
                    tagParts[tagParts.length] =
                        ' name="' + attributes.name + '"';
                    delete attributes.name;
                }
                if (attributes.hasOwnProperty("checked") &&
                    "" + attributes.checked == "true")
                {
                    tagParts[tagParts.length] = " checked";
                    delete attributes.checked;
                }
                if (attributes.hasOwnProperty("multiple") &&
                    "" + attributes.multiple == "true")
                {
                    tagParts[tagParts.length] = " multiple";
                    delete attributes.multiple;
                }
                tagParts[tagParts.length] = ">";

                var element =
                    document.createElement(tagParts.join(""));
            }
            else
            {
                var element = document.createElement(tagName);
            }

            for (var attr in attributes)
            {
                if (attributes.hasOwnProperty(attr))
                {
                    setAttribute(element, attr, attributes[attr]);
                }
            }

            return element;
        };
    }
    // All other browsers
    else
    {
        return function(tagName, attributes)
        {
            attributes = attributes || {};
            var element = document.createElement(tagName);
            for (var attr in attributes)
            {
                if (attributes.hasOwnProperty(attr))
                {
                    element.setAttribute(attr, attributes[attr]);
                }
            }
            return element;
        };
    }
})();

// Usage
var rb = createElement("input", {type: "radio", checked: true});

The full DOMBuilder version also handles event listener registration and specification of child nodes.

insin
A: 

why not creating the input, set the style to dispaly: none and then change the display when necesary this way you can also probably handle users whitout js better.

Miau
+3  A: 

Personally I wouldn't create nodes myself. As you've noticed there are just too many browser specific problems. Normally I use Builder.node from script.aculo.us. Using this your code would become something like this:

Builder.node('input', {type: 'radio', name: name})
ujh
A: 

Quick reply to an older post:

The post above by Roundcrisis is fine, IF AND ONLY IF, you know the number of radio/checkbox controls that will be used before-hand. In some situations, addressed by this topic of 'dynamically creating radio buttons', the number of controls that will be needed by the user is not known. Further, I do not recommend 'skipping' the 'try-catch' error trapping, as this allows for ease of catching future browser implementations which may not comply with the current standards. Of these solutions, I recommend using the solution proposed by Patrick Wilkes in his reply to his own question.

This is repeated here in an effort to avoid confusion:

function createRadioElement( name, checked ) { var radioInput; try { var radioHtml = ''; radioInput = document.createElement(radioHtml); } catch( err ) { radioInput = document.createElement('input'); radioInput.setAttribute('type', 'radio'); radioInput.setAttribute('name', name); if ( checked ) { radioInput.setAttribute('checked', 'checked'); } } return radioInput;}

Cypher