├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── debug.log ├── manifest.json ├── npm-scripts ├── before-build-dll.script.js └── before-build.script.js ├── package-lock.json ├── package.json ├── src ├── dll │ ├── dll.css │ └── dll.js ├── index.html ├── pages │ ├── alert │ │ └── index │ │ │ ├── content.ejs │ │ │ ├── html.js │ │ │ └── page.js │ ├── index │ │ ├── index │ │ │ ├── content.ejs │ │ │ ├── html.js │ │ │ └── page.js │ │ └── login │ │ │ ├── html.js │ │ │ ├── page.js │ │ │ ├── page.less │ │ │ └── templates │ │ │ ├── forget-password-box.html │ │ │ ├── login-box.ejs │ │ │ └── main.ejs │ └── user │ │ ├── edit-password │ │ ├── content.ejs │ │ ├── html.js │ │ └── page.js │ │ └── modify-info │ │ ├── content.ejs │ │ ├── html.js │ │ └── page.js └── public-resource │ ├── components │ ├── footer │ │ └── html.ejs │ ├── header │ │ └── html.ejs │ ├── side-menu │ │ └── html.ejs │ └── top-nav │ │ └── html.ejs │ ├── config │ ├── build-file.config.js │ └── common.config.js │ ├── iconfont │ ├── demo.css │ ├── demo.html │ ├── iconfont.css │ ├── iconfont.eot │ ├── iconfont.svg │ ├── iconfont.ttf │ └── iconfont.woff │ ├── imgs │ └── login-bg.jpg │ ├── layout │ ├── layout-without-nav │ │ ├── html.ejs │ │ └── html.js │ └── layout │ │ ├── html.ejs │ │ └── html.js │ ├── less │ ├── base-dir │ │ ├── _badge.less │ │ ├── _button.less │ │ ├── _form.less │ │ ├── _global.less │ │ ├── _iconfont.less │ │ ├── _mixins.less │ │ ├── _panel.less │ │ ├── _table.less │ │ └── _variables.less │ ├── base.less │ ├── components-dir │ │ ├── _modal.less │ │ ├── _side-nav.less │ │ ├── _tab.less │ │ └── _top-menu.less │ └── vendor-dir │ │ └── bootstrap │ │ ├── css │ │ └── bootstrap.min.css │ │ └── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── libs │ ├── libs.module.js │ └── without-jquery.module.js │ └── logic │ └── common.page.js ├── stats.json ├── vendor ├── ie-fix │ ├── html5shiv.min.js │ ├── jquery.xdomainrequest.min.js │ ├── respond-proxy.html │ ├── respond.min.js │ ├── respond.proxy.gif │ ├── respond.proxy.js │ └── xdomain.all.js ├── metisMenu │ ├── metisMenu.min.css │ └── metisMenu.min.js └── promise.min.js ├── webpack-config ├── base │ ├── dir-vars.config.js │ └── page-entries.config.js ├── devServer.config.js ├── entry.config.js ├── externals.config.js ├── inherit │ ├── module.config.js │ └── plugins.config.js ├── module.dev.config.js ├── module.product.config.js ├── output.config.js ├── plugins.dev.config.js ├── plugins.product.config.js ├── resolve.config.js └── vendor │ ├── eslint.config.js │ └── postcss.config.js ├── webpack-dll.config.js ├── webpack.config.js └── webpack.dev.config.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | extends: 'standard', 6 | parser: 'babel-eslint', 7 | parserOptions: { 8 | sourceType: 'module' 9 | }, 10 | globals: { 11 | // Put things like jQuery, etc 12 | jQuery: true, 13 | $: true, 14 | }, 15 | env: { 16 | browser: true, 17 | jquery: true, 18 | }, 19 | // required to lint *.vue files 20 | plugins: [ 21 | 'html' 22 | ], 23 | // add your custom rules here 24 | rules: { 25 | // allow debugger during development 26 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, 27 | "camelcase": 0, 28 | "no-extra-boolean-cast": 0, 29 | "space-before-function-paren": ["error", "never"], 30 | "semi": ["error", "always"], 31 | "comma-dangle": [2, "always-multiline"], 32 | "no-console": 0, //console 未删除 33 | "no-var": 0, 34 | "no-new": 0, 35 | "import/no-unresolved": 0, 36 | "no-underscore-dangle": [0], 37 | "prefer-template": 0, 38 | "object-shorthand": [0], 39 | "prefer-arrow-callback": 0, 40 | "prefer-rest-params": 0, 41 | "no-param-reassign": 0, 42 | "max-len": ["error", { 43 | "code": 200, 44 | "tabWidth": 2, 45 | "comments": 200, 46 | "ignoreComments": false, 47 | "ignoreTrailingComments": false, 48 | "ignoreUrls": true 49 | }], 50 | "global-require": 0, 51 | 'no-restricted-syntax': [ 52 | 2, 53 | 'LabeledStatement', 54 | 'WithStatement', 55 | ] 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | node_modules 11 | build 12 | 13 | # Windows Installer files 14 | *.cab 15 | *.msi 16 | *.msm 17 | *.msp 18 | 19 | # Windows shortcuts 20 | *.lnk 21 | 22 | *.sublime-project 23 | *.sublime-workspace 24 | npm-debug.log -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Array Huang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack-seed 2 | 3 | ## 注意 4 | 本项目master分支已升级到`webpack2`版本,如需查看`webpack1`版本,请查看[webpack1_version](https://github.com/Array-Huang/webpack-seed/tree/webpack1_version)分支。 5 | 6 | ## 项目介绍 7 | 本项目是一个基于webpack架构的**web app**脚手架,其特点如下: 8 | - 更适合多页应用。 9 | - 既可实现全后端分离,也可以生成后端渲染所需要的模板。 10 | - 引入layout和component的概念,方便多页面间对布局、组件的重用,妈妈再也不用担心我是选SPA呢还是Iframe了,咱们都!不!需!要! 11 | - 编译后的程序不依赖于外部的资源(包括css、font、图片等资源都做了迁移),可以整体放到CDN上。 12 | - 整合Bootstrap3及主题SB-Admin,但其实换掉也很简单,或者干脆不用CSS框架也行。 13 | - 不含Js框架(jQuery不算框架,谢谢)。 14 | - 本项目基于 ***webpack v2*** 和 ***webpack-dev-server v2***,全局和项目局部依赖都一样。 15 | 16 | ## 使用说明 17 | - 本项目使用包管理工具NPM,因此需要先把本项目所依赖的包下载下来: 18 | ``` 19 | $ npm install 20 | ``` 21 | 22 | - 启动服务器,推荐直接使用webpack-dev-server 23 | ``` 24 | $ npm run start 25 | ``` 26 | 27 | - 理论上来说,webpack-dev-server会自动帮你打开浏览器并展示示例页面;如果没有的话,请手动打开浏览器,在地址栏里输入`http://localhost:8080`,Duang!页面就出来了! 28 | 29 | ## CLI命令(npm scripts) 30 | | 命令 | 作用&效果 | 31 | | --------------- | ------------- | 32 | | npm run build | 根据`webpack.config.js`,build出一份生产环境的代码 | 33 | | npm run dev | 根据`webpack.dev.config.js`,build出一份开发环境的代码 | 34 | | npm run start | 开启webpack-dev-server并自动打开浏览器,自动监测源码变动并实现LiveReload,**推荐实际开发时使用此项** | 35 | | npm run profile | 显示编译过程中每一项资源的耗时,用来调优的 | 36 | | npm run dll | 生成Dll文件,每次升级第三方库时都需要重新执行一遍 | 37 | | npm run analyse | 生成打包文件结构的可视化分析报告;注意请在`npm run build`或`npm run dev`后再执行 | 38 | | npm run analyze | 作用同上 | 39 | 40 | ## 目录结构说明 41 | ``` 42 | ├─build # 编译后生成的所有代码、资源(图片、字体等,虽然只是简单的从源目录迁移过来) 43 | ├─node_modules # 利用npm管理的所有包及其依赖 44 | ├─vendor # 所有不能用npm管理的第三方库 45 | ├─.babelrc # babel的配置文件 46 | ├─.eslintrc # ESLint的配置文件 47 | ├─index.html # 仅作为重定向使用 48 | ├─package.json # npm的配置文件 49 | ├─webpack-config # 存放分拆后的webpack配置文件 50 | │ ├─base # 主要是存放一些变量 51 | │ ├─inherit # 存放生产环境和开发环境相同的部分,以供继承 52 | │ └─vendor # 存放webpack兼容第三方库所需的配置文件 53 | ├─webpack.config.js # 生产环境的webpack配置文件(无实质内容,仅为组织整理) 54 | ├─webpack.dev.config.js # 开发环境的webpack配置文件(无实质内容,仅为组织整理) 55 | ├─src # 当前项目的源码 56 | ├─pages # 各个页面独有的部分,如入口文件、只有该页面使用到的css、模板文件等 57 | │ ├─alert # 业务模块 58 | │ │ └─index # 具体页面 59 | │ ├─index # 业务模块 60 | │ │ ├─index # 具体页面 61 | │ │ └─login # 具体页面 62 | │ │ └─templates # 如果一个页面的HTML比较复杂,可以分成多块再拼在一起 63 | │ └─user # 业务模块 64 | │ ├─edit-password # 具体页面 65 | │ └─modify-info # 具体页面 66 | └─public-resource # 各个页面使用到的公共资源 67 | ├─components # 组件,可以是纯HTML,也可以包含js/css/image等,看自己需要 68 | │ ├─footer # 页尾 69 | │ ├─header # 页头 70 | │ ├─side-menu # 侧边栏 71 | │ └─top-nav # 顶部菜单 72 | ├─config # 各种配置文件 73 | ├─iconfont # iconfont的字体文件 74 | ├─imgs # 公用的图片资源 75 | ├─layout # UI布局,组织各个组件拼起来,因应需要可以有不同的布局套路 76 | │ ├─layout # 具体的布局套路 77 | │ └─layout-without-nav # 具体的布局套路 78 | ├─less # less文件,用sass的也可以,又或者是纯css 79 | │ ├─base-dir 80 | │ ├─components-dir # 如果组件本身不需要js的,那么要加载组件的css比较困难,我建议可以直接用less来加载 81 | │ └─base.less # 组织所有的less文件 82 | ├─libs # 与业务逻辑无关的库都可以放到这里 83 | └─logic # 业务逻辑 84 | ``` 85 | 86 | ## 更新日志 87 | ### 2.1.0 (2017-07-26) 88 | 更新了一批浏览器缓存相关配置,详情请看[webpack多页应用架构系列(十六):善用浏览器缓存,该去则去,该留则留](https://segmentfault.com/a/1190000010317802) 89 | 90 | ### 2.0.0 (2017-03-05) 91 | webpack及webpack-dev-server升级到v2版本,并相应修改webpack配置文件。 92 | 93 | ### 1.4.1 (2017-01-24) 94 | 支持js/css/less文件的热更新,但暂未支持模板文件。 95 | 96 | ### 1.3.1 (2016-12-01) 97 | 改为利用`webpack --json`来生成**webpack-bundle-analyzer**生成包文件结构的可视化分析报告所需的json文件。 98 | 99 | ### 1.3.0 (2016-11-22) 100 | 引入**webpack-bundle-analyzer**,用以生成打包文件结构的可视化分析报告。 101 | 102 | ### 2.0.0 (2016-10-21) 103 | 把基础设施从项目里抽离出来,实现多项目共用同一套架构/基础设施。由于本项目肩负有教程示例的责任,且2.x版本变化极大,因此另辟一个新repo([Array-Huang/webpack-seed-v2](https://github.com/Array-Huang/webpack-seed-v2))来放置。 104 | 105 | ### 1.2.2 (2016-10-16) 106 | 考虑到多个页面可能会共用html/js/css(例如**添加页面**和**修改页面**),在自动查找页面入口时,忽略以`_`开头的目录,因此,可以使用以`_`开头的目录来放置页面复用的资源。 107 | 108 | ### 1.2.0 (2016-10-14) 109 | 利用[`isaacs/node-glob`](https://github.com/isaacs/node-glob)根据约定好的文件目录结构自动查找页面入口,取代过去手动指定的做法(但如果在调试过程中希望只编译某些页面,仍然可以通过手动指定来实现)。 110 | 111 | ### 1.1.0 112 | 引入Dll的概念,将第三方库进行预打包,那么在打包我们的业务代码的时候,就不需要重复打包这些第三方库了。这尤其能提现在bootstrap上,可以省一大半的时间。 113 | - 如果修改了Dll所包含的第三方库,比如说升级之类的,请使用`npm run dll`重新打包Dll文件。注意:系统会在打包Dll前先清空Dll目录。 114 | - 如果重新打包了Dll,那么也请重新打包你的业务代码,使用`npm run build`或`npm run dev`。 115 | 116 | ### 1.0.2 117 | - 编译文件前先清空build目录。 118 | - 分拆webpack配置文件,避免配置文件日益臃肿。 119 | - 分开生产环境和开发环境的webpack配置文件。其中,`npm run build`会调用生产环境的webpack配置文件(webpack.config.js),而`npm run dev`和`npm run watch`会调用开发环境的配置文件。 120 | 121 | ### 1.0.0 122 | 由于此脚手架已具备投入生产环境的能力,故直接定义版本号为1.0.0 -------------------------------------------------------------------------------- /debug.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Array-Huang/webpack-seed/511480ba0ffd9c4153c1a2e5e7b79550aac6d2e2/debug.log -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dll", 3 | "content": { 4 | "./node_modules/jquery/dist/jquery.js": { 5 | "id": 0, 6 | "meta": {} 7 | }, 8 | "./node_modules/bootstrap/dist/js/bootstrap.min.js": { 9 | "id": 1, 10 | "meta": {} 11 | }, 12 | "./vendor/metisMenu/metisMenu.min.css": { 13 | "id": 2, 14 | "meta": {} 15 | }, 16 | "./node_modules/bootstrap/dist/css/bootstrap.min.css": { 17 | "id": 3, 18 | "meta": {} 19 | }, 20 | "./vendor/metisMenu/metisMenu.min.js": { 21 | "id": 4, 22 | "meta": {} 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /npm-scripts/before-build-dll.script.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var rimraf = require('rimraf'); 3 | var dirVars = require('../webpack-config/base/dir-vars.config.js'); 4 | rimraf(dirVars.dllDir, fs, function cb() { 5 | console.log('dll目录已清空'); 6 | }); 7 | -------------------------------------------------------------------------------- /npm-scripts/before-build.script.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var rimraf = require('rimraf'); 3 | var dirVars = require('../webpack-config/base/dir-vars.config.js'); 4 | rimraf(dirVars.buildDir, fs, function cb() { 5 | console.log('build目录已清空'); 6 | }); 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-seed", 3 | "version": "2.0.0", 4 | "description": "This is a seed for web application built by webpack", 5 | "scripts": { 6 | "build": "./node_modules/.bin/webpack --progress --colors --bail", 7 | "dev": "./node_modules/.bin/webpack --progress --colors --config ./webpack.dev.config.js", 8 | "start": "./node_modules/.bin/webpack-dev-server --config ./webpack.dev.config.js --open --hot", 9 | "profile": "./node_modules/.bin/webpack --colors --profile --display-modules --config ./webpack.dev.config.js", 10 | "dll": "./node_modules/.bin/webpack --progress --colors --config ./webpack-dll.config.js", 11 | "analyse": "webpack --json > ./build/stats.json && webpack-bundle-analyzer --port 8989 ./build/stats.json", 12 | "analyze": "npm run analyse" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git@github.com:Array-Huang/webpack-seed.git" 17 | }, 18 | "author": "Array Huang", 19 | "license": "MIT", 20 | "devDependencies": { 21 | "autoprefixer": "^6.4.0", 22 | "babel-core": "^6.25.0", 23 | "babel-eslint": "^7.2.3", 24 | "babel-loader": "^6.2.4", 25 | "babel-plugin-transform-runtime": "^6.15.0", 26 | "babel-preset-es2015": "^6.24.1", 27 | "babel-runtime": "^6.11.6", 28 | "css-loader": "^0.26.0", 29 | "ejs-loader": "^0.3.0", 30 | "eslint": "^3.19.0", 31 | "eslint-config-standard": "^7.1.0", 32 | "eslint-friendly-formatter": "^2.0.7", 33 | "eslint-loader": "^1.9.0", 34 | "eslint-plugin-html": "^2.0.3", 35 | "eslint-plugin-promise": "^3.5.0", 36 | "eslint-plugin-standard": "^2.3.1", 37 | "exports-loader": "^0.6.3", 38 | "expose-loader": "^0.7.1", 39 | "extract-text-webpack-plugin": "^2.1.2", 40 | "file-loader": "^0.10.0", 41 | "glob": "^7.1.2", 42 | "html-loader": "^0.4.3", 43 | "html-webpack-plugin": "^2.29.0", 44 | "less": "^2.7.1", 45 | "less-loader": "^2.2.3", 46 | "null-loader": "^0.1.1", 47 | "postcss-loader": "^1.2.2", 48 | "precss": "^1.4.0", 49 | "rimraf": "^2.5.4", 50 | "style-loader": "^0.13.1", 51 | "url-loader": "^0.5.9", 52 | "webpack": "^2.7.0", 53 | "webpack-bundle-analyzer": "^2.8.3", 54 | "webpack-dev-server": "^2.5.1", 55 | "webpack-plugin-hash-output": "^1.3.0" 56 | }, 57 | "dependencies": { 58 | "bootstrap": "^3.3.7", 59 | "jquery": "^1.12.4" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/pages/alert/index/content.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 |
6 |
7 |
8 |
9 | 消息通知筛选条件 10 |
11 | 12 |
13 |
14 |
15 | 16 | 21 |
22 | 23 |
24 |
25 | 26 |
27 |
28 |
29 | 30 | 31 |
32 |
33 |
34 |
35 | 消息通知列表 36 |
37 |
38 |
39 | 40 | 41 | 42 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 54 | 55 | 56 | 57 | 58 | 61 | 62 | 63 | 64 | 65 |
43 | 44 | 通知时间内容
52 | 53 | 2016-08-01 08:53抱歉,您未通过平台审核!原因:2333
59 | 60 | 2016-08-01 08:52系统已赠送了抵用券到您的账户,请在指定规则条件内使用。
66 |
67 |
68 |
    69 |
    70 |
    71 | 74 |
    75 |
    76 |
    77 |
    78 |
    -------------------------------------------------------------------------------- /src/pages/alert/index/html.js: -------------------------------------------------------------------------------- 1 | const content = require('./content.ejs'); // 调取存放本页面实际内容的模板文件 2 | const layout = require('layout'); // 调用管理后台内部所使用的布局方案,我在webpack配置里定义其别名为'layout' 3 | const pageTitle = '消息通知'; // 页面名称 4 | 5 | // 给layout传入“页面名称”这一参数(当然有需要的话也可以传入其它参数),同时也传入页面实际内容的HTML字符串。content({ pageTitle })的意思就是把pageTitle作为模板变量传给ejs模板引擎并返回最终生成的HTML字符串。 6 | module.exports = layout.init({ pageTitle }).run(content({ pageTitle })); 7 | -------------------------------------------------------------------------------- /src/pages/alert/index/page.js: -------------------------------------------------------------------------------- 1 | require('cp'); 2 | $(() => { 3 | 4 | }); 5 | -------------------------------------------------------------------------------- /src/pages/index/index/content.ejs: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 4 |
    5 | 6 |
    -------------------------------------------------------------------------------- /src/pages/index/index/html.js: -------------------------------------------------------------------------------- 1 | const content = require('./content.ejs'); 2 | const layout = require('layout'); 3 | 4 | module.exports = layout.init({ 5 | pageTitle: '', 6 | }).run(content()); 7 | -------------------------------------------------------------------------------- /src/pages/index/index/page.js: -------------------------------------------------------------------------------- 1 | require('cp'); 2 | const config = require('configModule'); 3 | 4 | $(() => { 5 | /* global IS_PRODUCTION:true */ // 由于ESLint会检测没有定义的变量,因此需要这一个`global`注释声明IS_PRODUCTION是一个全局变量(当然在本例中并不是)来规避warning 6 | if (!IS_PRODUCTION) { 7 | console.log('如果你看到这个Log,那么这个版本实际上是开发用的版本'); 8 | console.log(config.API_ROOT); 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /src/pages/index/login/html.js: -------------------------------------------------------------------------------- 1 | const config = require('configModule'); 2 | const noJquery = require('withoutJqueryModule'); 3 | const content = require('./templates/main.ejs'); 4 | const layout = require('layout-without-nav'); 5 | const dirsConfig = config.DIRS; 6 | 7 | const loginBoxHtml = require('./templates/login-box.ejs')({ 8 | constructInsideUrl: noJquery.constructInsideUrl, 9 | }); 10 | const forgetPasswordHtml = require('./templates/forget-password-box.html'); 11 | const renderData = Object.assign({}, dirsConfig, { loginBoxHtml, forgetPasswordHtml }); 12 | 13 | module.exports = layout.init({ 14 | pageTitle: '', 15 | }).run(content(renderData)); 16 | -------------------------------------------------------------------------------- /src/pages/index/login/page.js: -------------------------------------------------------------------------------- 1 | require('lessDir/base.less'); 2 | require('./page.less'); 3 | 4 | window.switchToPage = (page) => { 5 | switch (page) { 6 | case 'login': 7 | $('#user-edit-password').hide(); 8 | $('#login-box').show(); 9 | break; 10 | 11 | case 'forget-password': 12 | $('#login-box').hide(); 13 | $('#user-edit-password').show(); 14 | break; 15 | 16 | default: 17 | } 18 | }; 19 | 20 | $(() => { 21 | 22 | }); 23 | -------------------------------------------------------------------------------- /src/pages/index/login/page.less: -------------------------------------------------------------------------------- 1 | html, body { 2 | overflow-y: auto; 3 | } 4 | @media(min-width: 768px) { 5 | min-height: 945px; 6 | } 7 | 8 | @media(min-width: 768px) { 9 | #bg { 10 | width: 100%; 11 | height: 945px; 12 | position: absolute; 13 | z-index: 0; 14 | } 15 | } 16 | 17 | .register-panel, .login-panel, .forget-password-panel { 18 | margin-top: 100px; 19 | } 20 | 21 | .panel-heading { 22 | padding: 31px 15px; 23 | 24 | .panel-title { 25 | font-size: 24px; 26 | color: #333; 27 | } 28 | } 29 | 30 | .panel-body { 31 | /* max-height: 450px; 32 | overflow-y: auto; */ 33 | padding: 35px 43px; 34 | } 35 | 36 | .tab-content { 37 | margin-top: 15px; 38 | } 39 | 40 | .link-container { 41 | margin-top: 15px; 42 | } 43 | 44 | .form-inline .form-group { 45 | margin-right: 10px; 46 | } -------------------------------------------------------------------------------- /src/pages/index/login/templates/forget-password-box.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/index/login/templates/login-box.ejs: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 |
    5 |
    6 |
    7 |
    8 |

    9 | 欢迎登录XXX管理后台 10 |

    11 |
    12 |
    13 |
    14 |
    15 | 16 |
    17 | 18 |
    19 |
    20 |
    21 | 22 |
    23 | 24 |
    25 |
    26 | 马上登录 27 |
    28 | 33 |
    34 |
    35 |
    36 |
    37 |
    38 |
    -------------------------------------------------------------------------------- /src/pages/index/login/templates/main.ejs: -------------------------------------------------------------------------------- 1 | 8 | 15 |
    16 | <%= loginBoxHtml %> 17 | <%= forgetPasswordHtml %> 18 |
    -------------------------------------------------------------------------------- /src/pages/user/edit-password/content.ejs: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 | 5 |
    6 |
    7 |
    8 |
    9 | 10 | 11 |
    12 |
    13 | 14 | 15 |
    16 |
    17 | 18 | 19 |
    20 |
    21 | 22 |
    23 | 24 | 25 | 26 | 27 |
    28 |
    29 |
    30 | 31 |
    32 | 33 | 34 | 35 | 36 |
    37 |
    38 |
    39 |
    40 |
    41 |
    42 |
    43 | 44 |
    45 |
    46 |
    47 |
    48 |
    -------------------------------------------------------------------------------- /src/pages/user/edit-password/html.js: -------------------------------------------------------------------------------- 1 | const content = require('./content.ejs'); 2 | const layout = require('layout'); 3 | const pageTitle = '修改密码'; 4 | module.exports = layout.init({ pageTitle }).run(content({ pageTitle })); 5 | -------------------------------------------------------------------------------- /src/pages/user/edit-password/page.js: -------------------------------------------------------------------------------- 1 | require('cp'); 2 | $(() => { 3 | }); 4 | -------------------------------------------------------------------------------- /src/pages/user/modify-info/content.ejs: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 | 5 |
    6 |
    7 |
    8 |
    9 | 10 | 11 |
    12 |
    13 | 14 | 15 |
    16 |
    17 |
    18 |
    19 |
    20 |
    21 | 22 |
    23 |
    24 |
    25 |
    26 |
    -------------------------------------------------------------------------------- /src/pages/user/modify-info/html.js: -------------------------------------------------------------------------------- 1 | const content = require('./content.ejs'); 2 | const layout = require('layout'); 3 | const pageTitle = '修改个人信息'; 4 | module.exports = layout.init({ pageTitle }).run(content({ pageTitle })); 5 | -------------------------------------------------------------------------------- /src/pages/user/modify-info/page.js: -------------------------------------------------------------------------------- 1 | require('cp'); 2 | 3 | $(() => { 4 | }); 5 | -------------------------------------------------------------------------------- /src/public-resource/components/footer/html.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/public-resource/components/header/html.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <% if (pageTitle) { %> <%= pageTitle %> - <% } %> XXXX后台 7 | 8 | 9 | 10 | 13 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /src/public-resource/components/side-menu/html.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/public-resource/components/top-nav/html.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/public-resource/config/build-file.config.js: -------------------------------------------------------------------------------- 1 | require('!!file-loader?name=index.html!../../index.html'); 2 | module.exports = { 3 | js: { 4 | html5shiv: require('!!file-loader?name=static/js/[name].[ext]!../../../vendor/ie-fix/html5shiv.min.js'), 5 | respond: require('!!file-loader?name=static/js/[name].[ext]!../../../vendor/ie-fix/respond.min.js'), 6 | jquery: require('!!file-loader?name=static/js/[name].[ext]!jquery/dist/jquery.min.js'), 7 | }, 8 | images: { 9 | 'login-bg': require('!!file-loader?name=static/images/[name].[ext]!../imgs/login-bg.jpg'), 10 | }, 11 | // dll: { 12 | // js: require('!!file-loader?name=dll/dll.js!../../dll/dll.js'), 13 | // css: require('!file-loader?name=dll/dll.css!../../dll/dll.css'), 14 | // }, 15 | }; 16 | -------------------------------------------------------------------------------- /src/public-resource/config/common.config.js: -------------------------------------------------------------------------------- 1 | const buildFileConfig = require('configDir/build-file.config'); 2 | const moduleExports = { 3 | DIRS: { 4 | BUILD_FILE: buildFileConfig, 5 | }, 6 | 7 | PAGE_ROOT_PATH: '../../', 8 | }; 9 | 10 | /* 帮助确定ie下CORS的代理文件 */ 11 | moduleExports.DIRS.SERVER_API_URL = moduleExports.SERVER_API_URL; 12 | 13 | /* global IS_PRODUCTION:true */ // 由于ESLint会检测没有定义的变量,因此需要这一个`global`注释声明IS_PRODUCTION是一个全局变量(当然在本例中并不是)来规避warning 14 | if (IS_PRODUCTION) { // 由于本脚手架并没有牵涉到HTTP请求,因此此处仅作为演示分离开发/生产环境之用。 15 | moduleExports.API_ROOT = 'http://api.xxxx.com/'; 16 | } else { 17 | moduleExports.API_ROOT = 'http://localhost/mock/'; 18 | } 19 | 20 | module.exports = moduleExports; 21 | -------------------------------------------------------------------------------- /src/public-resource/iconfont/demo.css: -------------------------------------------------------------------------------- 1 | *{margin: 0;padding: 0;list-style: none;} 2 | /* 3 | KISSY CSS Reset 4 | 理念:1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。 5 | 2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。 6 | 3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。 7 | 特色:1. 适应中文;2. 基于最新主流浏览器。 8 | 维护:玉伯, 正淳 9 | */ 10 | 11 | /** 清除内外边距 **/ 12 | body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */ 13 | dl, dt, dd, ul, ol, li, /* list elements 列表元素 */ 14 | pre, /* text formatting elements 文本格式元素 */ 15 | form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */ 16 | th, td /* table elements 表格元素 */ { 17 | margin: 0; 18 | padding: 0; 19 | } 20 | 21 | /** 设置默认字体 **/ 22 | body, 23 | button, input, select, textarea /* for ie */ { 24 | font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif; 25 | } 26 | h1, h2, h3, h4, h5, h6 { font-size: 100%; } 27 | address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */ 28 | code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */ 29 | small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */ 30 | 31 | /** 重置列表元素 **/ 32 | ul, ol { list-style: none; } 33 | 34 | /** 重置文本格式元素 **/ 35 | a { text-decoration: none; } 36 | a:hover { text-decoration: underline; } 37 | 38 | 39 | /** 重置表单元素 **/ 40 | legend { color: #000; } /* for ie6 */ 41 | fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */ 42 | button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */ 43 | /* 注:optgroup 无法扶正 */ 44 | 45 | /** 重置表格元素 **/ 46 | table { border-collapse: collapse; border-spacing: 0; } 47 | 48 | /* 清除浮动 */ 49 | .ks-clear:after, .clear:after { 50 | content: '\20'; 51 | display: block; 52 | height: 0; 53 | clear: both; 54 | } 55 | .ks-clear, .clear { 56 | *zoom: 1; 57 | } 58 | 59 | .main {padding: 30px 100px;} 60 | .main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;} 61 | 62 | .helps{margin-top:40px;} 63 | .helps pre{ 64 | padding:20px; 65 | margin:10px 0; 66 | border:solid 1px #e7e1cd; 67 | background-color: #fffdef; 68 | overflow: auto; 69 | } 70 | 71 | .icon_lists li{ 72 | float:left; 73 | width: 100px; 74 | height:180px; 75 | text-align: center; 76 | } 77 | .icon_lists .icon{ 78 | font-size: 42px; 79 | line-height: 100px; 80 | margin: 10px 0; 81 | color:#333; 82 | -webkit-transition: font-size 0.25s ease-out 0s; 83 | -moz-transition: font-size 0.25s ease-out 0s; 84 | transition: font-size 0.25s ease-out 0s; 85 | 86 | } 87 | .icon_lists .icon:hover{ 88 | font-size: 100px; 89 | } 90 | -------------------------------------------------------------------------------- /src/public-resource/iconfont/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IconFont 7 | 8 | 9 | 10 | 11 |
    12 |

    IconFont 图标

    13 |
      14 | 15 |
    • 16 | 17 |
      编辑
      18 |
      &#xe600;
      19 |
      .edit
      20 |
    • 21 | 22 |
    • 23 | 24 |
      提醒
      25 |
      &#xe601;
      26 |
      .alert
      27 |
    • 28 | 29 |
    • 30 | 31 |
      锁定
      32 |
      &#xe602;
      33 |
      .password
      34 |
    • 35 | 36 |
    • 37 | 38 |
      用户
      39 |
      &#xe603;
      40 |
      .mine
      41 |
    • 42 | 43 |
    • 44 | 45 |
      退出
      46 |
      &#xe604;
      47 |
      .logout
      48 |
    • 49 | 50 |
    • 51 | 52 |
      新窗口打开
      53 |
      &#xe606;
      54 |
      .demo-page
      55 |
    • 56 | 57 |
    • 58 | 59 |
      向下
      60 |
      &#xe607;
      61 |
      .arrow-down
      62 |
    • 63 | 64 |
    • 65 | 66 |
      三角
      67 |
      &#xe605;
      68 |
      .triangle-down
      69 |
    • 70 | 71 |
    • 72 | 73 |
      返回
      74 |
      &#xe608;
      75 |
      .arrow-left
      76 |
    • 77 | 78 |
    79 | 80 | 81 |
    82 | 第一步:使用font-face声明字体 83 |
     84 | @font-face {font-family: 'iconfont';
     85 |     src: url('iconfont.eot'); /* IE9*/
     86 |     src: url('iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
     87 |     url('iconfont.woff') format('woff'), /* chrome、firefox */
     88 |     url('iconfont.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
     89 |     url('iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
     90 | }
     91 | 
    92 | 第二步:定义使用iconfont的样式 93 |
     94 | .iconfont{
     95 |     font-family:"iconfont" !important;
     96 |     font-size:16px;font-style:normal;
     97 |     -webkit-font-smoothing: antialiased;
     98 |     -webkit-text-stroke-width: 0.2px;
     99 |     -moz-osx-font-smoothing: grayscale;}
    100 | 
    101 | 第三步:挑选相应图标并获取字体编码,应用于页面 102 |
    103 | <i class="iconfont">&#x33;</i>
    104 | 
    105 |
    106 | 107 |
    108 | 109 | 110 | -------------------------------------------------------------------------------- /src/public-resource/iconfont/iconfont.css: -------------------------------------------------------------------------------- 1 | 2 | @font-face {font-family: "iconfont"; 3 | src: url('iconfont.eot?t=1473142795'); /* IE9*/ 4 | src: url('iconfont.eot?t=1473142795#iefix') format('embedded-opentype'), /* IE6-IE8 */ 5 | url('iconfont.woff?t=1473142795') format('woff'), /* chrome, firefox */ 6 | url('iconfont.ttf?t=1473142795') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ 7 | url('iconfont.svg?t=1473142795#iconfont') format('svg'); /* iOS 4.1- */ 8 | } 9 | 10 | .iconfont { 11 | font-family:"iconfont" !important; 12 | font-size:16px; 13 | font-style:normal; 14 | -webkit-font-smoothing: antialiased; 15 | -webkit-text-stroke-width: 0.2px; 16 | -moz-osx-font-smoothing: grayscale; 17 | } 18 | .icon-edit:before { content: "\e600"; } 19 | .icon-alert:before { content: "\e601"; } 20 | .icon-password:before { content: "\e602"; } 21 | .icon-mine:before { content: "\e603"; } 22 | .icon-logout:before { content: "\e604"; } 23 | .icon-demo-page:before { content: "\e606"; } 24 | .icon-arrow-down:before { content: "\e607"; } 25 | .icon-triangle-down:before { content: "\e605"; } 26 | .icon-arrow-left:before { content: "\e608"; } 27 | -------------------------------------------------------------------------------- /src/public-resource/iconfont/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Array-Huang/webpack-seed/511480ba0ffd9c4153c1a2e5e7b79550aac6d2e2/src/public-resource/iconfont/iconfont.eot -------------------------------------------------------------------------------- /src/public-resource/iconfont/iconfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Created by FontForge 20120731 at Tue Sep 6 14:19:55 2016 6 | By admin 7 | 8 | 9 | 10 | 24 | 26 | 28 | 30 | 32 | 36 | 38 | 42 | 45 | 50 | 54 | 56 | 60 | 62 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/public-resource/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Array-Huang/webpack-seed/511480ba0ffd9c4153c1a2e5e7b79550aac6d2e2/src/public-resource/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /src/public-resource/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Array-Huang/webpack-seed/511480ba0ffd9c4153c1a2e5e7b79550aac6d2e2/src/public-resource/iconfont/iconfont.woff -------------------------------------------------------------------------------- /src/public-resource/imgs/login-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Array-Huang/webpack-seed/511480ba0ffd9c4153c1a2e5e7b79550aac6d2e2/src/public-resource/imgs/login-bg.jpg -------------------------------------------------------------------------------- /src/public-resource/layout/layout-without-nav/html.ejs: -------------------------------------------------------------------------------- 1 | <%= header %> 2 |
    3 | <%= content %> 4 |
    5 | <%= footer %> -------------------------------------------------------------------------------- /src/public-resource/layout/layout-without-nav/html.js: -------------------------------------------------------------------------------- 1 | const config = require('configModule'); 2 | const noJquery = require('withoutJqueryModule'); 3 | const layout = require('./html.ejs'); 4 | const header = require('../../components/header/html.ejs'); 5 | const footer = require('../../components/footer/html.ejs'); 6 | 7 | const pf = { 8 | pageTitle: '', 9 | constructInsideUrl: noJquery.constructInsideUrl, 10 | }; 11 | 12 | const moduleExports = { 13 | init({ pageTitle }) { 14 | pf.pageTitle = pageTitle; 15 | return this; 16 | }, 17 | run(content) { 18 | const componentRenderData = Object.assign({}, config, pf); 19 | const renderData = { 20 | header: header(componentRenderData), 21 | footer: footer(componentRenderData), 22 | content, 23 | }; 24 | return layout(renderData); 25 | }, 26 | }; 27 | 28 | module.exports = moduleExports; 29 | -------------------------------------------------------------------------------- /src/public-resource/layout/layout/html.ejs: -------------------------------------------------------------------------------- 1 | <%= header %> 2 |
    3 | <%= topNav %> 4 | <%= sideMenu %> 5 | <%= content %> 6 |
    7 | <%= footer %> -------------------------------------------------------------------------------- /src/public-resource/layout/layout/html.js: -------------------------------------------------------------------------------- 1 | const config = require('configModule'); 2 | const noJquery = require('withoutJqueryModule'); 3 | const layout = require('./html.ejs'); // 整个页面布局的模板文件,主要是用来统筹各个公共组件的结构 4 | const header = require('../../components/header/html.ejs'); // 页头的模板 5 | const footer = require('../../components/footer/html.ejs'); // 页脚的模板 6 | const topNav = require('../../components/top-nav/html.ejs'); // 顶部栏的模板 7 | const sideMenu = require('../../components/side-menu/html.ejs'); // 侧边栏的模板 8 | 9 | /* 整理渲染公共部分所用到的模板变量 */ 10 | const pf = { 11 | pageTitle: '', 12 | constructInsideUrl: noJquery.constructInsideUrl, 13 | }; 14 | 15 | const moduleExports = { 16 | /* 处理各个页面传入而又需要在公共区域用到的参数 */ 17 | init({ pageTitle }) { 18 | pf.pageTitle = pageTitle; // 比如说页面名称,会在或面包屑里用到 19 | return this; 20 | }, 21 | 22 | /* 整合各公共组件和页面实际内容,最后生成完整的HTML文档 */ 23 | run(content) { 24 | const componentRenderData = Object.assign({}, config, pf); // 页头组件需要加载css/js等,因此需要比较多的变量 25 | const renderData = { 26 | header: header(componentRenderData), 27 | footer: footer(componentRenderData), 28 | topNav: topNav(componentRenderData), 29 | sideMenu: sideMenu(componentRenderData), 30 | content, 31 | }; 32 | return layout(renderData); 33 | }, 34 | }; 35 | 36 | module.exports = moduleExports; 37 | -------------------------------------------------------------------------------- /src/public-resource/less/base-dir/_badge.less: -------------------------------------------------------------------------------- 1 | .badge-important { 2 | background-color: @brand-danger; 3 | } 4 | .badge-info { 5 | background-color: @brand-primary; 6 | } 7 | .badge-success { 8 | background-color: @brand-success; 9 | } 10 | .badge-warning { 11 | background-color: @brand-warning; 12 | } 13 | .badge-inverse { 14 | background-color: #333; 15 | } 16 | -------------------------------------------------------------------------------- /src/public-resource/less/base-dir/_button.less: -------------------------------------------------------------------------------- 1 | .btn-outline { 2 | color: inherit; 3 | background-color: transparent; 4 | transition: all .5s; 5 | } 6 | 7 | .btn-primary.btn-outline { 8 | color: @brand-primary; 9 | } 10 | 11 | .btn-success.btn-outline { 12 | color: @brand-success; 13 | } 14 | 15 | .btn-info.btn-outline { 16 | color: @brand-info; 17 | } 18 | 19 | .btn-warning.btn-outline { 20 | color: @brand-warning; 21 | } 22 | 23 | .btn-danger.btn-outline { 24 | color: @brand-danger; 25 | } 26 | 27 | .btn-primary.btn-outline:hover, 28 | .btn-success.btn-outline:hover, 29 | .btn-info.btn-outline:hover, 30 | .btn-warning.btn-outline:hover, 31 | .btn-danger.btn-outline:hover { 32 | color: #fff; 33 | } 34 | 35 | /* 圆形按钮 */ 36 | .btn-circle { 37 | width: 30px; 38 | height: 30px; 39 | padding: 6px 0; 40 | border-radius: 15px; 41 | text-align: center; 42 | font-size: 12px; 43 | line-height: 1.428571429; 44 | 45 | &.btn-lg { 46 | width: 50px; 47 | height: 50px; 48 | padding: 10px 16px; 49 | border-radius: 25px; 50 | font-size: 18px; 51 | line-height: 1.33; 52 | } 53 | 54 | &.btn-xl { 55 | width: 70px; 56 | height: 70px; 57 | padding: 10px 16px; 58 | border-radius: 35px; 59 | font-size: 24px; 60 | line-height: 1.33; 61 | } 62 | } -------------------------------------------------------------------------------- /src/public-resource/less/base-dir/_form.less: -------------------------------------------------------------------------------- 1 | @media(min-width:768px) { //PC端 2 | .form-inline { 3 | .form-group { 4 | margin-top: 2px; 5 | margin-bottom: 2px; 6 | margin-right: 15px; 7 | white-space: nowrap; 8 | } 9 | } 10 | } 11 | 12 | .form-inline { 13 | & > .btn, & > label { 14 | margin-left: 10px; 15 | margin-right: 10px; 16 | } 17 | } 18 | 19 | .form-group .checkbox input[type="checkbox"] { 20 | margin-left: 0; 21 | } 22 | 23 | .form-required > label:after { 24 | content: " * "; 25 | color: red; 26 | } -------------------------------------------------------------------------------- /src/public-resource/less/base-dir/_global.less: -------------------------------------------------------------------------------- 1 | /* 全局通用style */ 2 | * { 3 | font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif; 4 | } 5 | 6 | html, body { 7 | .full-screen(); 8 | background-color: @gray-lightest; 9 | } 10 | 11 | a { 12 | .cursorPointer(); 13 | } 14 | 15 | /* 总容器 */ 16 | #wrapper { 17 | .full-screen(); 18 | } 19 | 20 | #page-wrapper { 21 | padding: 5px 5px 5px 5px; 22 | background-color: white; 23 | 24 | .page-header { 25 | font-size: 20px; 26 | } 27 | } 28 | @media(min-width:768px) { //PC端 29 | #page-wrapper { 30 | position: absolute; 31 | top: @top-bar-height + @top-bar-boder-width; 32 | bottom: 0; 33 | left: 250px; 34 | right: 0; 35 | padding: 10px 10px 10px 10px; 36 | overflow-y: auto; 37 | border-left: 1px solid darken(@gray-lightest, 6.5%); 38 | } 39 | } 40 | 41 | .picvcode { 42 | min-width: 80px; 43 | } 44 | 45 | /* 隐藏首屏加载页面时出现的花括号 */ 46 | .ms-controller{ 47 | visibility: hidden 48 | } -------------------------------------------------------------------------------- /src/public-resource/less/base-dir/_iconfont.less: -------------------------------------------------------------------------------- 1 | /* 搬fontawesome的样式过来用 */ 2 | .iconfont { 3 | display: inline-block; 4 | width: 1.5em; 5 | text-align: center; 6 | font-size: inherit; 7 | text-rendering: auto; 8 | } 9 | 10 | /* 图标无限旋转 */ 11 | .iconfont--spin { 12 | -webkit-animation: iconfont--spin 2s infinite linear; 13 | animation: iconfont--spin 2s infinite linear; 14 | } 15 | @-webkit-keyframes iconfont--spin { 16 | 0% { 17 | -webkit-transform: rotate(0deg); 18 | transform: rotate(0deg); 19 | } 20 | 100% { 21 | -webkit-transform: rotate(359deg); 22 | transform: rotate(359deg); 23 | } 24 | } 25 | @keyframes iconfont--spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } -------------------------------------------------------------------------------- /src/public-resource/less/base-dir/_mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | .full-screen() { 3 | width: 100%; 4 | } 5 | 6 | .size(@width, @height) { 7 | width: @width; 8 | height: @height; 9 | } 10 | 11 | .fl() { 12 | float: left; 13 | } 14 | 15 | .fr() { 16 | float: right; 17 | } 18 | 19 | .clearfix() { 20 | &:before,&:after{ 21 | content:""; 22 | display:table; 23 | } 24 | &:after{clear:both;} 25 | &{ 26 | *zoom:1;/*IE/7/6*/ 27 | } 28 | } 29 | 30 | .noselect() { 31 | -moz-user-select:none;/*火狐*/ 32 | -webkit-user-select:none;/*webkit浏览器*/ 33 | -ms-user-select:none;/*IE10*/ 34 | -khtml-user-select:none;/*早期浏览器*/ 35 | user-select:none; 36 | } 37 | 38 | .block-center() { 39 | margin-right: auto; 40 | margin-left: auto; 41 | display: block; 42 | } 43 | 44 | .text-ellipsis() { 45 | white-space: nowrap; 46 | overflow: hidden; 47 | text-overflow: ellipsis; 48 | } 49 | 50 | .cursorPointer() { 51 | cursor: pointer; 52 | } 53 | .cursorPointer { 54 | .cursorPointer(); 55 | } 56 | 57 | .padding0() { 58 | padding: 0; 59 | } 60 | .padding0 { 61 | .padding0(); 62 | } -------------------------------------------------------------------------------- /src/public-resource/less/base-dir/_panel.less: -------------------------------------------------------------------------------- 1 | /* 彩色panel */ 2 | .panel-green { 3 | border-color: @brand-success; 4 | .panel-heading { 5 | border-color: @brand-success; 6 | color: white; 7 | background-color: @brand-success; 8 | } 9 | a { 10 | color: @brand-success; 11 | &:hover { 12 | color: darken(@brand-success, 15%); 13 | } 14 | } 15 | } 16 | 17 | .panel-red { 18 | border-color: @brand-danger; 19 | .panel-heading { 20 | border-color: @brand-danger; 21 | color: white; 22 | background-color: @brand-danger; 23 | } 24 | a { 25 | color: @brand-danger; 26 | &:hover { 27 | color: darken(@brand-danger, 15%); 28 | } 29 | } 30 | } 31 | 32 | .panel-yellow { 33 | border-color: @brand-warning; 34 | .panel-heading { 35 | border-color: @brand-warning; 36 | color: white; 37 | background-color: @brand-warning; 38 | } 39 | a { 40 | color: @brand-warning; 41 | &:hover { 42 | color: darken(@brand-warning, 15%); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/public-resource/less/base-dir/_table.less: -------------------------------------------------------------------------------- 1 | @media(min-width:768px) { //PC端 2 | .table td .btn { 3 | margin-top: 2px; 4 | margin-bottom: 2px; 5 | } 6 | } 7 | 8 | .table td .btn { 9 | margin-left: 2px; 10 | margin-right: 2px; 11 | } -------------------------------------------------------------------------------- /src/public-resource/less/base-dir/_variables.less: -------------------------------------------------------------------------------- 1 | /* 颜色 */ 2 | @gray-darker: lighten(#000, 13.5%); 3 | @gray-dark: lighten(#000, 20%); 4 | @gray: lighten(#000, 33.5%); 5 | @gray-light: lighten(#000, 60%); 6 | @gray-lighter: lighten(#000, 93.5%); 7 | @gray-lightest: lighten(#000, 97.25%); 8 | @brand-primary: #428bca; 9 | @brand-success: #5cb85c; 10 | @brand-info: #5bc0de; 11 | @brand-warning: #f0ad4e; 12 | @brand-danger: #d9534f; 13 | 14 | /* 各种尺寸 */ 15 | @top-bar-height: 51px; 16 | @top-bar-boder-width: 1px; -------------------------------------------------------------------------------- /src/public-resource/less/base.less: -------------------------------------------------------------------------------- 1 | @base-dir: './base-dir'; 2 | @widgets-dir: './widgets-dir'; 3 | @components-dir: './components-dir'; 4 | @vendor-dir: './vendor-dir'; 5 | 6 | 7 | @import "@{vendor-dir}/bootstrap/css/bootstrap.min.css"; 8 | 9 | @import "@{base-dir}/_variables.less"; 10 | @import "@{base-dir}/_mixins.less"; 11 | 12 | /* 全局样式 */ 13 | @import "@{base-dir}/_global.less"; 14 | 15 | /* iconfont相关 */ 16 | @import "@{base-dir}/_iconfont.less"; 17 | 18 | /* 按钮 */ 19 | @import "@{base-dir}/_button.less"; 20 | 21 | /* panel(面板) */ 22 | @import "@{base-dir}/_panel.less"; 23 | 24 | /* badge(徽章) */ 25 | @import "@{base-dir}/_badge.less"; 26 | 27 | /* 表单 */ 28 | @import "@{base-dir}/_form.less"; 29 | 30 | /* 表格 */ 31 | @import "@{base-dir}/_table.less"; 32 | 33 | /* 顶部菜单栏 */ 34 | @import "@{components-dir}/_top-menu.less"; 35 | 36 | /* 侧边导航栏 */ 37 | @import "@{components-dir}/_side-nav.less"; 38 | 39 | /* 模态弹出框 */ 40 | @import "@{components-dir}/_modal.less"; 41 | 42 | /* 标签页 */ 43 | @import "@{components-dir}/_tab.less"; -------------------------------------------------------------------------------- /src/public-resource/less/components-dir/_modal.less: -------------------------------------------------------------------------------- 1 | @media (min-width: 1280px) { 2 | .modal-lg { 3 | width: 1200px; 4 | } 5 | } 6 | 7 | @media (min-width: 1440px) { 8 | .modal-lg { 9 | width: 1350px; 10 | } 11 | } -------------------------------------------------------------------------------- /src/public-resource/less/components-dir/_side-nav.less: -------------------------------------------------------------------------------- 1 | .sidebar { 2 | #side-menu { 3 | visibility: hidden; 4 | } 5 | 6 | ul li { 7 | border-bottom: 1px solid darken(@gray-lightest, 6.5%); 8 | a { 9 | &.active { 10 | background-color: @gray-lighter; 11 | } 12 | } 13 | } 14 | 15 | .sidebar-nav.navbar-collapse { 16 | padding-left: 0; 17 | padding-right: 0; 18 | } 19 | 20 | .sidebar-search { 21 | padding: 15px; 22 | } 23 | 24 | .arrow { 25 | float: right; 26 | 27 | &.iconfont:before { 28 | content: "\e608"; 29 | } 30 | } 31 | 32 | .active > a > .iconfont.arrow:before { 33 | content: "\e607"; 34 | } 35 | 36 | .nav-second-level li, .nav-third-level li { 37 | border-bottom: none !important; 38 | } 39 | 40 | .nav-second-level li a { 41 | padding-left: 37px; 42 | } 43 | 44 | .nav-third-level li a { 45 | padding-left: 52px; 46 | } 47 | } 48 | 49 | @media(min-width:768px) { //PC端 50 | .sidebar { 51 | z-index: 1; 52 | position: absolute; 53 | width: 250px; 54 | top: @top-bar-height + @top-bar-boder-width; 55 | bottom: 0; 56 | overflow-y: auto; 57 | } 58 | 59 | .navbar-top-links .dropdown-messages, 60 | .navbar-top-links .dropdown-tasks, 61 | .navbar-top-links .dropdown-alerts { 62 | margin-left: auto; 63 | } 64 | } -------------------------------------------------------------------------------- /src/public-resource/less/components-dir/_tab.less: -------------------------------------------------------------------------------- 1 | .tab-content { 2 | margin-top: 10px; 3 | } 4 | -------------------------------------------------------------------------------- /src/public-resource/less/components-dir/_top-menu.less: -------------------------------------------------------------------------------- 1 | .navbar { 2 | margin-bottom: 0; 3 | } 4 | 5 | .navbar-top-links { 6 | margin-right: 15px; 7 | 8 | li { 9 | display: inline-block; 10 | 11 | a { 12 | padding: 15px; 13 | // min-height: 50px; 14 | } 15 | } 16 | 17 | .dropdown-menu li { 18 | display: block; 19 | 20 | a { 21 | padding: 3px 20px; 22 | // min-height: 0; 23 | 24 | div { 25 | white-space: normal; 26 | } 27 | } 28 | } 29 | 30 | .dropdown-messages, .dropdown-tasks, .dropdown-alerts { 31 | width: 310px; 32 | min-width: 0; 33 | } 34 | 35 | .dropdown-messages { 36 | margin-left: 5px; 37 | } 38 | 39 | .dropdown-tasks { 40 | margin-left: -59px; 41 | } 42 | 43 | .dropdown-alerts { 44 | margin-left: -123px; 45 | } 46 | 47 | .dropdown-user { 48 | right: 0; 49 | left: auto; 50 | } 51 | } 52 | @media (min-width: 768px) { 53 | .navbar-right { 54 | margin-right: 15px; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/public-resource/less/vendor-dir/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Array-Huang/webpack-seed/511480ba0ffd9c4153c1a2e5e7b79550aac6d2e2/src/public-resource/less/vendor-dir/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/public-resource/less/vendor-dir/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Array-Huang/webpack-seed/511480ba0ffd9c4153c1a2e5e7b79550aac6d2e2/src/public-resource/less/vendor-dir/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/public-resource/less/vendor-dir/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Array-Huang/webpack-seed/511480ba0ffd9c4153c1a2e5e7b79550aac6d2e2/src/public-resource/less/vendor-dir/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/public-resource/less/vendor-dir/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Array-Huang/webpack-seed/511480ba0ffd9c4153c1a2e5e7b79550aac6d2e2/src/public-resource/less/vendor-dir/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/public-resource/libs/libs.module.js: -------------------------------------------------------------------------------- 1 | const moduleExports = { 2 | /** 3 | * URL相关 开始 4 | */ 5 | /* 在新窗口打开指定的URL */ 6 | openNewWindow(redirectUrl) { 7 | $('body').append(`<a href="${redirectUrl}" target="_blank" id="hidden-link" style="visibility: hidden;">在新窗口打开指定URL</a>`); 8 | document.getElementById('hidden-link').click(); 9 | }, 10 | /* URL相关 结束 */ 11 | 12 | /* 从一个对象中取出指定的字段形成一个新对象 */ 13 | fetchObjFields(fieldsArr, obj) { 14 | const resultObj = {}; 15 | for (let i = 0; i < fieldsArr.length; i ++) { 16 | const _key = fieldsArr[i]; 17 | resultObj[_key] = obj[_key]; 18 | } 19 | return resultObj; 20 | }, 21 | 22 | /* 在页面间传递参数 */ 23 | sendParamBetweenPages(toPage, key, value) { 24 | const localStorageKey = `${key}-to-${toPage}Page`; 25 | this.locStorage.set(localStorageKey, value); 26 | }, 27 | /* 在页面间接受参数 */ 28 | receiveParamBetweenPages(targetPage, key, dontRemove = false) { 29 | const localStorageKey = `${key}-to-${targetPage}Page`; 30 | const val = this.locStorage.get(localStorageKey); 31 | 32 | if (!dontRemove) { 33 | this.locStorage.remove(localStorageKey); 34 | } 35 | 36 | return val; 37 | }, 38 | _eventListenerArr: {}, 39 | /** 40 | * 监听自定义事件 41 | * 示例: 42 | libs.addEventListener({ 43 | eventName: 'order-status-select', 44 | cb: (ret) => { 45 | if (ret) { 46 | console.log(ret.value); 47 | } 48 | }, 49 | ); 50 | * 51 | */ 52 | addEventListener({ eventName, targetPage, cb }) { 53 | const config = require('configModule'); 54 | const intervalId = window.setInterval(() => { 55 | let dontRemove = false; 56 | if (!targetPage) { 57 | targetPage = 'any-page'; 58 | dontRemove = true; 59 | } 60 | const ret = this.receiveParamBetweenPages(targetPage, `event-${eventName}`, dontRemove); 61 | if (!!ret && typeof ret === 'object') { 62 | if ($.isFunction(cb)) { 63 | cb(ret); 64 | } 65 | } 66 | }, config.CHECK_CROSS_PAGE_EVENT_PER_TIME); 67 | this._eventListenerArr[eventName] = intervalId; 68 | }, 69 | /** 70 | * 移除事件监听 71 | * 示例: 72 | libs.removeEventListener({ eventName: 'order-status-select' }); 73 | * 74 | */ 75 | removeEventListener({ eventName }) { 76 | clearInterval(this._eventListenerArr[eventName]); 77 | }, 78 | 79 | /** 80 | * 将任意一个自定义事件广播出去,该事件可在任意页面通过addEventListener监听收到。 81 | * 示例: 82 | libs.sendEvent({ eventName: 'user-alerdy-login' }); 83 | libs.sendEvent({ 84 | eventName: 'user-alerdy-login', //事件名 85 | extra: { // callback中可取到的参数 86 | key1: 'value1', 87 | key2: 'value2' 88 | } 89 | }); 90 | libs.sendEvent({ 91 | eventName: 'user-alerdy-login', 92 | extra: { 93 | key1: 'value1', 94 | key2: 'value2', 95 | }, 96 | }); 97 | * 98 | */ 99 | sendEvent({ eventName, targetPage, extra }) { 100 | const ret = { 101 | value: extra, 102 | }; 103 | targetPage = !!targetPage ? targetPage : 'any-page'; 104 | this.sendParamBetweenPages(targetPage, `event-${eventName}`, ret); 105 | }, 106 | 107 | /* 格式化处理浮点型(带小数位) */ 108 | formatFloat(num, pos) { 109 | pos = pos || 2; 110 | return Math.round(num * Math.pow(10, pos)) / Math.pow(10, pos); 111 | }, 112 | 113 | /* 获取URL上的get参数 */ 114 | getRequestParams() { 115 | const url = window.location.search; // 获取url中"?"符后的字串 116 | const theRequest = {}; 117 | if (url.indexOf('?') !== -1) { 118 | const str = url.substr(1); 119 | const strs = str.split('&'); 120 | for (let i = 0; i < strs.length; i ++) { 121 | theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1]); 122 | } 123 | } 124 | return theRequest; 125 | }, 126 | 127 | tooltip: { 128 | init() { 129 | $('[data-toggle="tooltip"]').tooltip({ 130 | container: 'body', 131 | placement: 'top', 132 | }); 133 | }, 134 | 135 | hide($dom) { 136 | $dom.tooltip('hide'); 137 | }, 138 | }, 139 | }; 140 | 141 | module.exports = moduleExports; 142 | -------------------------------------------------------------------------------- /src/public-resource/libs/without-jquery.module.js: -------------------------------------------------------------------------------- 1 | const config = require('configModule'); 2 | module.exports = { 3 | /* 拼接系统内部的URL */ 4 | constructInsideUrl(url, urlTail) { 5 | urlTail = urlTail || ''; 6 | return config.PAGE_ROOT_PATH + url + '/page.html' + urlTail; 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /src/public-resource/logic/common.page.js: -------------------------------------------------------------------------------- 1 | // require('bootstrap/dist/css/bootstrap.min.css'); 2 | require('iconfontDir/iconfont.css'); 3 | require('lessDir/base.less'); 4 | require('metisMenu/metisMenu.min'); 5 | require('bootstrap/dist/js/bootstrap.min.js'); 6 | require('vendorDir/promise.min'); 7 | 8 | $(() => { 9 | $('#side-menu').metisMenu(); 10 | $('#side-menu').css('visibility', 'visible'); 11 | (() => { 12 | const width = (window.innerWidth > 0) ? window.innerWidth : window.screen.width; 13 | if (width < 768) { 14 | $('div.navbar-collapse').addClass('collapse'); 15 | // topOffset = 100; // 2-row-menu 16 | const topOffset = $('nav.navbar').height() + 1 + 1; 17 | 18 | let height = ((window.innerHeight > 0) ? window.innerHeight : window.screen.height) - 4; 19 | height = height - topOffset; 20 | if (height < 1) height = 1; 21 | if (height > topOffset) { 22 | $('#page-wrapper').css('min-height', (height) + 'px'); 23 | } 24 | } else { 25 | $('div.navbar-collapse').removeClass('collapse'); 26 | } 27 | 28 | const url = window.location.href; 29 | let element = $('ul.nav a').filter(function filterCb() { 30 | return this.href === url; 31 | }).addClass('active') 32 | .parent('li'); 33 | let ifContinue = true; 34 | while (ifContinue) { 35 | if (element.is('li')) { 36 | element = element.parent('ul').addClass('in') 37 | .parent('li') 38 | .addClass('active'); 39 | } else { 40 | ifContinue = false; 41 | } 42 | } 43 | })(); 44 | 45 | /* 事件绑定 开始 */ 46 | 47 | /* 事件绑定 结束 */ 48 | 49 | /* 各种定时器 开始 */ 50 | /* 各种定时器 结束 */ 51 | }); 52 | -------------------------------------------------------------------------------- /vendor/ie-fix/html5shiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /vendor/ie-fix/jquery.xdomainrequest.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery-ajaxTransport-XDomainRequest - v1.0.4 - 2015-03-05 3 | * https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest 4 | * Copyright (c) 2015 Jason Moon (@JSONMOON) 5 | * Licensed MIT (/blob/master/LICENSE.txt) 6 | */ 7 | (function(a){if(typeof define==='function'&&define.amd){define(['jquery'],a)}else if(typeof exports==='object'){module.exports=a(require('jquery'))}else{a(jQuery)}}(function($){if($.support.cors||!$.ajaxTransport||!window.XDomainRequest){return $}var n=/^(https?:)?\/\//i;var o=/^get|post$/i;var p=new RegExp('^(\/\/|'+location.protocol+')','i');$.ajaxTransport('* text html xml json',function(j,k,l){if(!j.crossDomain||!j.async||!o.test(j.type)||!n.test(j.url)||!p.test(j.url)){return}var m=null;return{send:function(f,g){var h='';var i=(k.dataType||'').toLowerCase();m=new XDomainRequest();if(/^\d+$/.test(k.timeout)){m.timeout=k.timeout}m.ontimeout=function(){g(500,'timeout')};m.onload=function(){var a='Content-Length: '+m.responseText.length+'\r\nContent-Type: '+m.contentType;var b={code:200,message:'success'};var c={text:m.responseText};try{if(i==='html'||/text\/html/i.test(m.contentType)){c.html=m.responseText}else if(i==='json'||(i!=='text'&&/\/json/i.test(m.contentType))){try{c.json=$.parseJSON(m.responseText)}catch(e){b.code=500;b.message='parseerror'}}else if(i==='xml'||(i!=='text'&&/\/xml/i.test(m.contentType))){var d=new ActiveXObject('Microsoft.XMLDOM');d.async=false;try{d.loadXML(m.responseText)}catch(e){d=undefined}if(!d||!d.documentElement||d.getElementsByTagName('parsererror').length){b.code=500;b.message='parseerror';throw'Invalid XML: '+m.responseText;}c.xml=d}}catch(parseMessage){throw parseMessage;}finally{g(b.code,b.message,c,a)}};m.onprogress=function(){};m.onerror=function(){g(500,'error',{text:m.responseText})};if(k.data){h=($.type(k.data)==='string')?k.data:$.param(k.data)}m.open(j.type,j.url);m.send(h)},abort:function(){if(m){m.abort()}}}});return $})); -------------------------------------------------------------------------------- /vendor/ie-fix/respond-proxy.html: -------------------------------------------------------------------------------- 1 | <!-- Respond.js: min/max-width media query polyfill. Remote proxy (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs --> 2 | <!DOCTYPE html> 3 | <html> 4 | <head> 5 | <meta charset="utf-8" /> 6 | <title>Respond JS Proxy 7 | 8 | 9 | 95 | 96 | -------------------------------------------------------------------------------- /vendor/ie-fix/respond.min.js: -------------------------------------------------------------------------------- 1 | /*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl 2 | * Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT 3 | * */ 4 | 5 | !function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b' ); 25 | AXO.close(); 26 | iframe = AXO.getElementById( "x" ); 27 | } else { 28 | iframe = doc.createElement( "iframe" ); 29 | iframe.style.cssText = "position:absolute;top:-99em"; 30 | docElem.insertBefore(iframe, docElem.firstElementChild || docElem.firstChild ); 31 | } 32 | 33 | iframe.src = checkBaseURL(proxyURL) + "?url=" + encode(redirectURL) + "&css=" + encode(checkBaseURL(url)); 34 | 35 | function checkFrameName() { 36 | var cssText; 37 | 38 | try { 39 | cssText = iframe.contentWindow.name; 40 | } 41 | catch (e) { } 42 | 43 | if (cssText) { 44 | // We've got what we need. Stop the iframe from loading further content. 45 | iframe.src = "about:blank"; 46 | iframe.parentNode.removeChild(iframe); 47 | iframe = null; 48 | 49 | 50 | // Per http://j.mp/kn9EPh, not taking any chances. Flushing the ActiveXObject 51 | if (AXO) { 52 | AXO = null; 53 | 54 | if (win.CollectGarbage) { 55 | win.CollectGarbage(); 56 | } 57 | } 58 | 59 | callback(cssText); 60 | } 61 | else{ 62 | win.setTimeout(checkFrameName, 100); 63 | } 64 | } 65 | 66 | win.setTimeout(checkFrameName, 500); 67 | } 68 | 69 | // http://stackoverflow.com/a/472729 70 | function checkBaseURL(href) { 71 | var el = document.createElement('div'), 72 | escapedURL = href.split('&').join('&'). 73 | split('<').join('<'). 74 | split('"').join('"'); 75 | 76 | el.innerHTML = 'x'; 77 | return el.firstChild.href; 78 | } 79 | 80 | function checkRedirectURL() { 81 | // IE6 & IE7 don't build out absolute urls in attributes. 82 | // So respond.proxy.gif remains relative instead of http://example.com/respond.proxy.gif. 83 | // This trickery resolves that issue. 84 | if (~ !redirectURL.indexOf(location.host)) { 85 | 86 | var fakeLink = doc.createElement("div"); 87 | 88 | fakeLink.innerHTML = ''; 89 | docElem.insertBefore(fakeLink, docElem.firstElementChild || docElem.firstChild ); 90 | 91 | // Grab the parsed URL from that dummy object 92 | redirectURL = fakeLink.firstChild.href; 93 | 94 | // Clean up 95 | fakeLink.parentNode.removeChild(fakeLink); 96 | fakeLink = null; 97 | } 98 | } 99 | 100 | function buildUrls(){ 101 | var links = doc.getElementsByTagName( "link" ); 102 | 103 | for( var i = 0, linkl = links.length; i < linkl; i++ ){ 104 | 105 | var thislink = links[i], 106 | href = links[i].href, 107 | extreg = (/^([a-zA-Z:]*\/\/(www\.)?)/).test( href ), 108 | ext = (baseElem && !extreg) || extreg; 109 | 110 | //make sure it's an external stylesheet 111 | if( thislink.rel.indexOf( "stylesheet" ) >= 0 && ext ){ 112 | (function( link ){ 113 | fakejax( href, function( css ){ 114 | link.styleSheet.rawCssText = css; 115 | respond.update(); 116 | } ); 117 | })( thislink ); 118 | } 119 | } 120 | 121 | 122 | } 123 | 124 | if( !respond.mediaQueriesSupported ){ 125 | checkRedirectURL(); 126 | buildUrls(); 127 | } 128 | 129 | })( window, document ); 130 | -------------------------------------------------------------------------------- /vendor/ie-fix/xdomain.all.js: -------------------------------------------------------------------------------- 1 | // XHook - v1.3.5 - https://github.com/jpillora/xhook 2 | // Jaime Pillora - MIT Copyright 2016 3 | (function(window,undefined) { 4 | var AFTER, BEFORE, COMMON_EVENTS, EventEmitter, FIRE, FormData, NativeFormData, NativeXMLHttp, OFF, ON, READY_STATE, UPLOAD_EVENTS, XHookFormData, XHookHttpRequest, XMLHTTP, convertHeaders, depricatedProp, document, fakeEvent, mergeObjects, msie, proxyEvents, slice, xhook, _base, 5 | __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 6 | 7 | document = window.document; 8 | 9 | BEFORE = 'before'; 10 | 11 | AFTER = 'after'; 12 | 13 | READY_STATE = 'readyState'; 14 | 15 | ON = 'addEventListener'; 16 | 17 | OFF = 'removeEventListener'; 18 | 19 | FIRE = 'dispatchEvent'; 20 | 21 | XMLHTTP = 'XMLHttpRequest'; 22 | 23 | FormData = 'FormData'; 24 | 25 | UPLOAD_EVENTS = ['load', 'loadend', 'loadstart']; 26 | 27 | COMMON_EVENTS = ['progress', 'abort', 'error', 'timeout']; 28 | 29 | msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1]); 30 | 31 | if (isNaN(msie)) { 32 | msie = parseInt((/trident\/.*; rv:(\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1]); 33 | } 34 | 35 | (_base = Array.prototype).indexOf || (_base.indexOf = function(item) { 36 | var i, x, _i, _len; 37 | for (i = _i = 0, _len = this.length; _i < _len; i = ++_i) { 38 | x = this[i]; 39 | if (x === item) { 40 | return i; 41 | } 42 | } 43 | return -1; 44 | }); 45 | 46 | slice = function(o, n) { 47 | return Array.prototype.slice.call(o, n); 48 | }; 49 | 50 | depricatedProp = function(p) { 51 | return p === "returnValue" || p === "totalSize" || p === "position"; 52 | }; 53 | 54 | mergeObjects = function(src, dst) { 55 | var k, v; 56 | for (k in src) { 57 | v = src[k]; 58 | if (depricatedProp(k)) { 59 | continue; 60 | } 61 | try { 62 | dst[k] = src[k]; 63 | } catch (_error) {} 64 | } 65 | return dst; 66 | }; 67 | 68 | proxyEvents = function(events, src, dst) { 69 | var event, p, _i, _len; 70 | p = function(event) { 71 | return function(e) { 72 | var clone, k, val; 73 | clone = {}; 74 | for (k in e) { 75 | if (depricatedProp(k)) { 76 | continue; 77 | } 78 | val = e[k]; 79 | clone[k] = val === src ? dst : val; 80 | } 81 | return dst[FIRE](event, clone); 82 | }; 83 | }; 84 | for (_i = 0, _len = events.length; _i < _len; _i++) { 85 | event = events[_i]; 86 | if (dst._has(event)) { 87 | src["on" + event] = p(event); 88 | } 89 | } 90 | }; 91 | 92 | fakeEvent = function(type) { 93 | var msieEventObject; 94 | if (document.createEventObject != null) { 95 | msieEventObject = document.createEventObject(); 96 | msieEventObject.type = type; 97 | return msieEventObject; 98 | } else { 99 | try { 100 | return new Event(type); 101 | } catch (_error) { 102 | return { 103 | type: type 104 | }; 105 | } 106 | } 107 | }; 108 | 109 | EventEmitter = function(nodeStyle) { 110 | var emitter, events, listeners; 111 | events = {}; 112 | listeners = function(event) { 113 | return events[event] || []; 114 | }; 115 | emitter = {}; 116 | emitter[ON] = function(event, callback, i) { 117 | events[event] = listeners(event); 118 | if (events[event].indexOf(callback) >= 0) { 119 | return; 120 | } 121 | i = i === undefined ? events[event].length : i; 122 | events[event].splice(i, 0, callback); 123 | }; 124 | emitter[OFF] = function(event, callback) { 125 | var i; 126 | if (event === undefined) { 127 | events = {}; 128 | return; 129 | } 130 | if (callback === undefined) { 131 | events[event] = []; 132 | } 133 | i = listeners(event).indexOf(callback); 134 | if (i === -1) { 135 | return; 136 | } 137 | listeners(event).splice(i, 1); 138 | }; 139 | emitter[FIRE] = function() { 140 | var args, event, i, legacylistener, listener, _i, _len, _ref; 141 | args = slice(arguments); 142 | event = args.shift(); 143 | if (!nodeStyle) { 144 | args[0] = mergeObjects(args[0], fakeEvent(event)); 145 | } 146 | legacylistener = emitter["on" + event]; 147 | if (legacylistener) { 148 | legacylistener.apply(emitter, args); 149 | } 150 | _ref = listeners(event).concat(listeners("*")); 151 | for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { 152 | listener = _ref[i]; 153 | listener.apply(emitter, args); 154 | } 155 | }; 156 | emitter._has = function(event) { 157 | return !!(events[event] || emitter["on" + event]); 158 | }; 159 | if (nodeStyle) { 160 | emitter.listeners = function(event) { 161 | return slice(listeners(event)); 162 | }; 163 | emitter.on = emitter[ON]; 164 | emitter.off = emitter[OFF]; 165 | emitter.fire = emitter[FIRE]; 166 | emitter.once = function(e, fn) { 167 | var fire; 168 | fire = function() { 169 | emitter.off(e, fire); 170 | return fn.apply(null, arguments); 171 | }; 172 | return emitter.on(e, fire); 173 | }; 174 | emitter.destroy = function() { 175 | return events = {}; 176 | }; 177 | } 178 | return emitter; 179 | }; 180 | 181 | xhook = EventEmitter(true); 182 | 183 | xhook.EventEmitter = EventEmitter; 184 | 185 | xhook[BEFORE] = function(handler, i) { 186 | if (handler.length < 1 || handler.length > 2) { 187 | throw "invalid hook"; 188 | } 189 | return xhook[ON](BEFORE, handler, i); 190 | }; 191 | 192 | xhook[AFTER] = function(handler, i) { 193 | if (handler.length < 2 || handler.length > 3) { 194 | throw "invalid hook"; 195 | } 196 | return xhook[ON](AFTER, handler, i); 197 | }; 198 | 199 | xhook.enable = function() { 200 | window[XMLHTTP] = XHookHttpRequest; 201 | if (NativeFormData) { 202 | window[FormData] = XHookFormData; 203 | } 204 | }; 205 | 206 | xhook.disable = function() { 207 | window[XMLHTTP] = xhook[XMLHTTP]; 208 | if (NativeFormData) { 209 | window[FormData] = NativeFormData; 210 | } 211 | }; 212 | 213 | convertHeaders = xhook.headers = function(h, dest) { 214 | var header, headers, k, name, v, value, _i, _len, _ref; 215 | if (dest == null) { 216 | dest = {}; 217 | } 218 | switch (typeof h) { 219 | case "object": 220 | headers = []; 221 | for (k in h) { 222 | v = h[k]; 223 | name = k.toLowerCase(); 224 | headers.push("" + name + ":\t" + v); 225 | } 226 | return headers.join('\n'); 227 | case "string": 228 | headers = h.split('\n'); 229 | for (_i = 0, _len = headers.length; _i < _len; _i++) { 230 | header = headers[_i]; 231 | if (/([^:]+):\s*(.+)/.test(header)) { 232 | name = (_ref = RegExp.$1) != null ? _ref.toLowerCase() : void 0; 233 | value = RegExp.$2; 234 | if (dest[name] == null) { 235 | dest[name] = value; 236 | } 237 | } 238 | } 239 | return dest; 240 | } 241 | }; 242 | 243 | NativeFormData = window[FormData]; 244 | 245 | XHookFormData = function(form) { 246 | var entries; 247 | this.fd = form ? new NativeFormData(form) : new NativeFormData(); 248 | this.form = form; 249 | entries = []; 250 | Object.defineProperty(this, 'entries', { 251 | get: function() { 252 | var fentries; 253 | fentries = !form ? [] : slice(form.querySelectorAll("input,select")).filter(function(e) { 254 | var _ref; 255 | return ((_ref = e.type) !== 'checkbox' && _ref !== 'radio') || e.checked; 256 | }).map(function(e) { 257 | return [e.name, e.type === "file" ? e.files : e.value]; 258 | }); 259 | return fentries.concat(entries); 260 | } 261 | }); 262 | this.append = (function(_this) { 263 | return function() { 264 | var args; 265 | args = slice(arguments); 266 | entries.push(args); 267 | return _this.fd.append.apply(_this.fd, args); 268 | }; 269 | })(this); 270 | }; 271 | 272 | if (NativeFormData) { 273 | xhook[FormData] = NativeFormData; 274 | window[FormData] = XHookFormData; 275 | } 276 | 277 | NativeXMLHttp = window[XMLHTTP]; 278 | 279 | xhook[XMLHTTP] = NativeXMLHttp; 280 | 281 | XHookHttpRequest = window[XMLHTTP] = function() { 282 | var ABORTED, currentState, emitFinal, emitReadyState, event, facade, hasError, hasErrorHandler, readBody, readHead, request, response, setReadyState, status, transiting, writeBody, writeHead, xhr, _i, _len, _ref; 283 | ABORTED = -1; 284 | xhr = new xhook[XMLHTTP](); 285 | request = {}; 286 | status = null; 287 | hasError = void 0; 288 | transiting = void 0; 289 | response = void 0; 290 | readHead = function() { 291 | var key, name, val, _ref; 292 | response.status = status || xhr.status; 293 | if (!(status === ABORTED && msie < 10)) { 294 | response.statusText = xhr.statusText; 295 | } 296 | if (status !== ABORTED) { 297 | _ref = convertHeaders(xhr.getAllResponseHeaders()); 298 | for (key in _ref) { 299 | val = _ref[key]; 300 | if (!response.headers[key]) { 301 | name = key.toLowerCase(); 302 | response.headers[name] = val; 303 | } 304 | } 305 | } 306 | }; 307 | readBody = function() { 308 | if (!xhr.responseType || xhr.responseType === "text") { 309 | response.text = xhr.responseText; 310 | response.data = xhr.responseText; 311 | } else if (xhr.responseType === "document") { 312 | response.xml = xhr.responseXML; 313 | response.data = xhr.responseXML; 314 | } else { 315 | response.data = xhr.response; 316 | } 317 | if ("responseURL" in xhr) { 318 | response.finalUrl = xhr.responseURL; 319 | } 320 | }; 321 | writeHead = function() { 322 | facade.status = response.status; 323 | facade.statusText = response.statusText; 324 | }; 325 | writeBody = function() { 326 | if ('text' in response) { 327 | facade.responseText = response.text; 328 | } 329 | if ('xml' in response) { 330 | facade.responseXML = response.xml; 331 | } 332 | if ('data' in response) { 333 | facade.response = response.data; 334 | } 335 | if ('finalUrl' in response) { 336 | facade.responseURL = response.finalUrl; 337 | } 338 | }; 339 | emitReadyState = function(n) { 340 | while (n > currentState && currentState < 4) { 341 | facade[READY_STATE] = ++currentState; 342 | if (currentState === 1) { 343 | facade[FIRE]("loadstart", {}); 344 | } 345 | if (currentState === 2) { 346 | writeHead(); 347 | } 348 | if (currentState === 4) { 349 | writeHead(); 350 | writeBody(); 351 | } 352 | facade[FIRE]("readystatechange", {}); 353 | if (currentState === 4) { 354 | setTimeout(emitFinal, 0); 355 | } 356 | } 357 | }; 358 | emitFinal = function() { 359 | if (!hasError) { 360 | facade[FIRE]("load", {}); 361 | } 362 | facade[FIRE]("loadend", {}); 363 | if (hasError) { 364 | facade[READY_STATE] = 0; 365 | } 366 | }; 367 | currentState = 0; 368 | setReadyState = function(n) { 369 | var hooks, process; 370 | if (n !== 4) { 371 | emitReadyState(n); 372 | return; 373 | } 374 | hooks = xhook.listeners(AFTER); 375 | process = function() { 376 | var hook; 377 | if (!hooks.length) { 378 | return emitReadyState(4); 379 | } 380 | hook = hooks.shift(); 381 | if (hook.length === 2) { 382 | hook(request, response); 383 | return process(); 384 | } else if (hook.length === 3 && request.async) { 385 | return hook(request, response, process); 386 | } else { 387 | return process(); 388 | } 389 | }; 390 | process(); 391 | }; 392 | facade = request.xhr = EventEmitter(); 393 | xhr.onreadystatechange = function(event) { 394 | try { 395 | if (xhr[READY_STATE] === 2) { 396 | readHead(); 397 | } 398 | } catch (_error) {} 399 | if (xhr[READY_STATE] === 4) { 400 | transiting = false; 401 | readHead(); 402 | readBody(); 403 | } 404 | setReadyState(xhr[READY_STATE]); 405 | }; 406 | hasErrorHandler = function() { 407 | hasError = true; 408 | }; 409 | facade[ON]('error', hasErrorHandler); 410 | facade[ON]('timeout', hasErrorHandler); 411 | facade[ON]('abort', hasErrorHandler); 412 | facade[ON]('progress', function() { 413 | if (currentState < 3) { 414 | setReadyState(3); 415 | } else { 416 | facade[FIRE]("readystatechange", {}); 417 | } 418 | }); 419 | if ('withCredentials' in xhr || xhook.addWithCredentials) { 420 | facade.withCredentials = false; 421 | } 422 | facade.status = 0; 423 | _ref = COMMON_EVENTS.concat(UPLOAD_EVENTS); 424 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 425 | event = _ref[_i]; 426 | facade["on" + event] = null; 427 | } 428 | facade.open = function(method, url, async, user, pass) { 429 | currentState = 0; 430 | hasError = false; 431 | transiting = false; 432 | request.headers = {}; 433 | request.headerNames = {}; 434 | request.status = 0; 435 | response = {}; 436 | response.headers = {}; 437 | request.method = method; 438 | request.url = url; 439 | request.async = async !== false; 440 | request.user = user; 441 | request.pass = pass; 442 | setReadyState(1); 443 | }; 444 | facade.send = function(body) { 445 | var hooks, k, modk, process, send, _j, _len1, _ref1; 446 | _ref1 = ['type', 'timeout', 'withCredentials']; 447 | for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 448 | k = _ref1[_j]; 449 | modk = k === "type" ? "responseType" : k; 450 | if (modk in facade) { 451 | request[k] = facade[modk]; 452 | } 453 | } 454 | request.body = body; 455 | send = function() { 456 | var header, value, _k, _len2, _ref2, _ref3; 457 | proxyEvents(COMMON_EVENTS, xhr, facade); 458 | if (facade.upload) { 459 | proxyEvents(COMMON_EVENTS.concat(UPLOAD_EVENTS), xhr.upload, facade.upload); 460 | } 461 | transiting = true; 462 | xhr.open(request.method, request.url, request.async, request.user, request.pass); 463 | _ref2 = ['type', 'timeout', 'withCredentials']; 464 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 465 | k = _ref2[_k]; 466 | modk = k === "type" ? "responseType" : k; 467 | if (k in request) { 468 | xhr[modk] = request[k]; 469 | } 470 | } 471 | _ref3 = request.headers; 472 | for (header in _ref3) { 473 | value = _ref3[header]; 474 | if (header) { 475 | xhr.setRequestHeader(header, value); 476 | } 477 | } 478 | if (request.body instanceof XHookFormData) { 479 | request.body = request.body.fd; 480 | } 481 | xhr.send(request.body); 482 | }; 483 | hooks = xhook.listeners(BEFORE); 484 | process = function() { 485 | var done, hook; 486 | if (!hooks.length) { 487 | return send(); 488 | } 489 | done = function(userResponse) { 490 | if (typeof userResponse === 'object' && (typeof userResponse.status === 'number' || typeof response.status === 'number')) { 491 | mergeObjects(userResponse, response); 492 | if (__indexOf.call(userResponse, 'data') < 0) { 493 | userResponse.data = userResponse.response || userResponse.text; 494 | } 495 | setReadyState(4); 496 | return; 497 | } 498 | process(); 499 | }; 500 | done.head = function(userResponse) { 501 | mergeObjects(userResponse, response); 502 | return setReadyState(2); 503 | }; 504 | done.progress = function(userResponse) { 505 | mergeObjects(userResponse, response); 506 | return setReadyState(3); 507 | }; 508 | hook = hooks.shift(); 509 | if (hook.length === 1) { 510 | return done(hook(request)); 511 | } else if (hook.length === 2 && request.async) { 512 | return hook(request, done); 513 | } else { 514 | return done(); 515 | } 516 | }; 517 | process(); 518 | }; 519 | facade.abort = function() { 520 | status = ABORTED; 521 | if (transiting) { 522 | xhr.abort(); 523 | } else { 524 | facade[FIRE]('abort', {}); 525 | } 526 | }; 527 | facade.setRequestHeader = function(header, value) { 528 | var lName, name; 529 | lName = header != null ? header.toLowerCase() : void 0; 530 | name = request.headerNames[lName] = request.headerNames[lName] || header; 531 | if (request.headers[name]) { 532 | value = request.headers[name] + ', ' + value; 533 | } 534 | request.headers[name] = value; 535 | }; 536 | facade.getResponseHeader = function(header) { 537 | var name; 538 | name = header != null ? header.toLowerCase() : void 0; 539 | return response.headers[name]; 540 | }; 541 | facade.getAllResponseHeaders = function() { 542 | return convertHeaders(response.headers); 543 | }; 544 | if (xhr.overrideMimeType) { 545 | facade.overrideMimeType = function() { 546 | return xhr.overrideMimeType.apply(xhr, arguments); 547 | }; 548 | } 549 | if (xhr.upload) { 550 | facade.upload = request.upload = EventEmitter(); 551 | } 552 | return facade; 553 | }; 554 | 555 | if (typeof define === "function" && define.amd) { 556 | define("xhook", [], function() { 557 | return xhook; 558 | }); 559 | } else { 560 | (this.exports || this).xhook = xhook; 561 | } 562 | 563 | }.call(this,window)); 564 | 565 | // XDomain - v0.7.5 - https://github.com/jpillora/xdomain 566 | // Jaime Pillora - MIT Copyright 2016 567 | (function(window,undefined) { 568 | // XHook - v1.3.5 - https://github.com/jpillora/xhook 569 | // Jaime Pillora - MIT Copyright 2016 570 | (function(window,undefined) { 571 | var AFTER, BEFORE, COMMON_EVENTS, EventEmitter, FIRE, FormData, NativeFormData, NativeXMLHttp, OFF, ON, READY_STATE, UPLOAD_EVENTS, XHookFormData, XHookHttpRequest, XMLHTTP, convertHeaders, depricatedProp, document, fakeEvent, mergeObjects, msie, proxyEvents, slice, xhook, _base, 572 | __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 573 | 574 | document = window.document; 575 | 576 | BEFORE = 'before'; 577 | 578 | AFTER = 'after'; 579 | 580 | READY_STATE = 'readyState'; 581 | 582 | ON = 'addEventListener'; 583 | 584 | OFF = 'removeEventListener'; 585 | 586 | FIRE = 'dispatchEvent'; 587 | 588 | XMLHTTP = 'XMLHttpRequest'; 589 | 590 | FormData = 'FormData'; 591 | 592 | UPLOAD_EVENTS = ['load', 'loadend', 'loadstart']; 593 | 594 | COMMON_EVENTS = ['progress', 'abort', 'error', 'timeout']; 595 | 596 | msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1]); 597 | 598 | if (isNaN(msie)) { 599 | msie = parseInt((/trident\/.*; rv:(\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1]); 600 | } 601 | 602 | (_base = Array.prototype).indexOf || (_base.indexOf = function(item) { 603 | var i, x, _i, _len; 604 | for (i = _i = 0, _len = this.length; _i < _len; i = ++_i) { 605 | x = this[i]; 606 | if (x === item) { 607 | return i; 608 | } 609 | } 610 | return -1; 611 | }); 612 | 613 | slice = function(o, n) { 614 | return Array.prototype.slice.call(o, n); 615 | }; 616 | 617 | depricatedProp = function(p) { 618 | return p === "returnValue" || p === "totalSize" || p === "position"; 619 | }; 620 | 621 | mergeObjects = function(src, dst) { 622 | var k, v; 623 | for (k in src) { 624 | v = src[k]; 625 | if (depricatedProp(k)) { 626 | continue; 627 | } 628 | try { 629 | dst[k] = src[k]; 630 | } catch (_error) {} 631 | } 632 | return dst; 633 | }; 634 | 635 | proxyEvents = function(events, src, dst) { 636 | var event, p, _i, _len; 637 | p = function(event) { 638 | return function(e) { 639 | var clone, k, val; 640 | clone = {}; 641 | for (k in e) { 642 | if (depricatedProp(k)) { 643 | continue; 644 | } 645 | val = e[k]; 646 | clone[k] = val === src ? dst : val; 647 | } 648 | return dst[FIRE](event, clone); 649 | }; 650 | }; 651 | for (_i = 0, _len = events.length; _i < _len; _i++) { 652 | event = events[_i]; 653 | if (dst._has(event)) { 654 | src["on" + event] = p(event); 655 | } 656 | } 657 | }; 658 | 659 | fakeEvent = function(type) { 660 | var msieEventObject; 661 | if (document.createEventObject != null) { 662 | msieEventObject = document.createEventObject(); 663 | msieEventObject.type = type; 664 | return msieEventObject; 665 | } else { 666 | try { 667 | return new Event(type); 668 | } catch (_error) { 669 | return { 670 | type: type 671 | }; 672 | } 673 | } 674 | }; 675 | 676 | EventEmitter = function(nodeStyle) { 677 | var emitter, events, listeners; 678 | events = {}; 679 | listeners = function(event) { 680 | return events[event] || []; 681 | }; 682 | emitter = {}; 683 | emitter[ON] = function(event, callback, i) { 684 | events[event] = listeners(event); 685 | if (events[event].indexOf(callback) >= 0) { 686 | return; 687 | } 688 | i = i === undefined ? events[event].length : i; 689 | events[event].splice(i, 0, callback); 690 | }; 691 | emitter[OFF] = function(event, callback) { 692 | var i; 693 | if (event === undefined) { 694 | events = {}; 695 | return; 696 | } 697 | if (callback === undefined) { 698 | events[event] = []; 699 | } 700 | i = listeners(event).indexOf(callback); 701 | if (i === -1) { 702 | return; 703 | } 704 | listeners(event).splice(i, 1); 705 | }; 706 | emitter[FIRE] = function() { 707 | var args, event, i, legacylistener, listener, _i, _len, _ref; 708 | args = slice(arguments); 709 | event = args.shift(); 710 | if (!nodeStyle) { 711 | args[0] = mergeObjects(args[0], fakeEvent(event)); 712 | } 713 | legacylistener = emitter["on" + event]; 714 | if (legacylistener) { 715 | legacylistener.apply(emitter, args); 716 | } 717 | _ref = listeners(event).concat(listeners("*")); 718 | for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { 719 | listener = _ref[i]; 720 | listener.apply(emitter, args); 721 | } 722 | }; 723 | emitter._has = function(event) { 724 | return !!(events[event] || emitter["on" + event]); 725 | }; 726 | if (nodeStyle) { 727 | emitter.listeners = function(event) { 728 | return slice(listeners(event)); 729 | }; 730 | emitter.on = emitter[ON]; 731 | emitter.off = emitter[OFF]; 732 | emitter.fire = emitter[FIRE]; 733 | emitter.once = function(e, fn) { 734 | var fire; 735 | fire = function() { 736 | emitter.off(e, fire); 737 | return fn.apply(null, arguments); 738 | }; 739 | return emitter.on(e, fire); 740 | }; 741 | emitter.destroy = function() { 742 | return events = {}; 743 | }; 744 | } 745 | return emitter; 746 | }; 747 | 748 | xhook = EventEmitter(true); 749 | 750 | xhook.EventEmitter = EventEmitter; 751 | 752 | xhook[BEFORE] = function(handler, i) { 753 | if (handler.length < 1 || handler.length > 2) { 754 | throw "invalid hook"; 755 | } 756 | return xhook[ON](BEFORE, handler, i); 757 | }; 758 | 759 | xhook[AFTER] = function(handler, i) { 760 | if (handler.length < 2 || handler.length > 3) { 761 | throw "invalid hook"; 762 | } 763 | return xhook[ON](AFTER, handler, i); 764 | }; 765 | 766 | xhook.enable = function() { 767 | window[XMLHTTP] = XHookHttpRequest; 768 | if (NativeFormData) { 769 | window[FormData] = XHookFormData; 770 | } 771 | }; 772 | 773 | xhook.disable = function() { 774 | window[XMLHTTP] = xhook[XMLHTTP]; 775 | if (NativeFormData) { 776 | window[FormData] = NativeFormData; 777 | } 778 | }; 779 | 780 | convertHeaders = xhook.headers = function(h, dest) { 781 | var header, headers, k, name, v, value, _i, _len, _ref; 782 | if (dest == null) { 783 | dest = {}; 784 | } 785 | switch (typeof h) { 786 | case "object": 787 | headers = []; 788 | for (k in h) { 789 | v = h[k]; 790 | name = k.toLowerCase(); 791 | headers.push("" + name + ":\t" + v); 792 | } 793 | return headers.join('\n'); 794 | case "string": 795 | headers = h.split('\n'); 796 | for (_i = 0, _len = headers.length; _i < _len; _i++) { 797 | header = headers[_i]; 798 | if (/([^:]+):\s*(.+)/.test(header)) { 799 | name = (_ref = RegExp.$1) != null ? _ref.toLowerCase() : void 0; 800 | value = RegExp.$2; 801 | if (dest[name] == null) { 802 | dest[name] = value; 803 | } 804 | } 805 | } 806 | return dest; 807 | } 808 | }; 809 | 810 | NativeFormData = window[FormData]; 811 | 812 | XHookFormData = function(form) { 813 | var entries; 814 | this.fd = form ? new NativeFormData(form) : new NativeFormData(); 815 | this.form = form; 816 | entries = []; 817 | Object.defineProperty(this, 'entries', { 818 | get: function() { 819 | var fentries; 820 | fentries = !form ? [] : slice(form.querySelectorAll("input,select")).filter(function(e) { 821 | var _ref; 822 | return ((_ref = e.type) !== 'checkbox' && _ref !== 'radio') || e.checked; 823 | }).map(function(e) { 824 | return [e.name, e.type === "file" ? e.files : e.value]; 825 | }); 826 | return fentries.concat(entries); 827 | } 828 | }); 829 | this.append = (function(_this) { 830 | return function() { 831 | var args; 832 | args = slice(arguments); 833 | entries.push(args); 834 | return _this.fd.append.apply(_this.fd, args); 835 | }; 836 | })(this); 837 | }; 838 | 839 | if (NativeFormData) { 840 | xhook[FormData] = NativeFormData; 841 | window[FormData] = XHookFormData; 842 | } 843 | 844 | NativeXMLHttp = window[XMLHTTP]; 845 | 846 | xhook[XMLHTTP] = NativeXMLHttp; 847 | 848 | XHookHttpRequest = window[XMLHTTP] = function() { 849 | var ABORTED, currentState, emitFinal, emitReadyState, event, facade, hasError, hasErrorHandler, readBody, readHead, request, response, setReadyState, status, transiting, writeBody, writeHead, xhr, _i, _len, _ref; 850 | ABORTED = -1; 851 | xhr = new xhook[XMLHTTP](); 852 | request = {}; 853 | status = null; 854 | hasError = void 0; 855 | transiting = void 0; 856 | response = void 0; 857 | readHead = function() { 858 | var key, name, val, _ref; 859 | response.status = status || xhr.status; 860 | if (!(status === ABORTED && msie < 10)) { 861 | response.statusText = xhr.statusText; 862 | } 863 | if (status !== ABORTED) { 864 | _ref = convertHeaders(xhr.getAllResponseHeaders()); 865 | for (key in _ref) { 866 | val = _ref[key]; 867 | if (!response.headers[key]) { 868 | name = key.toLowerCase(); 869 | response.headers[name] = val; 870 | } 871 | } 872 | } 873 | }; 874 | readBody = function() { 875 | if (!xhr.responseType || xhr.responseType === "text") { 876 | response.text = xhr.responseText; 877 | response.data = xhr.responseText; 878 | } else if (xhr.responseType === "document") { 879 | response.xml = xhr.responseXML; 880 | response.data = xhr.responseXML; 881 | } else { 882 | response.data = xhr.response; 883 | } 884 | if ("responseURL" in xhr) { 885 | response.finalUrl = xhr.responseURL; 886 | } 887 | }; 888 | writeHead = function() { 889 | facade.status = response.status; 890 | facade.statusText = response.statusText; 891 | }; 892 | writeBody = function() { 893 | if ('text' in response) { 894 | facade.responseText = response.text; 895 | } 896 | if ('xml' in response) { 897 | facade.responseXML = response.xml; 898 | } 899 | if ('data' in response) { 900 | facade.response = response.data; 901 | } 902 | if ('finalUrl' in response) { 903 | facade.responseURL = response.finalUrl; 904 | } 905 | }; 906 | emitReadyState = function(n) { 907 | while (n > currentState && currentState < 4) { 908 | facade[READY_STATE] = ++currentState; 909 | if (currentState === 1) { 910 | facade[FIRE]("loadstart", {}); 911 | } 912 | if (currentState === 2) { 913 | writeHead(); 914 | } 915 | if (currentState === 4) { 916 | writeHead(); 917 | writeBody(); 918 | } 919 | facade[FIRE]("readystatechange", {}); 920 | if (currentState === 4) { 921 | setTimeout(emitFinal, 0); 922 | } 923 | } 924 | }; 925 | emitFinal = function() { 926 | if (!hasError) { 927 | facade[FIRE]("load", {}); 928 | } 929 | facade[FIRE]("loadend", {}); 930 | if (hasError) { 931 | facade[READY_STATE] = 0; 932 | } 933 | }; 934 | currentState = 0; 935 | setReadyState = function(n) { 936 | var hooks, process; 937 | if (n !== 4) { 938 | emitReadyState(n); 939 | return; 940 | } 941 | hooks = xhook.listeners(AFTER); 942 | process = function() { 943 | var hook; 944 | if (!hooks.length) { 945 | return emitReadyState(4); 946 | } 947 | hook = hooks.shift(); 948 | if (hook.length === 2) { 949 | hook(request, response); 950 | return process(); 951 | } else if (hook.length === 3 && request.async) { 952 | return hook(request, response, process); 953 | } else { 954 | return process(); 955 | } 956 | }; 957 | process(); 958 | }; 959 | facade = request.xhr = EventEmitter(); 960 | xhr.onreadystatechange = function(event) { 961 | try { 962 | if (xhr[READY_STATE] === 2) { 963 | readHead(); 964 | } 965 | } catch (_error) {} 966 | if (xhr[READY_STATE] === 4) { 967 | transiting = false; 968 | readHead(); 969 | readBody(); 970 | } 971 | setReadyState(xhr[READY_STATE]); 972 | }; 973 | hasErrorHandler = function() { 974 | hasError = true; 975 | }; 976 | facade[ON]('error', hasErrorHandler); 977 | facade[ON]('timeout', hasErrorHandler); 978 | facade[ON]('abort', hasErrorHandler); 979 | facade[ON]('progress', function() { 980 | if (currentState < 3) { 981 | setReadyState(3); 982 | } else { 983 | facade[FIRE]("readystatechange", {}); 984 | } 985 | }); 986 | if ('withCredentials' in xhr || xhook.addWithCredentials) { 987 | facade.withCredentials = false; 988 | } 989 | facade.status = 0; 990 | _ref = COMMON_EVENTS.concat(UPLOAD_EVENTS); 991 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 992 | event = _ref[_i]; 993 | facade["on" + event] = null; 994 | } 995 | facade.open = function(method, url, async, user, pass) { 996 | currentState = 0; 997 | hasError = false; 998 | transiting = false; 999 | request.headers = {}; 1000 | request.headerNames = {}; 1001 | request.status = 0; 1002 | response = {}; 1003 | response.headers = {}; 1004 | request.method = method; 1005 | request.url = url; 1006 | request.async = async !== false; 1007 | request.user = user; 1008 | request.pass = pass; 1009 | setReadyState(1); 1010 | }; 1011 | facade.send = function(body) { 1012 | var hooks, k, modk, process, send, _j, _len1, _ref1; 1013 | _ref1 = ['type', 'timeout', 'withCredentials']; 1014 | for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 1015 | k = _ref1[_j]; 1016 | modk = k === "type" ? "responseType" : k; 1017 | if (modk in facade) { 1018 | request[k] = facade[modk]; 1019 | } 1020 | } 1021 | request.body = body; 1022 | send = function() { 1023 | var header, value, _k, _len2, _ref2, _ref3; 1024 | proxyEvents(COMMON_EVENTS, xhr, facade); 1025 | if (facade.upload) { 1026 | proxyEvents(COMMON_EVENTS.concat(UPLOAD_EVENTS), xhr.upload, facade.upload); 1027 | } 1028 | transiting = true; 1029 | xhr.open(request.method, request.url, request.async, request.user, request.pass); 1030 | _ref2 = ['type', 'timeout', 'withCredentials']; 1031 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 1032 | k = _ref2[_k]; 1033 | modk = k === "type" ? "responseType" : k; 1034 | if (k in request) { 1035 | xhr[modk] = request[k]; 1036 | } 1037 | } 1038 | _ref3 = request.headers; 1039 | for (header in _ref3) { 1040 | value = _ref3[header]; 1041 | if (header) { 1042 | xhr.setRequestHeader(header, value); 1043 | } 1044 | } 1045 | if (request.body instanceof XHookFormData) { 1046 | request.body = request.body.fd; 1047 | } 1048 | xhr.send(request.body); 1049 | }; 1050 | hooks = xhook.listeners(BEFORE); 1051 | process = function() { 1052 | var done, hook; 1053 | if (!hooks.length) { 1054 | return send(); 1055 | } 1056 | done = function(userResponse) { 1057 | if (typeof userResponse === 'object' && (typeof userResponse.status === 'number' || typeof response.status === 'number')) { 1058 | mergeObjects(userResponse, response); 1059 | if (__indexOf.call(userResponse, 'data') < 0) { 1060 | userResponse.data = userResponse.response || userResponse.text; 1061 | } 1062 | setReadyState(4); 1063 | return; 1064 | } 1065 | process(); 1066 | }; 1067 | done.head = function(userResponse) { 1068 | mergeObjects(userResponse, response); 1069 | return setReadyState(2); 1070 | }; 1071 | done.progress = function(userResponse) { 1072 | mergeObjects(userResponse, response); 1073 | return setReadyState(3); 1074 | }; 1075 | hook = hooks.shift(); 1076 | if (hook.length === 1) { 1077 | return done(hook(request)); 1078 | } else if (hook.length === 2 && request.async) { 1079 | return hook(request, done); 1080 | } else { 1081 | return done(); 1082 | } 1083 | }; 1084 | process(); 1085 | }; 1086 | facade.abort = function() { 1087 | status = ABORTED; 1088 | if (transiting) { 1089 | xhr.abort(); 1090 | } else { 1091 | facade[FIRE]('abort', {}); 1092 | } 1093 | }; 1094 | facade.setRequestHeader = function(header, value) { 1095 | var lName, name; 1096 | lName = header != null ? header.toLowerCase() : void 0; 1097 | name = request.headerNames[lName] = request.headerNames[lName] || header; 1098 | if (request.headers[name]) { 1099 | value = request.headers[name] + ', ' + value; 1100 | } 1101 | request.headers[name] = value; 1102 | }; 1103 | facade.getResponseHeader = function(header) { 1104 | var name; 1105 | name = header != null ? header.toLowerCase() : void 0; 1106 | return response.headers[name]; 1107 | }; 1108 | facade.getAllResponseHeaders = function() { 1109 | return convertHeaders(response.headers); 1110 | }; 1111 | if (xhr.overrideMimeType) { 1112 | facade.overrideMimeType = function() { 1113 | return xhr.overrideMimeType.apply(xhr, arguments); 1114 | }; 1115 | } 1116 | if (xhr.upload) { 1117 | facade.upload = request.upload = EventEmitter(); 1118 | } 1119 | return facade; 1120 | }; 1121 | 1122 | if (typeof define === "function" && define.amd) { 1123 | define("xhook", [], function() { 1124 | return xhook; 1125 | }); 1126 | } else { 1127 | (this.exports || this).xhook = xhook; 1128 | } 1129 | 1130 | }.call(this,window)); 1131 | var CHECK_INTERVAL, COMPAT_VERSION, XD_CHECK, console, cookies, createSocket, currentOrigin, document, emitter, feature, frames, getFrame, guid, handleSocket, initMaster, initSlave, initdMaster, initdSlave, instOf, jsonEncode, location, log, logger, masters, onMessage, parseUrl, setupEmitter, slaves, slice, sockets, startPostMessage, strip, toRegExp, warn, xdomain, xhook, _i, _len, _ref; 1132 | 1133 | initdMaster = false; 1134 | 1135 | slaves = function(s) { 1136 | var origin, path; 1137 | if (!initdMaster) { 1138 | initMaster(); 1139 | } 1140 | for (origin in s) { 1141 | path = s[origin]; 1142 | log("adding slave: " + origin); 1143 | slaves[origin] = path; 1144 | } 1145 | }; 1146 | 1147 | frames = {}; 1148 | 1149 | getFrame = function(origin, proxyPath) { 1150 | var frame; 1151 | if (frames[origin]) { 1152 | return frames[origin]; 1153 | } 1154 | frame = document.createElement("iframe"); 1155 | frame.id = frame.name = guid(); 1156 | log("creating iframe " + frame.id); 1157 | frame.src = "" + origin + proxyPath; 1158 | frame.setAttribute('style', 'display:none;'); 1159 | document.body.appendChild(frame); 1160 | return frames[origin] = frame.contentWindow; 1161 | }; 1162 | 1163 | initMaster = function() { 1164 | var convertFormData, convertToArrayBuffer, handleRequest; 1165 | initdMaster = true; 1166 | convertToArrayBuffer = function(args, done) { 1167 | var isBlob, isFile, name, obj, reader; 1168 | name = args[0], obj = args[1]; 1169 | isBlob = instOf(obj, 'Blob'); 1170 | isFile = instOf(obj, 'File'); 1171 | if (!(isBlob || isFile)) { 1172 | return 0; 1173 | } 1174 | reader = new FileReader(); 1175 | reader.onload = function() { 1176 | args[1] = null; 1177 | if (isFile) { 1178 | args[2] = obj.name; 1179 | } 1180 | return done(['XD_BLOB', args, this.result, obj.type]); 1181 | }; 1182 | reader.readAsArrayBuffer(obj); 1183 | return 1; 1184 | }; 1185 | convertFormData = function(entries, send) { 1186 | var c; 1187 | entries.forEach(function(args, i) { 1188 | var file, name, value, _i, _len; 1189 | name = args[0], value = args[1]; 1190 | if (instOf(value, 'FileList')) { 1191 | entries.splice(i, 1); 1192 | for (_i = 0, _len = value.length; _i < _len; _i++) { 1193 | file = value[_i]; 1194 | entries.splice(i, 0, [name, file]); 1195 | } 1196 | } 1197 | }); 1198 | c = 0; 1199 | entries.forEach(function(args, i) { 1200 | c += convertToArrayBuffer(args, function(newargs) { 1201 | entries[i] = newargs; 1202 | if (--c === 0) { 1203 | send(); 1204 | } 1205 | }); 1206 | }); 1207 | if (c === 0) { 1208 | send(); 1209 | } 1210 | }; 1211 | handleRequest = function(request, socket) { 1212 | var entries, obj, send; 1213 | socket.on("xhr-event", function() { 1214 | return request.xhr.dispatchEvent.apply(null, arguments); 1215 | }); 1216 | socket.on("xhr-upload-event", function() { 1217 | return request.xhr.upload.dispatchEvent.apply(null, arguments); 1218 | }); 1219 | obj = strip(request); 1220 | obj.headers = request.headers; 1221 | if (request.withCredentials) { 1222 | if (cookies.master) { 1223 | obj.headers[cookies.master] = document.cookie; 1224 | } 1225 | obj.slaveCookie = cookies.slave; 1226 | } 1227 | send = function() { 1228 | return socket.emit("request", obj); 1229 | }; 1230 | if (request.body) { 1231 | obj.body = request.body; 1232 | if (instOf(obj.body, 'FormData')) { 1233 | entries = obj.body.entries; 1234 | obj.body = ["XD_FD", entries]; 1235 | convertFormData(entries, send); 1236 | return; 1237 | } 1238 | } 1239 | send(); 1240 | }; 1241 | if (!('addWithCredentials' in xhook)) { 1242 | xhook.addWithCredentials = true; 1243 | } 1244 | return xhook.before(function(request, callback) { 1245 | var frame, p, socket; 1246 | p = parseUrl(request.url); 1247 | if (!p || p.origin === currentOrigin) { 1248 | return callback(); 1249 | } 1250 | if (!slaves[p.origin]) { 1251 | if (p) { 1252 | log("no slave matching: '" + p.origin + "'"); 1253 | } 1254 | return callback(); 1255 | } 1256 | log("proxying request to slave: '" + p.origin + "'"); 1257 | if (request.async === false) { 1258 | warn("sync not supported"); 1259 | return callback(); 1260 | } 1261 | frame = getFrame(p.origin, slaves[p.origin]); 1262 | socket = createSocket(guid(), frame); 1263 | socket.on("response", function(resp) { 1264 | callback(resp); 1265 | return socket.close(); 1266 | }); 1267 | request.xhr.addEventListener('abort', function() { 1268 | return socket.emit("abort"); 1269 | }); 1270 | if (socket.ready) { 1271 | handleRequest(request, socket); 1272 | } else { 1273 | socket.once('ready', function() { 1274 | return handleRequest(request, socket); 1275 | }); 1276 | } 1277 | }); 1278 | }; 1279 | 1280 | initdSlave = false; 1281 | 1282 | masters = function(m) { 1283 | var origin, path; 1284 | if (!initdSlave) { 1285 | initSlave(); 1286 | } 1287 | for (origin in m) { 1288 | path = m[origin]; 1289 | log("adding master: " + origin); 1290 | masters[origin] = path; 1291 | } 1292 | }; 1293 | 1294 | handleSocket = null; 1295 | 1296 | initSlave = function() { 1297 | initdSlave = true; 1298 | log("handling incoming sockets..."); 1299 | handleSocket = function(origin, socket) { 1300 | var master, masterRegex, pathRegex, regex; 1301 | if (origin === "null") { 1302 | origin = "*"; 1303 | } 1304 | pathRegex = null; 1305 | for (master in masters) { 1306 | regex = masters[master]; 1307 | try { 1308 | masterRegex = toRegExp(master); 1309 | if (masterRegex.test(origin)) { 1310 | pathRegex = toRegExp(regex); 1311 | break; 1312 | } 1313 | } catch (_error) {} 1314 | } 1315 | if (!pathRegex) { 1316 | warn("blocked request from: '" + origin + "'"); 1317 | return; 1318 | } 1319 | socket.once("request", function(req) { 1320 | var args, blob, entries, fd, k, p, v, xhr, _i, _len, _ref; 1321 | log("request: " + req.method + " " + req.url); 1322 | p = parseUrl(req.url); 1323 | if (!(p && pathRegex.test(p.path))) { 1324 | warn("blocked request to path: '" + p.path + "' by regex: " + pathRegex); 1325 | socket.close(); 1326 | return; 1327 | } 1328 | xhr = new XMLHttpRequest(); 1329 | xhr.open(req.method, req.url); 1330 | xhr.addEventListener("*", function(e) { 1331 | return socket.emit('xhr-event', e.type, strip(e)); 1332 | }); 1333 | if (xhr.upload) { 1334 | xhr.upload.addEventListener("*", function(e) { 1335 | return socket.emit('xhr-upload-event', e.type, strip(e)); 1336 | }); 1337 | } 1338 | socket.once("abort", function() { 1339 | return xhr.abort(); 1340 | }); 1341 | xhr.onreadystatechange = function() { 1342 | var resp; 1343 | if (xhr.readyState !== 4) { 1344 | return; 1345 | } 1346 | resp = { 1347 | status: xhr.status, 1348 | statusText: xhr.statusText, 1349 | data: xhr.response, 1350 | headers: xhook.headers(xhr.getAllResponseHeaders()) 1351 | }; 1352 | try { 1353 | resp.text = xhr.responseText; 1354 | } catch (_error) {} 1355 | return socket.emit('response', resp); 1356 | }; 1357 | if (req.withCredentials) { 1358 | xhr.withCredentials = true; 1359 | if (req.slaveCookie) { 1360 | req.headers[req.slaveCookie] = document.cookie; 1361 | } 1362 | } 1363 | if (req.timeout) { 1364 | xhr.timeout = req.timeout; 1365 | } 1366 | if (req.type) { 1367 | xhr.responseType = req.type; 1368 | } 1369 | _ref = req.headers; 1370 | for (k in _ref) { 1371 | v = _ref[k]; 1372 | xhr.setRequestHeader(k, v); 1373 | } 1374 | if (req.body instanceof Array && req.body[0] === "XD_FD") { 1375 | fd = new xhook.FormData(); 1376 | entries = req.body[1]; 1377 | for (_i = 0, _len = entries.length; _i < _len; _i++) { 1378 | args = entries[_i]; 1379 | if (args[0] === "XD_BLOB" && args.length === 4) { 1380 | blob = new Blob([args[2]], { 1381 | type: args[3] 1382 | }); 1383 | args = args[1]; 1384 | args[1] = blob; 1385 | } 1386 | fd.append.apply(fd, args); 1387 | } 1388 | req.body = fd; 1389 | } 1390 | xhr.send(req.body || null); 1391 | }); 1392 | log("slave listening for requests on socket: " + socket.id); 1393 | }; 1394 | if (window === window.parent) { 1395 | return warn("slaves must be in an iframe"); 1396 | } else { 1397 | return window.parent.postMessage("XDPING_" + COMPAT_VERSION, '*'); 1398 | } 1399 | }; 1400 | 1401 | XD_CHECK = "XD_CHECK"; 1402 | 1403 | sockets = {}; 1404 | 1405 | jsonEncode = true; 1406 | 1407 | createSocket = function(id, frame) { 1408 | var check, checks, emit, pendingEmits, ready, sock; 1409 | ready = false; 1410 | sock = sockets[id] = xhook.EventEmitter(true); 1411 | sock.id = id; 1412 | sock.once('close', function() { 1413 | sock.destroy(); 1414 | return sock.close(); 1415 | }); 1416 | pendingEmits = []; 1417 | sock.emit = function() { 1418 | var args, extra; 1419 | args = slice(arguments); 1420 | extra = typeof args[1] === "string" ? " -> " + args[1] : ""; 1421 | log("send socket: " + id + ": " + args[0] + extra); 1422 | args.unshift(id); 1423 | if (ready) { 1424 | emit(args); 1425 | } else { 1426 | pendingEmits.push(args); 1427 | } 1428 | }; 1429 | emit = function(args) { 1430 | if (jsonEncode) { 1431 | args = JSON.stringify(args); 1432 | } 1433 | frame.postMessage(args, "*"); 1434 | }; 1435 | sock.close = function() { 1436 | sock.emit('close'); 1437 | log("close socket: " + id); 1438 | sockets[id] = null; 1439 | }; 1440 | sock.once(XD_CHECK, function(obj) { 1441 | jsonEncode = typeof obj === "string"; 1442 | ready = sock.ready = true; 1443 | sock.emit('ready'); 1444 | log("ready socket: " + id + " (emit #" + pendingEmits.length + " pending)"); 1445 | while (pendingEmits.length) { 1446 | emit(pendingEmits.shift()); 1447 | } 1448 | }); 1449 | checks = 0; 1450 | check = (function(_this) { 1451 | return function() { 1452 | frame.postMessage([id, XD_CHECK, {}], "*"); 1453 | if (ready) { 1454 | return; 1455 | } 1456 | if (checks++ >= xdomain.timeout / CHECK_INTERVAL) { 1457 | warn("Timeout waiting on iframe socket"); 1458 | emitter.fire("timeout"); 1459 | sock.fire("abort"); 1460 | } else { 1461 | setTimeout(check, CHECK_INTERVAL); 1462 | } 1463 | }; 1464 | })(this); 1465 | setTimeout(check); 1466 | log("new socket: " + id); 1467 | return sock; 1468 | }; 1469 | 1470 | onMessage = function(fn) { 1471 | if (document.addEventListener) { 1472 | return window.addEventListener("message", fn); 1473 | } else { 1474 | return window.attachEvent("onmessage", fn); 1475 | } 1476 | }; 1477 | 1478 | startPostMessage = function() { 1479 | return onMessage(function(e) { 1480 | var d, extra, id, sock; 1481 | d = e.data; 1482 | if (typeof d === "string") { 1483 | if (/^XDPING(_(V\d+))?$/.test(d) && RegExp.$2 !== COMPAT_VERSION) { 1484 | return warn("your master is not compatible with your slave, check your xdomain.js version"); 1485 | } else if (/^xdomain-/.test(d)) { 1486 | d = d.split(","); 1487 | } else if (jsonEncode) { 1488 | try { 1489 | d = JSON.parse(d); 1490 | } catch (_error) { 1491 | return; 1492 | } 1493 | } 1494 | } 1495 | if (!(d instanceof Array)) { 1496 | return; 1497 | } 1498 | id = d.shift(); 1499 | if (!/^xdomain-/.test(id)) { 1500 | return; 1501 | } 1502 | sock = sockets[id]; 1503 | if (sock === null) { 1504 | return; 1505 | } 1506 | if (sock === undefined) { 1507 | if (!handleSocket) { 1508 | return; 1509 | } 1510 | sock = createSocket(id, e.source); 1511 | handleSocket(e.origin, sock); 1512 | } 1513 | extra = typeof d[1] === "string" ? " -> " + d[1] : ""; 1514 | log("receive socket: " + id + ": " + d[0] + extra); 1515 | sock.fire.apply(sock, d); 1516 | }); 1517 | }; 1518 | 1519 | 'use strict'; 1520 | 1521 | xhook = (this.exports || this).xhook; 1522 | 1523 | xdomain = function(o) { 1524 | if (!o) { 1525 | return; 1526 | } 1527 | if (o.masters) { 1528 | masters(o.masters); 1529 | } 1530 | if (o.slaves) { 1531 | slaves(o.slaves); 1532 | } 1533 | }; 1534 | 1535 | xdomain.masters = masters; 1536 | 1537 | xdomain.slaves = slaves; 1538 | 1539 | xdomain.debug = false; 1540 | 1541 | xdomain.timeout = 15e3; 1542 | 1543 | CHECK_INTERVAL = 100; 1544 | 1545 | cookies = xdomain.cookies = { 1546 | master: "Master-Cookie", 1547 | slave: "Slave-Cookie" 1548 | }; 1549 | 1550 | document = window.document; 1551 | 1552 | location = window.location; 1553 | 1554 | currentOrigin = xdomain.origin = location.protocol + '//' + location.host; 1555 | 1556 | guid = function() { 1557 | return 'xdomain-' + Math.round(Math.random() * Math.pow(2, 32)).toString(16); 1558 | }; 1559 | 1560 | slice = function(o, n) { 1561 | return Array.prototype.slice.call(o, n); 1562 | }; 1563 | 1564 | console = window.console || {}; 1565 | 1566 | emitter = null; 1567 | 1568 | setupEmitter = function() { 1569 | emitter = xhook.EventEmitter(true); 1570 | xdomain.on = emitter.on; 1571 | xdomain.off = emitter.off; 1572 | }; 1573 | 1574 | if (xhook) { 1575 | setupEmitter(); 1576 | } 1577 | 1578 | logger = function(type) { 1579 | return function(str) { 1580 | str = "xdomain (" + currentOrigin + "): " + str; 1581 | emitter.fire(type, str); 1582 | if (type === 'log' && !xdomain.debug) { 1583 | return; 1584 | } 1585 | if (type in xdomain) { 1586 | xdomain[type](str); 1587 | } else if (type in console) { 1588 | console[type](str); 1589 | } else if (type === 'warn') { 1590 | alert(str); 1591 | } 1592 | }; 1593 | }; 1594 | 1595 | log = logger('log'); 1596 | 1597 | warn = logger('warn'); 1598 | 1599 | _ref = ['postMessage', 'JSON']; 1600 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 1601 | feature = _ref[_i]; 1602 | if (!window[feature]) { 1603 | warn("requires '" + feature + "' and this browser does not support it"); 1604 | return; 1605 | } 1606 | } 1607 | 1608 | instOf = function(obj, global) { 1609 | if (!(global in window)) { 1610 | return false; 1611 | } 1612 | return obj instanceof window[global]; 1613 | }; 1614 | 1615 | COMPAT_VERSION = "V1"; 1616 | 1617 | parseUrl = xdomain.parseUrl = function(url) { 1618 | if (/^((https?:)?\/\/[^\/\?]+)(\/.*)?/.test(url)) { 1619 | return { 1620 | origin: (RegExp.$2 ? '' : location.protocol) + RegExp.$1, 1621 | path: RegExp.$3 1622 | }; 1623 | } else { 1624 | log("failed to parse absolute url: " + url); 1625 | return null; 1626 | } 1627 | }; 1628 | 1629 | toRegExp = function(obj) { 1630 | var str; 1631 | if (obj instanceof RegExp) { 1632 | return obj; 1633 | } 1634 | str = obj.toString().replace(/\W/g, function(str) { 1635 | return "\\" + str; 1636 | }).replace(/\\\*/g, ".*"); 1637 | return new RegExp("^" + str + "$"); 1638 | }; 1639 | 1640 | strip = function(src) { 1641 | var dst, k, v, _ref1; 1642 | dst = {}; 1643 | for (k in src) { 1644 | if (k === "returnValue") { 1645 | continue; 1646 | } 1647 | v = src[k]; 1648 | if ((_ref1 = typeof v) !== "function" && _ref1 !== "object") { 1649 | dst[k] = v; 1650 | } 1651 | } 1652 | return dst; 1653 | }; 1654 | 1655 | (function() { 1656 | var attrs, fn, k, prefix, script, _j, _k, _len1, _len2, _ref1, _ref2; 1657 | attrs = { 1658 | debug: function(value) { 1659 | if (typeof value !== "string") { 1660 | return; 1661 | } 1662 | return xdomain.debug = value !== "false"; 1663 | }, 1664 | slave: function(value) { 1665 | var p, s; 1666 | if (!value) { 1667 | return; 1668 | } 1669 | p = parseUrl(value); 1670 | if (!p) { 1671 | return; 1672 | } 1673 | s = {}; 1674 | s[p.origin] = p.path; 1675 | return slaves(s); 1676 | }, 1677 | master: function(value) { 1678 | var m, p; 1679 | if (!value) { 1680 | return; 1681 | } 1682 | if (value === "*") { 1683 | p = { 1684 | origin: "*", 1685 | path: "*" 1686 | }; 1687 | } else { 1688 | p = parseUrl(value); 1689 | } 1690 | if (!p) { 1691 | return; 1692 | } 1693 | m = {}; 1694 | m[p.origin] = p.path.replace(/^\//, "") ? p.path : "*"; 1695 | return masters(m); 1696 | } 1697 | }; 1698 | _ref1 = document.getElementsByTagName("script"); 1699 | for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 1700 | script = _ref1[_j]; 1701 | if (/xdomain/.test(script.src)) { 1702 | _ref2 = ['', 'data-']; 1703 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 1704 | prefix = _ref2[_k]; 1705 | for (k in attrs) { 1706 | fn = attrs[k]; 1707 | fn(script.getAttribute(prefix + k)); 1708 | } 1709 | } 1710 | } 1711 | } 1712 | })(); 1713 | 1714 | startPostMessage(); 1715 | 1716 | if (typeof define === "function" && define.amd) { 1717 | define("xdomain", ["xhook"], function(xh) { 1718 | xhook = xh; 1719 | setupEmitter(); 1720 | return xdomain; 1721 | }); 1722 | } else { 1723 | (this.exports || this).xdomain = xdomain; 1724 | } 1725 | 1726 | }.call(this,window)); -------------------------------------------------------------------------------- /vendor/metisMenu/metisMenu.min.css: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v1.1.3 3 | * Easy menu jQuery plugin for Twitter Bootstrap 3 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumus 7 | * Under MIT License 8 | */ 9 | 10 | .arrow{float:right;line-height:1.42857}.glyphicon.arrow:before{content:"\e079"}.active>a>.glyphicon.arrow:before{content:"\e114"}.fa.arrow:before{content:"\f104"}.active>a>.fa.arrow:before{content:"\f107"}.plus-times{float:right}.fa.plus-times:before{content:"\f067"}.active>a>.fa.plus-times{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.plus-minus{float:right}.fa.plus-minus:before{content:"\f067"}.active>a>.fa.plus-minus:before{content:"\f068"} -------------------------------------------------------------------------------- /vendor/metisMenu/metisMenu.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v1.1.3 3 | * Easy menu jQuery plugin for Twitter Bootstrap 3 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumus 7 | * Under MIT License 8 | */ 9 | !function(a,b,c){function d(b,c){this.element=a(b),this.settings=a.extend({},f,c),this._defaults=f,this._name=e,this.init()}var e="metisMenu",f={toggle:!0,doubleTapToGo:!1};d.prototype={init:function(){var b=this.element,d=this.settings.toggle,f=this;this.isIE()<=9?(b.find("li.active").has("ul").children("ul").collapse("show"),b.find("li").not(".active").has("ul").children("ul").collapse("hide")):(b.find("li.active").has("ul").children("ul").addClass("collapse in"),b.find("li").not(".active").has("ul").children("ul").addClass("collapse")),f.settings.doubleTapToGo&&b.find("li.active").has("ul").children("a").addClass("doubleTapToGo"),b.find("li").has("ul").children("a").on("click."+e,function(b){return b.preventDefault(),f.settings.doubleTapToGo&&f.doubleTapToGo(a(this))&&"#"!==a(this).attr("href")&&""!==a(this).attr("href")?(b.stopPropagation(),void(c.location=a(this).attr("href"))):(a(this).parent("li").toggleClass("active").children("ul").collapse("toggle"),void(d&&a(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide")))})},isIE:function(){for(var a,b=3,d=c.createElement("div"),e=d.getElementsByTagName("i");d.innerHTML="",e[0];)return b>4?b:a},doubleTapToGo:function(a){var b=this.element;return a.hasClass("doubleTapToGo")?(a.removeClass("doubleTapToGo"),!0):a.parent().children("ul").length?(b.find(".doubleTapToGo").removeClass("doubleTapToGo"),a.addClass("doubleTapToGo"),!1):void 0},remove:function(){this.element.off("."+e),this.element.removeData(e)}},a.fn[e]=function(b){return this.each(function(){var c=a(this);c.data(e)&&c.data(e).remove(),c.data(e,new d(this,b))}),this}}(jQuery,window,document); -------------------------------------------------------------------------------- /vendor/promise.min.js: -------------------------------------------------------------------------------- 1 | /*! Native Promise Only 2 | v0.8.0-a (c) Kyle Simpson 3 | MIT License: http://getify.mit-license.org 4 | */ 5 | !function(a,b,c){b[a]=b[a]||c(),"undefined"!=typeof module&&module.exports?module.exports=b[a]:"function"==typeof define&&define.amd&&define(function(){return b[a]})}("Promise","undefined"!=typeof global?global:this,function(){"use strict";function g(a,d){c.add(a,d),b||(b=e(c.drain))}function h(a){var b,c=typeof a;return null==a||"object"!=c&&"function"!=c||(b=a.then),"function"==typeof b?b:!1}function i(){for(var a=0;a0&&g(i,c))}catch(d){l.call(new n(c),d)}}}function l(a){var b=this;b.triggered||(b.triggered=!0,b.def&&(b=b.def),b.msg=a,b.state=2,b.chain.length>0&&g(i,b))}function m(a,b,c,d){for(var e=0;e { 7 | configEntry[page] = path.resolve(dirVars.pagesDir, page + '/page'); 8 | }); 9 | 10 | module.exports = configEntry; 11 | -------------------------------------------------------------------------------- /webpack-config/externals.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | jquery: 'window.jQuery', 3 | }; 4 | -------------------------------------------------------------------------------- /webpack-config/inherit/module.config.js: -------------------------------------------------------------------------------- 1 | var dirVars = require('../base/dir-vars.config.js'); 2 | var eslintFormatter = require('eslint-friendly-formatter'); 3 | module.exports = { 4 | rules: [ 5 | { 6 | test: /\.js$/, 7 | enforce: 'pre', 8 | loader: 'eslint-loader', 9 | include: dirVars.srcRootDir, 10 | exclude: /bootstrap/, 11 | options: { 12 | formatter: eslintFormatter, 13 | fix: true, 14 | }, 15 | }, 16 | { 17 | test: /\.js$/, 18 | include: dirVars.srcRootDir, 19 | loader: 'babel-loader', 20 | options: { 21 | presets: [['es2015', { loose: true }]], 22 | cacheDirectory: true, 23 | plugins: ['transform-runtime'], 24 | }, 25 | }, 26 | { 27 | test: /\.html$/, 28 | include: dirVars.srcRootDir, 29 | loader: 'html-loader', 30 | }, 31 | { 32 | test: /\.ejs$/, 33 | include: dirVars.srcRootDir, 34 | loader: 'ejs-loader', 35 | }, 36 | { 37 | // 图片加载器,雷同file-loader,更适合图片,可以将较小的图片转成base64,减少http请求 38 | // 如下配置,将小于8192byte的图片转成base64码 39 | test: /\.(png|jpg|gif)$/, 40 | include: dirVars.srcRootDir, 41 | // loader: 'url-loader?limit=8192&name=./static/img/[hash].[ext]', 42 | loader: 'url-loader', 43 | options: { 44 | limit: 8192, 45 | name: './static/img/[hash].[ext]', 46 | }, 47 | }, 48 | { 49 | // 专供bootstrap方案使用的,忽略bootstrap自带的字体文件 50 | test: /\.(woff|woff2|svg|eot|ttf)$/, 51 | include: /glyphicons/, 52 | loader: 'null-loader', 53 | }, 54 | { 55 | // 专供iconfont方案使用的,后面会带一串时间戳,需要特别匹配到 56 | test: /\.(woff|woff2|svg|eot|ttf)\??.*$/, 57 | include: dirVars.srcRootDir, 58 | // exclude: /glyphicons/, 59 | // loader: 'file-loader?name=static/fonts/[name].[ext]', 60 | loader: 'file-loader', 61 | options: { 62 | name: 'static/fonts/[name].[hash].[ext]', 63 | }, 64 | }, 65 | 66 | ], 67 | }; 68 | -------------------------------------------------------------------------------- /webpack-config/inherit/plugins.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | var path = require('path'); 5 | var dirVars = require('../base/dir-vars.config.js'); 6 | var pageArr = require('../base/page-entries.config.js'); 7 | 8 | var HashOutput = require('webpack-plugin-hash-output'); 9 | 10 | var configPlugins = [ 11 | 12 | /* 全局shimming */ 13 | new webpack.ProvidePlugin({ 14 | $: 'jquery', 15 | jQuery: 'jquery', 16 | 'window.jQuery': 'jquery', 17 | 'window.$': 'jquery', 18 | Vue: 'vue', 19 | vue: 'vue', 20 | }), 21 | /* 抽取出所有通用的部分 */ 22 | new webpack.optimize.CommonsChunkPlugin({ 23 | name: 'commons/commons', // 需要注意的是,chunk的name不能相同!!! 24 | filename: '[name]/bundle.[chunkhash].js', 25 | minChunks: 4, 26 | }), 27 | /* 抽取出webpack的runtime代码(),避免稍微修改一下入口文件就会改动commonChunk,导致原本有效的浏览器缓存失效 */ 28 | new webpack.optimize.CommonsChunkPlugin({ 29 | name: 'webpack-runtime', 30 | filename: 'commons/commons/webpack-runtime.[hash].js', 31 | }), 32 | /* 抽取出chunk的css */ 33 | new ExtractTextPlugin('[name]/styles.[contenthash].css'), 34 | /* 配置好Dll */ 35 | // new webpack.DllReferencePlugin({ 36 | // context: dirVars.staticRootDir, // 指定一个路径作为上下文环境,需要与DllPlugin的context参数保持一致,建议统一设置为项目根目录 37 | // manifest: require('../../manifest.json'), // 指定manifest.json 38 | // name: 'dll', // 当前Dll的所有内容都会存放在这个参数指定变量名的一个全局变量下,注意与DllPlugin的name参数保持一致 39 | // }), 40 | new HashOutput({ 41 | manifestFiles: 'webpack-runtime', // 指定包含 manifest 在内的 chunk 42 | }), 43 | ]; 44 | 45 | pageArr.forEach((page) => { 46 | const htmlPlugin = new HtmlWebpackPlugin({ 47 | filename: `${page}/page.html`, 48 | template: path.resolve(dirVars.pagesDir, `./${page}/html.js`), 49 | chunks: ['webpack-runtime', page, 'commons/commons'], 50 | hash: true, // 为静态资源生成hash值 51 | xhtml: true, 52 | }); 53 | configPlugins.push(htmlPlugin); 54 | }); 55 | 56 | module.exports = configPlugins; 57 | -------------------------------------------------------------------------------- /webpack-config/module.dev.config.js: -------------------------------------------------------------------------------- 1 | var dirVars = require('./base/dir-vars.config.js'); 2 | 3 | const moduleConfig = require('./inherit/module.config.js'); 4 | 5 | /* 6 | 由于ExtractTextPlugin不支持热更新,因此选择在开发环境下直接用style-loader加载样式。 7 | 如有问题,可切换回ExtractTextPlugin,即使不能用热更新,也可实现LiveReload 8 | */ 9 | moduleConfig.rules.push({ 10 | test: /\.css$/, 11 | exclude: /node_modules|bootstrap/, 12 | // loader: 'style!css?minimize&-autoprefixer!postcss', 13 | use: [ 14 | { 15 | loader: 'style-loader', 16 | }, 17 | { 18 | loader: 'css-loader', 19 | // options: { 20 | // minimize: true, 21 | // '-autoprefixer': true, 22 | // }, 23 | }, 24 | // { 25 | // loader: 'postcss-loader', 26 | // }, 27 | ], 28 | }); 29 | 30 | moduleConfig.rules.push({ 31 | test: /\.css$/, 32 | include: /bootstrap/, 33 | // loader: 'style!css', 34 | use: [ 35 | 'style-loader', 'css-loader', 36 | ], 37 | }); 38 | 39 | moduleConfig.rules.push({ 40 | test: /\.less$/, 41 | include: dirVars.srcRootDir, 42 | // loader: 'style!css?minimize&-autoprefixer!postcss!less', 43 | use: [ 44 | { 45 | loader: 'style-loader', 46 | }, 47 | { 48 | loader: 'css-loader', 49 | // options: { 50 | // minimize: true, 51 | // '-autoprefixer': true, 52 | // }, 53 | }, 54 | // { 55 | // loader: 'postcss-loader', 56 | // }, 57 | { 58 | loader: 'less-loader', 59 | }, 60 | ], 61 | }); 62 | 63 | module.exports = moduleConfig; 64 | -------------------------------------------------------------------------------- /webpack-config/module.product.config.js: -------------------------------------------------------------------------------- 1 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 2 | var dirVars = require('./base/dir-vars.config.js'); 3 | 4 | const moduleConfig = require('./inherit/module.config.js'); 5 | 6 | moduleConfig.rules.push({ 7 | test: /\.css$/, 8 | exclude: /node_modules|bootstrap/, 9 | // loader: ExtractTextPlugin.extract('css?minimize&-autoprefixer!postcss'), 10 | use: ExtractTextPlugin.extract([ 11 | { 12 | loader: 'css-loader', 13 | options: { 14 | minimize: true, 15 | '-autoprefixer': true, 16 | }, 17 | }, 18 | { 19 | loader: 'postcss-loader', 20 | }, 21 | ]), 22 | }); 23 | 24 | moduleConfig.rules.push({ 25 | test: /\.css$/, 26 | include: /bootstrap/, 27 | use: ExtractTextPlugin.extract([ 28 | { 29 | loader: 'css-loader', 30 | }, 31 | ]), 32 | }); 33 | 34 | moduleConfig.rules.push({ 35 | test: /\.less$/, 36 | include: dirVars.srcRootDir, 37 | use: ExtractTextPlugin.extract([ 38 | { 39 | loader: 'css-loader', 40 | options: { 41 | minimize: true, 42 | '-autoprefixer': true, 43 | }, 44 | }, 45 | { 46 | loader: 'postcss-loader', 47 | }, 48 | { 49 | loader: 'less-loader', 50 | }, 51 | ]), 52 | }); 53 | 54 | module.exports = moduleConfig; 55 | -------------------------------------------------------------------------------- /webpack-config/output.config.js: -------------------------------------------------------------------------------- 1 | var dirVars = require('./base/dir-vars.config.js'); 2 | module.exports = { 3 | path: dirVars.buildDir, 4 | publicPath: '/', 5 | filename: '[name]/entry.[chunkhash].js', // [name]表示entry每一项中的key,用以批量指定生成后文件的名称 6 | chunkFilename: '[id].[chunkhash].bundle.js', 7 | }; 8 | -------------------------------------------------------------------------------- /webpack-config/plugins.dev.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var pluginsConfig = require('./inherit/plugins.config.js'); 3 | 4 | pluginsConfig.push(new webpack.DefinePlugin({ 5 | IS_PRODUCTION: false, 6 | })); 7 | 8 | pluginsConfig.push(new webpack.LoaderOptionsPlugin({ 9 | options: { 10 | postcss: require('./vendor/postcss.config.js'), 11 | eslint: require('./vendor/eslint.config.js'), 12 | }, 13 | })); 14 | 15 | module.exports = pluginsConfig; 16 | -------------------------------------------------------------------------------- /webpack-config/plugins.product.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var pluginsConfig = require('./inherit/plugins.config.js'); 3 | 4 | /* webpack1下,用了压缩插件会导致所有loader添加min配置,而autoprefixser也被定格到某个browers配置 */ 5 | pluginsConfig.push(new webpack.optimize.UglifyJsPlugin({ 6 | ie8: true, 7 | compress: { 8 | warnings: false, 9 | }, 10 | mangle: { 11 | safari10: true, 12 | }, 13 | })); 14 | 15 | pluginsConfig.push(new webpack.DefinePlugin({ 16 | IS_PRODUCTION: true, 17 | })); 18 | 19 | pluginsConfig.push(new webpack.NoEmitOnErrorsPlugin()); // 配合CLI的--bail,一出error就终止webpack的编译进程 20 | 21 | pluginsConfig.push(new webpack.LoaderOptionsPlugin({ 22 | options: { 23 | postcss: require('./vendor/postcss.config.js'), 24 | eslint: require('./vendor/eslint.config.js'), 25 | }, 26 | })); 27 | 28 | /* HashedModuleIdsPlugin 这个插件,他是根据模块的相对路径生成一个长度只有四位的字符串作为模块的 module id , 29 | 这样就算引入了新的模块,也不会影响 module id 的值,只要模块的路径不改变的话。 */ 30 | pluginsConfig.push(new webpack.HashedModuleIdsPlugin()); 31 | 32 | module.exports = pluginsConfig; 33 | -------------------------------------------------------------------------------- /webpack-config/resolve.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var dirVars = require('./base/dir-vars.config.js'); 3 | module.exports = { 4 | // 模块别名的配置,为了使用方便,一般来说所有模块都是要配置一下别名的 5 | alias: { 6 | /* 各种目录 */ 7 | iconfontDir: path.resolve(dirVars.publicDir, 'iconfont/'), 8 | configDir: dirVars.configDir, 9 | vendorDir: dirVars.vendorDir, 10 | 11 | /* vendor */ 12 | /* bootstrap 相关 */ 13 | metisMenu: path.resolve(dirVars.vendorDir, 'metisMenu/'), 14 | 15 | /* libs */ 16 | withoutJqueryModule: path.resolve(dirVars.libsDir, 'without-jquery.module'), 17 | routerModule: path.resolve(dirVars.libsDir, 'router.module'), 18 | 19 | libs: path.resolve(dirVars.libsDir, 'libs.module'), 20 | 21 | /* less */ 22 | lessDir: path.resolve(dirVars.publicDir, 'less'), 23 | 24 | /* components */ 25 | 26 | /* layout */ 27 | layout: path.resolve(dirVars.layoutDir, 'layout/html'), 28 | 'layout-without-nav': path.resolve(dirVars.layoutDir, 'layout-without-nav/html'), 29 | 30 | /* logic */ 31 | cm: path.resolve(dirVars.logicDir, 'common.module'), 32 | cp: path.resolve(dirVars.logicDir, 'common.page'), 33 | 34 | /* config */ 35 | configModule: path.resolve(dirVars.configDir, 'common.config'), 36 | }, 37 | 38 | // 当require的模块找不到时,尝试添加这些后缀后进行寻找 39 | extensions: ['.js', '.css', '.less'], 40 | }; 41 | -------------------------------------------------------------------------------- /webpack-config/vendor/eslint.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var dirVars = require('../base/dir-vars.config.js'); 3 | module.exports = { 4 | configFile: path.resolve(dirVars.staticRootDir, './.eslintrc.js'), 5 | failOnWarning: true, 6 | failOnError: true, 7 | cache: true, 8 | }; 9 | -------------------------------------------------------------------------------- /webpack-config/vendor/postcss.config.js: -------------------------------------------------------------------------------- 1 | var precss = require('precss'); 2 | var autoprefixer = require('autoprefixer'); 3 | module.exports = function postcss() { 4 | return [precss, autoprefixer({ 5 | remove: false, 6 | browsers: ['ie >= 8', '> 1% in CN'], 7 | })]; 8 | }; 9 | -------------------------------------------------------------------------------- /webpack-dll.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 3 | const dirVars = require('./webpack-config/base/dir-vars.config.js'); // 与业务代码共用同一份路径的配置表 4 | 5 | module.exports = { 6 | output: { 7 | path: dirVars.dllDir, 8 | filename: '[name].js', 9 | library: '[name]', // 当前Dll的所有内容都会存放在这个参数指定变量名的一个全局变量下,注意与DllPlugin的name参数保持一致 10 | }, 11 | entry: { 12 | /* 13 | 指定需要打包的js模块 14 | 或是css/less/图片/字体文件等资源,但注意要在module参数配置好相应的loader 15 | */ 16 | dll: [ 17 | 'jquery', 18 | 'bootstrap/dist/css/bootstrap.min.css', 'bootstrap/dist/js/bootstrap.min.js', 19 | 'metisMenu/metisMenu.min', 'metisMenu/metisMenu.min.css', 20 | ], 21 | }, 22 | plugins: [ 23 | new webpack.DllPlugin({ 24 | path: 'manifest.json', // 本Dll文件中各模块的索引,供DllReferencePlugin读取使用 25 | name: '[name]', // 当前Dll的所有内容都会存放在这个参数指定变量名的一个全局变量下,注意与参数output.library保持一致 26 | context: dirVars.staticRootDir, // 指定一个路径作为上下文环境,需要与DllReferencePlugin的context参数保持一致,建议统一设置为项目根目录 27 | }), 28 | /* 跟业务代码一样,该兼容的还是得兼容 */ 29 | new webpack.ProvidePlugin({ 30 | $: 'jquery', 31 | jQuery: 'jquery', 32 | 'window.jQuery': 'jquery', 33 | 'window.$': 'jquery', 34 | }), 35 | new ExtractTextPlugin('[name].css'), // 打包css/less的时候会用到ExtractTextPlugin 36 | new webpack.optimize.UglifyJsPlugin({ 37 | compress: { 38 | warnings: false, 39 | }, 40 | }), 41 | new webpack.LoaderOptionsPlugin({ 42 | options: { 43 | postcss: require('./webpack-config/vendor/postcss.config.js'), 44 | }, 45 | }), 46 | ], 47 | module: require('./webpack-config/module.product.config.js'), // 沿用业务代码的module配置 48 | resolve: require('./webpack-config/resolve.config.js'), // 沿用业务代码的resolve配置 49 | }; 50 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | require('./npm-scripts/before-build.script'); 2 | 3 | module.exports = { 4 | entry: require('./webpack-config/entry.config.js'), 5 | 6 | output: require('./webpack-config/output.config.js'), 7 | 8 | module: require('./webpack-config/module.product.config.js'), 9 | 10 | resolve: require('./webpack-config/resolve.config.js'), 11 | 12 | plugins: require('./webpack-config/plugins.product.config.js'), 13 | 14 | externals: require('./webpack-config/externals.config.js'), 15 | }; 16 | -------------------------------------------------------------------------------- /webpack.dev.config.js: -------------------------------------------------------------------------------- 1 | require('./npm-scripts/before-build.script'); 2 | 3 | module.exports = { 4 | entry: require('./webpack-config/entry.config.js'), 5 | 6 | output: require('./webpack-config/output.config.js'), 7 | 8 | module: require('./webpack-config/module.dev.config.js'), 9 | 10 | resolve: require('./webpack-config/resolve.config.js'), 11 | 12 | plugins: require('./webpack-config/plugins.dev.config.js'), 13 | 14 | externals: require('./webpack-config/externals.config.js'), 15 | 16 | devServer: require('./webpack-config/devServer.config.js'), 17 | }; 18 | --------------------------------------------------------------------------------