2012-04-10 3 views
59

jQuery имеет resize() - событие, но оно просто работает с окном.Изменение размера элемента div

jQuery(window).resize(function() { /* What ever */ }); 

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

E.g.

jQuery('div').resize(function() { /* What ever */ }); 

Я хочу начать обратный вызов при изменении размера элемента div. Я не хочу запускать resizable-event - просто событие, чтобы проверить, изменился ли размер элемента div - .

У вас есть решение?

+2

события изменения размера запускаются только для окон (ов) объектов (и iframe может быть?). – BiAiB

+3

взгляните на эту страницу - http://benalman.com/code/projects/jquery-resize/examples/resize/ – Elen

ответ

2

только окно поддерживается да, но вы можете использовать плагин для него: http://benalman.com/projects/jquery-resize-plugin/

+1

Нет. Это именно то, что пытался ОП, и указал, что он не работает. –

+1

Я пропустил обновление для правильного ответа! –

+0

Работает в моем случае! : D – phlegx

26

DIV не огнь resize события, так что вы не будете в состоянии сделать именно то, что вы закодированы, но вы могли бы посмотрите на monitoring DOM properties.

Если вы на самом деле работаете с чем-то вроде resizables, и это единственный способ изменить размер div, тогда ваш плагин изменения размера, вероятно, будет реализовывать собственный обратный вызов.

6

что по этому поводу:

divH = divW = 0; 
jQuery(document).ready(function(){ 
    divW = jQuery("div").width(); 
    divH = jQuery("div").height(); 
}); 
function checkResize(){ 
    var w = jQuery("div").width(); 
    var h = jQuery("div").height(); 
    if (w != divW || h != divH) { 
     /*what ever*/ 
     divH = h; 
     divW = w; 
    } 
} 
jQuery(window).resize(checkResize); 
var timer = setInterval(checkResize, 1000); 

КСТАТИ Я предлагаю вам добавить идентификатор в DIV и изменить $ ("Див") до $ ("# yourid"), это будет быстрее, и он не сломается, когда позже вы добавите другие divs

+0

Конечно - это был просто пример - конечно, я использую id и классы для выбора моих элементов. Мне нравится ваша идея - я думаю, что это сработает! Большое спасибо. Я попробую через несколько минут и дам отзыв. – TJR

+0

Это контролирует DIV для изменения размера всякий раз, когда происходит событие «resize» окна. Вполне возможно, что размер div изменится без немедленного последующего изменения размера окна, и в этом случае часть '/ * what ever * /' не будет оцениваться. –

+0

Правильно! И это проблема в моем проекте. Элемент div находится во внешней оболочке, которая имеет атрибут css Overflow: hidden - поэтому окно не изменяет размер. Но по-другому пример будет работать нормально - я просто протестировал его. – TJR

0

Для интеграции с Google Maps я искал способ определить, когда div изменился по размеру. Поскольку карты Google всегда требуют правильных размеров, например. ширины и высоты для правильной визуализации.

Решение, с которым я столкнулся, - это делегирование события, в моем случае щелчок на вкладке. Это может быть окно изменения размера, конечно, идея остается той же:

if (parent.is(':visible')) { 
    w = parent.outerWidth(false); 
    h = w * mapRatio /*9/16*/; 
    this.map.css({ width: w, height: h }); 
} else { 
    this.map.closest('.tab').one('click', function() { 
     this.activate(); 
    }.bind(this)); 
} 

this.map в этом случае моя карта дел. Поскольку мой родитель невидим при загрузке, вычисленная ширина и высота равны 0 или не совпадают. С помощью .bind(this) я могу делегировать выполнение сценария (this.activate) на событие (click).

Теперь я уверен, что то же самое относится к событиям изменения размера.

$(window).one('resize', function() { 
    this.div.css({ /*whatever*/ }); 
}.bind(this)); 

Надеюсь, это поможет кому угодно!

3

Существует очень хороший, простой в использовании, легкий (использует собственные браузерные события для обнаружения) плагин для базового JavaScript и для jQuery, выпущенного в этом году. Он выполняет отлично:

https://github.com/sdecima/javascript-detect-element-resize

+1

вы сказали, что он не проводит опрос постоянно, но он делает это, он использует requestAnimationFrame: https://github.com/sdecima/javascript-detect- element-resize/blob/master/detect-element-resize.js –

+0

Интересно: ссылка на проект GitHub была вдохновлена ​​этим сообщением в блоге: http: //www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/Но код в сообщении значительно изменился позже, в то время как проект GitHub использует старый подход. Поэтому стоит взглянуть на оба, прежде чем вы решите, что использовать. –

24

Я был заинтересован только для триггера, когда ширина элемента была изменена (уход я не»о высоте), поэтому я создал событие Jquery, что делает именно то, что, используя невидимый элемент iframe.

$.event.special.widthChanged = { 
    remove: function() { 
     $(this).children('iframe.width-changed').remove(); 
    }, 
    add: function() { 
     var elm = $(this); 
     var iframe = elm.children('iframe.width-changed'); 
     if (!iframe.length) { 
      iframe = $('<iframe/>').addClass('width-changed').prependTo(this); 
     } 
     var oldWidth = elm.width(); 
     function elmResized() { 
      var width = elm.width(); 
      if (oldWidth != width) { 
       elm.trigger('widthChanged', [width, oldWidth]); 
       oldWidth = width; 
      } 
     } 

     var timer = 0; 
     var ielm = iframe[0]; 
     (ielm.contentWindow || ielm).onresize = function() { 
      clearTimeout(timer); 
      timer = setTimeout(elmResized, 20); 
     }; 
    } 
} 

Это требует следующий CSS:

iframe.width-changed { 
    width: 100%; 
    display: block; 
    border: 0; 
    height: 0; 
    margin: 0; 
} 

Вы можете увидеть его в действии здесь widthChanged fiddle

+0

Правильный ответ. Прикрепление события к окну iframe гораздо менее хакерское, чем интервал. –

+0

Это прекрасно! Я полностью создал js, добавив таблицу стилей динамически: 'var ss = document.createElement ('style'); ss.type = "text/css"; ss.innerHTML = "iframe.width-changed {width: 100%; display: block; border: 0; height: 0; margin: 0;}"; document.body.appendChild (ss); ' – runfaj

+0

Это чистый гений. – Thomas

12
// this is a Jquery plugin function that fires an event when the size of an element is changed 
// usage: $().sizeChanged(function(){}) 

(function ($) { 

$.fn.sizeChanged = function (handleFunction) { 
    var element = this; 
    var lastWidth = element.width(); 
    var lastHeight = element.height(); 

    setInterval(function() { 
     if (lastWidth === element.width()&&lastHeight === element.height()) 
      return; 
     if (typeof (handleFunction) == 'function') { 
      handleFunction({ width: lastWidth, height: lastHeight }, 
          { width: element.width(), height: element.height() }); 
      lastWidth = element.width(); 
      lastHeight = element.height(); 
     } 
    }, 100); 


    return element; 
}; 

}(jQuery)); 
0

Просто попробуйте FUNC (он может работать не только для дивы):

function resized(elem, func = function(){}, args = []){ 
    elem = jQuery(elem); 
    func = func.bind(elem); 
    var h = -1, w = -1; 
    setInterval(function(){ 
     if (elem.height() != h || elem.width() != w){ 
      h = elem.height(); 
      w = elem.width(); 
      func.apply(null, args); 
     } 
    }, 100); 
} 

Вы можете использовать его как этот

resized(/*element*/ '.advs-columns-main > div > div', /*callback*/ function(a){ 
    console.log(a); 
    console.log(this); //for accessing the jQuery element you passed 
}, /*callback arguments in array*/ ['I\'m the first arg named "a"!']); 

UPDATE: Вы можете также использовать более прогрессивный Бодрствующего (она может работать на любых объектах, не только DOM элементов):

function changed(elem, propsToBeChanged, func = function(){}, args = [], interval = 100){ 
     func = func.bind(elem); 
     var currentVal = {call: {}, std: {}}; 
     $.each(propsToBeChanged, (property, needCall)=>{ 
      needCall = needCall ? 'call' : 'std'; 
      currentVal[needCall][property] = new Boolean(); // is a minimal and unique value, its equivalent comparsion with each other will always return false 
     }); 
     setInterval(function(){ 
      $.each(propsToBeChanged, (property, needCall)=>{ 
       try{ 
        var currVal = needCall ? elem[property]() : elem[property]; 
       } catch (e){ // elem[property] is not a function anymore 
        var currVal = elem[property]; 
        needCall = false; 
        propsToBeChanged[property] = false; 
       } 
       needCall = needCall ? 'call' : 'std'; 
       if (currVal !== currentVal[needCall][property]){ 
        currentVal[needCall][property] = currVal; 
        func.apply(null, args); 
       } 
      }); 
     }, interval); 
    } 

Просто попробуйте :

var b = '2', 
    a = {foo: 'bar', ext:()=>{return b}}; 
changed(a, { 
// prop name || do eval like a function? 
    foo:  false, 
    ext:  true 
},()=>{console.log('changed')}) 

Он будет регистрировать 'изменен' каждый раз, когда вы меняете б, a.foo или a.ext непосредственно

+0

'setInterval' может стать довольно дорогостоящим, поскольку он продолжает изменять размер – ton

+0

@ton: Я думаю, что вы не совсем правы. Это происходит только в случае попытки изменить размер элемента при его изменении. :/Или вы беспокоитесь о производительности? В последних браузерах он отлично работает даже на «тяжелых» сайтах. – KaMeHb

+0

Если вы добавите простой 'console.log' непосредственно перед' $ .each', вы увидите, что он печатает каждые 100 мс, как вы установили в 'interval' – ton

Смежные вопросы