Подтвердить что ты не робот

JQuery - событие триггера, когда элемент удален из DOM

Я пытаюсь выяснить, как выполнить некоторый код js, когда элемент удален со страницы:

jQuery('#some-element').remove(); // remove some element from the page
/* need to figure out how to independently detect the above happened */

есть ли какое-то событие для него, например:

jQuery('#some-element').onremoval( function() {
    // do post-mortem stuff here
});

спасибо.

4b9b3361

Ответ 1

Просто проверено, оно уже встроено в текущую версию JQuery:

jQuery - v1.9.1

jQuery UI - v1.10.2

$("#myDiv").on("remove", function () {
    alert("Element was removed");
})

Важно. Это функциональность JQuery UI script (не JQuery), поэтому вам нужно загрузить оба сценария (jquery и jquery-ui), чтобы сделать это Работа. Вот пример: http://jsfiddle.net/72RTz/

Ответ 2

Для этого можно использовать специальные события jQuery.

Во всей простоте,

Настройка:

(function($){
  $.event.special.destroyed = {
    remove: function(o) {
      if (o.handler) {
        o.handler()
      }
    }
  }
})(jQuery)

Использование:

$('.thing').bind('destroyed', function() {
  // do stuff
})

Добавление к ответам комментариев Pierre и DesignerGuy:

Чтобы не вызвать обратный вызов при вызове $('.thing').off('destroyed'), измените условие if на: if (o.handler && o.type !== 'destroyed') { ... }

Ответ 3

Вы можете привязываться к событию DOMNodeRemoved (часть спецификации DOM Level 3 WC3).

Работает в IE9, последние версии Firefox и Chrome.

Пример:

$(document).bind("DOMNodeRemoved", function(e)
{
    alert("Removed: " + e.target.nodeName);
});

Вы также можете получать уведомление, когда элементы вставляются путем привязки к DOMNodeInserted

Ответ 4

Не существует встроенного события для удаления элементов, но вы можете создать его методом fake-extension jQuery default remove. Обратите внимание, что обратный вызов должен быть вызван до фактического удаления его, чтобы сохранить ссылку.

(function() {
    var ev = new $.Event('remove'),
        orig = $.fn.remove;
    $.fn.remove = function() {
        $(this).trigger(ev);
        return orig.apply(this, arguments);
    }
})();

$('#some-element').bind('remove', function() {
    console.log('removed!');
    // do pre-mortem stuff here
    // 'this' is still a reference to the element, before removing it
});

// some other js code here [...]

$('#some-element').remove();

Примечание: некоторые проблемы с этим ответом были очерчены другими плакатами.

  • Это не будет работать, если node будет удален с помощью html() replace() или других методов jQuery
  • Это событие пузырится вверх
  • переопределяет пользовательский интерфейс jQuery.

Наиболее элегантным решением этой проблемы является: fooobar.com/questions/32917/...

Ответ 5

Hooking .remove() не лучший способ справиться с этим, так как есть много способов удалить элементы со страницы (например, используя .html(), .replace() и т.д.)..

Чтобы предотвратить различные опасности утечки памяти, внутренне jQuery попытается вызвать функцию jQuery.cleanData() для каждого удаленного элемента, независимо от метода, используемого для его удаления.

См. этот ответ для получения дополнительной информации: утечки памяти javascript

Итак, для достижения наилучших результатов вы должны зацепить функцию cleanData, что является именно тем, что делает jquery.event.destroyed.

http://v3.javascriptmvc.com/jquery/dist/jquery.event.destroyed.js

Ответ 6

Для тех, кто использует jQuery UI:

jQuery UI переопределил некоторые из методов jQuery для реализации события remove, которое обрабатывается не только тогда, когда вы явно удаляете данный элемент, но также и если элемент удаляется из DOM с помощью любых самоочищающихся методов jQuery ( например, replace, html и т.д.). Это в основном позволяет вам перехватывать те же события, которые запускаются, когда jQuery "очищает" события и данные, связанные с элементом DOM.

John Resig указал, что он открывает идею реализации этого события в будущей версии ядра jQuery, но я не уверен, где он стоит в настоящее время.

Ответ 7

Я не мог получить этот ответ для работы с развязыванием (несмотря на обновление см. здесь), но смог найти способ обойти это. Ответ заключался в создании специального события "destroy_proxy", которое вызвало "разрушенное" событие. Вы помещаете прослушиватель событий на "destroy_proxy" и "destroy", а затем, когда вы хотите развязать, вы просто отвязываете "разрушенное" событие:

var count = 1;
(function ($) {
    $.event.special.destroyed_proxy = {
        remove: function (o) {
            $(this).trigger('destroyed');
        }
    }
})(jQuery)

$('.remove').on('click', function () {
    $(this).parent().remove();
});

$('li').on('destroyed_proxy destroyed', function () {
    console.log('Element removed');
    if (count > 2) {
        $('li').off('destroyed');
        console.log('unbinded');
    }
    count++;
});

Вот fiddle

Ответ 8

Решение без использования jQuery UI

(Я извлек это расширение из jQuery UI framework)

Работает с: empty() и html() и remove()

$.cleanData = ( function( orig ) {
    return function( elems ) {
        var events, elem, i;
        for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
            try {

                // Only trigger remove when necessary to save time
                events = $._data( elem, "events" );
                if ( events && events.remove ) {
                    $( elem ).triggerHandler( "remove" );
                }

            // Http://bugs.jquery.com/ticket/8235
            } catch ( e ) {}
        }
        orig( elems );
    };
} )( $.cleanData );

С помощью этого решения вы также можете отвязать обработчик событий.

$("YourElemSelector").off("remove");

Попробуй! - Пример

$.cleanData = (function(orig) {
  return function(elems) {
    var events, elem, i;
    for (i = 0;
      (elem = elems[i]) != null; i++) {
      try {

        // Only trigger remove when necessary to save time
        events = $._data(elem, "events");
        if (events && events.remove) {
          $(elem).triggerHandler("remove");
        }

        // Http://bugs.jquery.com/ticket/8235
      } catch (e) {}
    }
    orig(elems);
  };
})($.cleanData);


$("#DivToBeRemoved").on("remove", function() {
  console.log("div was removed event fired");
});

$("p").on("remove", function() {
  console.log("p was removed event fired");
});

$("span").on("remove", function() {
  console.log("span was removed event fired");
});

// $("span").off("remove");

$("#DivToBeRemoved").on("click", function() {
  console.log("Div was clicked");
});

function RemoveDiv() {
  //       $("#DivToBeRemoved").parent().html("");    
  $("#DivToBeRemoved").remove();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>OnRemove event handler attached to elements 'div', 'p' and 'span'.</h3>
<div class="container">
  <br>
  <button onclick="RemoveDiv();">Click here to remove div below</button>
  <div id="DivToBeRemoved">
    DIV TO BE REMOVED 
    contains 1 p element 
    which in turn contains a span element
    <p>i am p (within div)
      <br><br><span>i am span (within div)</span></p>
  </div>
</div>

Ответ 9

Мне нравится ответ mtkopone с использованием специальных событий jQuery, но обратите внимание, что он не работает. a) когда элементы отсоединяются, а не удаляются. b) когда некоторые старые библиотеки без jquery используют innerHTML для уничтожения ваших элементов

Ответ 10

Я не уверен, что для этого есть дескриптор события, поэтому вам нужно будет сохранить копию DOM и сравнить с существующей DOM в какой-то петле опроса, что может быть довольно неприятным. Firebug делает это, хотя - если вы проверяете HTML и выполняете некоторые изменения DOM, он выделяет изменения в желтом в консоли Firebug на короткое время.

В качестве альтернативы вы можете создать функцию удаления...

var removeElements = function(selector) {
    var elems = jQuery(selector);

    // Your code to notify the removal of the element here...
    alert(elems.length + " elements removed");

    jQuery(selector).remove();
};

// Sample usage
removeElements("#some-element");
removeElements("p");
removeElements(".myclass");

Ответ 11

Вот как создать jQuery live remove listener:

$(document).on('DOMNodeRemoved', function(e)
{
  var $element = $(e.target).find('.element');
  if ($element.length)
  {
    // do anything with $element
  }
});

Или:

$(document).on('DOMNodeRemoved', function(e)
{
  $(e.target).find('.element').each(function()
  {
    // do anything with $(this)
  }
});

Ответ 12

ссылаясь на ответ @David:

Когда вы хотите сделать soo с другой функцией, например. html(), как в моем случае, не забудьте добавить возврат в новую функцию:

(function() {
    var ev = new $.Event('html'),
        orig = $.fn.html;
    $.fn.html = function() {
        $(this).trigger(ev);
        return orig.apply(this, arguments);
    }
})();

Ответ 13

Это.

$.each(
  $('#some-element'), 
        function(i, item){
            item.addEventListener('DOMNodeRemovedFromDocument',
                function(e){ console.log('I has been removed'); console.log(e);
                })
         })

Ответ 14

Событие "удалить" из jQuery отлично работает, без добавления. Возможно, было бы более надежным во времени использовать простой трюк, а не исправлять jQuery.

Просто измените или добавьте атрибут в элемент, который вы собираетесь удалить из DOM. Таким образом, вы можете запускать любую функцию обновления, которая будет просто игнорировать элементы на пути к уничтожению, с атрибутом "do_not_count_it".

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

$('td[validity="count_it"]').on("remove", function () {
    $(this).attr("validity","do_not_count_it");
    update_prices();
});

И вот функция, которая находит последнюю цену в таблице, не принимая во внимание последнюю, если она была удалена. Действительно, когда инициируется событие "удалить", и когда эта функция вызывается, элемент еще не удаляется.

function update_prices(){
      var mytable=$("#pricestable");
      var lastpricecell = mytable.find('td[validity="count_it"]').last();
}

В конце концов, функция update_prices() работает нормально, и после этого элемент DOM удаляется.

Ответ 15

Другой подход - периодически проверять, является ли элемент еще частью DOM, проверяя, имеет ли он родительский node. Если вы не знаете, когда элемент может быть удален, вы можете использовать интервал:

var elem = document.querySelector('#some-element');
var intvl = setInterval(function(){
    if (!elem || !elem.parentNode){
        clearInterval(intvl);
        console.log('elem is no more');
    }
},10);

http://codepen.io/oriadam/pen/QEQGjq

Плюсы:

  • Использование jQuery
  • Поддержка любого вида удаления - jQuery, html-манипуляции, любая другая библиотека.

Минусы:

  • Использование jQuery:)
  • Использование интервала ← может быть улучшено путем присоединения к подозрительным событиям, вместо использования интервала