summaryrefslogtreecommitdiffstats
path: root/catalog-ui/app/third-party
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/app/third-party')
-rw-r--r--catalog-ui/app/third-party/PunchOutRegistry.js98
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/.npmignore3
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/.travis.yml12
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/Gruntfile.coffee110
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/LICENSE22
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/README.md71
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/bower.json16
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/build/ng-infinite-scroll.js209
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/build/ng-infinite-scroll.min.js22
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/package.json80
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/src/infinite-scroll.coffee209
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-local.conf.js27
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-shared.conf.js26
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-travis.conf.js32
-rw-r--r--catalog-ui/app/third-party/ng-infinite-scroll/test/spec/ng-infinite-scroll.spec.coffee221
15 files changed, 1158 insertions, 0 deletions
diff --git a/catalog-ui/app/third-party/PunchOutRegistry.js b/catalog-ui/app/third-party/PunchOutRegistry.js
new file mode 100644
index 0000000000..bc93453dc1
--- /dev/null
+++ b/catalog-ui/app/third-party/PunchOutRegistry.js
@@ -0,0 +1,98 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+(function(window) {
+ "use strict";
+
+ if (window.PunchOutRegistry) {
+ return;
+ }
+
+ var queuedFactoryRequests = new Map();
+ var factoryPromises = new Map();
+ var instancePromises = new Map();
+
+ function registerFactory(name, factory) {
+ if (factoryPromises.has(name) && !queuedFactoryRequests.has(name)) {
+ console.error("PunchOut \"" + name + "\" has been already registered");
+ return;
+ }
+ if (queuedFactoryRequests.has(name)) {
+ var factoryRequest = queuedFactoryRequests.get(name);
+ factoryRequest(factory);
+ queuedFactoryRequests.delete(name);
+ } else {
+ factoryPromises.set(name, Promise.resolve(factory));
+ }
+ }
+
+ function getFactoryPromise(name) {
+ var factoryPromise = factoryPromises.get(name);
+ if (!factoryPromise) {
+ factoryPromise = new Promise(function (resolveFactory) {
+ queuedFactoryRequests.set(name, resolveFactory);
+ });
+ factoryPromises.set(name, factoryPromise);
+ }
+ return factoryPromise;
+ }
+
+ function getInstancePromise(name, element) {
+ var factoryPromise;
+ var instancePromise = instancePromises.get(element);
+ if (!instancePromise) {
+ instancePromise = getFactoryPromise(name).then(function(factory) {
+ return factory();
+ });
+ instancePromises.set(element, instancePromise);
+ }
+ return instancePromise;
+ }
+
+ function renderPunchOut(params, element) {
+ var name = params.name;
+ var options = params.options || {};
+ var onEvent = params.onEvent || function () {};
+
+ getInstancePromise(name, element).then(function (punchOut) {
+ punchOut.render({options: options, onEvent: onEvent}, element);
+ });
+ }
+
+ function unmountPunchOut(element) {
+ if (!instancePromises.has(element)) {
+ console.error("There is no PunchOut in element", element);
+ return;
+ }
+ instancePromises.get(element).then(function(punchOut) {
+ punchOut.unmount(element);
+ });
+ instancePromises.delete(element);
+ }
+
+ var PunchOutRegistry = Object.freeze({
+ register: registerFactory,
+ render: renderPunchOut,
+ unmount: unmountPunchOut
+ });
+
+ window.PunchOutRegistry = PunchOutRegistry;
+
+})(this);
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/.npmignore b/catalog-ui/app/third-party/ng-infinite-scroll/.npmignore
new file mode 100644
index 0000000000..dcbd092327
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/.npmignore
@@ -0,0 +1,3 @@
+compile/*
+node_modules
+.tmp
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/.travis.yml b/catalog-ui/app/third-party/ng-infinite-scroll/.travis.yml
new file mode 100644
index 0000000000..ee95ccb343
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/.travis.yml
@@ -0,0 +1,12 @@
+language: node_js
+node_js:
+ - 0.10
+
+install:
+ - npm install
+
+before_script:
+ - npm install -g grunt-cli
+
+script:
+ - grunt test:protractor-travis
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/Gruntfile.coffee b/catalog-ui/app/third-party/ng-infinite-scroll/Gruntfile.coffee
new file mode 100644
index 0000000000..a9b9405731
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/Gruntfile.coffee
@@ -0,0 +1,110 @@
+module.exports = (grunt) ->
+ grunt.loadNpmTasks 'grunt-coffeelint'
+ grunt.loadNpmTasks 'grunt-contrib-clean'
+ grunt.loadNpmTasks 'grunt-contrib-coffee'
+ grunt.loadNpmTasks 'grunt-contrib-concat'
+ grunt.loadNpmTasks 'grunt-contrib-connect'
+ grunt.loadNpmTasks 'grunt-contrib-uglify'
+ grunt.loadNpmTasks 'grunt-protractor-runner'
+
+ sauceUser = 'pomerantsevp'
+ sauceKey = '497ab04e-f31b-4a7b-9b18-ae3fbe023222'
+
+ grunt.initConfig
+ pkg: grunt.file.readJSON 'package.json'
+ meta:
+ banner: '/* <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> */\n'
+ coffeelint:
+ src: 'src/**/*.coffee'
+ options:
+ max_line_length:
+ level: 'ignore'
+ line_endings:
+ value: 'unix'
+ level: 'error'
+ no_stand_alone_at:
+ level: 'error'
+ clean:
+ options:
+ force: true
+ build: ["compile/**", "build/**"]
+ coffee:
+ compile:
+ files: [
+ {
+ expand: true
+ cwd: 'src/'
+ src: '**/*.coffee'
+ dest: 'compile/'
+ ext: '.js'
+ }
+ ],
+ options:
+ bare: true
+ concat:
+ options:
+ banner: '<%= meta.banner %>'
+ dist:
+ src: 'compile/**/*.js'
+ dest: 'build/ng-infinite-scroll.js'
+ uglify:
+ options:
+ banner: '<%= meta.banner %>'
+ dist:
+ src: ['build/ng-infinite-scroll.js']
+ dest: 'build/ng-infinite-scroll.min.js'
+ connect:
+ testserver:
+ options:
+ port: 8000
+ hostname: '0.0.0.0'
+ middleware: (connect, options) ->
+ base = if Array.isArray(options.base) then options.base[options.base.length - 1] else options.base
+ [connect.static(base)]
+ protractor:
+ local:
+ options:
+ configFile: 'test/protractor-local.conf.js'
+ args:
+ params:
+ testThrottleValue: 500
+ travis:
+ options:
+ configFile: 'test/protractor-travis.conf.js'
+ args:
+ params:
+ # When using Sauce Connect, we should use a large timeout
+ # since everything is generally much slower than when testing locally.
+ testThrottleValue: 10000
+ sauceUser: sauceUser
+ sauceKey: sauceKey
+
+ grunt.registerTask 'webdriver', () ->
+ done = this.async()
+ p = require('child_process').spawn('node', ['node_modules/protractor/bin/webdriver-manager', 'update'])
+ p.stdout.pipe(process.stdout)
+ p.stderr.pipe(process.stderr)
+ p.on 'exit', (code) ->
+ if code isnt 0 then grunt.fail.warn('Webdriver failed to update')
+ done()
+
+ grunt.registerTask 'sauce-connect', () ->
+ done = this.async()
+ require('sauce-connect-launcher')({username: sauceUser, accessKey: sauceKey}, (err, sauceConnectProcess) ->
+ if err then console.error(err.message)
+ else done()
+ )
+
+ grunt.registerTask 'default', ['coffeelint', 'clean', 'coffee', 'concat', 'uglify']
+ grunt.registerTask 'test:protractor-local', [
+ 'default',
+ 'webdriver',
+ 'connect:testserver',
+ 'protractor:local'
+ ]
+
+ grunt.registerTask 'test:protractor-travis', [
+ 'connect:testserver',
+ 'sauce-connect',
+ 'protractor:travis'
+ ]
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/LICENSE b/catalog-ui/app/third-party/ng-infinite-scroll/LICENSE
new file mode 100644
index 0000000000..44ae2bfc40
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012 Michelle Tilley
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/README.md b/catalog-ui/app/third-party/ng-infinite-scroll/README.md
new file mode 100644
index 0000000000..aa8d8630e2
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/README.md
@@ -0,0 +1,71 @@
+[**Maintainer help needed**: I'm looking for fellows that are willing to help me maintain and improve this project.](https://github.com/sroze/ngInfiniteScroll/issues/267)
+
+---
+
+![logo](http://sroze.github.com/ngInfiniteScroll/images/logo-resized.png)
+
+[![Build Status](https://travis-ci.org/sroze/ngInfiniteScroll.png?branch=master)](https://travis-ci.org/sroze/ngInfiniteScroll)
+
+ngInfiniteScroll is a directive for [AngularJS](http://angularjs.org/) to evaluate an expression when the bottom of the directive's element approaches the bottom of the browser window, which can be used to implement infinite scrolling.
+
+Demos
+-----
+
+Check out the running demos [at the ngInfiniteScroll web site](http://sroze.github.com/ngInfiniteScroll/demos.html).
+
+Version Numbers
+---------------
+
+ngInfinite Scroll follows [semantic versioning](http://semver.org/) and uses the following versioning scheme:
+
+ * Versions starting with 0 (e.g. 0.1.0, 0.2.0, etc.) are for initial development, and the API is not stable
+ * Versions with an even minor version (1.0.0, 1.4.0, 2.2.0, etc.) are stable releases
+ * Versions with an odd minor version (1.1.0, 1.3.0, 2.1.0, etc.) are development releases
+
+The [download page](http://sroze.github.com/ngInfiniteScroll/#download) allows you to pick among various versions and specify which releases are stable (not including pre-release builds).
+
+Getting Started
+---------------
+
+ * Download ngInfiniteScroll from [the download page on the ngInfiniteScroll web site](http://sroze.github.com/ngInfiniteScroll/#download) or install it with:
+ * [Bower](http://bower.io/) via `bower install ngInfiniteScroll`
+ * [NPM](https://www.npmjs.com) via `npm install --save ng-infinite-scroll`
+ * [Nuget](https://www.nuget.org) via `PM> Install-Package ng-infinite-scroll`
+ * Include the script tag on your page after the AngularJS script tag (ngInfiniteScroll *doesn't* require jQuery)
+
+ <script type='text/javascript' src='path/to/angular.min.js'></script>
+ <script type='text/javascript' src='path/to/ng-infinite-scroll.min.js'></script>
+
+ * Ensure that your application module specifies `infinite-scroll` as a dependency:
+
+ angular.module('myApplication', ['infinite-scroll']);
+
+ * Use the directive by specifying an `infinite-scroll` attribute on an element.
+
+ <div infinite-scroll="myPagingFunction()" infinite-scroll-distance="3"></div>
+
+Note that neither the module nor the directive use the `ng` prefix, as that prefix is reserved for the core Angular module.
+
+Detailed Documentation
+----------------------
+
+ngInfiniteScroll accepts several attributes to customize the behavior of the directive; detailed instructions can be found [on the ngInfiniteScroll web site](http://sroze.github.com/ngInfiniteScroll/documentation.html).
+
+Ports
+-----
+
+If you use [AngularDart](https://github.com/angular/angular.dart), Juha Komulainen has [a port of the project](http://pub.dartlang.org/packages/ng_infinite_scroll) you can use.
+
+License
+-------
+
+ngInfiniteScroll is licensed under the MIT license. See the LICENSE file for more details.
+
+Testing
+-------
+
+ngInfiniteScroll uses Protractor for testing. Note that you will need to have Chrome browser, and the `grunt-cli` npm package installed globally if you wish to use grunt (`npm install -g grunt-cli`). Then, install the dependencies with `npm install`.
+
+* `grunt test:protractor-local` - run tests
+
+Thank you very much @pomerantsev for your work on these Protractor tests.
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/bower.json b/catalog-ui/app/third-party/ng-infinite-scroll/bower.json
new file mode 100644
index 0000000000..1171c45190
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/bower.json
@@ -0,0 +1,16 @@
+{
+ "name": "ngInfiniteScroll",
+ "main": "build/ng-infinite-scroll.js",
+ "ignore": [
+ "**/.*",
+ "_*",
+ "node_modules",
+ "compile",
+ "test",
+ "Gruntfile.coffee",
+ ".*"
+ ],
+ "dependencies": {
+ "angular": ">=1.2.0"
+ }
+}
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/build/ng-infinite-scroll.js b/catalog-ui/app/third-party/ng-infinite-scroll/build/ng-infinite-scroll.js
new file mode 100644
index 0000000000..0585004832
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/build/ng-infinite-scroll.js
@@ -0,0 +1,209 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+/* ng-infinite-scroll - v1.3.0 - 2016-06-30 */
+angular.module('infinite-scroll', []).value('THROTTLE_MILLISECONDS', null).directive('infiniteScroll', [
+ '$rootScope', '$window', '$interval', 'THROTTLE_MILLISECONDS', function($rootScope, $window, $interval, THROTTLE_MILLISECONDS) {
+ return {
+ scope: {
+ infiniteScroll: '&',
+ infiniteScrollContainer: '=',
+ infiniteScrollDistance: '=',
+ infiniteScrollDisabled: '=',
+ infiniteScrollUseDocumentBottom: '=',
+ infiniteScrollListenForEvent: '@'
+ },
+ link: function(scope, elem, attrs) {
+ var changeContainer, checkInterval, checkWhenEnabled, container, handleInfiniteScrollContainer, handleInfiniteScrollDisabled, handleInfiniteScrollDistance, handleInfiniteScrollUseDocumentBottom, handler, height, immediateCheck, offsetTop, pageYOffset, scrollDistance, scrollEnabled, throttle, unregisterEventListener, useDocumentBottom, windowElement;
+ windowElement = angular.element($window);
+ scrollDistance = null;
+ scrollEnabled = null;
+ checkWhenEnabled = null;
+ container = null;
+ immediateCheck = true;
+ useDocumentBottom = false;
+ unregisterEventListener = null;
+ checkInterval = false;
+ height = function(elem) {
+ elem = elem[0] || elem;
+ if (isNaN(elem.offsetHeight)) {
+ return elem.document.documentElement.clientHeight;
+ } else {
+ return elem.offsetHeight;
+ }
+ };
+ offsetTop = function(elem) {
+ if (!elem[0].getBoundingClientRect || elem.css('none')) {
+ return;
+ }
+ return elem[0].getBoundingClientRect().top + pageYOffset(elem);
+ };
+ pageYOffset = function(elem) {
+ elem = elem[0] || elem;
+ if (isNaN(window.pageYOffset)) {
+ return elem.document.documentElement.scrollTop;
+ } else {
+ return elem.ownerDocument.defaultView.pageYOffset;
+ }
+ };
+ handler = function() {
+ var containerBottom, containerTopOffset, elementBottom, remaining, shouldScroll;
+ if (container === windowElement) {
+ containerBottom = height(container) + pageYOffset(container[0].document.documentElement);
+ elementBottom = offsetTop(elem) + height(elem);
+ } else {
+ containerBottom = height(container);
+ containerTopOffset = 0;
+ if (offsetTop(container) !== void 0) {
+ containerTopOffset = offsetTop(container);
+ }
+ elementBottom = offsetTop(elem) - containerTopOffset + height(elem);
+ }
+ if (useDocumentBottom) {
+ elementBottom = height((elem[0].ownerDocument || elem[0].document).documentElement);
+ }
+ remaining = elementBottom - containerBottom;
+ shouldScroll = remaining <= height(container) * scrollDistance + 1;
+ if (shouldScroll) {
+ checkWhenEnabled = true;
+ if (scrollEnabled) {
+ if (scope.$$phase || $rootScope.$$phase) {
+ return scope.infiniteScroll();
+ } else {
+ return scope.$apply(scope.infiniteScroll);
+ }
+ }
+ } else {
+ if (checkInterval) {
+ $interval.cancel(checkInterval);
+ }
+ return checkWhenEnabled = false;
+ }
+ };
+ throttle = function(func, wait) {
+ var later, previous, timeout;
+ timeout = null;
+ previous = 0;
+ later = function() {
+ previous = new Date().getTime();
+ $interval.cancel(timeout);
+ timeout = null;
+ return func.call();
+ };
+ return function() {
+ var now, remaining;
+ now = new Date().getTime();
+ remaining = wait - (now - previous);
+ if (remaining <= 0) {
+ $interval.cancel(timeout);
+ timeout = null;
+ previous = now;
+ return func.call();
+ } else {
+ if (!timeout) {
+ return timeout = $interval(later, remaining, 1);
+ }
+ }
+ };
+ };
+ if (THROTTLE_MILLISECONDS != null) {
+ handler = throttle(handler, THROTTLE_MILLISECONDS);
+ }
+ scope.$on('$destroy', function() {
+ container.unbind('scroll', handler);
+ if (unregisterEventListener != null) {
+ unregisterEventListener();
+ unregisterEventListener = null;
+ }
+ if (checkInterval) {
+ return $interval.cancel(checkInterval);
+ }
+ });
+ handleInfiniteScrollDistance = function(v) {
+ return scrollDistance = parseFloat(v) || 0;
+ };
+ scope.$watch('infiniteScrollDistance', handleInfiniteScrollDistance);
+ handleInfiniteScrollDistance(scope.infiniteScrollDistance);
+ handleInfiniteScrollDisabled = function(v) {
+ scrollEnabled = !v;
+ if (scrollEnabled && checkWhenEnabled) {
+ checkWhenEnabled = false;
+ return handler();
+ }
+ };
+ scope.$watch('infiniteScrollDisabled', handleInfiniteScrollDisabled);
+ handleInfiniteScrollDisabled(scope.infiniteScrollDisabled);
+ handleInfiniteScrollUseDocumentBottom = function(v) {
+ return useDocumentBottom = v;
+ };
+ scope.$watch('infiniteScrollUseDocumentBottom', handleInfiniteScrollUseDocumentBottom);
+ handleInfiniteScrollUseDocumentBottom(scope.infiniteScrollUseDocumentBottom);
+ changeContainer = function(newContainer) {
+ if (container != null) {
+ container.unbind('scroll', handler);
+ }
+ container = newContainer;
+ if (newContainer != null) {
+ return container.bind('scroll', handler);
+ }
+ };
+ changeContainer(windowElement);
+ if (scope.infiniteScrollListenForEvent) {
+ unregisterEventListener = $rootScope.$on(scope.infiniteScrollListenForEvent, handler);
+ }
+ handleInfiniteScrollContainer = function(newContainer) {
+ if ((newContainer == null) || newContainer.length === 0) {
+ return;
+ }
+ if (newContainer.nodeType && newContainer.nodeType === 1) {
+ newContainer = angular.element(newContainer);
+ } else if (typeof newContainer.append === 'function') {
+ newContainer = angular.element(newContainer[newContainer.length - 1]);
+ } else if (typeof newContainer === 'string') {
+ newContainer = angular.element(document.querySelector(newContainer));
+ }
+ if (newContainer != null) {
+ return changeContainer(newContainer);
+ } else {
+ throw new Error("invalid infinite-scroll-container attribute.");
+ }
+ };
+ scope.$watch('infiniteScrollContainer', handleInfiniteScrollContainer);
+ handleInfiniteScrollContainer(scope.infiniteScrollContainer || []);
+ if (attrs.infiniteScrollParent != null) {
+ changeContainer(angular.element(elem.parent()));
+ }
+ if (attrs.infiniteScrollImmediateCheck != null) {
+ immediateCheck = scope.$eval(attrs.infiniteScrollImmediateCheck);
+ }
+ return checkInterval = $interval((function() {
+ if (immediateCheck) {
+ handler();
+ }
+ return $interval.cancel(checkInterval);
+ }));
+ }
+ };
+ }
+]);
+
+if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports) {
+ module.exports = 'infinite-scroll';
+}
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/build/ng-infinite-scroll.min.js b/catalog-ui/app/third-party/ng-infinite-scroll/build/ng-infinite-scroll.min.js
new file mode 100644
index 0000000000..e2a3036422
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/build/ng-infinite-scroll.min.js
@@ -0,0 +1,22 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+/* ng-infinite-scroll - v1.3.0 - 2016-06-30 */
+angular.module("infinite-scroll",[]).value("THROTTLE_MILLISECONDS",null).directive("infiniteScroll",["$rootScope","$window","$interval","THROTTLE_MILLISECONDS",function(a,b,c,d){return{scope:{infiniteScroll:"&",infiniteScrollContainer:"=",infiniteScrollDistance:"=",infiniteScrollDisabled:"=",infiniteScrollUseDocumentBottom:"=",infiniteScrollListenForEvent:"@"},link:function(e,f,g){var h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;return z=angular.element(b),u=null,v=null,j=null,k=null,r=!0,y=!1,x=null,i=!1,q=function(a){return a=a[0]||a,isNaN(a.offsetHeight)?a.document.documentElement.clientHeight:a.offsetHeight},s=function(a){if(a[0].getBoundingClientRect&&!a.css("none"))return a[0].getBoundingClientRect().top+t(a)},t=function(a){return a=a[0]||a,isNaN(window.pageYOffset)?a.document.documentElement.scrollTop:a.ownerDocument.defaultView.pageYOffset},p=function(){var b,d,g,h,l;return k===z?(b=q(k)+t(k[0].document.documentElement),g=s(f)+q(f)):(b=q(k),d=0,void 0!==s(k)&&(d=s(k)),g=s(f)-d+q(f)),y&&(g=q((f[0].ownerDocument||f[0].document).documentElement)),h=g-b,l=h<=q(k)*u+1,l?(j=!0,v?e.$$phase||a.$$phase?e.infiniteScroll():e.$apply(e.infiniteScroll):void 0):(i&&c.cancel(i),j=!1)},w=function(a,b){var d,e,f;return f=null,e=0,d=function(){return e=(new Date).getTime(),c.cancel(f),f=null,a.call()},function(){var g,h;return g=(new Date).getTime(),h=b-(g-e),h<=0?(c.cancel(f),f=null,e=g,a.call()):f?void 0:f=c(d,h,1)}},null!=d&&(p=w(p,d)),e.$on("$destroy",function(){if(k.unbind("scroll",p),null!=x&&(x(),x=null),i)return c.cancel(i)}),n=function(a){return u=parseFloat(a)||0},e.$watch("infiniteScrollDistance",n),n(e.infiniteScrollDistance),m=function(a){if(v=!a,v&&j)return j=!1,p()},e.$watch("infiniteScrollDisabled",m),m(e.infiniteScrollDisabled),o=function(a){return y=a},e.$watch("infiniteScrollUseDocumentBottom",o),o(e.infiniteScrollUseDocumentBottom),h=function(a){if(null!=k&&k.unbind("scroll",p),k=a,null!=a)return k.bind("scroll",p)},h(z),e.infiniteScrollListenForEvent&&(x=a.$on(e.infiniteScrollListenForEvent,p)),l=function(a){if(null!=a&&0!==a.length){if(a.nodeType&&1===a.nodeType?a=angular.element(a):"function"==typeof a.append?a=angular.element(a[a.length-1]):"string"==typeof a&&(a=angular.element(document.querySelector(a))),null!=a)return h(a);throw new Error("invalid infinite-scroll-container attribute.")}},e.$watch("infiniteScrollContainer",l),l(e.infiniteScrollContainer||[]),null!=g.infiniteScrollParent&&h(angular.element(f.parent())),null!=g.infiniteScrollImmediateCheck&&(r=e.$eval(g.infiniteScrollImmediateCheck)),i=c(function(){return r&&p(),c.cancel(i)})}}}]),"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="infinite-scroll");
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/package.json b/catalog-ui/app/third-party/ng-infinite-scroll/package.json
new file mode 100644
index 0000000000..8859faecdc
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/package.json
@@ -0,0 +1,80 @@
+{
+ "name": "ng-infinite-scroll",
+ "version": "1.3.0",
+ "description": "Infinite scrolling for AngularJS",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/sroze/ngInfiniteScroll.git"
+ },
+ "main": "build/ng-infinite-scroll.js",
+ "browser": "build/ng-infinite-scroll.js",
+ "scripts": {
+ "test": "grunt test:protractor-local"
+ },
+ "author": {
+ "name": "Michelle Tilley",
+ "email": "michelle@michelletilley.net",
+ "url": "http://michelletilley.net"
+ },
+ "contributors": [
+ {
+ "name": "Samuel ROZE",
+ "email": "samuel.roze@gmail.com",
+ "url": "http://sroze.io"
+ }
+ ],
+ "license": "MIT",
+ "devDependencies": {
+ "coffee-script": "~1.8.0",
+ "grunt": "~0.4.5",
+ "grunt-coffeelint": "~0.0.13",
+ "grunt-contrib-clean": "~0.6.0",
+ "grunt-contrib-coffee": "~0.12.0",
+ "grunt-contrib-concat": "~0.5.0",
+ "grunt-contrib-connect": "0.8.0",
+ "grunt-contrib-uglify": "~0.6.0",
+ "grunt-protractor-runner": "1.1.4",
+ "mkdirp": "0.5.0",
+ "protractor": "1.4.0",
+ "sauce-connect-launcher": "0.9.0"
+ },
+ "gitHead": "6fbf4b41947f9a3023b4aba0e613231950ccc4a1",
+ "bugs": {
+ "url": "https://github.com/sroze/ngInfiniteScroll/issues"
+ },
+ "homepage": "https://github.com/sroze/ngInfiniteScroll#readme",
+ "_id": "ng-infinite-scroll@1.3.0",
+ "_shasum": "c2e98d8fd134b0525a4d2cf58c95d9b583755112",
+ "_from": "ng-infinite-scroll@>=1.3.0 <2.0.0",
+ "_npmVersion": "3.9.5",
+ "_nodeVersion": "6.2.2",
+ "_npmUser": {
+ "name": "graingert",
+ "email": "tagrain@gmail.com"
+ },
+ "dist": {
+ "shasum": "c2e98d8fd134b0525a4d2cf58c95d9b583755112",
+ "tarball": "https://registry.npmjs.org/ng-infinite-scroll/-/ng-infinite-scroll-1.3.0.tgz"
+ },
+ "maintainers": [
+ {
+ "name": "binarymuse",
+ "email": "michelle@michelletilley.net"
+ },
+ {
+ "name": "graingert",
+ "email": "tagrain@gmail.com"
+ },
+ {
+ "name": "sroze",
+ "email": "samuel.roze@gmail.com"
+ }
+ ],
+ "_npmOperationalInternal": {
+ "host": "packages-12-west.internal.npmjs.com",
+ "tmp": "tmp/ng-infinite-scroll-1.3.0.tgz_1467302375605_0.8192659560590982"
+ },
+ "directories": {},
+ "_resolved": "https://registry.npmjs.org/ng-infinite-scroll/-/ng-infinite-scroll-1.3.0.tgz",
+ "readme": "ERROR: No README data found!"
+}
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/src/infinite-scroll.coffee b/catalog-ui/app/third-party/ng-infinite-scroll/src/infinite-scroll.coffee
new file mode 100644
index 0000000000..cf2f90fc19
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/src/infinite-scroll.coffee
@@ -0,0 +1,209 @@
+angular.module('infinite-scroll', [])
+ .value('THROTTLE_MILLISECONDS', null)
+ .directive 'infiniteScroll', [
+ '$rootScope', '$window', '$interval', 'THROTTLE_MILLISECONDS',
+($rootScope, $window, $interval, THROTTLE_MILLISECONDS) ->
+ scope:
+ infiniteScroll: '&'
+ infiniteScrollContainer: '='
+ infiniteScrollDistance: '='
+ infiniteScrollDisabled: '='
+ infiniteScrollUseDocumentBottom: '=',
+ infiniteScrollListenForEvent: '@'
+
+ link: (scope, elem, attrs) ->
+ windowElement = angular.element($window)
+
+ scrollDistance = null
+ scrollEnabled = null
+ checkWhenEnabled = null
+ container = null
+ immediateCheck = true
+ useDocumentBottom = false
+ unregisterEventListener = null
+ checkInterval = false
+
+ height = (elem) ->
+ elem = elem[0] or elem
+
+ if isNaN(elem.offsetHeight) then elem.document.documentElement.clientHeight else elem.offsetHeight
+
+ offsetTop = (elem) ->
+ if not elem[0].getBoundingClientRect or elem.css('none')
+ return
+
+ elem[0].getBoundingClientRect().top + pageYOffset(elem)
+
+ pageYOffset = (elem) ->
+ elem = elem[0] or elem
+
+ if isNaN(window.pageYOffset) then elem.document.documentElement.scrollTop else elem.ownerDocument.defaultView.pageYOffset
+
+ # infinite-scroll specifies a function to call when the window,
+ # or some other container specified by infinite-scroll-container,
+ # is scrolled within a certain range from the bottom of the
+ # document. It is recommended to use infinite-scroll-disabled
+ # with a boolean that is set to true when the function is
+ # called in order to throttle the function call.
+ handler = ->
+ if container == windowElement
+ containerBottom = height(container) + pageYOffset(container[0].document.documentElement)
+ elementBottom = offsetTop(elem) + height(elem)
+ else
+ containerBottom = height(container)
+ containerTopOffset = 0
+ if offsetTop(container) != undefined
+ containerTopOffset = offsetTop(container)
+ elementBottom = offsetTop(elem) - containerTopOffset + height(elem)
+
+ if(useDocumentBottom)
+ elementBottom = height((elem[0].ownerDocument || elem[0].document).documentElement)
+
+ remaining = elementBottom - containerBottom
+ shouldScroll = remaining <= height(container) * scrollDistance + 1
+
+ if shouldScroll
+ checkWhenEnabled = true
+
+ if scrollEnabled
+ if scope.$$phase || $rootScope.$$phase
+ scope.infiniteScroll()
+ else
+ scope.$apply(scope.infiniteScroll)
+ else
+ if checkInterval then $interval.cancel checkInterval
+ checkWhenEnabled = false
+
+ # The optional THROTTLE_MILLISECONDS configuration value specifies
+ # a minimum time that should elapse between each call to the
+ # handler. N.b. the first call the handler will be run
+ # immediately, and the final call will always result in the
+ # handler being called after the `wait` period elapses.
+ # A slimmed down version of underscore's implementation.
+ throttle = (func, wait) ->
+ timeout = null
+ previous = 0
+ later = ->
+ previous = new Date().getTime()
+ $interval.cancel(timeout)
+ timeout = null
+ func.call()
+
+ return ->
+ now = new Date().getTime()
+ remaining = wait - (now - previous)
+ if remaining <= 0
+ $interval.cancel(timeout)
+ timeout = null
+ previous = now
+ func.call()
+ else timeout = $interval(later, remaining, 1) unless timeout
+
+ if THROTTLE_MILLISECONDS?
+ handler = throttle(handler, THROTTLE_MILLISECONDS)
+
+ scope.$on '$destroy', ->
+ container.unbind 'scroll', handler
+ if unregisterEventListener?
+ unregisterEventListener()
+ unregisterEventListener = null
+ if checkInterval
+ $interval.cancel checkInterval
+
+ # infinite-scroll-distance specifies how close to the bottom of the page
+ # the window is allowed to be before we trigger a new scroll. The value
+ # provided is multiplied by the container height; for example, to load
+ # more when the bottom of the page is less than 3 container heights away,
+ # specify a value of 3. Defaults to 0.
+ handleInfiniteScrollDistance = (v) ->
+ scrollDistance = parseFloat(v) or 0
+
+ scope.$watch 'infiniteScrollDistance', handleInfiniteScrollDistance
+ # If I don't explicitly call the handler here, tests fail. Don't know why yet.
+ handleInfiniteScrollDistance scope.infiniteScrollDistance
+
+ # infinite-scroll-disabled specifies a boolean that will keep the
+ # infnite scroll function from being called; this is useful for
+ # debouncing or throttling the function call. If an infinite
+ # scroll is triggered but this value evaluates to true, then
+ # once it switches back to false the infinite scroll function
+ # will be triggered again.
+ handleInfiniteScrollDisabled = (v) ->
+ scrollEnabled = !v
+ if scrollEnabled && checkWhenEnabled
+ checkWhenEnabled = false
+ handler()
+
+ scope.$watch 'infiniteScrollDisabled', handleInfiniteScrollDisabled
+ # If I don't explicitly call the handler here, tests fail. Don't know why yet.
+ handleInfiniteScrollDisabled scope.infiniteScrollDisabled
+
+ # use the bottom of the document instead of the element's bottom.
+ # This useful when the element does not have a height due to its
+ # children being absolute positioned.
+ handleInfiniteScrollUseDocumentBottom = (v) ->
+ useDocumentBottom = v
+
+ scope.$watch 'infiniteScrollUseDocumentBottom', handleInfiniteScrollUseDocumentBottom
+ handleInfiniteScrollUseDocumentBottom scope.infiniteScrollUseDocumentBottom
+
+ # infinite-scroll-container sets the container which we want to be
+ # infinte scrolled, instead of the whole window. Must be an
+ # Angular or jQuery element, or, if jQuery is loaded,
+ # a jQuery selector as a string.
+ changeContainer = (newContainer) ->
+ if container?
+ container.unbind 'scroll', handler
+
+ container = newContainer
+ if newContainer?
+ container.bind 'scroll', handler
+
+ changeContainer windowElement
+
+ if scope.infiniteScrollListenForEvent
+ unregisterEventListener = $rootScope.$on scope.infiniteScrollListenForEvent, handler
+
+ handleInfiniteScrollContainer = (newContainer) ->
+ # TODO: For some reason newContainer is sometimes null instead
+ # of the empty array, which Angular is supposed to pass when the
+ # element is not defined
+ # (https://github.com/sroze/ngInfiniteScroll/pull/7#commitcomment-5748431).
+ # So I leave both checks.
+ if (not newContainer?) or newContainer.length == 0
+ return
+
+ if newContainer.nodeType && newContainer.nodeType == 1
+ newContainer = angular.element newContainer
+ else if typeof newContainer.append == 'function'
+ newContainer = angular.element newContainer[newContainer.length - 1]
+ else if typeof newContainer == 'string'
+ newContainer = angular.element document.querySelector newContainer
+
+ if newContainer?
+ changeContainer newContainer
+ else
+ throw new Error("invalid infinite-scroll-container attribute.")
+
+ scope.$watch 'infiniteScrollContainer', handleInfiniteScrollContainer
+ handleInfiniteScrollContainer(scope.infiniteScrollContainer or [])
+
+ # infinite-scroll-parent establishes this element's parent as the
+ # container infinitely scrolled instead of the whole window.
+ if attrs.infiniteScrollParent?
+ changeContainer angular.element elem.parent()
+
+ # infinte-scoll-immediate-check sets whether or not run the
+ # expression passed on infinite-scroll for the first time when the
+ # directive first loads, before any actual scroll.
+ if attrs.infiniteScrollImmediateCheck?
+ immediateCheck = scope.$eval(attrs.infiniteScrollImmediateCheck)
+
+ checkInterval = $interval (->
+ if immediateCheck
+ handler()
+ $interval.cancel checkInterval
+ )
+]
+if typeof module != "undefined" && typeof exports != "undefined" && module.exports == exports
+ module.exports = 'infinite-scroll'
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-local.conf.js b/catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-local.conf.js
new file mode 100644
index 0000000000..134c723f91
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-local.conf.js
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+var config = require('./protractor-shared.conf').config;
+
+config.multiCapabilities = [
+ { browserName: 'chrome' }
+];
+
+exports.config = config;
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-shared.conf.js b/catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-shared.conf.js
new file mode 100644
index 0000000000..d1e567d7b4
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-shared.conf.js
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+exports.config = {
+ specs: ['**/*.spec.coffee'],
+ baseUrl: 'http://localhost:8000/',
+ allScriptsTimeout: 30000,
+ getPageTimeout: 30000
+};
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-travis.conf.js b/catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-travis.conf.js
new file mode 100644
index 0000000000..54fe0bd828
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/test/protractor-travis.conf.js
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+var config = require('./protractor-shared.conf').config;
+
+// All available platform / browser combinations can be found on https://saucelabs.com/platforms
+config.multiCapabilities = [
+ {
+ browserName: 'chrome',
+ platform: 'OS X 10.10',
+ version: '37'
+ }
+];
+
+exports.config = config;
diff --git a/catalog-ui/app/third-party/ng-infinite-scroll/test/spec/ng-infinite-scroll.spec.coffee b/catalog-ui/app/third-party/ng-infinite-scroll/test/spec/ng-infinite-scroll.spec.coffee
new file mode 100644
index 0000000000..07e6fec8be
--- /dev/null
+++ b/catalog-ui/app/third-party/ng-infinite-scroll/test/spec/ng-infinite-scroll.spec.coffee
@@ -0,0 +1,221 @@
+fs = require "fs"
+mkdirp = require "mkdirp"
+
+getTemplate = (angularVersion, container, attrs, throttle) ->
+ """
+ <!doctype html>
+ <head>
+ <style>
+ html, body {
+ height: 100%;
+ }
+ </style>
+ <script src='http://ajax.googleapis.com/ajax/libs/angularjs/#{angularVersion}/angular.min.js'></script>
+ <script src="../../build/ng-infinite-scroll.js"></script>
+ <script>
+ angular.module('app', ['infinite-scroll'])
+ .config(function ($provide) {
+ $provide.value('THROTTLE_MILLISECONDS', #{throttle});
+ })
+ .run(function ($rootScope) {
+ $rootScope.items = [];
+ $rootScope.loadMore = function () {
+ [].push.apply($rootScope.items, new Array(100));
+ };
+
+ $rootScope.busy = true;
+
+ $rootScope.enable = function () {
+ $rootScope.busy = false;
+ };
+
+ $rootScope.triggerEvent = function () {
+ $rootScope.$emit('anEvent');
+ };
+ });
+ </script>
+ </head>
+ <body ng-app="app">
+ <a id="action" ng-click="enable()">Enable</a>
+ <a id="force" ng-click="loadMore()">Force</a>
+ <a id="trigger" ng-click="triggerEvent()">Trigger</a>
+ #{containers[container].start}
+ <div infinite-scroll="loadMore()" #{containers[container].attr} #{attrs}>
+ <p ng-repeat='item in items track by $index'>
+ {{$index}}
+ </p>
+ </div>
+ #{containers[container].end}
+ </body>
+ """
+
+containers =
+ window:
+ start: ""
+ end: ""
+ attr: ""
+ parent:
+ start: "<div id='parent' style='height: 50%; overflow: auto;'>"
+ end: "</div>"
+ attr: "infinite-scroll-parent"
+ ancestor:
+ start: "<div id='ancestor' style='height: 50%; overflow: auto;'><div>"
+ end: "</div></div>"
+ attr: "infinite-scroll-container='\"#ancestor\"'"
+
+getElementByIdScript = (id) ->
+ "document.getElementById('#{id}')"
+
+calculateChildrenHeightScript = (id) ->
+ """
+ [].concat.apply([], #{getElementByIdScript(id)}.childNodes)
+ .map(function (el) { return el.offsetHeight ? el.offsetHeight : 0; })
+ .reduce(function (cur, prev) { return prev + cur; }, 0)
+ """
+
+scrollToBottomScript = (container) ->
+ if container is "window"
+ "window.scrollTo(0, document.body.scrollHeight)"
+ else
+ "#{getElementByIdScript(container)}.scrollTop = #{calculateChildrenHeightScript(container)}"
+
+scrollToLastScreenScript = (container, offset) ->
+ # 2 * window.innerHeight means that the bottom of the screen should be somewhere close to
+ # body height - window height. That means that the top of the window is body height - 2 * window height.
+ if container is "window"
+ "window.scrollTo(0, document.body.scrollHeight - 2 * window.innerHeight + #{offset})"
+ else
+ """
+ #{getElementByIdScript(container)}.scrollTop =
+ #{calculateChildrenHeightScript(container)} - 2 * #{getElementByIdScript(container)}.offsetHeight + #{offset}
+ """
+
+collapseItemsScript = (container) ->
+ """
+ var items = document.getElementsByTagName('p')
+ for (i = 0; i < items.length; ++i) {
+ items[i].style.display = 'none'
+ }
+ """
+
+getItems = ->
+ element.all(By.repeater "item in items")
+
+tmpDir = ".tmp"
+pathToDocument = "#{tmpDir}/index.html"
+
+describe "ng-infinite-scroll", ->
+ for angularVersion in ["1.2.0", "1.3.4"]
+ describe "with Angular #{angularVersion}", ->
+ for container in ["window", "ancestor", "parent"]
+ describe "with #{container} as container", ->
+
+ replaceIndexFile = (attrs, throttle) ->
+ mkdirp tmpDir
+ fs.writeFileSync(pathToDocument, getTemplate(angularVersion, container, attrs, throttle))
+
+ describe "without throttling", ->
+
+ throttle = null
+
+ it "should be triggered immediately and when container is scrolled to the bottom", ->
+ replaceIndexFile "", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 100
+ browser.driver.executeScript(scrollToBottomScript(container))
+ expect(getItems().count()).toBe 200
+
+ it "does not trigger immediately when infinite-scroll-immediate-check is false", ->
+ replaceIndexFile "infinite-scroll-immediate-check='false'", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 0
+ element(By.id("force")).click()
+ expect(getItems().count()).toBe 100
+ browser.driver.executeScript(scrollToBottomScript(container))
+ expect(getItems().count()).toBe 200
+
+ it "respects the disabled attribute", ->
+ replaceIndexFile "infinite-scroll-disabled='busy'", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 0
+ element(By.id("action")).click()
+ expect(getItems().count()).toBe 100
+
+ it "respects the infinite-scroll-distance attribute", ->
+ replaceIndexFile "infinite-scroll-distance='1'", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 100
+ browser.driver.executeScript(scrollToLastScreenScript(container, -20))
+ expect(getItems().count()).toBe 100
+ browser.driver.executeScript(scrollToLastScreenScript(container, 20))
+ expect(getItems().count()).toBe 200
+
+ describe "with an event handler", ->
+
+ it "calls the event handler on an event", ->
+ replaceIndexFile "infinite-scroll-listen-for-event='anEvent'", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 100
+ browser.driver.executeScript(collapseItemsScript(container))
+ expect(getItems().count()).toBe 100
+ element(By.id("trigger")).click()
+ expect(getItems().count()).toBe 200
+
+ describe "with throttling", ->
+
+ throttle = browser.params.testThrottleValue
+
+ it "should be triggered immediately and when container is scrolled to the bottom", ->
+ replaceIndexFile "", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 100
+ browser.driver.executeScript(scrollToBottomScript(container))
+ expect(getItems().count()).toBe 100
+ browser.sleep(throttle)
+ expect(getItems().count()).toBe 200
+
+ it "does not trigger immediately when infinite-scroll-immediate-check is false", ->
+ replaceIndexFile "infinite-scroll-immediate-check='false'", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 0
+ element(By.id("force")).click()
+ expect(getItems().count()).toBe 100
+
+ it "respects the disabled attribute and is throttled when page loads", ->
+ replaceIndexFile "infinite-scroll-disabled='busy'", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 0
+ element(By.id("action")).click()
+ expect(getItems().count()).toBe 0
+ browser.sleep(throttle)
+ expect(getItems().count()).toBe 100
+
+ it "is not throttled when re-enabled if the throttle time has already elapsed", ->
+ replaceIndexFile "infinite-scroll-disabled='busy'", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 0
+ browser.sleep(throttle)
+ element(By.id("action")).click()
+ expect(getItems().count()).toBe 100
+
+ it "respects the infinite-scroll-distance attribute", ->
+ replaceIndexFile "infinite-scroll-distance='1'", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 100
+ browser.driver.executeScript(scrollToLastScreenScript(container, 20))
+ expect(getItems().count()).toBe 100
+ browser.sleep(throttle)
+ expect(getItems().count()).toBe 200
+
+ describe "with an event handler", ->
+
+ it "calls the event handler on an event", ->
+ replaceIndexFile "infinite-scroll-listen-for-event='anEvent'", throttle
+ browser.get pathToDocument
+ expect(getItems().count()).toBe 100
+ browser.driver.executeScript(collapseItemsScript(container))
+ expect(getItems().count()).toBe 100
+ element(By.id("trigger")).click()
+ expect(getItems().count()).toBe 100
+ browser.sleep(throttle)
+ expect(getItems().count()).toBe 200