提交 1ffd0eda 编写于 作者: Y Your Name

修复节点编译失败问题

上级 57b77549

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
{
"directory":"bower_components"
}
\ No newline at end of file
{
"development": {
"serverUrl": "/",
"nodeServerUrl":"/nodeHttpServer/",
"isDebug":true,
"assetUrl":"app/",
"PRODUCT_TYPE":"online",
"COOKIE_CONFIG":{
"path":"/",
"domain":"localhost"
},
"WEBSOCKET_PORT":11204
},
"production": {
"serverUrl": "../",
"nodeServerUrl":"../nodeHttpServer/",
"isDebug":false,
"assetUrl":"",
"PRODUCT_TYPE":"online",
"COOKIE_CONFIG":{
"path":"/",
"domain":".eolinker.com"
},
"WEBSOCKET_PORT":1204
},
"test": {
"serverUrl": "../",
"nodeServerUrl":"../nodeHttpServer/",
"isDebug":false,
"assetUrl":"",
"PRODUCT_TYPE":"online",
"COOKIE_CONFIG":{
"path":"/",
"domain":".eolinker.com"
},
"WEBSOCKET_PORT":11204
}
}
\ No newline at end of file
{
"name": "goku",
"version": "1.0.0",
"authors": [
"广州银云信息科技有限公司 "
],
"description": "",
"main": "",
"moduleType": [],
"license": "MIT",
"homepage": "",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"angular-ui-router": "^0.4.0",
"angular-resource": "^1.5.0",
"oclazyload": "^1.0.9",
"angular-md5": "^0.1.10"
},
"overrides": {}
}
require 'compass/import-once/activate'
Encoding.default_external = Encoding.find('utf-8')
# Require any additional compass plugins here.
# bootstrap 已经包含normalize
# require 'compass-normalize'
# Set this to the root of your project when deployed:
http_path = "/"
# project_path = ""
css_dir = ".tmp/serve/app"
sass_dir = "src/app"
images_dir = "src/assets/images"
javascripts_dir = "src/app/"
sprite_load_path = ["src/assets/images/sprite"]
# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
# output_style = :expanded
# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
sourcemap = true
# 使用绝对路径方便调试http://sass-lang.com/documentation/file.SASS_REFERENCE.html#options
sass_options = {:sourcemap => :file}
\ No newline at end of file
var gulp = require('gulp'),
argv = require('minimist'),
path = require('path'),
config = require('./config'),
$ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'event-stream', 'main-bower-files', 'uglify-save-license', 'del']
}),
gulpsync = $.sync(gulp),
sass = require('gulp-sass'),
replace = require('gulp-replace');
let eoSetPointSrc = () => {
let pointLangIsEn = argv(process.argv.slice(2)).en;
if(pointLangIsEn){
config.paths.src = '.tmp/enApp';
config.vendor.base.dest='.tmp/enApp/app'
}
}
gulp.task('dev-config', function () {
eoSetPointSrc();
return gulp.src('app.conf.json')
.pipe($.ngConfig(config.modules.ConstantModuleName, {
environment: 'development',
createModule: false,
wrap: true
}))
.pipe(gulp.dest(path.join(config.paths.src, '/app'))) //join() 方法用于把数组中的所有元素放入一个字符串。
});
gulp.task('prod-config', function () {
eoSetPointSrc();
return gulp.src('app.conf.json')
.pipe($.ngConfig(config.modules.ConstantModuleName, {
environment: 'production',
createModule: false,
wrap: true //生成闭包
}))
.pipe(gulp.dest(path.join(config.paths.src, '/app')))
});
gulp.task('test-config', function () {
eoSetPointSrc();
return gulp.src('app.conf.json')
.pipe($.ngConfig(config.modules.ConstantModuleName, {
environment: 'test',
createModule: false,
wrap: true //生成闭包
}))
.pipe(gulp.dest(path.join(config.paths.src, '/app')))
});
gulp.task('clean:dist', function () {
$.del([path.join(config.paths.dist, '/')]);
});
/**
* [清理DIST,TEMP文件夹]
*/
gulp.task('clean', function () {
$.del([path.join(config.paths.dist, '/'), path.join(config.paths.tmp, '/')]);
});
gulp.task('vendor', gulpsync.sync(['vendor:base']));
/**
* [复制依赖文件]
*/
gulp.task('vendor:base', function () {
var jsFilter = $.filter('**/*.js', {
restore: true
}),
cssFilter = $.filter('**/*.css', {
restore: true
});
return gulp.src(config.vendor.base.source)
.pipe($.expectFile(config.vendor.base.source))
.pipe(jsFilter)
.pipe($.concat(config.vendor.base.name + '.js'))
.pipe(jsFilter.restore)
.pipe(cssFilter)
.pipe($.concat(config.vendor.base.name + '.scss'))
.pipe(cssFilter.restore)
.pipe(gulp.dest(config.vendor.base.dest));
});
gulp.task('vendor:app', function () {
var jsFilter = $.filter('*.js', {
restore: true
}),
cssFilter = $.filter('*.css', {
restore: true
});
return gulp.src(config.vendor.app.source, {
base: 'bower_components'
})
.pipe($.expectFile(config.vendor.app.source))
.pipe(jsFilter)
.pipe(jsFilter.restore)
.pipe(cssFilter)
.pipe(cssFilter.restore)
.pipe(gulp.dest(config.vendor.app.dest));
});
/**
* [图片压缩]
*/
gulp.task('images', function () {
return gulp.src([
path.join(config.paths.src, '/assets/images/**/*'),
path.join('!' + config.paths.src, '/assets/images/sprite/**/*')
])
.pipe($.imagemin({
progressive: true,
svgoPlugins: [{
removeViewBox: false
}],
use: [$.imageminPngquant()]
}))
.pipe(gulp.dest(path.join(config.paths.dist, '/assets/images')));
});
gulp.task('fonts', function () {
return gulp.src(config.vendor.base.source, {
base: 'bower_components'
})
.pipe($.filter('**/*.{eot,svg,ttf,woff,woff2}'))
.pipe($.flatten())
.pipe(gulp.dest(path.join(config.paths.dist, '/fonts/')));
});
/**
* [复制文件] 前端依赖库以及静态文件
*/
gulp.task('other:vendor', function () {
return gulp.src([
path.join(config.paths.src, '/vendor/**/*'),
])
.pipe($.filter(function (file) {
return file.stat.isFile();
}))
.pipe(gulp.dest(path.join(config.paths.dist, '/vendor')));
});
gulp.task('other:libs:js', function () {
return gulp.src([
path.join(config.paths.src, '/libs/**/*.js')
])
.pipe($.filter(function (file) {
return file.stat.isFile();
}))
// .pipe($.babel())
.pipe($.stripDebug())
.pipe($.uglify())
.pipe(gulp.dest(path.join(config.paths.dist, '/libs')));
});
gulp.task('other:libs', ['other:libs:js'], function () {
return gulp.src([
path.join(config.paths.src, '/libs/**/*'),
path.join('!' + config.paths.src, '/libs/**/*.js')
])
.pipe($.filter(function (file) {
return file.stat.isFile();
}))
.pipe(gulp.dest(path.join(config.paths.dist, '/libs')));
});
gulp.task('other:assets', function () {
return gulp.src([
path.join(config.paths.src, '/app/assets/**/*')
])
.pipe($.filter(function (file) {
return file.stat.isFile();
}))
.pipe(gulp.dest(path.join(config.paths.dist, '/assets')));
});
gulp.task('version:scar', function () {
gulp.src([
path.join(config.paths.src, '../version/*.md'),
])
.pipe(replace(/(position\s)([^\u4e00-\u9fa5].*)/g, function (match) {
return match.replace(/position\s/, "position " + config.version.scar).replace(/\\/g, "/");
}))
.pipe(gulp.dest(path.join(config.paths.version, '/file')));
});
gulp.task('version:lethe', function () {
gulp.src([
path.join(config.paths.src, '../version/*.md'),
])
.pipe(replace(/(position\s)([^\u4e00-\u9fa5].*)/g, function (match) {
return match.replace(/position\s/, "position " + config.version.lethe).replace(/\\/g, "/");
}))
.pipe(gulp.dest(path.join(config.paths.version, '/file')));
});
\ No newline at end of file
'use strict';
var gutil = require('gulp-util');// node require 动态加载gulp-util
exports.paths = {//node export/module.exports(m.e优先级最高) 将函数、变量等导出,以使其它JavaScript脚本通过require()函数引入并使用
src: 'src',
enTmp:'.tmp/enApp',
dist: 'dist',
tmp: '.tmp',
e2e: 'test_e2e',
env:{
},
version:'version'
};
exports.modules={
ConstantModuleName:'eolinker',
templateModuleName:'eolinker'
}
/**
* [依赖配置]
*/
exports.vendor = {
// 程序启动依赖模块
base: {
source: require('../vendor.base.json'),
dest: 'src/app',
name: 'vendor'
},
// 按需加载模块
app: {
source: require('../vendor.json'),
dest: 'src/vendor'
}
};
/**
* [版本配置]
*/
exports.version = {
scar:"file:///C:/eoLinker/cn-eo-ams",//scar
lethe: "file:///F:/git/am_fe" //lethe
};
/**
* 错误处理
*/
exports.errorHandler = function() {
return function (err) {
gutil.beep();/*# 发出滴声提示*/
gutil.log(err.toString());/*# 输出错误信息*/
}
};
'use strict';
var gulp = require('gulp'),
path = require('path'),
config = require('./config'),
_ = require('lodash'),
$ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'event-stream', 'main-bower-files', 'uglify-save-license', 'del']
}),
browserSync = require('browser-sync'),
reload = browserSync.reload; //实时刷新
const babel = require('gulp-babel');
/**
* [代码质量管理]
*/
gulp.task('jshint', function () {
return gulp.src([
path.join(config.paths.src, 'module/**/*.js'),
path.join(config.paths.src, 'app/**/*.js'),
// path.join(config.paths.src, '.tmp/**/*.js'),
path.join('!' + config.paths.src, 'module/**/module.js')
])
.pipe($.plumber(config.errorHandler()))
.pipe($.jshint())
// .pipe(reload({
// stream: true
// }))
.pipe($.size());
});
/**
* [编译之前将scss注入index.scss]
*/
gulp.task('inject_sass', function () {
/**
* @description module inject
*/
var injectFiles = gulp.src([
path.join(config.paths.src, 'module/**/*.scss'),
path.join('!' + config.paths.src, 'module/**/import.scss')
], {
read: false
});
var injectOptions = {
transform: function (filePath) {
filePath = filePath.replace(config.paths.src + '/module/', '../module/');
return '@import "' + filePath + '";';
},
starttag: '//injector',
endtag: '//endinjector',
addRootSlash: false
};
/**
* @description common inject
*/
var tmpInjectCommonFiles = gulp.src([
path.join(config.paths.src, 'app/**/*.scss'),
path.join('!' + config.paths.src, 'app/*.scss'),
path.join('!' + config.paths.src, 'app/**/import.scss'),
path.join('!' + config.paths.src, 'app/scss/common/animation.scss')
], {
read: false
});
var tmpInjectCommonOptions = {
transform: function (filePath) {
filePath = filePath.replace(config.paths.src + '/app/', './');
return '@import "' + filePath + '";';
},
starttag: '//common-scss-injector',
endtag: '//common-scss-end',
addRootSlash: false
};
return gulp.src([
path.join(config.paths.src, 'app/index.scss'),
path.join(config.paths.src, 'module/index.scss')
])
.pipe($.inject(injectFiles, injectOptions))
.pipe($.inject(tmpInjectCommonFiles, tmpInjectCommonOptions))
.pipe(gulp.dest(path.join(config.paths.src, 'app/')))
});
gulp.task('clean:tmp', function () {
$.del([path.join(config.paths.tmp, '/')]);
});
gulp.task('clean', function () {
$.del([path.join(config.paths.dist, '/'), path.join(config.paths.tmp, '/')]);
});
/**
* [SASS预编译模块,依赖compass模块编译]
*/
gulp.task('styles:compass', ['inject_sass'], function () {
return gulp.src(path.join(config.paths.src, 'app/index.scss'))
.pipe($.plumber(config.errorHandler()))
.pipe($.compass({
config_file: path.join(__dirname, '/../config.rb'),
css: path.join(config.paths.tmp, '/serve/app/'),
sass: path.join(config.paths.src, '/app/'),
}))
//sprite图片路径修复
.pipe($.replace('../../../src/assets/images/', '../assets/images/'))
.pipe(gulp.dest(path.join(config.paths.tmp, '/serve/app/')))
//css改变时无刷新改变页面
.pipe(reload({
stream: true
}));
});
gulp.task('styles:theme:compass', function () {
return gulp.src(path.join(config.paths.src, '/theme/*.scss'))
.pipe($.plumber(config.errorHandler()))
.pipe($.compass({
config_file: path.join(__dirname, '/../config.rb'),
css: path.join(config.paths.tmp, '/serve/app/theme/'),
sass: path.join(config.paths.src, '/theme/')
}))
.pipe(gulp.dest(path.join(config.paths.tmp, '/serve/app/theme/')))
//css改变时无刷新改变页面
.pipe(reload({
stream: true
}));
});
/**
* [Html中的CSS以及JS注入]
*/
gulp.task('inject', ['build:tmpHtml:app','build:tmpHtml:module','jshint', 'styles:compass','vendor:base'], function () {
var injectStyles = gulp.src([
path.join(config.paths.tmp, '/serve/app/**/*.css'),
path.join(config.paths.tmp, '/serve/module/**/*.css'),
'!' + path.join(config.paths.tmp, '/serve/app/theme/*.css')
], {
read: false
});
var injectScripts = gulp.src([
path.join(config.paths.src, '/module/**/*.js'),
path.join(config.paths.src, '/app/**/*.js'),
path.join(config.paths.tmp, '/serve/**/*TmpHtml.js'),
// path.join('!' + config.paths.src, '/.tmp/vendor.js'),
path.join('!' + config.paths.src, '/app/vendor.js'),
path.join('!' + config.paths.src, 'module/**/module.js')
])
.pipe(babel({
"presets": ["stage-3", "es2015"]
}))
.pipe($.angularFilesort());
var injectOptions = {
ignorePath: [config.paths.src, path.join(config.paths.tmp, '/serve')],
addRootSlash: false
};
return gulp.src(path.join(config.paths.src, '/*.html'))
.pipe($.plumber(config.errorHandler()))
.pipe($.inject($.eventStream.merge(
injectStyles,
injectScripts
), injectOptions))
.pipe(gulp.dest(path.join(config.paths.tmp, '/serve')));
});
\ No newline at end of file
'use strict';
var gulp = require('gulp'),
config = require('./config'),
path = require('path'),
browserSync = require('browser-sync'),
proxyMiddleware = require('http-proxy-middleware'),
browserSyncSpa = require('browser-sync-spa');
gulp.task('watch', ['inject', 'vendor'], function () {
//监控index.html,和bower.json文件
// gulp.watch([path.join(config.paths.src, '/*.html'), 'bower.json', 'vendor.base.json', 'vendor.json'], ['inject']);
//监控CSS文件
gulp.watch([
path.join(config.paths.src, '/app/**/*.scss'),
path.join(config.paths.src, '/module/**/*.scss')
], function (event) {
if (event.type === 'changed') {
gulp.start('styles:compass');
} else {
gulp.start('inject');
}
});
gulp.watch([
path.join(config.paths.src, '/theme/**/*.scss')
], function (event) {
if (event.type === 'changed') {
gulp.start('styles:theme:compass');
browserSync.reload(event.path);
}
});
//监控JS文件
gulp.watch([
path.join(config.paths.src, '/module/**/*.js'),
path.join(config.paths.src, '/app/**/*.js'),
path.join('!' + config.paths.src, 'module/**/module.js')
], function (event) {
if (event.type === 'changed') {
gulp.start('jshint');
browserSync.reload(event.path);
} else {
gulp.start('inject');
}
});
//监控html文件
gulp.watch([
path.join(config.paths.src, '/app/**/*.html'),
path.join(config.paths.src, '/module/**/*.html'),
path.join('!' + config.paths.src, '/**/*.tmp.html')
], function (event) {
browserSync.reload(event.path);
});
gulp.watch([
path.join(config.paths.src, '/app/**/*.tmp.html'),
], function (event) {
gulp.start('build:tmpHtml:app');
browserSync.reload(event.path);
});
gulp.watch([
path.join(config.paths.src, '/module/**/*.tmp.html'),
], function (event) {
gulp.start('build:tmpHtml:module');
browserSync.reload(event.path);
});
});
function browserSyncInit(baseDir, open, port) {
var onProxyRes = function (proxyRes, req, res) {
// 重写set-cookie位置
if (proxyRes.headers['set-cookie']) {
proxyRes.headers['set-cookie'][0] = proxyRes.headers['set-cookie'][0].replace('domain=.eolinker.com', 'domain=localhost')
}
}
browserSync.use(browserSyncSpa({
selector: '[ng-app]'
}));
browserSync.init({
startPath: '/', //zh-cn/
port: port || 3000,
// https: true,
open: open || false, //决定Browsersync启动时自动打开的网址。默认为“本地” false://停止自动打开浏览器
server: {
baseDir: baseDir,
routes: {
"/bower_components": "bower_components"
},
//使用代理
middleware: [
proxyMiddleware(['/config','/cluster','/balance', '/apis', '/strategy', '/node', '/plugin', '/auth', '/project', '/guest', '/import', '/gateway', '/user', '/message','/account', '/permission', '/monitor'], {
onProxyRes: onProxyRes,
target: 'http://127.0.0.1',
changeOrigin: true,
secure: false
})
]
}
});
}
exports.browserSyncInit = browserSyncInit;
gulp.task('serve', ['clean:tmp', 'dev-config', 'watch'], function () {
browserSyncInit([path.join(config.paths.tmp, '/serve'), config.paths.src], true);
});
\ No newline at end of file
'use strict';
var gulp = require('gulp'),
path = require('path'),
fs = require('fs'),
config = require('./config'),
_ = require('lodash'),
$ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'event-stream', 'main-bower-files', 'uglify-save-license', 'del']
}),
browserSync = require('browser-sync'),
gulpsync = $.sync(gulp),
reload = browserSync.reload; //实时刷新
const babel = require('gulp-babel');
/**
* [编译之前将scss注入index.scss]
*/
gulp.task('clear_inject_sass', function () {
var injectFiles = gulp.src([
path.join(config.paths.src, 'module/_default/**/*.scss')
], {
read: false
});
var injectOptions = {
transform: function (filePath) {
filePath = filePath.replace(config.paths.src + '/module/', '../module/');
return '@import "' + filePath + '";';
},
starttag: '//injector',
endtag: '//endinjector',
addRootSlash: false
};
return gulp.src([path.join(config.paths.src, 'app/index.scss')])
.pipe($.inject(injectFiles, injectOptions))
.pipe(gulp.dest(path.join(config.paths.src, 'app/')))
});
/**
* [代码质量管理]
*/
gulp.task('build:jshint', function () {
return gulp.src([
path.join(config.paths.src, '/module/_default/**/*.js'),
path.join(config.paths.src, 'app/**/*.js')
])
.pipe($.plumber(config.errorHandler()))
.pipe($.jshint())
.pipe(reload({
stream: true
}))
.pipe($.size())
});
/**
* [SASS预编译模块,依赖compass模块编译]
*/
gulp.task('build:styles:compass', function () {
return gulp.src(path.join(config.paths.src, 'app/index.scss'))
.pipe($.plumber(config.errorHandler()))
.pipe($.compass({
config_file: path.join(__dirname, '/../config.rb'),
css: path.join(config.paths.tmp, '/serve/app/'),
sass: path.join(config.paths.src, '/app/'),
}))
//sprite图片路径修复
.pipe($.replace('../../../src/assets/images/', '../assets/images/'))
.pipe(gulp.dest(path.join(config.paths.tmp, '/serve/app/')))
//css改变时无刷新改变页面
.pipe(reload({
stream: true
}));
});
gulp.task('build:styles:theme:compass', function () {
return gulp.src(path.join(config.paths.src, '/theme/*.scss'))
.pipe($.plumber(config.errorHandler()))
.pipe($.compass({
config_file: path.join(__dirname, '/../config.rb'),
css: path.join(config.paths.tmp, '/serve/app/theme/'),
sass: path.join(config.paths.src, '/theme/')
}))
.pipe(gulp.dest(path.join(config.paths.dist, '/theme/')))
});
/**
* [生成Html模版文件]
*/
gulp.task('build:tmpHtml:app', function () {
return gulp.src([
path.join(config.paths.src, '/app/**/*.tmp.html')
])
.pipe($.minifyHtml({
empty: true,
spare: true,
quotes: true
}))
.pipe($.angularTemplatecache('eoAppTmpHtml.js', {
module: config.modules.templateModuleName,
root: 'app'
}))
.pipe(gulp.dest(config.paths.tmp + '//serve/'));
});
gulp.task('build:tmpHtml:module', function () {
return gulp.src([
path.join(config.paths.src, '/module/**/*.tmp.html')
])
.pipe($.minifyHtml({
empty: true,
spare: true,
quotes: true
}))
.pipe($.angularTemplatecache('eoModuleTmpHtml.js', {
module: config.modules.templateModuleName,
root: 'module'
}))
.pipe(gulp.dest(config.paths.tmp + '//serve/'));
});
/**
* [Html中的CSS以及JS注入]
*/
gulp.task('build:inject', ['build:jshint', 'build:styles:compass', 'vendor:base'], function () {
var injectStyles = gulp.src([
path.join(config.paths.tmp, '/serve/app/**/*.css'),
path.join(config.paths.src, 'module/_default/**/*.scss'),
'!' + path.join(config.paths.tmp, '/serve/app/theme/*.css')
], {
read: false
});
var injectScripts = gulp.src([
path.join(config.paths.src, '/app/**/*.js'),
path.join(config.paths.src, '/module/_default/**/*.js'),
path.join('!' + config.paths.src, '/app/vendor.js'),
])
.pipe(babel({
"presets": ["stage-3", "es2015"]
}))
.pipe($.angularFilesort())
.pipe(gulp.dest(config.paths.tmp + '/serve/app/'))
var injectOptions = {
ignorePath: [config.paths.src, path.join(config.paths.tmp, '/serve')],
addRootSlash: false
};
return gulp.src(path.join(config.paths.src, '/*.html'))
.pipe($.plumber(config.errorHandler()))
.pipe($.inject($.eventStream.merge(
injectStyles,
injectScripts
), injectOptions))
.pipe(gulp.dest(path.join(config.paths.tmp, '/serve')));
});
\ No newline at end of file
'use strict';
/**
* @name 编译
* @author 广州银云信息科技有限公司
*/
/**
* @version 4.0
* @description 去掉图片压缩&字体压缩
*/
var gulp = require('gulp');
var path = require('path');
var config = require('./config');
var _ = require('lodash');
var $ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del', 'imagemin-pngquant']
});
var sass = require('gulp-sass');
var replace = require('gulp-replace');
/**
* [生成Html模版文件]
*/
gulp.task('build:partials', function () {
return gulp.src([
path.join(config.paths.src, '/app/**/*.html')
])
.pipe($.minifyHtml({
empty: true,
spare: true,
quotes: true
}))
.pipe($.angularTemplatecache('templateCacheHtml.js', {
module: config.modules.templateModuleName,
root: 'app'
}))
.pipe(gulp.dest(config.paths.tmp + '/partials/'));
});
gulp.task('build:partials:_default', function () {
return gulp.src([
path.join(config.paths.src, '/module/_default/**/*.html')
])
.pipe($.minifyHtml({
empty: true,
spare: true,
quotes: true
}))
.pipe($.angularTemplatecache('_default_templateCacheHtml.js', {
module: config.modules.templateModuleName,
root: 'module/_default'
}))
.pipe(gulp.dest(config.paths.tmp + '/partials/'));
});
/**
* [Html,Js,Css压缩合并]
*/
gulp.task('build:html', ['build:inject', 'build:partials','build:partials:_default'], function () {
var partialsInjectFile = gulp.src([path.join(config.paths.tmp, '/partials/templateCacheHtml.js'),path.join(config.paths.tmp, '/partials/_default_templateCacheHtml.js')], {
read: false
});
var partialsInjectOptions = {
starttag: '<!-- inject:partials -->',
ignorePath: path.join(config.paths.tmp, '/partials'),
addRootSlash: false
};
var htmlFilter = $.filter('*.html', {
restore: true
});
var jsFilter = $.filter('**/*.js', {
restore: true
});
var cssFilter = $.filter('**/*.css', {
restore: true
});
return gulp.src(path.join(config.paths.tmp, '/serve/*.html'))
//error
.pipe($.plumber(config.errorHandler()))
//inject template
.pipe($.inject(partialsInjectFile, partialsInjectOptions))
//js
.pipe($.useref()) //合并和压缩
.pipe(jsFilter)
//修复HTML图片地址
.pipe($.replace('app/assets/', 'assets/'))
.pipe($.stripDebug())
.pipe($.uglify())
.pipe(jsFilter.restore)
//css
.pipe(cssFilter)
//修复HTML图片地址
.pipe($.replace('app/assets/', 'assets/'))
.pipe($.replace('(assets/', '(../assets/'))
.pipe($.autoprefixer({
browsers: ['last 20 versions'],
cascade: false
}))
.pipe($.csso())
.pipe(cssFilter.restore)
//md5后缀
.pipe($.if('*.css', $.rev()))
.pipe($.if('*.js', $.rev()))
//替换md5后缀的文件名
.pipe($.revReplace())
//html处理
.pipe(htmlFilter)
// .pipe($.replace('<base href="/">', '<base href="/eolinker/">'))
// .pipe($.minifyHtml({
// empty: true,
// spare: true,
// quotes: true,
// conditionals: true
// }))
.pipe(htmlFilter.restore)
.pipe(gulp.dest(path.join(config.paths.dist, '/')))
.pipe($.size({
title: path.join(config.paths.dist, '/'),
showFiles: true
}));
});
gulp.task('build', $.sequence('prod-config', ['clean', 'clear_inject_sass', 'build:html'],'other:vendor', 'other:libs', 'other:assets'));//,'translate'
gulp.task('build:e2e', $.sequence('test-config', ['clean', 'build:html'],'other:vendor', 'other:libs', 'other:assets'));
\ No newline at end of file
'use strict';
var gulp = require('gulp'),
config = require('./config'),
browserSync = require('browser-sync'),
proxyMiddleware = require('http-proxy-middleware'),
browserSyncSpa = require('browser-sync-spa');
function browserSyncInit(baseDir, open, port) {
var onProxyRes = function (proxyRes, req, res) {
// 重写set-cookie位置
if (proxyRes.headers['set-cookie']) {
proxyRes.headers['set-cookie'][0] = proxyRes.headers['set-cookie'][0].replace('domain=.eolinker.com', 'domain=localhost')
}
}
browserSync.use(browserSyncSpa({
selector: '[ng-app]'
}));
browserSync.init({
startPath: '/', //zh-cn/
port: port || 3000,
https: true,
open: open || false, //决定Browsersync启动时自动打开的网址。默认为“本地” false://停止自动打开浏览器
server: {
baseDir: baseDir,
routes: {
"/bower_components": "bower_components"
},
//使用代理
middleware: [
proxyMiddleware(['/apis','/strategy','/node','/plugin','/auth','/project','/guest','/balance','/import','/gateway','/user','/message','/account','/permission','/monitor'], {onProxyRes: onProxyRes, target: 'http://47.95.203.198:10003', changeOrigin: true,secure: false})
]
}
});
}
exports.browserSyncInit = browserSyncInit;
gulp.task('serve:dist', ['build'], function () {
browserSyncInit(config.paths.dist, true);
});
\ No newline at end of file
'use strict';
var gulp = require('gulp');
var fs = require('fs');
fs.readdirSync('./gulp').forEach(function (file) {
if((/\.(js|coffee)$/i).test(file)){
require('./gulp/' + file);
}
});
gulp.task('default', ['clean'], function () {
gulp.start('build');
});
\ No newline at end of file
{
"name": "angular-ui-router",
"version": "0.4.3",
"license": "MIT",
"main": "./release/angular-ui-router.js",
"dependencies": {
"angular": "^1.0.8"
},
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"component.json",
"package.json",
"lib",
"config",
"sample",
"test",
"tests",
"ngdoc_assets",
"Gruntfile.js",
"files.js"
],
"homepage": "https://github.com/angular-ui/angular-ui-router-bower",
"_release": "0.4.3",
"_resolution": {
"type": "version",
"tag": "0.4.3",
"commit": "ef38bc78495ec7719dcd6876886cf5a27420f330"
},
"_source": "https://github.com/angular-ui/angular-ui-router-bower.git",
"_target": "^0.4.0",
"_originalSource": "angular-ui-router"
}
\ No newline at end of file
# Report an Issue
Help us make UI-Router better! If you think you might have found a bug, or some other weirdness, start by making sure
it hasn't already been reported. You can [search through existing issues](https://github.com/angular-ui/ui-router/search?q=wat%3F&type=Issues)
to see if someone's reported one similar to yours.
If not, then [create a plunkr](http://bit.ly/UIR-Plunk) that demonstrates the problem (try to use as little code
as possible: the more minimalist, the faster we can debug it).
Next, [create a new issue](https://github.com/angular-ui/ui-router/issues/new) that briefly explains the problem,
and provides a bit of background as to the circumstances that triggered it. Don't forget to include the link to
that plunkr you created!
**Note**: If you're unsure how a feature is used, or are encountering some unexpected behavior that you aren't sure
is a bug, it's best to talk it out on
[StackOverflow](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) before reporting it. This
keeps development streamlined, and helps us focus on building great software.
Issues only! |
-------------|
Please keep in mind that the issue tracker is for *issues*. Please do *not* post an issue if you need help or support. Instead, see one of the above-mentioned forums or [IRC](irc://irc.freenode.net/#angularjs). |
####Purple Labels
A purple label means that **you** need to take some further action.
- ![Not Actionable - Need Info](ngdoc_assets/incomplete.png): Your issue is not specific enough, or there is no clear action that we can take. Please clarify and refine your issue.
- ![Plunkr Please](ngdoc_assets/example.png): Please [create a plunkr](http://bit.ly/UIR-Plunk)
- ![StackOverflow](ngdoc_assets/so.png): We suspect your issue is really a help request, or could be answered by the community. Please ask your question on [StackOverflow](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router). If you determine that is an actual issue, please explain why.
If your issue gets labeled with purple label, no further action will be taken until you respond to the label appropriately.
# Contribute
**(1)** See the **[Developing](#developing)** section below, to get the development version of UI-Router up and running on your local machine.
**(2)** Check out the [roadmap](https://github.com/angular-ui/ui-router/milestones) to see where the project is headed, and if your feature idea fits with where we're headed.
**(3)** If you're not sure, [open an RFC](https://github.com/angular-ui/ui-router/issues/new?title=RFC:%20My%20idea) to get some feedback on your idea.
**(4)** Finally, commit some code and open a pull request. Code & commits should abide by the following rules:
- *Always* have test coverage for new features (or regression tests for bug fixes), and *never* break existing tests
- Commits should represent one logical change each; if a feature goes through multiple iterations, squash your commits down to one
- Make sure to follow the [Angular commit message format](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit-message-format) so your change will appear in the changelog of the next release.
- Changes should always respect the coding style of the project
# Developing
UI-Router uses <code>grunt >= 0.4.x</code>. Make sure to upgrade your environment and read the
[Migration Guide](http://gruntjs.com/upgrading-from-0.3-to-0.4).
Dependencies for building from source and running tests:
* [grunt-cli](https://github.com/gruntjs/grunt-cli) - run: `$ npm install -g grunt-cli`
* Then, install the development dependencies by running `$ npm install` from the project directory
There are a number of targets in the gruntfile that are used to generating different builds:
* `grunt`: Perform a normal build, runs jshint and karma tests
* `grunt build`: Perform a normal build
* `grunt dist`: Perform a clean build and generate documentation
* `grunt dev`: Run dev server (sample app) and watch for changes, builds and runs karma tests on changes.
The MIT License
Copyright (c) 2013-2015 The AngularUI Team, Karsten Sperling
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# AngularUI Router &nbsp;[![Build Status](https://travis-ci.org/angular-ui/ui-router.svg?branch=master)](https://travis-ci.org/angular-ui/ui-router)
#### The de-facto solution to flexible routing with nested views
---
**[Download 0.2.18](https://cdn.rawgit.com/angular-ui/ui-router/0.2.18/release/angular-ui-router.js)** (or **[Minified](https://cdn.rawgit.com/angular-ui/ui-router/0.2.18/release/angular-ui-router.min.js)**) **|**
**[Guide](https://github.com/angular-ui/ui-router/wiki) |**
**[API](http://angular-ui.github.io/ui-router/site) |**
**[Sample](http://angular-ui.github.com/ui-router/sample/) ([Src](https://github.com/angular-ui/ui-router/tree/gh-pages/sample)) |**
**[FAQ](https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions) |**
**[Resources](#resources) |**
**[Report an Issue](https://github.com/angular-ui/ui-router/blob/master/CONTRIBUTING.md#report-an-issue) |**
**[Contribute](https://github.com/angular-ui/ui-router/blob/master/CONTRIBUTING.md#contribute) |**
**[Help!](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) |**
**[Discuss](https://groups.google.com/forum/#!categories/angular-ui/router)**
---
*_Please help us out by testing the 1.0 alpha release!_*
[1.0.0alpha0 Announcement](https://github.com/angular-ui/ui-router/releases/tag/1.0.0alpha0) ([Source Code](https://github.com/angular-ui/ui-router/tree/master)) | [Sample App](http://ui-router.github.io/sample-app/) ([Source Code](https://github.com/ui-router/sample-app)) | [Known Issues](https://github.com/angular-ui/ui-router/issues?q=is%3Aissue+is%3Aopen+label%3A1.0)
---
AngularUI Router is a routing framework for [AngularJS](http://angularjs.org), which allows you to organize the
parts of your interface into a [*state machine*](https://en.wikipedia.org/wiki/Finite-state_machine). Unlike the
[`$route` service](http://docs.angularjs.org/api/ngRoute.$route) in the Angular ngRoute module, which is organized around URL
routes, UI-Router is organized around [*states*](https://github.com/angular-ui/ui-router/wiki),
which may optionally have routes, as well as other behavior, attached.
States are bound to *named*, *nested* and *parallel views*, allowing you to powerfully manage your application's interface.
Check out the sample app: http://angular-ui.github.io/ui-router/sample/
-
**Note:** *UI-Router is under active development. As such, while this library is well-tested, the API may change. Consider using it in production applications only if you're comfortable following a changelog and updating your usage accordingly.*
## Get Started
**(1)** Get UI-Router in one of the following ways:
- clone & [build](CONTRIBUTING.md#developing) this repository
- [download the release](http://angular-ui.github.io/ui-router/release/angular-ui-router.js) (or [minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js))
- [link to cdn](http://cdnjs.com/libraries/angular-ui-router)
- via **[jspm](http://jspm.io/)**: by running `$ jspm install angular-ui-router` from your console
- or via **[npm](https://www.npmjs.org/)**: by running `$ npm install angular-ui-router` from your console
- or via **[Bower](http://bower.io/)**: by running `$ bower install angular-ui-router` from your console
- or via **[Component](https://github.com/component/component)**: by running `$ component install angular-ui/ui-router` from your console
**(2)** Include `angular-ui-router.js` (or `angular-ui-router.min.js`) in your `index.html`, after including Angular itself (For Component users: ignore this step)
**(3)** Add `'ui.router'` to your main module's list of dependencies (For Component users: replace `'ui.router'` with `require('angular-ui-router')`)
When you're done, your setup should look similar to the following:
>
```html
<!doctype html>
<html ng-app="myApp">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
<script src="js/angular-ui-router.min.js"></script>
<script>
var myApp = angular.module('myApp', ['ui.router']);
// For Component users, it should look like this:
// var myApp = angular.module('myApp', [require('angular-ui-router')]);
</script>
...
</head>
<body>
...
</body>
</html>
```
### [Nested States & Views](http://plnkr.co/edit/u18KQc?p=preview)
The majority of UI-Router's power is in its ability to nest states & views.
**(1)** First, follow the [setup](#get-started) instructions detailed above.
**(2)** Then, add a [`ui-view` directive](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-view) to the `<body />` of your app.
>
```html
<!-- index.html -->
<body>
<div ui-view></div>
<!-- We'll also add some navigation: -->
<a ui-sref="state1">State 1</a>
<a ui-sref="state2">State 2</a>
</body>
```
**(3)** You'll notice we also added some links with [`ui-sref` directives](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-sref). In addition to managing state transitions, this directive auto-generates the `href` attribute of the `<a />` element it's attached to, if the corresponding state has a URL. Next we'll add some templates. These will plug into the `ui-view` within `index.html`. Notice that they have their own `ui-view` as well! That is the key to nesting states and views.
>
```html
<!-- partials/state1.html -->
<h1>State 1</h1>
<hr/>
<a ui-sref="state1.list">Show List</a>
<div ui-view></div>
```
```html
<!-- partials/state2.html -->
<h1>State 2</h1>
<hr/>
<a ui-sref="state2.list">Show List</a>
<div ui-view></div>
```
**(4)** Next, we'll add some child templates. *These* will get plugged into the `ui-view` of their parent state templates.
>
```html
<!-- partials/state1.list.html -->
<h3>List of State 1 Items</h3>
<ul>
<li ng-repeat="item in items">{{ item }}</li>
</ul>
```
>
```html
<!-- partials/state2.list.html -->
<h3>List of State 2 Things</h3>
<ul>
<li ng-repeat="thing in things">{{ thing }}</li>
</ul>
```
**(5)** Finally, we'll wire it all up with `$stateProvider`. Set up your states in the module config, as in the following:
>
```javascript
myApp.config(function($stateProvider, $urlRouterProvider) {
//
// For any unmatched url, redirect to /state1
$urlRouterProvider.otherwise("/state1");
//
// Now set up the states
$stateProvider
.state('state1', {
url: "/state1",
templateUrl: "partials/state1.html"
})
.state('state1.list', {
url: "/list",
templateUrl: "partials/state1.list.html",
controller: function($scope) {
$scope.items = ["A", "List", "Of", "Items"];
}
})
.state('state2', {
url: "/state2",
templateUrl: "partials/state2.html"
})
.state('state2.list', {
url: "/list",
templateUrl: "partials/state2.list.html",
controller: function($scope) {
$scope.things = ["A", "Set", "Of", "Things"];
}
});
});
```
**(6)** See this quick start example in action.
>**[Go to Quick Start Plunker for Nested States & Views](http://plnkr.co/edit/u18KQc?p=preview)**
**(7)** This only scratches the surface
>**[Dive Deeper!](https://github.com/angular-ui/ui-router/wiki)**
### [Multiple & Named Views](http://plnkr.co/edit/SDOcGS?p=preview)
Another great feature is the ability to have multiple `ui-view`s view per template.
**Pro Tip:** *While multiple parallel views are a powerful feature, you'll often be able to manage your
interfaces more effectively by nesting your views, and pairing those views with nested states.*
**(1)** Follow the [setup](#get-started) instructions detailed above.
**(2)** Add one or more `ui-view` to your app, give them names.
>
```html
<!-- index.html -->
<body>
<div ui-view="viewA"></div>
<div ui-view="viewB"></div>
<!-- Also a way to navigate -->
<a ui-sref="route1">Route 1</a>
<a ui-sref="route2">Route 2</a>
</body>
```
**(3)** Set up your states in the module config:
>
```javascript
myApp.config(function($stateProvider) {
$stateProvider
.state('index', {
url: "",
views: {
"viewA": { template: "index.viewA" },
"viewB": { template: "index.viewB" }
}
})
.state('route1', {
url: "/route1",
views: {
"viewA": { template: "route1.viewA" },
"viewB": { template: "route1.viewB" }
}
})
.state('route2', {
url: "/route2",
views: {
"viewA": { template: "route2.viewA" },
"viewB": { template: "route2.viewB" }
}
})
});
```
**(4)** See this quick start example in action.
>**[Go to Quick Start Plunker for Multiple & Named Views](http://plnkr.co/edit/SDOcGS?p=preview)**
## Resources
* [In-Depth Guide](https://github.com/angular-ui/ui-router/wiki)
* [API Reference](http://angular-ui.github.io/ui-router/site)
* [Sample App](http://angular-ui.github.com/ui-router/sample/) ([Source](https://github.com/angular-ui/ui-router/tree/gh-pages/sample))
* [FAQ](https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions)
* [Slides comparing ngRoute to ui-router](http://slid.es/timkindberg/ui-router#/)
* [UI-Router Extras / Addons](http://christopherthielen.github.io/ui-router-extras/#/home) (@christopherthielen)
### Videos
* [Introduction Video](https://egghead.io/lessons/angularjs-introduction-ui-router) (egghead.io)
* [Tim Kindberg on Angular UI-Router](https://www.youtube.com/watch?v=lBqiZSemrqg)
* [Activating States](https://egghead.io/lessons/angularjs-ui-router-activating-states) (egghead.io)
* [Learn Angular.js using UI-Router](http://youtu.be/QETUuZ27N0w) (LearnCode.academy)
## Reporting issues and Contributing
Please read our [Contributor guidelines](CONTRIBUTING.md) before reporting an issue or creating a pull request.
{
"name": "angular-ui-router",
"version": "0.4.3",
"license" : "MIT",
"main": "./release/angular-ui-router.js",
"dependencies": {
"angular": "^1.0.8"
},
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"component.json",
"package.json",
"lib",
"config",
"sample",
"test",
"tests",
"ngdoc_assets",
"Gruntfile.js",
"files.js"
]
}
/*jshint globalstrict:true*/
/*global angular:false*/
'use strict';
var isDefined = angular.isDefined,
isFunction = angular.isFunction,
isString = angular.isString,
isObject = angular.isObject,
isArray = angular.isArray,
forEach = angular.forEach,
extend = angular.extend,
copy = angular.copy,
toJson = angular.toJson;
function inherit(parent, extra) {
return extend(new (extend(function() {}, { prototype: parent }))(), extra);
}
function merge(dst) {
forEach(arguments, function(obj) {
if (obj !== dst) {
forEach(obj, function(value, key) {
if (!dst.hasOwnProperty(key)) dst[key] = value;
});
}
});
return dst;
}
/**
* Finds the common ancestor path between two states.
*
* @param {Object} first The first state.
* @param {Object} second The second state.
* @return {Array} Returns an array of state names in descending order, not including the root.
*/
function ancestors(first, second) {
var path = [];
for (var n in first.path) {
if (first.path[n] !== second.path[n]) break;
path.push(first.path[n]);
}
return path;
}
/**
* IE8-safe wrapper for `Object.keys()`.
*
* @param {Object} object A JavaScript object.
* @return {Array} Returns the keys of the object as an array.
*/
function objectKeys(object) {
if (Object.keys) {
return Object.keys(object);
}
var result = [];
forEach(object, function(val, key) {
result.push(key);
});
return result;
}
/**
* IE8-safe wrapper for `Array.prototype.indexOf()`.
*
* @param {Array} array A JavaScript array.
* @param {*} value A value to search the array for.
* @return {Number} Returns the array index value of `value`, or `-1` if not present.
*/
function indexOf(array, value) {
if (Array.prototype.indexOf) {
return array.indexOf(value, Number(arguments[2]) || 0);
}
var len = array.length >>> 0, from = Number(arguments[2]) || 0;
from = (from < 0) ? Math.ceil(from) : Math.floor(from);
if (from < 0) from += len;
for (; from < len; from++) {
if (from in array && array[from] === value) return from;
}
return -1;
}
/**
* Merges a set of parameters with all parameters inherited between the common parents of the
* current state and a given destination state.
*
* @param {Object} currentParams The value of the current state parameters ($stateParams).
* @param {Object} newParams The set of parameters which will be composited with inherited params.
* @param {Object} $current Internal definition of object representing the current state.
* @param {Object} $to Internal definition of object representing state to transition to.
*/
function inheritParams(currentParams, newParams, $current, $to) {
var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = [];
for (var i in parents) {
if (!parents[i] || !parents[i].params) continue;
parentParams = objectKeys(parents[i].params);
if (!parentParams.length) continue;
for (var j in parentParams) {
if (indexOf(inheritList, parentParams[j]) >= 0) continue;
inheritList.push(parentParams[j]);
inherited[parentParams[j]] = currentParams[parentParams[j]];
}
}
return extend({}, inherited, newParams);
}
/**
* Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
*
* @param {Object} a The first object.
* @param {Object} b The second object.
* @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified,
* it defaults to the list of keys in `a`.
* @return {Boolean} Returns `true` if the keys match, otherwise `false`.
*/
function equalForKeys(a, b, keys) {
if (!keys) {
keys = [];
for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
}
for (var i=0; i<keys.length; i++) {
var k = keys[i];
if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
}
return true;
}
/**
* Returns the subset of an object, based on a list of keys.
*
* @param {Array} keys
* @param {Object} values
* @return {Boolean} Returns a subset of `values`.
*/
function filterByKeys(keys, values) {
var filtered = {};
forEach(keys, function (name) {
filtered[name] = values[name];
});
return filtered;
}
// like _.indexBy
// when you know that your index values will be unique, or you want last-one-in to win
function indexBy(array, propName) {
var result = {};
forEach(array, function(item) {
result[item[propName]] = item;
});
return result;
}
// extracted from underscore.js
// Return a copy of the object only containing the whitelisted properties.
function pick(obj) {
var copy = {};
var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
forEach(keys, function(key) {
if (key in obj) copy[key] = obj[key];
});
return copy;
}
// extracted from underscore.js
// Return a copy of the object omitting the blacklisted properties.
function omit(obj) {
var copy = {};
var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1));
for (var key in obj) {
if (indexOf(keys, key) == -1) copy[key] = obj[key];
}
return copy;
}
function pluck(collection, key) {
var result = isArray(collection) ? [] : {};
forEach(collection, function(val, i) {
result[i] = isFunction(key) ? key(val) : val[key];
});
return result;
}
function filter(collection, callback) {
var array = isArray(collection);
var result = array ? [] : {};
forEach(collection, function(val, i) {
if (callback(val, i)) {
result[array ? result.length : i] = val;
}
});
return result;
}
function map(collection, callback) {
var result = isArray(collection) ? [] : {};
forEach(collection, function(val, i) {
result[i] = callback(val, i);
});
return result;
}
// issue #2676 #2889
function silenceUncaughtInPromise (promise) {
return promise.then(undefined, function() {}) && promise;
}
/**
* @ngdoc overview
* @name ui.router.util
*
* @description
* # ui.router.util sub-module
*
* This module is a dependency of other sub-modules. Do not include this module as a dependency
* in your angular app (use {@link ui.router} module instead).
*
*/
angular.module('ui.router.util', ['ng']);
/**
* @ngdoc overview
* @name ui.router.router
*
* @requires ui.router.util
*
* @description
* # ui.router.router sub-module
*
* This module is a dependency of other sub-modules. Do not include this module as a dependency
* in your angular app (use {@link ui.router} module instead).
*/
angular.module('ui.router.router', ['ui.router.util']);
/**
* @ngdoc overview
* @name ui.router.state
*
* @requires ui.router.router
* @requires ui.router.util
*
* @description
* # ui.router.state sub-module
*
* This module is a dependency of the main ui.router module. Do not include this module as a dependency
* in your angular app (use {@link ui.router} module instead).
*
*/
angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']);
/**
* @ngdoc overview
* @name ui.router
*
* @requires ui.router.state
*
* @description
* # ui.router
*
* ## The main module for ui.router
* There are several sub-modules included with the ui.router module, however only this module is needed
* as a dependency within your angular app. The other modules are for organization purposes.
*
* The modules are:
* * ui.router - the main "umbrella" module
* * ui.router.router -
*
* *You'll need to include **only** this module as the dependency within your angular app.*
*
* <pre>
* <!doctype html>
* <html ng-app="myApp">
* <head>
* <script src="js/angular.js"></script>
* <!-- Include the ui-router script -->
* <script src="js/angular-ui-router.min.js"></script>
* <script>
* // ...and add 'ui.router' as a dependency
* var myApp = angular.module('myApp', ['ui.router']);
* </script>
* </head>
* <body>
* </body>
* </html>
* </pre>
*/
angular.module('ui.router', ['ui.router.state']);
angular.module('ui.router.compat', ['ui.router']);
/**
* @ngdoc object
* @name ui.router.util.$resolve
*
* @requires $q
* @requires $injector
*
* @description
* Manages resolution of (acyclic) graphs of promises.
*/
$Resolve.$inject = ['$q', '$injector'];
function $Resolve( $q, $injector) {
var VISIT_IN_PROGRESS = 1,
VISIT_DONE = 2,
NOTHING = {},
NO_DEPENDENCIES = [],
NO_LOCALS = NOTHING,
NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING });
/**
* @ngdoc function
* @name ui.router.util.$resolve#study
* @methodOf ui.router.util.$resolve
*
* @description
* Studies a set of invocables that are likely to be used multiple times.
* <pre>
* $resolve.study(invocables)(locals, parent, self)
* </pre>
* is equivalent to
* <pre>
* $resolve.resolve(invocables, locals, parent, self)
* </pre>
* but the former is more efficient (in fact `resolve` just calls `study`
* internally).
*
* @param {object} invocables Invocable objects
* @return {function} a function to pass in locals, parent and self
*/
this.study = function (invocables) {
if (!isObject(invocables)) throw new Error("'invocables' must be an object");
var invocableKeys = objectKeys(invocables || {});
// Perform a topological sort of invocables to build an ordered plan
var plan = [], cycle = [], visited = {};
function visit(value, key) {
if (visited[key] === VISIT_DONE) return;
cycle.push(key);
if (visited[key] === VISIT_IN_PROGRESS) {
cycle.splice(0, indexOf(cycle, key));
throw new Error("Cyclic dependency: " + cycle.join(" -> "));
}
visited[key] = VISIT_IN_PROGRESS;
if (isString(value)) {
plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES);
} else {
var params = $injector.annotate(value);
forEach(params, function (param) {
if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param);
});
plan.push(key, value, params);
}
cycle.pop();
visited[key] = VISIT_DONE;
}
forEach(invocables, visit);
invocables = cycle = visited = null; // plan is all that's required
function isResolve(value) {
return isObject(value) && value.then && value.$$promises;
}
return function (locals, parent, self) {
if (isResolve(locals) && self === undefined) {
self = parent; parent = locals; locals = null;
}
if (!locals) locals = NO_LOCALS;
else if (!isObject(locals)) {
throw new Error("'locals' must be an object");
}
if (!parent) parent = NO_PARENT;
else if (!isResolve(parent)) {
throw new Error("'parent' must be a promise returned by $resolve.resolve()");
}
// To complete the overall resolution, we have to wait for the parent
// promise and for the promise for each invokable in our plan.
var resolution = $q.defer(),
result = silenceUncaughtInPromise(resolution.promise),
promises = result.$$promises = {},
values = extend({}, locals),
wait = 1 + plan.length/3,
merged = false;
silenceUncaughtInPromise(result);
function done() {
// Merge parent values we haven't got yet and publish our own $$values
if (!--wait) {
if (!merged) merge(values, parent.$$values);
result.$$values = values;
result.$$promises = result.$$promises || true; // keep for isResolve()
delete result.$$inheritedValues;
resolution.resolve(values);
}
}
function fail(reason) {
result.$$failure = reason;
resolution.reject(reason);
}
// Short-circuit if parent has already failed
if (isDefined(parent.$$failure)) {
fail(parent.$$failure);
return result;
}
if (parent.$$inheritedValues) {
merge(values, omit(parent.$$inheritedValues, invocableKeys));
}
// Merge parent values if the parent has already resolved, or merge
// parent promises and wait if the parent resolve is still in progress.
extend(promises, parent.$$promises);
if (parent.$$values) {
merged = merge(values, omit(parent.$$values, invocableKeys));
result.$$inheritedValues = omit(parent.$$values, invocableKeys);
done();
} else {
if (parent.$$inheritedValues) {
result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys);
}
parent.then(done, fail);
}
// Process each invocable in the plan, but ignore any where a local of the same name exists.
for (var i=0, ii=plan.length; i<ii; i+=3) {
if (locals.hasOwnProperty(plan[i])) done();
else invoke(plan[i], plan[i+1], plan[i+2]);
}
function invoke(key, invocable, params) {
// Create a deferred for this invocation. Failures will propagate to the resolution as well.
var invocation = $q.defer(), waitParams = 0;
function onfailure(reason) {
invocation.reject(reason);
fail(reason);
}
// Wait for any parameter that we have a promise for (either from parent or from this
// resolve; in that case study() will have made sure it's ordered before us in the plan).
forEach(params, function (dep) {
if (promises.hasOwnProperty(dep) && !locals.hasOwnProperty(dep)) {
waitParams++;
promises[dep].then(function (result) {
values[dep] = result;
if (!(--waitParams)) proceed();
}, onfailure);
}
});
if (!waitParams) proceed();
function proceed() {
if (isDefined(result.$$failure)) return;
try {
invocation.resolve($injector.invoke(invocable, self, values));
invocation.promise.then(function (result) {
values[key] = result;
done();
}, onfailure);
} catch (e) {
onfailure(e);
}
}
// Publish promise synchronously; invocations further down in the plan may depend on it.
promises[key] = silenceUncaughtInPromise(invocation.promise);
}
return result;
};
};
/**
* @ngdoc function
* @name ui.router.util.$resolve#resolve
* @methodOf ui.router.util.$resolve
*
* @description
* Resolves a set of invocables. An invocable is a function to be invoked via
* `$injector.invoke()`, and can have an arbitrary number of dependencies.
* An invocable can either return a value directly,
* or a `$q` promise. If a promise is returned it will be resolved and the
* resulting value will be used instead. Dependencies of invocables are resolved
* (in this order of precedence)
*
* - from the specified `locals`
* - from another invocable that is part of this `$resolve` call
* - from an invocable that is inherited from a `parent` call to `$resolve`
* (or recursively
* - from any ancestor `$resolve` of that parent).
*
* The return value of `$resolve` is a promise for an object that contains
* (in this order of precedence)
*
* - any `locals` (if specified)
* - the resolved return values of all injectables
* - any values inherited from a `parent` call to `$resolve` (if specified)
*
* The promise will resolve after the `parent` promise (if any) and all promises
* returned by injectables have been resolved. If any invocable
* (or `$injector.invoke`) throws an exception, or if a promise returned by an
* invocable is rejected, the `$resolve` promise is immediately rejected with the
* same error. A rejection of a `parent` promise (if specified) will likewise be
* propagated immediately. Once the `$resolve` promise has been rejected, no
* further invocables will be called.
*
* Cyclic dependencies between invocables are not permitted and will cause `$resolve`
* to throw an error. As a special case, an injectable can depend on a parameter
* with the same name as the injectable, which will be fulfilled from the `parent`
* injectable of the same name. This allows inherited values to be decorated.
* Note that in this case any other injectable in the same `$resolve` with the same
* dependency would see the decorated value, not the inherited value.
*
* Note that missing dependencies -- unlike cyclic dependencies -- will cause an
* (asynchronous) rejection of the `$resolve` promise rather than a (synchronous)
* exception.
*
* Invocables are invoked eagerly as soon as all dependencies are available.
* This is true even for dependencies inherited from a `parent` call to `$resolve`.
*
* As a special case, an invocable can be a string, in which case it is taken to
* be a service name to be passed to `$injector.get()`. This is supported primarily
* for backwards-compatibility with the `resolve` property of `$routeProvider`
* routes.
*
* @param {object} invocables functions to invoke or
* `$injector` services to fetch.
* @param {object} locals values to make available to the injectables
* @param {object} parent a promise returned by another call to `$resolve`.
* @param {object} self the `this` for the invoked methods
* @return {object} Promise for an object that contains the resolved return value
* of all invocables, as well as any inherited and local values.
*/
this.resolve = function (invocables, locals, parent, self) {
return this.study(invocables)(locals, parent, self);
};
}
angular.module('ui.router.util').service('$resolve', $Resolve);
function parseStateRef(ref, current) {
var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed;
if (preparsed) ref = current + '(' + preparsed[1] + ')';
parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'");
return { state: parsed[1], paramExpr: parsed[3] || null };
}
function stateContext(el) {
var stateData = el.parent().inheritedData('$uiView');
if (stateData && stateData.state && stateData.state.name) {
return stateData.state;
}
}
function getTypeInfo(el) {
// SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]';
var isForm = el[0].nodeName === "FORM";
return {
attr: isForm ? "action" : (isSvg ? 'xlink:href' : 'href'),
isAnchor: el.prop("tagName").toUpperCase() === "A",
clickable: !isForm
};
}
function clickHook(el, $state, $timeout, type, current) {
return function(e) {
var button = e.which || e.button, target = current();
if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || el.attr('target'))) {
// HACK: This is to allow ng-clicks to be processed before the transition is initiated:
var transition = $timeout(function() {
$state.go(target.state, target.params, target.options);
});
e.preventDefault();
// if the state has no URL, ignore one preventDefault from the <a> directive.
var ignorePreventDefaultCount = type.isAnchor && !target.href ? 1: 0;
e.preventDefault = function() {
if (ignorePreventDefaultCount-- <= 0) $timeout.cancel(transition);
};
}
};
}
function defaultOpts(el, $state) {
return { relative: stateContext(el) || $state.$current, inherit: true };
}
/**
* @ngdoc directive
* @name ui.router.state.directive:ui-sref
*
* @requires ui.router.state.$state
* @requires $timeout
*
* @restrict A
*
* @description
* A directive that binds a link (`<a>` tag) to a state. If the state has an associated
* URL, the directive will automatically generate & update the `href` attribute via
* the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking
* the link will trigger a state transition with optional parameters.
*
* Also middle-clicking, right-clicking, and ctrl-clicking on the link will be
* handled natively by the browser.
*
* You can also use relative state paths within ui-sref, just like the relative
* paths passed to `$state.go()`. You just need to be aware that the path is relative
* to the state that the link lives in, in other words the state that loaded the
* template containing the link.
*
* You can specify options to pass to {@link ui.router.state.$state#methods_go $state.go()}
* using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`,
* and `reload`.
*
* @example
* Here's an example of how you'd use ui-sref and how it would compile. If you have the
* following template:
* <pre>
* <a ui-sref="home">Home</a> | <a ui-sref="about">About</a> | <a ui-sref="{page: 2}">Next page</a>
*
* <ul>
* <li ng-repeat="contact in contacts">
* <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a>
* </li>
* </ul>
* </pre>
*
* Then the compiled html would be (assuming Html5Mode is off and current state is contacts):
* <pre>
* <a href="#/home" ui-sref="home">Home</a> | <a href="#/about" ui-sref="about">About</a> | <a href="#/contacts?page=2" ui-sref="{page: 2}">Next page</a>
*
* <ul>
* <li ng-repeat="contact in contacts">
* <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a>
* </li>
* <li ng-repeat="contact in contacts">
* <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a>
* </li>
* <li ng-repeat="contact in contacts">
* <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a>
* </li>
* </ul>
*
* <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
* </pre>
*
* @param {string} ui-sref 'stateName' can be any valid absolute or relative state
* @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#methods_go $state.go()}
*/
$StateRefDirective.$inject = ['$state', '$timeout'];
function $StateRefDirective($state, $timeout) {
return {
restrict: 'A',
require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
link: function(scope, element, attrs, uiSrefActive) {
var ref = parseStateRef(attrs.uiSref, $state.current.name);
var def = { state: ref.state, href: null, params: null };
var type = getTypeInfo(element);
var active = uiSrefActive[1] || uiSrefActive[0];
var unlinkInfoFn = null;
var hookFn;
def.options = extend(defaultOpts(element, $state), attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {});
var update = function(val) {
if (val) def.params = angular.copy(val);
def.href = $state.href(ref.state, def.params, def.options);
if (unlinkInfoFn) unlinkInfoFn();
if (active) unlinkInfoFn = active.$$addStateInfo(ref.state, def.params);
if (def.href !== null) attrs.$set(type.attr, def.href);
};
if (ref.paramExpr) {
scope.$watch(ref.paramExpr, function(val) { if (val !== def.params) update(val); }, true);
def.params = angular.copy(scope.$eval(ref.paramExpr));
}
update();
if (!type.clickable) return;
hookFn = clickHook(element, $state, $timeout, type, function() { return def; });
element[element.on ? 'on' : 'bind']("click", hookFn);
scope.$on('$destroy', function() {
element[element.off ? 'off' : 'unbind']("click", hookFn);
});
}
};
}
/**
* @ngdoc directive
* @name ui.router.state.directive:ui-state
*
* @requires ui.router.state.uiSref
*
* @restrict A
*
* @description
* Much like ui-sref, but will accept named $scope properties to evaluate for a state definition,
* params and override options.
*
* @param {string} ui-state 'stateName' can be any valid absolute or relative state
* @param {Object} ui-state-params params to pass to {@link ui.router.state.$state#methods_href $state.href()}
* @param {Object} ui-state-opts options to pass to {@link ui.router.state.$state#methods_go $state.go()}
*/
$StateRefDynamicDirective.$inject = ['$state', '$timeout'];
function $StateRefDynamicDirective($state, $timeout) {
return {
restrict: 'A',
require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
link: function(scope, element, attrs, uiSrefActive) {
var type = getTypeInfo(element);
var active = uiSrefActive[1] || uiSrefActive[0];
var group = [attrs.uiState, attrs.uiStateParams || null, attrs.uiStateOpts || null];
var watch = '[' + group.map(function(val) { return val || 'null'; }).join(', ') + ']';
var def = { state: null, params: null, options: null, href: null };
var unlinkInfoFn = null;
var hookFn;
function runStateRefLink (group) {
def.state = group[0]; def.params = group[1]; def.options = group[2];
def.href = $state.href(def.state, def.params, def.options);
if (unlinkInfoFn) unlinkInfoFn();
if (active) unlinkInfoFn = active.$$addStateInfo(def.state, def.params);
if (def.href) attrs.$set(type.attr, def.href);
}
scope.$watch(watch, runStateRefLink, true);
runStateRefLink(scope.$eval(watch));
if (!type.clickable) return;
hookFn = clickHook(element, $state, $timeout, type, function() { return def; });
element[element.on ? 'on' : 'bind']("click", hookFn);
scope.$on('$destroy', function() {
element[element.off ? 'off' : 'unbind']("click", hookFn);
});
}
};
}
/**
* @ngdoc directive
* @name ui.router.state.directive:ui-sref-active
*
* @requires ui.router.state.$state
* @requires ui.router.state.$stateParams
* @requires $interpolate
*
* @restrict A
*
* @description
* A directive working alongside ui-sref to add classes to an element when the
* related ui-sref directive's state is active, and removing them when it is inactive.
* The primary use-case is to simplify the special appearance of navigation menus
* relying on `ui-sref`, by having the "active" state's menu button appear different,
* distinguishing it from the inactive menu items.
*
* ui-sref-active can live on the same element as ui-sref or on a parent element. The first
* ui-sref-active found at the same level or above the ui-sref will be used.
*
* Will activate when the ui-sref's target state or any child state is active. If you
* need to activate only when the ui-sref target state is active and *not* any of
* it's children, then you will use
* {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq}
*
* @example
* Given the following template:
* <pre>
* <ul>
* <li ui-sref-active="active" class="item">
* <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
* </li>
* </ul>
* </pre>
*
*
* When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins",
* the resulting HTML will appear as (note the 'active' class):
* <pre>
* <ul>
* <li ui-sref-active="active" class="item active">
* <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
* </li>
* </ul>
* </pre>
*
* The class name is interpolated **once** during the directives link time (any further changes to the
* interpolated value are ignored).
*
* Multiple classes may be specified in a space-separated format:
* <pre>
* <ul>
* <li ui-sref-active='class1 class2 class3'>
* <a ui-sref="app.user">link</a>
* </li>
* </ul>
* </pre>
*
* It is also possible to pass ui-sref-active an expression that evaluates
* to an object hash, whose keys represent active class names and whose
* values represent the respective state names/globs.
* ui-sref-active will match if the current active state **includes** any of
* the specified state names/globs, even the abstract ones.
*
* @Example
* Given the following template, with "admin" being an abstract state:
* <pre>
* <div ui-sref-active="{'active': 'admin.*'}">
* <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
* </div>
* </pre>
*
* When the current state is "admin.roles" the "active" class will be applied
* to both the <div> and <a> elements. It is important to note that the state
* names/globs passed to ui-sref-active shadow the state provided by ui-sref.
*/
/**
* @ngdoc directive
* @name ui.router.state.directive:ui-sref-active-eq
*
* @requires ui.router.state.$state
* @requires ui.router.state.$stateParams
* @requires $interpolate
*
* @restrict A
*
* @description
* The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate
* when the exact target state used in the `ui-sref` is active; no child states.
*
*/
$StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate'];
function $StateRefActiveDirective($state, $stateParams, $interpolate) {
return {
restrict: "A",
controller: ['$scope', '$element', '$attrs', '$timeout', function ($scope, $element, $attrs, $timeout) {
var states = [], activeClasses = {}, activeEqClass, uiSrefActive;
// There probably isn't much point in $observing this
// uiSrefActive and uiSrefActiveEq share the same directive object with some
// slight difference in logic routing
activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope);
try {
uiSrefActive = $scope.$eval($attrs.uiSrefActive);
} catch (e) {
// Do nothing. uiSrefActive is not a valid expression.
// Fall back to using $interpolate below
}
uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);
if (isObject(uiSrefActive)) {
forEach(uiSrefActive, function(stateOrName, activeClass) {
if (isString(stateOrName)) {
var ref = parseStateRef(stateOrName, $state.current.name);
addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);
}
});
}
// Allow uiSref to communicate with uiSrefActive[Equals]
this.$$addStateInfo = function (newState, newParams) {
// we already got an explicit state provided by ui-sref-active, so we
// shadow the one that comes from ui-sref
if (isObject(uiSrefActive) && states.length > 0) {
return;
}
var deregister = addState(newState, newParams, uiSrefActive);
update();
return deregister;
};
$scope.$on('$stateChangeSuccess', update);
function addState(stateName, stateParams, activeClass) {
var state = $state.get(stateName, stateContext($element));
var stateHash = createStateHash(stateName, stateParams);
var stateInfo = {
state: state || { name: stateName },
params: stateParams,
hash: stateHash
};
states.push(stateInfo);
activeClasses[stateHash] = activeClass;
return function removeState() {
var idx = states.indexOf(stateInfo);
if (idx !== -1) states.splice(idx, 1);
};
}
/**
* @param {string} state
* @param {Object|string} [params]
* @return {string}
*/
function createStateHash(state, params) {
if (!isString(state)) {
throw new Error('state should be a string');
}
if (isObject(params)) {
return state + toJson(params);
}
params = $scope.$eval(params);
if (isObject(params)) {
return state + toJson(params);
}
return state;
}
// Update route state
function update() {
for (var i = 0; i < states.length; i++) {
if (anyMatch(states[i].state, states[i].params)) {
addClass($element, activeClasses[states[i].hash]);
} else {
removeClass($element, activeClasses[states[i].hash]);
}
if (exactMatch(states[i].state, states[i].params)) {
addClass($element, activeEqClass);
} else {
removeClass($element, activeEqClass);
}
}
}
function addClass(el, className) { $timeout(function () { el.addClass(className); }); }
function removeClass(el, className) { el.removeClass(className); }
function anyMatch(state, params) { return $state.includes(state.name, params); }
function exactMatch(state, params) { return $state.is(state.name, params); }
update();
}]
};
}
angular.module('ui.router.state')
.directive('uiSref', $StateRefDirective)
.directive('uiSrefActive', $StateRefActiveDirective)
.directive('uiSrefActiveEq', $StateRefActiveDirective)
.directive('uiState', $StateRefDynamicDirective);
/**
* @ngdoc filter
* @name ui.router.state.filter:isState
*
* @requires ui.router.state.$state
*
* @description
* Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}.
*/
$IsStateFilter.$inject = ['$state'];
function $IsStateFilter($state) {
var isFilter = function (state, params) {
return $state.is(state, params);
};
isFilter.$stateful = true;
return isFilter;
}
/**
* @ngdoc filter
* @name ui.router.state.filter:includedByState
*
* @requires ui.router.state.$state
*
* @description
* Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}.
*/
$IncludedByStateFilter.$inject = ['$state'];
function $IncludedByStateFilter($state) {
var includesFilter = function (state, params, options) {
return $state.includes(state, params, options);
};
includesFilter.$stateful = true;
return includesFilter;
}
angular.module('ui.router.state')
.filter('isState', $IsStateFilter)
.filter('includedByState', $IncludedByStateFilter);
/**
* @ngdoc object
* @name ui.router.util.$templateFactoryProvider
*
* @description
* Provider for $templateFactory. Manages which template-loading mechanism to
* use, and will default to the most recent one ($templateRequest on Angular
* versions starting from 1.3, $http otherwise).
*/
function TemplateFactoryProvider() {
var shouldUnsafelyUseHttp = angular.version.minor < 3;
/**
* @ngdoc function
* @name ui.router.util.$templateFactoryProvider#shouldUnsafelyUseHttp
* @methodOf ui.router.util.$templateFactoryProvider
*
* @description
* Forces $templateFactory to use $http instead of $templateRequest. This
* might cause XSS, as $http doesn't enforce the regular security checks for
* templates that have been introduced in Angular 1.3. Note that setting this
* to false on Angular older than 1.3.x will crash, as the $templateRequest
* service (and the security checks) are not implemented on these versions.
*
* See the $sce documentation, section
* <a href="https://docs.angularjs.org/api/ng/service/$sce#impact-on-loading-templates">
* Impact on loading templates</a> for more details about this mechanism.
*
* @param {boolean} value
*/
this.shouldUnsafelyUseHttp = function(value) {
shouldUnsafelyUseHttp = !!value;
};
/**
* @ngdoc object
* @name ui.router.util.$templateFactory
*
* @requires $http
* @requires $templateCache
* @requires $injector
*
* @description
* Service. Manages loading of templates.
*/
this.$get = ['$http', '$templateCache', '$injector', function($http, $templateCache, $injector){
return new TemplateFactory($http, $templateCache, $injector, shouldUnsafelyUseHttp);}];
}
/**
* @ngdoc object
* @name ui.router.util.$templateFactory
*
* @requires $http
* @requires $templateCache
* @requires $injector
*
* @description
* Service. Manages loading of templates.
*/
function TemplateFactory($http, $templateCache, $injector, shouldUnsafelyUseHttp) {
/**
* @ngdoc function
* @name ui.router.util.$templateFactory#fromConfig
* @methodOf ui.router.util.$templateFactory
*
* @description
* Creates a template from a configuration object.
*
* @param {object} config Configuration object for which to load a template.
* The following properties are search in the specified order, and the first one
* that is defined is used to create the template:
*
* @param {string|object} config.template html string template or function to
* load via {@link ui.router.util.$templateFactory#fromString fromString}.
* @param {string|object} config.templateUrl url to load or a function returning
* the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}.
* @param {Function} config.templateProvider function to invoke via
* {@link ui.router.util.$templateFactory#fromProvider fromProvider}.
* @param {object} params Parameters to pass to the template function.
* @param {object} locals Locals to pass to `invoke` if the template is loaded
* via a `templateProvider`. Defaults to `{ params: params }`.
*
* @return {string|object} The template html as a string, or a promise for
* that string,or `null` if no template is configured.
*/
this.fromConfig = function (config, params, locals) {
return (
isDefined(config.template) ? this.fromString(config.template, params) :
isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) :
isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) :
null
);
};
/**
* @ngdoc function
* @name ui.router.util.$templateFactory#fromString
* @methodOf ui.router.util.$templateFactory
*
* @description
* Creates a template from a string or a function returning a string.
*
* @param {string|object} template html template as a string or function that
* returns an html template as a string.
* @param {object} params Parameters to pass to the template function.
*
* @return {string|object} The template html as a string, or a promise for that
* string.
*/
this.fromString = function (template, params) {
return isFunction(template) ? template(params) : template;
};
/**
* @ngdoc function
* @name ui.router.util.$templateFactory#fromUrl
* @methodOf ui.router.util.$templateFactory
*
* @description
* Loads a template from the a URL via `$http` and `$templateCache`.
*
* @param {string|Function} url url of the template to load, or a function
* that returns a url.
* @param {Object} params Parameters to pass to the url function.
* @return {string|Promise.<string>} The template html as a string, or a promise
* for that string.
*/
this.fromUrl = function (url, params) {
if (isFunction(url)) url = url(params);
if (url == null) return null;
else {
if(!shouldUnsafelyUseHttp) {
return $injector.get('$templateRequest')(url);
} else {
return $http
.get(url, { cache: $templateCache, headers: { Accept: 'text/html' }})
.then(function(response) { return response.data; });
}
}
};
/**
* @ngdoc function
* @name ui.router.util.$templateFactory#fromProvider
* @methodOf ui.router.util.$templateFactory
*
* @description
* Creates a template by invoking an injectable provider function.
*
* @param {Function} provider Function to invoke via `$injector.invoke`
* @param {Object} params Parameters for the template.
* @param {Object} locals Locals to pass to `invoke`. Defaults to
* `{ params: params }`.
* @return {string|Promise.<string>} The template html as a string, or a promise
* for that string.
*/
this.fromProvider = function (provider, params, locals) {
return $injector.invoke(provider, null, locals || { params: params });
};
}
angular.module('ui.router.util').provider('$templateFactory', TemplateFactoryProvider);
/**
* @ngdoc object
* @name ui.router.router.$urlRouterProvider
*
* @requires ui.router.util.$urlMatcherFactoryProvider
* @requires $locationProvider
*
* @description
* `$urlRouterProvider` has the responsibility of watching `$location`.
* When `$location` changes it runs through a list of rules one by one until a
* match is found. `$urlRouterProvider` is used behind the scenes anytime you specify
* a url in a state configuration. All urls are compiled into a UrlMatcher object.
*
* There are several methods on `$urlRouterProvider` that make it useful to use directly
* in your module config.
*/
$UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider'];
function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) {
var rules = [], otherwise = null, interceptDeferred = false, listener;
// Returns a string that is a prefix of all strings matching the RegExp
function regExpPrefix(re) {
var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source);
return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : '';
}
// Interpolates matched values into a String.replace()-style pattern
function interpolate(pattern, match) {
return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) {
return match[what === '$' ? 0 : Number(what)];
});
}
/**
* @ngdoc function
* @name ui.router.router.$urlRouterProvider#rule
* @methodOf ui.router.router.$urlRouterProvider
*
* @description
* Defines rules that are used by `$urlRouterProvider` to find matches for
* specific URLs.
*
* @example
* <pre>
* var app = angular.module('app', ['ui.router.router']);
*
* app.config(function ($urlRouterProvider) {
* // Here's an example of how you might allow case insensitive urls
* $urlRouterProvider.rule(function ($injector, $location) {
* var path = $location.path(),
* normalized = path.toLowerCase();
*
* if (path !== normalized) {
* return normalized;
* }
* });
* });
* </pre>
*
* @param {function} rule Handler function that takes `$injector` and `$location`
* services as arguments. You can use them to return a valid path as a string.
*
* @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
*/
this.rule = function (rule) {
if (!isFunction(rule)) throw new Error("'rule' must be a function");
rules.push(rule);
return this;
};
/**
* @ngdoc object
* @name ui.router.router.$urlRouterProvider#otherwise
* @methodOf ui.router.router.$urlRouterProvider
*
* @description
* Defines a path that is used when an invalid route is requested.
*
* @example
* <pre>
* var app = angular.module('app', ['ui.router.router']);
*
* app.config(function ($urlRouterProvider) {
* // if the path doesn't match any of the urls you configured
* // otherwise will take care of routing the user to the
* // specified url
* $urlRouterProvider.otherwise('/index');
*
* // Example of using function rule as param
* $urlRouterProvider.otherwise(function ($injector, $location) {
* return '/a/valid/url';
* });
* });
* </pre>
*
* @param {string|function} rule The url path you want to redirect to or a function
* rule that returns the url path. The function version is passed two params:
* `$injector` and `$location` services, and must return a url string.
*
* @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance
*/
this.otherwise = function (rule) {
if (isString(rule)) {
var redirect = rule;
rule = function () { return redirect; };
}
else if (!isFunction(rule)) throw new Error("'rule' must be a function");
otherwise = rule;
return this;
};
function handleIfMatch($injector, handler, match) {
if (!match) return false;
var result = $injector.invoke(handler, handler, { $match: match });
return isDefined(result) ? result : true;
}
/**
* @ngdoc function
* @name ui.router.router.$urlRouterProvider#when
* @methodOf ui.router.router.$urlRouterProvider
*
* @description
* Registers a handler for a given url matching.
*
* If the handler is a string, it is
* treated as a redirect, and is interpolated according to the syntax of match
* (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise).
*
* If the handler is a function, it is injectable. It gets invoked if `$location`
* matches. You have the option of inject the match object as `$match`.
*
* The handler can return
*
* - **falsy** to indicate that the rule didn't match after all, then `$urlRouter`
* will continue trying to find another one that matches.
* - **string** which is treated as a redirect and passed to `$location.url()`
* - **void** or any **truthy** value tells `$urlRouter` that the url was handled.
*
* @example
* <pre>
* var app = angular.module('app', ['ui.router.router']);
*
* app.config(function ($urlRouterProvider) {
* $urlRouterProvider.when($state.url, function ($match, $stateParams) {
* if ($state.$current.navigable !== state ||
* !equalForKeys($match, $stateParams) {
* $state.transitionTo(state, $match, false);
* }
* });
* });
* </pre>
*
* @param {string|object} what The incoming path that you want to redirect.
* @param {string|function} handler The path you want to redirect your user to.
*/
this.when = function (what, handler) {
var redirect, handlerIsString = isString(handler);
if (isString(what)) what = $urlMatcherFactory.compile(what);
if (!handlerIsString && !isFunction(handler) && !isArray(handler))
throw new Error("invalid 'handler' in when()");
var strategies = {
matcher: function (what, handler) {
if (handlerIsString) {
redirect = $urlMatcherFactory.compile(handler);
handler = ['$match', function ($match) { return redirect.format($match); }];
}
return extend(function ($injector, $location) {
return handleIfMatch($injector, handler, what.exec($location.path(), $location.search()));
}, {
prefix: isString(what.prefix) ? what.prefix : ''
});
},
regex: function (what, handler) {
if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky");
if (handlerIsString) {
redirect = handler;
handler = ['$match', function ($match) { return interpolate(redirect, $match); }];
}
return extend(function ($injector, $location) {
return handleIfMatch($injector, handler, what.exec($location.path()));
}, {
prefix: regExpPrefix(what)
});
}
};
var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp };
for (var n in check) {
if (check[n]) return this.rule(strategies[n](what, handler));
}
throw new Error("invalid 'what' in when()");
};
/**
* @ngdoc function
* @name ui.router.router.$urlRouterProvider#deferIntercept
* @methodOf ui.router.router.$urlRouterProvider
*
* @description
* Disables (or enables) deferring location change interception.
*
* If you wish to customize the behavior of syncing the URL (for example, if you wish to
* defer a transition but maintain the current URL), call this method at configuration time.
* Then, at run time, call `$urlRouter.listen()` after you have configured your own
* `$locationChangeSuccess` event handler.
*
* @example
* <pre>
* var app = angular.module('app', ['ui.router.router']);
*
* app.config(function ($urlRouterProvider) {
*
* // Prevent $urlRouter from automatically intercepting URL changes;
* // this allows you to configure custom behavior in between
* // location changes and route synchronization:
* $urlRouterProvider.deferIntercept();
*
* }).run(function ($rootScope, $urlRouter, UserService) {
*
* $rootScope.$on('$locationChangeSuccess', function(e) {
* // UserService is an example service for managing user state
* if (UserService.isLoggedIn()) return;
*
* // Prevent $urlRouter's default handler from firing
* e.preventDefault();
*
* UserService.handleLogin().then(function() {
* // Once the user has logged in, sync the current URL
* // to the router:
* $urlRouter.sync();
* });
* });
*
* // Configures $urlRouter's listener *after* your custom listener
* $urlRouter.listen();
* });
* </pre>
*
* @param {boolean} defer Indicates whether to defer location change interception. Passing
no parameter is equivalent to `true`.
*/
this.deferIntercept = function (defer) {
if (defer === undefined) defer = true;
interceptDeferred = defer;
};
/**
* @ngdoc object
* @name ui.router.router.$urlRouter
*
* @requires $location
* @requires $rootScope
* @requires $injector
* @requires $browser
*
* @description
*
*/
this.$get = $get;
$get.$inject = ['$location', '$rootScope', '$injector', '$browser', '$sniffer'];
function $get( $location, $rootScope, $injector, $browser, $sniffer) {
var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl;
function appendBasePath(url, isHtml5, absolute) {
if (baseHref === '/') return url;
if (isHtml5) return baseHref.slice(0, -1) + url;
if (absolute) return baseHref.slice(1) + url;
return url;
}
// TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree
function update(evt) {
if (evt && evt.defaultPrevented) return;
var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl;
lastPushedUrl = undefined;
// TODO: Re-implement this in 1.0 for https://github.com/angular-ui/ui-router/issues/1573
//if (ignoreUpdate) return true;
function check(rule) {
var handled = rule($injector, $location);
if (!handled) return false;
if (isString(handled)) $location.replace().url(handled);
return true;
}
var n = rules.length, i;
for (i = 0; i < n; i++) {
if (check(rules[i])) return;
}
// always check otherwise last to allow dynamic updates to the set of rules
if (otherwise) check(otherwise);
}
function listen() {
listener = listener || $rootScope.$on('$locationChangeSuccess', update);
return listener;
}
if (!interceptDeferred) listen();
return {
/**
* @ngdoc function
* @name ui.router.router.$urlRouter#sync
* @methodOf ui.router.router.$urlRouter
*
* @description
* Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`.
* This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event,
* perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed
* with the transition by calling `$urlRouter.sync()`.
*
* @example
* <pre>
* angular.module('app', ['ui.router'])
* .run(function($rootScope, $urlRouter) {
* $rootScope.$on('$locationChangeSuccess', function(evt) {
* // Halt state change from even starting
* evt.preventDefault();
* // Perform custom logic
* var meetsRequirement = ...
* // Continue with the update and state transition if logic allows
* if (meetsRequirement) $urlRouter.sync();
* });
* });
* </pre>
*/
sync: function() {
update();
},
listen: function() {
return listen();
},
update: function(read) {
if (read) {
location = $location.url();
return;
}
if ($location.url() === location) return;
$location.url(location);
$location.replace();
},
push: function(urlMatcher, params, options) {
var url = urlMatcher.format(params || {});
// Handle the special hash param, if needed
if (url !== null && params && params['#']) {
url += '#' + params['#'];
}
$location.url(url);
lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined;
if (options && options.replace) $location.replace();
},
/**
* @ngdoc function
* @name ui.router.router.$urlRouter#href
* @methodOf ui.router.router.$urlRouter
*
* @description
* A URL generation method that returns the compiled URL for a given
* {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters.
*
* @example
* <pre>
* $bob = $urlRouter.href(new UrlMatcher("/about/:person"), {
* person: "bob"
* });
* // $bob == "/about/bob";
* </pre>
*
* @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate.
* @param {object=} params An object of parameter values to fill the matcher's required parameters.
* @param {object=} options Options object. The options are:
*
* - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl".
*
* @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher`
*/
href: function(urlMatcher, params, options) {
if (!urlMatcher.validates(params)) return null;
var isHtml5 = $locationProvider.html5Mode();
if (angular.isObject(isHtml5)) {
isHtml5 = isHtml5.enabled;
}
isHtml5 = isHtml5 && $sniffer.history;
var url = urlMatcher.format(params);
options = options || {};
if (!isHtml5 && url !== null) {
url = "#" + $locationProvider.hashPrefix() + url;
}
// Handle special hash param, if needed
if (url !== null && params && params['#']) {
url += '#' + params['#'];
}
url = appendBasePath(url, isHtml5, options.absolute);
if (!options.absolute || !url) {
return url;
}
var slash = (!isHtml5 && url ? '/' : ''), port = $location.port();
port = (port === 80 || port === 443 ? '' : ':' + port);
return [$location.protocol(), '://', $location.host(), port, slash, url].join('');
}
};
}
}
angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider);
$ViewProvider.$inject = [];
function $ViewProvider() {
this.$get = $get;
/**
* @ngdoc object
* @name ui.router.state.$view
*
* @requires ui.router.util.$templateFactory
* @requires $rootScope
*
* @description
*
*/
$get.$inject = ['$rootScope', '$templateFactory'];
function $get( $rootScope, $templateFactory) {
return {
// $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... })
/**
* @ngdoc function
* @name ui.router.state.$view#load
* @methodOf ui.router.state.$view
*
* @description
*
* @param {string} name name
* @param {object} options option object.
*/
load: function load(name, options) {
var result, defaults = {
template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {}
};
options = extend(defaults, options);
if (options.view) {
result = $templateFactory.fromConfig(options.view, options.params, options.locals);
}
return result;
}
};
}
}
angular.module('ui.router.state').provider('$view', $ViewProvider);
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
{
"name": "angular",
"version": "1.6.4",
"license": "MIT",
"main": "./angular.js",
"ignore": [],
"dependencies": {
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册