Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 0b6f1ce

Browse files
committed
feat(ngAnimate): add support for animation
1 parent 4bfb66c commit 0b6f1ce

25 files changed

+1611
-84
lines changed

angularFiles.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ angularFiles = {
99
'src/auto/injector.js',
1010

1111
'src/ng/anchorScroll.js',
12+
'src/ng/animation.js',
13+
'src/ng/animator.js',
1214
'src/ng/browser.js',
1315
'src/ng/cacheFactory.js',
1416
'src/ng/compile.js',
@@ -71,7 +73,6 @@ angularFiles = {
7173
'src/ngMock/angular-mocks.js',
7274
'src/ngMobile/mobile.js',
7375
'src/ngMobile/directive/ngClick.js',
74-
7576
'src/bootstrap/bootstrap.js'
7677
],
7778

@@ -103,6 +104,7 @@ angularFiles = {
103104
'test/ng/*.js',
104105
'test/ng/directive/*.js',
105106
'test/ng/filter/*.js',
107+
'test/ngAnimate/*.js',
106108
'test/ngCookies/*.js',
107109
'test/ngResource/*.js',
108110
'test/ngSanitize/*.js',

docs/spec/ngdocSpec.js

+16
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,22 @@ describe('ngdoc', function() {
475475
'<div><p>I am self.</p></div>');
476476
});
477477
});
478+
479+
describe('@animations', function() {
480+
it('should render @this', function() {
481+
var doc = new Doc('@name a\n@animations\nenter - Add text\nleave - Remove text\n');
482+
doc.ngdoc = 'filter';
483+
doc.parse();
484+
expect(doc.html()).toContain(
485+
'<h3 id="Animations">Animations</h3>\n' +
486+
'<div class="animations">' +
487+
'<ul>' +
488+
'<li>enter - Add text</li>' +
489+
'<li>leave - Remove text</li>' +
490+
'</ul>' +
491+
'</div>');
492+
});
493+
});
478494
});
479495

480496
describe('usage', function() {

docs/src/dom.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ DOM.prototype = {
8989
replace(/-+/gm, '-').
9090
replace(/-*$/gm, '');
9191
anchor = {'id': id};
92-
className = {'class': id.toLowerCase().replace(/[._]/mg, '-')};
92+
var classNameValue = id.toLowerCase().replace(/[._]/mg, '-');
93+
if(classNameValue == 'hide') classNameValue = '';
94+
className = {'class': classNameValue};
9395
}
9496
this.tag('h' + this.headingDepth, anchor, heading);
9597
if (content instanceof Array) {

docs/src/ngdoc.js

+54
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,18 @@ Doc.prototype = {
328328
});
329329
dom.html(param.description);
330330
});
331+
if(this.animations) {
332+
dom.h('Animations', this.animations, function(animations){
333+
dom.html('<ul>');
334+
var animations = animations.split("\n");
335+
animations.forEach(function(ani) {
336+
dom.html('<li>');
337+
dom.text(ani);
338+
dom.html('</li>');
339+
});
340+
dom.html('</ul>');
341+
});
342+
}
331343
},
332344

333345
html_usage_returns: function(dom) {
@@ -433,6 +445,48 @@ Doc.prototype = {
433445
dom.text('</' + element + '>');
434446
});
435447
}
448+
if(self.animations) {
449+
var animations = [], matches = self.animations.split("\n");
450+
matches.forEach(function(ani) {
451+
var name = ani.match(/^\s*(.+?)\s*-/)[1];
452+
animations.push(name);
453+
});
454+
455+
dom.html('with <span id="animations">animations</span>');
456+
var comment;
457+
if(animations.length == 1) {
458+
comment = 'The ' + animations[0] + ' animation is supported';
459+
}
460+
else {
461+
var rhs = animations[animations.length-1];
462+
var lhs = '';
463+
for(var i=0;i<animations.length-1;i++) {
464+
if(i>0) {
465+
lhs += ', ';
466+
}
467+
lhs += animations[i];
468+
}
469+
comment = 'The ' + lhs + ' and ' + rhs + ' animations are supported';
470+
}
471+
var element = self.element || 'ANY';
472+
dom.code(function() {
473+
dom.text('//' + comment + "\n");
474+
dom.text('<' + element + ' ');
475+
dom.text(dashCase(self.shortName));
476+
renderParams('\n ', '="', '"', true);
477+
dom.text(' ng-animate="{');
478+
animations.forEach(function(ani, index) {
479+
if (index) {
480+
dom.text(', ');
481+
}
482+
dom.text(ani + ': \'' + ani + '-animation\'');
483+
});
484+
dom.text('}">\n ...\n');
485+
dom.text('</' + element + '>');
486+
});
487+
488+
dom.html('<a href="api/ng.$animator#Methods">Click here</a> to learn more about the steps involved in the animation.');
489+
}
436490
}
437491
self.html_usage_directiveInfo(dom);
438492
self.html_usage_parameters(dom);

lib/showdown/showdown-0.9.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -977,9 +977,9 @@ var _EncodeCode = function(text) {
977977

978978
var _DoItalicsAndBold = function(text) {
979979

980-
// <strong> must go first:
980+
// ** must go first:
981981
text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,
982-
"<strong>$2</strong>");
982+
"**$2</strong>");
983983

984984
text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
985985
"<em>$2</em>");
@@ -1293,4 +1293,4 @@ var escapeCharacters_callback = function(wholeMatch,m1) {
12931293
return "~E"+charCodeToEscape+"E";
12941294
}
12951295

1296-
} // end of Showdown.converter
1296+
} // end of Showdown.converter

src/Angular.js

+5
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ function inherit(parent, extra) {
247247
return extend(new (extend(function() {}, {prototype:parent}))(), extra);
248248
}
249249

250+
var START_SPACE = /^\s*/;
251+
var END_SPACE = /\s*$/;
252+
function stripWhitespace(str) {
253+
return isString(str) ? str.replace(START_SPACE, '').replace(END_SPACE, '') : str;
254+
}
250255

251256
/**
252257
* @ngdoc function

src/AngularPublic.js

+2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ function publishExternalAPI(angular){
107107
directive(ngEventDirectives);
108108
$provide.provider({
109109
$anchorScroll: $AnchorScrollProvider,
110+
$animation: $AnimationProvider,
111+
$animator: $AnimatorProvider,
110112
$browser: $BrowserProvider,
111113
$cacheFactory: $CacheFactoryProvider,
112114
$controller: $ControllerProvider,

src/loader.js

+27
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,33 @@ function setupModuleLoader(window) {
163163
*/
164164
constant: invokeLater('$provide', 'constant', 'unshift'),
165165

166+
/**
167+
* @ngdoc method
168+
* @name angular.Module#animation
169+
* @methodOf angular.Module
170+
* @param {string} name animation name
171+
* @param {Function} animationFactory Factory function for creating new instance of an animation.
172+
* @description
173+
*
174+
* Defines an animation hook that can be later used with {@link ng.directive:ngAnimate ngAnimate}
175+
* alongside {@link ng.directive:ngAnimate#Description common ng directives} as well as custom directives.
176+
* <pre>
177+
* module.animation('animation-name', function($inject1, $inject2) {
178+
* return {
179+
* //this gets called in preparation to setup an animation
180+
* setup : function(element) { ... },
181+
*
182+
* //this gets called once the animation is run
183+
* start : function(element, done, memo) { ... }
184+
* }
185+
* })
186+
* </pre>
187+
*
188+
* See {@link ng.$animationProvider#register $animationProvider.register()} and
189+
* {@link ng.directive:ngAnimate ngAnimate} for more information.
190+
*/
191+
animation: invokeLater('$animationProvider', 'register'),
192+
166193
/**
167194
* @ngdoc method
168195
* @name angular.Module#filter

src/ng/animation.js

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* @ngdoc object
3+
* @name ng.$animationProvider
4+
* @description
5+
*
6+
* The $AnimationProvider provider allows developers to register and access custom JavaScript animations directly inside
7+
* of a module.
8+
*
9+
*/
10+
$AnimationProvider.$inject = ['$provide'];
11+
function $AnimationProvider($provide) {
12+
var suffix = 'Animation';
13+
14+
/**
15+
* @ngdoc function
16+
* @name ng.$animation#register
17+
* @methodOf ng.$animationProvider
18+
*
19+
* @description
20+
* Registers a new injectable animation factory function. The factory function produces the animation object which
21+
* has these two properties:
22+
*
23+
* * `setup`: `function(Element):*` A function which receives the starting state of the element. The purpose
24+
* of this function is to get the element ready for animation. Optionally the function returns an memento which
25+
* is passed to the `start` function.
26+
* * `start`: `function(Element, doneFunction, *)` The element to animate, the `doneFunction` to be called on
27+
* element animation completion, and an optional memento from the `setup` function.
28+
*
29+
* @param {string} name The name of the animation.
30+
* @param {function} factory The factory function that will be executed to return the animation object.
31+
*
32+
*/
33+
this.register = function(name, factory) {
34+
$provide.factory(camelCase(name) + suffix, factory);
35+
};
36+
37+
this.$get = ['$injector', function($injector) {
38+
/**
39+
* @ngdoc function
40+
* @name ng.$animation
41+
* @function
42+
*
43+
* @description
44+
* The $animation service is used to retrieve any defined animation functions. When executed, the $animation service
45+
* will return a object that contains the setup and start functions that were defined for the animation.
46+
*
47+
* @param {String} name Name of the animation function to retrieve. Animation functions are registered and stored
48+
* inside of the AngularJS DI so a call to $animate('custom') is the same as injecting `customAnimation`
49+
* via dependency injection.
50+
* @return {Object} the animation object which contains the `setup` and `start` functions that perform the animation.
51+
*/
52+
return function $animation(name) {
53+
if (name) {
54+
try {
55+
return $injector.get(camelCase(name) + suffix);
56+
} catch (e) {
57+
//TODO(misko): this is a hack! we should have a better way to test if the injector has a given key.
58+
// The issue is that the animations are optional, and if not present they should be silently ignored.
59+
// The proper way to fix this is to add API onto the injector so that we can ask to see if a given
60+
// animation is supported.
61+
}
62+
}
63+
}
64+
}];
65+
};

0 commit comments

Comments
 (0)