Thursday, May 23, 2024
 Popular · Latest · Hot · Upcoming
53
rated 0 times [  59] [ 6]  / answers: 1 / hits: 22326  / 10 Years ago, wed, june 11, 2014, 12:00:00

Within the link function part of a directive we have access to the element object. I wish to determine if the element object is within the current viewport / if it is available.



I currently have the following:



link: function (scope, element, attrs, controller) {


var page = angular.element(window);
page.bind('scroll', function () {
var windowScroll = page[0].pageYOffset,
windowHeight = page[0].innerHeight;
// elementScroll = element.xpos; - this is undefined?
// elementScroll = element.getBoundingClientRect().top - this does not work... undefined?

// elementScroll = element[0].getBoundingClientRect().top - this does not work... undefined?
// ... logic follows that if elementScroll is between windowScroll & windowScroll + windowHeight it is visible!

});


I just can't seem to get the x and y positions for my specific element (the directive may be repeated many times).



Please note that I do not intend to install or use jQuery in my application.


More From » angularjs

 Answers
12

You can use element[0].getBoundingClientRect, it works - there is an example:



http://plnkr.co/edit/2eOw3B0MaM2vw3bQuFnf



If you need to track element visibility in angular directive, except scroll you also need to handle events: DOMContentLoaded, load and resize. Also it would be better to create only one handler for those events, and stop tracking element when directive is destroyed



app.directive('trackVisibility', function(){
function isVisible(el) {
var rect = el.getBoundingClientRect();
var clw = (window.innerWidth || document.documentElement.clientWidth);
var clh = (window.innerHeight || document.documentElement.clientHeight) ;

// checks if element is fully visible
//return (rect.top >= 0 && rect.bottom <= clh) && (rect.left >= 0 && rect.right <= clw);

// checks if part of element is visible
return (rect.left <= clw && 0 <= rect.right && rect.top <= clh && 0 <= rect.bottom);

}
var reg = [];

function register(element, fn) {
reg.push([element, fn]);
}

function deregister(element) {
reg = angular.filter(reg, function (item) {
return item[0] !== element;
});
}

angular.element(window).on('DOMContentLoaded load resize scroll', function () {
angular.forEach(reg, function (item) {
item[1](isVisible(item[0]));
});
});

return {
restrict: 'A',
link: function (scope, element, attrs, controller) {
register(element[0], function(isVisible){
scope.$apply(function(){
scope.isVisible = isVisible;
})
});
scope.$on('$destroy', function(){
deregister(element);
})
}
};
});


there is an example:
http://plnkr.co/edit/VkCgBvGnCWZ0JCM8tlaJ



I have used this approach to dynamically load images when they become visible.


[#70616] Monday, June 9, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
anabellejaynav

Total Points: 176
Total Questions: 105
Total Answers: 105

Location: Croatia
Member since Fri, Sep 11, 2020
4 Years ago
anabellejaynav questions
;