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

Begin route change #968

Merged
merged 8 commits into from
Jun 2, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/content/cookbook/deeplinking.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ In this example we have a simple app which consist of two screens:
angular.module('deepLinking', ['ngSanitize'])
.config(function($routeProvider) {
$routeProvider.
when("/welcome", {template:'welcome.html', controller:WelcomeCntl}).
when("/settings", {template:'settings.html', controller:SettingsCntl});
when("/welcome", {templateUrl:'welcome.html', controller:WelcomeCntl}).
when("/settings", {templateUrl:'settings.html', controller:SettingsCntl});
});

AppCntl.$inject = ['$scope', '$route']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ provided by Angular's web framework:
$provide.factory('routeTemplateMonitor',
['$route', 'batchLog', '$rootScope',
function($route, batchLog, $rootScope) {
$rootScope.$on('$afterRouteChange', function() {
$rootScope.$on('$routeChangeSuccess', function() {
batchLog($route.current ? $route.current.template : null);
});
}]);
Expand Down
4 changes: 2 additions & 2 deletions docs/content/tutorial/step_07.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ __`app/js/app.js`:__
angular.module('phonecat', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {template: 'partials/phone-list.html', controller: PhoneListCtrl}).
when('/phones/:phoneId', {template: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
}]);
</pre>
Expand Down
2 changes: 1 addition & 1 deletion docs/src/ngdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Doc.prototype = {
function extractWords(text) {
var tokens = text.toLowerCase().split(/[,\.\`\'\"\#\s]+/mg);
tokens.forEach(function(key){
var match = key.match(/^(([\$\_a-z]|ng\:)[\w\_\-]{2,})/);
var match = key.match(/^(([\$\_a-z]|ng\:)[\w\_\-]+)/);
if (match){
key = match[1];
if (!keywords[key]) {
Expand Down
4 changes: 2 additions & 2 deletions example/temp.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<script>
setupModuleLoader(window);
angular.module('example', [], function($routeProvider) {
$routeProvider.when('/view1', {controller: MyCtrl, template: 'view1.html'});
$routeProvider.when('/view2', {controller: MyCtrl, template: 'view2.html'});
$routeProvider.when('/view1', {controller: MyCtrl, templateUrl: 'view1.html'});
$routeProvider.when('/view2', {controller: MyCtrl, templateUrl: 'view2.html'});

function MyCtrl($location, $scope) {
$scope.url = function() {
Expand Down
5 changes: 4 additions & 1 deletion src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -913,10 +913,13 @@ function angularInit(element, bootstrap) {
function bootstrap(element, modules) {
element = jqLite(element);
modules = modules || [];
modules.unshift(['$provide', function($provide) {
$provide.value('$rootElement', element);
}]);
modules.unshift('ng');
var injector = createInjector(modules);
injector.invoke(
['$rootScope', '$compile', '$injector', function(scope, compile, injector){
['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){
scope.$apply(function() {
element.data('$injector', injector);
compile(element)(scope);
Expand Down
142 changes: 115 additions & 27 deletions src/auto/injector.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,32 @@ var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(.+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
function inferInjectionArgs(fn) {
assertArgFn(fn);
if (!fn.$inject) {
var args = fn.$inject = [];
var fnText = fn.toString().replace(STRIP_COMMENTS, '');
var argDecl = fnText.match(FN_ARGS);
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
arg.replace(FN_ARG, function(all, underscore, name){
args.push(name);
function annotate(fn) {
var $inject,
fnText,
argDecl,
last;

if (typeof fn == 'function') {
if (!($inject = fn.$inject)) {
$inject = [];
fnText = fn.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS);
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
arg.replace(FN_ARG, function(all, underscore, name){
$inject.push(name);
});
});
});
fn.$inject = $inject;
}
} else if (isArray(fn)) {
last = fn.length - 1;
assertArgFn(fn[last], 'fn')
$inject = fn.slice(0, last);
} else {
assertArgFn(fn, 'fn', true);
}
return fn.$inject;
return $inject;
}

///////////////////////////////////////
Expand Down Expand Up @@ -152,6 +165,87 @@ function inferInjectionArgs(fn) {
* @returns {Object} new instance of `Type`.
*/

/**
* @ngdoc method
* @name angular.module.AUTO.$injector#annotate
* @methodOf angular.module.AUTO.$injector
*
* @description
* Returns an array of service names which the function is requesting for injection. This API is used by the injector
* to determine which services need to be injected into the function when the function is invoked. There are three
* ways in which the function can be annotated with the needed dependencies.
*
* # Argument names
*
* The simplest form is to extract the dependencies from the arguments of the function. This is done by converting
* the function into a string using `toString()` method and extracting the argument names.
* <pre>
* // Given
* function MyController($scope, $route) {
* // ...
* }
*
* // Then
* expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
* </pre>
*
* This method does not work with code minfication / obfuscation. For this reason the following annotation strategies
* are supported.
*
* # The `$injector` property
*
* If a function has an `$inject` property and its value is an array of strings, then the strings represent names of
* services to be injected into the function.
* <pre>
* // Given
* var MyController = function(obfuscatedScope, obfuscatedRoute) {
* // ...
* }
* // Define function dependencies
* MyController.$inject = ['$scope', '$route'];
*
* // Then
* expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
* </pre>
*
* # The array notation
*
* It is often desirable to inline Injected functions and that's when setting the `$inject` property is very
* inconvenient. In these situations using the array notation to specify the dependencies in a way that survives
* minification is a better choice:
*
* <pre>
* // We wish to write this (not minification / obfuscation safe)
* injector.invoke(function($compile, $rootScope) {
* // ...
* });
*
* // We are forced to write break inlining
* var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
* // ...
* };
* tmpFn.$inject = ['$compile', '$rootScope'];
* injector.invoke(tempFn);
*
* // To better support inline function the inline annotation is supported
* injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
* // ...
* }]);
*
* // Therefore
* expect(injector.annotate(
* ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
* ).toEqual(['$compile', '$rootScope']);
* </pre>
*
* @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described
* above.
*
* @returns {Array.<string>} The names of the services which the function requires.
*/




/**
* @ngdoc object
Expand Down Expand Up @@ -454,30 +548,23 @@ function createInjector(modulesToLoad) {

function invoke(fn, self, locals){
var args = [],
$inject,
length,
$inject = annotate(fn),
length, i,
key;

if (typeof fn == 'function') {
$inject = inferInjectionArgs(fn);
length = $inject.length;
} else {
if (isArray(fn)) {
$inject = fn;
length = $inject.length - 1;
fn = $inject[length];
}
assertArgFn(fn, 'fn');
}

for(var i = 0; i < length; i++) {
for(i = 0, length = $inject.length; i < length; i++) {
key = $inject[i];
args.push(
locals && locals.hasOwnProperty(key)
? locals[key]
: getService(key, path)
);
}
if (!fn.$inject) {
// this means that we must be an array.
fn = fn[length];
}


// Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
switch (self ? -1 : args.length) {
Expand Down Expand Up @@ -510,7 +597,8 @@ function createInjector(modulesToLoad) {
return {
invoke: invoke,
instantiate: instantiate,
get: getService
get: getService,
annotate: annotate
};
}
}
7 changes: 6 additions & 1 deletion src/bootstrap/bootstrap-prettify.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,12 @@ directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location',
$provide.value('$anchorScroll', angular.noop);
$provide.value('$browser', $browser);
$provide.provider('$location', function() {
this.$get = function() { return $location; };
this.$get = ['$rootScope', function($rootScope) {
docsRootScope.$on('$locationChangeSuccess', function(event, oldUrl, newUrl) {
$rootScope.$broadcast('$locationChangeSuccess', oldUrl, newUrl);
});
return $location;
}];
this.html5Mode = angular.noop;
});
$provide.decorator('$defer', ['$rootScope', '$delegate', function($rootScope, $delegate) {
Expand Down
70 changes: 31 additions & 39 deletions src/ng/directive/ngView.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@
<file name="script.js">
angular.module('ngView', [], function($routeProvider, $locationProvider) {
$routeProvider.when('/Book/:bookId', {
template: 'book.html',
templateUrl: 'book.html',
controller: BookCntl
});
$routeProvider.when('/Book/:bookId/ch/:chapterId', {
template: 'chapter.html',
templateUrl: 'chapter.html',
controller: ChapterCntl
});

Expand Down Expand Up @@ -112,11 +112,10 @@ var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$c
restrict: 'ECA',
terminal: true,
link: function(scope, element, attr) {
var changeCounter = 0,
lastScope,
var lastScope,
onloadExp = attr.onload || '';

scope.$on('$afterRouteChange', update);
scope.$on('$routeChangeSuccess', update);
update();


Expand All @@ -127,43 +126,36 @@ var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$c
}
}

function clearContent() {
element.html('');
destroyLastScope();
}

function update() {
var template = $route.current && $route.current.template,
thisChangeId = ++changeCounter;

function clearContent() {
// ignore callback if another route change occured since
if (thisChangeId === changeCounter) {
element.html('');
destroyLastScope();
}
}
var locals = $route.current && $route.current.locals,
template = locals && locals.$template;

if (template) {
$http.get(template, {cache: $templateCache}).success(function(response) {
// ignore callback if another route change occured since
if (thisChangeId === changeCounter) {
element.html(response);
destroyLastScope();

var link = $compile(element.contents()),
current = $route.current,
controller;

lastScope = current.scope = scope.$new();
if (current.controller) {
controller = $controller(current.controller, {$scope: lastScope});
element.contents().data('$ngControllerController', controller);
}

link(lastScope);
lastScope.$emit('$viewContentLoaded');
lastScope.$eval(onloadExp);

// $anchorScroll might listen on event...
$anchorScroll();
}
}).error(clearContent);
element.html(template);
destroyLastScope();

var link = $compile(element.contents()),
current = $route.current,
controller;

lastScope = current.scope = scope.$new();
if (current.controller) {
locals.$scope = lastScope;
controller = $controller(current.controller, locals);
element.contents().data('$ngControllerController', controller);
}

link(lastScope);
lastScope.$emit('$viewContentLoaded');
lastScope.$eval(onloadExp);

// $anchorScroll might listen on event...
$anchorScroll();
} else {
clearContent();
}
Expand Down
Loading