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

Определить, был ли элемент изменен с помощью javascript?

Можно ли просто добавить прослушиватели событий к определенным элементам, чтобы определить, были ли изменены их высота или ширина? Я бы хотел сделать это, не используя что-то интенсивное, например:

$(window).resize(function() { ... });

В идеале я хотел бы привязываться к определенным элементам:

$("#primaryContent p").resize(function() { ... });

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

4b9b3361

Ответ 1

Здесь плагин jQuery с методами watch и unwatch, которые могут просматривать определенные свойства элемента. Он вызывается как метод объекта jQuery. Он использует встроенные функции в браузерах, которые возвращают события при изменении DOM, и использует setTimeout() для браузеров, которые не поддерживают эти события.

Общий синтаксис функции watch приведен ниже:

$("selector here").watch(props, func, interval, id);
  • props представляет собой разделенную запятыми строку свойств, которые вы хотите (например, "width,height").
  • func - это функция обратного вызова, переданная параметрами watchData, index, где watchData относится к объекту формы { id: itId, props: [], func: func, vals: [] }, а index - индекс измененного свойства. this относится к измененному элементу.
  • interval - это интервал в миллисекундах для setInterval() в браузерах, которые не поддерживают просмотр свойств в DOM.
  • id - это необязательный идентификатор, который идентифицирует этого наблюдателя и используется для удаления определенного наблюдателя из объекта jQuery.

Общий синтаксис функции unwatch приведен ниже:

$("selector here").unwatch(id);
  • id - необязательный идентификатор, который идентифицирует этот наблюдатель для удаления. Если id не указан, все наблюдатели от объекта будут удалены.

Для тех, кому интересно, код плагина воспроизводится ниже:

$.fn.watch = function(props, func, interval, id) {
    /// <summary>
    /// Allows you to monitor changes in a specific
    /// CSS property of an element by polling the value.
    /// when the value changes a function is called.
    /// The function called is called in the context
    /// of the selected element (ie. this)
    /// </summary>    
    /// <param name="prop" type="String">CSS Property to watch. If not specified (null) code is called on interval</param>    
    /// <param name="func" type="Function">
    /// Function called when the value has changed.
    /// </param>    
    /// <param name="func" type="Function">
    /// optional id that identifies this watch instance. Use if
    /// if you have multiple properties you're watching.
    /// </param>
    /// <param name="id" type="String">A unique ID that identifies this watch instance on this element</param>  
    /// <returns type="jQuery" /> 
    if (!interval)
        interval = 200;
    if (!id)
        id = "_watcher";

    return this.each(function() {
        var _t = this;
        var el = $(this);
        var fnc = function() { __watcher.call(_t, id) };
        var itId = null;

        if (typeof (this.onpropertychange) == "object")
            el.bind("propertychange." + id, fnc);
        else if ($.browser.mozilla)
            el.bind("DOMAttrModified." + id, fnc);
        else
            itId = setInterval(fnc, interval);

        var data = { id: itId,
            props: props.split(","),
            func: func,
            vals: []
        };
        $.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); });
        el.data(id, data);
    });

    function __watcher(id) {
        var el = $(this);
        var w = el.data(id);

        var changed = false;
        var i = 0;
        for (i; i < w.props.length; i++) {
            var newVal = el.css(w.props[i]);
            if (w.vals[i] != newVal) {
                w.vals[i] = newVal;
                changed = true;
                break;
            }
        }
        if (changed && w.func) {
            var _t = this;
            w.func.call(_t, w, i)
        }
    }
}
$.fn.unwatch = function(id) {
    this.each(function() {
        var w = $(this).data(id);
        var el = $(this);
        el.removeData();

        if (typeof (this.onpropertychange) == "object")
            el.unbind("propertychange." + id, fnc);
        else if ($.browser.mozilla)
            el.unbind("DOMAttrModified." + id, fnc);
        else
            clearInterval(w.id);
    });
    return this;
}

Ответ 2

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

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


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

(function(){
  var attachEvent = document.attachEvent;
  var isIE = navigator.userAgent.match(/Trident/);
  var requestFrame = (function(){
    var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
        function(fn){ return window.setTimeout(fn, 20); };
    return function(fn){ return raf(fn); };
  })();

  var cancelFrame = (function(){
    var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
           window.clearTimeout;
    return function(id){ return cancel(id); };
  })();

  function resizeListener(e){
    var win = e.target || e.srcElement;
    if (win.__resizeRAF__) cancelFrame(win.__resizeRAF__);
    win.__resizeRAF__ = requestFrame(function(){
      var trigger = win.__resizeTrigger__;
      trigger.__resizeListeners__.forEach(function(fn){
        fn.call(trigger, e);
      });
    });
  }

  function objectLoad(e){
    this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
    this.contentDocument.defaultView.addEventListener('resize', resizeListener);
  }

  window.addResizeListener = function(element, fn){
    if (!element.__resizeListeners__) {
      element.__resizeListeners__ = [];
      if (attachEvent) {
        element.__resizeTrigger__ = element;
        element.attachEvent('onresize', resizeListener);
      }
      else {
        if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
        var obj = element.__resizeTrigger__ = document.createElement('object'); 
        obj.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;');
        obj.__resizeElement__ = element;
        obj.onload = objectLoad;
        obj.type = 'text/html';
        if (isIE) element.appendChild(obj);
        obj.data = 'about:blank';
        if (!isIE) element.appendChild(obj);
      }
    }
    element.__resizeListeners__.push(fn);
  };

  window.removeResizeListener = function(element, fn){
    element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
    if (!element.__resizeListeners__.length) {
      if (attachEvent) element.detachEvent('onresize', resizeListener);
      else {
        element.__resizeTrigger__.contentDocument.defaultView.removeEventListener('resize', resizeListener);
        element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__);
      }
    }
  }
})();

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

Здесь используется псевдокод для этого решения:

var myElement = document.getElementById('my_element'),
    myResizeFn = function(){
        /* do something on resize */
    };
addResizeListener(myElement, myResizeFn);
removeResizeListener(myElement, myResizeFn);

Demo

http://www.backalleycoder.com/resize-demo.html

Ответ 3

Да, это возможно. Вам нужно будет отслеживать все элементы при загрузке и хранить их. Вы можете попробовать демо here. В нем вам не нужно использовать какие-либо библиотеки, но я использовал jQuery только для того, чтобы быть быстрее.

Первое, что нужно сначала - сохранить их начальный размер

Вы можете сделать это, используя этот метод:

var state = [];           //Create an public (not necessary) array to store sizes.

$(window).load(function() {
    $("*").each(function() {
        var arr = [];
        arr[0] = this
        arr[1] = this.offsetWidth;
        arr[2] = this.offsetHeight;

        state[state.length] = arr;    //Store all elements' initial size
    });
});

Опять же, я использовал jQuery, чтобы быть быстрым.

Вторые - Проверьте!

Конечно, вам нужно будет проверить, было ли изменено:

function checksize(ele) {
    for (var i = 0; i < state.length; i++) {       //Search through your "database"
        if (state[i][0] == ele) {
            if (state[i][1] == ele.offsetWidth && state[i][2] == ele.offsetHeight) {
                return false
            } else {
                return true
            }
        }
    }
}

Просто он вернет false, если он не изменился, true, если он был изменен.

Надеюсь, это поможет вам!

Демо: http://jsfiddle.net/DerekL/6Evk6/