2009-09-22 11 views
53

Buduję pasek narzędzi, który ma zostać umieszczony na stronie. element div zostanie włączony do domyślnego ustawienia wyświetlania : brak. Czy jest sposób, w jaki mogę umieścić detektor zdarzeń na moim pasku narzędzi, aby móc go odsłuchać, gdy stanie się on widoczny, aby można go było zainicjować? czy będę musiał przekazać mu zmienną ze strony zawierającej?JS: detektor zdarzeń, gdy element staje się widoczny?

Dzięki

+0

Czy ta odpowiedź pomaga? http://stackoverflow.com/questions/1397251/event-detect-when-css-property-changed-using-jquery#answer-1397500 – kangax

+0

@kangax, dziękuję. Ale ponieważ nie jest to powszechnie stosowane, myślę, że zamierzam zarysować cały pomysł słuchacza zdarzeń i pójść inną drogą. –

+0

Zobacz tę odpowiedź dla implementacji zdarzenia "onVisible" w JavaScript: http://stackoverflow.com/a/3807340/975097 –

Odpowiedz

9

Zdarzenia javascript zajmują się interakcją użytkownika, jeśli twój kod jest wystarczająco zorganizowany, powinieneś być w stanie wywołać funkcję inicjującą w tym samym miejscu, w którym zmienia się widoczność (tj. Nie powinieneś zmieniać mojegoElement.style.display w wielu miejscach, zamiast wywołać funkcję/metodę, która wykonuje to i nic innego warto)

+8

Ale jak byłbyś w stanie wykryć zmianę widoczności (tzn. Wywołać funkcję, gdy tylko element stanie się widoczny)? –

+0

Nie mogę tego zrobić. Zamiast próbować wykryć zmianę, musisz wiedzieć dokładnie, gdzie jest ona sprowokowana i zadzwonić tam. Jeśli zmiana widoczności nie jest czymś, za co bezpośrednio odpowiada Twój własny kod (np. Część lib), a logika, z jaką to się dzieje, jest bardzo wymyślna, myślę, że nie masz szczęścia? :) – figha

+2

Zignorowałem to pytanie, ponieważ pomimo całego sensu, jaki wywołuje, nie ma to związku z rzeczywistym problemem. (jeśli nie wyświetlam żadnych w ramce, wszystkie elementy dzieci stają się niewidoczne) – Sebas

11

Istnieje co najmniej jeden sposób, ale nie jest to bardzo dobry. można po prostu sondowanie element zmian, takich jak ten:

var previous_style, 
    poll = window.setInterval(function() 
{ 
    var current_style = document.getElementById('target').style.display; 
    if (previous_style != current_style) { 
     alert('style changed'); 
     window.clearInterval(poll); 
    } else { 
     previous_style = current_style; 
    } 
}, 100); 

Norma określa również mutation events DOM, ale nigdy nie miałem okazję z nich korzystać, a nie jestem pewien, jak dobrze są one obsługiwane. Można by wykorzystać je tak:

target.addEventListener('DOMAttrModified', function() 
{ 
    if (e.attrName == 'style') { 
     alert('style changed'); 
    } 
}, false); 

Ten kod jest wyłączony mojej głowie, więc nie jestem pewien, czy by to działało.

Najprostszym i najłatwiejszym rozwiązaniem byłoby wywołanie zwrotne w funkcji wyświetlania celu.

+0

Interesujące, dziękuję. Kilka lat później status DOMAttrModified zmienił się: "Przestarzałe - ta funkcja została usunięta ze standardów internetowych, chociaż niektóre przeglądarki nadal mogą ją obsługiwać, jest ona w trakcie upuszczania". (Mozilla) – BurninLeo

-1

moje rozwiązanie:

; (function ($) { 
$.each([ "toggle", "show", "hide" ], function(i, name) { 
    var cssFn = $.fn[ name ]; 
    $.fn[ name ] = function(speed, easing, callback) { 
     if(speed == null || typeof speed === "boolean"){ 
      var ret=cssFn.apply(this, arguments) 
      $.fn.triggerVisibleEvent.apply(this,arguments) 
      return ret 
     }else{ 
      var that=this 
      var new_callback=function(){ 
       callback.call(this) 
       $.fn.triggerVisibleEvent.apply(that,arguments) 
      } 
      var ret=this.animate(genFx(name, true), speed, easing, new_callback) 
      return ret 
     } 
    }; 
}); 

$.fn.triggerVisibleEvent=function(){ 
    this.each(function(){ 
     if($(this).is(':visible')){ 
      $(this).trigger('visible') 
      $(this).find('[data-trigger-visible-event]').triggerVisibleEvent() 
     } 
    }) 
} 
})(jQuery); 

na przykład:

if(!$info_center.is(':visible')){ 
    $info_center.attr('data-trigger-visible-event','true').one('visible',processMoreLessButton) 
}else{ 
    processMoreLessButton() 
} 

function processMoreLessButton(){ 
//some logic 
} 
+3

Powinieneś powiedzieć każdemu, że użyłeś oryginalnego kodu jQuery, to wzbudziłoby więcej pewności;) – aemonge

3

Jak mówi @figha, , jeśli jest to twoja własna strona internetowa, powinieneś po prostu uruchomić to, co potrzebujesz, aby uruchomić po uczynieniu elementu widocznym.

Jednakże dla udzielenia odpowiedzi na pytanie (i innych podejmowania Chrome lub Firefox Rozszerzenia, gdzie jest to częsty przypadek użycia), Mutation Summary i Mutation Observer pozwoli DOM zmienia się wyzwalać zdarzenia.

Na przykład wyzwalanie zdarzenia dla elementów z atrybutem data-widget dodawanym do DOM. Pożyczanie this excellent example from David Walsh's blog:

var observer = new MutationObserver(function(mutations) { 
    // For the sake of...observation...let's output the mutation to console to see how this all works 
    mutations.forEach(function(mutation) { 
     console.log(mutation.type); 
    });  
}); 

// Notify me of everything! 
var observerConfig = { 
    attributes: true, 
    childList: true, 
    characterData: true 
}; 

// Node, config 
// In this case we'll listen to all changes to body and child nodes 
var targetNode = document.body; 
observer.observe(targetNode, observerConfig); 

Responses to added, removed, valueChanged and more. valueChanged zawiera wszystkie atrybuty, w tym display itp.

+1

Er, czy niżejsza troska wyjaśnia dlaczego? – mikemaccana

+0

Prawdopodobnie dlatego, że chce wiedzieć, kiedy jest rzeczywiście na ekranie. Tak, mogę tylko założyć, że downvoter ma ten sam powód. –

+0

Nie odpowiada na pytanie, a wysyłanie tylko linków nie jest zalecane. –

2

Wystarczy do uwag na temat DOMAttrModified wsparcia przeglądarki detektor zdarzeń:

Cross-browser wsparcie

Zdarzenia te nie są realizowane konsekwentnie w całej inny przeglądarki, na przykład:

  • IE przed wersji 9 nie obsługuje zdarzenia mutacja w ogóle i nie implementuje niektóre z nich poprawnie w wersji 9 (na przykład DOMNodeInserted)

  • WebKit nie obsługuje DOMAttrModified (patrz WebKit błąd 8191 i tym obejście)

  • „wydarzenia nazwa mutacja”, czyli DOMElementNameChanged i DOMAttributeNameChanged nie są obsługiwane w Firefox (od wersji 11), a prawdopodobnie także w innych przeglądarkach.

Źródło: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events

13

miałem ten sam problem i stworzył plugin jQuery rozwiązywać je na naszej stronie.

https://github.com/shaunbowe/jquery.visibilityChanged

Oto jak można używać go w oparciu o przykład:

$('#contentDiv').visibilityChanged(function(element, visible) { 
    alert("do something"); 
}); 
+0

Nie można ustawić go do pracy z widocznością wyzwalaną przez AJAX – JackTheKnife

5

Idąc naprzód, nowy HTML Przecięcie Obserwator API jest rzeczą szukasz. Pozwala skonfigurować wywołanie zwrotne, które jest wywoływane, gdy jeden element, zwany celem, przecina rzutnię urządzenia lub określony element. Jest dostępny w najnowszych wersjach Chrome, Firefox i Edge. Aby uzyskać więcej informacji, patrz https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API.

Prosty przykład kodu do obserwowania display: none przełączania:

// Start observing visbility of element. On change, the 
// the callback is called with Boolean visibility as 
// argument: 

respondToVisibility(element, callback) { 
    var options = { 
    root: document.documentElement 
    } 

    var observer = new IntersectionObserver((entries, observer) => { 
    entries.forEach(entry => { 
     callback(entry.intersectionRatio > 0); 
    }); 
    }, options); 

    observer.observe(element); 
} 

w akcji: https://jsfiddle.net/elmarj/u35tez5n/5/

+1

> Interfejs API Intersection Observer pozwala skonfigurować wywołanie zwrotne, które jest wywoływane, gdy jeden element, zwany obiektem docelowym, przecina rzutnię urządzenia lub określony element; – stil

1
var targetNode = document.getElementById('elementId'); 
var observer = new MutationObserver(function(){ 
    if(targetNode.style.display !='none'){//doSomething } 
}); 
observer.observe(targetNode, { attributes: true, childList: true }); 

mogę być trochę późno, ale może po prostu użyć MutationObserver obserwować wszelkie zmiany na pożądanym elemencie. Jeśli nastąpi jakakolwiek zmiana, musisz po prostu sprawdzić, czy element jest wyświetlany.

+0

Jedyna odpowiedź sprawia, że ​​czuję się dobrze w 2018 roku – userlond

Powiązane problemy