Возможная ошибка при изменении имени класса элемента с помощью JavaScript в IE8, IE9 и IE10 - PullRequest
0 голосов
/ 07 марта 2012

Примечание: У меня был предыдущий аналогичный вопрос, который я сейчас пытался удалить.Я думал, что проблема была в элементе управления .NET webbrowser, но в IE.

Следующий код представляет собой содержимое файла .htm, который просто отображает 3 элемента, по которым можно щелкнуть.При щелчке каждого элемента метод javascript меняет свой фон на синий, а фон выбранного ранее элемента снова становится белым.

Вот проблема, которая возникает только в IE8, 9 и 10. Она работает в FF, Chrome, и мне удалось продемонстрировать, что она работает в IE5 и IE7, используя предварительный просмотр IE10.

Нажмите на пункт1, затем нажмите на ПУНКТ 1.1 - ПУНКТ 1.1 выделен, но ПУНКТ 1 не выделен.

Однако (перемещение вверх по дереву документа):
Нажмите на ПУНКТ 1, затем КОРЕНЬ - без проблем
Нажмите на ПУНКТ 1,1, затем ПУНКТ 1 - Нет проблем.

Теперь, если я переключаю метод javascript selectElement (e), чтобы сначала отменить выбор, а затем выбрать, проблема становится такой:

Нажмитев пункте 1.1, затем щелкните элемент 1 - между щелчком элемента 1 и отображением синего фона наблюдается заметная задержка.

Если метки изображений удалены, проблема исчезнет.

Прокручивание элемента вне поля зрения и затем снова в нем исправляет рендеринг.К сожалению, вызов Invalidate или Update не устраняет проблему.

Переключение стиля отображения ранее выбранного элемента на none и затем обратно снова решает проблему - если пользователь не выбирает текст узлапо ошибке (например, двойной щелчок)

Некоторые вещи, которые я пробовал:

  1. Вместо простого изменения класса, я попытался полностью заменить externalhtml, но этоне имеет значения.
  2. Удаление тега изображения и включение фонового изображения не имеет значения.

Код

* При тестировании на собственной машине,веб-страница не сможет найти файл 'expand_tree_20x8.png';это не имеет значения, поскольку демонстрируется поведение, можно ли найти изображения или нет.Важно то, что теги изображений должны быть в файле.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en-GB">

    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

        <style type="text/css">
            span, img {margin:0;padding:0}
            .child {margin-left: 10px;}
            .normal {background-color: White;}
            .selected {background-color: blue; color: white;}
        </style>

        <script type="text/javascript">

            var selectedElement;

            function selectElement(e) {

                /* Select new element */
                e.attributes["class"].value = "selected";

                /* Unselect currently selected */
                if (selectedElement) {
                    selectedElement.attributes["class"].value = "normal";
                }

                selectedElement = e;
            }


        </script>

    </head>

    <body>

        <div>

            <div class="child"><label id="root_id" class="normal" onclick="selectElement(this)">ROOT</label></div>

            <div class="child"><img alt="img" src="temp/expand_tree_20x8.png" />

                <label id="item1_id" class="normal" onclick="selectElement(this)">ITEM 1</label>

                <div class="child"><img alt="img" src="temp/expand_tree_20x8.png" />
                    <label id="item1_1_id" class="normal" onclick="selectElement(this)">ITEM 1.1</label>
                </div>

            </div>

        </div>

    </body>

</html>

1 Ответ

0 голосов
/ 07 марта 2012

Это, вероятно, не решит проблему перерисовки, с которой вы столкнулись, но это было слишком долго, чтобы включить в комментарий.

Переменная e обычно обозначает объект события, а не объект dom. Так что это смущает других разработчиков, когда они смотрят на ваш код. Измените его на elem, ele, domObj или что-нибудь еще, кроме e.

Во-вторых, то, как вы устанавливаете имя класса, странно. Я ожидаю увидеть className.

var selectedElement;

function selectElement(elem) {

    /* Select new element */
    elem.className = "selected";

    /* Unselect currently selected */
    if (selectedElement) {
        selectedElement.className = "normal";
    }

    selectedElement = elem;
}

Вероятно, было бы лучше использовать некоторые вспомогательные функции для добавления и удаления класса, чтобы вы могли иметь более одного класса для элементов.

function hasClass(elem, cls) {
    return elem.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
function addClass(elem, cls) {
    if (!this.hasClass(elem, cls)) elem.className += " " + cls;
}
function removeClass(elem, cls) {
    if (hasClass(elem, cls)) {
        var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
        elem.className = elem.className.replace(reg, ' ');
    }
}


var selectedElement;
function selectElement(elem) {

    /* Select new element */
    addClass(elem, "selected");

    /* Unselect currently selected */
    if (selectedElement) {
        removeClass(selectedElement, "normal";
    }

    selectedElement = elem;
}

Иногда чтение высоты вызывает перерисовку, поэтому попробуйте сделать что-то вроде этого

var selectedElement;
function selectElement(elem) {

    /* Select new element */
    addClass(elem, "selected");

    /* Unselect currently selected */
    if (selectedElement) {
        removeClass(selectedElement, "normal";
    }

    /* Try to force a redraw */
    //elem.style.display = "none";  //if just reading offsetHeight, does not work try uncommenting the two lines of code.
    var redrawFix = elem.offsetHeight;
    //elem.style.display = "block";  //or inline or whatever

    selectedElement = elem;
}
...