angular-ui-scroll
Advanced tools
Comparing version 1.5.1 to 1.5.2
{ | ||
"name": "angular-ui-scroll", | ||
"version": "1.5.1", | ||
"version": "1.5.2", | ||
"homepage": "https://github.com/angular-ui/ui-scroll.git", | ||
@@ -5,0 +5,0 @@ "description": "AngularJS infinite scrolling module", |
/*! | ||
* angular-ui-scroll | ||
* https://github.com/angular-ui/ui-scroll.git | ||
* Version: 1.5.1 -- 2016-06-27T18:18:39.277Z | ||
* Version: 1.5.2 -- 2016-11-18T00:26:15.332Z | ||
* License: MIT | ||
@@ -6,0 +6,0 @@ */ |
/*! | ||
* angular-ui-scroll | ||
* https://github.com/angular-ui/ui-scroll.git | ||
* Version: 1.5.1 -- 2016-06-27T18:18:39.277Z | ||
* Version: 1.5.2 -- 2016-11-18T00:26:15.332Z | ||
* License: MIT | ||
*/ | ||
!function(){"use strict";angular.module("ui.scroll.grid",[]).directive("uiScrollTh",["$log","$timeout",function(a,b){function c(a){this.getLayout=function(){return a.getLayout()},this.applyLayout=function(b){return a.applyLayout(b)},this.columnFromPoint=function(b,c){return a.columnFromPoint(b,c)},Object.defineProperty(this,"columns",{get:function(){return a.getColumns()}})}function d(a,b){this.css=function(){var c=arguments[0],d=arguments[1];return 1==arguments.length?b.header.css(c):void(2==arguments.length&&(b.header.css(c,d),a.forEachRow(function(a){return a[b.id].css(c,d)}),b.css[c]=d))},this.moveBefore=function(c){a.moveBefore(b,c)},this.exchangeWith=function(c){a.exchangeWith(b,c)},Object.defineProperty(this,"columnId",{get:function(){return b.id}})}function e(a,b,c){function d(a,b,c){var d=a.offset();return b<d.left||d.left+a.outerWidth(!0)<b?!1:!(c<d.top||d.top+a.outerHeight(!0)<c)}function e(a,b){a.detach(),b.before(a)}function f(a,b){var c=a.parent();a.detach(),c.append(a)}function g(a,b){a.removeAttr("style");for(var c in b)b.hasOwnProperty(c)&&a.css(c,b[c])}this.header=c,this.cells=[],this.css={},this.mapTo=b.length,this.id=b.length,this.applyLayout=function(a){this.css=angular.extend({},a.css),this.mapTo=a.mapTo,g(this.header,this.css)},this.moveBefore=function(b){var d=this;b?(e(c,b.header),a.forEachRow(function(a){return e(a[d.id],a[b.id])})):(f(c),a.forEachRow(function(a){return f(a[d.id])}))},this.columnFromPoint=function(b,e){var f=this;if(d(c,b,e))return this;var g=void 0;return a.forEachRow(function(a){d(a[f.id],b,e)&&(g=f)}),g},this.applyCss=function(a){g(a,this.css)}}function f(a,f){function g(a){var b=a[0].parent(),c=[];a.forEach(function(b,d){i[d].applyCss(b),c[i[d].mapTo]=a[d],a[d].detach()}),c.forEach(function(a){return b.append(a)})}var h=this,i=[],j=new Map;b(function(){f.adapter.gridAdapter=new c(h),f.adapter.transform=function(a,b){return g(j.get(a),b)}}),this.registerColumn=function(a){i.push(new e(this,i,a))},this.registerCell=function(a,b){var c=j.get(a);return c||(c=[],j.set(a,c)),c.length>=i.length?!1:(c.push(b),!0)},this.unregisterCell=function(a,b){var c=j.get(a),d=c.indexOf(b);c.splice(d,1),c.length||j["delete"](a)},this.forEachRow=function(a){j.forEach(a)},this.getColumns=function(){var a=this,b=[];return i.slice().sort(function(a,b){return a.mapTo-b.mapTo}).forEach(function(c){return b.push(new d(a,c))}),b},this.getLayout=function(){var a=[];return i.forEach(function(b,c){return a.push({index:c,css:angular.extend({},b.css),mapTo:b.mapTo})}),a},this.applyLayout=function(a){if(!a||a.length!=i.length)throw new Error("Failed to apply layout - number of layouts should match number of columns");a.forEach(function(a,b){i[b].applyLayout(a)}),g(i.map(function(a){return a.header})),j.forEach(function(a){g(a)})},this.moveBefore=function(a,b){var c=b;if(b%1!==0&&(c=b?i[b.columnId].mapTo:i.length),!(0>c||c>i.length)){var d=a.mapTo,e=void 0;c-=c>d?1:0,i.forEach(function(a){a.mapTo-=a.mapTo>d?1:0,a.mapTo+=a.mapTo>=c?1:0,e=a.mapTo===c+1?a:e}),a.mapTo=c,a.moveBefore(e)}},this.exchangeWith=function(a,b){0>b||b>=i.length||(i.find(function(a){return a.mapTo===b}).mapTo=a.mapTo,a.mapTo=b)},this.columnFromPoint=function(a,b){for(var c=0;c<i.length;c++){var e=i[c].columnFromPoint(a,b);if(e)break}return e?new d(this,e):void 0}}return{require:["^^uiScrollViewport"],restrict:"A",link:function(a,b,c,d,e){d[0].gridController=d[0].gridController||new f(a,d[0]),d[0].gridController.registerColumn(b)}}}]).directive("uiScrollTd",["$log",function(a){return{require:["?^^uiScrollViewport"],restrict:"A",link:function(a,b,c,d,e){d[0]&&!function(){var c=d[0].gridController;c.registerCell(a,b)&&a.$on("$destroy",function(){return c.unregisterCell(a,b)})}()}}}])}(); |
/*! | ||
* angular-ui-scroll | ||
* https://github.com/angular-ui/ui-scroll.git | ||
* Version: 1.5.1 -- 2016-06-27T18:18:39.277Z | ||
* Version: 1.5.2 -- 2016-11-18T00:26:15.332Z | ||
* License: MIT | ||
@@ -6,0 +6,0 @@ */ |
/*! | ||
* angular-ui-scroll | ||
* https://github.com/angular-ui/ui-scroll.git | ||
* Version: 1.5.1 -- 2016-06-27T18:18:39.277Z | ||
* Version: 1.5.2 -- 2016-11-18T00:26:15.332Z | ||
* License: MIT | ||
*/ | ||
!function(){"use strict";var a=function(){function a(a,b){var c=[],d=!0,e=!1,f=void 0;try{for(var g,h=a[Symbol.iterator]();!(d=(g=h.next()).done)&&(c.push(g.value),!b||c.length!==b);d=!0);}catch(i){e=!0,f=i}finally{try{!d&&h["return"]&&h["return"]()}finally{if(e)throw f}}return c}return function(b,c){if(Array.isArray(b))return b;if(Symbol.iterator in Object(b))return a(b,c);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();angular.module("ui.scroll.jqlite",["ui.scroll"]).service("jqLiteExtras",["$log","$window",function(b,c){return{registerFor:function(b){function d(b,c,d){var e=b[0],f=a({top:["scrollTop","pageYOffset","scrollLeft"],left:["scrollLeft","pageXOffset","scrollTop"]}[c],3),g=f[0],h=f[1],i=f[2];return j(e)?angular.isDefined(d)?e.scrollTo(b[i].call(b),d):h in e?e[h]:e.document.documentElement[g]:(angular.isDefined(d)&&(e[g]=d),e[g])}function e(b,c){var d=void 0,e=void 0,f=void 0,h=void 0,k=void 0,l=void 0,m=void 0,n=void 0,o=void 0,p=void 0,q=void 0,r=void 0;if(j(b))return d=document.documentElement[{height:"clientHeight",width:"clientWidth"}[c]],{base:d,padding:0,border:0,margin:0};var s=a({width:[b.offsetWidth,"Left","Right"],height:[b.offsetHeight,"Top","Bottom"]}[c],3);return d=s[0],m=s[1],n=s[2],l=i(b),q=g(b,l["padding"+m])||0,r=g(b,l["padding"+n])||0,e=g(b,l["border"+m+"Width"])||0,f=g(b,l["border"+n+"Width"])||0,h=l["margin"+m],k=l["margin"+n],o=g(b,h)||0,p=g(b,k)||0,{base:d,padding:q+r,border:e+f,margin:o+p}}function f(a,b,c){var d=void 0,f=void 0,g=e(a,b);return g.base>0?{base:g.base-g.padding-g.border,outer:g.base,outerfull:g.base+g.margin}[c]:(d=i(a),f=d[b],(0>f||null===f)&&(f=a.style[b]||0),f=parseFloat(f)||0,{base:f-g.padding-g.border,outer:f,outerfull:f+g.padding+g.border+g.margin}[c])}var g,h,i,j;return h=angular.element.prototype.css,b.prototype.css=function(a,b){var c=this,d=c[0];return d&&3!==d.nodeType&&8!==d.nodeType&&d.style?h.call(c,a,b):void 0},j=function(a){return a&&a.document&&a.location&&a.alert&&a.setInterval},c.getComputedStyle?(i=function(a){return c.getComputedStyle(a,null)},g=function(a,b){return parseFloat(b)}):(i=function(a){return a.currentStyle},g=function(a,b){var c=void 0,d=void 0,e=void 0,f=void 0,g=void 0,h=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,i=new RegExp("^("+h+")(?!px)[a-z%]+$","i");return i.test(b)?(g=a.style,c=g.left,e=a.runtimeStyle,f=e&&e.left,e&&(e.left=g.left),g.left=b,d=g.pixelLeft,g.left=c,f&&(e.left=f),d):parseFloat(b)}),angular.forEach({before:function(a){var b,c,d,e,f,g,h;if(h=this,c=h[0],f=h.parent(),b=f.contents(),b[0]===c)return f.prepend(a);for(d=e=1,g=b.length-1;g>=1?g>=e:e>=g;d=g>=1?++e:--e)if(b[d]===c)return void angular.element(b[d-1]).after(a);throw new Error("invalid DOM structure "+c.outerHTML)},height:function(a){var b;return b=this,angular.isDefined(a)?(angular.isNumber(a)&&(a+="px"),h.call(b,"height",a)):f(this[0],"height","base")},outerHeight:function(a){return f(this[0],"height",a?"outerfull":"outer")},outerWidth:function(a){return f(this[0],"width",a?"outerfull":"outer")},offset:function(a){var b=void 0,c=void 0,d=this,e={top:0,left:0},f=d[0],g=f&&f.ownerDocument;if(arguments.length){if(void 0===a)return d;throw new Error("offset setter method is not implemented")}return g?(b=g.documentElement,null!=f.getBoundingClientRect&&(e=f.getBoundingClientRect()),c=g.defaultView||g.parentWindow,{top:e.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:e.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):void 0},scrollTop:function(a){return d(this,"top",a)},scrollLeft:function(a){return d(this,"left",a)}},function(a,c){return b.prototype[c]?void 0:b.prototype[c]=a})}}}]).run(["$log","$window","jqLiteExtras",function(a,b,c){return b.jQuery?void 0:c.registerFor(angular.element)}])}(); |
/*! | ||
* angular-ui-scroll | ||
* https://github.com/angular-ui/ui-scroll.git | ||
* Version: 1.5.1 -- 2016-06-27T18:18:39.277Z | ||
* Version: 1.5.2 -- 2016-11-18T00:26:15.332Z | ||
* License: MIT | ||
@@ -212,5 +212,3 @@ */ | ||
function Viewport(buffer, element, viewportController, attrs) { | ||
var PADDING_MIN = 0.3; | ||
var PADDING_DEFAULT = 0.5; | ||
function Viewport(buffer, element, viewportController, padding) { | ||
var topPadding = undefined; | ||
@@ -231,8 +229,7 @@ var bottomPadding = undefined; | ||
add: function add(item) { | ||
var existedItem = cache.find(function (i) { | ||
return i.index === item.scope.$index; | ||
}); | ||
if (existedItem) { | ||
existedItem.height = item.element.outerHeight(); | ||
return; | ||
for (var i = cache.length - 1; i >= 0; i--) { | ||
if (cache[i].index === item.scope.$index) { | ||
cache[i].height = item.element.outerHeight(); | ||
return; | ||
} | ||
} | ||
@@ -275,3 +272,3 @@ cache.push({ | ||
function bufferPadding() { | ||
return viewport.outerHeight() * Math.max(PADDING_MIN, +attrs.padding || PADDING_DEFAULT); // some extra space to initiate preload | ||
return viewport.outerHeight() * padding; // some extra space to initiate preload | ||
} | ||
@@ -423,3 +420,3 @@ | ||
function Adapter($attr, viewport, buffer, adjustBuffer) { | ||
function Adapter($attr, viewport, buffer, adjustBuffer, element) { | ||
var viewportScope = viewport.scope() || $rootScope; | ||
@@ -527,19 +524,45 @@ var disabled = false; | ||
if (expression) { | ||
var match = expression.match(/^(\S+)(?:\s+on\s+(\w(?:\w|\d)*))?$/); | ||
// it is ok to have relaxed validation for the first part of the 'on' expression. | ||
// additional validation will be done by the $parse service below | ||
var match = expression.match(/^(\S+)(?:\s+on\s+(\w(?:\w|\d)*))?/); | ||
if (!match) throw new Error('Expected injection expression in form of \'target\' or \'target on controller\' but got \'' + expression + '\''); | ||
var target = match[1]; | ||
var controllerName = match[2]; | ||
if (controllerName) { | ||
var candidate = viewport; | ||
scope = undefined; | ||
var onControllerName = match[2]; | ||
var parseController = function parseController(controllerName, on) { | ||
var candidate = element; | ||
while (candidate.length) { | ||
var controller = candidate.attr('ng-controller'); | ||
if (controller === controllerName) { | ||
scope = candidate.scope(); | ||
break; | ||
var candidateScope = candidate.scope(); | ||
// ng-controller's 'Controller As' parsing | ||
var candidateName = (candidate.attr('ng-controller') || '').match(/(\w(?:\w|\d)*)(?:\s+as\s+(\w(?:\w|\d)*))?/); | ||
if (candidateName && candidateName[on ? 1 : 2] === controllerName) { | ||
scope = candidateScope; | ||
return true; | ||
} | ||
// directive's/component's 'Controller As' parsing | ||
if (!on && candidateScope && candidateScope.hasOwnProperty(controllerName) && Object.getPrototypeOf(candidateScope[controllerName]).constructor.hasOwnProperty('$inject')) { | ||
scope = candidateScope; | ||
return true; | ||
} | ||
candidate = candidate.parent(); | ||
} | ||
if (!scope) throw new Error('Failed to locate target controller \'' + controllerName + '\' to inject \'' + target + '\''); | ||
}; | ||
if (onControllerName) { | ||
// 'on' syntax DOM parsing (adapter='adapter on ctrl') | ||
scope = null; | ||
parseController(onControllerName, true); | ||
if (!scope) { | ||
throw new Error('Failed to locate target controller \'' + onControllerName + '\' to inject \'' + target + '\''); | ||
} | ||
} else { | ||
// try to parse DOM with 'Controller As' syntax (adapter='ctrl.adapter') | ||
var controllerAsName = undefined; | ||
var dotIndex = target.indexOf('.'); | ||
if (dotIndex > 0) { | ||
controllerAsName = target.substr(0, dotIndex); | ||
parseController(controllerAsName, false); | ||
} | ||
} | ||
assign = $parse(target).assign; | ||
@@ -580,12 +603,23 @@ } | ||
var match = $attr.uiScroll.match(/^\s*(\w+)\s+in\s+([(\w|\$)\.]+)\s*$/); | ||
if (!match) { | ||
throw new Error('Expected uiScroll in form of \'_item_ in _datasource_\' but got \'' + $attr.uiScroll + '\''); | ||
} | ||
if (!match) throw new Error('Expected uiScroll in form of \'_item_ in _datasource_\' but got \'' + $attr.uiScroll + '\''); | ||
function parseNumericAttr(value, defaultValue) { | ||
var result = $parse(value)($scope); | ||
return isNaN(result) ? defaultValue : result; | ||
} | ||
var BUFFER_MIN = 3; | ||
var BUFFER_DEFAULT = 10; | ||
var PADDING_MIN = 0.3; | ||
var PADDING_DEFAULT = 0.5; | ||
var datasource = null; | ||
var itemName = match[1]; | ||
var datasourceName = match[2]; | ||
var bufferSize = Math.max(3, +$attr.bufferSize || 10); | ||
var viewportController = controllers[0]; | ||
var startIndex = parseInt($attr.startIndex, 10); | ||
startIndex = isNaN(startIndex) ? 1 : startIndex; | ||
var bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT)); | ||
var padding = Math.max(PADDING_MIN, parseNumericAttr($attr.padding, PADDING_DEFAULT)); | ||
var startIndex = parseNumericAttr($attr.startIndex, 1); | ||
var ridActual = 0; // current data revision id | ||
@@ -595,4 +629,4 @@ var pending = []; | ||
var buffer = new Buffer(bufferSize); | ||
var viewport = new Viewport(buffer, element, viewportController, $attr); | ||
var adapter = new Adapter($attr, viewport, buffer, adjustBuffer); | ||
var viewport = new Viewport(buffer, element, viewportController, padding); | ||
var adapter = new Adapter($attr, viewport, buffer, adjustBuffer, element); | ||
if (viewportController) viewportController.adapter = adapter; | ||
@@ -599,0 +633,0 @@ |
/*! | ||
* angular-ui-scroll | ||
* https://github.com/angular-ui/ui-scroll.git | ||
* Version: 1.5.1 -- 2016-06-27T18:18:39.277Z | ||
* Version: 1.5.2 -- 2016-11-18T00:26:15.332Z | ||
* License: MIT | ||
*/ | ||
!function(){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol?"symbol":typeof a};angular.module("ui.scroll",[]).directive("uiScrollViewport",function(){return{restrict:"A",controller:["$log","$scope","$element",function(a,b,c){var d=this;d.container=c,d.viewport=c,angular.forEach(c.children(),function(a){"tbody"===a.tagName.toLowerCase()&&(d.viewport=angular.element(a))})}]}}).directive("uiScroll",["$log","$injector","$rootScope","$timeout","$q","$parse",function(b,c,d,e,f,g){function h(a,b){return b.after(a),[]}function i(a){return a.element.remove(),a.scope.$destroy(),[]}function j(b,c){if(!p)return h(b,c);if(q){var d=function(){var a=f.defer();return p.enter(b,null,c,function(){return a.resolve()}),{v:[a.promise]}}();if("object"===("undefined"==typeof d?"undefined":a(d)))return d.v}return[p.enter(b,null,c)]}function k(b){if(!p)return i(b);if(q){var c=function(){var a=f.defer();return p.leave(b.element,function(){return b.scope.$destroy(),a.resolve()}),{v:[a.promise]}}();if("object"===("undefined"==typeof c?"undefined":a(c)))return c.v}return[p.leave(b.element).then(function(){return b.scope.$destroy()})]}function l(a){var b=Object.create(Array.prototype);return angular.extend(b,{size:a,reset:function(a){b.remove(0,b.length),b.eof=!1,b.bof=!1,b.first=a,b.next=a,b.minIndex=a,b.maxIndex=a,b.minIndexUser=null,b.maxIndexUser=null},append:function(a){a.forEach(function(a){++b.next,b.insert("append",a)}),b.maxIndex=b.eof?b.next-1:Math.max(b.next-1,b.maxIndex)},prepend:function(a){a.reverse().forEach(function(a){--b.first,b.insert("prepend",a)}),b.minIndex=b.bof?b.minIndex=b.first:Math.min(b.first,b.minIndex)},insert:function(a,c){var d={item:c};if(a%1===0)d.op="insert",b.splice(a,0,d);else switch(d.op=a,a){case"append":b.push(d);break;case"prepend":b.unshift(d)}},remove:function(a,c){if(angular.isNumber(a)){for(var d=a;c>d;d++)i(b[d]);return b.splice(a,c-a)}return b.splice(b.indexOf(a),1),k(a)},effectiveHeight:function(a){if(!a.length)return 0;var b=Number.MAX_VALUE,c=Number.MIN_VALUE;return a.forEach(function(a){a.element[0].offsetParent&&(b=Math.min(b,a.element.offset().top),c=Math.max(c,a.element.offset().top+a.element.outerHeight(!0)))}),Math.max(0,c-b)}}),b}function m(a,b,c,d){function e(){var a=Object.create(Array.prototype);return angular.extend(a,{add:function(b){var c=a.find(function(a){return a.index===b.scope.$index});return c?void(c.height=b.element.outerHeight()):void a.push({index:b.scope.$index,height:b.element.outerHeight()})},clear:function(){a.length=0}}),a}function f(a){var b=void 0;switch(a.tagName){case"dl":throw new Error("ui-scroll directive does not support <"+a.tagName+"> as a repeating tag: "+a.outerHTML);case"tr":var c=angular.element("<table><tr><td><div></div></td></tr></table>");b=c.find("tr");break;case"li":b=angular.element("<li></li>");break;default:b=angular.element("<div></div>")}return b.cache=new e,b}function g(){return n.outerHeight()*Math.max(i,+d.padding||k)}var i=.3,k=.5,l=void 0,m=void 0,n=c&&c.viewport?c.viewport:angular.element(window),o=c&&c.container?c.container:void 0;return n.css({"overflow-y":"auto",display:"block"}),angular.extend(n,{createPaddingElements:function(a){l=new f(a),m=new f(a),b.before(l),b.after(m)},applyContainerStyle:function(){o&&o!==n&&n.css("height",window.getComputedStyle(o[0]).height)},bottomDataPos:function(){var a=n[0].scrollHeight;return a=null!=a?a:n[0].document.documentElement.scrollHeight,a-m.height()},topDataPos:function(){return l.height()},bottomVisiblePos:function(){return n.scrollTop()+n.outerHeight()},topVisiblePos:function(){return n.scrollTop()},insertElement:function(a,b){return h(a,b||l)},insertElementAnimated:function(a,b){return j(a,b||l)},shouldLoadBottom:function(){return!a.eof&&n.bottomDataPos()<n.bottomVisiblePos()+g()},clipBottom:function(){for(var b=0,c=0,d=0,e=n.bottomDataPos()-n.bottomVisiblePos()-g(),f=a.length-1;f>=0&&(d=a[f].element.outerHeight(!0),!(c+d>e));f--)m.cache.add(a[f]),c+=d,b++;b>0&&(a.eof=!1,a.remove(a.length-b,a.length),a.next-=b,n.adjustPadding())},shouldLoadTop:function(){return!a.bof&&n.topDataPos()>n.topVisiblePos()-g()},clipTop:function(){for(var b=0,c=0,d=0,e=n.topVisiblePos()-n.topDataPos()-g(),f=0;f<a.length&&(d=a[f].element.outerHeight(!0),!(c+d>e));f++)l.cache.add(a[f]),c+=d,b++;b>0&&(l.height(l.height()+c),a.bof=!1,a.remove(0,b),a.first+=b)},adjustPadding:function(){if(a.length){var b=l.cache.reduce(function(b,c){return b+(c.index<a.first?c.height:0)},0),c=m.cache.reduce(function(b,c){return b+(c.index>=a.next?c.height:0)},0),d=a.reduce(function(a,b){return a+b.element.outerHeight(!0)},0),e=(d+b+c)/(a.maxIndex-a.minIndex+1),f=null!==a.minIndexUser&&a.minIndex>a.minIndexUser,g=null!==a.maxIndexUser&&a.maxIndex<a.maxIndexUser,h=f?(a.minIndex-a.minIndexUser)*e:0,i=g?(a.maxIndexUser-a.maxIndex)*e:0;l.height(b+h),m.height(c+i)}},adjustScrollTopAfterMinIndexSet:function(b){if(null!==a.minIndexUser&&a.minIndex>a.minIndexUser){var c=l.height()-b;n.scrollTop(n.scrollTop()+c)}},adjustScrollTopAfterPrepend:function(b){if(b.prepended.length){var c=a.effectiveHeight(b.prepended),d=l.height()-c;d>=0?l.height(d):(l.height(0),n.scrollTop(n.scrollTop()-d))}},resetTopPadding:function(){l.height(0),l.cache.clear()},resetBottomPadding:function(){m.height(0),m.cache.clear()}}),n}function n(a,b,c,e){function f(c){var d=a[c],e=i,f=void 0;if(d){var h=d.match(/^(\S+)(?:\s+on\s+(\w(?:\w|\d)*))?$/);if(!h)throw new Error("Expected injection expression in form of 'target' or 'target on controller' but got '"+d+"'");var j=h[1],l=h[2];if(l){var m=b;for(e=void 0;m.length;){var n=m.attr("ng-controller");if(n===l){e=m.scope();break}m=m.parent()}if(!e)throw new Error("Failed to locate target controller '"+l+"' to inject '"+j+"'")}f=g(j).assign}return function(a){k!==a&&(k[c]=a),f&&f(e,a)}}function h(a,b){if(angular.isArray(b)){var d=void 0,e=c.indexOf(a)+1;b.reverse().forEach(function(b){b===a.item?(d=!0,e--):c.insert(e,b)}),d||(a.op="remove")}}var i=b.scope()||d,j=!1,k=this;f("adapter")(k);var l=f("topVisible"),m=f("topVisibleElement"),n=f("topVisibleScope"),o=f("isLoading");Object.defineProperty(this,"disabled",{get:function(){return j},set:function(a){return(j=a)?null:e()}}),this.isLoading=!1,this.isBOF=function(){return c.bof},this.isEOF=function(){return c.eof},this.applyUpdates=function(a,b){if(angular.isFunction(a))c.slice(0).forEach(function(b){h(b,a(b.item,b.scope,b.element))});else{if(a%1!==0)throw new Error("applyUpdates - "+a+" is not a valid index");var d=a-c.first;d>=0&&d<c.length&&h(c[d],b)}e()},this.append=function(a){c.append(a),e()},this.prepend=function(a){c.prepend(a),e()},this.loading=function(a){o(a)},this.calculateProperties=function(){for(var a=void 0,d=void 0,e=void 0,f=void 0,g=void 0,h=0,i=0;i<c.length;i++){if(a=c[i],e=a.element.offset().top,f=g!==e,g=e,f&&(d=a.element.outerHeight(!0)),!(f&&b.topDataPos()+h+d<=b.topVisiblePos())){f&&(l(a.item),m(a.element),n(a.scope));break}h+=d}}}function o(a,b,h,i,j){function k(a,b,c){var d=Object.getOwnPropertyDescriptor(a,b);d&&(d.set||d.get)||Object.defineProperty(a,b,{set:function(a){R[b]=a,e(function(){if(N[c]=a,!M.length){var d=O.topDataPos();O.adjustPadding(),"minIndex"===b&&O.adjustScrollTopAfterMinIndexSet(d)}})},get:function(){return R[b]}})}function o(b){return b&&b!==L||a.$$destroyed}function p(){O.bind("resize",C),O.bind("scroll",C)}function q(){O.unbind("resize",C),O.unbind("scroll",C)}function r(){O.resetTopPadding(),O.resetBottomPadding(),arguments.length&&(K=arguments[0]),N.reset(K),z()}function s(a){return a.element.height()&&a.element[0].offsetParent}function t(a){s(a)&&(N.forEach(function(a){angular.isFunction(a.unregisterVisibilityWatcher)&&(a.unregisterVisibilityWatcher(),delete a.unregisterVisibilityWatcher)}),z())}function u(a,b){v(a,b,O.insertElement),s(a)||(a.unregisterVisibilityWatcher=a.scope.$watch(function(){return t(a)})),a.element.addClass("ng-hide")}function v(a,b,c){var d=void 0,e=b>0?N[b-1].element:void 0;return j(function(b,f){d=c(b,e),a.element=b,a.scope=f,f[G]=a.item}),P.transform&&P.transform(a.scope,a.element),d}function w(){var a=[],b=[],c=[],d=[];return N.forEach(function(e,f){switch(e.op){case"prepend":b.unshift(e);break;case"append":u(e,f),e.op="none",d.push(e);break;case"insert":a=a.concat(v(e,f,O.insertElementAnimated)),e.op="none",d.push(e);break;case"remove":c.push(e)}}),c.forEach(function(b){return a=a.concat(N.remove(b))}),b.length&&b.forEach(function(a){u(a),a.op="none"}),N.forEach(function(a,b){return a.scope.$index=N.first+b}),{prepended:b,removed:c,inserted:d,animated:a}}function x(a,b){b.animated.length?f.all(b.animated).then(function(){O.adjustPadding(),z(a)}):O.adjustPadding()}function y(a,b){O.shouldLoadBottom()?(!b||N.effectiveHeight(b.inserted)>0)&&1===M.push(!0)&&(B(a),P.loading(!0)):O.shouldLoadTop()&&(!b||N.effectiveHeight(b.prepended)>0||M[0])&&1===M.push(!1)&&(B(a),P.loading(!0))}function z(a){a||(M=[],a=++L);var b=w();e(function(){b.inserted.forEach(function(a){return a.element.removeClass("ng-hide")}),b.prepended.forEach(function(a){return a.element.removeClass("ng-hide")}),o(a)||(x(a,b),y(a),M.length||P.calculateProperties())})}function A(a){var b=w();e(function(){b.inserted.forEach(function(a){return a.element.removeClass("ng-hide")}),b.prepended.forEach(function(a){return a.element.removeClass("ng-hide")}),O.adjustScrollTopAfterPrepend(b),o(a)||(x(a,b),y(a,b),M.shift(),M.length?B(a):(P.loading(!1),p(),P.calculateProperties()))})}function B(a){M[0]?N.length&&!O.shouldLoadBottom()?A(a):S(function(b){o(a)||(b.length<I&&(N.eof=!0),b.length>0&&(O.clipTop(),N.append(b)),A(a))}):N.length&&!O.shouldLoadTop()?A(a):T(function(b){o(a)||(b.length<I&&(N.bof=!0),b.length>0&&(N.length&&O.clipBottom(),N.prepend(b)),A(a))})}function C(){d.$$phase||P.isLoading||P.disabled||(y(L),M.length?q():(P.calculateProperties(),a.$apply()))}function D(a){if(!P.disabled){var b=O[0].scrollTop,c=O[0].scrollHeight-O[0].clientHeight;(0===b&&!N.bof||b===c&&!N.eof)&&a.preventDefault()}}var E=h.uiScroll.match(/^\s*(\w+)\s+in\s+([(\w|\$)\.]+)\s*$/);if(!E)throw new Error("Expected uiScroll in form of '_item_ in _datasource_' but got '"+h.uiScroll+"'");var F=null,G=E[1],H=E[2],I=Math.max(3,+h.bufferSize||10),J=i[0],K=parseInt(h.startIndex,10);K=isNaN(K)?1:K;var L=0,M=[],N=new l(I),O=new m(N,b,J,h),P=new n(h,O,N,z);J&&(J.adapter=P);var Q=function(){return angular.isObject(F)&&angular.isFunction(F.get)};if(F=g(H)(a),!Q()&&(F=c.get(H),!Q()))throw new Error(H+" is not a valid datasource");var R={};k(F,"minIndex","minIndexUser"),k(F,"maxIndex","maxIndexUser");var S=2!==F.get.length?function(a){return F.get(N.next,I,a)}:function(a){F.get({index:N.next,append:N.length?N[N.length-1].item:void 0,count:I},a)},T=2!==F.get.length?function(a){return F.get(N.first-I,I,a)}:function(a){F.get({index:N.first-I,prepend:N.length?N[0].item:void 0,count:I},a)};P.reload=r,j(function(a,b){O.createPaddingElements(a[0]),b.$destroy(),a.remove()}),a.$on("$destroy",function(){q(),O.unbind("mousewheel",D)}),O.bind("mousewheel",D),e(function(){O.applyContainerStyle(),r()})}var p=c.has&&c.has("$animate")?c.get("$animate"):null,q=1===angular.version.major&&angular.version.minor<3;return{require:["?^^uiScrollViewport"],restrict:"A",transclude:"element",priority:1e3,terminal:!0,link:o}}])}(); | ||
!function(){"use strict";var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol?"symbol":typeof a};angular.module("ui.scroll",[]).directive("uiScrollViewport",function(){return{restrict:"A",controller:["$log","$scope","$element",function(a,b,c){var d=this;d.container=c,d.viewport=c,angular.forEach(c.children(),function(a){"tbody"===a.tagName.toLowerCase()&&(d.viewport=angular.element(a))})}]}}).directive("uiScroll",["$log","$injector","$rootScope","$timeout","$q","$parse",function(b,c,d,e,f,g){function h(a,b){return b.after(a),[]}function i(a){return a.element.remove(),a.scope.$destroy(),[]}function j(b,c){if(!p)return h(b,c);if(q){var d=function(){var a=f.defer();return p.enter(b,null,c,function(){return a.resolve()}),{v:[a.promise]}}();if("object"===("undefined"==typeof d?"undefined":a(d)))return d.v}return[p.enter(b,null,c)]}function k(b){if(!p)return i(b);if(q){var c=function(){var a=f.defer();return p.leave(b.element,function(){return b.scope.$destroy(),a.resolve()}),{v:[a.promise]}}();if("object"===("undefined"==typeof c?"undefined":a(c)))return c.v}return[p.leave(b.element).then(function(){return b.scope.$destroy()})]}function l(a){var b=Object.create(Array.prototype);return angular.extend(b,{size:a,reset:function(a){b.remove(0,b.length),b.eof=!1,b.bof=!1,b.first=a,b.next=a,b.minIndex=a,b.maxIndex=a,b.minIndexUser=null,b.maxIndexUser=null},append:function(a){a.forEach(function(a){++b.next,b.insert("append",a)}),b.maxIndex=b.eof?b.next-1:Math.max(b.next-1,b.maxIndex)},prepend:function(a){a.reverse().forEach(function(a){--b.first,b.insert("prepend",a)}),b.minIndex=b.bof?b.minIndex=b.first:Math.min(b.first,b.minIndex)},insert:function(a,c){var d={item:c};if(a%1===0)d.op="insert",b.splice(a,0,d);else switch(d.op=a,a){case"append":b.push(d);break;case"prepend":b.unshift(d)}},remove:function(a,c){if(angular.isNumber(a)){for(var d=a;c>d;d++)i(b[d]);return b.splice(a,c-a)}return b.splice(b.indexOf(a),1),k(a)},effectiveHeight:function(a){if(!a.length)return 0;var b=Number.MAX_VALUE,c=Number.MIN_VALUE;return a.forEach(function(a){a.element[0].offsetParent&&(b=Math.min(b,a.element.offset().top),c=Math.max(c,a.element.offset().top+a.element.outerHeight(!0)))}),Math.max(0,c-b)}}),b}function m(a,b,c,d){function e(){var a=Object.create(Array.prototype);return angular.extend(a,{add:function(b){for(var c=a.length-1;c>=0;c--)if(a[c].index===b.scope.$index)return void(a[c].height=b.element.outerHeight());a.push({index:b.scope.$index,height:b.element.outerHeight()})},clear:function(){a.length=0}}),a}function f(a){var b=void 0;switch(a.tagName){case"dl":throw new Error("ui-scroll directive does not support <"+a.tagName+"> as a repeating tag: "+a.outerHTML);case"tr":var c=angular.element("<table><tr><td><div></div></td></tr></table>");b=c.find("tr");break;case"li":b=angular.element("<li></li>");break;default:b=angular.element("<div></div>")}return b.cache=new e,b}function g(){return l.outerHeight()*d}var i=void 0,k=void 0,l=c&&c.viewport?c.viewport:angular.element(window),m=c&&c.container?c.container:void 0;return l.css({"overflow-y":"auto",display:"block"}),angular.extend(l,{createPaddingElements:function(a){i=new f(a),k=new f(a),b.before(i),b.after(k)},applyContainerStyle:function(){m&&m!==l&&l.css("height",window.getComputedStyle(m[0]).height)},bottomDataPos:function(){var a=l[0].scrollHeight;return a=null!=a?a:l[0].document.documentElement.scrollHeight,a-k.height()},topDataPos:function(){return i.height()},bottomVisiblePos:function(){return l.scrollTop()+l.outerHeight()},topVisiblePos:function(){return l.scrollTop()},insertElement:function(a,b){return h(a,b||i)},insertElementAnimated:function(a,b){return j(a,b||i)},shouldLoadBottom:function(){return!a.eof&&l.bottomDataPos()<l.bottomVisiblePos()+g()},clipBottom:function(){for(var b=0,c=0,d=0,e=l.bottomDataPos()-l.bottomVisiblePos()-g(),f=a.length-1;f>=0&&(d=a[f].element.outerHeight(!0),!(c+d>e));f--)k.cache.add(a[f]),c+=d,b++;b>0&&(a.eof=!1,a.remove(a.length-b,a.length),a.next-=b,l.adjustPadding())},shouldLoadTop:function(){return!a.bof&&l.topDataPos()>l.topVisiblePos()-g()},clipTop:function(){for(var b=0,c=0,d=0,e=l.topVisiblePos()-l.topDataPos()-g(),f=0;f<a.length&&(d=a[f].element.outerHeight(!0),!(c+d>e));f++)i.cache.add(a[f]),c+=d,b++;b>0&&(i.height(i.height()+c),a.bof=!1,a.remove(0,b),a.first+=b)},adjustPadding:function(){if(a.length){var b=i.cache.reduce(function(b,c){return b+(c.index<a.first?c.height:0)},0),c=k.cache.reduce(function(b,c){return b+(c.index>=a.next?c.height:0)},0),d=a.reduce(function(a,b){return a+b.element.outerHeight(!0)},0),e=(d+b+c)/(a.maxIndex-a.minIndex+1),f=null!==a.minIndexUser&&a.minIndex>a.minIndexUser,g=null!==a.maxIndexUser&&a.maxIndex<a.maxIndexUser,h=f?(a.minIndex-a.minIndexUser)*e:0,j=g?(a.maxIndexUser-a.maxIndex)*e:0;i.height(b+h),k.height(c+j)}},adjustScrollTopAfterMinIndexSet:function(b){if(null!==a.minIndexUser&&a.minIndex>a.minIndexUser){var c=i.height()-b;l.scrollTop(l.scrollTop()+c)}},adjustScrollTopAfterPrepend:function(b){if(b.prepended.length){var c=a.effectiveHeight(b.prepended),d=i.height()-c;d>=0?i.height(d):(i.height(0),l.scrollTop(l.scrollTop()-d))}},resetTopPadding:function(){i.height(0),i.cache.clear()},resetBottomPadding:function(){k.height(0),k.cache.clear()}}),l}function n(a,b,c,e,f){function h(b){var c=a[b],d=j,e=void 0;if(c){var h=c.match(/^(\S+)(?:\s+on\s+(\w(?:\w|\d)*))?/);if(!h)throw new Error("Expected injection expression in form of 'target' or 'target on controller' but got '"+c+"'");var i=h[1],k=h[2],m=function(a,b){for(var c=f;c.length;){var e=c.scope(),g=(c.attr("ng-controller")||"").match(/(\w(?:\w|\d)*)(?:\s+as\s+(\w(?:\w|\d)*))?/);if(g&&g[b?1:2]===a)return d=e,!0;if(!b&&e&&e.hasOwnProperty(a)&&Object.getPrototypeOf(e[a]).constructor.hasOwnProperty("$inject"))return d=e,!0;c=c.parent()}};if(k){if(d=null,m(k,!0),!d)throw new Error("Failed to locate target controller '"+k+"' to inject '"+i+"'")}else{var n=void 0,o=i.indexOf(".");o>0&&(n=i.substr(0,o),m(n,!1))}e=g(i).assign}return function(a){l!==a&&(l[b]=a),e&&e(d,a)}}function i(a,b){if(angular.isArray(b)){var d=void 0,e=c.indexOf(a)+1;b.reverse().forEach(function(b){b===a.item?(d=!0,e--):c.insert(e,b)}),d||(a.op="remove")}}var j=b.scope()||d,k=!1,l=this;h("adapter")(l);var m=h("topVisible"),n=h("topVisibleElement"),o=h("topVisibleScope"),p=h("isLoading");Object.defineProperty(this,"disabled",{get:function(){return k},set:function(a){return(k=a)?null:e()}}),this.isLoading=!1,this.isBOF=function(){return c.bof},this.isEOF=function(){return c.eof},this.applyUpdates=function(a,b){if(angular.isFunction(a))c.slice(0).forEach(function(b){i(b,a(b.item,b.scope,b.element))});else{if(a%1!==0)throw new Error("applyUpdates - "+a+" is not a valid index");var d=a-c.first;d>=0&&d<c.length&&i(c[d],b)}e()},this.append=function(a){c.append(a),e()},this.prepend=function(a){c.prepend(a),e()},this.loading=function(a){p(a)},this.calculateProperties=function(){for(var a=void 0,d=void 0,e=void 0,f=void 0,g=void 0,h=0,i=0;i<c.length;i++){if(a=c[i],e=a.element.offset().top,f=g!==e,g=e,f&&(d=a.element.outerHeight(!0)),!(f&&b.topDataPos()+h+d<=b.topVisiblePos())){f&&(m(a.item),n(a.element),o(a.scope));break}h+=d}}}function o(a,b,h,i,j){function k(b,c){var d=g(b)(a);return isNaN(d)?c:d}function o(a,b,c){var d=Object.getOwnPropertyDescriptor(a,b);d&&(d.set||d.get)||Object.defineProperty(a,b,{set:function(a){X[b]=a,e(function(){if(T[c]=a,!S.length){var d=U.topDataPos();U.adjustPadding(),"minIndex"===b&&U.adjustScrollTopAfterMinIndexSet(d)}})},get:function(){return X[b]}})}function p(b){return b&&b!==R||a.$$destroyed}function q(){U.bind("resize",D),U.bind("scroll",D)}function r(){U.unbind("resize",D),U.unbind("scroll",D)}function s(){U.resetTopPadding(),U.resetBottomPadding(),arguments.length&&(Q=arguments[0]),T.reset(Q),A()}function t(a){return a.element.height()&&a.element[0].offsetParent}function u(a){t(a)&&(T.forEach(function(a){angular.isFunction(a.unregisterVisibilityWatcher)&&(a.unregisterVisibilityWatcher(),delete a.unregisterVisibilityWatcher)}),A())}function v(a,b){w(a,b,U.insertElement),t(a)||(a.unregisterVisibilityWatcher=a.scope.$watch(function(){return u(a)})),a.element.addClass("ng-hide")}function w(a,b,c){var d=void 0,e=b>0?T[b-1].element:void 0;return j(function(b,f){d=c(b,e),a.element=b,a.scope=f,f[L]=a.item}),V.transform&&V.transform(a.scope,a.element),d}function x(){var a=[],b=[],c=[],d=[];return T.forEach(function(e,f){switch(e.op){case"prepend":b.unshift(e);break;case"append":v(e,f),e.op="none",d.push(e);break;case"insert":a=a.concat(w(e,f,U.insertElementAnimated)),e.op="none",d.push(e);break;case"remove":c.push(e)}}),c.forEach(function(b){return a=a.concat(T.remove(b))}),b.length&&b.forEach(function(a){v(a),a.op="none"}),T.forEach(function(a,b){return a.scope.$index=T.first+b}),{prepended:b,removed:c,inserted:d,animated:a}}function y(a,b){b.animated.length?f.all(b.animated).then(function(){U.adjustPadding(),A(a)}):U.adjustPadding()}function z(a,b){U.shouldLoadBottom()?(!b||T.effectiveHeight(b.inserted)>0)&&1===S.push(!0)&&(C(a),V.loading(!0)):U.shouldLoadTop()&&(!b||T.effectiveHeight(b.prepended)>0||S[0])&&1===S.push(!1)&&(C(a),V.loading(!0))}function A(a){a||(S=[],a=++R);var b=x();e(function(){b.inserted.forEach(function(a){return a.element.removeClass("ng-hide")}),b.prepended.forEach(function(a){return a.element.removeClass("ng-hide")}),p(a)||(y(a,b),z(a),S.length||V.calculateProperties())})}function B(a){var b=x();e(function(){b.inserted.forEach(function(a){return a.element.removeClass("ng-hide")}),b.prepended.forEach(function(a){return a.element.removeClass("ng-hide")}),U.adjustScrollTopAfterPrepend(b),p(a)||(y(a,b),z(a,b),S.shift(),S.length?C(a):(V.loading(!1),q(),V.calculateProperties()))})}function C(a){S[0]?T.length&&!U.shouldLoadBottom()?B(a):Y(function(b){p(a)||(b.length<O&&(T.eof=!0),b.length>0&&(U.clipTop(),T.append(b)),B(a))}):T.length&&!U.shouldLoadTop()?B(a):Z(function(b){p(a)||(b.length<O&&(T.bof=!0),b.length>0&&(T.length&&U.clipBottom(),T.prepend(b)),B(a))})}function D(){d.$$phase||V.isLoading||V.disabled||(z(R),S.length?r():(V.calculateProperties(),a.$apply()))}function E(a){if(!V.disabled){var b=U[0].scrollTop,c=U[0].scrollHeight-U[0].clientHeight;(0===b&&!T.bof||b===c&&!T.eof)&&a.preventDefault()}}var F=h.uiScroll.match(/^\s*(\w+)\s+in\s+([(\w|\$)\.]+)\s*$/);if(!F)throw new Error("Expected uiScroll in form of '_item_ in _datasource_' but got '"+h.uiScroll+"'");var G=3,H=10,I=.3,J=.5,K=null,L=F[1],M=F[2],N=i[0],O=Math.max(G,k(h.bufferSize,H)),P=Math.max(I,k(h.padding,J)),Q=k(h.startIndex,1),R=0,S=[],T=new l(O),U=new m(T,b,N,P),V=new n(h,U,T,A,b);N&&(N.adapter=V);var W=function(){return angular.isObject(K)&&angular.isFunction(K.get)};if(K=g(M)(a),!W()&&(K=c.get(M),!W()))throw new Error(M+" is not a valid datasource");var X={};o(K,"minIndex","minIndexUser"),o(K,"maxIndex","maxIndexUser");var Y=2!==K.get.length?function(a){return K.get(T.next,O,a)}:function(a){K.get({index:T.next,append:T.length?T[T.length-1].item:void 0,count:O},a)},Z=2!==K.get.length?function(a){return K.get(T.first-O,O,a)}:function(a){K.get({index:T.first-O,prepend:T.length?T[0].item:void 0,count:O},a)};V.reload=s,j(function(a,b){U.createPaddingElements(a[0]),b.$destroy(),a.remove()}),a.$on("$destroy",function(){r(),U.unbind("mousewheel",E)}),U.bind("mousewheel",E),e(function(){U.applyContainerStyle(),s()})}var p=c.has&&c.has("$animate")?c.get("$animate"):null,q=1===angular.version.major&&angular.version.minor<3;return{require:["?^^uiScrollViewport"],restrict:"A",transclude:"element",priority:1e3,terminal:!0,link:o}}])}(); |
{ | ||
"name": "angular-ui-scroll", | ||
"description": "two way infinite scroll", | ||
"version": "1.5.1", | ||
"version": "1.5.2", | ||
"src": "./src/", | ||
@@ -6,0 +6,0 @@ "public": "./public/", |
@@ -11,3 +11,3 @@ The common way to present to the user a list of data elements of undefined length is to start with a small portion at the top of the | ||
uiScroll directive | ||
------------------- | ||
------------------- | ||
@@ -49,3 +49,3 @@ [![Build Status](https://travis-ci.org/angular-ui/ui-scroll.svg?branch=master)](https://travis-ci.org/angular-ui/ui-scroll) [![npm version](https://badge.fury.io/js/angular-ui-scroll.svg)](http://badge.fury.io/js/angular-ui-scroll) [![Bower version](https://badge.fury.io/bo/angular-ui-scroll.svg)](http://badge.fury.io/bo/angular-ui-scroll) [![Join the chat at https://gitter.im/angular-ui/ui-scroll](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular-ui/ui-scroll?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
```html | ||
<ANY ui-scroll="{scroll_expression}" buffer-size="value" padding="value" start-index="value" adapter="name"> | ||
<ANY ui-scroll="{scroll_expression}" buffer-size="value" padding="value" start-index="value" adapter="expression"> | ||
... | ||
@@ -72,21 +72,24 @@ </ANY> | ||
###Parameters | ||
* **uiScroll – {scroll_expression}** – The expression indicating how to enumerate a collection. Only one format is currently supported: | ||
* **variable in datasource** – where variable is the user defined loop variable and datasource is the name of the data source service to enumerate. | ||
* **buffer-size - value**, optional - number of items requested from the datasource in a single request. The default is 10 and the minimal value is 3 | ||
* **padding - value**, optional - extra height added to the visible area for the purpose of determining when the items should be created/destroyed. | ||
The value is relative to the visible height of the area, the default is 0.5 and the minimal value is 0.3 | ||
* **start-index - value**, optional - index of the first item to be requested from the datasource. The default is 1. | ||
* **adapter - expression**, optional - if provided a reference to the adapter object for the scroller instance will be injected in the appropriate scope. If you have multiple scrollers within the same viewport, make sure that every one of them has its unique adapter name. | ||
* **uiScroll – scroll expression** – The expression indicating how to enumerate a collection. Only one format is currently supported: | ||
* **variable in datasource** – where variable is the user defined loop variable and datasource is the name of the data source to enumerate. | ||
* **buffer-size - expression**, optional - number of items requested from the datasource in a single request. The default is 10 and the minimal value is 3 | ||
* **padding - expression**, optional - extra height added to the visible area for the purpose of determining when the items should be created/destroyed. The value is relative to the visible height of the area, the default is 0.5 and the minimal value is 0.3 | ||
* **start-index - expression**, optional - index of the first item to be requested from the datasource. The default is 1. | ||
* **adapter - assignable expression**, optional - if provided a reference to the adapter object for the scroller instance will be injected in the appropriate scope. If you have multiple scrollers within the same viewport, make sure that every one of them has its unique adapter name. | ||
Some of the properties offered by the adapter can also be accessed directly from the directive by using matching attributes. In the same way as for the adapter attribute, syntax for such attributes allows for providing an expression to be used to access the corresponding value. Below is a list of such attributes: | ||
Some of the properties offered by the adapter can also be accessed directly from the directive by using matching attributes. In the same way as for the adapter attribute, syntax for such attributes allows for providing a reference expression to be used to access the corresponding value. Below is a list of such attributes: | ||
* **is-loading - expression**, optional - a boolean value indicating whether there are any pending load requests will be injected in the appropriate scope. See also `isLoading` adapter property. | ||
* **top-visible - expression**, optional - a reference to the item currently in the topmost visible position will be injected in the appropriate scope. See also `topVisible` adapter property. | ||
* **top-visible-element - expression**, optional - a reference to the DOM element currently in the topmost visible position will be injected in the appropriate scope. See also `topVisibleElement` adapter property. | ||
* **top-visible-scope - expression**, optional - a reference to the scope created for the item currently in the topmost visible position will be injected in the appropriate scope. See also `topVisibleScope` adapter property. | ||
* **is-loading - assignable expression**, optional - a boolean value indicating whether there are any pending load requests will be injected in the appropriate scope. See also `isLoading` adapter property. | ||
* **top-visible - assignable expression**, optional - a reference to the item currently in the topmost visible position will be injected in the appropriate scope. See also `topVisible` adapter property. | ||
* **top-visible-element - assignable expression**, optional - a reference to the DOM element currently in the topmost visible position will be injected in the appropriate scope. See also `topVisibleElement` adapter property. | ||
* **top-visible-scope - assignable expression**, optional - a reference to the scope created for the item currently in the topmost visible position will be injected in the appropriate scope. See also `topVisibleScope` adapter property. | ||
The `expression` can be any angular assignable expression. The scroller will inject the requested value into the target scope by applying the target expression. The scope associated with the viewport (the element marked with the [uiScrollViewport](#uiscrollviewport-directive) directive) will be used as the target scope. If the viewport is not defined (window viewport), the $rootScope will be used as the target scope. | ||
The `expression` can be any angular expression (assignable expression where so specified). All expressions are evaluated once at the time when the scroller is initalized. Changes in the expresion value after scroller intialization will have no impact on the scroller behavior. | ||
The second format `expression on controller` can be used to explicitly specify the scope associated with the specified controller as the target scope for the injection. In this format `expression` is any angular assignable expression, and `controller` is the name of controller constructor function as specified in the `ng-controller` directive. The scroller will traverse its parents to locate the target scope associated with the specified controller. | ||
The assignable expressions will be used by scroller to inject the requested value into the target scope. The scope associated with the viewport (the element marked with the [uiScrollViewport](#uiscrollviewport-directive) directive) will be used as the target scope. If the viewport is not defined (window viewport), the $rootScope will be used as the target scope. Note that the nearest additional scope-wrapper (like ng-if directive set right on the viewport) makes this mechanism unusable. There are two options which help in this case: | ||
1. The second format `expression on controller` can be used to explicitly target the scope associated with the specified controller as the target scope for the injection. In this format `expression` is any angular assignable expression, and `controller` is the name of controller constructor function as specified in the `ng-controller` directive. The scroller will traverse its parents to locate the target scope associated with the specified controller. | ||
2. Also `Controller As` syntax could be used as an alternative way to specify target controller in assignable expressions. | ||
###Data Source | ||
@@ -122,5 +125,5 @@ Data source is an object to be used by the uiScroll directive to access the data. | ||
As the scroller recieves the items requested by the `get` method, the value of minimum and maximum values of the item index are placed in the `minIndex` and `maxIndex` properties respectively. The values of the properties are cumulative - the value of the `minIndex` will never increase, and the value of the `maxIndex` will never decrease - except the values are reset in response to a call to the adapter `reload` method. The values of the properties are used to maintain the appearance of the scroller scrollBar. | ||
Values of the properties can be assigned programmatically. If the range of the index values is known in advance, assigneing them programmatically would improve the usability of the scrollBar. | ||
Values of the properties can be assigned programmatically. If the range of the index values is known in advance, assigneing them programmatically would improve the usability of the scrollBar. | ||
###Adapter | ||
@@ -139,4 +142,18 @@ The adapter object is an internal object created for every instance of the scroller. Properties and methods of the adapter can be used to manipulate and assess the scroller the adapter was created for. Adapter based API replaces old (undocumented) event based API introduced earlier for this purpose. The event based API is now deprecated and no longer supported. | ||
* Method `reload` | ||
* Method `isBOF` | ||
isBOF() | ||
#### Description | ||
returns `true` if the first item of the dataset is already in the buffer. No further requests for preceding items will be issued, returns `false` otherwise. | ||
* Method `isEOF` | ||
isEOF() | ||
#### Description | ||
returns `true` if the last item of the dataset is already in the buffer. No further requests for tailing items will be issued, returns `false` otherwise, | ||
* Method `reload` | ||
reload() | ||
@@ -149,7 +166,7 @@ or | ||
Calling this method reinitializes and reloads the scroller content. `startIndex` is an integer indicating what item index the scroller will use to start the load process. The value of the argument replaces the value provided with the start-index attribute. Calling `reload()` is equivalent to calling `reload` method with current value of the `start-index` attribute . | ||
**important: `startIndex` should fall within underlying datset boundaries** The scroller will request two batches of items one starting from the `startIndex` and another one preceding the first one (starting from `startIndex - bufferSize`). If both requests come back empty, the scroller will consider the dataset to be empty and will place no further data requests. | ||
* Method `applyUpdates` | ||
**important: `startIndex` should fall within underlying datset boundaries** The scroller will request two batches of items one starting from the `startIndex` and another one preceding the first one (starting from `startIndex - bufferSize`). If both requests come back empty, the scroller will consider the dataset to be empty and will place no further data requests. | ||
* Method `applyUpdates` | ||
applyUpdates(index, newItems) | ||
@@ -173,3 +190,3 @@ #### Description | ||
#### Description | ||
Adds new items after the last item in the buffer. | ||
Adds new items after the last item in the buffer. | ||
#### Parameters | ||
@@ -179,3 +196,3 @@ * **newItems** provides an array of items to be appended. | ||
* Method `prepend` | ||
prepend(newItems) | ||
@@ -186,3 +203,3 @@ #### Description | ||
* **newItems** provides an array of items to be prepended. | ||
####Manipulating the scroller content with adapter methods | ||
@@ -220,3 +237,3 @@ | ||
The uiScrollTh and uiScrollTd directives provide a way to build flexible dynamic grids. Handling of grid rows is done by the uiScroll directive itself. In addition to this uiScrollTh and uiScrollTd directive provide tools to programmatically change grid layout, inclduing applying styles to columns, changing column size and order, as well as saving the modifications to the layout and applying previosly saved layouts. | ||
The uiScrollTh and uiScrollTd directives provide a way to build flexible dynamic grids. Handling of grid rows is done by the uiScroll directive itself. In addition to this uiScrollTh and uiScrollTd directive provide tools to programmatically change grid layout, inclduing applying styles to columns, changing column size and order, as well as saving the modifications to the layout and applying previosly saved layouts. | ||
At this point the above functionality is supported only for table based scrollable grids. | ||
@@ -248,7 +265,7 @@ | ||
The grid directives have the same dependency requirements as the uiScroll directive itself. To use the directives make sure the `ui.scroll.grid` module is on the list of the module dependencies. Also you have to load the dist/ui-scroll-grid.js file in your page. | ||
The grid directives have the same dependency requirements as the uiScroll directive itself. To use the directives make sure the `ui.scroll.grid` module is on the list of the module dependencies. Also you have to load the dist/ui-scroll-grid.js file in your page. | ||
### Controlling scrollable grid with the GridAdapter | ||
GridAdapter object (along with ColumnAdapter objects) provides methods and properties to be used to change the scrollable grid layout. A reference to this object is injected as a property named `gridAdapter`in the scroller adapter. | ||
GridAdapter object (along with ColumnAdapter objects) provides methods and properties to be used to change the scrollable grid layout. A reference to this object is injected as a property named `gridAdapter`in the scroller adapter. | ||
@@ -273,3 +290,3 @@ `GridAdapter` object implements the following properties: | ||
Examples ([look here for sources](https://github.com/angular-ui/ui-scroll/tree/master/demo/examples)) consist of several pages (.html files) showing various ways to use the ui-scroll directive. Each page relays on its own datasource service (called `datasource`) defined in the javascript file with the same name and .js extension. | ||
Examples ([look here for sources](https://github.com/angular-ui/ui-scroll/tree/master/demo)) consist of several pages (.html files) showing various ways to use the ui-scroll directive. Each page relays on its own datasource service (called `datasource`) defined in the javascript file with the same name and .js extension. | ||
@@ -283,2 +300,6 @@ I intentionally broke every rule of proper html/css structure (i.e. embedded styles). This is done to keep the html as bare bones as possible and leave | ||
###v1.5.2 | ||
* Refactored assignable expressions and attributes scope bindings. | ||
* Added new demos and tests. fixed IE compatibility. | ||
###v1.5.1 | ||
@@ -339,2 +360,1 @@ * Refactored adjustments during elements append/prepend. | ||
* Fixed the problem occurring if the scroller is $destroyed while there are requests pending: [#64](https://github.com/Hill30/NGScroller/issues/64). | ||
@@ -200,5 +200,3 @@ /*! | ||
function Viewport(buffer, element, viewportController, attrs) { | ||
const PADDING_MIN = 0.3; | ||
const PADDING_DEFAULT = 0.5; | ||
function Viewport(buffer, element, viewportController, padding) { | ||
let topPadding; | ||
@@ -219,6 +217,7 @@ let bottomPadding; | ||
add(item) { | ||
let existedItem = cache.find(i => i.index === item.scope.$index); | ||
if (existedItem) { | ||
existedItem.height = item.element.outerHeight(); | ||
return; | ||
for(let i = cache.length - 1; i >= 0; i--) { | ||
if(cache[i].index === item.scope.$index) { | ||
cache[i].height = item.element.outerHeight(); | ||
return; | ||
} | ||
} | ||
@@ -261,3 +260,3 @@ cache.push({ | ||
function bufferPadding() { | ||
return viewport.outerHeight() * Math.max(PADDING_MIN, +attrs.padding || PADDING_DEFAULT); // some extra space to initiate preload | ||
return viewport.outerHeight() * padding; // some extra space to initiate preload | ||
} | ||
@@ -423,3 +422,3 @@ | ||
function Adapter($attr, viewport, buffer, adjustBuffer) { | ||
function Adapter($attr, viewport, buffer, adjustBuffer, element) { | ||
const viewportScope = viewport.scope() || $rootScope; | ||
@@ -514,21 +513,45 @@ let disabled = false; | ||
if (expression) { | ||
let match = expression.match(/^(\S+)(?:\s+on\s+(\w(?:\w|\d)*))?$/); | ||
// it is ok to have relaxed validation for the first part of the 'on' expression. | ||
// additional validation will be done by the $parse service below | ||
let match = expression.match(/^(\S+)(?:\s+on\s+(\w(?:\w|\d)*))?/); | ||
if (!match) | ||
throw new Error('Expected injection expression in form of \'target\' or \'target on controller\' but got \'' + expression + '\''); | ||
let target = match[1]; | ||
let controllerName = match[2]; | ||
if (controllerName) { | ||
let candidate = viewport; | ||
scope = undefined; | ||
let onControllerName = match[2]; | ||
let parseController = (controllerName, on) => { | ||
let candidate = element; | ||
while (candidate.length) { | ||
let controller = candidate.attr('ng-controller'); | ||
if (controller === controllerName) { | ||
scope = candidate.scope(); | ||
break; | ||
let candidateScope = candidate.scope(); | ||
// ng-controller's "Controller As" parsing | ||
let candidateName = (candidate.attr('ng-controller') || '').match(/(\w(?:\w|\d)*)(?:\s+as\s+(\w(?:\w|\d)*))?/); | ||
if (candidateName && candidateName[on ? 1 : 2] === controllerName) { | ||
scope = candidateScope; | ||
return true; | ||
} | ||
// directive's/component's "Controller As" parsing | ||
if (!on && candidateScope && candidateScope.hasOwnProperty(controllerName) && Object.getPrototypeOf(candidateScope[controllerName]).constructor.hasOwnProperty('$inject')) { | ||
scope = candidateScope; | ||
return true; | ||
} | ||
candidate = candidate.parent(); | ||
} | ||
if (!scope) | ||
throw new Error('Failed to locate target controller \'' + controllerName + '\' to inject \'' + target + '\''); | ||
}; | ||
if (onControllerName) { // 'on' syntax DOM parsing (adapter="adapter on ctrl") | ||
scope = null; | ||
parseController(onControllerName, true); | ||
if (!scope) { | ||
throw new Error('Failed to locate target controller \'' + onControllerName + '\' to inject \'' + target + '\''); | ||
} | ||
} | ||
else { // try to parse DOM with 'Controller As' syntax (adapter="ctrl.adapter") | ||
let controllerAsName; | ||
let dotIndex = target.indexOf('.'); | ||
if(dotIndex > 0) { | ||
controllerAsName = target.substr(0, dotIndex); | ||
parseController(controllerAsName, false); | ||
} | ||
} | ||
assign = $parse(target).assign; | ||
@@ -571,13 +594,23 @@ } | ||
const match = $attr.uiScroll.match(/^\s*(\w+)\s+in\s+([(\w|\$)\.]+)\s*$/); | ||
if (!(match)) | ||
if (!match) { | ||
throw new Error('Expected uiScroll in form of \'_item_ in _datasource_\' but got \'' + $attr.uiScroll + '\''); | ||
} | ||
function parseNumericAttr(value, defaultValue) { | ||
let result = $parse(value)($scope); | ||
return isNaN(result) ? defaultValue : result; | ||
} | ||
const BUFFER_MIN = 3; | ||
const BUFFER_DEFAULT = 10; | ||
const PADDING_MIN = 0.3; | ||
const PADDING_DEFAULT = 0.5; | ||
let datasource = null; | ||
const itemName = match[1]; | ||
const datasourceName = match[2]; | ||
const bufferSize = Math.max(3, +$attr.bufferSize || 10); | ||
const viewportController = controllers[0]; | ||
let startIndex = parseInt($attr.startIndex, 10); | ||
startIndex = isNaN(startIndex) ? 1 : startIndex; | ||
const bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT)); | ||
const padding = Math.max(PADDING_MIN, parseNumericAttr($attr.padding, PADDING_DEFAULT)); | ||
let startIndex = parseNumericAttr($attr.startIndex, 1); | ||
let ridActual = 0;// current data revision id | ||
@@ -587,4 +620,4 @@ let pending = []; | ||
let buffer = new Buffer(bufferSize); | ||
let viewport = new Viewport(buffer, element, viewportController, $attr); | ||
let adapter = new Adapter($attr, viewport, buffer, adjustBuffer); | ||
let viewport = new Viewport(buffer, element, viewportController, padding); | ||
let adapter = new Adapter($attr, viewport, buffer, adjustBuffer, element); | ||
if (viewportController) | ||
@@ -591,0 +624,0 @@ viewportController.adapter = adapter; |
@@ -31,9 +31,7 @@ 'use strict'; | ||
left: ['scrollLeft', 'pageXOffset', 'scrollTop'] | ||
}[direction], 3); | ||
}[direction], 3), | ||
method = _top$left$direction[0], | ||
prop = _top$left$direction[1], | ||
preserve = _top$left$direction[2]; | ||
var method = _top$left$direction[0]; | ||
var prop = _top$left$direction[1]; | ||
var preserve = _top$left$direction[2]; | ||
if (isWindow(elem)) { | ||
@@ -40,0 +38,0 @@ if (angular.isDefined(value)) { |
'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
@@ -203,5 +203,3 @@ /*! | ||
function Viewport(buffer, element, viewportController, attrs) { | ||
var PADDING_MIN = 0.3; | ||
var PADDING_DEFAULT = 0.5; | ||
function Viewport(buffer, element, viewportController, padding) { | ||
var topPadding = void 0; | ||
@@ -222,8 +220,7 @@ var bottomPadding = void 0; | ||
add: function add(item) { | ||
var existedItem = cache.find(function (i) { | ||
return i.index === item.scope.$index; | ||
}); | ||
if (existedItem) { | ||
existedItem.height = item.element.outerHeight(); | ||
return; | ||
for (var i = cache.length - 1; i >= 0; i--) { | ||
if (cache[i].index === item.scope.$index) { | ||
cache[i].height = item.element.outerHeight(); | ||
return; | ||
} | ||
} | ||
@@ -266,3 +263,3 @@ cache.push({ | ||
function bufferPadding() { | ||
return viewport.outerHeight() * Math.max(PADDING_MIN, +attrs.padding || PADDING_DEFAULT); // some extra space to initiate preload | ||
return viewport.outerHeight() * padding; // some extra space to initiate preload | ||
} | ||
@@ -414,3 +411,3 @@ | ||
function Adapter($attr, viewport, buffer, adjustBuffer) { | ||
function Adapter($attr, viewport, buffer, adjustBuffer, element) { | ||
var viewportScope = viewport.scope() || $rootScope; | ||
@@ -518,19 +515,45 @@ var disabled = false; | ||
if (expression) { | ||
var match = expression.match(/^(\S+)(?:\s+on\s+(\w(?:\w|\d)*))?$/); | ||
// it is ok to have relaxed validation for the first part of the 'on' expression. | ||
// additional validation will be done by the $parse service below | ||
var match = expression.match(/^(\S+)(?:\s+on\s+(\w(?:\w|\d)*))?/); | ||
if (!match) throw new Error('Expected injection expression in form of \'target\' or \'target on controller\' but got \'' + expression + '\''); | ||
var target = match[1]; | ||
var controllerName = match[2]; | ||
if (controllerName) { | ||
var candidate = viewport; | ||
scope = undefined; | ||
var onControllerName = match[2]; | ||
var parseController = function parseController(controllerName, on) { | ||
var candidate = element; | ||
while (candidate.length) { | ||
var controller = candidate.attr('ng-controller'); | ||
if (controller === controllerName) { | ||
scope = candidate.scope(); | ||
break; | ||
var candidateScope = candidate.scope(); | ||
// ng-controller's "Controller As" parsing | ||
var candidateName = (candidate.attr('ng-controller') || '').match(/(\w(?:\w|\d)*)(?:\s+as\s+(\w(?:\w|\d)*))?/); | ||
if (candidateName && candidateName[on ? 1 : 2] === controllerName) { | ||
scope = candidateScope; | ||
return true; | ||
} | ||
// directive's/component's "Controller As" parsing | ||
if (!on && candidateScope && candidateScope.hasOwnProperty(controllerName) && Object.getPrototypeOf(candidateScope[controllerName]).constructor.hasOwnProperty('$inject')) { | ||
scope = candidateScope; | ||
return true; | ||
} | ||
candidate = candidate.parent(); | ||
} | ||
if (!scope) throw new Error('Failed to locate target controller \'' + controllerName + '\' to inject \'' + target + '\''); | ||
}; | ||
if (onControllerName) { | ||
// 'on' syntax DOM parsing (adapter="adapter on ctrl") | ||
scope = null; | ||
parseController(onControllerName, true); | ||
if (!scope) { | ||
throw new Error('Failed to locate target controller \'' + onControllerName + '\' to inject \'' + target + '\''); | ||
} | ||
} else { | ||
// try to parse DOM with 'Controller As' syntax (adapter="ctrl.adapter") | ||
var controllerAsName = void 0; | ||
var dotIndex = target.indexOf('.'); | ||
if (dotIndex > 0) { | ||
controllerAsName = target.substr(0, dotIndex); | ||
parseController(controllerAsName, false); | ||
} | ||
} | ||
assign = $parse(target).assign; | ||
@@ -571,12 +594,23 @@ } | ||
var match = $attr.uiScroll.match(/^\s*(\w+)\s+in\s+([(\w|\$)\.]+)\s*$/); | ||
if (!match) { | ||
throw new Error('Expected uiScroll in form of \'_item_ in _datasource_\' but got \'' + $attr.uiScroll + '\''); | ||
} | ||
if (!match) throw new Error('Expected uiScroll in form of \'_item_ in _datasource_\' but got \'' + $attr.uiScroll + '\''); | ||
function parseNumericAttr(value, defaultValue) { | ||
var result = $parse(value)($scope); | ||
return isNaN(result) ? defaultValue : result; | ||
} | ||
var BUFFER_MIN = 3; | ||
var BUFFER_DEFAULT = 10; | ||
var PADDING_MIN = 0.3; | ||
var PADDING_DEFAULT = 0.5; | ||
var datasource = null; | ||
var itemName = match[1]; | ||
var datasourceName = match[2]; | ||
var bufferSize = Math.max(3, +$attr.bufferSize || 10); | ||
var viewportController = controllers[0]; | ||
var startIndex = parseInt($attr.startIndex, 10); | ||
startIndex = isNaN(startIndex) ? 1 : startIndex; | ||
var bufferSize = Math.max(BUFFER_MIN, parseNumericAttr($attr.bufferSize, BUFFER_DEFAULT)); | ||
var padding = Math.max(PADDING_MIN, parseNumericAttr($attr.padding, PADDING_DEFAULT)); | ||
var startIndex = parseNumericAttr($attr.startIndex, 1); | ||
var ridActual = 0; // current data revision id | ||
@@ -586,4 +620,4 @@ var pending = []; | ||
var buffer = new Buffer(bufferSize); | ||
var viewport = new Viewport(buffer, element, viewportController, $attr); | ||
var adapter = new Adapter($attr, viewport, buffer, adjustBuffer); | ||
var viewport = new Viewport(buffer, element, viewportController, padding); | ||
var adapter = new Adapter($attr, viewport, buffer, adjustBuffer, element); | ||
if (viewportController) viewportController.adapter = adapter; | ||
@@ -590,0 +624,0 @@ |
@@ -810,2 +810,34 @@ /*global describe, beforeEach, module, inject, it, spyOn, expect, runTest */ | ||
describe('attributes scope binding', function () { | ||
var calls = null; | ||
var bufferSize = 5; | ||
it('bufferSize scope binding should work (1)', function () { | ||
inject(function (myInfiniteDatasource) { | ||
var spy = spyOn(myInfiniteDatasource, 'get').and.callThrough(); | ||
runTest({datasource: 'myInfiniteDatasource', bufferSize: bufferSize}, | ||
function () { | ||
calls = spy.calls.all().length; | ||
expect(calls > 0).toBe(true); | ||
} | ||
); | ||
}); | ||
}); | ||
it('bufferSize scope binding should work (2)', function () { | ||
inject(function (myInfiniteDatasource) { | ||
var spy = spyOn(myInfiniteDatasource, 'get').and.callThrough(); | ||
runTest({datasource: 'myInfiniteDatasource', bufferSize: 'start'}, | ||
function () { | ||
expect(spy.calls.all().length).toBe(calls); | ||
}, { | ||
scope: { | ||
'start': bufferSize | ||
} | ||
} | ||
); | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -1,2 +0,2 @@ | ||
var createHtml = function (settings) { | ||
function createHtml (settings) { | ||
var viewportStyle = ' style="height:' + (settings.viewportHeight || 200) + 'px"'; | ||
@@ -17,34 +17,5 @@ var itemStyle = settings.itemHeight ? ' style="height:' + settings.itemHeight + 'px"' : ''; | ||
'</div>'; | ||
}; | ||
} | ||
var runTest = function (scrollSettings, run, options) { | ||
inject(function ($rootScope, $compile, $window, $timeout) { | ||
var scroller = angular.element(createHtml(scrollSettings)); | ||
var scope = $rootScope.$new(); | ||
//if (angular.element(document).find('body').find('div').children().length) | ||
//debugger | ||
angular.element(document).find('body').append(scroller); | ||
$compile(scroller)(scope); | ||
scope.$apply(); | ||
$timeout.flush(); | ||
try { | ||
run(scroller, scope, $timeout); | ||
} | ||
finally { | ||
scroller.remove(); | ||
if (options && typeof options.cleanupTest === 'function') { | ||
options.cleanupTest(scroller, scope, $timeout); | ||
} | ||
} | ||
}); | ||
}; | ||
var createGridHtml = function (settings) { | ||
function createGridHtml (settings) { | ||
var viewportStyle = ' style="height:' + (settings.viewportHeight || 200) + 'px"'; | ||
@@ -71,13 +42,43 @@ var columns = ['col0', 'col1', 'col2', 'col3']; | ||
return html; | ||
} | ||
}; | ||
function finalize (scroller, options, scope, $timeout) { | ||
scroller.remove(); | ||
var runGridTest = function (scrollSettings, run, options) { | ||
if (options && typeof options.cleanupTest === 'function') { | ||
options.cleanupTest(scroller, scope, $timeout); | ||
} | ||
} | ||
function runTest (scrollSettings, run, options) { | ||
inject(function ($rootScope, $compile, $window, $timeout) { | ||
var scroller = angular.element(createHtml(scrollSettings)); | ||
var scope = $rootScope.$new(); | ||
angular.element(document).find('body').append(scroller); | ||
if(options && options.scope) { | ||
angular.extend(scope, options.scope); | ||
} | ||
$compile(scroller)(scope); | ||
scope.$apply(); | ||
$timeout.flush(); | ||
try { | ||
run(scroller, scope, $timeout); | ||
} | ||
finally { | ||
finalize(scroller, options, scope, $timeout); | ||
} | ||
}); | ||
} | ||
function runGridTest (scrollSettings, run, options) { | ||
inject(function ($rootScope, $compile, $window, $timeout) { | ||
var scroller = angular.element(createGridHtml(scrollSettings)); | ||
var scope = $rootScope.$new(); | ||
//if (angular.element(document).find('body').find('div').children().length) | ||
//debugger | ||
angular.element(document).find('body').append(scroller); | ||
@@ -95,7 +96,3 @@ var head = angular.element(scroller.children()[0]); | ||
} finally { | ||
scroller.remove(); | ||
if (options && typeof options.cleanupTest === 'function') { | ||
options.cleanupTest(scroller, scope, $timeout); | ||
} | ||
finalize(scroller, options, scope, $timeout); | ||
} | ||
@@ -105,3 +102,2 @@ | ||
); | ||
}; | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
697682
142
18651
347