开发者

CSS doesn't apply to dynamically created elements in IE 7?

开发者 https://www.devze.com 2023-01-01 01:40 出处:网络
Still looking for an answer. Changing or reassigning to the filter\'s innerHTML successfully redraws the element, but breaks my script, so that\'s out.

Still looking for an answer.

Changing or reassigning to the filter's innerHTML successfully redraws the element, but breaks my script, so that's out.

Adding additional child nodes, including text nodes, does not force a redraw. Removing the added node does not force a redraw.

Using the ie7.js family of scripts does not work.


In the project I am working on, I dynamically generate (with javascript) filters that look like this:

<div class="filter">
    <a ... class="filter_delete_link">Delete</a>
    <div class="filter_field">
        ...
    </div>
    <div class="filter_compare">
        ...
    </div>
    <div class="filter_constraint">
        ...
    </div>
    <div class="filter_logic">
        ...
    </div>
</div>

And I have CSS that applies to each filter (for example):

.filter a.filter_delete_link{
    display:block;
    height:16px;
    background: url('../images/remove_16.gif') no-repeat;
    padding-left:20px;
}

However, it seems in IE 7 (and probably 6 for that matter), these styles don't get applied to the new filters.

Everything works perfectly in Firefox/Chrome/IE8.

Using the IE8 developer tools, set to IE7 mode, the browser can see the new elements, and can see the CSS, but just isn't applying the CSS.

Is there a way to force IE to reload styles, or perhaps is there a better way to fix this?


The JavaScript: (simplified)

var builder = {
    ...
    createNewFilter: function() {
        var newFilter = document.createElement('div');

        var deleteLink = document.createElement('a');
        deleteLink.href = '#';
        deleteLink.setAttribute('class','filter_delete_link');
        deleteLink.title = 'Delete Condition';
        deleteLink.innerHTML = "Delete";
        newFilter.appendChild(deleteLink);

        var field = document.createElement('div');
        field.setAttribute('class','filter_field');
        var fieldSelect = this.getFieldSelectBox();
        field.appendChild(fieldSelect);
        newFilter.appendChild(f开发者_运维技巧ield);

        // more of the same...

        deleteLink.onclick = function() {
            builder.removeFilter(newFilter);
        };
        fieldSelect.onchange = function () {
            builder.updateFilter(newFilter);
        }

        return newFilter;
    },
    addNewFilter: function() {
        var nNewFilter = this.createNewFilter(this.numFilters++);
        this.root.insertBefore(nNewFilter,this.nAddLink);

        //other unrelated stuff...

        //provided by Josh Stodola
        //redraw(this.root);

        return nNewFilter;
    }
}


The problem, I've discovered is that IE 6/7 doesn't register the class name changes with elm.setAttribute('class','x') until the UI is redrawn.

The solution is to use the form elm.className = 'x'

**This problem was also noticeable from moving from IE9 quirks to standards mode. The solution was the same.


Sounds to me like you need to force a redraw of the UI for this element. There are several ways to do this, but the following is the most effective method...

// elm is a reference to your element
var disp = elm.style.display;
elm.style.display = "none";
var redrawFix = elm.offsetHeight;
elm.style.display = disp;

Here is another method I found on Ajaxian...

function redraw(elm) {
  var n = document.createTextNode(' ');
  elm.appendChild(n);
  setTimeout(function(){ n.parentNode.removeChild(n) }, 0);
  return elm;
}


IE6/7 has a lot of problems/bugs/misbehaviours with regard to creating and adding elements in the DOM using createElement. I strongly recommend to switch to jQuery for this since it does all the work in a cross browser compatible manner and has already taken (almost) all the IE6/7 specific misbehaviours into account so that you don't need to end up with a doubled amount of code to get it to work in all browsers the world is aware of. Here's a copy'n'paste'n'runnable SSCCE:

<!doctype html>
<html lang="en">
    <head>
        <title>Test</title>
        <script src="http://code.jquery.com/jquery-latest.min.js"></script>
        <script>
            $(document).ready(function() {
                $('#add').click(function() {
                    var newElement = $('<div class="filter"><a href="#" class="delete">delete</a></div>');
                    $('#container').append(newElement);
                });
            });
        </script>
        <style>
            .filter { background: pink; }
            .delete { background: yellow; }
        </style>
    </head>
    <body>
        <div id="container"></div>
        <button id="add">add</button>
    </body>
</html>

Update: as per the comments, jQuery is absolutely not an option. Well, best what you can try is to set element attributes only after the element is been added to the DOM. Also try not to clone nodes in IE6/7, this is often epic fail. Rather create a brand new node from beginning on.


Could it be that you're missing " at the end of some elements?

<a ... class="filter_delete_link>Delete</a> missing "
<div class="filter_field> missing "


You have a missing " on the line that reads <a ... class="filter_delete_link>Delete</a>

Edit:
I don't think it's a problem with IE7 as it seems to work fine here - http://jsfiddle.net/nhvrA/.
I'll keep investigating.


Don't you need a width as well as a height on the element? I know display: block should give it width: 100%, but IE is not that bright. Does anything change if you provide a width?


Building off of other comments and answers in this thread, I resolved this problem using the Prototype library:

<div id"dynamically-added-block"> ... </div>
...
$("dynamically-added-block").up().show();

Simply, get the parent and re-show it. Tested in IE8, using both Browser Mode: IE8, Document Mode: IE8 and Browser Mode: IE7, Document Mode: IE7. Have not tested with the dreaded quirks mode.

0

精彩评论

暂无评论...
验证码 换一张
取 消