angular-in-viewport
Advanced tools
Comparing version 1.0.1 to 1.1.0
{ | ||
"name": "angular-in-viewport", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"homepage": "https://github.com/showpad/angular-in-viewport", | ||
"authors": [ | ||
"Klaas Cuvelier <cuvelierklaas@gmail.com>" | ||
], | ||
"description": "Directives to check if a DOM element is in a specified viewport", | ||
@@ -9,0 +6,0 @@ "main": "dist/in-viewport.js", |
# Changelog | ||
## 1.1.0 | ||
* Allow to specify `window` as the viewport (thx @compwright) | ||
## 1.0.1 | ||
@@ -4,0 +7,0 @@ * Fix package.json main file |
@@ -11,2 +11,6 @@ (function (angular) { | ||
angular | ||
.module('in-viewport') | ||
.directive('viewportEnter', viewportEnterDefinition); | ||
/** | ||
@@ -42,6 +46,2 @@ * Directive definition for viewport-enter | ||
angular | ||
.module('in-viewport') | ||
.directive('viewportEnter', viewportEnterDefinition); | ||
})(window.angular); | ||
@@ -51,2 +51,6 @@ (function (angular) { | ||
angular | ||
.module('in-viewport') | ||
.directive('viewportLeave', viewportLeaveDefinition); | ||
/** | ||
@@ -82,6 +86,2 @@ * Directive definition for viewport-enter | ||
angular | ||
.module('in-viewport') | ||
.directive('viewportLeave', viewportLeaveDefinition); | ||
})(window.angular); | ||
@@ -91,2 +91,5 @@ (function (angular) { | ||
angular | ||
.module('in-viewport') | ||
.directive('viewport', ViewportDefinition); | ||
@@ -96,3 +99,3 @@ /** | ||
*/ | ||
function ViewportDefinition() | ||
function ViewportDefinition($window) | ||
{ | ||
@@ -103,6 +106,8 @@ return { | ||
controller: ViewportController, | ||
link: ViewportLinking | ||
link: viewportLinking($window) | ||
}; | ||
} | ||
ViewportDefinition.$inject = ['$window']; | ||
/** | ||
@@ -114,3 +119,3 @@ * Controller for viewport directive | ||
{ | ||
var viewport = null, | ||
var viewportFn = null, | ||
isUpdating = false, | ||
@@ -128,3 +133,3 @@ updateAgain = false, | ||
if (!viewport) { | ||
if (!viewportFn) { | ||
return; | ||
@@ -140,3 +145,3 @@ } | ||
viewportRect = viewport.getBoundingClientRect(); | ||
viewportRect = viewportFn(); | ||
@@ -148,5 +153,5 @@ angular.forEach(items, function (item) { | ||
pointIsInsideBounds(elementRect.left, elementRect.top, viewportRect) || | ||
pointIsInsideBounds(elementRect.left + elementRect.width, elementRect.top, viewportRect) || | ||
pointIsInsideBounds(elementRect.left, elementRect.top + elementRect.height, viewportRect) || | ||
pointIsInsideBounds(elementRect.left + elementRect.width, elementRect.top + elementRect.height, viewportRect); | ||
pointIsInsideBounds(elementRect.right, elementRect.top, viewportRect) || | ||
pointIsInsideBounds(elementRect.left, elementRect.bottom, viewportRect) || | ||
pointIsInsideBounds(elementRect.right, elementRect.bottom, viewportRect); | ||
@@ -182,18 +187,24 @@ // On first check and on change | ||
{ | ||
return x >= bounds.left && | ||
y >= bounds.top && | ||
x <= bounds.left + bounds.width && | ||
y <= bounds.top + bounds.height; | ||
return x >= bounds.left && x <= bounds.right && y >= bounds.top && y <= bounds.bottom; | ||
} | ||
/** | ||
* Set the viewport element | ||
* @param element | ||
* Set the viewport box function | ||
* @param function | ||
*/ | ||
function setViewport (element) | ||
function setViewportFn(fn) | ||
{ | ||
viewport = element; | ||
viewportFn = fn; | ||
} | ||
/** | ||
* Return the current viewport box function | ||
* @returns {*} | ||
*/ | ||
function getViewportFn() | ||
{ | ||
return viewportFn; | ||
} | ||
/** | ||
* trigger an update | ||
@@ -240,2 +251,11 @@ */ | ||
/** | ||
* Get list of items | ||
* @returns {Array} | ||
*/ | ||
function getItems() | ||
{ | ||
return items; | ||
} | ||
angular.element($window) | ||
@@ -245,5 +265,7 @@ .on('resize', updateDelayed) | ||
this.setViewport = setViewport; | ||
this.add = add; | ||
this.updateDelayed = updateDelayed; | ||
this.setViewportFn = setViewportFn; | ||
this.getViewportFn = getViewportFn; | ||
this.add = add; | ||
this.getItems = getItems; | ||
this.updateDelayed = updateDelayed; | ||
} | ||
@@ -263,20 +285,35 @@ | ||
*/ | ||
function ViewportLinking($scope, iElement, iAttrs, viewport) | ||
function viewportLinking($window) | ||
{ | ||
viewport.setViewport(iElement[0]); | ||
iElement.on('scroll', viewport.updateDelayed); | ||
var linkFn = function($scope, iElement, iAttrs, $ctrl) { | ||
if (iAttrs.viewport === 'window') { | ||
$ctrl.setViewportFn(function() { | ||
return { | ||
top: 0, | ||
left: 0, | ||
bottom: window.innerHeight || document.documentElement.clientHeight, | ||
right: window.innerWidth || document.documentElement.clientWidth | ||
}; | ||
}); | ||
angular.element($window).on('scroll', $ctrl.updateDelayed); | ||
} else { | ||
$ctrl.setViewportFn(function() { | ||
return iElement[0].getBoundingClientRect(); | ||
}); | ||
iElement.on('scroll', $ctrl.updateDelayed); | ||
} | ||
// Trick angular in calling this on digest | ||
$scope.$watch(function () { | ||
viewport.updateDelayed(); | ||
}); | ||
} | ||
// Trick angular in calling this on digest | ||
$scope.$watch(function () { | ||
$ctrl.updateDelayed(); | ||
}); | ||
}; | ||
ViewportLinking.$inject = ['$scope', 'iElement', 'iAttrs', 'viewport']; | ||
linkFn.$inject = ['$scope', 'iElement', 'iAttrs', 'viewport']; | ||
angular | ||
.module('in-viewport') | ||
.directive('viewport', ViewportDefinition); | ||
return linkFn; | ||
} | ||
viewportLinking.$inject = ['$window']; | ||
})(window.angular); |
!function(i){"use strict";i.module("in-viewport",[])}(window.angular); | ||
!function(e){"use strict";function n(){return{require:"^viewport",restrict:"A",link:t}}function t(e,n,t,i){8!==n[0].nodeType&&t.viewportEnter&&i.add("enter",n[0],function(){e.$apply(function(){e.$eval(t.viewportEnter)})})}e.module("in-viewport").directive("viewportEnter",n)}(window.angular); | ||
!function(e){"use strict";function i(){return{require:"^viewport",restrict:"A",link:n}}function n(e,i,n,t){8!==i[0].nodeType&&n.viewportLeave&&t.add("leave",i[0],function(){e.$apply(function(){e.$eval(n.viewportLeave)})})}e.module("in-viewport").directive("viewportLeave",i)}(window.angular); | ||
!function(e){"use strict";function t(){return{restrict:"A",scope:!0,controller:n,link:i}}function n(t){function n(){var t,o,l;if(c){if(f)return void(a=!0);f=!0,t=c.getBoundingClientRect(),e.forEach(p,function(e){o=e.element.getBoundingClientRect(),l=i(o.left,o.top,t)||i(o.left+o.width,o.top,t)||i(o.left,o.top+o.height,t)||i(o.left+o.width,o.top+o.height,t),(null===e.state||e.state!==l)&&(l&&"function"==typeof e.enter?e.enter():l||"function"!=typeof e.leave||e.leave()),e.state=l}),f=!1,a&&(a=!1,n())}}function i(e,t,n){return e>=n.left&&t>=n.top&&e<=n.left+n.width&&t<=n.top+n.height}function o(e){c=e}function l(){window.clearTimeout(r),r=window.setTimeout(function(){n()},100)}function u(e,t,n){var i;if(-1===["leave","enter"].indexOf(e))throw"invalid event specified";i=d.indexOf(t),-1===i&&(d.push(t),p.push({element:t,state:null,leave:null,enter:null}),i=d.length-1),p[i][e]=n}var r,c=null,f=!1,a=!1,d=[],p=[];e.element(t).on("resize",l).on("orientationchange",l),this.setViewport=o,this.add=u,this.updateDelayed=l}function i(e,t,n,i){i.setViewport(t[0]),t.on("scroll",i.updateDelayed),e.$watch(function(){i.updateDelayed()})}n.$inject=["$window"],i.$inject=["$scope","iElement","iAttrs","viewport"],e.module("in-viewport").directive("viewport",t)}(window.angular); | ||
!function(t){"use strict";function e(t){return{restrict:"A",scope:!0,controller:n,link:i(t)}}function n(e){function n(){var e,o,r;if(f){if(a)return void(w=!0);a=!0,e=f(),t.forEach(p,function(t){o=t.element.getBoundingClientRect(),r=i(o.left,o.top,e)||i(o.right,o.top,e)||i(o.left,o.bottom,e)||i(o.right,o.bottom,e),(null===t.state||t.state!==r)&&(r&&"function"==typeof t.enter?t.enter():r||"function"!=typeof t.leave||t.leave()),t.state=r}),a=!1,w&&(w=!1,n())}}function i(t,e,n){return t>=n.left&&t<=n.right&&e>=n.top&&e<=n.bottom}function o(t){f=t}function r(){return f}function u(){window.clearTimeout(d),d=window.setTimeout(function(){n()},100)}function l(t,e,n){var i;if(-1===["leave","enter"].indexOf(t))throw"invalid event specified";i=s.indexOf(e),-1===i&&(s.push(e),p.push({element:e,state:null,leave:null,enter:null}),i=s.length-1),p[i][t]=n}function c(){return p}var d,f=null,a=!1,w=!1,s=[],p=[];t.element(e).on("resize",u).on("orientationchange",u),this.setViewportFn=o,this.getViewportFn=r,this.add=l,this.getItems=c,this.updateDelayed=u}function i(e){var n=function(n,i,o,r){"window"===o.viewport?(r.setViewportFn(function(){return{top:0,left:0,bottom:window.innerHeight||document.documentElement.clientHeight,right:window.innerWidth||document.documentElement.clientWidth}}),t.element(e).on("scroll",r.updateDelayed)):(r.setViewportFn(function(){return i[0].getBoundingClientRect()}),i.on("scroll",r.updateDelayed)),n.$watch(function(){r.updateDelayed()})};return n.$inject=["$scope","iElement","iAttrs","viewport"],n}t.module("in-viewport").directive("viewport",e),e.$inject=["$window"],n.$inject=["$window"],i.$inject=["$window"]}(window.angular); |
{ | ||
"name": "angular-in-viewport", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "Directives to check if a DOM element is in a specified viewport", | ||
@@ -5,0 +5,0 @@ "main": "dist/in-viewport.js", |
@@ -13,4 +13,6 @@ [![GitHub version](https://badge.fury.io/gh/showpad%2Fangular-in-viewport.svg)](http://badge.fury.io/gh/showpad%2Fangular-in-viewport) | ||
### viewport | ||
Directive (attribute) specifying the DOM element which should be used as viewport | ||
Directive (attribute) specifying the DOM element which should be used as viewport. | ||
To use `window` as the viewport element, set `viewport="window"` on any parent element. | ||
### viewport-enter | ||
@@ -23,5 +25,8 @@ Directive (attribute) specifying a DOM element which should be watched. When the element enters the viewport the value of the attribute will be evaled. | ||
#Compatibility | ||
This plugin has been tested with Angular 1.2 and 1.3 | ||
This plugin works with Angular 1.x (v1.2 and higher) | ||
#Example | ||
Viewport container element: | ||
```HTML | ||
@@ -33,3 +38,11 @@ <ul style="width: 200px; height: 200px" viewport> | ||
Window viewport: | ||
```HTML | ||
<ul style="width: 200px; height: 200px" viewport="window"> | ||
<li ng-repeat="item in items" style="width: 200px; height: 200px" viewport-leave="item.visible = false" viewport-enter="item.visible = true"> | ||
</ul> | ||
``` | ||
# License | ||
This Angular module has been published under the [MIT license](LICENSE) |
@@ -11,3 +11,3 @@ (function (angular) { | ||
*/ | ||
function ViewportDefinition() | ||
function ViewportDefinition($window) | ||
{ | ||
@@ -18,6 +18,8 @@ return { | ||
controller: ViewportController, | ||
link: ViewportLinking | ||
link: viewportLinking($window) | ||
}; | ||
} | ||
ViewportDefinition.$inject = ['$window']; | ||
/** | ||
@@ -29,3 +31,3 @@ * Controller for viewport directive | ||
{ | ||
var viewport = null, | ||
var viewportFn = null, | ||
isUpdating = false, | ||
@@ -43,3 +45,3 @@ updateAgain = false, | ||
if (!viewport) { | ||
if (!viewportFn) { | ||
return; | ||
@@ -55,3 +57,3 @@ } | ||
viewportRect = viewport.getBoundingClientRect(); | ||
viewportRect = viewportFn(); | ||
@@ -63,5 +65,5 @@ angular.forEach(items, function (item) { | ||
pointIsInsideBounds(elementRect.left, elementRect.top, viewportRect) || | ||
pointIsInsideBounds(elementRect.left + elementRect.width, elementRect.top, viewportRect) || | ||
pointIsInsideBounds(elementRect.left, elementRect.top + elementRect.height, viewportRect) || | ||
pointIsInsideBounds(elementRect.left + elementRect.width, elementRect.top + elementRect.height, viewportRect); | ||
pointIsInsideBounds(elementRect.right, elementRect.top, viewportRect) || | ||
pointIsInsideBounds(elementRect.left, elementRect.bottom, viewportRect) || | ||
pointIsInsideBounds(elementRect.right, elementRect.bottom, viewportRect); | ||
@@ -97,24 +99,21 @@ // On first check and on change | ||
{ | ||
return x >= bounds.left && | ||
y >= bounds.top && | ||
x <= bounds.left + bounds.width && | ||
y <= bounds.top + bounds.height; | ||
return x >= bounds.left && x <= bounds.right && y >= bounds.top && y <= bounds.bottom; | ||
} | ||
/** | ||
* Set the viewport element | ||
* @param element | ||
* Set the viewport box function | ||
* @param function | ||
*/ | ||
function setViewport(element) | ||
function setViewportFn(fn) | ||
{ | ||
viewport = element; | ||
viewportFn = fn; | ||
} | ||
/** | ||
* Return the current viewport | ||
* Return the current viewport box function | ||
* @returns {*} | ||
*/ | ||
function getViewport() | ||
function getViewportFn() | ||
{ | ||
return viewport; | ||
return viewportFn; | ||
} | ||
@@ -177,4 +176,4 @@ | ||
this.setViewport = setViewport; | ||
this.getViewport = getViewport; | ||
this.setViewportFn = setViewportFn; | ||
this.getViewportFn = getViewportFn; | ||
this.add = add; | ||
@@ -197,15 +196,35 @@ this.getItems = getItems; | ||
*/ | ||
function ViewportLinking($scope, iElement, iAttrs, viewport) | ||
function viewportLinking($window) | ||
{ | ||
viewport.setViewport(iElement[0]); | ||
iElement.on('scroll', viewport.updateDelayed); | ||
var linkFn = function($scope, iElement, iAttrs, $ctrl) { | ||
if (iAttrs.viewport === 'window') { | ||
$ctrl.setViewportFn(function() { | ||
return { | ||
top: 0, | ||
left: 0, | ||
bottom: window.innerHeight || document.documentElement.clientHeight, | ||
right: window.innerWidth || document.documentElement.clientWidth | ||
}; | ||
}); | ||
angular.element($window).on('scroll', $ctrl.updateDelayed); | ||
} else { | ||
$ctrl.setViewportFn(function() { | ||
return iElement[0].getBoundingClientRect(); | ||
}); | ||
iElement.on('scroll', $ctrl.updateDelayed); | ||
} | ||
// Trick angular in calling this on digest | ||
$scope.$watch(function () { | ||
viewport.updateDelayed(); | ||
}); | ||
// Trick angular in calling this on digest | ||
$scope.$watch(function () { | ||
$ctrl.updateDelayed(); | ||
}); | ||
}; | ||
linkFn.$inject = ['$scope', 'iElement', 'iAttrs', 'viewport']; | ||
return linkFn; | ||
} | ||
ViewportLinking.$inject = ['$scope', 'iElement', 'iAttrs', 'viewport']; | ||
viewportLinking.$inject = ['$window']; | ||
})(window.angular); |
@@ -28,3 +28,3 @@ 'use strict'; | ||
this.updateDelayed = function () {}; | ||
this.setViewport = function () {}; | ||
this.setViewportFn = function () {}; | ||
@@ -31,0 +31,0 @@ viewportMockController = this; |
@@ -28,3 +28,3 @@ 'use strict'; | ||
this.updateDelayed = function () {}; | ||
this.setViewport = function () {}; | ||
this.setViewportFn = function () {}; | ||
@@ -31,0 +31,0 @@ viewportMockController = this; |
@@ -38,7 +38,7 @@ 'use strict'; | ||
describe('setViewport/getViewport', function () { | ||
it('should set/get the current viewport element', function () { | ||
describe('setViewportFn/getViewportFn', function () { | ||
it('should set/get the current viewport box function', function () { | ||
var viewport = {}; | ||
controller.setViewport(viewport); | ||
expect(controller.getViewport()).toEqual(viewport); | ||
controller.setViewportFn(viewport); | ||
expect(controller.getViewportFn()).toEqual(viewport); | ||
}); | ||
@@ -138,3 +138,3 @@ }); | ||
element[0].scrollTop = 550; | ||
element[0].dispatchEvent(createEvent('scroll'));; | ||
element[0].dispatchEvent(createEvent('scroll')); | ||
@@ -141,0 +141,0 @@ element[0].scrollTop = 0; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
40400
25
944
46