Skip to content

Commit

Permalink
feat(ngAnimate): add support for animation
Browse files Browse the repository at this point in the history
  • Loading branch information
mhevery committed Apr 2, 2013
1 parent 4bfb66c commit 0b6f1ce
Show file tree
Hide file tree
Showing 25 changed files with 1,611 additions and 84 deletions.
4 changes: 3 additions & 1 deletion angularFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ angularFiles = {
'src/auto/injector.js',

'src/ng/anchorScroll.js',
'src/ng/animation.js',
'src/ng/animator.js',
'src/ng/browser.js',
'src/ng/cacheFactory.js',
'src/ng/compile.js',
Expand Down Expand Up @@ -71,7 +73,6 @@ angularFiles = {
'src/ngMock/angular-mocks.js',
'src/ngMobile/mobile.js',
'src/ngMobile/directive/ngClick.js',

'src/bootstrap/bootstrap.js'
],

Expand Down Expand Up @@ -103,6 +104,7 @@ angularFiles = {
'test/ng/*.js',
'test/ng/directive/*.js',
'test/ng/filter/*.js',
'test/ngAnimate/*.js',
'test/ngCookies/*.js',
'test/ngResource/*.js',
'test/ngSanitize/*.js',
Expand Down
16 changes: 16 additions & 0 deletions docs/spec/ngdocSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,22 @@ describe('ngdoc', function() {
'<div><p>I am self.</p></div>');
});
});

describe('@animations', function() {
it('should render @this', function() {
var doc = new Doc('@name a\n@animations\nenter - Add text\nleave - Remove text\n');
doc.ngdoc = 'filter';
doc.parse();
expect(doc.html()).toContain(
'<h3 id="Animations">Animations</h3>\n' +
'<div class="animations">' +
'<ul>' +
'<li>enter - Add text</li>' +
'<li>leave - Remove text</li>' +
'</ul>' +
'</div>');
});
});
});

describe('usage', function() {
Expand Down
4 changes: 3 additions & 1 deletion docs/src/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ DOM.prototype = {
replace(/-+/gm, '-').
replace(/-*$/gm, '');
anchor = {'id': id};
className = {'class': id.toLowerCase().replace(/[._]/mg, '-')};
var classNameValue = id.toLowerCase().replace(/[._]/mg, '-');
if(classNameValue == 'hide') classNameValue = '';
className = {'class': classNameValue};
}
this.tag('h' + this.headingDepth, anchor, heading);
if (content instanceof Array) {
Expand Down
54 changes: 54 additions & 0 deletions docs/src/ngdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,18 @@ Doc.prototype = {
});
dom.html(param.description);
});
if(this.animations) {
dom.h('Animations', this.animations, function(animations){
dom.html('<ul>');
var animations = animations.split("\n");
animations.forEach(function(ani) {
dom.html('<li>');
dom.text(ani);
dom.html('</li>');
});
dom.html('</ul>');
});
}
},

html_usage_returns: function(dom) {
Expand Down Expand Up @@ -433,6 +445,48 @@ Doc.prototype = {
dom.text('</' + element + '>');
});
}
if(self.animations) {
var animations = [], matches = self.animations.split("\n");
matches.forEach(function(ani) {
var name = ani.match(/^\s*(.+?)\s*-/)[1];
animations.push(name);
});

dom.html('with <span id="animations">animations</span>');
var comment;
if(animations.length == 1) {
comment = 'The ' + animations[0] + ' animation is supported';
}
else {
var rhs = animations[animations.length-1];
var lhs = '';
for(var i=0;i<animations.length-1;i++) {
if(i>0) {
lhs += ', ';
}
lhs += animations[i];
}
comment = 'The ' + lhs + ' and ' + rhs + ' animations are supported';
}
var element = self.element || 'ANY';
dom.code(function() {
dom.text('//' + comment + "\n");
dom.text('<' + element + ' ');
dom.text(dashCase(self.shortName));
renderParams('\n ', '="', '"', true);
dom.text(' ng-animate="{');
animations.forEach(function(ani, index) {
if (index) {
dom.text(', ');
}
dom.text(ani + ': \'' + ani + '-animation\'');
});
dom.text('}">\n ...\n');
dom.text('</' + element + '>');
});

dom.html('<a href="api/ng.$animator#Methods">Click here</a> to learn more about the steps involved in the animation.');
}
}
self.html_usage_directiveInfo(dom);
self.html_usage_parameters(dom);
Expand Down
6 changes: 3 additions & 3 deletions lib/showdown/showdown-0.9.js
Original file line number Diff line number Diff line change
Expand Up @@ -977,9 +977,9 @@ var _EncodeCode = function(text) {

var _DoItalicsAndBold = function(text) {

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

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

} // end of Showdown.converter
} // end of Showdown.converter
5 changes: 5 additions & 0 deletions src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,11 @@ function inherit(parent, extra) {
return extend(new (extend(function() {}, {prototype:parent}))(), extra);
}

var START_SPACE = /^\s*/;
var END_SPACE = /\s*$/;
function stripWhitespace(str) {
return isString(str) ? str.replace(START_SPACE, '').replace(END_SPACE, '') : str;
}

/**
* @ngdoc function
Expand Down
2 changes: 2 additions & 0 deletions src/AngularPublic.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ function publishExternalAPI(angular){
directive(ngEventDirectives);
$provide.provider({
$anchorScroll: $AnchorScrollProvider,
$animation: $AnimationProvider,
$animator: $AnimatorProvider,
$browser: $BrowserProvider,
$cacheFactory: $CacheFactoryProvider,
$controller: $ControllerProvider,
Expand Down
27 changes: 27 additions & 0 deletions src/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,33 @@ function setupModuleLoader(window) {
*/
constant: invokeLater('$provide', 'constant', 'unshift'),

/**
* @ngdoc method
* @name angular.Module#animation
* @methodOf angular.Module
* @param {string} name animation name
* @param {Function} animationFactory Factory function for creating new instance of an animation.
* @description
*
* Defines an animation hook that can be later used with {@link ng.directive:ngAnimate ngAnimate}
* alongside {@link ng.directive:ngAnimate#Description common ng directives} as well as custom directives.
* <pre>
* module.animation('animation-name', function($inject1, $inject2) {
* return {
* //this gets called in preparation to setup an animation
* setup : function(element) { ... },
*
* //this gets called once the animation is run
* start : function(element, done, memo) { ... }
* }
* })
* </pre>
*
* See {@link ng.$animationProvider#register $animationProvider.register()} and
* {@link ng.directive:ngAnimate ngAnimate} for more information.
*/
animation: invokeLater('$animationProvider', 'register'),

/**
* @ngdoc method
* @name angular.Module#filter
Expand Down
65 changes: 65 additions & 0 deletions src/ng/animation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* @ngdoc object
* @name ng.$animationProvider
* @description
*
* The $AnimationProvider provider allows developers to register and access custom JavaScript animations directly inside
* of a module.
*
*/
$AnimationProvider.$inject = ['$provide'];
function $AnimationProvider($provide) {
var suffix = 'Animation';

/**
* @ngdoc function
* @name ng.$animation#register
* @methodOf ng.$animationProvider
*
* @description
* Registers a new injectable animation factory function. The factory function produces the animation object which
* has these two properties:
*
* * `setup`: `function(Element):*` A function which receives the starting state of the element. The purpose
* of this function is to get the element ready for animation. Optionally the function returns an memento which
* is passed to the `start` function.
* * `start`: `function(Element, doneFunction, *)` The element to animate, the `doneFunction` to be called on
* element animation completion, and an optional memento from the `setup` function.
*
* @param {string} name The name of the animation.
* @param {function} factory The factory function that will be executed to return the animation object.
*
*/
this.register = function(name, factory) {
$provide.factory(camelCase(name) + suffix, factory);
};

this.$get = ['$injector', function($injector) {
/**
* @ngdoc function
* @name ng.$animation
* @function
*
* @description
* The $animation service is used to retrieve any defined animation functions. When executed, the $animation service
* will return a object that contains the setup and start functions that were defined for the animation.
*
* @param {String} name Name of the animation function to retrieve. Animation functions are registered and stored
* inside of the AngularJS DI so a call to $animate('custom') is the same as injecting `customAnimation`
* via dependency injection.
* @return {Object} the animation object which contains the `setup` and `start` functions that perform the animation.
*/
return function $animation(name) {
if (name) {
try {
return $injector.get(camelCase(name) + suffix);
} catch (e) {
//TODO(misko): this is a hack! we should have a better way to test if the injector has a given key.
// The issue is that the animations are optional, and if not present they should be silently ignored.
// The proper way to fix this is to add API onto the injector so that we can ask to see if a given
// animation is supported.
}
}
}
}];
};
Loading

0 comments on commit 0b6f1ce

Please sign in to comment.