diff --git a/angular-tree-control.js b/angular-tree-control.js
index e3bd034..5cecf41 100644
--- a/angular-tree-control.js
+++ b/angular-tree-control.js
@@ -2,7 +2,7 @@
'use strict';
angular.module( 'treeControl', [] )
- .directive( 'treecontrol', ['$compile', function( $compile ) {
+ .directive( 'treecontrol', ['$compile', '$timeout', function( $compile, $timeout) {
/**
* @param cssClass - the css class
* @param addClassProperty - should we wrap the class name with class=""
@@ -90,6 +90,9 @@
ensureDefault($scope.options.injectClasses, "labelSelected", "");
ensureDefault($scope.options, "equality", defaultEquality);
ensureDefault($scope.options, "isLeaf", defaultIsLeaf);
+ ensureDefault($scope.options, "enableIntervalToggle", false);
+ ensureDefault($scope.options, "childrenLimitInterval", 10);
+ ensureDefault($scope.options, "childrenTimeInterval", 10);
$scope.selectedNodes = $scope.selectedNodes || [];
$scope.expandedNodes = $scope.expandedNodes || [];
@@ -202,11 +205,25 @@
return isThisNodeSelected?"tree-selected" + injectSelectionClass:"";
};
+ $scope.enableIntervalToggleOnScope = function(scope){
+ var limitInterval = $scope.options.childrenLimitInterval*1;
+ var timeInterval = $scope.options.childrenTimeInterval*1;
+
+ scope.childrenLimit = limitInterval;
+ $timeout(function addChildren(){
+ if(scope.childrenLimit < (scope.node.children || []).length){
+ scope.childrenLimit = scope.childrenLimit + limitInterval;
+ $timeout(addChildren, timeInterval);
+ }
+ }, timeInterval);
+ };
+
//tree template
var orderBy = $scope.orderBy ? ' | orderBy:orderBy:reverseOrder' : '';
+ var limitTo = $scope.options.enableIntervalToggle ? ' | limitTo:childrenLimit' : '';
var template =
'
' +
- '- ' +
+ '
- ' +
'' +
'' +
'' +
@@ -270,6 +287,7 @@
//Rendering template for a root node
treemodelCntr.template( scope, function(clone) {
element.html('').append( clone );
+ if(scope.options.enableIntervalToggle) scope.enableIntervalToggleOnScope(scope);
});
// save the transclude function from compile (which is not bound to a scope as apposed to the one from link)
// we can fix this to work with the link transclude function with angular 1.2.6. as for angular 1.2.0 we need
@@ -285,8 +303,9 @@
require: "^treecontrol",
link: function( scope, element, attrs, treemodelCntr) {
// Rendering template for the current node
- treemodelCntr.template(scope, function(clone) {
+ treemodelCntr.template(scope, function(clone) {
element.html('').append(clone);
+ if(scope.options.enableIntervalToggle) scope.enableIntervalToggleOnScope(scope);
});
}
}
diff --git a/bower.json b/bower.json
index 8eb1295..113b99f 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
- "name": "angular-tree-control",
- "version": "0.2.9",
+ "name": "angular-tree-control-smooth-expand",
+ "version": "0.3.0",
"main": [
"./angular-tree-control.js",
"./css/tree-control.css"
@@ -12,7 +12,7 @@
"karma.conf.js"
],
"dependencies": {
- "angular": "~1.2.7"
+ "angular": "~1.3.15"
},
"devDependencies": {
"angular-mocks": "~1.2.7",
diff --git a/package.json b/package.json
index 0197800..67f056f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
- "name": "angular-tree-control",
- "version": "0.2.0",
+ "name": "angular-tree-control-smooth-expand",
+ "version": "0.3.0",
"description": "Angular Tree Control",
"main": "angular-tree-control.js",
"scripts": {
@@ -8,14 +8,14 @@
},
"repository": {
"type": "git",
- "url": "git://github.com/wix/angular-tree-control.git"
+ "url": "git://github.com/ssteffl/angular-tree-control.git"
},
"author": "",
"license": "ISC",
"bugs": {
- "url": "https://github.com/wix/angular-tree-control/issues"
+ "url": "https://github.com/ssteffl/angular-tree-control-smooth-expand/issues"
},
- "homepage": "https://github.com/wix/angular-tree-control",
+ "homepage": "https://github.com/ssteffl/angular-tree-control-smooth-expand",
"devDependencies": {
"grunt": "~0.4.2",
"grunt-release": "~0.6.0",
diff --git a/test/angular-tree-control-test.js b/test/angular-tree-control-test.js
index 9fb4d9b..0c7a8e4 100644
--- a/test/angular-tree-control-test.js
+++ b/test/angular-tree-control-test.js
@@ -6,6 +6,7 @@ describe('treeControl', function() {
inject(function ($injector) {
$compile = $injector.get('$compile');
$rootScope = $injector.get('$rootScope');
+ $timeout = $injector.get('$timeout');
});
num = 1;
});
@@ -639,4 +640,122 @@ describe('treeControl', function() {
});
+ describe('gradual children expanding', function(){
+ it('should add 20 children per 25 ms', function(){
+ var TIME_INTERVAL = 25,
+ LIMIT_INTERVAL = 20,
+ MAX_NODES = 100;
+ $rootScope.treedata = createSubTree(1, MAX_NODES);
+ $rootScope.treeOptions = {
+ enableIntervalToggle: true,
+ childrenLimitInterval: LIMIT_INTERVAL,
+ childrenTimeInterval: TIME_INTERVAL
+ };
+ element = $compile('{{node.label}}')($rootScope);
+ $rootScope.$digest();
+
+ var expectedChildCount = LIMIT_INTERVAL, flag = false;
+ runs(function(){
+ setTimeout(function checkChildCount(){
+ if(expectedChildCount<=MAX_NODES){
+ expect(element.find('li').length).toBe(expectedChildCount);
+ expectedChildCount += LIMIT_INTERVAL;
+ $timeout.flush();
+ setTimeout(checkChildCount, TIME_INTERVAL);
+ }
+ else flag = true;
+ }, TIME_INTERVAL/2);
+ });
+ waitsFor(function(){ return flag;}, 'Timeouts finished', TIME_INTERVAL*(MAX_NODES/LIMIT_INTERVAL*2));
+ });
+ it('should default childrenTimeInterval to 10 ms', function(){
+ var TIME_INTERVAL = 10,
+ LIMIT_INTERVAL = 20,
+ MAX_NODES = 100;
+ $rootScope.treedata = createSubTree(1, MAX_NODES);
+ $rootScope.treeOptions = {
+ enableIntervalToggle: true,
+ childrenLimitInterval: LIMIT_INTERVAL,
+ };
+ element = $compile('{{node.label}}')($rootScope);
+ $rootScope.$digest();
+ var expectedChildCount = LIMIT_INTERVAL, flag = false;
+ runs(function(){
+ setTimeout(function checkChildCount(){
+ if(expectedChildCount<=MAX_NODES){
+ expect(element.find('li').length).toBe(expectedChildCount);
+ expectedChildCount += LIMIT_INTERVAL;
+ $timeout.flush();
+ setTimeout(checkChildCount, TIME_INTERVAL);
+ }
+ else flag = true;
+ }, TIME_INTERVAL/2);
+ });
+ waitsFor(function(){ return flag;}, 'Timeouts finished', TIME_INTERVAL*(MAX_NODES/LIMIT_INTERVAL*2));
+ });
+ it('should default childrenLimitInterval to 10', function(){
+ var TIME_INTERVAL = 20,
+ LIMIT_INTERVAL = 10,
+ MAX_NODES = 50;
+ $rootScope.treedata = createSubTree(1, MAX_NODES);
+ $rootScope.treeOptions = {
+ enableIntervalToggle: true,
+ childrenTimeInterval: TIME_INTERVAL
+ };
+ element = $compile('{{node.label}}')($rootScope);
+ $rootScope.$digest();
+ var expectedChildCount = LIMIT_INTERVAL, flag = false;
+ runs(function(){
+ setTimeout(function checkChildCount(){
+ if(expectedChildCount<=MAX_NODES){
+ expect(element.find('li').length).toBe(expectedChildCount);
+ expectedChildCount += LIMIT_INTERVAL;
+ $timeout.flush();
+ setTimeout(checkChildCount, TIME_INTERVAL);
+ }
+ else flag = true;
+ }, TIME_INTERVAL/2);
+ });
+ waitsFor(function(){ return flag;}, 'Timeouts finished', TIME_INTERVAL*(MAX_NODES/LIMIT_INTERVAL*2));
+ });
+ it('should handle nested expansion properly', function(){
+ var TIME_INTERVAL = 10,
+ LIMIT_INTERVAL = 10,
+ MAX_NODES = 50;
+ $rootScope.treedata = createSubTree(2, MAX_NODES);
+ $rootScope.treeOptions = {
+ enableIntervalToggle: true
+ };
+ element = $compile('{{node.label}}')($rootScope);
+ $rootScope.$digest();
+ var expectedChildCount = LIMIT_INTERVAL, subTreeExpectedChildCount = LIMIT_INTERVAL, flag = false;
+ runs(function(){
+ setTimeout(function checkChildCount(){
+ if(expectedChildCount<=MAX_NODES){
+ expect(element.find('li').length).toBe(expectedChildCount);
+ expectedChildCount += LIMIT_INTERVAL;
+ $timeout.flush();
+ setTimeout(checkChildCount, TIME_INTERVAL);
+ }
+ else {
+ element.find('li:eq(0) .tree-branch-head').click()
+ testSubTree();
+ }
+ }, TIME_INTERVAL/2);
+
+ function testSubTree(){
+ setTimeout(function checkChildCount(){
+ if(subTreeExpectedChildCount<=MAX_NODES){
+ expect(element.find('li:eq(0) li').length).toBe(subTreeExpectedChildCount);
+ subTreeExpectedChildCount += LIMIT_INTERVAL;
+ $timeout.flush();
+ setTimeout(checkChildCount, TIME_INTERVAL);
+ }
+ else flag = true;
+ }, TIME_INTERVAL/2);
+ }
+ });
+ waitsFor(function(){ return flag;}, 'Timeouts finished', 2*TIME_INTERVAL*(MAX_NODES/LIMIT_INTERVAL*2));
+ });
+ });
});