JavaScript "сгладить" DOM ​​веб-страницы, сохраняя внешний вид? - PullRequest
3 голосов
/ 02 января 2011

Я хотел бы написать код JavaScript, который "выравнивает" DOM ​​произвольной веб-страницы, сохраняя при этом внешний вид (но не обязательно изменение размера или другие динамические поведения)

Теоретически я считаю, что это просто вопрос записи положения каждого элемента относительно окна (например, PPK findPos(element)), а также его вычисленных стилей CSS (например, window.getComputedStyle(element).cssText), перемещая элемент от его родителя к прямому потомку «body», делая его абсолютно позиционированным в ранее записанной позиции, и устанавливая записанные атрибуты CSS непосредственно на элементе.

У меня был некоторый успех с этим подходом, но он не близок к совершенству:

function walkDOM(element, parent, nodes) {
    parent = parent || { top : 0, left : 0, depth : 0 };
    nodes = nodes || [];

    if (element.nodeType === 1) {
        var node = findPos(element);
        node.element = element;
        node.width = element.scrollWidth;
        node.height = element.scrollHeight;
        node.depth = parent.depth + 1;
        node.cssText = window.getComputedStyle(element).cssText;
        nodes.push(node);

        for (var i = 0; i < element.childNodes.length; i++) {
            walkDOM(element.childNodes[i], node, nodes);
        }
    }
    return nodes;
}

// based on http://www.quirksmode.org/js/findpos.html
function findPos(element) {
    var position = { left : 0, top : 0 };
    if (element.offsetParent) {
        do {
            position.left += element.offsetLeft;
            position.top += element.offsetTop;
        } while (element = element.offsetParent);
    }
    return position;
}

var nodes = walkDOM(document.body);

nodes.forEach(function(node) {
    var e = node.element;

    if (e !== document.body)
        e.parentNode.removeChild(e);

    // e.setAttribute("style", node.cssText);
    e.style.position = "absolute";
    e.style.top = node.top + "px";
    e.style.left = node.left + "px";
    e.style.width = node.width + "px";
    e.style.height = node.height + "px";
    e.style.zIndex = node.depth + 1;

    if (e !== document.body)
        document.body.appendChild(e);
});

Ответы [ 2 ]

1 голос
/ 02 января 2011

Я пробовал нечто подобное, но я сглаживаю только узлы блочного уровня, так как выполнение всех них убьет макет (подумайте о em внутри p и т. Д.). Итак, я шел по дереву так:

var treeWalker = document.createTreeWalker(
    document.body,
    NodeFilter.SHOW_ELEMENT,
    function (node) { 
        if (window.getComputedStyle(node, null).getPropertyValue("display") == "block") {
            return NodeFilter.FILTER_ACCEPT;
        }
        return NodeFilter.FILTER_REJECT; 
    },
    false
);

var nodeList = new Array();
while(treeWalker.nextNode()) {
    nodeList.push(treeWalker.currentNode);
}

Затем просто итерируйте их (так как вы получите их в правильном обратном порядке) и переместите их в тело при применении позиционирования.

Для моих целей я просто воссоздал простые div поля, чтобы они могли изучить макет, и обнаружил, что у меня возникли проблемы с элементами блока, изначально расположенными в других, которые их обрезали (переполнение скрыто) В настоящее время я использую маски svg для воспроизведения отсечения.

0 голосов
/ 02 января 2011

Похоже, у вас хорошее начало.Рассматривали ли вы использовать jQuery для этого?У них есть действительно полезные функции, которые могут упростить эту задачу, особенно функция offset (), которая получает абсолютную позицию элементов в документе.

http://api.jquery.com/category/manipulation/style-properties/
http://api.jquery.com/offset/
http://api.jquery.com/position/
http://jqueryui.com/demos/position/

Вы также можете попробовать сделать элементы фиксированнымивместо абсолютного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...