angular-snapscroll
Advanced tools
Comparing version 1.2.0 to 1.3.0
{ | ||
"name": "angular-snapscroll", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"authors": [ | ||
@@ -5,0 +5,0 @@ "Joel Mukuthu <joelmukuthu@gmail.com>" |
@@ -0,1 +1,6 @@ | ||
## 1.3.0 | ||
### Features | ||
- Add module exports (https://github.com/joelmukuthu/angular-snapscroll/issues/46) | ||
## 1.2.0 | ||
@@ -63,1 +68,11 @@ | ||
- Change angular dep version to the lowest supported version (`1.2.24`) | ||
## 0.2.5 | ||
### Features | ||
- Support for installation with npm | ||
## 0.2.4 | ||
### Fixes | ||
- Fix wheel event when jQuery is also included on the page |
/** | ||
* angular-snapscroll | ||
* Version: 1.2.0 | ||
* (c) 2014-2016 Joel Mukuthu | ||
* Version: 1.3.0 | ||
* (c) 2014-2017 Joel Mukuthu | ||
* MIT License | ||
* Built on: 12-12-2016 21:13:13 GMT+0100 | ||
* Built on: 06-03-2017 12:22:02 GMT+0100 | ||
**/ | ||
(function () { | ||
angular | ||
.module('snapscroll', ['wheelie', 'scrollie']) | ||
.value('defaultSnapscrollScrollEasing', undefined) | ||
.value('defaultSnapscrollScrollDelay', 250) | ||
.value('defaultSnapscrollSnapDuration', 800) | ||
.value('defaultSnapscrollResizeDelay', 400) | ||
.value('defaultSnapscrollBindScrollTimeout', 400) | ||
.value('defaultSnapscrollPreventDoubleSnapDelay', 1000); | ||
})(); | ||
if (typeof exports === 'object') { | ||
module.exports = 'snapscroll'; | ||
} | ||
(function () { | ||
angular.module('snapscroll') | ||
.directive('fitWindowHeight', [ | ||
'$window', | ||
'$timeout', | ||
'defaultSnapscrollResizeDelay', | ||
function ( | ||
$window, | ||
$timeout, | ||
defaultSnapscrollResizeDelay | ||
) { | ||
return { | ||
restrict: 'A', | ||
require: 'snapscroll', | ||
link: function (scope, element, attributes, snapscroll) { | ||
var windowElement, | ||
resizePromise, | ||
resizeDelay = attributes.resizeDelay; | ||
angular | ||
.module('snapscroll', ['wheelie', 'scrollie']) | ||
.value('defaultSnapscrollScrollEasing', undefined) | ||
.value('defaultSnapscrollScrollDelay', 250) | ||
.value('defaultSnapscrollSnapDuration', 800) | ||
.value('defaultSnapscrollResizeDelay', 400) | ||
.value('defaultSnapscrollBindScrollTimeout', 400) | ||
.value('defaultSnapscrollPreventDoubleSnapDelay', 1000); | ||
function onWindowResize() { | ||
if (resizeDelay === false) { | ||
angular.module('snapscroll').directive('fitWindowHeight', [ | ||
'$window', | ||
'$timeout', | ||
'defaultSnapscrollResizeDelay', | ||
function ( | ||
$window, | ||
$timeout, | ||
defaultSnapscrollResizeDelay | ||
) { | ||
return { | ||
restrict: 'A', | ||
require: 'snapscroll', | ||
link: function (scope, element, attributes, snapscroll) { | ||
var windowElement, | ||
resizePromise, | ||
resizeDelay = attributes.resizeDelay; | ||
function onWindowResize() { | ||
if (resizeDelay === false) { | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
} else { | ||
$timeout.cancel(resizePromise); | ||
resizePromise = $timeout(function () { | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
} else { | ||
$timeout.cancel(resizePromise); | ||
resizePromise = $timeout(function () { | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
}, resizeDelay); | ||
} | ||
}, resizeDelay); | ||
} | ||
} | ||
function init() { | ||
if (resizeDelay === 'false') { | ||
resizeDelay = false; | ||
} else { | ||
resizeDelay = parseInt(resizeDelay, 10); | ||
if (isNaN(resizeDelay)) { | ||
resizeDelay = defaultSnapscrollResizeDelay; | ||
} | ||
function init() { | ||
if (resizeDelay === 'false') { | ||
resizeDelay = false; | ||
} else { | ||
resizeDelay = parseInt(resizeDelay, 10); | ||
if (isNaN(resizeDelay)) { | ||
resizeDelay = defaultSnapscrollResizeDelay; | ||
} | ||
} | ||
// set initial snapHeight | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
// set initial snapHeight | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
// update snapHeight on window resize | ||
windowElement = angular.element($window); | ||
windowElement.on('resize', onWindowResize); | ||
scope.$on('$destroy', function () { | ||
windowElement.off('resize'); | ||
}); | ||
} | ||
init(); | ||
// update snapHeight on window resize | ||
windowElement = angular.element($window); | ||
windowElement.on('resize', onWindowResize); | ||
scope.$on('$destroy', function () { | ||
windowElement.off('resize'); | ||
}); | ||
} | ||
}; | ||
}]); | ||
})(); | ||
(function () { | ||
function isNumber(value) { | ||
return angular.isNumber(value) && !isNaN(value); | ||
init(); | ||
} | ||
}; | ||
} | ||
]); | ||
var isDefined = angular.isDefined; | ||
var isUndefined = angular.isUndefined; | ||
var isFunction = angular.isFunction; | ||
var forEach = angular.forEach; | ||
angular.module('snapscroll').directive('snapscroll', [ | ||
'$timeout', | ||
'$document', | ||
'wheelie', | ||
'scrollie', | ||
'defaultSnapscrollScrollEasing', | ||
'defaultSnapscrollScrollDelay', | ||
'defaultSnapscrollSnapDuration', | ||
'defaultSnapscrollBindScrollTimeout', | ||
'defaultSnapscrollPreventDoubleSnapDelay', | ||
function ( | ||
$timeout, | ||
$document, | ||
wheelie, | ||
scrollie, | ||
defaultSnapscrollScrollEasing, | ||
defaultSnapscrollScrollDelay, | ||
defaultSnapscrollSnapDuration, | ||
defaultSnapscrollBindScrollTimeout, | ||
defaultSnapscrollPreventDoubleSnapDelay | ||
) { | ||
function isNumber(value) { | ||
return angular.isNumber(value) && !isNaN(value); | ||
} | ||
var scopeObject = { | ||
enabled: '=snapscroll', | ||
snapIndex: '=?', | ||
snapHeight: '=?', | ||
beforeSnap: '&', | ||
afterSnap: '&', | ||
snapAnimation: '=?' | ||
}; | ||
var isDefined = angular.isDefined; | ||
var isUndefined = angular.isUndefined; | ||
var isFunction = angular.isFunction; | ||
var forEach = angular.forEach; | ||
var controller = ['$scope', function ($scope) { | ||
this.setSnapHeight = function (height) { | ||
$scope.snapHeight = height; | ||
}; | ||
}]; | ||
return { | ||
restrict: 'A', | ||
scope: { | ||
enabled: '=snapscroll', | ||
snapIndex: '=?', | ||
snapHeight: '=?', | ||
beforeSnap: '&', | ||
afterSnap: '&', | ||
snapAnimation: '=?' | ||
}, | ||
controller: ['$scope', function ($scope) { | ||
this.setSnapHeight = function (height) { | ||
$scope.snapHeight = height; | ||
}; | ||
}], | ||
link: function (scope, element, attributes) { | ||
function getChildren() { | ||
return element.children(); | ||
} | ||
var snapscrollAsAnAttribute = [ | ||
'$timeout', | ||
'$document', | ||
'wheelie', | ||
'scrollie', | ||
'defaultSnapscrollScrollEasing', | ||
'defaultSnapscrollScrollDelay', | ||
'defaultSnapscrollSnapDuration', | ||
'defaultSnapscrollBindScrollTimeout', | ||
'defaultSnapscrollPreventDoubleSnapDelay', | ||
function ( | ||
$timeout, | ||
$document, | ||
wheelie, | ||
scrollie, | ||
defaultSnapscrollScrollEasing, | ||
defaultSnapscrollScrollDelay, | ||
defaultSnapscrollSnapDuration, | ||
defaultSnapscrollBindScrollTimeout, | ||
defaultSnapscrollPreventDoubleSnapDelay | ||
) { | ||
return { | ||
restrict: 'A', | ||
scope: scopeObject, | ||
controller: controller, | ||
link: function (scope, element, attributes) { | ||
function getChildren() { | ||
return element.children(); | ||
} | ||
function getHeight(domElement) { | ||
return domElement.offsetHeight; | ||
} | ||
function getHeight(domElement) { | ||
return domElement.offsetHeight; | ||
} | ||
function getChildHeight(snapIndex) { | ||
return getHeight(getChildren()[snapIndex]); | ||
} | ||
function getChildHeight(snapIndex) { | ||
return getHeight(getChildren()[snapIndex]); | ||
function getSnapHeight() { | ||
return getHeight(element[0]); | ||
} | ||
function getScrollHeight() { | ||
return element[0].scrollHeight; | ||
} | ||
function rectifyScrollTop(scrollTop) { | ||
var maxScrollTop = getScrollHeight() - getSnapHeight(); | ||
if (scrollTop > maxScrollTop) { | ||
return maxScrollTop; | ||
} | ||
return scrollTop; | ||
} | ||
function getSnapHeight() { | ||
return getHeight(element[0]); | ||
function getScrollTop(compositeIndex, previousCompositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
var scrollTop = 0; | ||
var children = getChildren(); | ||
for (var i = 0; i < snapIndex; i++) { | ||
scrollTop += getHeight(children[i]); | ||
} | ||
function getScrollHeight() { | ||
return element[0].scrollHeight; | ||
if (innerSnapIndex === 0) { | ||
return rectifyScrollTop(scrollTop); | ||
} | ||
function rectifyScrollTop(scrollTop) { | ||
var maxScrollTop = getScrollHeight() - getSnapHeight(); | ||
if (scrollTop > maxScrollTop) { | ||
return maxScrollTop; | ||
var snapHeight = getSnapHeight(); | ||
var childHeight = getHeight(children[snapIndex]); | ||
var innerScrollTop; | ||
if (isDefined(previousCompositeIndex) && | ||
innerSnapIndex < previousCompositeIndex[1]) { | ||
innerScrollTop = childHeight; | ||
for (var j = innerSnapIndex; j >= 0; j--) { | ||
innerScrollTop -= snapHeight; | ||
} | ||
return scrollTop; | ||
} else { | ||
innerScrollTop = 0; | ||
for (var k = 0; k < innerSnapIndex; k++) { | ||
innerScrollTop += snapHeight; | ||
} | ||
var overflow = innerScrollTop + snapHeight - childHeight; | ||
if (overflow > 0) { | ||
innerScrollTop -= overflow; | ||
} | ||
} | ||
function getScrollTop(compositeIndex, previousCompositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
return rectifyScrollTop(scrollTop + innerScrollTop); | ||
} | ||
var scrollTop = 0; | ||
var children = getChildren(); | ||
for (var i = 0; i < snapIndex; i++) { | ||
scrollTop += getHeight(children[i]); | ||
function snapTo(compositeIndex, previousCompositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var isSnapIndexChanged = isUndefined(previousCompositeIndex) || | ||
snapIndex !== previousCompositeIndex[0]; | ||
if (isSnapIndexChanged) { | ||
var returnValue = scope.beforeSnap({ | ||
snapIndex: snapIndex, | ||
$event: scope.sourceEvent | ||
}); | ||
if (returnValue === false) { | ||
if (isDefined(previousCompositeIndex)) { | ||
scope.ignoreCompositeIndexChange = true; | ||
scope.compositeIndex = previousCompositeIndex; | ||
} | ||
return; | ||
} | ||
if (innerSnapIndex === 0) { | ||
return rectifyScrollTop(scrollTop); | ||
if (isNumber(returnValue)) { | ||
scope.snapIndex = returnValue; | ||
return; | ||
} | ||
var snapHeight = getSnapHeight(); | ||
var childHeight = getHeight(children[snapIndex]); | ||
var innerScrollTop; | ||
if (isDefined(previousCompositeIndex) && | ||
innerSnapIndex < previousCompositeIndex[1]) { | ||
innerScrollTop = childHeight; | ||
for (var j = innerSnapIndex; j >= 0; j--) { | ||
innerScrollTop -= snapHeight; | ||
} | ||
} else { | ||
innerScrollTop = 0; | ||
for (var k = 0; k < innerSnapIndex; k++) { | ||
innerScrollTop += snapHeight; | ||
} | ||
var overflow = innerScrollTop + snapHeight - childHeight; | ||
if (overflow > 0) { | ||
innerScrollTop -= overflow; | ||
} | ||
} | ||
return rectifyScrollTop(scrollTop + innerScrollTop); | ||
} | ||
function snapTo(compositeIndex, previousCompositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var isSnapIndexChanged = isUndefined(previousCompositeIndex) || | ||
snapIndex !== previousCompositeIndex[0]; | ||
return scrollTo(getScrollTop( | ||
compositeIndex, | ||
previousCompositeIndex | ||
)).then(function () { | ||
if (isSnapIndexChanged) { | ||
var returnValue = scope.beforeSnap({ | ||
scope.afterSnap({ | ||
snapIndex: snapIndex, | ||
$event: scope.sourceEvent | ||
}); | ||
if (returnValue === false) { | ||
if (isDefined(previousCompositeIndex)) { | ||
scope.ignoreCompositeIndexChange = true; | ||
scope.compositeIndex = previousCompositeIndex; | ||
} | ||
return; | ||
} | ||
if (isNumber(returnValue)) { | ||
scope.snapIndex = returnValue; | ||
return; | ||
} | ||
} | ||
scope.sourceEvent = undefined; | ||
}); | ||
} | ||
return scrollTo(getScrollTop( | ||
compositeIndex, | ||
previousCompositeIndex | ||
)).then(function () { | ||
if (isSnapIndexChanged) { | ||
scope.afterSnap({ | ||
snapIndex: snapIndex, | ||
$event: scope.sourceEvent | ||
}); | ||
} | ||
scope.sourceEvent = undefined; | ||
}); | ||
function getCurrentScrollTop() { | ||
return element[0].scrollTop; | ||
} | ||
function scrollTo(scrollTop) { | ||
var args; | ||
if (!scope.snapAnimation) { | ||
args = [ | ||
element, | ||
scrollTop | ||
]; | ||
} else if (isUndefined(scope.snapEasing)) { | ||
// TODO: add tests for this. Will require refactoring | ||
// the default values into an object, which is a good | ||
// change anyway | ||
args = [ | ||
element, | ||
scrollTop, | ||
scope.snapDuration | ||
]; | ||
} else { | ||
args = [ | ||
element, | ||
scrollTop, | ||
scope.snapDuration, | ||
scope.snapEasing | ||
]; | ||
} | ||
function getCurrentScrollTop() { | ||
return element[0].scrollTop; | ||
var currentScrollTop = getCurrentScrollTop(); | ||
if (scrollTop > currentScrollTop) { | ||
scope.snapDirection = 'down'; | ||
} else if (scrollTop < currentScrollTop) { | ||
scope.snapDirection = 'up'; | ||
} else { | ||
scope.snapDirection = 'same'; | ||
} | ||
function scrollTo(scrollTop) { | ||
var args; | ||
if (!scope.snapAnimation) { | ||
args = [ | ||
element, | ||
scrollTop | ||
]; | ||
} else if (isUndefined(scope.snapEasing)) { | ||
// TODO: add tests for this. Will require refactoring | ||
// the default values into an object, which is a good | ||
// change anyway | ||
args = [ | ||
element, | ||
scrollTop, | ||
scope.snapDuration | ||
]; | ||
} else { | ||
args = [ | ||
element, | ||
scrollTop, | ||
scope.snapDuration, | ||
scope.snapEasing | ||
]; | ||
} | ||
unbindScroll(); | ||
return scrollie.to.apply(scrollie, args).then(function () { | ||
scope.snapDirection = undefined; | ||
bindScrollAfterDelay(); | ||
allowNextSnapAfterDelay(); | ||
}); | ||
} | ||
var currentScrollTop = getCurrentScrollTop(); | ||
if (scrollTop > currentScrollTop) { | ||
scope.snapDirection = 'down'; | ||
} else if (scrollTop < currentScrollTop) { | ||
scope.snapDirection = 'up'; | ||
function allowNextSnapAfterDelay() { | ||
function allowNextSnap() { | ||
scope.preventUp = false; | ||
scope.preventDown = false; | ||
} | ||
if (scope.preventUp || scope.preventDown) { | ||
if (scope.preventDoubleSnapDelay === false) { | ||
allowNextSnap(); | ||
} else { | ||
scope.snapDirection = 'same'; | ||
$timeout( | ||
allowNextSnap, | ||
scope.preventDoubleSnapDelay | ||
); | ||
} | ||
} | ||
} | ||
unbindScroll(); | ||
return scrollie.to.apply(scrollie, args).then(function () { | ||
scope.snapDirection = undefined; | ||
bindScrollAfterDelay(); | ||
allowNextSnapAfterDelay(); | ||
}); | ||
function isScrollable() { | ||
var snapHeight = getSnapHeight(); | ||
if (!snapHeight) { | ||
return false; | ||
} | ||
var children = getChildren(); | ||
if (!children.length) { | ||
return false; | ||
} | ||
var totalHeight = 0; | ||
forEach(children, function (child) { | ||
totalHeight += getHeight(child); | ||
}); | ||
if (totalHeight < snapHeight) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function allowNextSnapAfterDelay() { | ||
function allowNextSnap() { | ||
scope.preventUp = false; | ||
scope.preventDown = false; | ||
function isSnapIndexValid(snapIndex) { | ||
return snapIndex >= 0 && | ||
snapIndex <= getChildren().length - 1; | ||
} | ||
function snapIndexChanged(current, previous) { | ||
if (!isScrollable()) { | ||
return; | ||
} | ||
if (isUndefined(current)) { | ||
scope.snapIndex = 0; | ||
return; | ||
} | ||
if (!isNumber(current)) { | ||
if (!isNumber(previous)) { | ||
previous = 0; | ||
} | ||
if (scope.preventUp || scope.preventDown) { | ||
if (scope.preventDoubleSnapDelay === false) { | ||
allowNextSnap(); | ||
} else { | ||
$timeout( | ||
allowNextSnap, | ||
scope.preventDoubleSnapDelay | ||
); | ||
} | ||
} | ||
scope.snapIndex = previous; | ||
return; | ||
} | ||
function isScrollable() { | ||
var snapHeight = getSnapHeight(); | ||
if (!snapHeight) { | ||
return false; | ||
if (current % 1 !== 0) { | ||
scope.snapIndex = Math.round(current); | ||
return; | ||
} | ||
if (scope.ignoreSnapIndexChange === true) { | ||
scope.ignoreSnapIndexChange = undefined; | ||
return; | ||
} | ||
if (!isSnapIndexValid(current)) { | ||
if (!isSnapIndexValid(previous)) { | ||
previous = 0; | ||
} | ||
var children = getChildren(); | ||
if (!children.length) { | ||
return false; | ||
} | ||
var totalHeight = 0; | ||
forEach(children, function (child) { | ||
totalHeight += getHeight(child); | ||
}); | ||
if (totalHeight < snapHeight) { | ||
return false; | ||
} | ||
return true; | ||
scope.ignoreSnapIndexChange = true; | ||
scope.snapIndex = previous; | ||
return; | ||
} | ||
scope.compositeIndex = [current, 0]; | ||
} | ||
function isSnapIndexValid(snapIndex) { | ||
return snapIndex >= 0 && | ||
snapIndex <= getChildren().length - 1; | ||
function watchSnapIndex() { | ||
scope.unwatchSnapIndex = scope.$watch( | ||
'snapIndex', | ||
snapIndexChanged | ||
); | ||
} | ||
function unwatchSnapIndex() { | ||
if (!isFunction(scope.unwatchSnapIndex)) { | ||
return; | ||
} | ||
scope.unwatchSnapIndex(); | ||
scope.unwatchSnapIndex = undefined; | ||
} | ||
function snapIndexChanged(current, previous) { | ||
if (!isScrollable()) { | ||
return; | ||
} | ||
if (isUndefined(current)) { | ||
scope.snapIndex = 0; | ||
return; | ||
} | ||
if (!isNumber(current)) { | ||
if (!isNumber(previous)) { | ||
previous = 0; | ||
} | ||
scope.snapIndex = previous; | ||
return; | ||
} | ||
if (current % 1 !== 0) { | ||
scope.snapIndex = Math.round(current); | ||
return; | ||
} | ||
if (scope.ignoreSnapIndexChange === true) { | ||
scope.ignoreSnapIndexChange = undefined; | ||
return; | ||
} | ||
if (!isSnapIndexValid(current)) { | ||
if (!isSnapIndexValid(previous)) { | ||
previous = 0; | ||
} | ||
scope.ignoreSnapIndexChange = true; | ||
scope.snapIndex = previous; | ||
return; | ||
} | ||
scope.compositeIndex = [current, 0]; | ||
function compositeIndexChanged(current, previous) { | ||
if (isUndefined(current)) { | ||
return; | ||
} | ||
var snapIndex = current[0]; | ||
if (scope.snapIndex !== snapIndex) { | ||
scope.ignoreSnapIndexChange = true; | ||
scope.snapIndex = snapIndex; | ||
} | ||
if (scope.ignoreCompositeIndexChange === true) { | ||
scope.ignoreCompositeIndexChange = undefined; | ||
return; | ||
} | ||
snapTo(current, previous); | ||
} | ||
function watchSnapIndex() { | ||
scope.unwatchSnapIndex = scope.$watch( | ||
'snapIndex', | ||
snapIndexChanged | ||
); | ||
function watchCompositeIndex() { | ||
scope.unwatchCompositeIndex = scope.$watchCollection( | ||
'compositeIndex', | ||
compositeIndexChanged | ||
); | ||
} | ||
function unwatchCompositeIndex() { | ||
if (!isFunction(scope.unwatchCompositeIndex)) { | ||
return; | ||
} | ||
scope.unwatchCompositeIndex(); | ||
scope.unwatchCompositeIndex = undefined; | ||
} | ||
function unwatchSnapIndex() { | ||
if (!isFunction(scope.unwatchSnapIndex)) { | ||
return; | ||
} | ||
scope.unwatchSnapIndex(); | ||
scope.unwatchSnapIndex = undefined; | ||
function getMaxInnerSnapIndex(snapIndex) { | ||
var snapHeight = getSnapHeight(); | ||
var childHeight = getChildHeight(snapIndex); | ||
if (childHeight <= snapHeight) { | ||
return 0; | ||
} | ||
var max = parseInt((childHeight / snapHeight), 10); | ||
if (childHeight % snapHeight === 0) { | ||
max -= 1; | ||
} | ||
return max; | ||
} | ||
function compositeIndexChanged(current, previous) { | ||
if (isUndefined(current)) { | ||
return; | ||
} | ||
var snapIndex = current[0]; | ||
if (scope.snapIndex !== snapIndex) { | ||
scope.ignoreSnapIndexChange = true; | ||
scope.snapIndex = snapIndex; | ||
} | ||
if (scope.ignoreCompositeIndexChange === true) { | ||
scope.ignoreCompositeIndexChange = undefined; | ||
return; | ||
} | ||
snapTo(current, previous); | ||
function isCompositeIndexValid(compositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
if (innerSnapIndex < 0) { | ||
return isSnapIndexValid(snapIndex - 1); | ||
} | ||
if (innerSnapIndex > getMaxInnerSnapIndex(snapIndex)) { | ||
return isSnapIndexValid(snapIndex + 1); | ||
} | ||
return true; | ||
} | ||
function watchCompositeIndex() { | ||
scope.unwatchCompositeIndex = scope.$watchCollection( | ||
'compositeIndex', | ||
compositeIndexChanged | ||
); | ||
function rectifyCompositeIndex(compositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
if (innerSnapIndex < 0) { | ||
return [ | ||
snapIndex - 1, | ||
getMaxInnerSnapIndex(snapIndex - 1) | ||
]; | ||
} | ||
if (innerSnapIndex > getMaxInnerSnapIndex(snapIndex)) { | ||
return [snapIndex + 1, 0]; | ||
} | ||
return compositeIndex; | ||
} | ||
function unwatchCompositeIndex() { | ||
if (!isFunction(scope.unwatchCompositeIndex)) { | ||
return; | ||
} | ||
scope.unwatchCompositeIndex(); | ||
scope.unwatchCompositeIndex = undefined; | ||
function snap(direction, event) { | ||
if (!isScrollable()) { | ||
return; | ||
} | ||
function getMaxInnerSnapIndex(snapIndex) { | ||
var snapHeight = getSnapHeight(); | ||
var childHeight = getChildHeight(snapIndex); | ||
if (childHeight <= snapHeight) { | ||
return 0; | ||
} | ||
var max = parseInt((childHeight / snapHeight), 10); | ||
if (childHeight % snapHeight === 0) { | ||
max -= 1; | ||
} | ||
return max; | ||
direction === 'up' && (scope.preventDown = false); | ||
direction === 'down' && (scope.preventUp = false); | ||
if (scope.snapDirection === direction) { | ||
return true; | ||
} | ||
function isCompositeIndexValid(compositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
if (innerSnapIndex < 0) { | ||
return isSnapIndexValid(snapIndex - 1); | ||
} | ||
if (innerSnapIndex > getMaxInnerSnapIndex(snapIndex)) { | ||
return isSnapIndexValid(snapIndex + 1); | ||
} | ||
if (scope.preventUp || scope.preventDown) { | ||
return true; | ||
} | ||
function rectifyCompositeIndex(compositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
if (innerSnapIndex < 0) { | ||
return [ | ||
snapIndex - 1, | ||
getMaxInnerSnapIndex(snapIndex - 1) | ||
]; | ||
} | ||
if (innerSnapIndex > getMaxInnerSnapIndex(snapIndex)) { | ||
return [snapIndex + 1, 0]; | ||
} | ||
return compositeIndex; | ||
var snapIndex = scope.compositeIndex[0]; | ||
var innerSnapIndex = scope.compositeIndex[1]; | ||
var newInnerSnapIndex; | ||
if (direction === 'up') { | ||
newInnerSnapIndex = innerSnapIndex - 1; | ||
} | ||
if (direction === 'down') { | ||
newInnerSnapIndex = innerSnapIndex + 1; | ||
} | ||
function snap(direction, event) { | ||
if (!isScrollable()) { | ||
return; | ||
} | ||
var newCompositeIndex = [snapIndex, newInnerSnapIndex]; | ||
if (!isCompositeIndexValid(newCompositeIndex)) { | ||
return; | ||
} | ||
direction === 'up' && (scope.preventDown = false); | ||
direction === 'down' && (scope.preventUp = false); | ||
if (event.type === 'wheel') { | ||
direction === 'up' && (scope.preventUp = true); | ||
direction === 'down' && (scope.preventDown = true); | ||
} | ||
if (scope.snapDirection === direction) { | ||
return true; | ||
} | ||
scope.$apply(function () { | ||
scope.sourceEvent = event; | ||
scope.compositeIndex = rectifyCompositeIndex( | ||
newCompositeIndex | ||
); | ||
}); | ||
if (scope.preventUp || scope.preventDown) { | ||
return true; | ||
} | ||
return true; | ||
} | ||
var snapIndex = scope.compositeIndex[0]; | ||
var innerSnapIndex = scope.compositeIndex[1]; | ||
var newInnerSnapIndex; | ||
if (direction === 'up') { | ||
newInnerSnapIndex = innerSnapIndex - 1; | ||
} | ||
if (direction === 'down') { | ||
newInnerSnapIndex = innerSnapIndex + 1; | ||
} | ||
function snapUp(event) { | ||
return snap('up', event); | ||
} | ||
var newCompositeIndex = [snapIndex, newInnerSnapIndex]; | ||
if (!isCompositeIndexValid(newCompositeIndex)) { | ||
return; | ||
} | ||
function snapDown(event) { | ||
return snap('down', event); | ||
} | ||
if (event.type === 'wheel') { | ||
direction === 'up' && (scope.preventUp = true); | ||
direction === 'down' && (scope.preventDown = true); | ||
function bindWheel() { | ||
if (scope.disableWheelBinding || scope.wheelBound) { | ||
return; | ||
} | ||
wheelie.bind(element, { | ||
up: function (e) { | ||
e.preventDefault(); | ||
if (snapUp(e)) { | ||
e.stopPropagation(); | ||
} | ||
}, | ||
down: function (e) { | ||
e.preventDefault(); | ||
if (snapDown(e)) { | ||
e.stopPropagation(); | ||
} | ||
} | ||
}, scope.ignoreWheelClass); | ||
scope.wheelBound = true; | ||
} | ||
scope.$apply(function () { | ||
scope.sourceEvent = event; | ||
scope.compositeIndex = rectifyCompositeIndex( | ||
newCompositeIndex | ||
); | ||
}); | ||
return true; | ||
function unbindWheel() { | ||
if (!scope.wheelBound) { | ||
return; | ||
} | ||
wheelie.unbind(element); | ||
scope.wheelBound = false; | ||
} | ||
function snapUp(event) { | ||
return snap('up', event); | ||
} | ||
function setHeight(angularElement, height) { | ||
angularElement.css('height', height + 'px'); | ||
} | ||
function snapDown(event) { | ||
return snap('down', event); | ||
function snapHeightChanged(current, previous) { | ||
if (isUndefined(current)) { | ||
return; | ||
} | ||
function bindWheel() { | ||
if (scope.disableWheelBinding || scope.wheelBound) { | ||
return; | ||
if (!isNumber(current)) { | ||
if (isNumber(previous)) { | ||
scope.snapHeight = previous; | ||
} | ||
wheelie.bind(element, { | ||
up: function (e) { | ||
e.preventDefault(); | ||
if (snapUp(e)) { | ||
e.stopPropagation(); | ||
} | ||
}, | ||
down: function (e) { | ||
e.preventDefault(); | ||
if (snapDown(e)) { | ||
e.stopPropagation(); | ||
} | ||
} | ||
}, scope.ignoreWheelClass); | ||
scope.wheelBound = true; | ||
return; | ||
} | ||
function unbindWheel() { | ||
if (!scope.wheelBound) { | ||
return; | ||
setHeight(element, current); | ||
forEach(getChildren(), function (child) { | ||
setHeight(angular.element(child), current); | ||
}); | ||
if (isDefined(scope.snapIndex)) { | ||
if (isUndefined(scope.compositeIndex)) { | ||
scope.compositeIndex = [scope.snapIndex, 0]; | ||
} | ||
wheelie.unbind(element); | ||
scope.wheelBound = false; | ||
snapTo(scope.compositeIndex); | ||
} | ||
} | ||
function setHeight(angularElement, height) { | ||
angularElement.css('height', height + 'px'); | ||
function watchSnapHeight() { | ||
scope.unwatchSnapHeight = scope.$watch( | ||
'snapHeight', | ||
snapHeightChanged | ||
); | ||
} | ||
function unwatchSnapHeight() { | ||
if (!isFunction(scope.unwatchSnapHeight)) { | ||
return; | ||
} | ||
scope.unwatchSnapHeight(); | ||
scope.unwatchSnapHeight = undefined; | ||
} | ||
function snapHeightChanged(current, previous) { | ||
if (isUndefined(current)) { | ||
return; | ||
function getCompositeIndex(scrollTop) { | ||
var snapIndex = 0; | ||
var innerSnapIndex = 0; | ||
if (scrollTop > 0) { | ||
snapIndex = -1; | ||
var children = getChildren(); | ||
var childHeight; | ||
while (scrollTop > 0) { | ||
childHeight = getHeight(children[++snapIndex]); | ||
scrollTop -= childHeight; | ||
} | ||
if (!isNumber(current)) { | ||
if (isNumber(previous)) { | ||
scope.snapHeight = previous; | ||
var snapHeight = getSnapHeight(); | ||
if (childHeight > snapHeight) { | ||
scrollTop += childHeight - snapHeight; | ||
if (scrollTop >= snapHeight) { | ||
innerSnapIndex++; | ||
} | ||
return; | ||
while (scrollTop > 0) { | ||
innerSnapIndex++; | ||
scrollTop -= snapHeight; | ||
} | ||
if ((snapHeight / 2) >= -scrollTop) { | ||
innerSnapIndex += 1; | ||
} | ||
} else if ((childHeight / 2) >= -scrollTop) { | ||
snapIndex += 1; | ||
} | ||
} | ||
setHeight(element, current); | ||
forEach(getChildren(), function (child) { | ||
setHeight(angular.element(child), current); | ||
}); | ||
return rectifyCompositeIndex([snapIndex, innerSnapIndex]); | ||
} | ||
if (isDefined(scope.snapIndex)) { | ||
if (isUndefined(scope.compositeIndex)) { | ||
scope.compositeIndex = [scope.snapIndex, 0]; | ||
} | ||
function onScroll() { | ||
function snapFromSrollTop() { | ||
var compositeIndex = getCompositeIndex( | ||
getCurrentScrollTop() | ||
); | ||
if (scope.compositeIndex[0] === compositeIndex[0] && | ||
scope.compositeIndex[1] === compositeIndex[1]) { | ||
snapTo(scope.compositeIndex); | ||
} else { | ||
scope.$apply(function () { | ||
scope.compositeIndex = compositeIndex; | ||
}); | ||
} | ||
} | ||
function watchSnapHeight() { | ||
scope.unwatchSnapHeight = scope.$watch( | ||
'snapHeight', | ||
snapHeightChanged | ||
scrollie.stop(element); | ||
if (scope.scrollDelay === false) { | ||
snapFromSrollTop(); | ||
} else { | ||
$timeout.cancel(scope.scrollPromise); | ||
scope.scrollPromise = $timeout( | ||
function () { | ||
snapFromSrollTop(); | ||
scope.scrollPromise = undefined; | ||
}, | ||
scope.scrollDelay | ||
); | ||
} | ||
} | ||
function unwatchSnapHeight() { | ||
if (!isFunction(scope.unwatchSnapHeight)) { | ||
return; | ||
} | ||
scope.unwatchSnapHeight(); | ||
scope.unwatchSnapHeight = undefined; | ||
function bindScroll() { | ||
if (scope.preventSnappingAfterManualScroll || | ||
scope.scrollBound) { | ||
return; | ||
} | ||
function getCompositeIndex(scrollTop) { | ||
var snapIndex = 0; | ||
var innerSnapIndex = 0; | ||
if (scrollTop > 0) { | ||
snapIndex = -1; | ||
var children = getChildren(); | ||
var childHeight; | ||
while (scrollTop > 0) { | ||
childHeight = getHeight(children[++snapIndex]); | ||
scrollTop -= childHeight; | ||
} | ||
var snapHeight = getSnapHeight(); | ||
if (childHeight > snapHeight) { | ||
scrollTop += childHeight - snapHeight; | ||
if (scrollTop >= snapHeight) { | ||
innerSnapIndex++; | ||
} | ||
while (scrollTop > 0) { | ||
innerSnapIndex++; | ||
scrollTop -= snapHeight; | ||
} | ||
if ((snapHeight / 2) >= -scrollTop) { | ||
innerSnapIndex += 1; | ||
} | ||
} else if ((childHeight / 2) >= -scrollTop) { | ||
snapIndex += 1; | ||
} | ||
} | ||
return rectifyCompositeIndex([snapIndex, innerSnapIndex]); | ||
if (isDefined(scope.snapDirection)) { // still snapping | ||
// TODO: add tests for this | ||
bindScrollAfterDelay(); | ||
return; | ||
} | ||
element.on('scroll', onScroll); | ||
scope.scrollBound = true; | ||
} | ||
function onScroll() { | ||
function snapFromSrollTop() { | ||
var compositeIndex = getCompositeIndex( | ||
getCurrentScrollTop() | ||
); | ||
if (scope.compositeIndex[0] === compositeIndex[0] && | ||
scope.compositeIndex[1] === compositeIndex[1]) { | ||
snapTo(scope.compositeIndex); | ||
} else { | ||
scope.$apply(function () { | ||
scope.compositeIndex = compositeIndex; | ||
}); | ||
} | ||
} | ||
scrollie.stop(element); | ||
if (scope.scrollDelay === false) { | ||
snapFromSrollTop(); | ||
} else { | ||
$timeout.cancel(scope.scrollPromise); | ||
scope.scrollPromise = $timeout( | ||
function () { | ||
snapFromSrollTop(); | ||
scope.scrollPromise = undefined; | ||
}, | ||
scope.scrollDelay | ||
); | ||
} | ||
function unbindScroll() { | ||
if (!scope.scrollBound) { | ||
return; | ||
} | ||
element.off('scroll', onScroll); | ||
scope.scrollBound = false; | ||
} | ||
function bindScroll() { | ||
if (scope.preventSnappingAfterManualScroll || | ||
scope.scrollBound) { | ||
return; | ||
} | ||
if (isDefined(scope.snapDirection)) { // still snapping | ||
// TODO: add tests for this | ||
bindScrollAfterDelay(); | ||
return; | ||
} | ||
element.on('scroll', onScroll); | ||
scope.scrollBound = true; | ||
function bindScrollAfterDelay() { | ||
if (scope.preventSnappingAfterManualScroll) { | ||
return; | ||
} | ||
function unbindScroll() { | ||
if (!scope.scrollBound) { | ||
return; | ||
} | ||
element.off('scroll', onScroll); | ||
scope.scrollBound = false; | ||
if (scope.bindScrollPromise) { | ||
$timeout.cancel(scope.bindScrollPromise); | ||
} | ||
scope.bindScrollPromise = $timeout( | ||
function () { | ||
bindScroll(); | ||
scope.bindScrollPromise = undefined; | ||
}, | ||
defaultSnapscrollBindScrollTimeout | ||
); | ||
} | ||
function bindScrollAfterDelay() { | ||
if (scope.preventSnappingAfterManualScroll) { | ||
return; | ||
} | ||
if (scope.bindScrollPromise) { | ||
$timeout.cancel(scope.bindScrollPromise); | ||
} | ||
scope.bindScrollPromise = $timeout( | ||
function () { | ||
bindScroll(); | ||
scope.bindScrollPromise = undefined; | ||
}, | ||
defaultSnapscrollBindScrollTimeout | ||
); | ||
function onKeyDown(e) { | ||
if (e.originalEvent) { | ||
e = e.originalEvent; | ||
} | ||
var handler; | ||
var keyCode = e.keyCode; | ||
if (keyCode === 38) { | ||
handler = snapUp; | ||
} | ||
if (keyCode === 40) { | ||
handler = snapDown; | ||
} | ||
if (handler) { | ||
e.preventDefault(); | ||
handler(e); | ||
} | ||
} | ||
function onKeyDown(e) { | ||
if (e.originalEvent) { | ||
e = e.originalEvent; | ||
} | ||
var handler; | ||
var keyCode = e.keyCode; | ||
if (keyCode === 38) { | ||
handler = snapUp; | ||
} | ||
if (keyCode === 40) { | ||
handler = snapDown; | ||
} | ||
if (handler) { | ||
e.preventDefault(); | ||
handler(e); | ||
} | ||
function bindArrowKeys() { | ||
if (!scope.enableArrowKeys || scope.arrowKeysBound) { | ||
return; | ||
} | ||
$document.on('keydown', onKeyDown); | ||
scope.arrowKeysBound = true; | ||
} | ||
function bindArrowKeys() { | ||
if (!scope.enableArrowKeys || scope.arrowKeysBound) { | ||
return; | ||
} | ||
$document.on('keydown', onKeyDown); | ||
scope.arrowKeysBound = true; | ||
function unbindArrowKeys() { | ||
if (!scope.arrowKeysBound) { | ||
return; | ||
} | ||
$document.off('keydown', onKeyDown); | ||
scope.arrowKeysBound = false; | ||
} | ||
function unbindArrowKeys() { | ||
if (!scope.arrowKeysBound) { | ||
return; | ||
function init() { | ||
var scrollDelay = attributes.scrollDelay; | ||
if (scrollDelay === 'false') { | ||
scope.scrollDelay = false; | ||
} else { | ||
scrollDelay = parseInt(scrollDelay, 10); | ||
if (isNaN(scrollDelay)) { | ||
scrollDelay = defaultSnapscrollScrollDelay; | ||
} | ||
$document.off('keydown', onKeyDown); | ||
scope.arrowKeysBound = false; | ||
scope.scrollDelay = scrollDelay; | ||
} | ||
function init() { | ||
var scrollDelay = attributes.scrollDelay; | ||
if (scrollDelay === 'false') { | ||
scope.scrollDelay = false; | ||
} else { | ||
scrollDelay = parseInt(scrollDelay, 10); | ||
if (isNaN(scrollDelay)) { | ||
scrollDelay = defaultSnapscrollScrollDelay; | ||
} | ||
scope.scrollDelay = scrollDelay; | ||
} | ||
var preventDoubleSnapDelay = ( | ||
attributes.preventDoubleSnapDelay | ||
var preventDoubleSnapDelay = ( | ||
attributes.preventDoubleSnapDelay | ||
); | ||
if (preventDoubleSnapDelay === 'false') { | ||
scope.preventDoubleSnapDelay = false; | ||
} else { | ||
preventDoubleSnapDelay = parseInt( | ||
preventDoubleSnapDelay, | ||
10 | ||
); | ||
if (preventDoubleSnapDelay === 'false') { | ||
scope.preventDoubleSnapDelay = false; | ||
} else { | ||
preventDoubleSnapDelay = parseInt( | ||
preventDoubleSnapDelay, | ||
10 | ||
if (isNaN(preventDoubleSnapDelay)) { | ||
preventDoubleSnapDelay = ( | ||
defaultSnapscrollPreventDoubleSnapDelay | ||
); | ||
if (isNaN(preventDoubleSnapDelay)) { | ||
preventDoubleSnapDelay = ( | ||
defaultSnapscrollPreventDoubleSnapDelay | ||
); | ||
} | ||
scope.preventDoubleSnapDelay = preventDoubleSnapDelay; | ||
} | ||
scope.preventDoubleSnapDelay = preventDoubleSnapDelay; | ||
} | ||
var snapEasing = attributes.snapEasing; | ||
if (isDefined(snapEasing)) { | ||
scope.snapEasing = scope.$parent.$eval(snapEasing); | ||
} else if (isFunction(defaultSnapscrollScrollEasing)) { | ||
scope.snapEasing = defaultSnapscrollScrollEasing; | ||
} | ||
var snapEasing = attributes.snapEasing; | ||
if (isDefined(snapEasing)) { | ||
scope.snapEasing = scope.$parent.$eval(snapEasing); | ||
} else if (isFunction(defaultSnapscrollScrollEasing)) { | ||
scope.snapEasing = defaultSnapscrollScrollEasing; | ||
} | ||
var snapDuration = parseInt(attributes.snapDuration, 10); | ||
if (isNaN(snapDuration)) { | ||
snapDuration = defaultSnapscrollSnapDuration; | ||
} | ||
scope.snapDuration = snapDuration; | ||
var snapDuration = parseInt(attributes.snapDuration, 10); | ||
if (isNaN(snapDuration)) { | ||
snapDuration = defaultSnapscrollSnapDuration; | ||
} | ||
scope.snapDuration = snapDuration; | ||
// TODO: perform initial snap without animation | ||
if (isUndefined(scope.snapAnimation)) { | ||
scope.snapAnimation = true; | ||
} | ||
// TODO: perform initial snap without animation | ||
if (isUndefined(scope.snapAnimation)) { | ||
scope.snapAnimation = true; | ||
} | ||
scope.disableWheelBinding = isDefined( | ||
attributes.disableWheelBinding | ||
); | ||
scope.disableWheelBinding = isDefined( | ||
attributes.disableWheelBinding | ||
); | ||
scope.enableArrowKeys = isDefined( | ||
attributes.enableArrowKeys | ||
); | ||
scope.enableArrowKeys = isDefined( | ||
attributes.enableArrowKeys | ||
); | ||
scope.preventSnappingAfterManualScroll = isDefined( | ||
attributes.preventSnappingAfterManualScroll | ||
); | ||
scope.preventSnappingAfterManualScroll = isDefined( | ||
attributes.preventSnappingAfterManualScroll | ||
); | ||
scope.ignoreWheelClass = attributes.ignoreWheelClass; | ||
scope.ignoreWheelClass = attributes.ignoreWheelClass; | ||
if (element.css('overflowY') !== 'scroll') { | ||
element.css('overflowY', 'auto'); | ||
} | ||
if (element.css('overflowY') !== 'scroll') { | ||
element.css('overflowY', 'auto'); | ||
} | ||
scope.$watch('enabled', function (current, previous) { | ||
function updateCompositeIndexFromScrollTop() { | ||
if (scope.preventSnappingAfterManualScroll) { | ||
return; | ||
} | ||
scope.compositeIndex = getCompositeIndex( | ||
getCurrentScrollTop() | ||
); | ||
scope.$watch('enabled', function (current, previous) { | ||
function updateCompositeIndexFromScrollTop() { | ||
if (scope.preventSnappingAfterManualScroll) { | ||
return; | ||
} | ||
if (current !== false) { | ||
if (previous === false) { | ||
updateCompositeIndexFromScrollTop(); | ||
} | ||
watchCompositeIndex(); | ||
watchSnapIndex(); | ||
watchSnapHeight(); | ||
bindScroll(); | ||
bindWheel(); | ||
bindArrowKeys(); | ||
} else { | ||
unwatchCompositeIndex(); | ||
unwatchSnapIndex(); | ||
unwatchSnapHeight(); | ||
unbindScroll(); | ||
unbindWheel(); | ||
unbindArrowKeys(); | ||
scope.compositeIndex = getCompositeIndex( | ||
getCurrentScrollTop() | ||
); | ||
} | ||
if (current !== false) { | ||
if (previous === false) { | ||
updateCompositeIndexFromScrollTop(); | ||
} | ||
}); | ||
watchCompositeIndex(); | ||
watchSnapIndex(); | ||
watchSnapHeight(); | ||
bindScroll(); | ||
bindWheel(); | ||
bindArrowKeys(); | ||
} else { | ||
unwatchCompositeIndex(); | ||
unwatchSnapIndex(); | ||
unwatchSnapHeight(); | ||
unbindScroll(); | ||
unbindWheel(); | ||
unbindArrowKeys(); | ||
} | ||
}); | ||
scope.$on('$destroy', function () { | ||
if (scope.enabled !== false) { | ||
unbindScroll(); | ||
unbindWheel(); | ||
unbindArrowKeys(); | ||
} | ||
}); | ||
} | ||
init(); | ||
scope.$on('$destroy', function () { | ||
if (scope.enabled !== false) { | ||
unbindScroll(); | ||
unbindWheel(); | ||
unbindArrowKeys(); | ||
} | ||
}); | ||
} | ||
}; | ||
} | ||
]; | ||
angular.module('snapscroll') | ||
.directive('snapscroll', snapscrollAsAnAttribute); | ||
})(); | ||
init(); | ||
} | ||
}; | ||
} | ||
]); |
@@ -1,2 +0,2 @@ | ||
/* angular-snapscroll v1.2.0, (c) 2014-2016 Joel Mukuthu, MIT License, built: 12-12-2016 21:13:13 GMT+0100 */ | ||
!function(){angular.module("snapscroll",["wheelie","scrollie"]).value("defaultSnapscrollScrollEasing",void 0).value("defaultSnapscrollScrollDelay",250).value("defaultSnapscrollSnapDuration",800).value("defaultSnapscrollResizeDelay",400).value("defaultSnapscrollBindScrollTimeout",400).value("defaultSnapscrollPreventDoubleSnapDelay",1e3)}(),function(){angular.module("snapscroll").directive("fitWindowHeight",["$window","$timeout","defaultSnapscrollResizeDelay",function(a,b,c){return{restrict:"A",require:"snapscroll",link:function(d,e,f,g){function h(){l===!1?g.setSnapHeight(a.innerHeight):(b.cancel(k),k=b(function(){g.setSnapHeight(a.innerHeight)},l))}function i(){"false"===l?l=!1:(l=parseInt(l,10),isNaN(l)&&(l=c)),g.setSnapHeight(a.innerHeight),j=angular.element(a),j.on("resize",h),d.$on("$destroy",function(){j.off("resize")})}var j,k,l=f.resizeDelay;i()}}}])}(),function(){function a(a){return angular.isNumber(a)&&!isNaN(a)}var b=angular.isDefined,c=angular.isUndefined,d=angular.isFunction,e=angular.forEach,f={enabled:"=snapscroll",snapIndex:"=?",snapHeight:"=?",beforeSnap:"&",afterSnap:"&",snapAnimation:"=?"},g=["$scope",function(a){this.setSnapHeight=function(b){a.snapHeight=b}}],h=["$timeout","$document","wheelie","scrollie","defaultSnapscrollScrollEasing","defaultSnapscrollScrollDelay","defaultSnapscrollSnapDuration","defaultSnapscrollBindScrollTimeout","defaultSnapscrollPreventDoubleSnapDelay",function(h,i,j,k,l,m,n,o,p){return{restrict:"A",scope:f,controller:g,link:function(f,g,q){function r(){return g.children()}function s(a){return a.offsetHeight}function t(a){return s(r()[a])}function u(){return s(g[0])}function v(){return g[0].scrollHeight}function w(a){var b=v()-u();return a>b?b:a}function x(a,c){for(var d=a[0],e=a[1],f=0,g=r(),h=0;h<d;h++)f+=s(g[h]);if(0===e)return w(f);var i,j=u(),k=s(g[d]);if(b(c)&&e<c[1]){i=k;for(var l=e;l>=0;l--)i-=j}else{i=0;for(var m=0;m<e;m++)i+=j;var n=i+j-k;n>0&&(i-=n)}return w(f+i)}function y(d,e){var g=d[0],h=c(e)||g!==e[0];if(h){var i=f.beforeSnap({snapIndex:g,$event:f.sourceEvent});if(i===!1)return void(b(e)&&(f.ignoreCompositeIndexChange=!0,f.compositeIndex=e));if(a(i))return void(f.snapIndex=i)}return A(x(d,e)).then(function(){h&&f.afterSnap({snapIndex:g,$event:f.sourceEvent}),f.sourceEvent=void 0})}function z(){return g[0].scrollTop}function A(a){var b;b=f.snapAnimation?c(f.snapEasing)?[g,a,f.snapDuration]:[g,a,f.snapDuration,f.snapEasing]:[g,a];var d=z();return a>d?f.snapDirection="down":a<d?f.snapDirection="up":f.snapDirection="same",Z(),k.to.apply(k,b).then(function(){f.snapDirection=void 0,$(),B()})}function B(){function a(){f.preventUp=!1,f.preventDown=!1}(f.preventUp||f.preventDown)&&(f.preventDoubleSnapDelay===!1?a():h(a,f.preventDoubleSnapDelay))}function C(){var a=u();if(!a)return!1;var b=r();if(!b.length)return!1;var c=0;return e(b,function(a){c+=s(a)}),!(c<a)}function D(a){return a>=0&&a<=r().length-1}function E(b,d){if(C())return c(b)?void(f.snapIndex=0):a(b)?b%1!==0?void(f.snapIndex=Math.round(b)):f.ignoreSnapIndexChange===!0?void(f.ignoreSnapIndexChange=void 0):D(b)?void(f.compositeIndex=[b,0]):(D(d)||(d=0),f.ignoreSnapIndexChange=!0,void(f.snapIndex=d)):(a(d)||(d=0),void(f.snapIndex=d))}function F(){f.unwatchSnapIndex=f.$watch("snapIndex",E)}function G(){d(f.unwatchSnapIndex)&&(f.unwatchSnapIndex(),f.unwatchSnapIndex=void 0)}function H(a,b){if(!c(a)){var d=a[0];return f.snapIndex!==d&&(f.ignoreSnapIndexChange=!0,f.snapIndex=d),f.ignoreCompositeIndexChange===!0?void(f.ignoreCompositeIndexChange=void 0):void y(a,b)}}function I(){f.unwatchCompositeIndex=f.$watchCollection("compositeIndex",H)}function J(){d(f.unwatchCompositeIndex)&&(f.unwatchCompositeIndex(),f.unwatchCompositeIndex=void 0)}function K(a){var b=u(),c=t(a);if(c<=b)return 0;var d=parseInt(c/b,10);return c%b===0&&(d-=1),d}function L(a){var b=a[0],c=a[1];return c<0?D(b-1):!(c>K(b))||D(b+1)}function M(a){var b=a[0],c=a[1];return c<0?[b-1,K(b-1)]:c>K(b)?[b+1,0]:a}function N(a,b){if(C()){if("up"===a&&(f.preventDown=!1),"down"===a&&(f.preventUp=!1),f.snapDirection===a)return!0;if(f.preventUp||f.preventDown)return!0;var c,d=f.compositeIndex[0],e=f.compositeIndex[1];"up"===a&&(c=e-1),"down"===a&&(c=e+1);var g=[d,c];if(L(g))return"wheel"===b.type&&("up"===a&&(f.preventUp=!0),"down"===a&&(f.preventDown=!0)),f.$apply(function(){f.sourceEvent=b,f.compositeIndex=M(g)}),!0}}function O(a){return N("up",a)}function P(a){return N("down",a)}function Q(){f.disableWheelBinding||f.wheelBound||(j.bind(g,{up:function(a){a.preventDefault(),O(a)&&a.stopPropagation()},down:function(a){a.preventDefault(),P(a)&&a.stopPropagation()}},f.ignoreWheelClass),f.wheelBound=!0)}function R(){f.wheelBound&&(j.unbind(g),f.wheelBound=!1)}function S(a,b){a.css("height",b+"px")}function T(d,h){if(!c(d)){if(!a(d))return void(a(h)&&(f.snapHeight=h));S(g,d),e(r(),function(a){S(angular.element(a),d)}),b(f.snapIndex)&&(c(f.compositeIndex)&&(f.compositeIndex=[f.snapIndex,0]),y(f.compositeIndex))}}function U(){f.unwatchSnapHeight=f.$watch("snapHeight",T)}function V(){d(f.unwatchSnapHeight)&&(f.unwatchSnapHeight(),f.unwatchSnapHeight=void 0)}function W(a){var b=0,c=0;if(a>0){b=-1;for(var d,e=r();a>0;)d=s(e[++b]),a-=d;var f=u();if(d>f){for(a+=d-f,a>=f&&c++;a>0;)c++,a-=f;f/2>=-a&&(c+=1)}else d/2>=-a&&(b+=1)}return M([b,c])}function X(){function a(){var a=W(z());f.compositeIndex[0]===a[0]&&f.compositeIndex[1]===a[1]?y(f.compositeIndex):f.$apply(function(){f.compositeIndex=a})}k.stop(g),f.scrollDelay===!1?a():(h.cancel(f.scrollPromise),f.scrollPromise=h(function(){a(),f.scrollPromise=void 0},f.scrollDelay))}function Y(){if(!f.preventSnappingAfterManualScroll&&!f.scrollBound){if(b(f.snapDirection))return void $();g.on("scroll",X),f.scrollBound=!0}}function Z(){f.scrollBound&&(g.off("scroll",X),f.scrollBound=!1)}function $(){f.preventSnappingAfterManualScroll||(f.bindScrollPromise&&h.cancel(f.bindScrollPromise),f.bindScrollPromise=h(function(){Y(),f.bindScrollPromise=void 0},o))}function _(a){a.originalEvent&&(a=a.originalEvent);var b,c=a.keyCode;38===c&&(b=O),40===c&&(b=P),b&&(a.preventDefault(),b(a))}function aa(){f.enableArrowKeys&&!f.arrowKeysBound&&(i.on("keydown",_),f.arrowKeysBound=!0)}function ba(){f.arrowKeysBound&&(i.off("keydown",_),f.arrowKeysBound=!1)}function ca(){var a=q.scrollDelay;"false"===a?f.scrollDelay=!1:(a=parseInt(a,10),isNaN(a)&&(a=m),f.scrollDelay=a);var e=q.preventDoubleSnapDelay;"false"===e?f.preventDoubleSnapDelay=!1:(e=parseInt(e,10),isNaN(e)&&(e=p),f.preventDoubleSnapDelay=e);var h=q.snapEasing;b(h)?f.snapEasing=f.$parent.$eval(h):d(l)&&(f.snapEasing=l);var i=parseInt(q.snapDuration,10);isNaN(i)&&(i=n),f.snapDuration=i,c(f.snapAnimation)&&(f.snapAnimation=!0),f.disableWheelBinding=b(q.disableWheelBinding),f.enableArrowKeys=b(q.enableArrowKeys),f.preventSnappingAfterManualScroll=b(q.preventSnappingAfterManualScroll),f.ignoreWheelClass=q.ignoreWheelClass,"scroll"!==g.css("overflowY")&&g.css("overflowY","auto"),f.$watch("enabled",function(a,b){function c(){f.preventSnappingAfterManualScroll||(f.compositeIndex=W(z()))}a!==!1?(b===!1&&c(),I(),F(),U(),Y(),Q(),aa()):(J(),G(),V(),Z(),R(),ba())}),f.$on("$destroy",function(){f.enabled!==!1&&(Z(),R(),ba())})}ca()}}}];angular.module("snapscroll").directive("snapscroll",h)}(); | ||
/* angular-snapscroll v1.3.0, (c) 2014-2017 Joel Mukuthu, MIT License, built: 06-03-2017 12:22:02 GMT+0100 */ | ||
"object"==typeof exports&&(module.exports="snapscroll"),angular.module("snapscroll",["wheelie","scrollie"]).value("defaultSnapscrollScrollEasing",void 0).value("defaultSnapscrollScrollDelay",250).value("defaultSnapscrollSnapDuration",800).value("defaultSnapscrollResizeDelay",400).value("defaultSnapscrollBindScrollTimeout",400).value("defaultSnapscrollPreventDoubleSnapDelay",1e3),angular.module("snapscroll").directive("fitWindowHeight",["$window","$timeout","defaultSnapscrollResizeDelay",function(a,b,c){return{restrict:"A",require:"snapscroll",link:function(d,e,f,g){function h(){l===!1?g.setSnapHeight(a.innerHeight):(b.cancel(k),k=b(function(){g.setSnapHeight(a.innerHeight)},l))}function i(){"false"===l?l=!1:(l=parseInt(l,10),isNaN(l)&&(l=c)),g.setSnapHeight(a.innerHeight),j=angular.element(a),j.on("resize",h),d.$on("$destroy",function(){j.off("resize")})}var j,k,l=f.resizeDelay;i()}}}]),angular.module("snapscroll").directive("snapscroll",["$timeout","$document","wheelie","scrollie","defaultSnapscrollScrollEasing","defaultSnapscrollScrollDelay","defaultSnapscrollSnapDuration","defaultSnapscrollBindScrollTimeout","defaultSnapscrollPreventDoubleSnapDelay",function(a,b,c,d,e,f,g,h,i){function j(a){return angular.isNumber(a)&&!isNaN(a)}var k=angular.isDefined,l=angular.isUndefined,m=angular.isFunction,n=angular.forEach;return{restrict:"A",scope:{enabled:"=snapscroll",snapIndex:"=?",snapHeight:"=?",beforeSnap:"&",afterSnap:"&",snapAnimation:"=?"},controller:["$scope",function(a){this.setSnapHeight=function(b){a.snapHeight=b}}],link:function(o,p,q){function r(){return p.children()}function s(a){return a.offsetHeight}function t(a){return s(r()[a])}function u(){return s(p[0])}function v(){return p[0].scrollHeight}function w(a){var b=v()-u();return a>b?b:a}function x(a,b){for(var c=a[0],d=a[1],e=0,f=r(),g=0;g<c;g++)e+=s(f[g]);if(0===d)return w(e);var h,i=u(),j=s(f[c]);if(k(b)&&d<b[1]){h=j;for(var l=d;l>=0;l--)h-=i}else{h=0;for(var m=0;m<d;m++)h+=i;var n=h+i-j;n>0&&(h-=n)}return w(e+h)}function y(a,b){var c=a[0],d=l(b)||c!==b[0];if(d){var e=o.beforeSnap({snapIndex:c,$event:o.sourceEvent});if(e===!1)return void(k(b)&&(o.ignoreCompositeIndexChange=!0,o.compositeIndex=b));if(j(e))return void(o.snapIndex=e)}return A(x(a,b)).then(function(){d&&o.afterSnap({snapIndex:c,$event:o.sourceEvent}),o.sourceEvent=void 0})}function z(){return p[0].scrollTop}function A(a){var b;b=o.snapAnimation?l(o.snapEasing)?[p,a,o.snapDuration]:[p,a,o.snapDuration,o.snapEasing]:[p,a];var c=z();return o.snapDirection=a>c?"down":a<c?"up":"same",Z(),d.to.apply(d,b).then(function(){o.snapDirection=void 0,$(),B()})}function B(){function b(){o.preventUp=!1,o.preventDown=!1}(o.preventUp||o.preventDown)&&(o.preventDoubleSnapDelay===!1?b():a(b,o.preventDoubleSnapDelay))}function C(){var a=u();if(!a)return!1;var b=r();if(!b.length)return!1;var c=0;return n(b,function(a){c+=s(a)}),!(c<a)}function D(a){return a>=0&&a<=r().length-1}function E(a,b){if(C())return l(a)?void(o.snapIndex=0):j(a)?a%1!=0?void(o.snapIndex=Math.round(a)):o.ignoreSnapIndexChange===!0?void(o.ignoreSnapIndexChange=void 0):D(a)?void(o.compositeIndex=[a,0]):(D(b)||(b=0),o.ignoreSnapIndexChange=!0,void(o.snapIndex=b)):(j(b)||(b=0),void(o.snapIndex=b))}function F(){o.unwatchSnapIndex=o.$watch("snapIndex",E)}function G(){m(o.unwatchSnapIndex)&&(o.unwatchSnapIndex(),o.unwatchSnapIndex=void 0)}function H(a,b){if(!l(a)){var c=a[0];if(o.snapIndex!==c&&(o.ignoreSnapIndexChange=!0,o.snapIndex=c),o.ignoreCompositeIndexChange===!0)return void(o.ignoreCompositeIndexChange=void 0);y(a,b)}}function I(){o.unwatchCompositeIndex=o.$watchCollection("compositeIndex",H)}function J(){m(o.unwatchCompositeIndex)&&(o.unwatchCompositeIndex(),o.unwatchCompositeIndex=void 0)}function K(a){var b=u(),c=t(a);if(c<=b)return 0;var d=parseInt(c/b,10);return c%b==0&&(d-=1),d}function L(a){var b=a[0],c=a[1];return c<0?D(b-1):!(c>K(b))||D(b+1)}function M(a){var b=a[0],c=a[1];return c<0?[b-1,K(b-1)]:c>K(b)?[b+1,0]:a}function N(a,b){if(C()){if("up"===a&&(o.preventDown=!1),"down"===a&&(o.preventUp=!1),o.snapDirection===a)return!0;if(o.preventUp||o.preventDown)return!0;var c,d=o.compositeIndex[0],e=o.compositeIndex[1];"up"===a&&(c=e-1),"down"===a&&(c=e+1);var f=[d,c];if(L(f))return"wheel"===b.type&&("up"===a&&(o.preventUp=!0),"down"===a&&(o.preventDown=!0)),o.$apply(function(){o.sourceEvent=b,o.compositeIndex=M(f)}),!0}}function O(a){return N("up",a)}function P(a){return N("down",a)}function Q(){o.disableWheelBinding||o.wheelBound||(c.bind(p,{up:function(a){a.preventDefault(),O(a)&&a.stopPropagation()},down:function(a){a.preventDefault(),P(a)&&a.stopPropagation()}},o.ignoreWheelClass),o.wheelBound=!0)}function R(){o.wheelBound&&(c.unbind(p),o.wheelBound=!1)}function S(a,b){a.css("height",b+"px")}function T(a,b){if(!l(a)){if(!j(a))return void(j(b)&&(o.snapHeight=b));S(p,a),n(r(),function(b){S(angular.element(b),a)}),k(o.snapIndex)&&(l(o.compositeIndex)&&(o.compositeIndex=[o.snapIndex,0]),y(o.compositeIndex))}}function U(){o.unwatchSnapHeight=o.$watch("snapHeight",T)}function V(){m(o.unwatchSnapHeight)&&(o.unwatchSnapHeight(),o.unwatchSnapHeight=void 0)}function W(a){var b=0,c=0;if(a>0){b=-1;for(var d,e=r();a>0;)d=s(e[++b]),a-=d;var f=u();if(d>f){for(a+=d-f,a>=f&&c++;a>0;)c++,a-=f;f/2>=-a&&(c+=1)}else d/2>=-a&&(b+=1)}return M([b,c])}function X(){function b(){var a=W(z());o.compositeIndex[0]===a[0]&&o.compositeIndex[1]===a[1]?y(o.compositeIndex):o.$apply(function(){o.compositeIndex=a})}d.stop(p),o.scrollDelay===!1?b():(a.cancel(o.scrollPromise),o.scrollPromise=a(function(){b(),o.scrollPromise=void 0},o.scrollDelay))}function Y(){if(!o.preventSnappingAfterManualScroll&&!o.scrollBound){if(k(o.snapDirection))return void $();p.on("scroll",X),o.scrollBound=!0}}function Z(){o.scrollBound&&(p.off("scroll",X),o.scrollBound=!1)}function $(){o.preventSnappingAfterManualScroll||(o.bindScrollPromise&&a.cancel(o.bindScrollPromise),o.bindScrollPromise=a(function(){Y(),o.bindScrollPromise=void 0},h))}function _(a){a.originalEvent&&(a=a.originalEvent);var b,c=a.keyCode;38===c&&(b=O),40===c&&(b=P),b&&(a.preventDefault(),b(a))}function aa(){o.enableArrowKeys&&!o.arrowKeysBound&&(b.on("keydown",_),o.arrowKeysBound=!0)}function ba(){o.arrowKeysBound&&(b.off("keydown",_),o.arrowKeysBound=!1)}function ca(){var a=q.scrollDelay;"false"===a?o.scrollDelay=!1:(a=parseInt(a,10),isNaN(a)&&(a=f),o.scrollDelay=a);var b=q.preventDoubleSnapDelay;"false"===b?o.preventDoubleSnapDelay=!1:(b=parseInt(b,10),isNaN(b)&&(b=i),o.preventDoubleSnapDelay=b);var c=q.snapEasing;k(c)?o.snapEasing=o.$parent.$eval(c):m(e)&&(o.snapEasing=e);var d=parseInt(q.snapDuration,10);isNaN(d)&&(d=g),o.snapDuration=d,l(o.snapAnimation)&&(o.snapAnimation=!0),o.disableWheelBinding=k(q.disableWheelBinding),o.enableArrowKeys=k(q.enableArrowKeys),o.preventSnappingAfterManualScroll=k(q.preventSnappingAfterManualScroll),o.ignoreWheelClass=q.ignoreWheelClass,"scroll"!==p.css("overflowY")&&p.css("overflowY","auto"),o.$watch("enabled",function(a,b){function c(){o.preventSnappingAfterManualScroll||(o.compositeIndex=W(z()))}a!==!1?(b===!1&&c(),I(),F(),U(),Y(),Q(),aa()):(J(),G(),V(),Z(),R(),ba())}),o.$on("$destroy",function(){o.enabled!==!1&&(Z(),R(),ba())})}ca()}}}]); |
The MIT License | ||
Copyright (c) 2014 - 2016, Joel Mukuthu. | ||
Copyright (c) 2014 - 2017, Joel Mukuthu. | ||
@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
{ | ||
"name": "angular-snapscroll", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Vertical scroll-and-snap functionality in angular", | ||
@@ -39,4 +39,4 @@ "main": "dist/angular-snapscroll.js", | ||
"angular": "^1.2.24", | ||
"angular-scrollie": "^1.0.0", | ||
"angular-wheelie": "^2.1.0" | ||
"angular-scrollie": "^1.1.1", | ||
"angular-wheelie": "^3.0.1" | ||
}, | ||
@@ -43,0 +43,0 @@ "repository": { |
@@ -1,57 +0,54 @@ | ||
(function () { | ||
angular.module('snapscroll') | ||
.directive('fitWindowHeight', [ | ||
'$window', | ||
'$timeout', | ||
'defaultSnapscrollResizeDelay', | ||
function ( | ||
$window, | ||
$timeout, | ||
defaultSnapscrollResizeDelay | ||
) { | ||
return { | ||
restrict: 'A', | ||
require: 'snapscroll', | ||
link: function (scope, element, attributes, snapscroll) { | ||
var windowElement, | ||
resizePromise, | ||
resizeDelay = attributes.resizeDelay; | ||
angular.module('snapscroll').directive('fitWindowHeight', [ | ||
'$window', | ||
'$timeout', | ||
'defaultSnapscrollResizeDelay', | ||
function ( | ||
$window, | ||
$timeout, | ||
defaultSnapscrollResizeDelay | ||
) { | ||
return { | ||
restrict: 'A', | ||
require: 'snapscroll', | ||
link: function (scope, element, attributes, snapscroll) { | ||
var windowElement, | ||
resizePromise, | ||
resizeDelay = attributes.resizeDelay; | ||
function onWindowResize() { | ||
if (resizeDelay === false) { | ||
function onWindowResize() { | ||
if (resizeDelay === false) { | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
} else { | ||
$timeout.cancel(resizePromise); | ||
resizePromise = $timeout(function () { | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
} else { | ||
$timeout.cancel(resizePromise); | ||
resizePromise = $timeout(function () { | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
}, resizeDelay); | ||
} | ||
}, resizeDelay); | ||
} | ||
} | ||
function init() { | ||
if (resizeDelay === 'false') { | ||
resizeDelay = false; | ||
} else { | ||
resizeDelay = parseInt(resizeDelay, 10); | ||
if (isNaN(resizeDelay)) { | ||
resizeDelay = defaultSnapscrollResizeDelay; | ||
} | ||
function init() { | ||
if (resizeDelay === 'false') { | ||
resizeDelay = false; | ||
} else { | ||
resizeDelay = parseInt(resizeDelay, 10); | ||
if (isNaN(resizeDelay)) { | ||
resizeDelay = defaultSnapscrollResizeDelay; | ||
} | ||
} | ||
// set initial snapHeight | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
// set initial snapHeight | ||
snapscroll.setSnapHeight($window.innerHeight); | ||
// update snapHeight on window resize | ||
windowElement = angular.element($window); | ||
windowElement.on('resize', onWindowResize); | ||
scope.$on('$destroy', function () { | ||
windowElement.off('resize'); | ||
}); | ||
} | ||
init(); | ||
// update snapHeight on window resize | ||
windowElement = angular.element($window); | ||
windowElement.on('resize', onWindowResize); | ||
scope.$on('$destroy', function () { | ||
windowElement.off('resize'); | ||
}); | ||
} | ||
}; | ||
}]); | ||
})(); | ||
init(); | ||
} | ||
}; | ||
} | ||
]); |
@@ -1,733 +0,724 @@ | ||
(function () { | ||
function isNumber(value) { | ||
return angular.isNumber(value) && !isNaN(value); | ||
} | ||
angular.module('snapscroll').directive('snapscroll', [ | ||
'$timeout', | ||
'$document', | ||
'wheelie', | ||
'scrollie', | ||
'defaultSnapscrollScrollEasing', | ||
'defaultSnapscrollScrollDelay', | ||
'defaultSnapscrollSnapDuration', | ||
'defaultSnapscrollBindScrollTimeout', | ||
'defaultSnapscrollPreventDoubleSnapDelay', | ||
function ( | ||
$timeout, | ||
$document, | ||
wheelie, | ||
scrollie, | ||
defaultSnapscrollScrollEasing, | ||
defaultSnapscrollScrollDelay, | ||
defaultSnapscrollSnapDuration, | ||
defaultSnapscrollBindScrollTimeout, | ||
defaultSnapscrollPreventDoubleSnapDelay | ||
) { | ||
function isNumber(value) { | ||
return angular.isNumber(value) && !isNaN(value); | ||
} | ||
var isDefined = angular.isDefined; | ||
var isUndefined = angular.isUndefined; | ||
var isFunction = angular.isFunction; | ||
var forEach = angular.forEach; | ||
var isDefined = angular.isDefined; | ||
var isUndefined = angular.isUndefined; | ||
var isFunction = angular.isFunction; | ||
var forEach = angular.forEach; | ||
var scopeObject = { | ||
enabled: '=snapscroll', | ||
snapIndex: '=?', | ||
snapHeight: '=?', | ||
beforeSnap: '&', | ||
afterSnap: '&', | ||
snapAnimation: '=?' | ||
}; | ||
return { | ||
restrict: 'A', | ||
scope: { | ||
enabled: '=snapscroll', | ||
snapIndex: '=?', | ||
snapHeight: '=?', | ||
beforeSnap: '&', | ||
afterSnap: '&', | ||
snapAnimation: '=?' | ||
}, | ||
controller: ['$scope', function ($scope) { | ||
this.setSnapHeight = function (height) { | ||
$scope.snapHeight = height; | ||
}; | ||
}], | ||
link: function (scope, element, attributes) { | ||
function getChildren() { | ||
return element.children(); | ||
} | ||
var controller = ['$scope', function ($scope) { | ||
this.setSnapHeight = function (height) { | ||
$scope.snapHeight = height; | ||
}; | ||
}]; | ||
function getHeight(domElement) { | ||
return domElement.offsetHeight; | ||
} | ||
var snapscrollAsAnAttribute = [ | ||
'$timeout', | ||
'$document', | ||
'wheelie', | ||
'scrollie', | ||
'defaultSnapscrollScrollEasing', | ||
'defaultSnapscrollScrollDelay', | ||
'defaultSnapscrollSnapDuration', | ||
'defaultSnapscrollBindScrollTimeout', | ||
'defaultSnapscrollPreventDoubleSnapDelay', | ||
function ( | ||
$timeout, | ||
$document, | ||
wheelie, | ||
scrollie, | ||
defaultSnapscrollScrollEasing, | ||
defaultSnapscrollScrollDelay, | ||
defaultSnapscrollSnapDuration, | ||
defaultSnapscrollBindScrollTimeout, | ||
defaultSnapscrollPreventDoubleSnapDelay | ||
) { | ||
return { | ||
restrict: 'A', | ||
scope: scopeObject, | ||
controller: controller, | ||
link: function (scope, element, attributes) { | ||
function getChildren() { | ||
return element.children(); | ||
} | ||
function getChildHeight(snapIndex) { | ||
return getHeight(getChildren()[snapIndex]); | ||
} | ||
function getHeight(domElement) { | ||
return domElement.offsetHeight; | ||
} | ||
function getSnapHeight() { | ||
return getHeight(element[0]); | ||
} | ||
function getChildHeight(snapIndex) { | ||
return getHeight(getChildren()[snapIndex]); | ||
function getScrollHeight() { | ||
return element[0].scrollHeight; | ||
} | ||
function rectifyScrollTop(scrollTop) { | ||
var maxScrollTop = getScrollHeight() - getSnapHeight(); | ||
if (scrollTop > maxScrollTop) { | ||
return maxScrollTop; | ||
} | ||
return scrollTop; | ||
} | ||
function getSnapHeight() { | ||
return getHeight(element[0]); | ||
function getScrollTop(compositeIndex, previousCompositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
var scrollTop = 0; | ||
var children = getChildren(); | ||
for (var i = 0; i < snapIndex; i++) { | ||
scrollTop += getHeight(children[i]); | ||
} | ||
function getScrollHeight() { | ||
return element[0].scrollHeight; | ||
if (innerSnapIndex === 0) { | ||
return rectifyScrollTop(scrollTop); | ||
} | ||
function rectifyScrollTop(scrollTop) { | ||
var maxScrollTop = getScrollHeight() - getSnapHeight(); | ||
if (scrollTop > maxScrollTop) { | ||
return maxScrollTop; | ||
var snapHeight = getSnapHeight(); | ||
var childHeight = getHeight(children[snapIndex]); | ||
var innerScrollTop; | ||
if (isDefined(previousCompositeIndex) && | ||
innerSnapIndex < previousCompositeIndex[1]) { | ||
innerScrollTop = childHeight; | ||
for (var j = innerSnapIndex; j >= 0; j--) { | ||
innerScrollTop -= snapHeight; | ||
} | ||
return scrollTop; | ||
} else { | ||
innerScrollTop = 0; | ||
for (var k = 0; k < innerSnapIndex; k++) { | ||
innerScrollTop += snapHeight; | ||
} | ||
var overflow = innerScrollTop + snapHeight - childHeight; | ||
if (overflow > 0) { | ||
innerScrollTop -= overflow; | ||
} | ||
} | ||
function getScrollTop(compositeIndex, previousCompositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
return rectifyScrollTop(scrollTop + innerScrollTop); | ||
} | ||
var scrollTop = 0; | ||
var children = getChildren(); | ||
for (var i = 0; i < snapIndex; i++) { | ||
scrollTop += getHeight(children[i]); | ||
function snapTo(compositeIndex, previousCompositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var isSnapIndexChanged = isUndefined(previousCompositeIndex) || | ||
snapIndex !== previousCompositeIndex[0]; | ||
if (isSnapIndexChanged) { | ||
var returnValue = scope.beforeSnap({ | ||
snapIndex: snapIndex, | ||
$event: scope.sourceEvent | ||
}); | ||
if (returnValue === false) { | ||
if (isDefined(previousCompositeIndex)) { | ||
scope.ignoreCompositeIndexChange = true; | ||
scope.compositeIndex = previousCompositeIndex; | ||
} | ||
return; | ||
} | ||
if (innerSnapIndex === 0) { | ||
return rectifyScrollTop(scrollTop); | ||
if (isNumber(returnValue)) { | ||
scope.snapIndex = returnValue; | ||
return; | ||
} | ||
var snapHeight = getSnapHeight(); | ||
var childHeight = getHeight(children[snapIndex]); | ||
var innerScrollTop; | ||
if (isDefined(previousCompositeIndex) && | ||
innerSnapIndex < previousCompositeIndex[1]) { | ||
innerScrollTop = childHeight; | ||
for (var j = innerSnapIndex; j >= 0; j--) { | ||
innerScrollTop -= snapHeight; | ||
} | ||
} else { | ||
innerScrollTop = 0; | ||
for (var k = 0; k < innerSnapIndex; k++) { | ||
innerScrollTop += snapHeight; | ||
} | ||
var overflow = innerScrollTop + snapHeight - childHeight; | ||
if (overflow > 0) { | ||
innerScrollTop -= overflow; | ||
} | ||
} | ||
return rectifyScrollTop(scrollTop + innerScrollTop); | ||
} | ||
function snapTo(compositeIndex, previousCompositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var isSnapIndexChanged = isUndefined(previousCompositeIndex) || | ||
snapIndex !== previousCompositeIndex[0]; | ||
return scrollTo(getScrollTop( | ||
compositeIndex, | ||
previousCompositeIndex | ||
)).then(function () { | ||
if (isSnapIndexChanged) { | ||
var returnValue = scope.beforeSnap({ | ||
scope.afterSnap({ | ||
snapIndex: snapIndex, | ||
$event: scope.sourceEvent | ||
}); | ||
if (returnValue === false) { | ||
if (isDefined(previousCompositeIndex)) { | ||
scope.ignoreCompositeIndexChange = true; | ||
scope.compositeIndex = previousCompositeIndex; | ||
} | ||
return; | ||
} | ||
if (isNumber(returnValue)) { | ||
scope.snapIndex = returnValue; | ||
return; | ||
} | ||
} | ||
scope.sourceEvent = undefined; | ||
}); | ||
} | ||
return scrollTo(getScrollTop( | ||
compositeIndex, | ||
previousCompositeIndex | ||
)).then(function () { | ||
if (isSnapIndexChanged) { | ||
scope.afterSnap({ | ||
snapIndex: snapIndex, | ||
$event: scope.sourceEvent | ||
}); | ||
} | ||
scope.sourceEvent = undefined; | ||
}); | ||
function getCurrentScrollTop() { | ||
return element[0].scrollTop; | ||
} | ||
function scrollTo(scrollTop) { | ||
var args; | ||
if (!scope.snapAnimation) { | ||
args = [ | ||
element, | ||
scrollTop | ||
]; | ||
} else if (isUndefined(scope.snapEasing)) { | ||
// TODO: add tests for this. Will require refactoring | ||
// the default values into an object, which is a good | ||
// change anyway | ||
args = [ | ||
element, | ||
scrollTop, | ||
scope.snapDuration | ||
]; | ||
} else { | ||
args = [ | ||
element, | ||
scrollTop, | ||
scope.snapDuration, | ||
scope.snapEasing | ||
]; | ||
} | ||
function getCurrentScrollTop() { | ||
return element[0].scrollTop; | ||
var currentScrollTop = getCurrentScrollTop(); | ||
if (scrollTop > currentScrollTop) { | ||
scope.snapDirection = 'down'; | ||
} else if (scrollTop < currentScrollTop) { | ||
scope.snapDirection = 'up'; | ||
} else { | ||
scope.snapDirection = 'same'; | ||
} | ||
function scrollTo(scrollTop) { | ||
var args; | ||
if (!scope.snapAnimation) { | ||
args = [ | ||
element, | ||
scrollTop | ||
]; | ||
} else if (isUndefined(scope.snapEasing)) { | ||
// TODO: add tests for this. Will require refactoring | ||
// the default values into an object, which is a good | ||
// change anyway | ||
args = [ | ||
element, | ||
scrollTop, | ||
scope.snapDuration | ||
]; | ||
} else { | ||
args = [ | ||
element, | ||
scrollTop, | ||
scope.snapDuration, | ||
scope.snapEasing | ||
]; | ||
} | ||
unbindScroll(); | ||
return scrollie.to.apply(scrollie, args).then(function () { | ||
scope.snapDirection = undefined; | ||
bindScrollAfterDelay(); | ||
allowNextSnapAfterDelay(); | ||
}); | ||
} | ||
var currentScrollTop = getCurrentScrollTop(); | ||
if (scrollTop > currentScrollTop) { | ||
scope.snapDirection = 'down'; | ||
} else if (scrollTop < currentScrollTop) { | ||
scope.snapDirection = 'up'; | ||
function allowNextSnapAfterDelay() { | ||
function allowNextSnap() { | ||
scope.preventUp = false; | ||
scope.preventDown = false; | ||
} | ||
if (scope.preventUp || scope.preventDown) { | ||
if (scope.preventDoubleSnapDelay === false) { | ||
allowNextSnap(); | ||
} else { | ||
scope.snapDirection = 'same'; | ||
$timeout( | ||
allowNextSnap, | ||
scope.preventDoubleSnapDelay | ||
); | ||
} | ||
} | ||
} | ||
unbindScroll(); | ||
return scrollie.to.apply(scrollie, args).then(function () { | ||
scope.snapDirection = undefined; | ||
bindScrollAfterDelay(); | ||
allowNextSnapAfterDelay(); | ||
}); | ||
function isScrollable() { | ||
var snapHeight = getSnapHeight(); | ||
if (!snapHeight) { | ||
return false; | ||
} | ||
var children = getChildren(); | ||
if (!children.length) { | ||
return false; | ||
} | ||
var totalHeight = 0; | ||
forEach(children, function (child) { | ||
totalHeight += getHeight(child); | ||
}); | ||
if (totalHeight < snapHeight) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function allowNextSnapAfterDelay() { | ||
function allowNextSnap() { | ||
scope.preventUp = false; | ||
scope.preventDown = false; | ||
function isSnapIndexValid(snapIndex) { | ||
return snapIndex >= 0 && | ||
snapIndex <= getChildren().length - 1; | ||
} | ||
function snapIndexChanged(current, previous) { | ||
if (!isScrollable()) { | ||
return; | ||
} | ||
if (isUndefined(current)) { | ||
scope.snapIndex = 0; | ||
return; | ||
} | ||
if (!isNumber(current)) { | ||
if (!isNumber(previous)) { | ||
previous = 0; | ||
} | ||
if (scope.preventUp || scope.preventDown) { | ||
if (scope.preventDoubleSnapDelay === false) { | ||
allowNextSnap(); | ||
} else { | ||
$timeout( | ||
allowNextSnap, | ||
scope.preventDoubleSnapDelay | ||
); | ||
} | ||
} | ||
scope.snapIndex = previous; | ||
return; | ||
} | ||
function isScrollable() { | ||
var snapHeight = getSnapHeight(); | ||
if (!snapHeight) { | ||
return false; | ||
if (current % 1 !== 0) { | ||
scope.snapIndex = Math.round(current); | ||
return; | ||
} | ||
if (scope.ignoreSnapIndexChange === true) { | ||
scope.ignoreSnapIndexChange = undefined; | ||
return; | ||
} | ||
if (!isSnapIndexValid(current)) { | ||
if (!isSnapIndexValid(previous)) { | ||
previous = 0; | ||
} | ||
var children = getChildren(); | ||
if (!children.length) { | ||
return false; | ||
} | ||
var totalHeight = 0; | ||
forEach(children, function (child) { | ||
totalHeight += getHeight(child); | ||
}); | ||
if (totalHeight < snapHeight) { | ||
return false; | ||
} | ||
return true; | ||
scope.ignoreSnapIndexChange = true; | ||
scope.snapIndex = previous; | ||
return; | ||
} | ||
scope.compositeIndex = [current, 0]; | ||
} | ||
function isSnapIndexValid(snapIndex) { | ||
return snapIndex >= 0 && | ||
snapIndex <= getChildren().length - 1; | ||
function watchSnapIndex() { | ||
scope.unwatchSnapIndex = scope.$watch( | ||
'snapIndex', | ||
snapIndexChanged | ||
); | ||
} | ||
function unwatchSnapIndex() { | ||
if (!isFunction(scope.unwatchSnapIndex)) { | ||
return; | ||
} | ||
scope.unwatchSnapIndex(); | ||
scope.unwatchSnapIndex = undefined; | ||
} | ||
function snapIndexChanged(current, previous) { | ||
if (!isScrollable()) { | ||
return; | ||
} | ||
if (isUndefined(current)) { | ||
scope.snapIndex = 0; | ||
return; | ||
} | ||
if (!isNumber(current)) { | ||
if (!isNumber(previous)) { | ||
previous = 0; | ||
} | ||
scope.snapIndex = previous; | ||
return; | ||
} | ||
if (current % 1 !== 0) { | ||
scope.snapIndex = Math.round(current); | ||
return; | ||
} | ||
if (scope.ignoreSnapIndexChange === true) { | ||
scope.ignoreSnapIndexChange = undefined; | ||
return; | ||
} | ||
if (!isSnapIndexValid(current)) { | ||
if (!isSnapIndexValid(previous)) { | ||
previous = 0; | ||
} | ||
scope.ignoreSnapIndexChange = true; | ||
scope.snapIndex = previous; | ||
return; | ||
} | ||
scope.compositeIndex = [current, 0]; | ||
function compositeIndexChanged(current, previous) { | ||
if (isUndefined(current)) { | ||
return; | ||
} | ||
var snapIndex = current[0]; | ||
if (scope.snapIndex !== snapIndex) { | ||
scope.ignoreSnapIndexChange = true; | ||
scope.snapIndex = snapIndex; | ||
} | ||
if (scope.ignoreCompositeIndexChange === true) { | ||
scope.ignoreCompositeIndexChange = undefined; | ||
return; | ||
} | ||
snapTo(current, previous); | ||
} | ||
function watchSnapIndex() { | ||
scope.unwatchSnapIndex = scope.$watch( | ||
'snapIndex', | ||
snapIndexChanged | ||
); | ||
function watchCompositeIndex() { | ||
scope.unwatchCompositeIndex = scope.$watchCollection( | ||
'compositeIndex', | ||
compositeIndexChanged | ||
); | ||
} | ||
function unwatchCompositeIndex() { | ||
if (!isFunction(scope.unwatchCompositeIndex)) { | ||
return; | ||
} | ||
scope.unwatchCompositeIndex(); | ||
scope.unwatchCompositeIndex = undefined; | ||
} | ||
function unwatchSnapIndex() { | ||
if (!isFunction(scope.unwatchSnapIndex)) { | ||
return; | ||
} | ||
scope.unwatchSnapIndex(); | ||
scope.unwatchSnapIndex = undefined; | ||
function getMaxInnerSnapIndex(snapIndex) { | ||
var snapHeight = getSnapHeight(); | ||
var childHeight = getChildHeight(snapIndex); | ||
if (childHeight <= snapHeight) { | ||
return 0; | ||
} | ||
var max = parseInt((childHeight / snapHeight), 10); | ||
if (childHeight % snapHeight === 0) { | ||
max -= 1; | ||
} | ||
return max; | ||
} | ||
function compositeIndexChanged(current, previous) { | ||
if (isUndefined(current)) { | ||
return; | ||
} | ||
var snapIndex = current[0]; | ||
if (scope.snapIndex !== snapIndex) { | ||
scope.ignoreSnapIndexChange = true; | ||
scope.snapIndex = snapIndex; | ||
} | ||
if (scope.ignoreCompositeIndexChange === true) { | ||
scope.ignoreCompositeIndexChange = undefined; | ||
return; | ||
} | ||
snapTo(current, previous); | ||
function isCompositeIndexValid(compositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
if (innerSnapIndex < 0) { | ||
return isSnapIndexValid(snapIndex - 1); | ||
} | ||
if (innerSnapIndex > getMaxInnerSnapIndex(snapIndex)) { | ||
return isSnapIndexValid(snapIndex + 1); | ||
} | ||
return true; | ||
} | ||
function watchCompositeIndex() { | ||
scope.unwatchCompositeIndex = scope.$watchCollection( | ||
'compositeIndex', | ||
compositeIndexChanged | ||
); | ||
function rectifyCompositeIndex(compositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
if (innerSnapIndex < 0) { | ||
return [ | ||
snapIndex - 1, | ||
getMaxInnerSnapIndex(snapIndex - 1) | ||
]; | ||
} | ||
if (innerSnapIndex > getMaxInnerSnapIndex(snapIndex)) { | ||
return [snapIndex + 1, 0]; | ||
} | ||
return compositeIndex; | ||
} | ||
function unwatchCompositeIndex() { | ||
if (!isFunction(scope.unwatchCompositeIndex)) { | ||
return; | ||
} | ||
scope.unwatchCompositeIndex(); | ||
scope.unwatchCompositeIndex = undefined; | ||
function snap(direction, event) { | ||
if (!isScrollable()) { | ||
return; | ||
} | ||
function getMaxInnerSnapIndex(snapIndex) { | ||
var snapHeight = getSnapHeight(); | ||
var childHeight = getChildHeight(snapIndex); | ||
if (childHeight <= snapHeight) { | ||
return 0; | ||
} | ||
var max = parseInt((childHeight / snapHeight), 10); | ||
if (childHeight % snapHeight === 0) { | ||
max -= 1; | ||
} | ||
return max; | ||
direction === 'up' && (scope.preventDown = false); | ||
direction === 'down' && (scope.preventUp = false); | ||
if (scope.snapDirection === direction) { | ||
return true; | ||
} | ||
function isCompositeIndexValid(compositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
if (innerSnapIndex < 0) { | ||
return isSnapIndexValid(snapIndex - 1); | ||
} | ||
if (innerSnapIndex > getMaxInnerSnapIndex(snapIndex)) { | ||
return isSnapIndexValid(snapIndex + 1); | ||
} | ||
if (scope.preventUp || scope.preventDown) { | ||
return true; | ||
} | ||
function rectifyCompositeIndex(compositeIndex) { | ||
var snapIndex = compositeIndex[0]; | ||
var innerSnapIndex = compositeIndex[1]; | ||
if (innerSnapIndex < 0) { | ||
return [ | ||
snapIndex - 1, | ||
getMaxInnerSnapIndex(snapIndex - 1) | ||
]; | ||
} | ||
if (innerSnapIndex > getMaxInnerSnapIndex(snapIndex)) { | ||
return [snapIndex + 1, 0]; | ||
} | ||
return compositeIndex; | ||
var snapIndex = scope.compositeIndex[0]; | ||
var innerSnapIndex = scope.compositeIndex[1]; | ||
var newInnerSnapIndex; | ||
if (direction === 'up') { | ||
newInnerSnapIndex = innerSnapIndex - 1; | ||
} | ||
if (direction === 'down') { | ||
newInnerSnapIndex = innerSnapIndex + 1; | ||
} | ||
function snap(direction, event) { | ||
if (!isScrollable()) { | ||
return; | ||
} | ||
var newCompositeIndex = [snapIndex, newInnerSnapIndex]; | ||
if (!isCompositeIndexValid(newCompositeIndex)) { | ||
return; | ||
} | ||
direction === 'up' && (scope.preventDown = false); | ||
direction === 'down' && (scope.preventUp = false); | ||
if (event.type === 'wheel') { | ||
direction === 'up' && (scope.preventUp = true); | ||
direction === 'down' && (scope.preventDown = true); | ||
} | ||
if (scope.snapDirection === direction) { | ||
return true; | ||
} | ||
scope.$apply(function () { | ||
scope.sourceEvent = event; | ||
scope.compositeIndex = rectifyCompositeIndex( | ||
newCompositeIndex | ||
); | ||
}); | ||
if (scope.preventUp || scope.preventDown) { | ||
return true; | ||
} | ||
return true; | ||
} | ||
var snapIndex = scope.compositeIndex[0]; | ||
var innerSnapIndex = scope.compositeIndex[1]; | ||
var newInnerSnapIndex; | ||
if (direction === 'up') { | ||
newInnerSnapIndex = innerSnapIndex - 1; | ||
} | ||
if (direction === 'down') { | ||
newInnerSnapIndex = innerSnapIndex + 1; | ||
} | ||
function snapUp(event) { | ||
return snap('up', event); | ||
} | ||
var newCompositeIndex = [snapIndex, newInnerSnapIndex]; | ||
if (!isCompositeIndexValid(newCompositeIndex)) { | ||
return; | ||
} | ||
function snapDown(event) { | ||
return snap('down', event); | ||
} | ||
if (event.type === 'wheel') { | ||
direction === 'up' && (scope.preventUp = true); | ||
direction === 'down' && (scope.preventDown = true); | ||
function bindWheel() { | ||
if (scope.disableWheelBinding || scope.wheelBound) { | ||
return; | ||
} | ||
wheelie.bind(element, { | ||
up: function (e) { | ||
e.preventDefault(); | ||
if (snapUp(e)) { | ||
e.stopPropagation(); | ||
} | ||
}, | ||
down: function (e) { | ||
e.preventDefault(); | ||
if (snapDown(e)) { | ||
e.stopPropagation(); | ||
} | ||
} | ||
}, scope.ignoreWheelClass); | ||
scope.wheelBound = true; | ||
} | ||
scope.$apply(function () { | ||
scope.sourceEvent = event; | ||
scope.compositeIndex = rectifyCompositeIndex( | ||
newCompositeIndex | ||
); | ||
}); | ||
return true; | ||
function unbindWheel() { | ||
if (!scope.wheelBound) { | ||
return; | ||
} | ||
wheelie.unbind(element); | ||
scope.wheelBound = false; | ||
} | ||
function snapUp(event) { | ||
return snap('up', event); | ||
} | ||
function setHeight(angularElement, height) { | ||
angularElement.css('height', height + 'px'); | ||
} | ||
function snapDown(event) { | ||
return snap('down', event); | ||
function snapHeightChanged(current, previous) { | ||
if (isUndefined(current)) { | ||
return; | ||
} | ||
function bindWheel() { | ||
if (scope.disableWheelBinding || scope.wheelBound) { | ||
return; | ||
if (!isNumber(current)) { | ||
if (isNumber(previous)) { | ||
scope.snapHeight = previous; | ||
} | ||
wheelie.bind(element, { | ||
up: function (e) { | ||
e.preventDefault(); | ||
if (snapUp(e)) { | ||
e.stopPropagation(); | ||
} | ||
}, | ||
down: function (e) { | ||
e.preventDefault(); | ||
if (snapDown(e)) { | ||
e.stopPropagation(); | ||
} | ||
} | ||
}, scope.ignoreWheelClass); | ||
scope.wheelBound = true; | ||
return; | ||
} | ||
function unbindWheel() { | ||
if (!scope.wheelBound) { | ||
return; | ||
setHeight(element, current); | ||
forEach(getChildren(), function (child) { | ||
setHeight(angular.element(child), current); | ||
}); | ||
if (isDefined(scope.snapIndex)) { | ||
if (isUndefined(scope.compositeIndex)) { | ||
scope.compositeIndex = [scope.snapIndex, 0]; | ||
} | ||
wheelie.unbind(element); | ||
scope.wheelBound = false; | ||
snapTo(scope.compositeIndex); | ||
} | ||
} | ||
function setHeight(angularElement, height) { | ||
angularElement.css('height', height + 'px'); | ||
function watchSnapHeight() { | ||
scope.unwatchSnapHeight = scope.$watch( | ||
'snapHeight', | ||
snapHeightChanged | ||
); | ||
} | ||
function unwatchSnapHeight() { | ||
if (!isFunction(scope.unwatchSnapHeight)) { | ||
return; | ||
} | ||
scope.unwatchSnapHeight(); | ||
scope.unwatchSnapHeight = undefined; | ||
} | ||
function snapHeightChanged(current, previous) { | ||
if (isUndefined(current)) { | ||
return; | ||
function getCompositeIndex(scrollTop) { | ||
var snapIndex = 0; | ||
var innerSnapIndex = 0; | ||
if (scrollTop > 0) { | ||
snapIndex = -1; | ||
var children = getChildren(); | ||
var childHeight; | ||
while (scrollTop > 0) { | ||
childHeight = getHeight(children[++snapIndex]); | ||
scrollTop -= childHeight; | ||
} | ||
if (!isNumber(current)) { | ||
if (isNumber(previous)) { | ||
scope.snapHeight = previous; | ||
var snapHeight = getSnapHeight(); | ||
if (childHeight > snapHeight) { | ||
scrollTop += childHeight - snapHeight; | ||
if (scrollTop >= snapHeight) { | ||
innerSnapIndex++; | ||
} | ||
return; | ||
while (scrollTop > 0) { | ||
innerSnapIndex++; | ||
scrollTop -= snapHeight; | ||
} | ||
if ((snapHeight / 2) >= -scrollTop) { | ||
innerSnapIndex += 1; | ||
} | ||
} else if ((childHeight / 2) >= -scrollTop) { | ||
snapIndex += 1; | ||
} | ||
} | ||
setHeight(element, current); | ||
forEach(getChildren(), function (child) { | ||
setHeight(angular.element(child), current); | ||
}); | ||
return rectifyCompositeIndex([snapIndex, innerSnapIndex]); | ||
} | ||
if (isDefined(scope.snapIndex)) { | ||
if (isUndefined(scope.compositeIndex)) { | ||
scope.compositeIndex = [scope.snapIndex, 0]; | ||
} | ||
function onScroll() { | ||
function snapFromSrollTop() { | ||
var compositeIndex = getCompositeIndex( | ||
getCurrentScrollTop() | ||
); | ||
if (scope.compositeIndex[0] === compositeIndex[0] && | ||
scope.compositeIndex[1] === compositeIndex[1]) { | ||
snapTo(scope.compositeIndex); | ||
} else { | ||
scope.$apply(function () { | ||
scope.compositeIndex = compositeIndex; | ||
}); | ||
} | ||
} | ||
function watchSnapHeight() { | ||
scope.unwatchSnapHeight = scope.$watch( | ||
'snapHeight', | ||
snapHeightChanged | ||
scrollie.stop(element); | ||
if (scope.scrollDelay === false) { | ||
snapFromSrollTop(); | ||
} else { | ||
$timeout.cancel(scope.scrollPromise); | ||
scope.scrollPromise = $timeout( | ||
function () { | ||
snapFromSrollTop(); | ||
scope.scrollPromise = undefined; | ||
}, | ||
scope.scrollDelay | ||
); | ||
} | ||
} | ||
function unwatchSnapHeight() { | ||
if (!isFunction(scope.unwatchSnapHeight)) { | ||
return; | ||
} | ||
scope.unwatchSnapHeight(); | ||
scope.unwatchSnapHeight = undefined; | ||
function bindScroll() { | ||
if (scope.preventSnappingAfterManualScroll || | ||
scope.scrollBound) { | ||
return; | ||
} | ||
function getCompositeIndex(scrollTop) { | ||
var snapIndex = 0; | ||
var innerSnapIndex = 0; | ||
if (scrollTop > 0) { | ||
snapIndex = -1; | ||
var children = getChildren(); | ||
var childHeight; | ||
while (scrollTop > 0) { | ||
childHeight = getHeight(children[++snapIndex]); | ||
scrollTop -= childHeight; | ||
} | ||
var snapHeight = getSnapHeight(); | ||
if (childHeight > snapHeight) { | ||
scrollTop += childHeight - snapHeight; | ||
if (scrollTop >= snapHeight) { | ||
innerSnapIndex++; | ||
} | ||
while (scrollTop > 0) { | ||
innerSnapIndex++; | ||
scrollTop -= snapHeight; | ||
} | ||
if ((snapHeight / 2) >= -scrollTop) { | ||
innerSnapIndex += 1; | ||
} | ||
} else if ((childHeight / 2) >= -scrollTop) { | ||
snapIndex += 1; | ||
} | ||
} | ||
return rectifyCompositeIndex([snapIndex, innerSnapIndex]); | ||
if (isDefined(scope.snapDirection)) { // still snapping | ||
// TODO: add tests for this | ||
bindScrollAfterDelay(); | ||
return; | ||
} | ||
element.on('scroll', onScroll); | ||
scope.scrollBound = true; | ||
} | ||
function onScroll() { | ||
function snapFromSrollTop() { | ||
var compositeIndex = getCompositeIndex( | ||
getCurrentScrollTop() | ||
); | ||
if (scope.compositeIndex[0] === compositeIndex[0] && | ||
scope.compositeIndex[1] === compositeIndex[1]) { | ||
snapTo(scope.compositeIndex); | ||
} else { | ||
scope.$apply(function () { | ||
scope.compositeIndex = compositeIndex; | ||
}); | ||
} | ||
} | ||
scrollie.stop(element); | ||
if (scope.scrollDelay === false) { | ||
snapFromSrollTop(); | ||
} else { | ||
$timeout.cancel(scope.scrollPromise); | ||
scope.scrollPromise = $timeout( | ||
function () { | ||
snapFromSrollTop(); | ||
scope.scrollPromise = undefined; | ||
}, | ||
scope.scrollDelay | ||
); | ||
} | ||
function unbindScroll() { | ||
if (!scope.scrollBound) { | ||
return; | ||
} | ||
element.off('scroll', onScroll); | ||
scope.scrollBound = false; | ||
} | ||
function bindScroll() { | ||
if (scope.preventSnappingAfterManualScroll || | ||
scope.scrollBound) { | ||
return; | ||
} | ||
if (isDefined(scope.snapDirection)) { // still snapping | ||
// TODO: add tests for this | ||
bindScrollAfterDelay(); | ||
return; | ||
} | ||
element.on('scroll', onScroll); | ||
scope.scrollBound = true; | ||
function bindScrollAfterDelay() { | ||
if (scope.preventSnappingAfterManualScroll) { | ||
return; | ||
} | ||
function unbindScroll() { | ||
if (!scope.scrollBound) { | ||
return; | ||
} | ||
element.off('scroll', onScroll); | ||
scope.scrollBound = false; | ||
if (scope.bindScrollPromise) { | ||
$timeout.cancel(scope.bindScrollPromise); | ||
} | ||
scope.bindScrollPromise = $timeout( | ||
function () { | ||
bindScroll(); | ||
scope.bindScrollPromise = undefined; | ||
}, | ||
defaultSnapscrollBindScrollTimeout | ||
); | ||
} | ||
function bindScrollAfterDelay() { | ||
if (scope.preventSnappingAfterManualScroll) { | ||
return; | ||
} | ||
if (scope.bindScrollPromise) { | ||
$timeout.cancel(scope.bindScrollPromise); | ||
} | ||
scope.bindScrollPromise = $timeout( | ||
function () { | ||
bindScroll(); | ||
scope.bindScrollPromise = undefined; | ||
}, | ||
defaultSnapscrollBindScrollTimeout | ||
); | ||
function onKeyDown(e) { | ||
if (e.originalEvent) { | ||
e = e.originalEvent; | ||
} | ||
var handler; | ||
var keyCode = e.keyCode; | ||
if (keyCode === 38) { | ||
handler = snapUp; | ||
} | ||
if (keyCode === 40) { | ||
handler = snapDown; | ||
} | ||
if (handler) { | ||
e.preventDefault(); | ||
handler(e); | ||
} | ||
} | ||
function onKeyDown(e) { | ||
if (e.originalEvent) { | ||
e = e.originalEvent; | ||
} | ||
var handler; | ||
var keyCode = e.keyCode; | ||
if (keyCode === 38) { | ||
handler = snapUp; | ||
} | ||
if (keyCode === 40) { | ||
handler = snapDown; | ||
} | ||
if (handler) { | ||
e.preventDefault(); | ||
handler(e); | ||
} | ||
function bindArrowKeys() { | ||
if (!scope.enableArrowKeys || scope.arrowKeysBound) { | ||
return; | ||
} | ||
$document.on('keydown', onKeyDown); | ||
scope.arrowKeysBound = true; | ||
} | ||
function bindArrowKeys() { | ||
if (!scope.enableArrowKeys || scope.arrowKeysBound) { | ||
return; | ||
} | ||
$document.on('keydown', onKeyDown); | ||
scope.arrowKeysBound = true; | ||
function unbindArrowKeys() { | ||
if (!scope.arrowKeysBound) { | ||
return; | ||
} | ||
$document.off('keydown', onKeyDown); | ||
scope.arrowKeysBound = false; | ||
} | ||
function unbindArrowKeys() { | ||
if (!scope.arrowKeysBound) { | ||
return; | ||
function init() { | ||
var scrollDelay = attributes.scrollDelay; | ||
if (scrollDelay === 'false') { | ||
scope.scrollDelay = false; | ||
} else { | ||
scrollDelay = parseInt(scrollDelay, 10); | ||
if (isNaN(scrollDelay)) { | ||
scrollDelay = defaultSnapscrollScrollDelay; | ||
} | ||
$document.off('keydown', onKeyDown); | ||
scope.arrowKeysBound = false; | ||
scope.scrollDelay = scrollDelay; | ||
} | ||
function init() { | ||
var scrollDelay = attributes.scrollDelay; | ||
if (scrollDelay === 'false') { | ||
scope.scrollDelay = false; | ||
} else { | ||
scrollDelay = parseInt(scrollDelay, 10); | ||
if (isNaN(scrollDelay)) { | ||
scrollDelay = defaultSnapscrollScrollDelay; | ||
} | ||
scope.scrollDelay = scrollDelay; | ||
} | ||
var preventDoubleSnapDelay = ( | ||
attributes.preventDoubleSnapDelay | ||
var preventDoubleSnapDelay = ( | ||
attributes.preventDoubleSnapDelay | ||
); | ||
if (preventDoubleSnapDelay === 'false') { | ||
scope.preventDoubleSnapDelay = false; | ||
} else { | ||
preventDoubleSnapDelay = parseInt( | ||
preventDoubleSnapDelay, | ||
10 | ||
); | ||
if (preventDoubleSnapDelay === 'false') { | ||
scope.preventDoubleSnapDelay = false; | ||
} else { | ||
preventDoubleSnapDelay = parseInt( | ||
preventDoubleSnapDelay, | ||
10 | ||
if (isNaN(preventDoubleSnapDelay)) { | ||
preventDoubleSnapDelay = ( | ||
defaultSnapscrollPreventDoubleSnapDelay | ||
); | ||
if (isNaN(preventDoubleSnapDelay)) { | ||
preventDoubleSnapDelay = ( | ||
defaultSnapscrollPreventDoubleSnapDelay | ||
); | ||
} | ||
scope.preventDoubleSnapDelay = preventDoubleSnapDelay; | ||
} | ||
scope.preventDoubleSnapDelay = preventDoubleSnapDelay; | ||
} | ||
var snapEasing = attributes.snapEasing; | ||
if (isDefined(snapEasing)) { | ||
scope.snapEasing = scope.$parent.$eval(snapEasing); | ||
} else if (isFunction(defaultSnapscrollScrollEasing)) { | ||
scope.snapEasing = defaultSnapscrollScrollEasing; | ||
} | ||
var snapEasing = attributes.snapEasing; | ||
if (isDefined(snapEasing)) { | ||
scope.snapEasing = scope.$parent.$eval(snapEasing); | ||
} else if (isFunction(defaultSnapscrollScrollEasing)) { | ||
scope.snapEasing = defaultSnapscrollScrollEasing; | ||
} | ||
var snapDuration = parseInt(attributes.snapDuration, 10); | ||
if (isNaN(snapDuration)) { | ||
snapDuration = defaultSnapscrollSnapDuration; | ||
} | ||
scope.snapDuration = snapDuration; | ||
var snapDuration = parseInt(attributes.snapDuration, 10); | ||
if (isNaN(snapDuration)) { | ||
snapDuration = defaultSnapscrollSnapDuration; | ||
} | ||
scope.snapDuration = snapDuration; | ||
// TODO: perform initial snap without animation | ||
if (isUndefined(scope.snapAnimation)) { | ||
scope.snapAnimation = true; | ||
} | ||
// TODO: perform initial snap without animation | ||
if (isUndefined(scope.snapAnimation)) { | ||
scope.snapAnimation = true; | ||
} | ||
scope.disableWheelBinding = isDefined( | ||
attributes.disableWheelBinding | ||
); | ||
scope.disableWheelBinding = isDefined( | ||
attributes.disableWheelBinding | ||
); | ||
scope.enableArrowKeys = isDefined( | ||
attributes.enableArrowKeys | ||
); | ||
scope.enableArrowKeys = isDefined( | ||
attributes.enableArrowKeys | ||
); | ||
scope.preventSnappingAfterManualScroll = isDefined( | ||
attributes.preventSnappingAfterManualScroll | ||
); | ||
scope.preventSnappingAfterManualScroll = isDefined( | ||
attributes.preventSnappingAfterManualScroll | ||
); | ||
scope.ignoreWheelClass = attributes.ignoreWheelClass; | ||
scope.ignoreWheelClass = attributes.ignoreWheelClass; | ||
if (element.css('overflowY') !== 'scroll') { | ||
element.css('overflowY', 'auto'); | ||
} | ||
if (element.css('overflowY') !== 'scroll') { | ||
element.css('overflowY', 'auto'); | ||
} | ||
scope.$watch('enabled', function (current, previous) { | ||
function updateCompositeIndexFromScrollTop() { | ||
if (scope.preventSnappingAfterManualScroll) { | ||
return; | ||
} | ||
scope.compositeIndex = getCompositeIndex( | ||
getCurrentScrollTop() | ||
); | ||
scope.$watch('enabled', function (current, previous) { | ||
function updateCompositeIndexFromScrollTop() { | ||
if (scope.preventSnappingAfterManualScroll) { | ||
return; | ||
} | ||
if (current !== false) { | ||
if (previous === false) { | ||
updateCompositeIndexFromScrollTop(); | ||
} | ||
watchCompositeIndex(); | ||
watchSnapIndex(); | ||
watchSnapHeight(); | ||
bindScroll(); | ||
bindWheel(); | ||
bindArrowKeys(); | ||
} else { | ||
unwatchCompositeIndex(); | ||
unwatchSnapIndex(); | ||
unwatchSnapHeight(); | ||
unbindScroll(); | ||
unbindWheel(); | ||
unbindArrowKeys(); | ||
scope.compositeIndex = getCompositeIndex( | ||
getCurrentScrollTop() | ||
); | ||
} | ||
if (current !== false) { | ||
if (previous === false) { | ||
updateCompositeIndexFromScrollTop(); | ||
} | ||
}); | ||
watchCompositeIndex(); | ||
watchSnapIndex(); | ||
watchSnapHeight(); | ||
bindScroll(); | ||
bindWheel(); | ||
bindArrowKeys(); | ||
} else { | ||
unwatchCompositeIndex(); | ||
unwatchSnapIndex(); | ||
unwatchSnapHeight(); | ||
unbindScroll(); | ||
unbindWheel(); | ||
unbindArrowKeys(); | ||
} | ||
}); | ||
scope.$on('$destroy', function () { | ||
if (scope.enabled !== false) { | ||
unbindScroll(); | ||
unbindWheel(); | ||
unbindArrowKeys(); | ||
} | ||
}); | ||
} | ||
init(); | ||
scope.$on('$destroy', function () { | ||
if (scope.enabled !== false) { | ||
unbindScroll(); | ||
unbindWheel(); | ||
unbindArrowKeys(); | ||
} | ||
}); | ||
} | ||
}; | ||
} | ||
]; | ||
angular.module('snapscroll') | ||
.directive('snapscroll', snapscrollAsAnAttribute); | ||
})(); | ||
init(); | ||
} | ||
}; | ||
} | ||
]); |
@@ -1,10 +0,12 @@ | ||
(function () { | ||
angular | ||
.module('snapscroll', ['wheelie', 'scrollie']) | ||
.value('defaultSnapscrollScrollEasing', undefined) | ||
.value('defaultSnapscrollScrollDelay', 250) | ||
.value('defaultSnapscrollSnapDuration', 800) | ||
.value('defaultSnapscrollResizeDelay', 400) | ||
.value('defaultSnapscrollBindScrollTimeout', 400) | ||
.value('defaultSnapscrollPreventDoubleSnapDelay', 1000); | ||
})(); | ||
if (typeof exports === 'object') { | ||
module.exports = 'snapscroll'; | ||
} | ||
angular | ||
.module('snapscroll', ['wheelie', 'scrollie']) | ||
.value('defaultSnapscrollScrollEasing', undefined) | ||
.value('defaultSnapscrollScrollDelay', 250) | ||
.value('defaultSnapscrollSnapDuration', 800) | ||
.value('defaultSnapscrollResizeDelay', 400) | ||
.value('defaultSnapscrollBindScrollTimeout', 400) | ||
.value('defaultSnapscrollPreventDoubleSnapDelay', 1000); |
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
273424
5687
+ Addedangular-wheelie@3.0.1(transitive)
- Removedangular-wheelie@2.1.0(transitive)
Updatedangular-scrollie@^1.1.1
Updatedangular-wheelie@^3.0.1