jQuery ma resize()
zdarzenie -, ale działa tylko z oknem.
jQuery(window).resize(function() { /* What ever */ });
To działa dobrze! Ale kiedy chcę dodać zdarzenie do elementu div, nie działa.
Na przykład
jQuery('div').resize(function() { /* What ever */ });
Chcę rozpocząć wywołanie zwrotne, gdy zmieni się rozmiar elementu div. Nie chcę rozpoczynać zdarzenia o zmiennym rozmiarze - po prostu zdarzenia, aby sprawdzić, czy rozmiar elementu div się zmienił.
Czy jest jakieś rozwiązanie, aby to zrobić?
javascript
jquery
TJR
źródło
źródło
Odpowiedzi:
DIV
nie uruchamiaresize
zdarzenia, więc nie będziesz w stanie zrobić dokładnie tego, co zakodowałeś, ale możesz przyjrzeć się monitorowaniu właściwości DOM .Jeśli faktycznie pracujesz z czymś takim jak resizables i jest to jedyny sposób na zmianę rozmiaru elementu div, to Twoja wtyczka do zmiany rozmiaru prawdopodobnie zaimplementuje własne wywołanie zwrotne.
źródło
Interesował mnie tylko wyzwalacz, gdy szerokość elementu została zmieniona (nie obchodzi mnie wysokość), więc stworzyłem zdarzenie jquery, które robi dokładnie to, używając niewidocznego elementu 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); }; } }
Wymaga następującego CSS:
iframe.width-changed { width: 100%; display: block; border: 0; height: 0; margin: 0; }
Możesz zobaczyć to w akcji tutaj widthChanged fiddle
źródło
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);
// 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));
źródło
Stworzyłem wtyczkę jquery jquery.resize , użyj resizeObserver, jeśli jest obsługiwana, lub rozwiązania opartego na zdarzeniu przewijania marcj / css-element-queries , bez setTimeout / setInterval.
Używasz tylko
jQuery('div').on('resize', function() { /* What ever */ });
lub jako wtyczka zmiany rozmiaru
jQuery('div').resizer(function() { /* What ever */ });
Stworzyłem to dla terminala jQuery i rozpakowałem do oddzielnych pakietów repo i npm, ale w międzyczasie przełączyłem się na ukrytą ramkę iframe, ponieważ miałem problemy ze zmianą rozmiaru, jeśli element był wewnątrz iframe. Mogę odpowiednio zaktualizować wtyczkę. Możesz spojrzeć na wtyczkę zmiany rozmiaru opartą na iframe w kodzie źródłowym terminala jQuery .
EDYCJA : nowa wersja używa elementu iframe i zmienia rozmiar obiektu okna, ponieważ poprzednie rozwiązania nie działały, gdy strona znajdowała się wewnątrz elementu iframe.
EDIT2 : Ponieważ element zastępczy używa elementu iframe, którego nie można używać z kontrolkami formularza lub obrazami, należy dodać go do elementu opakowania.
EDIT3:: istnieje lepsze rozwiązanie wykorzystujące polifill resizeObserver, który używa obserwatora mutacji (jeśli resizeObserver nie jest obsługiwany) i działa nawet w IE. Ma również typy TypeScript.
źródło
a co z tym:
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);
Swoją drogą sugeruję dodanie id do div i zmianę $ ("div") na $ ("# yourid"), będzie szybsze i nie zepsuje się, gdy później dodasz inne div
źródło
resize
zdarzenia okna . Można sobie wyobrazić, że rozmiar elementu div zmieni się bez natychmiastowej zmiany rozmiaru okna, w którym to przypadku/* what ever */
część nie zostanie oceniona.$(window).resize
nasłuchuje czynności fizycznej zmiany rozmiaru okna przeglądarki przez, powiedzmy, przeciągnięcie prawego dolnego rogu. Nie ma żadnych zdarzeń DOM, które wyzwalają to zdarzenieoverflow:hidden
lub nie. Ta odpowiedź nie rozwiązuje Twojego problemu. Bardziej sensowne byłoby uruchomienie tego kodu w zegarze niż podłączenie go do nasłuchiwania losowych zdarzeń, które prawdopodobnie nigdy nie zostaną wyzwolone. Byłoby jeszcze lepiej, gdybyś mógł użyć monitorowania właściwości DOM i wrócić do licznika czasu (lub ręcznie wywołać jakieś zdarzenie w miejscach, w których rozmiar div może się zmienić).Jest naprawdę fajna, łatwa w użyciu, lekka (wykorzystuje natywne zdarzenia przeglądarki do wykrywania) wtyczka zarówno dla podstawowego JavaScript, jak i dla jQuery, która została wydana w tym roku. Działa doskonale:
https://github.com/sdecima/javascript-detect-element-resize
źródło
Obsługiwane jest tylko okno tak, ale możesz użyć do niego wtyczki: http://benalman.com/projects/jquery-resize-plugin/
źródło
W przypadku integracji map Google szukałem sposobu na wykrycie, kiedy zmienił się rozmiar elementu div. Ponieważ mapy google zawsze wymagają odpowiednich wymiarów, np. Szerokości i wysokości, aby poprawnie renderować.
Rozwiązanie, które wymyśliłem, to delegacja wydarzenia, w moim przypadku kliknięcie karty. Może to być oczywiście zmiana rozmiaru okna, idea pozostaje ta sama:
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
w tym przypadku jest mój div mapy. Ponieważ mój rodzic jest niewidoczny podczas ładowania, obliczona szerokość i wysokość są równe 0 lub nie są zgodne. Używając.bind(this)
mogę delegować wykonywanie skryptu (this.activate
) do zdarzenia (click
).Teraz jestem pewien, że to samo dotyczy wydarzeń związanych ze zmianą rozmiaru.
$(window).one('resize', function() { this.div.css({ /*whatever*/ }); }.bind(this));
Mam nadzieję, że to pomoże każdemu!
źródło
Po prostu wypróbuj tę funkcję (może działać nie tylko w przypadku elementów DIV):
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); }
Możesz tego używać w ten sposób
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"!']);
AKTUALIZACJA: Możesz także użyć bardziej progresywnego obserwatora (może działać dla dowolnych obiektów, nie tylko elementów 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); }
Po prostu spróbuj:
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')})
Będzie rejestrował 'zmianę' za każdym razem, gdy bezpośrednio zmienisz b, a.foo lub a.ext
źródło
setInterval
może stać się dość drogi, ponieważ ciągle próbuje zmienić rozmiarconsole.log
tuż przed$.each
, zobaczysz, że będzie on drukowany co100ms
, tak jak ustawiłeśinterval
setInterval
działa. To jak e-mail „żywy” - ciągle pinguje serwer. Wiem to. I co? Wydajność? Przeczytaj mój komentarz powyżej. Martwisz się o coś innego? Napisz do mnie, przyjacielu.Możesz zmienić swój tekst, Treść lub Atrybut w zależności od rozmiaru ekranu: HTML:
<p class="change">Frequently Asked Questions (FAQ)</p> <p class="change">Frequently Asked Questions </p>
JavaScript:
<script> const changeText = document.querySelector('.change'); function resize() { if((window.innerWidth<500)&&(changeText.textContent="Frequently Asked Questions (FAQ)")){ changeText.textContent="FAQ"; } else { changeText.textContent="Frequently Asked Questions (FAQ)"; } } window.onresize = resize; </script>
źródło
Jeśli chcesz zmienić rozmiar samego div, musisz to określić w stylu css. Musisz dodać przepełnienie i zmienić rozmiar właściwości .
Poniżej znajduje się mój fragment kodu
#div1 { width: 90%; height: 350px; padding: 10px; border: 1px solid #aaaaaa; overflow: auto; resize: both; } <div id="div1"> </div>
źródło