parent
1272affe5c
commit
31f48ae943
|
@ -1,69 +1,51 @@
|
|||
'use strict';
|
||||
|
||||
/*
|
||||
* A module for adding new a routing system Angular 1.
|
||||
*/
|
||||
angular.module('ngComponentRouter', [])
|
||||
.directive('ngOutlet', ngOutletDirective)
|
||||
.directive('ngOutlet', ngOutletFillContentDirective)
|
||||
.directive('ngLink', ngLinkDirective);
|
||||
|
||||
/*
|
||||
* A module for inspecting controller constructors
|
||||
*/
|
||||
angular.module('ng')
|
||||
.provider('$$directiveIntrospector', $$directiveIntrospectorProvider)
|
||||
.config(compilerProviderDecorator);
|
||||
///<reference path="../typings/angularjs/angular.d.ts"/>
|
||||
|
||||
/*
|
||||
* decorates $compileProvider so that we have access to routing metadata
|
||||
*/
|
||||
function compilerProviderDecorator($compileProvider, $$directiveIntrospectorProvider) {
|
||||
var directive = $compileProvider.directive;
|
||||
$compileProvider.directive = function (name, factory) {
|
||||
function compilerProviderDecorator($compileProvider,
|
||||
$$directiveIntrospectorProvider: DirectiveIntrospectorProvider) {
|
||||
let directive = $compileProvider.directive;
|
||||
$compileProvider.directive = function(name: string, factory: Function) {
|
||||
$$directiveIntrospectorProvider.register(name, factory);
|
||||
return directive.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* private service that holds route mappings for each controller
|
||||
*/
|
||||
function $$directiveIntrospectorProvider() {
|
||||
var directiveBuffer = [];
|
||||
var directiveFactoriesByName = {};
|
||||
var onDirectiveRegistered = null;
|
||||
return {
|
||||
register: function (name, factory) {
|
||||
if (angular.isArray(factory)) {
|
||||
factory = factory[factory.length - 1];
|
||||
}
|
||||
directiveFactoriesByName[name] = factory;
|
||||
if (onDirectiveRegistered) {
|
||||
onDirectiveRegistered(name, factory);
|
||||
} else {
|
||||
directiveBuffer.push({name: name, factory: factory});
|
||||
}
|
||||
},
|
||||
$get: function () {
|
||||
var fn = function (newOnControllerRegistered) {
|
||||
onDirectiveRegistered = newOnControllerRegistered;
|
||||
while (directiveBuffer.length > 0) {
|
||||
var directive = directiveBuffer.pop();
|
||||
onDirectiveRegistered(directive.name, directive.factory);
|
||||
}
|
||||
};
|
||||
class DirectiveIntrospectorProvider {
|
||||
private directiveBuffer: any[] = [];
|
||||
private directiveFactoriesByName: {[name: string]: Function} = {};
|
||||
private onDirectiveRegistered: (name: string, factory: Function) => any = null;
|
||||
|
||||
fn.getTypeByName = function (name) {
|
||||
return directiveFactoriesByName[name];
|
||||
};
|
||||
|
||||
return fn;
|
||||
register(name: string, factory: Function) {
|
||||
if (angular.isArray(factory)) {
|
||||
factory = factory[factory.length - 1];
|
||||
}
|
||||
};
|
||||
}
|
||||
this.directiveFactoriesByName[name] = factory;
|
||||
if (this.onDirectiveRegistered) {
|
||||
this.onDirectiveRegistered(name, factory);
|
||||
} else {
|
||||
this.directiveBuffer.push({name: name, factory: factory});
|
||||
}
|
||||
}
|
||||
|
||||
$get() {
|
||||
let fn: any = newOnControllerRegistered => {
|
||||
this.onDirectiveRegistered = newOnControllerRegistered;
|
||||
while (this.directiveBuffer.length > 0) {
|
||||
let directive = this.directiveBuffer.pop();
|
||||
this.onDirectiveRegistered(directive.name, directive.factory);
|
||||
}
|
||||
};
|
||||
|
||||
fn.getTypeByName = name => this.directiveFactoriesByName[name];
|
||||
|
||||
return fn;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ngOutlet
|
||||
|
@ -79,8 +61,8 @@ function $$directiveIntrospectorProvider() {
|
|||
*
|
||||
* The value for the `ngOutlet` attribute is optional.
|
||||
*/
|
||||
function ngOutletDirective($animate, $q, $router) {
|
||||
var rootRouter = $router;
|
||||
function ngOutletDirective($animate, $q: ng.IQService, $router) {
|
||||
let rootRouter = $router;
|
||||
|
||||
return {
|
||||
restrict: 'AE',
|
||||
|
@ -89,117 +71,120 @@ function ngOutletDirective($animate, $q, $router) {
|
|||
priority: 400,
|
||||
require: ['?^^ngOutlet', 'ngOutlet'],
|
||||
link: outletLink,
|
||||
controller: function () {},
|
||||
controller: class {},
|
||||
controllerAs: '$$ngOutlet'
|
||||
};
|
||||
|
||||
function outletLink(scope, $element, attrs, ctrls, $transclude) {
|
||||
var outletName = attrs.ngOutlet || 'default',
|
||||
parentCtrl = ctrls[0],
|
||||
myCtrl = ctrls[1],
|
||||
router = (parentCtrl && parentCtrl.$$router) || rootRouter;
|
||||
function outletLink(scope, element, attrs, ctrls, $transclude) {
|
||||
class Outlet {
|
||||
constructor(private controller, private router) {}
|
||||
|
||||
myCtrl.$$currentComponent = null;
|
||||
private currentController;
|
||||
private currentInstruction;
|
||||
private currentScope;
|
||||
private currentElement;
|
||||
private previousLeaveAnimation;
|
||||
|
||||
var childRouter,
|
||||
currentController,
|
||||
currentInstruction,
|
||||
currentScope,
|
||||
currentElement,
|
||||
previousLeaveAnimation;
|
||||
private cleanupLastView() {
|
||||
if (this.previousLeaveAnimation) {
|
||||
$animate.cancel(this.previousLeaveAnimation);
|
||||
this.previousLeaveAnimation = null;
|
||||
}
|
||||
|
||||
function cleanupLastView() {
|
||||
if (previousLeaveAnimation) {
|
||||
$animate.cancel(previousLeaveAnimation);
|
||||
previousLeaveAnimation = null;
|
||||
if (this.currentScope) {
|
||||
this.currentScope.$destroy();
|
||||
this.currentScope = null;
|
||||
}
|
||||
if (this.currentElement) {
|
||||
this.previousLeaveAnimation = $animate.leave(this.currentElement);
|
||||
this.previousLeaveAnimation.then(() => this.previousLeaveAnimation = null);
|
||||
this.currentElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentScope) {
|
||||
currentScope.$destroy();
|
||||
currentScope = null;
|
||||
}
|
||||
if (currentElement) {
|
||||
previousLeaveAnimation = $animate.leave(currentElement);
|
||||
previousLeaveAnimation.then(function () {
|
||||
previousLeaveAnimation = null;
|
||||
});
|
||||
currentElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
router.registerPrimaryOutlet({
|
||||
reuse: function (instruction) {
|
||||
var next = $q.when(true);
|
||||
var previousInstruction = currentInstruction;
|
||||
currentInstruction = instruction;
|
||||
if (currentController && currentController.$onReuse) {
|
||||
next = $q.when(currentController.$onReuse(currentInstruction, previousInstruction));
|
||||
reuse(instruction) {
|
||||
let next = $q.when(true);
|
||||
let previousInstruction = this.currentInstruction;
|
||||
this.currentInstruction = instruction;
|
||||
if (this.currentController && this.currentController.$onReuse) {
|
||||
next = $q.when(
|
||||
this.currentController.$onReuse(this.currentInstruction, previousInstruction));
|
||||
}
|
||||
|
||||
return next;
|
||||
},
|
||||
canReuse: function (nextInstruction) {
|
||||
var result;
|
||||
if (!currentInstruction ||
|
||||
currentInstruction.componentType !== nextInstruction.componentType) {
|
||||
}
|
||||
|
||||
canReuse(nextInstruction) {
|
||||
let result;
|
||||
if (!this.currentInstruction ||
|
||||
this.currentInstruction.componentType !== nextInstruction.componentType) {
|
||||
result = false;
|
||||
} else if (currentController && currentController.$canReuse) {
|
||||
result = currentController.$canReuse(nextInstruction, currentInstruction);
|
||||
} else if (this.currentController && this.currentController.$canReuse) {
|
||||
result = this.currentController.$canReuse(nextInstruction, this.currentInstruction);
|
||||
} else {
|
||||
result = nextInstruction === currentInstruction ||
|
||||
angular.equals(nextInstruction.params, currentInstruction.params);
|
||||
result = nextInstruction === this.currentInstruction ||
|
||||
angular.equals(nextInstruction.params, this.currentInstruction.params);
|
||||
}
|
||||
return $q.when(result);
|
||||
},
|
||||
canDeactivate: function (instruction) {
|
||||
if (currentController && currentController.$canDeactivate) {
|
||||
return $q.when(currentController.$canDeactivate(instruction, currentInstruction));
|
||||
}
|
||||
|
||||
canDeactivate(instruction) {
|
||||
if (this.currentController && this.currentController.$canDeactivate) {
|
||||
return $q.when(
|
||||
this.currentController.$canDeactivate(instruction, this.currentInstruction));
|
||||
}
|
||||
return $q.when(true);
|
||||
},
|
||||
deactivate: function (instruction) {
|
||||
if (currentController && currentController.$onDeactivate) {
|
||||
return $q.when(currentController.$onDeactivate(instruction, currentInstruction));
|
||||
}
|
||||
return $q.when();
|
||||
},
|
||||
activate: function (instruction) {
|
||||
var previousInstruction = currentInstruction;
|
||||
currentInstruction = instruction;
|
||||
}
|
||||
|
||||
var componentName = myCtrl.$$componentName = instruction.componentType;
|
||||
|
||||
if (typeof componentName != 'string') {
|
||||
throw new Error('Component is not a string for ' + instruction.urlPath);
|
||||
}
|
||||
|
||||
myCtrl.$$routeParams = instruction.params;
|
||||
|
||||
myCtrl.$$template = '<div ' + dashCase(componentName) + '></div>';
|
||||
|
||||
myCtrl.$$router = router.childRouter(instruction.componentType);
|
||||
|
||||
var newScope = scope.$new();
|
||||
|
||||
var clone = $transclude(newScope, function (clone) {
|
||||
$animate.enter(clone, null, currentElement || $element);
|
||||
cleanupLastView();
|
||||
});
|
||||
|
||||
|
||||
currentElement = clone;
|
||||
currentScope = newScope;
|
||||
|
||||
// TODO: prefer the other directive retrieving the controller
|
||||
// by debug mode
|
||||
currentController = currentElement.children().eq(0).controller(componentName);
|
||||
|
||||
if (currentController && currentController.$onActivate) {
|
||||
return currentController.$onActivate(instruction, previousInstruction);
|
||||
deactivate(instruction) {
|
||||
if (this.currentController && this.currentController.$onDeactivate) {
|
||||
return $q.when(
|
||||
this.currentController.$onDeactivate(instruction, this.currentInstruction));
|
||||
}
|
||||
return $q.when();
|
||||
}
|
||||
});
|
||||
|
||||
activate(instruction) {
|
||||
let previousInstruction = this.currentInstruction;
|
||||
this.currentInstruction = instruction;
|
||||
|
||||
let componentName = this.controller.$$componentName = instruction.componentType;
|
||||
|
||||
if (typeof componentName !== 'string') {
|
||||
throw new Error('Component is not a string for ' + instruction.urlPath);
|
||||
}
|
||||
|
||||
this.controller.$$routeParams = instruction.params;
|
||||
this.controller.$$template = '<div ' + dashCase(componentName) + '></div>';
|
||||
this.controller.$$router = this.router.childRouter(instruction.componentType);
|
||||
|
||||
let newScope = scope.$new();
|
||||
|
||||
let clone = $transclude(newScope, clone => {
|
||||
$animate.enter(clone, null, this.currentElement || element);
|
||||
this.cleanupLastView();
|
||||
});
|
||||
|
||||
this.currentElement = clone;
|
||||
this.currentScope = newScope;
|
||||
|
||||
// TODO: prefer the other directive retrieving the controller
|
||||
// by debug mode
|
||||
this.currentController = this.currentElement.children().eq(0).controller(componentName);
|
||||
|
||||
if (this.currentController && this.currentController.$onActivate) {
|
||||
return this.currentController.$onActivate(instruction, previousInstruction);
|
||||
}
|
||||
return $q.when();
|
||||
}
|
||||
}
|
||||
|
||||
let parentCtrl = ctrls[0], myCtrl = ctrls[1],
|
||||
router = (parentCtrl && parentCtrl.$$router) || rootRouter;
|
||||
|
||||
myCtrl.$$currentComponent = null;
|
||||
|
||||
router.registerPrimaryOutlet(new Outlet(myCtrl, router));
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -210,14 +195,14 @@ function ngOutletFillContentDirective($compile) {
|
|||
restrict: 'EA',
|
||||
priority: -400,
|
||||
require: 'ngOutlet',
|
||||
link: function (scope, $element, attrs, ctrl) {
|
||||
var template = ctrl.$$template;
|
||||
$element.html(template);
|
||||
var link = $compile($element.contents());
|
||||
link: (scope, element, attrs, ctrl) => {
|
||||
let template = ctrl.$$template;
|
||||
element.html(template);
|
||||
let link = $compile(element.contents());
|
||||
link(scope);
|
||||
|
||||
// TODO: move to primary directive
|
||||
var componentInstance = scope[ctrl.$$componentName];
|
||||
let componentInstance = scope[ctrl.$$componentName];
|
||||
if (componentInstance) {
|
||||
ctrl.$$currentComponent = componentInstance;
|
||||
|
||||
|
@ -228,7 +213,6 @@ function ngOutletFillContentDirective($compile) {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @name ngLink
|
||||
* @description
|
||||
|
@ -240,9 +224,9 @@ function ngOutletFillContentDirective($compile) {
|
|||
* ## Example
|
||||
*
|
||||
* ```js
|
||||
* angular.module('myApp', ['ngFuturisticRouter'])
|
||||
* angular.module('myApp', ['ngComponentRouter'])
|
||||
* .controller('AppController', ['$router', function($router) {
|
||||
* $router.config({ path: '/user/:id' component: 'user' });
|
||||
* $router.config({ path: '/user/:id', component: 'user' });
|
||||
* this.user = { name: 'Brian', id: 123 };
|
||||
* });
|
||||
* ```
|
||||
|
@ -254,42 +238,35 @@ function ngOutletFillContentDirective($compile) {
|
|||
* ```
|
||||
*/
|
||||
function ngLinkDirective($router, $parse) {
|
||||
var rootRouter = $router;
|
||||
let rootRouter = $router;
|
||||
|
||||
return {
|
||||
require: '?^^ngOutlet',
|
||||
restrict: 'A',
|
||||
link: ngLinkDirectiveLinkFn
|
||||
};
|
||||
return {require: '?^^ngOutlet', restrict: 'A', link: ngLinkDirectiveLinkFn};
|
||||
|
||||
function ngLinkDirectiveLinkFn(scope, elt, attrs, ctrl) {
|
||||
var router = (ctrl && ctrl.$$router) || rootRouter;
|
||||
function ngLinkDirectiveLinkFn(scope, element, attrs, ctrl) {
|
||||
let router = (ctrl && ctrl.$$router) || rootRouter;
|
||||
if (!router) {
|
||||
return;
|
||||
}
|
||||
|
||||
var instruction = null;
|
||||
var link = attrs.ngLink || '';
|
||||
let instruction = null;
|
||||
let link = attrs.ngLink || '';
|
||||
|
||||
function getLink(params) {
|
||||
instruction = router.generate(params);
|
||||
return './' + angular.stringifyInstruction(instruction);
|
||||
}
|
||||
|
||||
var routeParamsGetter = $parse(link);
|
||||
let routeParamsGetter = $parse(link);
|
||||
// we can avoid adding a watcher if it's a literal
|
||||
if (routeParamsGetter.constant) {
|
||||
var params = routeParamsGetter();
|
||||
elt.attr('href', getLink(params));
|
||||
let params = routeParamsGetter();
|
||||
element.attr('href', getLink(params));
|
||||
} else {
|
||||
scope.$watch(function () {
|
||||
return routeParamsGetter(scope);
|
||||
}, function (params) {
|
||||
elt.attr('href', getLink(params));
|
||||
}, true);
|
||||
scope.$watch(() => routeParamsGetter(scope), params => element.attr('href', getLink(params)),
|
||||
true);
|
||||
}
|
||||
|
||||
elt.on('click', function (event) {
|
||||
element.on('click', event => {
|
||||
if (event.which !== 1 || !instruction) {
|
||||
return;
|
||||
}
|
||||
|
@ -300,9 +277,21 @@ function ngLinkDirective($router, $parse) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function dashCase(str) {
|
||||
return str.replace(/([A-Z])/g, function ($1) {
|
||||
return '-' + $1.toLowerCase();
|
||||
});
|
||||
function dashCase(str: string): string {
|
||||
return str.replace(/[A-Z]/g, match => '-' + match.toLowerCase());
|
||||
}
|
||||
|
||||
/*
|
||||
* A module for adding new a routing system Angular 1.
|
||||
*/
|
||||
angular.module('ngComponentRouter', [])
|
||||
.directive('ngOutlet', ngOutletDirective)
|
||||
.directive('ngOutlet', ngOutletFillContentDirective)
|
||||
.directive('ngLink', ngLinkDirective);
|
||||
|
||||
/*
|
||||
* A module for inspecting controller constructors
|
||||
*/
|
||||
angular.module('ng')
|
||||
.provider('$$directiveIntrospector', DirectiveIntrospectorProvider)
|
||||
.config(compilerProviderDecorator);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"version": "v4",
|
||||
"repo": "angular/DefinitelyTyped",
|
||||
"ref": "master",
|
||||
"path": "typings",
|
||||
"bundle": "typings/tsd.d.ts",
|
||||
"installed": {
|
||||
"angularjs/angular.d.ts": {
|
||||
"commit": "746b9a892629060bc853e792afff536e0ec4655e"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"preinstall": "node tools/npm/check-node-modules --purge",
|
||||
"postinstall": "node tools/npm/copy-npm-shrinkwrap && node tools/chromedriverpatch.js && webdriver-manager update && bower install && gulp pubget.dart && tsd reinstall --overwrite --clean --config modules/angular2/tsd.json && tsd reinstall --overwrite --clean --config tools/tsd.json",
|
||||
"postinstall": "node tools/npm/copy-npm-shrinkwrap && node tools/chromedriverpatch.js && webdriver-manager update && bower install && gulp pubget.dart && tsd reinstall --overwrite --clean --config modules/angular2/tsd.json && tsd reinstall --overwrite --clean --config tools/tsd.json && tsd reinstall --overwrite --config modules/angular1_router/tsd.json",
|
||||
"test": "gulp test.all.js && gulp test.all.dart"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
Loading…
Reference in New Issue