diff --git a/benchmarks/repeat-animate-bp/app-classfilter.js b/benchmarks/repeat-animate-bp/app-classfilter.js new file mode 100644 index 000000000000..6c2708da145f --- /dev/null +++ b/benchmarks/repeat-animate-bp/app-classfilter.js @@ -0,0 +1,9 @@ +'use strict'; + +angular.module('repeatAnimateBenchmark', ['ngAnimate']) + .config(function($animateProvider) { + $animateProvider.classNameFilter(/animate-/); + }) + .run(function($rootScope) { + $rootScope.fileType = 'classfilter'; + }); diff --git a/benchmarks/repeat-animate-bp/app-noanimate.js b/benchmarks/repeat-animate-bp/app-noanimate.js new file mode 100644 index 000000000000..cc99bfcc8cd7 --- /dev/null +++ b/benchmarks/repeat-animate-bp/app-noanimate.js @@ -0,0 +1,6 @@ +'use strict'; + +angular.module('repeatAnimateBenchmark', []) + .run(function($rootScope) { + $rootScope.fileType = 'noanimate'; + }); diff --git a/benchmarks/repeat-animate-bp/app.js b/benchmarks/repeat-animate-bp/app.js new file mode 100644 index 000000000000..e7ac91d7c5fd --- /dev/null +++ b/benchmarks/repeat-animate-bp/app.js @@ -0,0 +1,7 @@ +'use strict'; + +angular.module('repeatAnimateBenchmark', ['ngAnimate']) + .run(function($rootScope) { + $rootScope.fileType = 'default'; + }); + diff --git a/benchmarks/repeat-animate-bp/bp.conf.js b/benchmarks/repeat-animate-bp/bp.conf.js new file mode 100644 index 000000000000..5bba15017c10 --- /dev/null +++ b/benchmarks/repeat-animate-bp/bp.conf.js @@ -0,0 +1,20 @@ +module.exports = function(config) { + config.set({ + scripts: [ + { + id: 'angular', + src: '/build/angular.js' + }, + { + id: 'angular-animate', + src: '/build/angular-animate.js' + }, + { + id: 'app', + src: 'app.js', + }, + { + src: 'common.js' + }] + }); +}; diff --git a/benchmarks/repeat-animate-bp/common.js b/benchmarks/repeat-animate-bp/common.js new file mode 100644 index 000000000000..18934d438df8 --- /dev/null +++ b/benchmarks/repeat-animate-bp/common.js @@ -0,0 +1,122 @@ +'use strict'; + +(function() { + var app = angular.module('repeatAnimateBenchmark'); + + var animateProvider; + + app.config(function($compileProvider, $animateProvider) { + if ($compileProvider.debugInfoEnabled) { + $compileProvider.debugInfoEnabled(false); + } + + }); + + app.run(function($animate) { + if ($animate.enabled) { + $animate.enabled(true); + } + }); + + app.controller('DataController', function($scope, $rootScope, $animate) { + var totalRows = 500; + var totalColumns = 20; + + var data = $scope.data = []; + + function fillData() { + if ($animate.enabled) { + $animate.enabled($scope.benchmarkType === 'globallyDisabled' ? false : true); + } + + for (var i=0; i<totalRows; i++) { + data[i] = []; + for (var j=0; j<totalColumns; j++) { + data[i][j] = { + i: i + }; + } + } + } + + benchmarkSteps.push({ + name: 'enter', + fn: function() { + $scope.$apply(function() { + fillData(); + }); + } + }); + + benchmarkSteps.push({ + name: 'leave', + fn: function() { + $scope.$apply(function() { + data = $scope.data = []; + }); + } + }); + }); + + app.directive('disableAnimations', function($animate) { + return { + link: { + pre: function(s, e) { + $animate.enabled(e, false); + } + } + }; + }); + + app.directive('noop', function($animate) { + return { + link: { + pre: angular.noop + } + }; + }); + + app.directive('baseline', function($document) { + return { + restrict: 'E', + link: function ($scope, $element) { + var document = $document[0]; + + var i, j, row, cell, comment; + var template = document.createElement('span'); + template.setAttribute('ng-repeat', 'foo in foos'); + template.classList.add('ng-scope'); + template.appendChild(document.createElement('span')); + template.appendChild(document.createTextNode(':')); + + function createList() { + for (i = 0; i < $scope.data.length; i++) { + row = document.createElement('div'); + $element[0].appendChild(row); + for (j = 0; j < $scope.data[i].length; j++) { + cell = template.cloneNode(true); + row.appendChild(cell); + cell.childNodes[0].textContent = i; + cell.ng3992 = 'xxx'; + comment = document.createComment('ngRepeat end: bar in foo'); + row.appendChild(comment); + } + + comment = document.createComment('ngRepeat end: foo in foos'); + $element[0].appendChild(comment); + } + } + + $scope.$watch('data.length', function(newVal) { + if (newVal === 0) { + while ($element[0].firstChild) { + $element[0].removeChild($element[0].firstChild); + } + } else { + createList(); + } + }); + } + }; + }); +})(); \ No newline at end of file diff --git a/benchmarks/repeat-animate-bp/main.html b/benchmarks/repeat-animate-bp/main.html new file mode 100644 index 000000000000..d7649592338e --- /dev/null +++ b/benchmarks/repeat-animate-bp/main.html @@ -0,0 +1,70 @@ +<div ng-app="repeatAnimateBenchmark" ng-cloak> + <div ng-controller="DataController"> + <div class="container-fluid"> + <p> + Tests rendering of an ngRepeat with 1000 elements.<br> + Animations can be enabled / disabled in different ways.<br> + Two tests require reloading the app with different module / app configurations. + </p> + + <div><label><input type="radio" ng-model="benchmarkType" value="none">none: </label></div> + <div><label><input type="radio" ng-model="benchmarkType" value="baseline">baseline (vanilla Javascript): </label></div> + <div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'default'" value="enabled">enabled : </label> (requires <a href="./">app.js</a>)</div> + <div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'default' && fileType !== 'classfilter'" value="globallyDisabled">globally disabled:</label> (requires <a href="./">app.js</a> or <a href="?app=app-classfilter.js">app-classfilter.js</a>)</div> + <div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'default'" value="disabledParentElement">disabled by $animate.enabled() on parent element: </label> (requires <a href="./">app.js</a>)</div> + <div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'noanimate'" value="noanimate">Without ngAnimate:</label> (requires <a href="?app=app-noanimate.js">app-noanimate.js</a>)</div> + <div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'classfilter'" value="disabledClassFilter">disabled by classNameFilter on element:</label> (requires <a href="?app=app-classfilter.js">app-classfilter.js</a>)</div> + + <ng-switch on="benchmarkType"> + <baseline ng-switch-when="baseline"> + </baseline> + <div ng-switch-when="noanimate"> + <div noop> + <div ng-repeat="row in data"> + <span ng-repeat="column in row"> + <span>{{column.i}}</span> + </span> + </div> + </div> + </div> + <div ng-switch-when="enabled"> + <div noop> + <div ng-repeat="row in data"> + <span ng-repeat="column in row"> + <span>{{column.i}}</span> + </span> + </div> + </div> + </div> + <div ng-switch-when="globallyDisabled"> + <div noop> + <div ng-repeat="row in data"> + <span ng-repeat="column in row"> + <span>{{column.i}}</span> + </span> + </div> + </div> + </div> + <div ng-switch-when="disabledClassFilter"> + <div noop> + <div ng-repeat="row in data"> + <span class="disable-animations" ng-repeat="column in row"> + <span>{{column.i}}</span> + </span> + </div> + </div> + </div> + <div ng-switch-when="disabledParentElement"> + <div disable-animations> + <div ng-repeat="row in data"> + <span ng-repeat="column in row"> + <span>{{column.i}}</span> + </span> + </div> + </div> + </div> + </ng-switch> + + </div> + </div> +</div>