Сохранить только поддерево дерева DOM

#jquery #dom

#jquery #dom

Вопрос:

В статьях BBC, таких как эта, есть элемент DOM с классом story-body , глубоко в цепочке DOM.

Я хочу скрыть все элементы DOM «снаружи» этого (уникального) элемента DOM. Проблема в том, что я не могу просто сделать

 $('*').hide();
$('.story-body');
  

потому что мне нужно убедиться, что сохранены родители, прародители и т.д. Из story-body . Я также не могу сделать

 $('*').hide();

var current = $('.story-body').show();
while(current = current.parent()) {
   current.show();
}
  

потому что это просто показало бы все.

Есть предложения?

Ответ №1:

Вы могли бы скрыть все, а затем показать .story-body его цепочку предков и всех его потомков:

 $("body *").hide();               // Hide all
var sb = $(".story-body").show(); // Find and show story-body
sb.parents().show();              // ...and its parents
sb.find("*").show();              // ...and its contents
  

Или в виде двухстрочного файла, если вам нравится сверхкомпактные вещи:

 $("body *").hide();
$(".story-body").show().parents().show().end().find("*").show();
  

Но я бы не стал рассчитывать на эффект скрытия всех этих других элементов. Хотя, когда я попробовал это в той истории, это сработало нормально.

Вот букмарклет для этого, скопируйте javascript: строку ниже и вставьте ее в качестве цели для закладки, затем перейдите на страницу новостей BBC и щелкните закладку:

javascript:(function(){(function(){var d=document,s=d.createElement("script"),st=new Date();s.src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js";d.body.appendChild(s);after();function after(){var $,sb;if(typeof jQuery!=="function"){if(new Date()-st<5000){setTimeout(after,100);}return;}$=jQuery.noConflict();$("body *").hide();sb=$(".story-body").show();sb.parents().show();sb.find("*").show();}})();})();

Источник:

 (function() {
    // Load jQuery
    var d = document,
        s = document.createElement("script"),
        st = new Date();
    s.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js";
    d.body.appendChild(s);

    // Wait for it to load
    after();
    function after() {
        var $, sb;
        if (typeof jQuery !== "function") {
            // Not loaded yet
            if (new Date() - st < 5000) { // Give up after 5 seconds
                // Try again in 100ms
                setTimeout(after, 100);
            }
            return;
        }

        // Minimize impact
        $ = jQuery.noConflict();

        // Do the work
        $("body *").hide();
        sb = $(".story-body").show();
        sb.parents().show();
        sb.find("*").show();
    }
})();
  

Кажется, работает просто отлично на четырех или пяти историях, которые я пробовал.

Комментарии:

1. Спасибо за это. Я получаю следующую ошибку: «Неперехваченная ошибка типа: не удается вызвать метод ‘write’ неопределенного» (строка 8931 jquery) Есть идеи?

2. @Randomblue: Нет, извините. Однако букмарклет работает (просто проверено трижды, фактически копируется текст из приведенного выше ответа и тому подобное), Поэтому должно быть что-то другое между вашим кодом и кодом букмарклета.

3. Я пишу расширение для Google Chrome… Я понятия не имею, откуда берется проблема. Букмарклет действительно работает нормально.

4. @Randomblue: Странно! Какой файл jQuery вы используете? (Итак, я знаю, что такое строка 8931 …)

Ответ №2:

Вы могли бы отсоединить историю, удалить все остальное, а затем снова вставить историю:

  var stories = $('.story-body');
 stories.detach();
 $(document.body).children().remove();
 stories.appendTo(document.body);
  

Комментарии:

1. Неплохая мысль, но она подрывает CSS, применяемый к области истории с помощью структурных селекторов.