javascript - directivas de Angularjs actualizando ante cambios en los valores de los atributos del DOM
He estado trabajando en un módulo scrollspy para Angularjs. Me he encontrado con el problema de que si la página está manejando contenido dinámico, los datos de scrollspy (posiciones de los elementos) se desactualizan rápidamente. ¿Cuál es la forma de Angularjs de manejar problemas como este?
¿Debería cualquier directiva que realice manipulación del DOM $broadcast un evento que el módulo scrollspy vigila, permitiéndole refactorizar sus datos de posición?
¿Debería el módulo scrollspy verificar cada x segundos si hay un cambio en scrollHeight con $timeout?
¿O incluso mejor, existe una manera de enlazar y observar cambios en los valores de los atributos del DOM (atributos como offsetTop, offsetHeight, scrollHeight, no atributos de datos)?
Actualización: Código base agregado a GitHub
Respuesta #1
Los observadores de mutaciones parecen ser la herramienta necesaria, desafortunadamente solo son compatibles con los navegadores más recientes.
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
if( MutationObserver ) {
for ( var i = 0; i < spyService.spies.length; i++ ) {
var spy = spyService.spies[i].scope.spy;
var target = document.getElementById(spy);
var config = {
attributes: true,
childList: true,
characterData: true,
subtree: true
};
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.warn('mutation observation');
});
}).observe(target, config);
}
}
else {
console.warn('no mutation observers here');
$interval(function() {
angular.element( document ).ready( function() {
console.log('refreshing');
});
}, 2000);
}
Actualmente buscando un polyfill que realmente funcione.
EDITAR: Se agregó sondeo como alternativa si los Observadores de Mutaciones no son compatibles.
Respuesta #2
Algo así debería funcionar... aunque parece que no se actualiza con las transiciones de CSS.
scope.$watch(function(){
return elem[0].offsetLeft;
}, function(x){
console.log('ITEM AT '+x);
});
