Расширение Chrome Inject HTML на странице YouTube [дубликат]

У меня была та же проблема с vs2013, и изменение политики выполнения не исправить. Единственным рабочим решением, которое я нашел, было удаление Nuget из VS и его установка снова. Шаги здесь: https://stackoverflow.com/a/32619961/3853238

172
задан Nakilon 22 April 2012 в 03:14
поделиться

12 ответов

DOMNodeInserted устарел, наряду с другими событиями мутации DOM, из-за проблем с производительностью - рекомендуется использовать MutationObserver для просмотра DOM. Однако он поддерживается только в новых браузерах, поэтому вы должны вернуться на DOMNodeInserted, когда MutationObserver недоступен.

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if (!mutation.addedNodes) return

    for (var i = 0; i < mutation.addedNodes.length; i++) {
      // do things to your newly added nodes here
      var node = mutation.addedNodes[i]
    }
  })
})

observer.observe(document.body, {
    childList: true
  , subtree: true
  , attributes: false
  , characterData: false
})

// stop watching using:
observer.disconnect()
110
ответ дан hughsk 19 August 2018 в 17:03
поделиться
  • 1
    Я всегда находил MutationObserver api немного сложным, поэтому я создал библиотеку arrival.js , чтобы обеспечить более простой api для прослушивания создания / удаления элементов. – Uzair Farooq 17 April 2014 в 19:23
  • 2
    Я рекомендую использовать @UzairFarooq отличную библиотеку github.com/uzairfarooq/arrive – Dennis 14 July 2014 в 16:13
  • 3
    @hughsk: Как я могу сделать это только для определенного элемента <div>? – user2284570 12 October 2014 в 21:01
  • 4
    Следует отметить две вещи: (1) Лучше сделать if (mutation.addedNodes.length), так как if (mutation.addedNodes) все равно вернет true, даже если это пустой массив. (2) Вы не можете сделать mutation.addedNodes.forEach(), потому что addedNodes является nodeList, и вы не можете перебирать nodeList с forEach. Для решения этого вопроса см. toddmotto.com/ditch-the-array-foreach-call-nodelist-hack – thdoan 15 January 2015 в 05:57
  • 5
    Можете ли вы привести пример того, как это можно использовать? Не знаете, где поставить мой селектор jquery или код, который я хочу выполнить, когда существует элемент DOM. – Superdooperhero 30 May 2018 в 13:12

Вы можете сделать

$('#yourelement').ready(function() {

});

Обратите внимание, что это будет работать, только если элемент присутствует в DOM при запросе с сервера. Если элемент динамически добавляется через JavaScript, это не сработает, и вам, возможно, придется посмотреть на другие ответы.

15
ответ дан aug 19 August 2018 в 17:03
поделиться
  • 1
    Функция .ready() работает для большинства вещей (если не что-либо), а не только document. Он просто не будет работать с динамически создаваемыми элементами, даже на .live(). – Richard Neil Ilagan 2 April 2011 в 19:47
  • 2
    @Bery, как отметил Ричард, это работает только для элементов, которые уже присутствуют в HTML, когда он сначала запрашивается с сервера. Если Javascript используется для динамического добавления элемента в DOM, он не работает. – Chandranshu 30 January 2013 в 14:11
  • 3
    Он работает отлично. Просто присоедините его к ссылке элемента в памяти, а не в строку '#yourelement' – Sam 30 October 2013 в 12:51
  • 4
    @Sam, можете ли вы прояснить, как прикрепить его к ссылке элемента в памяти? – Vikas Singhal 19 February 2014 в 19:48
  • 5
    Этот ответ неверен. То, что вы на самом деле проверяете здесь, является регулярным $(document).ready(), а не тем элементом, который, по вашему мнению, будет применяться. Вот как работает этот специальный прослушиватель. [Д0] Пример – Shikkediel 2 February 2016 в 19:34

Вот решение, возвращающее обещание в ванильном Javascript (без грязных обратных вызовов). По умолчанию он проверяет каждые 200 мс.

function waitFor(selector) {
    return new Promise(function (res, rej) {
        waitForElementToDisplay(selector, 200);
        function waitForElementToDisplay(selector, time) {
            if (document.querySelector(selector) != null) {
                res(document.querySelector(selector));
            }
            else {
                setTimeout(function () {
                    waitForElementToDisplay(selector, time);
                }, time);
            }
        }
    });
}
0
ответ дан blaster 19 August 2018 в 17:03
поделиться

Вы можете прослушивать события DOMNodeInserted или DOMSubtreeModified, которые срабатывают всякий раз, когда новый элемент добавляется в DOM.

Существует также плагин LiveQuery jQuery, который будет определять, когда будет создан новый элемент:

$("#future_element").livequery(function(){
    //element created
});
23
ответ дан ElephantHunter 19 August 2018 в 17:03
поделиться
  • 1
    Очень хороший плагин! Есть ли какая-либо функция в jquery прямо? Мне интересно, что для этого нет существующей функции. И если это плагин, пожалуйста, проголосуйте за этот ответ;) Для меня он работает отлично. Большое спасибо. – Samuel 10 August 2012 в 21:35
  • 2
    Примечание. IE 9 реализует DOMNodeInserted, но имеет основную ошибку, в которой он не срабатывает, когда вы добавляете элемент для времени, и в большинстве случаев вы хотите его использовать. Подробности находятся по адресу: help.dottoro.com/ljmcxjla.php – mikemaccana 3 December 2012 в 13:48
  • 3
    ПРЕДУПРЕЖДЕНИЕ О ДЕПРЕКАЦИИ (см. принятый ответ). – Ryne Everett 5 May 2015 в 22:56

Для простого подхода с использованием jQuery я нашел, что это хорошо работает:

  // Wait for element to exist.
  function elementLoaded(el, cb) {
    if ($(el).length) {
      // Element is now loaded.
      cb($(el));
    } else {
      // Repeat every 500ms.
      setTimeout(function() {
        elementLoaded(el, cb)
      }, 500);
    }
  };

  elementLoaded('.element-selector', function(el) {
    // Element is ready to use.
    el.click(function() {
      alert("You just clicked a dynamically inserted element");
    });
  });

Здесь мы просто проверяем каждые 500 мс, чтобы увидеть, загружен ли элемент, когда он есть, мы можем его использовать .

Это особенно полезно для добавления обработчиков кликов к элементам, которые динамически добавлены в документ.

8
ответ дан Hedley Smith 19 August 2018 в 17:03
поделиться

Вот функция, которая действует как тонкая оболочка вокруг MutationObserver. Единственное требование - браузер поддерживает MutationObserver; нет никакой зависимости от JQuery. Выполните фрагмент ниже, чтобы увидеть рабочий пример.

function waitForMutation(parentNode, isMatchFunc, handlerFunc, observeSubtree, disconnectAfterMatch) {
  var defaultIfUndefined = function(val, defaultVal) {
    return (typeof val === "undefined") ? defaultVal : val;
  };

  observeSubtree = defaultIfUndefined(observeSubtree, false);
  disconnectAfterMatch = defaultIfUndefined(disconnectAfterMatch, false);

  var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      if (mutation.addedNodes) {
        for (var i = 0; i < mutation.addedNodes.length; i++) {
          var node = mutation.addedNodes[i];
          if (isMatchFunc(node)) {
            handlerFunc(node);
            if (disconnectAfterMatch) observer.disconnect();
          };
        }
      }
    });
  });

  observer.observe(parentNode, {
    childList: true,
    attributes: false,
    characterData: false,
    subtree: observeSubtree
  });
}

// Example
waitForMutation(
  // parentNode: Root node to observe. If the mutation you're looking for
  // might not occur directly below parentNode, pass 'true' to the
  // observeSubtree parameter.
  document.getElementById("outerContent"),
  // isMatchFunc: Function to identify a match. If it returns true,
  // handlerFunc will run.
  // MutationObserver only fires once per mutation, not once for every node
  // inside the mutation. If the element we're looking for is a child of
  // the newly-added element, we need to use something like
  // node.querySelector() to find it.
  function(node) {
    return node.querySelector(".foo") !== null;
  },
  // handlerFunc: Handler.
  function(node) {
    var elem = document.createElement("div");
    elem.appendChild(document.createTextNode("Added node (" + node.innerText + ")"));
    document.getElementById("log").appendChild(elem);
  },
  // observeSubtree
  true,
  // disconnectAfterMatch: If this is true the hanlerFunc will only run on
  // the first time that isMatchFunc returns true. If it's false, the handler
  // will continue to fire on matches.
  false);

// Set up UI. Using JQuery here for convenience.

$outerContent = $("#outerContent");
$innerContent = $("#innerContent");

$("#addOuter").on("click", function() {
  var newNode = $("<div><span class='foo'>Outer</span></div>");
  $outerContent.append(newNode);
});
$("#addInner").on("click", function() {
  var newNode = $("<div><span class='foo'>Inner</span></div>");
  $innerContent.append(newNode);
});
.content {
  padding: 1em;
  border: solid 1px black;
  overflow-y: auto;
}
#innerContent {
  height: 100px;
}
#outerContent {
  height: 200px;
}
#log {
  font-family: Courier;
  font-size: 10pt;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Create some mutations</h2>
<div id="main">
  <button id="addOuter">Add outer node</button>
  <button id="addInner">Add inner node</button>
  <div class="content" id="outerContent">
    <div class="content" id="innerContent"></div>
  </div>
</div>
<h2>Log</h2>
<div id="log"></div>

5
ответ дан Ivan Karajas 19 August 2018 в 17:03
поделиться

Как насчет библиотеки insertionQuery ?

insertionQuery использует обратные вызовы анимации CSS, прикрепленные к селектору (ям), указанным для запуска обратного вызова при создании элемента. Этот метод позволяет запускать обратные вызовы всякий раз, когда создается элемент, а не только в первый раз.

Из github:

Способ не-dom-event для обнаружения узлов, отображающих ,

Это не только для более широкой поддержки браузера. Это может быть лучше, чем DOMMutationObserver для определенных вещей.

Почему?

  • Потому что DOM Events замедляет работу браузера, а insertionQuery не работает
  • . Поскольку DOM Mutation Observer имеет меньшую поддержку браузера, чем insertionQuery
  • . Поскольку с помощью insertionQuery вы можете фильтровать изменения DOM с помощью селекторов без служебных издержек!

Широкая поддержка!

IE10 + и в основном что-нибудь еще (в том числе мобильное)

8
ответ дан Josiah 19 August 2018 в 17:03
поделиться

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

Предположим, что функция doTheRestOfTheStuff(parameters) должна вызываться только после появления элемента с идентификатором the_Element_ID или законченная загрузка, мы можем использовать

var existCondition = setInterval(function() {
 if ($('#the_Element_ID').length) {
    console.log("Exists!");
    clearInterval(existCondition);
    doTheRestOfTheStuff(parameters);
 }
}, 100); // check every 100ms
12
ответ дан prime 19 August 2018 в 17:03
поделиться

У меня была такая же проблема, поэтому я пошел дальше и написал для нее плагин .

$(selector).waitUntilExists(function);

Код:

;(function ($, window) {

var intervals = {};
var removeListener = function(selector) {

    if (intervals[selector]) {

        window.clearInterval(intervals[selector]);
        intervals[selector] = null;
    }
};
var found = 'waitUntilExists.found';

/**
 * @function
 * @property {object} jQuery plugin which runs handler function once specified
 *           element is inserted into the DOM
 * @param {function|string} handler 
 *            A function to execute at the time when the element is inserted or 
 *            string "remove" to remove the listener from the given selector
 * @param {bool} shouldRunHandlerOnce 
 *            Optional: if true, handler is unbound after its first invocation
 * @example jQuery(selector).waitUntilExists(function);
 */

$.fn.waitUntilExists = function(handler, shouldRunHandlerOnce, isChild) {

    var selector = this.selector;
    var $this = $(selector);
    var $elements = $this.not(function() { return $(this).data(found); });

    if (handler === 'remove') {

        // Hijack and remove interval immediately if the code requests
        removeListener(selector);
    }
    else {

        // Run the handler on all found elements and mark as found
        $elements.each(handler).data(found, true);

        if (shouldRunHandlerOnce && $this.length) {

            // Element was found, implying the handler already ran for all 
            // matched elements
            removeListener(selector);
        }
        else if (!isChild) {

            // If this is a recurring search or if the target has not yet been 
            // found, create an interval to continue searching for the target
            intervals[selector] = window.setInterval(function () {

                $this.waitUntilExists(handler, shouldRunHandlerOnce, true);
            }, 500);
        }
    }

    return $this;
};

}(jQuery, window));
108
ответ дан Roland Soós 19 August 2018 в 17:03
поделиться
  • 1
    Спасибо за плагин. Я раздвоил и немного улучшил его. Не стесняйтесь брать все, что захотите, из моего обновления. У меня есть еще несколько запланированных улучшений: обновленный плагин – Brandon Belvin 4 June 2013 в 22:46
  • 2
  • 3
    возможно, вам стоит упомянуть, как это работает: он работает, задавая каждые 500 мс, если существует элемент (используя window.setInterval). Я не знаю, работает ли MutationObserver ответ на опрос ... – sports 30 March 2015 в 21:18
  • 4
    Он не работает должным образом, если элемент уже находится на странице. Вот правильная версия этой функции: gist.github.com/PizzaBrandon/5709010 – Roland Soós 24 February 2016 в 08:09
  • 5
    Не могли бы вы объяснить, что используется ; в начале функции (;(function ($, window) {)? – mrid 23 December 2016 в 11:36

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

/**
 * @brief Wait for something to be ready before triggering a timeout
 * @param {callback} isready Function which returns true when the thing we're waiting for has happened
 * @param {callback} success Function to call when the thing is ready
 * @param {callback} error Function to call if we time out before the event becomes ready
 * @param {int} count Number of times to retry the timeout (default 300 or 6s)
 * @param {int} interval Number of milliseconds to wait between attempts (default 20ms)
 */
function waitUntil(isready, success, error, count, interval){
    if (count === undefined) {
        count = 300;
    }
    if (interval === undefined) {
        interval = 20;
    }
    if (isready()) {
        success();
        return;
    }
    // The call back isn't ready. We need to wait for it
    setTimeout(function(){
        if (!count) {
            // We have run out of retries
            if (error !== undefined) {
                error();
            }
        } else {
            // Try again
            waitUntil(isready, success, error, count -1, interval);
        }
    }, interval);
}

Чтобы вызвать это, например, в jQuery, используйте что-то вроде:

waitUntil(function(){
    return $('#myelement').length > 0;
}, function(){
    alert("myelement now exists");
}, function(){
    alert("I'm bored. I give up.");
});
3
ответ дан xgretsch 19 August 2018 в 17:03
поделиться

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

Параметры:

  1. selector: Эта функция ищет элемент $ {selector }
  2. time: эта функция проверяет, существует ли этот элемент каждые $ {time} миллисекунд.
    function waitForElementToDisplay(selector, time) {
            if(document.querySelector(selector)!=null) {
                alert("The element is displayed, you can put your code instead of this alert.")
                return;
            }
            else {
                setTimeout(function() {
                    waitForElementToDisplay(selector, time);
                }, time);
            }
        }
    

В качестве примера установка selector="#div1" и time=5000 будет искать HTML-тег, чей id="div1" каждые 5000 миллисекунд.

45
ответ дан YakovL 19 August 2018 в 17:03
поделиться

Более чистый пример использования MutationObserver:

new MutationObserver( mutation => {
    if (!mutation.addedNodes) return
    mutation.addedNodes.forEach( node => {
        // do stuff with node
    })
})
2
ответ дан Zaz 19 August 2018 в 17:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: