Showing preview only (790K chars total). Download the full file or copy to clipboard to get everything.
Repository: unbug/generator-webappstarter
Branch: master
Commit: 2b588e2d6bbb
Files: 149
Total size: 738.3 KB
Directory structure:
gitextract_xg95i7qs/
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .jshintrc
├── .travis.yml
├── .yo-rc.json
├── LICENSE
├── README.md
├── app/
│ ├── index.js
│ └── templates/
│ ├── _package.json
│ ├── app/
│ │ ├── .babelrc
│ │ ├── README.md
│ │ ├── data/
│ │ │ └── user.json
│ │ ├── gulpfile.js
│ │ ├── html/
│ │ │ ├── debug/
│ │ │ │ ├── analytics.html
│ │ │ │ └── index.html
│ │ │ ├── include/
│ │ │ │ ├── cache.manifest
│ │ │ │ ├── components.html
│ │ │ │ ├── download.html
│ │ │ │ ├── footer.html
│ │ │ │ ├── htmlhead.html
│ │ │ │ ├── manifest-version.html
│ │ │ │ ├── msgbox-deja.html
│ │ │ │ ├── msgbox.html
│ │ │ │ ├── scripts-version.html
│ │ │ │ ├── styles-version.html
│ │ │ │ ├── tooltip.html
│ │ │ │ ├── view-home.html
│ │ │ │ ├── view-user.html
│ │ │ │ └── views.html
│ │ │ └── official/
│ │ │ ├── analytics.html
│ │ │ └── index.html
│ │ ├── scss/
│ │ │ ├── _animate.scss
│ │ │ ├── _box.scss
│ │ │ ├── _button.scss
│ │ │ ├── _common.scss
│ │ │ ├── _components.scss
│ │ │ ├── _fonts.scss
│ │ │ ├── _footer.scss
│ │ │ ├── _header.scss
│ │ │ ├── _icon.scss
│ │ │ ├── _list.scss
│ │ │ ├── _loading-spinner.scss
│ │ │ ├── _mixin.scss
│ │ │ ├── _msgbox-android.scss
│ │ │ ├── _msgbox-deja.scss
│ │ │ ├── _msgbox.scss
│ │ │ ├── _section-download.scss
│ │ │ ├── _slide.scss
│ │ │ ├── _sprites.scss
│ │ │ ├── _tooltip.scss
│ │ │ ├── _util.scss
│ │ │ ├── _value.scss
│ │ │ ├── _view-home.scss
│ │ │ ├── _view-user.scss
│ │ │ ├── _view.scss
│ │ │ └── styles.scss
│ │ ├── src/
│ │ │ ├── app/
│ │ │ │ ├── App.js
│ │ │ │ ├── controller/
│ │ │ │ │ ├── Controller.js
│ │ │ │ │ ├── HomeController.js
│ │ │ │ │ └── UserController.js
│ │ │ │ ├── model/
│ │ │ │ │ ├── Model.js
│ │ │ │ │ ├── RequestHelper.js
│ │ │ │ │ ├── StoreHelper.js
│ │ │ │ │ └── UserModel.js
│ │ │ │ ├── resources/
│ │ │ │ │ ├── Actions.js
│ │ │ │ │ ├── Audios.js
│ │ │ │ │ └── i18n/
│ │ │ │ │ ├── en_US/
│ │ │ │ │ │ ├── Msgbox.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── zh_CN/
│ │ │ │ │ ├── Msgbox.js
│ │ │ │ │ └── index.js
│ │ │ │ └── view/
│ │ │ │ ├── HomeView.js
│ │ │ │ ├── UserView.js
│ │ │ │ └── View.js
│ │ │ ├── core/
│ │ │ │ ├── Class.js
│ │ │ │ ├── Event.js
│ │ │ │ ├── HashHandler.js
│ │ │ │ ├── MicroTmpl.js
│ │ │ │ ├── NativeBridge.js
│ │ │ │ ├── Navigator.js
│ │ │ │ ├── Pubsub.js
│ │ │ │ ├── Router.js
│ │ │ │ └── Subject.js
│ │ │ ├── lib/
│ │ │ │ ├── Core.js
│ │ │ │ ├── Core.standalone.js
│ │ │ │ ├── diffDOM.js
│ │ │ │ ├── hammer.js
│ │ │ │ ├── impress.js
│ │ │ │ ├── rebound.js
│ │ │ │ ├── swing/
│ │ │ │ │ ├── card.js
│ │ │ │ │ ├── dom.js
│ │ │ │ │ ├── sister.js
│ │ │ │ │ ├── stack.js
│ │ │ │ │ ├── swing.js
│ │ │ │ │ └── vendor-prefix.js
│ │ │ │ ├── velocity.js
│ │ │ │ ├── velocityui.js
│ │ │ │ ├── zepto.js
│ │ │ │ └── zepto.waypoints.js
│ │ │ ├── util/
│ │ │ │ ├── AppCache.js
│ │ │ │ ├── Base64.js
│ │ │ │ ├── DateHandler.js
│ │ │ │ ├── Easing.js
│ │ │ │ ├── FacebookShare.js
│ │ │ │ ├── FormHandler.js
│ │ │ │ ├── GUID.js
│ │ │ │ ├── ImpressGenerator.js
│ │ │ │ ├── LocalHost.js
│ │ │ │ ├── LocalParam.js
│ │ │ │ ├── LocalStorage.js
│ │ │ │ ├── MetaHandler.js
│ │ │ │ ├── Number.js
│ │ │ │ ├── OpenAppInBrowser.js
│ │ │ │ ├── RandomColor.js
│ │ │ │ ├── RandomList.js
│ │ │ │ ├── RequestAnimationFrame.js
│ │ │ │ ├── RequestHandler.js
│ │ │ │ ├── Scratch.js
│ │ │ │ ├── SeededRandom.js
│ │ │ │ ├── Shake.js
│ │ │ │ ├── SimpleSlider.js
│ │ │ │ ├── Slider.js
│ │ │ │ ├── SlotMachine.js
│ │ │ │ ├── TabStatus.js
│ │ │ │ ├── ThirdVendor.js
│ │ │ │ ├── Unveil.js
│ │ │ │ ├── VersionCompare.js
│ │ │ │ ├── VirtualDOMLite.js
│ │ │ │ ├── WaypointsHandler.js
│ │ │ │ ├── WechatShare.js
│ │ │ │ └── YiXinShare.js
│ │ │ └── widget/
│ │ │ ├── Msgbox.js
│ │ │ └── Tooltip.js
│ │ └── webpack.config.js
│ ├── editorconfig
│ ├── ftppass
│ ├── gitignore
│ └── jshintrc
├── model/
│ ├── index.js
│ └── templates/
│ └── Model.js
├── module/
│ ├── index.js
│ └── templates/
│ ├── ModuleController.js
│ ├── ModuleView.js
│ ├── module.html
│ └── module.scss
├── package.json
├── test/
│ └── test-app.js
└── update/
└── index.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
================================================
FILE: .gitattributes
================================================
* text=auto
================================================
FILE: .gitignore
================================================
.DS_Store
Thumbs.db
.sass-cache
.idea
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
npm-debug.log
node_modules
dist
================================================
FILE: .jshintrc
================================================
{
"node": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"undef": true,
"unused": true,
"strict": true
}
================================================
FILE: .travis.yml
================================================
sudo: false
language: node_js
node_js:
- 'iojs'
- '0.12'
- '0.10'
================================================
FILE: .yo-rc.json
================================================
{
"generator-generator": {}
}
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015 unbug
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
[](https://nodei.co/npm/generator-webappstarter/)
>Note: This generator is supporting a very early stage app,things gonna change very frequently,so please do not fork it or do any pull request.
Readme
=================
webappstarter generator will give you a Simple Mobile Web App Boilerplate and Structure!
>The App will automatically adjusts according to a device’s screen size without any extra work.
Install
========
```shell
npm install -g generator-webappstarter
```
Prereqs and installation requirements
=====================================
1.install [node](https://nodejs.org/) and [Python](https://www.python.org/).
2.install [yeoman](http://yeoman.io/).
```shell
npm install -g yo
```
3.[optional]Clone this git repo to your local,and from the root of the repo,run
```shell
npm link
```
to developing the generator locally.
Generator commands
==================
1.generate a new project,run
```shell
mkdir myProject
cd myProject
yo webappstarter
```
or run with `--skip-install` option to skip install dependencies
```shell
mkdir myProject
cd myProject
yo webappstarter --skip-install
```
install dependencies manually with `npm install` or just copy `node_modules` folder from another project which was generated by webappstarter.
2.generate a new module,run
```shell
//this command will do:
//add "html/include/view-modulename.html" and inlude it to "html/include/views.html"
//add "scss/_view-modulename.scss" and import it to "scss/_view.scss"
//add "src/app/view/ModuleNameView.js"
//add "src/app/controller/ModuleNameController.js" and require it in src/app/App.js
yo webappstarter:module ModuleName
```
3.generate a new model,run
```shell
//this command will do:
//add "src/app/model/ModelNameModel.js"
yo webappstarter:model ModelName
```
4.update your project's boilerplate and structure
```shell
//this command will update
//"./src/core" directory
//"./src/lib" directory
//"./src/util" directory
//"./src/widget" directory
//some files in "./src/app/" directory
//some files in "./scss/" directory
//some files in "./html/" directory
yo webappstarter:update
```
> Warning: When you are asked before an overwrite can occur,please be careful.Default "Y" is overwrite,"n" is skip.
More configurations,please take a look at "project" property of "package.json" file after the generator is done.
Run ```gulp``` to re-build project is required after change the "package.json" file.
Project commands
=================
run this command before you get started.
```shell
npm install -g gulp
```
1.build project,watch change and start browserSync,run
```shell
gulp
```
or run with forever
```shell
forever ./node_modules/.bin/gulp
```
2.deploy to test server,run
```shell
gulp deploytest
```
Please update your ftp auth name and password in ".ftppass".
View the page on test server [http://office.mozat.com:8083/PROJECTNAME/](http://office.mozat.com:8083/PROJECTNAME/).
This command require [openssl](https://www.openssl.org/).
For windows,you might needd to add openssl path to classpath.
3.deploy to offical server,run
```shell
gulp deploy
```
View the page on offical server [http://m.deja.me/PROJECTNAME/](http://m.deja.me/PROJECTNAME/).
This command require [rsync](https://rsync.samba.org/).
For windows,unzip /tools/rsync.zip to a local path and add the path to classpath.
4.run this command to copy source images to project's `resources/images/` path,then generate `scss/_sprites.csss` and `resources/images/sprites.png` for sourceSprites in `package.json`.
```shell
gulp copy
```
5.run this command to start jshint.
```shell
gulp jshint
```
6.run this command to start browserSync,Change browserSync options in `package.json`.
```shell
gulp serve
```
7.run this command to start pagespeed,Change pagespeed options in `package.json`.
```shell
gulp pagespeed
```
Structure
================
The structure is modular design,follow the DOOR-KEY rule you only take minutes to understand it:
* The DOOR for javascript is in ```/src/app/App.js```,and the KEY is ```require```,see [webpack](https://webpack.github.io/docs/commonjs.html) and [commonjs](http://www.commonjs.org/specs/modules/1.0/)
* The DOOR for stylesheets is in ```/scss/styles.scss```,and the KEY is ```@import```,see [SASS](http://sass-lang.com/)
* The DOOR for HTML is in ```/html/debug/index.html```,and the KEY is ```@@include```,see [gulp-file-include](https://www.npmjs.com/package/gulp-file-include)
Git
==========
Random git commit message
```shell
git commit -m"`curl -s http://whatthecommit.com/index.txt`"
```
================================================
FILE: app/index.js
================================================
'use strict';
var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');
module.exports = yeoman.generators.Base.extend({
constructor: function () {
yeoman.generators.Base.apply(this, arguments);
this.option('skip-install', {
desc: 'Whether dependencies should be installed',
defaults: false
});
},
askFor: function () {
var done = this.async();
// Have Yeoman greet the user.
this.log(yosay('I will give you a Simple Mobile Web App Boilerplate and Structure!'));
var prompts = [{
type: 'input',
name: 'name',
message: 'Give your project a name:(products|account|config|favorite|creation|feed|feedback|dilog|invite|vote|event|share|monitor|follow,are invalid names).',
default: this.appname // Default to current folder name
}];
this.prompt(prompts, function (answers) {
this.projectName = answers.name;
// Save user configuration options to .yo-rc.json file
this.config.set({
projectName: this.projectName
});
this.config.save();
done();
}.bind(this));
},
writing: {
app: function () {
this.template('_package.json', 'package.json');
this.directory('app', './');
},
projectfiles: function () {
this.fs.copy(
this.templatePath('ftppass'),
this.destinationPath('.ftppass')
);
this.fs.copy(
this.templatePath('gitignore'),
this.destinationPath('.gitignore')
);
this.fs.copy(
this.templatePath('editorconfig'),
this.destinationPath('.editorconfig')
);
this.fs.copy(
this.templatePath('jshintrc'),
this.destinationPath('.jshintrc')
);
}
},
install: function () {
this.installDependencies({
bower: false,
npm: true,
skipInstall: this.options['skip-install'],
callback: function () {
console.log('Everything is ready!');
}
});
}
});
================================================
FILE: app/templates/_package.json
================================================
{
"name": "<%=projectName%>",
"version": "0.0.1",
"description": "Hello <%=projectName%>",
"project": {
"invalidNames": "products|account|config|favorite|creation|feed|feedback|dilog|invite|vote|event|share|monitor|follow",
"title": "Title - <%=projectName%>",
"viewport": 750,
"manifest": false,
"sourceImg": "statics/UI/build/img/**/*.{png,jpg}",
"sourceSprites": "statics/UI/build/assets/*.png",
"watchJshint": true,
"watchScsslint": false,
"babel": false,
"browserSync": {
"open": true,
"server": {
"baseDir": "./"
}
},
"pagespeed": {
"url": "http://m.deja.me/<%=projectName%>/",
"options": {
"strategy": "mobile"
}
}
},
"dependencies": {},
"devDependencies": {
"babel": "^5.6.14",
"babel-core": "^6.6.5",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"browser-sync": "^2.11.1",
"chai": "^3.0.0",
"chai-as-promised": "^5.1.0",
"date-utils": "^1.2.16",
"del": "^1.1.1",
"eslint-config-unstandard": "^1.1.0",
"gulp": "^3.9.0",
"gulp-autoprefixer": "^2.1.0",
"gulp-cachebust": "0.0.5",
"gulp-cached": "^1.0.4",
"gulp-csso": "^1.0.0",
"gulp-file-include": "^0.8.0",
"gulp-if": "^1.2.5",
"gulp-imagemin": "^2.2.1",
"gulp-jshint": "^1.9.2",
"gulp-load-plugins": "^0.8.1",
"gulp-minify-html": "^1.0.6",
"gulp-replace": "^0.5.3",
"gulp-sass": "^2.2.0",
"gulp-scsslint": "0.0.5",
"gulp-sftp": "^0.1.4",
"gulp-size": "^1.2.1",
"gulp-sourcemaps": "^1.5.1",
"gulp-uglify": "^1.1.0",
"gulp-util": "^3.0.4",
"gulp-eslint": "^2.0.0",
"imagemin-pngquant": "^4.0.0",
"jshint-stylish": "^1.0.1",
"log4js": "^0.6.26",
"mocha": "^2.2.5",
"pem": "^1.7.1",
"protractor": "^2.5.1",
"psi": "^1.0.6",
"q": "^1.2.0",
"rsync": "^0.4.0",
"run-sequence": "^1.0.2",
"sprity": "^1.0.8",
"strip-ansi": "^3.0.1",
"through2": "^0.6.3",
"vinyl-source-stream": "^1.1.0",
"wd": "^0.3.12",
"wd-bridge": "0.0.2",
"webpack": "^1.12.14",
"webpack-dev-middleware": "^1.5.1",
"webpack-stream": "^3.1.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"web app",
"mozat"
],
"author": "unbug",
"license": "MIT"
}
================================================
FILE: app/templates/app/.babelrc
================================================
{ "presets": ["es2015","react"] }
================================================
FILE: app/templates/app/README.md
================================================
Readme
=================
This project require [node](https://nodejs.org/).
Run `npm install` to install dependencies before get started.
This project is generated by [generator-webappstarter](https://github.com/unbug/generator-webappstarter)
Project commands
=================
run this command before you get started.
```shell
npm install -g gulp
```
1.build project,watch change and start browserSync,run
```shell
gulp
```
or run with forever
```shell
forever ./node_modules/.bin/gulp
```
2.deploy to test server,run
```shell
gulp deploytest
```
Please update your ftp auth name and password in ".ftppass".
View the page on test server [http://office.mozat.com:8083/PROJECTNAME/](http://office.mozat.com:8083/PROJECTNAME/).
This command require [openssl](https://www.openssl.org/).
For windows,you might needd to add openssl path to classpath.
3.deploy to offical server,run
```shell
gulp deploy
```
View the page on offical server [http://m.deja.me/PROJECTNAME/](http://m.deja.me/PROJECTNAME/).
This command require [rsync](https://rsync.samba.org/).
For windows,unzip /tools/rsync.zip to a local path and add the path to classpath.
4.run this command to copy source images to project's `resources/images/` path,then generate `scss/_dubug-sprites.csss` and `resources/images/sprites.png` for sourceSprites in `package.json`.
```shell
gulp copy
```
5.run this command to start jshint.
```shell
gulp jshint
```
6.run this command to start browserSync,Change browserSync options in `package.json`.
```shell
gulp serve
```
7.run this command to start pagespeed,Change pagespeed options in `package.json`.
```shell
gulp pagespeed
```
Structure
================
The structure is modular design,follow the DOOR-KEY rule you only take minutes to understand it:
* The DOOR for javascript is in ```/src/app/App.js```,and the KEY is ```require```,see [webpack](https://webpack.github.io/docs/commonjs.html) and [commonjs](http://www.commonjs.org/specs/modules/1.0/)
* The DOOR for stylesheets is in ```/scss/styles.scss```,and the KEY is ```@import```,see [SASS](http://sass-lang.com/)
* The DOOR for HTML is in ```/html/debug/index.html```,and the KEY is ```@@include```,see [gulp-file-include](https://www.npmjs.com/package/gulp-file-include)
Git
==========
Random git commit message
```shell
git commit -m"`curl -s http://whatthecommit.com/index.txt`"
```
================================================
FILE: app/templates/app/data/user.json
================================================
[
{"name": "Peter"},
{"name": "Joy"},
{"name": "Brian"}
]
================================================
FILE: app/templates/app/gulpfile.js
================================================
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var fs = require('fs');
var path = require('path');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var through2 = require('through2');
var $ = require('gulp-load-plugins')();
var del = require('del');
var pem = require('pem');
var rsync = require('rsync');
var sprity = require('sprity');
var pngquant = require('imagemin-pngquant');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync').create();//http://www.browsersync.io/docs/gulp/
var pagespeed = require('psi');
var cachebust = new $.cachebust();
var webpackStream = require("webpack-stream");
require('date-utils');
//values
var conf = require('./package.json');
var projectName = conf.name;
//not available project names
var notAvailableNames = conf.project.invalidNames;
if (notAvailableNames.split('|').indexOf(projectName) != -1) {
console.log('\n"' + notAvailableNames + '" are not available project names!\n');
return;
}
var title = conf.project.title || conf.name;
var viewport = conf.project.viewport || 'device-width';
var globalVersion = conf.version;
var distPath = './dist/';
var distProjectPath = distPath + projectName;
var sourceImg = conf.project.sourceImg;//source images path to copy to this project
var sourceSprites = conf.project.sourceSprites;//source images path to generate sprites
var isBuild = false;
//build version:
//script version
//style version
//manifest version
var startTime = 0;
var buildVersion = 0;
gulp.task('build_version', function (cb) {
var startDate = new Date();
startTime = startDate.getTime();
buildVersion = startDate.toFormat('YYYYMMDDHHMISS');
cb();
});
//clear images
gulp.task('clean:images', function (cb) {
del(['./resources/images/*'], {force: true}, cb);
});
//copy source images to "/resources/images"
gulp.task('copy:source_imgs', function () {
return gulp.src([sourceImg])
.pipe(gulp.dest('./resources/images'))
.pipe($.size({title: 'copy source images'}));
});
//generate sprites.png and _debug-sprites.scss
gulp.task('sprites', function () {
return sprity.src({
src: sourceSprites,
name: 'sprites',
style: '_sprites.scss',
cssPath: '../images/',
processor: 'css'
})
.pipe($.if('*.png', gulp.dest('./resources/images/'), gulp.dest('./scss/')))
.pipe($.size({title: 'sprites'}));
});
//watching script change to start default task
gulp.task('watch', function () {
return gulp.watch([
'src/**/*.js', '!src/app.js',
'scss/**/*.scss',
'html/**/*.html'
], function (event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
var tasks = ['prepare'];
if (/.*\.js$/.test(event.path)) {
//jshint
conf.project.watchJshint && gulp.src(event.path)
.pipe($.jshint())
.pipe($.jshint.reporter('jshint-stylish'));
tasks.push('webpackjs');
}
else if (/.*\.scss$/.test(event.path)) {
//scsslint
//https://github.com/noahmiller/gulp-scsslint
conf.project.watchScsslint && gulp.src(event.path)
.pipe($.scsslint())
.pipe($.scsslint.reporter());
tasks.push('sass');
}
else if (/.*\.html$/.test(event.path)) {
tasks.push('html');
}
tasks.push('manifest');
runSequence.apply(null,tasks);
});
});
//compile sass files
var AUTOPREFIXER_BROWSERS = [
'ie >= 10',
'ie_mob >= 10',
'ff >= 30',
'chrome >= 34',
'safari >= 7',
'opera >= 23',
'ios >= 7',
'android >= 4.4',
'bb >= 10'
];
gulp.task('sass', function (cb) {
gulp.src(['./scss/**/*.scss'], {buffer: true})
.pipe($.replace(/_VIEWPORT_WIDTH_/g, viewport == 'device-width'?'100%': viewport+'px'))
.pipe(gulp.dest('./.scss'))//fix replace not working
.on('end', function () {
gulp.src(['./.scss/**/*.scss'], {buffer: true})
.pipe($.sourcemaps.init())
.pipe($.sass({errLogToConsole: true}))
.pipe($.cached('sass-cache', {
optimizeMemory: true
}))
.pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
.pipe($.sourcemaps.write())
.pipe(gulp.dest('./resources/css/'))
.on('end', function () {
del(['./.scss'], {force: true});
cb();
});
});
});
//compile js files
var webpackConfig = require('./webpack.config');
gulp.task('webpackjs', function() {
return gulp.src(['./src/**/*.js'])
.pipe($.cached('webpackjs-cache', {
optimizeMemory: true
}))
.pipe(webpackStream(webpackConfig[isBuild?'build':'dev']))
.pipe(gulp.dest('./src'));
});
//compile html files
gulp.task('html', function () {
return gulp.src(['./html/debug/*.html'])
.pipe($.fileInclude({
basepath: './html/'
}))
.pipe($.cached('html-cache', {
optimizeMemory: true
}))
.pipe($.replace(/_BUILD_VERSION_/g, buildVersion))
.pipe($.replace(/_GLOBAL_VERSION_/g, globalVersion))
.pipe($.replace(/_VIEWPORT_WIDTH_/g, viewport))
.pipe($.replace(/_TITLE_/g, title))
.pipe($.replace(/_MANIFEST_/g, conf.project.manifest?'manifest="cache.manifest"':''))
.pipe(gulp.dest('./'));
});
//generate cache.manifest
gulp.task('manifest', function (cb) {
var resources = ['src/app.js'];
gulp.src(['./resources/**/*.*'])
.pipe(through2.obj(function (file, enc, next) {
this.push(file.path.replace(__dirname+'/',''));
next();
}))
.on('data', function (data) {
resources.push(data)
})
.on('end', function () {
gulp.src(['./html/include/cache.manifest'])
.pipe($.replace(/_BUILD_VERSION_/g, buildVersion))
.pipe($.replace(/_GLOBAL_VERSION_/g, globalVersion))
.pipe($.replace(/_FILES_/g, resources.join('\n')))
.pipe(gulp.dest('./'))
.on('end', function () {
cb();
});
});
});
//clear dist folder
gulp.task('clean:dist', function (cb) {
del([distPath + '*'], {force: true}, cb);
});
//copy resources to "/dist/resources/"
gulp.task('dist:resources', function () {
return gulp.src('./resources/**/*.*')
.pipe(gulp.dest(distProjectPath + '/resources/'))
.pipe($.size({title: 'dist:resources'}));
});
//compress images to dist
gulp.task('dist:images', function () {
return gulp.src(['./resources/**/*.*g'])
.pipe($.imagemin({
use: [pngquant()]
}))
.pipe(cachebust.resources())
.pipe(gulp.dest(distProjectPath + '/resources/'))
.pipe($.size({title: 'dist:images'}));
});
//compress css to dist
gulp.task('dist:css', function () {
return gulp.src('./resources/**/*.css')
.pipe(cachebust.references())
.pipe($.csso())
.pipe(cachebust.resources())
.pipe(gulp.dest(distProjectPath + '/resources'))
.pipe($.size({title: 'dist:css'}));
});
//compress js to dist
gulp.task('dist:js', function () {
return gulp.src(['./src/app.js'])
//remove //_DEBUG_ in files,
//such as: "///_DEBUG_*Todo: debug actions //*/ "
//will become "/*Todo: debug actions //*/",so uglify could remove all comments
.pipe($.replace(/\/\/_DEBUG_/g, ''))
.pipe(cachebust.references())
.pipe($.uglify())
.pipe(cachebust.resources())
.pipe(gulp.dest(distProjectPath + '/src/'))
.pipe($.size({title: 'dist:js'}));
});
//compress html to dist
gulp.task('dist:html', function () {
return gulp.src(['html/official/*.html'])
.pipe($.fileInclude({
basepath: './html/'
}))
.pipe($.replace(/_BUILD_VERSION_/g, buildVersion))
.pipe($.replace(/_GLOBAL_VERSION_/g, globalVersion))
.pipe($.replace(/_VIEWPORT_WIDTH_/g, viewport))
.pipe($.replace(/_TITLE_/g, title))
.pipe($.replace(/_MANIFEST_/g, conf.project.manifest?'manifest="cache.manifest"':''))
.pipe(cachebust.references())
.pipe($.minifyHtml({
empty: true,
cdata: true,
conditionals: true,
spare: true,
quotes: true
}))
.pipe(gulp.dest(distProjectPath))
.pipe($.size({title: 'dist:html'}));
});
//copy cache.manifest to dist
gulp.task('dist:manifest', function () {
return gulp.src('./cache.manifest')
.pipe(cachebust.references())
.pipe(gulp.dest(distProjectPath + '/'))
.pipe($.size({title: 'dist:manifest'}));
});
//deploy to test server
//view http://office.mozat.com:8081/m/PROJECTNAME/
gulp.task('deploy:test', function (cb) {
pem.createCertificate({}, function (err, kyes) {
gulp.src(distPath + '**/*')
.pipe($.sftp({
host: '172.28.2.62',
port: 22,
auth: 'testServer',
key: kyes.clientKey,
keyContents: kyes.keyContents,
remotePath: '/home/gaolu/m/'
}, cb));
});
});
//deploy to offical server
//view http://m.deja.me/PROJECTNAME/
gulp.task('deploy:offical', function (cb) {
//set rsync proxy
process.env.RSYNC_PROXY = 'proxy.lan:8080';
var client = new rsync()
.executable('rsync')
.flags('azv')
.source(distPath)
.destination('rsync://10.160.241.153/m.deja.me/');
client.execute(function (error, code, cmd) {
console.log('\t' + cmd);
//reset rsync proxy
process.env.RSYNC_PROXY = '';
cb();
});
});
//deploy to offical server
//view http://m.deja.me/PROJECTNAME/
// deploy guide
// 1. get rsync's port
// grep rsync /etc/services
// 2. open tunnel
// sudo ssh -N -L 127.0.0.1:873:10.160.241.153:873 tunnel@ssh.mozat.com
gulp.task('_deploy:offical', function (cb) {
//set rsync proxy
var client = new rsync()
.executable('rsync')
.flags('azv')
.source(distPath)
.destination('rsync://localhost/m.deja.me/');
client.execute(function (error, code, cmd) {
console.log('\t' + cmd);
//reset rsync proxy
process.env.RSYNC_PROXY = '';
cb();
});
});
// Lint JavaScript
gulp.task('jshint', function () {
return gulp.src(['./src/**/*.js', '!./src/*.js', '!./src/lib/zepto.js'])
.pipe($.jshint())
.pipe($.jshint.reporter('jshint-stylish'))
.pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});
//browser-sync serve
var browserSyncOptions = conf.project.browserSync || {};
gulp.task('serve', function () {
browserSync.init(browserSyncOptions);
gulp.watch(['./*.html'], browserSync.reload);
gulp.watch(['./src/*.js'], browserSync.reload);
gulp.watch(['./resources/**/*.css'], browserSync.reload);
gulp.watch(['./resources/**/*.*g'], browserSync.reload);
});
// Run PageSpeed Insights
gulp.task('pagespeed', function (cb) {
// By default we use the PageSpeed Insights free (no API key) tier.
// Use a Google Developer API key if you have one: http://goo.gl/RkN0vE
// key: 'YOUR_API_KEY'
pagespeed.output(conf.project.pagespeed.url, conf.project.pagespeed.options, function (err, data) {
cb();
});
});
//print after tasks all done
gulp.task('_endlog', function (cb) {
var endDate = new Date();
var logs = [];
logs.push('\nBuild version is ' + buildVersion);
logs.push(', Completed in ' + ((endDate.getTime() - startTime) / 1000) + 's at ' + endDate + '\n');
console.log(logs.join(''));
cb();
});
//test
function getProtractorBinary(binaryName){
var winExt = /^win/.test(process.platform)? '.cmd' : '';
var pkgPath = require.resolve('protractor');
var protractorDir = path.resolve(path.join(path.dirname(pkgPath), '..', 'bin'));
return path.join(protractorDir, '/'+binaryName+winExt);
}
gulp.task('protractor-install', function(done){
spawn(getProtractorBinary('webdriver-manager'), ['update'], {
stdio: 'inherit'
}).once('close', done);
});
gulp.task('wd', function(done){
spawn(getProtractorBinary('webdriver-manager'), ['start'], {
stdio: 'inherit'
}).once('close', done);
});
gulp.task('scenario', function (done) {
var argv = process.argv.slice(3); // forward args to protractor
argv.push('test/protractor.conf.js');
spawn(getProtractorBinary('protractor'), argv, {
stdio: 'inherit'
}).once('close', done);
});
//end test
function handleError(err) {
console.log(err.toString());
this.emit('end');
}
//task queues
gulp.task('copy', function (cb) {
runSequence('clean:images', 'copy:source_imgs', 'sprites', cb);
});
gulp.task('prepare', function (cb) {
runSequence('build_version', cb);
});
gulp.task('compile', function (cb) {
runSequence('sass', 'webpackjs', 'manifest', 'html', cb);
});
gulp.task('dist', function (cb) {
isBuild = true;
runSequence('clean:dist', 'prepare', 'compile','dist:resources', 'dist:images', 'dist:css', 'dist:js', 'dist:manifest','dist:html', '_endlog', cb);
});
gulp.task('default', function (cb) {
runSequence('prepare', 'compile', 'watch', 'serve', cb);
});
//deploy to test server
gulp.task('deploytest', function (cb) {
runSequence('dist', 'deploy:test', cb);
});
//deploy to offical server
gulp.task('deploy', function (cb) {
runSequence('dist', 'deploy:offical', cb);
});
//deploy to offical server
gulp.task('deployrc', function (cb) {
distProjectPath = distProjectPath +'_rc';
runSequence('deploy', cb);
});
//deploy to offical server from home
gulp.task('_deploy', function (cb) {
runSequence('dist', '_deploy:offical', cb);
});
gulp.task('_deployrc', function (cb) {
distProjectPath = distProjectPath +'_rc';
runSequence('_deploy', cb);
});
gulp.task('test', function (done) {
runSequence('scenario',done);
});
================================================
FILE: app/templates/app/html/debug/analytics.html
================================================
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
</body>
</html>
================================================
FILE: app/templates/app/html/debug/index.html
================================================
<!DOCTYPE HTML>
<html>
<head>
<!-- htmlhead -->
@@include('include/htmlhead.html')
<!-- end htmlhead -->
<!-- styles -->
@@include('include/styles-version.html')
<!--end styles -->
</head>
<body ontouchstart="" class="" style="visibility: hidden;">
<!-- views -->
@@include('include/views.html')
<!--end views -->
<!-- components -->
@@include('include/components.html')
<!-- end components -->
<!-- scripts -->
@@include('include/scripts-version.html')
<!--end scripts -->
</body>
</html>
================================================
FILE: app/templates/app/html/include/cache.manifest
================================================
CACHE MANIFEST
# Version: _GLOBAL_VERSION_
# Build: _BUILD_VERSION_
CACHE:
_FILES_
NETWORK:
*
================================================
FILE: app/templates/app/html/include/components.html
================================================
<!-- msgbox -->
@@include('include/msgbox.html')
<!-- end msgbox -->
<!-- tooltip -->
@@include('include/tooltip.html')
<!-- end tooltip -->
================================================
FILE: app/templates/app/html/include/download.html
================================================
<section class="section-download hide" data-eventname="appDownload" data-eventparams="0,1">
<div class="sd-logo"><img src="resources/images/logo.png"></div>
<div class="sd-info">
<div class="name">Deja</div>
<div class="dest">Get your style on.</div>
</div>
<div class="sd-btns">
<div class="btn bt-primary size-s">OPEN APP</div>
</div>
</section>
================================================
FILE: app/templates/app/html/include/footer.html
================================================
<section class="footer-section hide">
<div class="stores">
<a class="apple" data-analytics="store=apple"
href="https://itunes.apple.com/us/app/deja-fashion/id971025031?mt=8&111111"><i
class="icon icon-bt_Appbutton"></i></a>
<a class="google" data-analytics="store=google" href="http://deja.me/"><i class="icon icon-bt_google"></i></a>
</div>
<div class="about">
<p>For further enquires, contact us at <a href="mailto:event@dejafashion.com?subject=Deja Fashion">event@dejafashion.com</a>
</p>
<p>© 2015 Deja Fashion Pte Ltd. All Rights Reserved.</p>
</div>
</section>
================================================
FILE: app/templates/app/html/include/htmlhead.html
================================================
<meta charset="UTF-8">
<meta content="target-densitydpi=device-dpi,width=_VIEWPORT_WIDTH_" name="viewport">
<title>_TITLE_</title>
<meta name="author" content="Mozat"/>
<meta name="Copyright" content="Mozat Pte Ltd"/>
<meta name="format-detection" content="email=no,address=no,telephone=no">
================================================
FILE: app/templates/app/html/include/manifest-version.html
================================================
<html manifest="_GLOBAL_VERSION_.manifest">
================================================
FILE: app/templates/app/html/include/msgbox-deja.html
================================================
<div class="box-ct signin">
<div class="box-bd">
<div>
<div class="msg fix-break-word">Please sign in</div>
<div class="plf">
<div class="b" data-plf="fb"><i class="icon icon-btn_fb_login"></i></div>
</div>
</div>
<div class="no"><i class="icon icon-ic_s_close_nor_2x"></i></div>
</div>
</div>
================================================
FILE: app/templates/app/html/include/msgbox.html
================================================
<section class="msgbox">
<div class="box-mask"></div>
<div class="msgbox-ct">
<div class="msgbox-bd">
<div class="box-ct dialog">
<div class="box-bd">
<div>
<div class="content">
<div class="title">Confirm your information</div>
<div class="msg"></div>
</div>
<div class="bbts">
<div class="no">Cancel</div>
<div class="yes">Confirm</div>
</div>
</div>
</div>
</div>
<div class="box-ct menu absolute">
<div class="box-bd">
<div class="options"></div>
<div class="opt no">Cancel</div>
</div>
</div>
<div class="box-ct loading">
<div class="box-bd">
<div>
<div class="loading-spinner">
<span class="loading-top"></span>
<span class="loading-right"></span>
<span class="loading-bottom"></span>
<span class="loading-left"></span>
</div>
<div class="msg">Submitting</div>
</div>
</div>
</div>
<!-- msgbox deja -->
@@include('include/msgbox-deja.html')
<!-- end msgbox deja -->
</div>
</div>
</section>
================================================
FILE: app/templates/app/html/include/scripts-version.html
================================================
<script src="src/app.js" defer></script>
================================================
FILE: app/templates/app/html/include/styles-version.html
================================================
<link rel="stylesheet" href="resources/css/styles.css">
================================================
FILE: app/templates/app/html/include/tooltip.html
================================================
<script type="text/html" id="tpl_tooltip">
<section class="tooltip <%=theme%> <%=rootCls%>" id="<%=rootId%>">
<section class="tooltip__ct">
<div class="tooltip__bd animated">
<div class="tooltip__content <%=bodyCls%>"><%=body%></div>
<div class="tooltip__arrow <%=arrow.type%>" style="<%=arrow.style%>">
<div></div>
</div>
</div>
</section>
</section>
</script>
================================================
FILE: app/templates/app/html/include/view-home.html
================================================
<section class="view view-home">
<section class="main">
<section class="btn bt-default" data-fake-link="#/user/">View Users!</section>
</section>
</section>
================================================
FILE: app/templates/app/html/include/view-user.html
================================================
<section class="view view-user">
<section class="users">
<section class="list user-item-default" data-element="list">
<script type="text/html" data-template="listItem">
<article class="item">
<%=name%>
</article>
</script>
</section>
<section class="btn bt-primary back">Go back!</section>
</section>
</section>
================================================
FILE: app/templates/app/html/include/views.html
================================================
<!-- view-home -->
@@include('include/view-home.html')
<!--end view-home -->
<!-- view-user -->
@@include('include/view-user.html')
<!--end view-user -->
================================================
FILE: app/templates/app/html/official/analytics.html
================================================
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
</body>
</html>
================================================
FILE: app/templates/app/html/official/index.html
================================================
<!DOCTYPE HTML>
<html _MANIFEST_>
<head>
<!-- htmlhead -->
@@include('include/htmlhead.html')
<!-- end htmlhead -->
<!-- styles -->
@@include('include/styles-version.html')
<!--end styles -->
</head>
<body ontouchstart="" class="" style="visibility: hidden;">
<!-- views -->
@@include('include/views.html')
<!--end views -->
<!-- components -->
@@include('include/components.html')
<!-- end components -->
<!-- scripts -->
@@include('include/scripts-version.html')
<!--end scripts -->
</body>
</html>
================================================
FILE: app/templates/app/scss/_animate.scss
================================================
@charset "UTF-8";
/*
参考自 http://daneden.github.io/animate.css/
*/
/*
@-webkit-keyframes rotateRight{
@for $i from 0 through 45 {
none:2.22%*$i;-webkit-transform: rotate(8deg*$i);
}
}
*/
@-webkit-keyframes tada {
0% {
-webkit-transform: scale(1);
}
10%, 20% {
-webkit-transform: scale(0.6) rotate(-3deg);
}
30%, 50% {
-webkit-transform: scale(0.9) rotate(3deg);
}
70%, 90% {
-webkit-transform: scale(1.0) rotate(3deg);
}
40%, 60%, 80% {
-webkit-transform: scale(1.1) rotate(-3deg);
}
100% {
-webkit-transform: scale(1) rotate(0deg);
}
}
@-webkit-keyframes bounceIn {
0% {
opacity: 0;
-webkit-transform: scale(.3);
}
50% {
opacity: 1;
-webkit-transform: scale(1.05);
}
70% {
-webkit-transform: scale(.9);
}
100% {
opacity: 1;
-webkit-transform: scale(1);
}
}
@-webkit-keyframes MicroBounceOut {
0% {
opacity: 0;
-webkit-transform: scale3d(1, 1.03, 1) translate3d(0, 1, 0);
}
99% {
-webkit-transform: scale3d(1, .999, 1);
}
100% {
opacity: 1;
-webkit-transform: scale3d(1, 1, 1);
}
}
@-webkit-keyframes MicroPopUp {
0% {
opacity: 0;
-webkit-transform: scale3d(1.1, 1.1, 1);
}
90% {
-webkit-transform: scale3d(.99, .99, 1);
}
100% {
opacity: 1;
-webkit-transform: scale3d(1, 1, 1);
}
}
@-webkit-keyframes MicroMask {
0% {
opacity: 0;
}
100% {
opacity: .5;
}
}
@-webkit-keyframes bounceInDown {
0% {
opacity: 0;
-webkit-transform: translateY(-2000px);
}
60% {
opacity: 1;
-webkit-transform: translateY(30px);
}
80% {
-webkit-transform: translateY(-10px);
}
100% {
-webkit-transform: translateY(0);
opacity: 1;
}
}
@-webkit-keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-webkit-keyframes fadeInOut {
0%, 100% {
opacity: 0;
}
40% {
opacity: 1;
}
}
@-webkit-keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@-webkit-keyframes flash {
0%, 50%, 100% {
opacity: 1;
}
25%, 75% {
opacity: 0;
}
}
@-webkit-keyframes fadeInUp {
0% {
opacity: 0;
-webkit-transform: translateY(20px);
}
100% {
opacity: 1;
-webkit-transform: translateY(0);
}
}
@-webkit-keyframes fadeInUpMax {
0% {
opacity: 0;
-webkit-transform: translateY(100%);
}
100% {
opacity: 1;
-webkit-transform: translateY(0);
}
}
@-webkit-keyframes fadeInDown {
0% {
opacity: 0;
-webkit-transform: translateY(-20px);
}
100% {
opacity: 1;
-webkit-transform: translateY(0);
}
}
@-webkit-keyframes fadeInLeft {
0% {
opacity: 0;
-webkit-transform: translate3d(-100%, 0, 0);
}
90% {
opacity: .9;
-webkit-transform: translate3d(1%, 0, 0);
}
100% {
opacity: 1;
-webkit-transform: none;
}
}
@-webkit-keyframes fadeInRight {
0% {
opacity: 0;
-webkit-transform: translate3d(100%, 0, 0);
}
90% {
opacity: .9;
-webkit-transform: translate3d(-1%, 0, 0);
}
100% {
opacity: 1;
-webkit-transform: none;
}
}
@-webkit-keyframes flipInY {
0% {
-webkit-transform: perspective(400px) rotateY(90deg);
transform: perspective(400px) rotateY(90deg);
opacity: 0;
}
40% {
-webkit-transform: perspective(400px) rotateY(-10deg);
transform: perspective(400px) rotateY(-10deg);
}
70% {
-webkit-transform: perspective(400px) rotateY(10deg);
transform: perspective(400px) rotateY(10deg);
}
100% {
-webkit-transform: perspective(400px) rotateY(0deg);
transform: perspective(400px) rotateY(0deg);
opacity: 1;
}
}
@-webkit-keyframes flipInX {
from {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
opacity: 0;
}
40% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
opacity: 1;
}
80% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
}
to {
-webkit-transform: perspective(400px);
transform: perspective(400px);
}
}
@-webkit-keyframes zoomIn {
0% {
opacity: 0;
-webkit-transform: scale3d(.3, .3, .3);
transform: scale3d(.3, .3, .3);
}
50% {
opacity: 1;
}
}
@-webkit-keyframes slideInUp {
0% {
-webkit-transform: translateY(100%);
transform: translateY(100%);
visibility: visible;
}
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
}
@-webkit-keyframes slideInDown {
0% {
-webkit-transform: translateY(-100%);
transform: translateY(-100%);
visibility: visible;
}
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
}
@-webkit-keyframes slideOutDown {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
visibility: hidden;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
@keyframes slideOutDown {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
visibility: hidden;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
@-webkit-keyframes slideOutLeft {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
visibility: hidden;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
@keyframes slideOutLeft {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
visibility: hidden;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
@-webkit-keyframes slideOutRight {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
visibility: hidden;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
}
@keyframes slideOutRight {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
visibility: hidden;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
}
@-webkit-keyframes slideOutUp {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
visibility: hidden;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
}
@keyframes slideOutUp {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
100% {
visibility: hidden;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
}
@-webkit-keyframes spinnerRotateRight {
0% {
-webkit-transform: rotate(0deg);
}
8.32% {
-webkit-transform: rotate(0deg);
}
8.33% {
-webkit-transform: rotate(30deg);
}
16.65% {
-webkit-transform: rotate(30deg);
}
16.66% {
-webkit-transform: rotate(60deg);
}
24.99% {
-webkit-transform: rotate(60deg);
}
25% {
-webkit-transform: rotate(90deg);
}
33.32% {
-webkit-transform: rotate(90deg);
}
33.33% {
-webkit-transform: rotate(120deg);
}
41.65% {
-webkit-transform: rotate(120deg);
}
41.66% {
-webkit-transform: rotate(150deg);
}
49.99% {
-webkit-transform: rotate(150deg);
}
50% {
-webkit-transform: rotate(180deg);
}
58.32% {
-webkit-transform: rotate(180deg);
}
58.33% {
-webkit-transform: rotate(210deg);
}
66.65% {
-webkit-transform: rotate(210deg);
}
66.66% {
-webkit-transform: rotate(240deg);
}
74.99% {
-webkit-transform: rotate(240deg);
}
75% {
-webkit-transform: rotate(270deg);
}
83.32% {
-webkit-transform: rotate(270deg);
}
83.33% {
-webkit-transform: rotate(300deg);
}
91.65% {
-webkit-transform: rotate(300deg);
}
91.66% {
-webkit-transform: rotate(330deg);
}
100% {
-webkit-transform: rotate(330deg);
}
}
================================================
FILE: app/templates/app/scss/_box.scss
================================================
@charset "UTF-8";
.box-h{
@include box-h;
}
.box-h-c-c{
@include box-h-c-c;
}
.box-h-c-r{
@include box-h-c-r;
}
.box-h-c-l{
@include box-h-c-l;
}
.box-h-t-c{
@include box-h-t-c;
}
.box-h-t-l{
@include box-h-t-l;
}
.box-h-t-r{
@include box-h-t-r;
}
.box-h-b-c{
@include box-h-b-c;
}
.box-h-b-l{
@include box-h-b-l;
}
.box-h-b-r{
@include box-h-b-r;
}
.box-v{
@include box-v;
}
.box-v-c-c{
@include box-v-c-c;
}
.box-v-c-l{
@include box-v-c-l;
}
.box-v-c-r{
@include box-v-c-r;
}
.box-v-t-c{
@include box-v-t-c;
}
.box-v-t-l{
@include box-v-t-l;
}
.box-v-t-r{
@include box-v-t-r;
}
.box-v-b-c{
@include box-v-b-c;
}
.box-v-b-l{
@include box-v-b-l;
}
.box-v-b-r{
@include box-v-b-r;
}
================================================
FILE: app/templates/app/scss/_button.scss
================================================
@charset "UTF-8";
.btn {
display: inline-block;
text-align: center;
@include active-default;
@include disabled-select;
}
.btn-2i {
i {
&:nth-child(2), &.active {
display: none;
}
}
&:active,&.on {
i {
&:nth-child(1), &.normal {
display: none;
}
&:nth-child(2), &.active {
display: inline-block;
}
}
}
&.dis-active{
&:active{
i {
&:nth-child(1), &.normal {
display: inline-block;
}
&:nth-child(2), &.active {
display: none;
}
}
}
}
}
.bt-primary,.bt-default {
height: 100px;
line-height: 98px;
font-size: 38px;
padding: 0 30px;
text-transform: uppercase;
&.size-s{
padding: 0 20px;
font-size: 28px;
height: 70px;
line-height: 68px;
}
}
.bt-primary{
color: #fff;
background-color: $color-black-fourth;
&:active {
background-color: $color-red;
}
&.disabled{
background-color: $color-gray-third;
&:active{
background-color: $color-gray-third;
}
}
}
.bt-default {
border: 2px solid $color-black-second;
color: $color-black-fourth;
background: #fff;
&:active {
border: 2px solid $color-red;
color: #fff;
background-color: $color-red;
}
&.disabled{
color: #cfcfcf;
&:active{
border: 2px solid $color-gray;
color: #f1f1f1;
background-color: inherit;
}
}
}
================================================
FILE: app/templates/app/scss/_common.scss
================================================
@charset "UTF-8";
/* http://css-tricks.com/poll-results-how-do-you-order-your-css-properties/ */
body, html {
text-align: left;
height: 100%; /*高度必须为100%*/
width: 100%;
font-family: Roboto, HelveticaNeue, Helvetica, Arial, sans-serif;
font-size: 16px;
font-weight: normal;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: center;
}
body {
width: $layout-with;
min-height: 100%;
height: auto;
}
* {
margin: 0;
padding: 0;
border: 0;
-webkit-user-select: text;
word-break: normal;
}
*, :after, :before {
-webkit-box-sizing: border-box; /*高宽不算padding,margin*/
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
a, img {
-webkit-touch-callout: none; /*禁用长按弹出系统菜单*/
}
a {
text-decoration: none;
}
section, p, div {
max-height: 999999px;
}
textarea, input[type="password"], input[type="text"] {
resize: none; /*禁用可缩放*/
outline: none; /*禁用发光效果*/
-webkit-appearance: none; /*禁用增加外观效果*/
white-space: pre-wrap;
word-wrap: break-word;
background: #fff;
overflow: scroll;
}
audio {
width: 0;
height: 0;
padding: 0;
margin: 0;
opacity: 0;
visibility: hidden;
display: none;
position: absolute;
top: 0;
left: 0;
}
================================================
FILE: app/templates/app/scss/_components.scss
================================================
@charset "UTF-8";
/*debug-button.scss*/
@import "button.scss";
/*end debug-button.scss*/
/*debug-slide.scss*/
@import "slide.scss";
/*end debug-slide.scss*/
/*debug-msgbox.scss*/
@import "msgbox.scss";
/*end debug-msgbox.scss*/
/*debug-tooltip.scss*/
@import "tooltip.scss";
/*end debug-tooltip.scss*/
/*debug-loading-spinner.scss*/
@import "loading-spinner.scss";
/*end debug-loading-spinner.scss*/
/*debug-section-download.scss*/
@import "section-download.scss";
/*end debug-section-download.scss*/
================================================
FILE: app/templates/app/scss/_fonts.scss
================================================
@charset "UTF-8";
================================================
FILE: app/templates/app/scss/_footer.scss
================================================
@charset "UTF-8";
.footer-section {
margin-top: -1px;
width: 100%;
background-color: #3d1c21;
padding: 45px 0;
color: #fff;
> .stores {
@include box-h-c-c;
a {
display: inline-block;
margin: 0 20px;
}
}
> .about {
font-size: 24px;
margin-top: 18px;
p {
line-height: 30px;
text-align: center;
}
.a, a:active, a:link, a:hover {
color: #fff;
text-decoration: underline;
}
}
}
================================================
FILE: app/templates/app/scss/_header.scss
================================================
@charset "UTF-8";
.tabs-title-default {
@include box-h;
-webkit-border-radius: 10px;
background-color: #eeeeee;
overflow: hidden;
border: 2px solid #acacac;
> div {
@include box-h-c-c;
-webkit-box-flex: 1;
width: 50%;
font-size: 28px;
padding: 12px 0;
color: #acacac;
background-color: #f0f0f0;
@include active-default;
&.first {
-webkit-border-top-left-radius: 8px;
-webkit-border-bottom-left-radius: 8px;
}
&.last {
-webkit-border-top-right-radius: 8px;
-webkit-border-bottom-right-radius: 8px;
}
&.on {
color: #fff;
background-color: #acacac;
}
}
}
.tabs-title-underline {
position: relative;
@include box-h;
height: 70px;
width: 100%;
padding: 0 28px;
background-color: #fff;
color: #747474;
> article {
position: relative;
@include box-h-c-c;
height: 100%;
-webkit-box-flex: 1;
@include active-default;
> .title {
height: 100%;
width: 100%;
text-align: center;
line-height: 70px;
font-size: 32px;
}
> .underline {
position: absolute;
bottom: 0;
left: 0;
@include box-h-c-c;
height: 5px;
width: 100%;;
> div {
opacity: 0;
height: 0;
width: 0;
background-color: #e84142;
-webkit-transition: all .35s ease-in-out;
}
}
> .notify {
display: none;
z-index: 2;
position: absolute;
width: 8px;
height: 8px;
top: 14px;
right: 14px;
background-color: #e84142;
-webkit-border-radius: 100%;
&.on {
@include box-h;
}
}
&.on {
color: #292929;
> .underline {
> div {
opacity: 1;
height: 100%;
width: 80%;
}
}
}
}
}
.section-title-default {
@include box-h-c-l;
height: 100px;
line-height: 100px;
padding: 0 20px;
> div {
display: -webkit-box;
}
> .dot {
width: 10px;
height: 10px;
-webkit-border-radius: 5px;
background-color: $color-black-third;
}
> .title {
padding-left: 12px;
font-size: 36px;
line-height: 38px;
color: $color-black-third;
-webkit-box-flex: 1;
/*
&.animated{
@include animated-1s;
-webkit-animation-name: fadeInLeft;
}
*/
}
> .link {
> a, > a:active, > a:hover, > a:visited {
font-size: 32px;
color: #00a0e9;
}
}
&.bar {
height: 120px;
line-height: 120px;
> .dot {
width: 4px;
height: 30px;
background-color: $color-red;
-webkit-border-radius: 0;
}
> .title {
color: $color-black-second;
padding-left: 20px;
}
}
&.center {
@include box-h-c-c;
.title {
display: inline-block;
}
.dot {
margin-top: -14px;
}
}
}
.section-title-similar{
width: 100%;
height: 48px;
padding: 0 40px;
line-height: 48px;
font-size: 28px;
color: $color-gray-second;
background-color: #f9f9f9;
}
================================================
FILE: app/templates/app/scss/_icon.scss
================================================
@charset "UTF-8";
/*debug-sprites.scss*/
@import "sprites.scss";
/*end debug-sprites.scss*/
.icon {
background-repeat: no-repeat;
display: inline-block;
@include disabled-select;
}
================================================
FILE: app/templates/app/scss/_list.scss
================================================
@charset "UTF-8";
.tabs-content-default {
display: none;
&.show {
display: block;
@include animated-1s;
}
&.animated {
-webkit-animation-name: fadeInUp;
}
}
.user-item-default {
@include box-v;
width: 100%;
font-size: 38px;
> .item {
@include box-h;
width: 100%;
padding: 30px;
text-align: center;
}
}
================================================
FILE: app/templates/app/scss/_loading-spinner.scss
================================================
@charset "UTF-8";
.loading-spinner {
font-size: 120%;
height: 1em;
width: 1em;
position: relative;
-webkit-transform-origin: 0.5em 0.5em;
> span {
display: block;
position: absolute;
width: 0.1em;
height: 0.25em;
top: 0;
-webkit-transform-origin: 0.05em 0.5em;
-webkit-border-radius: 0.05em;
border-radius: 0.05em;
content: " ";
&:before, &:after {
display: block;
position: absolute;
width: 0.1em;
height: 0.25em;
top: 0;
-webkit-transform-origin: 0.05em 0.5em;
-webkit-border-radius: 0.05em;
border-radius: 0.05em;
content: " ";
}
&.loading-top {
background-color: rgba(0, 0, 0, 0.99);
&:after {
background-color: rgba(0, 0, 0, 0.9);
}
}
&.loading-left {
background-color: rgba(0, 0, 0, 0.7);
&:before {
background-color: rgba(0, 0, 0, 0.8);
}
&:after {
background-color: rgba(0, 0, 0, 0.6);
}
}
&.loading-bottom {
background-color: rgba(0, 0, 0, 0.4);
&:before {
background-color: rgba(0, 0, 0, 0.5);
}
&:after {
background-color: rgba(0, 0, 0, 0.35);
}
}
&.loading-right {
background-color: rgba(0, 0, 0, 0.25);
&:before {
background-color: rgba(0, 0, 0, 0.3);
}
&:after {
background-color: rgba(0, 0, 0, 0.2);
}
}
&.loading-top {
&:before {
background-color: rgba(0, 0, 0, 0.15);
}
-webkit-transform: rotate(0deg);
}
left: 50%;
margin-left: -0.05em;
&.loading-right {
-webkit-transform: rotate(90deg);
}
&.loading-bottom {
-webkit-transform: rotate(180deg);
}
&.loading-left {
-webkit-transform: rotate(270deg);
}
&:before {
-webkit-transform: rotate(30deg);
}
&:after {
-webkit-transform: rotate(-30deg);
}
}
-webkit-animation-name: spinnerRotateRight;
-webkit-animation-duration: .8s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
}
================================================
FILE: app/templates/app/scss/_mixin.scss
================================================
@charset "UTF-8";
@mixin animated-1s {
animation-duration: 1s;
animation-iteration-count: 1;
animation-fill-mode: both;
animation-timing-function: ease-in-out;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: 1;
-webkit-animation-fill-mode: both;
-webkit-animation-timing-function: ease-in-out;
}
@mixin blank-bg {
background-image: url('about:blank');
/*
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABBJREFUeNpi+P//PwNAgAEACPwC/tuiTRYAAAAASUVORK5CYII=);
background-repeat: repeat;
*/
display: block !important;
}
@mixin box-h {
display: -webkit-box;
-webkit-box-orient: horizontal;
}
@mixin box-h-c-c {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack: center;
-webkit-box-align: center;
}
@mixin box-h-c-r {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack: end;
-webkit-box-align: center;
}
@mixin box-h-c-l {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: center;
-webkit-box-pack: start;
}
@mixin box-h-t-c {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: start;
-webkit-box-pack: center;
}
@mixin box-h-t-l {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: start;
-webkit-box-pack: start;
}
@mixin box-h-t-r {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: start;
-webkit-box-pack: end;
}
@mixin box-h-b-c {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack: center;
-webkit-box-align: end;
}
@mixin box-h-b-l {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack: start;
-webkit-box-align: end;
}
@mixin box-h-b-r {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack: end;
-webkit-box-align: end;
}
@mixin box-v {
display: -webkit-box;
-webkit-box-orient: vertical;
}
@mixin box-v-c-c {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: center;
-webkit-box-pack: center;
}
@mixin box-v-c-l {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-pack: center;
-webkit-box-align: start;
}
@mixin box-v-c-r {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-pack: center;
-webkit-box-align: end;
}
@mixin box-v-t-c {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: center;
}
@mixin box-v-t-l {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: start;
-webkit-box-pack: start;
}
@mixin box-v-t-r {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: start;
-webkit-box-pack: end;
}
@mixin box-v-b-c {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-pack: end;
-webkit-box-align: center;
}
@mixin box-v-b-l {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-pack: end;
-webkit-box-align: start;
}
@mixin box-v-b-r {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-pack: end;
-webkit-box-align: end;
}
@mixin active-default {
&:active {
opacity: $active-opacity;
}
}
@mixin active-ripple {
position: relative;
overflow: hidden;
&:after {
content: "";
position: absolute;
left: 50%;
top: 50%;
display: inherit;
padding-top: $layout-with;
padding-left: $layout-with;
margin-top: -$layout-with/2;
margin-left: -$layout-with/2;
border-radius: 50%;
opacity: 0;
background: rgba(255,255,255,0.5);
transition: all 1s;
}
&:active:after {
padding-top: 0;
padding-left: 0;
margin-top: 0;
margin-left: 0;
opacity: 1;
transition: 0s;
}
}
@mixin gpu-accelerate {
-webkit-transform: translateZ(0);
}
@mixin disabled-select {
-webkit-user-select: none;
}
@mixin disabled-select-all {
* {
@include disabled-select;
}
}
================================================
FILE: app/templates/app/scss/_msgbox-android.scss
================================================
@charset "UTF-8";
$android-border-radius: 8px;
/* android */
.msgbox{
.msgbox-bd.android{
color: #000;
> .box-ct.dialog{
$dialog-w: $layout-with * 0.86;
> .box-bd {
width: $dialog-w;
-webkit-border-radius: $android-border-radius;
.content {
background-color: #fff;
-webkit-border-radius: $android-border-radius $android-border-radius 0 0;
}
.bbts {
@include box-h-c-r;
width: 100%;
background-color: #fff;
padding: 14px 30px;
> div {
display: inline-block;
min-width: 172px;
height: 76px;
padding: 20px 22px;
color: #009688;
text-align: center;
text-transform: uppercase;
background-color: #fff;
-webkit-border-radius: 0 !important;
&:active {
background-color: #b6b6b6;
}
margin-top: 0;
&.no {
margin-right: 0;
}
}
}
}
}
> .box-ct.menu {
$dialog-w: $layout-with * 0.98;
$option-h: 120px;
//position: fixed;
left: ($layout-with - $dialog-w)/2;
bottom: 0px;
> .box-bd {
width: $dialog-w;
padding-bottom: 0;
> div {
@include box-v;
}
.opt {
&:active {
background-color: #b6b6b6;
}
@include box-h-c-c;
-webkit-box-flex: 1;
padding: 20px 0;
height: $option-h;
background-color: #fff;
text-transform: uppercase;
color: #009688;
&.msg{
height: auto;
min-height: $option-h;
padding: 20px;
color: #7b7b7b;
text-transform: none;
&:active{
background-color: #fff;
}
}
&.no {
margin-top: 20px;
background-color: #fff;
-webkit-border-radius: 0 !important;
font-weight: normal;
&:active{
background-color: #b6b6b6;
}
}
&.highlight{
color: #009688;
}
}
.options{
-webkit-border-radius: $android-border-radius;
overflow: hidden;
> div {
margin-top: 0;
&:first-child{
-webkit-border-radius: $android-border-radius $android-border-radius 0 0;
margin-top: 0;
}
}
}
}
}
}
}
/* end android */
================================================
FILE: app/templates/app/scss/_msgbox-deja.scss
================================================
@charset "UTF-8";
/* deja */
.msgbox {
.msgbox-bd.deja{
> .box-ct.dialog {
$dialog-w: $layout-with * 0.82;
color: $color-black-second;
> .box-bd {
width: $dialog-w;
-webkit-border-radius: 0;
.content {
padding-top: 68px;
line-height: 42px;
background-color: #fff;
-webkit-border-radius: 0;
}
.msg {
color: $color-black-second;
padding: 0 30px 68px 30px;
}
.title {
line-height: 60px;
}
.bbts {
background-color: #fff;
> div {
margin-top: 0;
height: 110px;
border-top: 1px solid #e1e1e1;
font-size: 34px;
color: #fff;
&:first-child {
-webkit-border-radius: 0;
}
&:last-child {
-webkit-border-radius: 0;
}
&.no {
margin-right: 0;
color: $color-black-second;
background-color: #f6f6f6;
&:active{
background-color: #fff;
}
}
&.yes {
background-color: $color-red;
font-weight: normal;
&:active{
background-color: rgba(248,31,52,0.5);
}
}
}
}
}
}
> .box-ct.signin {
$dialog-w: 620px;
> .box-bd {
position: relative;
width: $dialog-w;
min-height: 340px;
background-color: #fff;
padding: 30px;
> div {
@include box-v-c-c;
}
.msg {
font-size: 34px;
color: $color-black-second;
min-height: 200px;
text-align: center;
padding-top: 100px;
}
.plf {
.b {
@include active-default;
}
}
.no {
position: absolute;
top: 0;
left: 0;
width: 80px;
height: 80px;
background-color: #e1e1e1;
&:active {
background-color: $color-red;
}
}
}
}
> .box-ct.winfaceanalysis {
$dialog-w: 536px;
> .box-bd {
position: relative;
width: $dialog-w;
> div {
@include box-v-c-c;
position: absolute;
}
.no {
top: 0;
left: 0;
width: 100px;
height: 100px;
}
.share{
left: 0;
bottom: 0;
width: 100%;
height: 200px;
}
}
}
}
}
/* end deja */
================================================
FILE: app/templates/app/scss/_msgbox.scss
================================================
@charset "UTF-8";
$ios-border-radius: 30px;
/* default */
.msgbox {
position: fixed;
z-index: 999;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: none;
background-color: transparent;
word-break: break-all;
overflow: hidden;
&.show {
display: -webkit-box;
> .box-mask {
-webkit-animation-name: MicroMask;
@include animated-1s;
-webkit-animation-timing-function: linear;
-webkit-animation-duration: 250ms;
}
}
> .box-mask, > .msgbox-ct {
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
> .box-mask {
position: absolute;
background-color: #000;
opacity: 0;
}
> .msgbox-ct {
position: relative;
-webkit-transform: translateZ(0);
background-color: transparent;
display: -webkit-box;
-webkit-box-pack: center;
> .msgbox-bd {
position: relative;
@include box-v-c-c;
width: $layout-with;
height: 100%;
> .box-ct {
display: -webkit-box;
font-size: 40px;
color: #f6f6f6;
-webkit-animation-name: MicroPopUp;
@include animated-1s;
-webkit-animation-duration: 250ms;
> .box-bd {
-webkit-transform: translateZ(0);
> div {
width: 100%;
height: 100%;
}
}
&.absolute{
position: absolute;
}
}
> .box-ct.dialog {
$dialog-w: $layout-with * 0.72;
color: #000;
> .box-bd {
width: $dialog-w;
overflow: hidden;
-webkit-border-radius: $ios-border-radius;
> div {
@include box-v;
}
.content {
padding-top: 30px;
background-color: rgba(225, 225, 225, .9);
-webkit-border-radius: $ios-border-radius $ios-border-radius 0 0;
}
.title {
@include box-h-c-c;
font-size: 36px;
}
.msg {
font-size: 28px;
padding: 0 30px 30px 30px;
line-height: 36px;
@include box-v-c-c;
.simley {
margin-left: 40px;
-webkit-animation-name: bounceIn;
@include animated-1s;
-webkit-animation-duration: .6s;
}
> p {
width: 100%;
@include box-h-t-l;
&.c {
text-align: center;
@include box-h-c-c;
}
}
}
.bbts {
@include box-h-c-c;
> div {
&:active {
background-color: #d0d0d0;
}
@include box-h-c-c;
-webkit-box-flex: 1;
font-size: 36px;
color: #007aff;
margin-top: 1px;
padding: 20px 0;
height: 88px;
background-color: rgba(225, 225, 225, .9);
&:first-child {
-webkit-border-radius: 0 0 0 $ios-border-radius;
}
&:last-child {
-webkit-border-radius: 0 0 $ios-border-radius 0;
}
&.no {
margin-right: 1px;
}
&.yes {
font-weight: bold;
}
}
}
}
}
> .box-ct.menu {
$dialog-w: $layout-with * 0.95;
$option-h: 115px;
//position: fixed;
left: ($layout-with - $dialog-w)/2;
bottom: 0px;
color: #000;
-webkit-animation-name: slideInUp;
&.close{
-webkit-animation-name: slideOutDown;
}
> .box-bd {
width: $dialog-w;
padding-bottom: 18px;
> div {
@include box-v;
}
.opt {
&:active {
background-color: #e9e9e9;
}
@include box-h-c-c;
-webkit-box-flex: 1;
font-size: 36px;
color: #007aff;
padding: 20px 0;
height: $option-h;
background-color: #f6f7f8;
&.msg{
height: auto;
min-height: $option-h;
padding: 20px;
color: #8f8f8f;
font-size: 28px;
text-align: center;
&:active{
background-color: #f6f7f8;
}
}
&.no {
margin-top: 18px;
background-color: #fff;
-webkit-border-radius: $ios-border-radius;
font-weight: bold;
&:active{
background-color: #f5f5f5;
}
}
&.highlight{
color: #f1442c;
}
}
.options{
-webkit-border-radius: $ios-border-radius;
overflow: hidden;
> div {
margin-top: 1px;
&:first-child{
-webkit-border-radius: $ios-border-radius $ios-border-radius 0 0;
margin-top: 0;
}
}
}
}
}
> .box-ct.loading {
$dialog-w: 240px;
> .box-bd {
padding-top: 50px;
width: $dialog-w;
height: 240px;
background-color: rgba(225, 225, 225, .9);
-webkit-border-radius: 10px;
> div {
@include box-v-c-c;
}
.msg {
font-size: 34px;
color: #000;
margin-top: 40px;
}
}
}
}
}
}
/* end default */
/*debug-msgbox-android.scss*/
@import "msgbox-android.scss";
/*end debug-msgbox-android.scss*/
/*debug-msgbox-deja.scss*/
@import "msgbox-deja.scss";
/*end debug-msgbox-deja.scss*/
================================================
FILE: app/templates/app/scss/_section-download.scss
================================================
@charset "UTF-8";
.section-download{
@include box-h-c-c;
padding: 20px;
background-color: #fdfdfd;
.sd-logo{
width: 114px;
height: 114px;
img{
width: 100%;
height: 100%;
}
}
.sd-info{
@include box-v;
padding: 23px 20px;
-webkit-box-flex: 1;
.name{
font-size: 36px;
font-weight: bold;
}
.dest{
font-size: 28px;
color: $color-black-third;
}
}
}
================================================
FILE: app/templates/app/scss/_slide.scss
================================================
@charset "UTF-8";
.slide {
position: relative;
}
.slide > * {
position: absolute;
width: 100%;
height: 100%;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.slide > *:not(.selected):not([animate]) {
display: none !important;
}
.slide-from-right > *, .slide-from-bottom > * {
-webkit-transition: -webkit-transform .6s cubic-bezier(0.4, 0, 0.2, 1);
transition: transform .6s cubic-bezier(0.4, 0, 0.2, 1);
}
.slide-from-right > .selected ~ [animate]:not(.selected) {
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
.slide-from-right > [animate]:not(.selected) {
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
.slide-from-bottom > .selected ~ [animate]:not(.selected) {
-webkit-transform: translateY(100%);
transform: translateY(100%);
}
.slide-from-bottom > [animate]:not(.selected) {
-webkit-transform: translateY(-100%);
transform: translateY(-100%);
}
.slide-from-right > .selected, .slide-from-bottom > .selected {
-webkit-transform: none;
transform: none;
}
================================================
FILE: app/templates/app/scss/_sprites.scss
================================================
.icon {
background-image: url('../images/sprites.png');
}
.icon-ic_s_close_pre_2x {
background-position: -4px -4px;
width: 30px;
height: 30px;
}
.icon-ic_s_close_nor_2x {
background-position: -4px -42px;
width: 30px;
height: 30px;
}
.icon-bt_google {
background-position: -4px -80px;
width: 180px;
height: 60px;
}
.icon-bt_Appbutton {
background-position: -4px -148px;
width: 180px;
height: 60px;
}
.icon-btn_fb_login {
background-position: -4px -216px;
width: 460px;
height: 95px;
}
.icon-ic_url_copy_pre_2x {
background-position: -4px -319px;
width: 120px;
height: 120px;
}
.icon-ic_about_ins_pre {
background-position: -4px -447px;
width: 120px;
height: 120px;
}
.icon-ic_about_tw_nor {
background-position: -4px -575px;
width: 120px;
height: 120px;
}
.icon-ic_about_tw_pre {
background-position: -4px -703px;
width: 120px;
height: 120px;
}
.icon-ic_about_fb_nor {
background-position: -4px -831px;
width: 120px;
height: 120px;
}
.icon-ic_about_fb_pre {
background-position: -4px -959px;
width: 120px;
height: 120px;
}
.icon-ic_url_copy_nor_2x {
background-position: -4px -1087px;
width: 120px;
height: 120px;
}
.icon-ic_about_ins_nor {
background-position: -4px -1215px;
width: 120px;
height: 120px;
}
.icon-logo {
background-position: -4px -1343px;
width: 140px;
height: 140px;
}
.icon-ic_vote_skip_nor_2x {
background-position: -4px -1491px;
width: 154px;
height: 154px;
}
.icon-ic_vote_skip_pre_2x {
background-position: -4px -1653px;
width: 154px;
height: 154px;
}
.icon-ic_vote_vote_nor_2x {
background-position: -4px -1815px;
width: 154px;
height: 154px;
}
.icon-ic_vote_vote_pre_2x {
background-position: -4px -1977px;
width: 154px;
height: 154px;
}
.icon-pic_vote_good_2x {
background-position: -4px -2139px;
width: 290px;
height: 240px;
}
.icon-pic_vote_skip_2x {
background-position: -4px -2387px;
width: 290px;
height: 240px;
}
================================================
FILE: app/templates/app/scss/_tooltip.scss
================================================
@charset "UTF-8";
$tooltip-color-default: #fff;
.tooltip {
position: fixed;
z-index: 90;
left: 0;
width: 100%;
display: none;
background-color: transparent;
&.show {
@include box-h-c-c;
}
>.tooltip__ct{
width: $layout-with;
padding-top: 20px;
padding-bottom: 20px;
overflow-x: hidden;
>.tooltip__bd{
position: relative;
display: inline-block;
top: 0;
padding: 20px;
background-color: $tooltip-color-default;
font-size: 30px;
color: $color-black-second;
border: 1px solid rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.3);
-webkit-border-radius: 5px;
@include gpu-accelerate;
&.animated{
@include animated-1s;
-webkit-animation-duration: 350ms;
&.fadeIn{
-webkit-animation-name: fadeIn;
}
&.flipInY{
-webkit-animation-name: flipInY;
}
&.flipInX{
-webkit-animation-name: flipInX;
}
&.slideInUp{
-webkit-animation-name: slideInUp;
}
&.slideInDown{
-webkit-animation-name: slideInDown;
}
&.zoomIn{
-webkit-animation-name: zoomIn;
}
&.fadeInLeft{
-webkit-animation-name: fadeInLeft;
}
&.fadeInRight{
-webkit-animation-name: fadeInRight;
}
&.fadeInUp{
-webkit-animation-name: fadeInUp;
}
&.fadeInDown{
-webkit-animation-name: fadeInDown;
}
&.fadeOut{
-webkit-animation-name: fadeOut;
}
}
>.tooltip__content{
text-align: center;
}
>.tooltip__arrow{
position: absolute;
background-color: $tooltip-color-default;
width: 16px;
height: 16px;
overflow: hidden;
@include gpu-accelerate;
>div{
width: 32px;
height: 32px;
border: 1px solid rgba(0, 0, 0, 0.3);
}
&.left{
left: -9px;
-webkit-transform: rotate(-45deg);
}
&.right{
right: -9px;
-webkit-transform: rotate(135deg);
}
&.top{
top: -9px;
-webkit-transform: rotate(45deg);
}
&.bottom{
bottom: -9px;
-webkit-transform: rotate(-135deg);
}
}
}
}
&.clear{
>.tooltip__ct{
>.tooltip__bd{
background-color: transparent;
color: $tooltip-color-default;
border: 0;
-webkit-box-shadow: none;
-webkit-border-radius: 0;
>.tooltip__arrow {
display: none;
}
}
}
}
//theme
&.red{
>.tooltip__ct{
>.tooltip__bd{
background-color: $color-red;
color: $tooltip-color-default;
border: 0;
-webkit-box-shadow: none;
-webkit-border-radius: 0;
>.tooltip__arrow {
background-color: $color-red;
>div {
border: 0;
}
}
}
}
}
&.black{
font-family: "Segoe Print",Roboto, HelveticaNeue, Helvetica, Arial, sans-serif;
>.tooltip__ct{
>.tooltip__bd{
//background-color: rgba(38,39,41,0.9);
background-color: $color-black-fourth;
color: #fff;
border: 0;
-webkit-box-shadow: none;
-webkit-border-radius: 0;
>.tooltip__arrow {
//background-color: rgba(38,39,41,0.9);
background-color: $color-black-fourth;
>div {
border: 0;
}
}
}
}
}
}
================================================
FILE: app/templates/app/scss/_util.scss
================================================
@charset "UTF-8";
.ellipsis {
text-overflow: ellipsis;
display: block;
white-space: nowrap;
overflow: hidden;
}
.clearfix::before,
.clearfix::after {
content: "";
display: table;
}
.clearfix::after {
clear: both;
}
.fix-break-word, p {
@include blank-bg;
background-color: transparent;
word-break: break-all;
// Non standard for webkit
word-break: break-word;
-webkit-hyphens: auto;
hyphens: auto;
}
.hide {
display: none !important;
}
.uppercase {
text-transform: uppercase;
}
img{
&.lazy{
opacity: 0;
//transition: opacity .3s ease-in;
min-height: 1px;
min-width: 1px;
}
&.lazy[src]:not(.animated){
opacity: 1;
}
&.lazy--loaded,&+.lazy__real{
&.animated{
@include animated-1s;
-webkit-animation-name: fadeIn;
-webkit-animation-duration: .3s;
}
}
&.lazy__virtual{
opacity: 0 !important;
&+.lazy__real{
display: none;
}
&.lazy--loaded{
display: none;
&+.lazy__real{
display: inherit;
}
}
}
&.fix-space{
display: block;
}
}
.img-loading-placeholder{
background: url(../images/loading_logo_2x.png) 50% 50% no-repeat;
}
.default-active {
@include active-default;
}
.ripple-active {
@include active-ripple;
}
.disabled-select {
@include disabled-select;
}
.disabled-select-all {
@include disabled-select-all;
}
================================================
FILE: app/templates/app/scss/_value.scss
================================================
@charset "UTF-8";
/*size*/
$layout-with: _VIEWPORT_WIDTH_;/*see viewport:viewport package.json*/
/*end size*/
/*color*/
$color-black: #2f2f2f;
$color-black-second: #414141;
$color-black-third: #818181;
$color-black-fourth: #262729;
$color-gray: #b5b7b6;
$color-gray-second: #cecece;
$color-gray-third: #eaeaea;
$color-gray-fourth: #e1e1e1;
$color-red: #f81f34;
$color-blue: #71b0ea;
/*end color*/
$active-opacity: .8;
================================================
FILE: app/templates/app/scss/_view-home.scss
================================================
@charset "UTF-8";
.view-home {
width: 100%;
min-height: 100%;
background-color: #35161f;
font-size: 38px;
.main {
@include box-h-c-c;
padding: 200px 30px;
}
}
================================================
FILE: app/templates/app/scss/_view-user.scss
================================================
@charset "UTF-8";
.view-user {
width: 100%;
background-color: #fff;
color: #292929;
.users {
@include box-v-c-c;
padding: 50px 30px;
.list {
padding: 50px;
}
}
}
================================================
FILE: app/templates/app/scss/_view.scss
================================================
body > .view {
width: 100%;
visibility: hidden;
display: none;
&.animated {
@include animated-1s;
-webkit-animation-fill-mode: none; /*transform的动效会使当前view里fixed的元素将无效*/
-webkit-animation-name: MicroBounceOut;
-webkit-animation-duration: 350ms;
}
&.show {
visibility: visible !important;
display: block !important;
}
}
/*debug-view-home.scss*/
@import "view-home.scss";
/*end debug-view-home.scss*/
/*debug-view-user.scss*/
@import "view-user.scss";
/*end debug-view-user.scss*/
================================================
FILE: app/templates/app/scss/styles.scss
================================================
@charset "UTF-8";
/*_value.scss*/
@import "value.scss";
/*end _value.scss*/
/*_mixin.scss*/
@import "mixin.scss";
/*end _mixin.scss*/
/*_util.scss*/
@import "util.scss";
/*end _util.scss*/
/*_box.scss*/
@import "box.scss";
/*end _box.scss*/
/*_fonts.scss*/
@import "fonts.scss";
/*end _fonts.scss*/
/*_common.scss*/
@import "common.scss";
/*end _common.scss*/
/*_animate.scss*/
@import "animate.scss";
/*end _animate.scss*/
/*_icon.scss*/
@import "icon.scss";
/*end _icon.scss*/
/*_components.scss*/
@import "components.scss";
/*end _components.scss*/
/*_header.scss*/
@import "header.scss";
/*end _header.scss*/
/*_list.scss*/
@import "list.scss";
/*end _list.scss*/
/*_footer.scss*/
@import "footer.scss";
/*end _footer.scss*/
/*_view.scss*/
@import "view.scss";
/*end _view.scss*/
================================================
FILE: app/templates/app/src/app/App.js
================================================
//require('util/AppCache');
require('lib/zepto');
require('lib/Core');
require('app/resources/i18n');
var BasicController = require('app/controller/Controller');
var HomeController = require('app/controller/HomeController');
var UserController = require('app/controller/UserController');
//__INSERT_POINT__ Don't delete!!
function App() {
var params = Core.localParam(),
standalone = params.search['standalone'];//如果带此参数,初始页非首页的浏览器历史返回将不会回首页
setTimeout(function () {
//Core.Router.init(standalone?'':'/home/');
Core.Router.init();
}, 50);
}
window.App = new App;
================================================
FILE: app/templates/app/src/app/controller/Controller.js
================================================
var Actions = require('app/resources/Actions');
var ThirdVendor = require('util/ThirdVendor');
var BasicModel = require('app/model/Model');
var BasicView = require('app/view/View');
function Controller() {
this.models = {
Basic: BasicModel
};
this.views = {
Basic: BasicView
};
//所有视图初始化前,需要获得客户端的用户登录信息
//Core.Router.onReady(onUserinfo);
Core.Router.onChanged(onViewChanged);
var CTRL = this,
isApp = Core.NativeBridge.isApp(),
params = Core.localParam(),
_userid = params.search['userid'],
_sig = params.search['sig'];
///*Todo: debug user
_userid && CTRL.models.Basic.setUserId(_userid);
_sig && CTRL.models.Basic.setUserSig(_sig);
//*/
//更新数据缓存时间
Core.Event.on('resetModelUpdateTimeout', CTRL.models.Basic.modelUpdate.timer.resetAll);
//通过API名称,调用客户API
Core.Event.on('appAPI', appAPI);
//分享
Core.Event.on('share', appShare);
//去下载
Core.Event.on('appDownload', redirectToDownload);
//直接到Store去下载
Core.Event.on('openAppInStore', downloadDejaInApp);
//去更新
Core.Event.on('appUpdate', appUpdate);
//去deja.me
Core.Event.on('redirectToDejame', redirectToDejame);
//跳转出商城
Core.Event.on('redirect', redirectToPage);
//去登录
Core.Event.on('login', onLogin);
//去WEB登录
Core.Event.on('webLogin', webLogin);
//去App登录
Core.Event.on('appLogin', appLogin);
//从App获取用户信息
Core.Event.on('appUserinfo', onUserinfo);
//去反馈
Core.Event.on('feedback', onFeedback);
//复制文本
Core.Event.on('appCopyText', appCopyText);
//更新标题
Core.Event.on('appModifyTitle', appModifyTitle);
//修改右上角功能菜单
Core.Event.on('appActionbutton', appActionButton);
//修改右上角功能菜单成默认
Core.Event.on('appActionDefaultButton', appActionDefaultButton);
//修改右上角功能菜单成分享
Core.Event.on('appActionShareButton', appActionShareButton);
//修改右上角功能菜单成Filter
Core.Event.on('appActionFilterButton', appActionFilterButton);
//修改右上角功能菜单成add
Core.Event.on('appActionAddButton', appActionAddButton);
//注册webview关闭事件
Core.Event.on('appOnUnload', appOnUnload);
//关闭webview
Core.Event.on('appCloseWebView', appCloseWebView);
//Update Profile
Core.Event.on('appUpdateProfile', appUpdateProfile);
//tab 切换
Core.Event.on('switchTab', switchTab);
//触发暂时性动画
Core.Event.on('trigerAnimate', trigerAnimate);
//text 收展
Core.Event.on('toggleTextSectionExpand', toggleTextSectionExpand);
//统计
Core.Event.on('analytics', analytics);
//滚动到顶部
Core.Event.on('scrollTop', scrollTop);
//back
Core.Event.on('back', function (action) {
Core.Router.back(action || -1);
});
function analytics(params, title) {
setTimeout(function () {
var url = Actions.analytics + '?devevent=1' + (params ? ('&' + params) : '');
//android和iOS
if ($.os.ios && !$.os.android) {
url += '&ios';
} else if ($.os.android) {
url += '&android';
}
if (ThirdVendor) {
url += '&plf=' + ThirdVendor.code;
}
if (CTRL.models.Basic.isLogined()) {
url += '&logined';
}
url += '&t=' + (new Date().getTime());
Core.Navigator.protocol(url, true);
}, 0);
}
function scrollTop() {
var top = Math.min(Math.min(window.pageYOffset, document.documentElement.scrollTop || document.body.scrollTop), window.scrollY),
start = top,
to = 0,
timer = 0,
change = to - start,
currentTime = 0,
increment = 20,
duration = 500;
(function animloop() {
// increment the time
currentTime += increment;
if (start < 2 || CTRL.views.Basic.GlobalTouch.touched || currentTime > duration) {
if (start < 2) {
window.scrollTo(0, 1);
}
cancelRequestAnimFrame(timer);
return;
}
window.scrollTo(0, Math.easeInOutQuad(currentTime, start, change, duration));
timer = requestAnimFrame(animloop);
})();
}
function onViewChanged() {
appModifyTitle();
CTRL.views.Basic.msgbox.hideLoading();
}
function onUserinfo() {
if (isApp) {
Core.NativeBridge.userInfo(null, function (rs) {
CTRL.models.Basic.setAppUserMeta(rs);
if (rs && !!rs.userid) {
if (CTRL.models.Basic.verifyLoginCookie() && CTRL.models.Basic.verifyLoginCookieTimeout(30)) {
Core.Router.run();
} else {
rs.sig ? appLogin() : appAnonymousLogin();
}
} else {
Core.Router.run();
}
});
//Core.NativeBridge.device(function(rs){
// if(rs){
// CTRL.models.Basic.setNativeBridgeDeviceMeta(rs);
// }
//});
} else {
Core.Router.run();
}
}
function onLogin(arg, msg, callback) {
if (isApp) {
appLogin(callback);
} else {
CTRL.views.Basic.msgbox.showSignin({
msg: msg,
yesCallback: function (plf) {
webLogin(Actions.main + (arg || ''), null, plf);
}
});
//CTRL.views.Basic.msgbox.showDownload({
// yesCallback: function () {
// redirectToDownload(Actions.main + (arg || ''));
// }
//});
}
}
function onFeedback(email) {
Core.Navigator.protocol('mailto:' + (email || 'mozat@mozat.com?subject=Suggestion'), true);
}
function switchTab(el, tabs, tabContents) {
if (!tabs || !tabContents) {
return;
}
var isClicked = !!el;
el = el || tabs[0];
for (var i = 0; i < tabs.length; i++) {
if (tabs[i] == el) {
tabs[i].classList.add('on');
trigerAnimate(tabContents.eq(i));
tabContents[i] && tabContents[i].classList.add('show');
isClicked && Core.Event.trigger('analyticsCurView', 'tab=' + i);
} else {
tabs[i].classList.remove('on');
tabContents[i] && tabContents[i].classList.remove('show');
}
}
Core.Event.trigger('analyticsCurView');
}
function trigerAnimate(el, classname, timeout) {
if (!el) {
return;
}
classname = classname || 'animated';
timeout = timeout || 1200;
el.animTimer && clearTimeout(el.animTimer);
el.addClass(classname);
el.animTimer = setTimeout(function () {
el.removeClass(classname);
}, timeout);
}
function toggleTextSectionExpand(el) {
el && el.classList.toggle('expand');
}
function webLogin(surl, furl, pf) {
var murl = window.location.href;
surl = surl || murl;
furl = furl || murl;
pf = pf || 'fb';
redirectToPage(Actions.login
.replace('{SURL}', encodeURIComponent(surl))
.replace('{FURL}', encodeURIComponent(furl))
.replace('{PF}', pf));
}
function appLogin(callback, subProtocol) {
Core.NativeBridge.login(null, function (rs) {
if (rs) {
CTRL.models.Basic.saveLoginCookieTimeout();
CTRL.models.Basic.setAppUserMeta(rs);
if (callback) {
callback();
} else {
Core.Router.run();
}
}
}, subProtocol);
}
function appAnonymousLogin(callback) {
appLogin(callback, '?anonymous=1')
}
function appUpdate(msg, force) {
redirectToApp(function () {
CTRL.views.Basic.msgbox.showDialog({
msg: msg || 'Please up to date your App',
noText: force ? null : 'Close',
yesText: 'Update',
yesCallback: function () {
downloadDejaInApp();
}
});
});
}
function appShare(callback, plf) {
redirectToApp(function () {
var fn = Core.NativeBridge['share' + (plf ? ('_' + plf) : '')];
fn && fn(null, callback);
});
}
function appCopyText(text) {
if (isApp) {
Core.NativeBridge.copy(text);
}
}
function appModifyTitle(title) {
title = title || document.title;
document.title = title;
if (isApp) {
Core.NativeBridge.modifytitle(title);
}
}
function appActionButton(name, callback) {
if (isApp) {
Core.NativeBridge.updateBarButton(name, !Core.isDebug && callback);
}
}
function appActionShareButton() {
appActionButton('share');
}
function appActionFilterButton(callback) {
appActionButton('filter', callback);
}
function appActionAddButton(callback) {
appActionButton('add', callback);
}
function appActionDefaultButton() {
appActionButton('', function () {
});
}
function appOnUnload(callback) {
if (isApp) {
Core.NativeBridge.set_before_for_unload(callback);
}
}
function appCloseWebView() {
if (isApp) {
Core.NativeBridge.closeweb();
}
}
/**
* @param subProtocol String creationLike,creationDelete,productLike,follow
*/
function appUpdateProfile(subProtocol) {
appAPI('updateProfile', null, null, subProtocol);
}
/**
* dejafashion://name/subProtocol
* window.__dejafashion_data_name = data;
* window.__dejafashion_after_name = callback;
*/
function appAPI(name, data, callback, subProtocol, redirect) {
if (isApp) {
Core.NativeBridge.trigger.apply(null, arguments);
} else if (redirect) {
var proto = [name];
subProtocol && proto.push(subProtocol);
redirectToDownload(null, true, Actions.dejafashionSchema + proto.join('/'));
}
}
function downloadDejaInApp() {
var url = Actions.dejaAppAndroid;
if ($.os.ios && !$.os.android) {
url = Actions.dejaAppIos;
}
window.location = url;
}
function redirectToDejame() {
redirectToPage(Actions.dejame);
}
//打开客户端原生视图
function redirectToApp(callback, link) {
if (isApp) {
callback && callback();
} else {
CTRL.views.Basic.msgbox.showDownload({
yesCallback: function () {
redirectToDownload(link || window.location.href);
}
});
}
}
/**
* open a web site in app,or just op
* @param link
* @param autoopen
* @param schema
*/
function redirectToDownload(link, autoopen, schema) {
link = !!link && link != '0' ? ('#url=dejafashion://web/' + link) : '';
link = !!schema ? ('#url=' + schema) : link;
redirectToPage(Actions.dejaDwonloadBridge + (autoopen ? '?autoopen=1' : '') + link);
}
function redirectToPage(link) {
if (link) {
!(/__NativeBridge_target/g.test(link)) && appActionDefaultButton();
window.location = link;
}
}
}//end Controller
module.exports = new Controller;
================================================
FILE: app/templates/app/src/app/controller/HomeController.js
================================================
var Actions = require('../resources/Actions');
var BasicModel = require('app/model/Model');
var BasicView = require('app/view/View');
var HomeView = require('app/view/HomeView');
function HomeController() {
this.models = {
Basic: BasicModel
}
this.views = {
Basic: BasicView,
Home: HomeView
};
var CTRL = this,
viewNames,
curViewId = '',
viewHomeQuery = {};
viewNames = {
'home': 'Home'
}
Core.Router
.onUnsubscribed(onViewUnnamed,unViewUnnamed)
.subscribe('/home/', onViewHome, unViewHome);
//统计视图
Core.Event.on('analyticsCurView', analyticsCurView);
//forwardHome
Core.Event.on('forwardHome', forwardHome);
function unViewUnnamed() {
unViewHome();
}
function unViewHome() {
CTRL.views.Home.hide();
}
function onViewUnnamed(req) {
onViewHome(req);
Core.Event.trigger('analytics');
}
function onViewHome(req) {
curViewId = 'home';
viewHomeQuery = req.query;
CTRL.views.Home.show();
//追加统计
analyticsCurView();
}
function forwardHome(arg) {
Core.Router.forward('/home/' + (arg || ''));
}
function analyticsCurView(params, title) {
if (!Core.Router.currentMatch(['/home/', Core.Router.getUnsubscribedAction()])) {
return;
}
params = params ? ('&' + params) : '';
title = title || viewNames[curViewId] || document.title;
Core.Event.trigger('analytics', 'viewid=' + curViewId + params, title);
}
}
module.exports = new HomeController;
================================================
FILE: app/templates/app/src/app/controller/UserController.js
================================================
var Actions = require('../resources/Actions');
var BasicModel = require('app/model/Model');
var UserModel = require('app/model/UserModel');
var BasicView = require('app/view/View');
var UserView = require('app/view/UserView');
function UserController() {
this.models = {
Basic: BasicModel,
User: UserModel
}
this.views = {
Basic: BasicView,
User: UserView
};
var CTRL = this,
viewNames,
curViewId = '',
viewUserQuery = {};
viewNames = {
'user': 'User'
}
Core.Router.subscribe('/user/', onViewUser, unViewUser);
//统计视图
Core.Event.on('analyticsCurView', analyticsCurView);
//forwardUser
Core.Event.on('forwardUser', forwardUser);
function unViewUser() {
CTRL.views.User.hide();
}
function onViewUser(req) {
curViewId = 'user';
viewUserQuery = req.query;
CTRL.views.User.show();
CTRL.views.Basic.msgbox.hideLoading();
CTRL.models.User.user.request({id: viewUserQuery.userid},afterRequestUser);
//追加统计
analyticsCurView();
}
function afterRequestUser(success) {
CTRL.views.Basic.msgbox.hideLoading();
if (success) {
CTRL.models.User.user.timer.update();
} else {
CTRL.views.Basic.msgbox.showFailed();
}
}
function forwardUser(arg) {
Core.Router.forward('/user/' + (arg || ''));
}
function analyticsCurView(params, title) {
if (!Core.Router.currentMatch(['/user/'])) {
return;
}
params = params ? ('&' + params) : '';
title = title || viewNames[curViewId] || document.title;
Core.Event.trigger('analytics', 'viewid=' + curViewId + params, title);
}
}
module.exports = new UserController;
================================================
FILE: app/templates/app/src/app/model/Model.js
================================================
var RequestHelper = require('app/model/RequestHelper');
var Actions = require('app/resources/Actions');
var Mdl = Core.Class.Model,
lcStorage = Core.localStorage;
function Model() {
var MODEL = this,
userId, udid, appUserMeta,sig,
loginCookieTimerPrefix = 'loginCookieTimer_';
this.getCookie = function (sKey) {
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
}
this.setCookie = function (name, value, days) {
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toGMTString();
}
else var expires = "";
document.cookie = name + "=" + value + expires + "; path=/";
}
//校验登录 cookies
this.verifyLoginCookie = function () {
var uid = this.getCookie('uid');
this.setUserId(uid);
return uid;
}
this.saveLoginCookieTimeout = function () {
var key = loginCookieTimerPrefix + this.getUserId();
lcStorage.set(key, new Date().getTime());
}
//校验 cookies 有效期,这里用 1 天
this.verifyLoginCookieTimeout = function (minutes) {
var key = loginCookieTimerPrefix + this.getUserId(),
last = lcStorage.get(key) || 0;
minutes = minutes || 1 * 60 * 24 * 1;
return ( (new Date().getTime()) - last ) < minutes * 60 * 1000;
}
this.setUdId = function (id) {
udid = id;
}
this.getUdId = function () {
return udid;
}
this.setUserId = function (id) {
userId = id || userId;
}
this.getUserId = function () {
return userId || (appUserMeta && appUserMeta.userid) || this.getCookie('uid');
}
this.getAppUserMeta = function () {
return appUserMeta;
}
this.setAppUserMeta = function (data) {
appUserMeta = data;
}
this.getUserSig = function () {
return sig || (appUserMeta && appUserMeta.sig) || this.getCookie('sig');
}
this.setUserSig = function (val) {
sig = val;
}
this.isLogined = function () {
return !!this.getUserId() && !!this.getUserSig();
}
//数据缓存更新
this.modelUpdate = new Mdl();
}
module.exports = new Model;
================================================
FILE: app/templates/app/src/app/model/RequestHelper.js
================================================
var getJSON = Core.RequestHandler.getJSON,
postJSON = Core.RequestHandler.postJSON,
JSONP = Core.RequestHandler.JSONP;
function request(action, data, callback, scope, options) {
options = options || {};
var __STORE_ID, conf;
data = data || {};
data._t = new Date().getTime();
__STORE_ID = data.__STORE_ID;
delete data.__STORE_ID;
conf = {
action: action,
data: data,
complete: function (data) {
if (data.success) {
scope && scope.set && scope.set(data.data, __STORE_ID);
}
callback && callback(data.success);
}
};
for (var name in options) conf[name] = options[name];
conf.action = action;
conf.data = data;
getJSON(conf);
}
function post(action, data, callback, scope, options) {
options = options || {};
var conf = {
action: action,
data: data,
contentType: options.contentType || "application/json;charset=utf-8",
complete: function (data) {
if (data.success) {
scope && scope.set && scope.set(data.data);
}
callback && callback(data.success);
}
};
for (var name in options) conf[name] = options[name];
conf.action = action;
conf.data = data;
postJSON(conf);
}
module.exports = {
getJSON: getJSON,
postJSON: postJSON,
JSONP: JSONP,
request: request,
post: post
};
================================================
FILE: app/templates/app/src/app/model/StoreHelper.js
================================================
var RequestHelper = require('app/model/RequestHelper');
function pagingStore(action, options) {
var option = {
isFromStore: false,
page: 0,
page_size: 20,
setWithStoreData: function (data) {
this.resetPage(data.__page);
this.set(data, data.__STORE_ID);
},
resetPage: function (storePage) {
if (storePage == undefined || storePage == null) {
this.isFromStore = false;
this.page = 0;
}
//reset page by history
else {
this.isFromStore = true;
this.page = storePage + 1;
}
},
request: function (data, callback) {
this.isFromStore = false;
data = data || {};
var _this = this;
var __STORE_ID;
__STORE_ID = data.__STORE_ID;
delete data.__STORE_ID;
data.page = this.page;
data.page_size = this.page_size;
RequestHelper.getJSON({
data: data,
action: action,
complete: function (data) {
if (data.success) {
_this.set(function (storeData) {
//set __STORE_ID's cache data
if (storeData) {
storeData.__page = _this.page;
storeData.end = data.data.end;
storeData.data = storeData.data.concat(data.data.data);
}
//set model's data
else {
storeData = data.data;
storeData.__page = _this.page;
}
return storeData;
}, __STORE_ID);
_this.page++;
}
callback && callback(data.success);
}
});
}
};
Core.Class.apply(option, options);
return new Core.Class.Model(option);
}
function requestStore(action, options) {
var option = {
request: function (data,callback) {
RequestHelper.request(action,data,callback,this);
}
};
Core.Class.apply(option, options);
return new Core.Class.Model(option);
}
function postStore(action, options) {
var option = {
post: function (data,callback) {
RequestHelper.post(action,data,callback,this);
}
};
Core.Class.apply(option, options);
return new Core.Class.Model(option);
}
function JSONPStore(action, options) {
var option = {
request: function(data, callback){
data = data || {};
var _this = this,
__STORE_ID = data.__STORE_ID,
callbackName;
callbackName = '__JSCB_'+Core.GUID(8);
data.callback = callbackName;
delete data.__STORE_ID;
window[callbackName] = function(data){
_this.set(data, __STORE_ID);
callback && callback(data);
}
RequestHelper.JSONP({
url: action,
data: data
});
}
};
Core.Class.apply(option, options);
return new Core.Class.Model(option);
}
function pagingJSONPStore(action, options) {
var option = {
isFromStore: false,
page: 0,
page_size: 20,
setWithStoreData: function (data) {
this.resetPage(data.__page);
this.set(data, data.__STORE_ID);
},
resetPage: function (storePage) {
if (storePage == undefined || storePage == null) {
this.isFromStore = false;
this.page = 0;
}
//reset page by history
else {
this.isFromStore = true;
this.page = storePage + 1;
}
},
request: function (data, callback) {
this.isFromStore = false;
data = data || {};
var _this = this,
__STORE_ID = data.__STORE_ID,
callbackName;
callbackName = '__JSCB_'+Core.GUID(8);
data.callback = callbackName;
delete data.__STORE_ID;
window[callbackName] = function(data){
_this.set(function (storeData) {
//set __STORE_ID's cache data
if (storeData) {
storeData.__page = _this.page;
storeData.data = storeData.data.concat(data.data.data);
}
//set model's data
else {
storeData = data;
storeData.__page = _this.page;
}
return storeData;
}, __STORE_ID);
_this.page++;
callback && callback(data);
}
data.page = this.page;
data.page_size = this.page_size;
RequestHelper.JSONP({
url: action,
data: data
});
}
};
Core.Class.apply(option, options);
return new Core.Class.Model(option);
}
module.exports = {
pagingStore: pagingStore,
requestStore: requestStore,
postStore: postStore,
JSONPStore: JSONPStore,
pagingJSONPStore: pagingJSONPStore
};
================================================
FILE: app/templates/app/src/app/model/UserModel.js
================================================
var StoreHelper = require('app/model/StoreHelper');
var Actions = require('app/resources/Actions');
var Basic = require('app/model/Model');
var Mdl = Core.Class.Model,
lcStorage = Core.localStorage;
function User() {
}
User.prototype.user = StoreHelper.requestStore(Actions.user);
User.prototype.userInfo = StoreHelper.JSONPStore(Actions.user);
module.exports = new User();
================================================
FILE: app/templates/app/src/app/resources/Actions.js
================================================
var thisPage = window.location.href
//注意,保留search 是为了避免微信自动追加的应用检测状态值
//.replace(window.location.search,'')
.replace(window.location.hash, '');
var thisPath = thisPage.substring(0, thisPage.lastIndexOf('/') + 1);
///*official
var Actions = {
user: Core.localHost + '/user/list.php',
login: Core.localHost + '/account/login_third?success={SURL}&fail={FURL}&pf={PF}',
main: thisPath + 'index.html',
analytics: thisPath + 'analytics.html',
dejame: 'http://deja.me/u/XPKab9',
dejaAppAndroid: 'http://deja.me/u/XPKab9',
dejaAppIos: 'http://deja.me/u/fzb1KO',
dejaDwonloadBridge: 'http://m.deja.me/bridge/',
dejaShareLogo: thisPath + 'resources/images/deja_icon_ios_228.png'
}
//*/
///_DEBUG_*Todo: debug actions
var Actions = {
user: 'data/user.json',
login: Core.localHost + '/account/login_third?success={SURL}&fail={FURL}&pf={PF}',
main: thisPath + 'index.html',
analytics: thisPath + 'analytics.html',
dejame: 'http://deja.me/u/XPKab9',
dejaAppAndroid: 'http://deja.me/u/XPKab9',
dejaAppIos: 'http://deja.me/u/fzb1KO',
dejaDwonloadBridge: 'http://m.deja.me/bridge/',
dejaShareLogo: thisPath + 'resources/images/deja_icon_ios_228.png'
}
//*/
module.exports = Actions;
================================================
FILE: app/templates/app/src/app/resources/Audios.js
================================================
var Audios = {}
module.exports = Audios;
================================================
FILE: app/templates/app/src/app/resources/i18n/en_US/Msgbox.js
================================================
module.exports = {
ok: 'OK',
no: 'Cancel',
sure: 'Sure',
loading: 'Loading...',
submitting: 'Submitting...'
}
================================================
FILE: app/templates/app/src/app/resources/i18n/en_US/index.js
================================================
var Msgbox = require('./Msgbox');
var en_US = {
Msgbox: Msgbox
}
module.exports = en_US;
================================================
FILE: app/templates/app/src/app/resources/i18n/index.js
================================================
var en_US = require('./en_US');
var zh_CN = require('./zh_CN');
var langs = {
zh_CN: zh_CN
}
//https://github.com/jquery-i18n-properties/jquery-i18n-properties/blob/master/jquery.i18n.properties.js
function getLangName(lang) {
if (!lang || lang.length < 2) {
lang = (navigator.languages) ? navigator.languages[0]
: (navigator.language || navigator.userLanguage /* IE */ || 'en');
}
lang = lang.toLowerCase();
lang = lang.replace(/-/,"_"); // some browsers report language as en-US instead of en_US
if (lang.length > 3) {
lang = lang.substring(0, 3) + lang.substring(3).toUpperCase();
}
return lang;
}
function i18n() {
this.getLangName = getLangName;
}
i18n.prototype = en_US;
function createI18n(lang) {
var lang = langs[lang];
if(lang) {
Core.extend(i18n, lang);
}else{
lang = i18n;
}
return new lang;
}
var oI18n = createI18n(getLangName());
window.i18n = oI18n;
module.exports = oI18n;
================================================
FILE: app/templates/app/src/app/resources/i18n/zh_CN/Msgbox.js
================================================
module.exports = {
ok: '好的',
no: '取消',
sure: '确定',
loading: '正在加载...',
submitting: '正在提交...'
}
================================================
FILE: app/templates/app/src/app/resources/i18n/zh_CN/index.js
================================================
var Msgbox = require('./Msgbox');
function zh_CN() {
//extend from super
zh_CN.superclass.constructor.call(this);
this.Msgbox = Msgbox;
}
module.exports = zh_CN;
================================================
FILE: app/templates/app/src/app/view/HomeView.js
================================================
var BasicView = require('app/view/View');
var BasicModel = require('app/model/Model');
function HomeView() {
this.models = {
Basic: BasicModel
}
this.viewCls = 'view-home';
this._BasicView = BasicView;
var VIEW = this,
isApp = Core.NativeBridge.isApp(),
Tpl, els,
tap = VIEW._BasicView.tapEvent;
//model listeners
function initEls() {
if(els){return;}
els = VIEW._BasicView.getElements(VIEW.viewCls);
bindEvent();
}//end initEls
function initTpls(){
if(Tpl){return;}
Tpl = Tpl || VIEW._BasicView.getTemplates(VIEW.viewCls);
}
function initResources() {
initEls();
initTpls();
}
this.getEls = function () {
initEls();
return els;
}
this.getTpls = function(){
initTpls();
return Tpl;
}
function bindEvent() {
}//end bindEvent
this.show = function () {
initResources();
if (!els.main.hasClass('show')) {
Core.Event.trigger('trigerAnimate', els.main);
VIEW._BasicView.show(VIEW.viewCls);
}
}
this.hide = function () {
if (!els) {
return;
}
}
function render(data) {
initResources();
}//end render
}//end View
module.exports = new HomeView();
================================================
FILE: app/templates/app/src/app/view/UserView.js
================================================
var BasicView = require('app/view/View');
var BasicModel = require('app/model/Model');
var UserModel = require('app/model/UserModel');
function UserView() {
this.models = {
Basic: BasicModel,
User: UserModel
}
this.viewCls = 'view-user';
this._BasicView = BasicView;
var VIEW = this,
isApp = Core.NativeBridge.isApp(),
Tpl, els,
tap = VIEW._BasicView.tapEvent;
//model listeners
VIEW.models.User.user.updated(render);
function initEls() {
if(els){return;}
els = VIEW._BasicView.getElements(VIEW.viewCls,function(){
return {
back: this.main.find('.back')
}
});
bindEvent();
}//end initEls
function initTpls(){
if(Tpl){return;}
Tpl = Tpl || VIEW._BasicView.getTemplates(VIEW.viewCls);
}
function initResources() {
initEls();
initTpls();
}
this.getEls = function () {
initEls();
return els;
}
this.getTpls = function(){
initTpls();
return Tpl;
}
function bindEvent() {
els.back.on(tap, Core.Router.back);
}//end bindEvent
this.show = function () {
initResources();
Core.Event.trigger('trigerAnimate',els.main);
VIEW._BasicView.show(VIEW.viewCls);
}
this.hide = function () {
if (!els) {
return;
}
}
function render(data) {
initResources();
data = data || VIEW.models.User.user.get();
if (!data || !data.length) {
return;
}
var list = [];
data.forEach(function (key, index) {
list.push(Tpl.listItem(key));
});
els.list.html(list.join(''));
list = null;
}//end render
}//end View
module.exports = new UserView();
================================================
FILE: app/templates/app/src/app/view/View.js
================================================
var Actions = require('app/resources/Actions');
var Msgbox = require('widget/Msgbox');
var WechatShare = require('util/WechatShare');
var YiXinShare = require('util/YiXinShare');
var BasicModel = require('app/model/Model');
function View() {
this.models = {
Basic: BasicModel
}
var VIEW = this,
els, shareStore = {},
params = Core.localParam(),
isApp = Core.NativeBridge.isApp();
//click事件
this.tapEvent = $.os.ios || $.os.android ? 'tap' : 'click';
function init() {
Core.MetaHandler.fixViewportWidth();
initEls();
bindEvent();
VIEW.hide();
els.body.css({'visibility': 'visible'});
};//end init
function initEls() {
var body = $('body');
els = {
window: $(window),
body: body,
views: body.children('.view')
}
VIEW.GlobalTouch = {
preventMove: false,
touched: false
}
window.GlobalTouch = VIEW.GlobalTouch;
VIEW.msgbox = new Msgbox({
// themeCls: 'deja',
GlobalTouch: VIEW.GlobalTouch
});
}
this.getEls = function () {
return els;
}
this.getView = function (viewCls) {
return els.views.filter('.' + viewCls);
}
//parse elements have "data-template" into templates
this.getTemplates = function (viewCls) {
var el = this.getView(viewCls);
if (el.$Templates) {
return el.$Templates;
}
var Templates = {};
el.find('*[data-template]').each(function () {
var key = $(this),
name = key.attr('data-template');
if (name) {
Templates[name] = Core.microTmpl(key.text());
}
});
el.$Templates = Templates;
return Templates;
}
/**
* find all elements have "data-element"
* @param viewCls
* @param extra object
* e.g.:
* //1. pass an object
* {
* defaultUserid: 'user_id_xxxx'
* }
*
* //2. pass a function that return an obeject,"this" is the elements' own object
* function(){
* return {
* userList: this.main.find('.list')
* }
* }
*
* @returns {*}
*/
this.getElements = function (viewCls,extra) {
var el = this.getView(viewCls);
if (el.$Elements) {
return el.$Elements;
}
var Elements = {
window: els.window,
body: els.body,
main: el,
apply: function(conf){
Core.Class.apply(Elements,conf);
}
};
el.find('*[data-element]').each(function () {
var name = $(this).attr('data-element');
if (name) {
Elements[name] = Elements[name] || el.find('*[data-element="'+name+'"]');
}
});
Elements.apply(extra);
el.$Elements = Elements;
return Elements;
}
this.resizeCalculateWindow = function () {
els.window = $(window);
els.body = $('body');
setTimeout(function () {
els.bodyHeight = els.body.height();
els.windowMaxScroll = els.bodyHeight - els.window.height() * 2;
}, 300);
}
this.isMaxWindowScroll = function (budget) {
var top = Math.min(Math.min(window.pageYOffset, document.documentElement.scrollTop || document.body.scrollTop), window.scrollY),
maxScroll = budget ? (els.bodyHeight - budget) : els.windowMaxScroll;
return top > maxScroll;
}
function bindEvent() {
document.addEventListener('touchmove', function (e) {
VIEW.GlobalTouch.preventMove && e.preventDefault();
}, false);
document.addEventListener('touchstart', function (e) {
VIEW.GlobalTouch.touched = true;
}, false);
document.addEventListener('touchend', function (e) {
VIEW.GlobalTouch.touched = false;
}, false);
//data-prevent-move="start" prevent document to move ontouchstart and cancel ontouchend,
//data-prevent-move="all" will always prevent the whole document to move
els.body.on('touchstart', '* [data-prevent-move]', function () {
VIEW._BasicView.GlobalTouch.preventMove = true;
});
els.body.on('touchend', '* [data-prevent-move="start"]', function () {
VIEW._BasicView.GlobalTouch.preventMove = false;
});
if (VIEW.tapEvent == 'tap') {
els.body.on('click', 'a', function (e) {
e.preventDefault();
return false;
});
els.body.on('tap', 'a', function () {
Core.Event.trigger('redirect', this.href);
});
}
//fix chrome for android active effect remain issue
$.os.android && /Chrome/i.test(window.navigator.userAgent) && els.body.on('touchstart', '* [data-fix-active]', function (e) {
e.preventDefault();
});
els.body.on(VIEW.tapEvent, '* [data-fake-link]', function () {
Core.Event.trigger('redirect', this.getAttribute('data-fake-link'));
});
els.body.on(VIEW.tapEvent == 'tap' ? 'touchstart' : VIEW.tapEvent, '* [data-analytics]', function () {
Core.Event.trigger(this.getAttribute('data-analytics-global') ? 'analytics' : 'analyticsCurView', this.getAttribute('data-analytics'));
});
els.body.on(VIEW.tapEvent, '* [data-eventname]', function () {
var ename = this.getAttribute('data-eventname'),
eparam = this.getAttribute('data-eventparam') || '',
eparams = this.getAttribute('data-eventparams') || '';
if (ename) {
var params = [];
params.push(ename);
if (eparams) {
Array.prototype.push.apply(params, eparams.split(','));
} else if (eparam) {
params.push(eparam);
}
Core.Event.trigger.apply(null, params);
}
});
}
this.show = function (viewCls, autoRevert) {
this.hide(viewCls);
var view = this.getView(viewCls);
!view.hasClass('show') && view.addClass('show');
//auto scroll to history position,and restore title
if (autoRevert === undefined || autoRevert) {
Core.Event.trigger('appModifyTitle', Core.Router.getHistoryTitle());
setTimeout(Core.Router.scrollToHistoryPosition, 100);
restoreShare();
}
return this;
}
this.hide = function (notCls) {
(notCls ? els.views.not('.' + notCls) : els.views).removeClass('show');
return this;
}
/**
*
* option = {
title String 'share title',
text String 'share text',
summary String 'share summary',
imageurl String 'share image url',
thumburl String 'share image thumb url',
link String 'share link'
}
*/
this.renderShare = function (option) {
option = option || {};
option.link = option.link || window.location.href;
option.title = option.title || document.title;
option.summary = option.summary || option.title;
option.text = option.text || option.summary;
option.thumburl = option.thumburl || Actions.dejaShareLogo;
option.imageurl = option.imageurl || option.thumburl;
Core.NativeBridge.set_data_for_share(option);
shareStore[Core.Router.getCurrentHashStr()] = option;
updateWechatShareMeta(option.title, option.summary, option.thumburl || option.imageurl);
updateYiXinShareMeta(option.summary, option.thumburl || option.imageurl);
return this;
}
function updateWechatShareMeta(title, content, link, img) {
WechatShare({
"appid": "",
"img_url": img || Actions.dejaShareLogo,
"img_width": "200",
"img_height": "200",
"link": link || window.location.href,
"url": link || window.location.href,
"desc": content || document.title,
"content": content || document.title,
"title": title || document.title
});
}
function updateYiXinShareMeta(content, img) {
YiXinShare({
content: content || document.title,
img: img || Actions.dejaShareLogo
});
}
function restoreShare() {
if(shareStore[Core.Router.getCurrentHashStr()]){
VIEW.renderShare(shareStore[Core.Router.getCurrentHashStr()]);
}
}
this.lazyLoadImg = function (el) {
el && setTimeout(function () {
el.find("img").unveil(200, function () {
this.onload = function () {
if (/lazy/.test(this.className)) {
this.classList.add('lazy--loaded');
//this.style.opacity = 1;
}
}
});
}, 0);
}
this.renderI18n = function(el){
el.find('*[data-i18n]').each(function () {
var currEl = $(this),
name = currEl.attr('data-i18n');
if (name) {
var attrs = name.split('.'),
text = window[attrs.shift()];
attrs.forEach(function (key) {
if(key.length && text!==undefined){
text = text[key];
}
});
if(text!==undefined){
currEl.html(text);
}
}
});
}
init();
}//end View
module.exports = new View;
================================================
FILE: app/templates/app/src/core/Class.js
================================================
var Subject = require('./Subject');
var Class;
/**
* @param obj
* @param config
* @param promise
*/
function apply(obj, config, promise) {
var conf = typeof config=='function'?config.call(obj):config;
if (conf) {
var attr;
for (attr in conf) {
obj[attr] = promise ? promise(conf[attr]) : conf[attr];
}
}
}
/**
*
* @param obj
* @param config
* @param promise
*/
function applyIf(obj, config, promise) {
var conf = typeof config=='function'?config.call(obj):config;
if (conf) {
var attr;
for (attr in conf) {
if (!obj[attr]) {
obj[attr] = promise ? promise(conf[attr]) : conf[attr];
}
}
}
}
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = (function () {
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
var result = [], prop, i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
};
}());
}
//http://stackoverflow.com/a/16788517/479039
function objectEquals(x, y) {
if (x === null || x === undefined || y === null || y === undefined) {
return x === y;
}
// after this just checking type of one would be enough
if (x.constructor !== y.constructor) {
return false;
}
// if they are functions, they should exactly refer to same one (because of closures)
if (x instanceof Function) {
return x === y;
}
// if they are regexps, they should exactly refer to same one (it is hard to better equality check on current ES)
if (x instanceof RegExp) {
return x === y;
}
if (x === y || x.valueOf() === y.valueOf()) {
return true;
}
if (Array.isArray(x) && x.length !== y.length) {
return false;
}
// if they are dates, they must had equal valueOf
if (x instanceof Date) {
return false;
}
// if they are strictly equal, they both need to be object at least
if (!(x instanceof Object)) {
return false;
}
if (!(y instanceof Object)) {
return false;
}
// recursive object equality check
var p = Object.keys(x);
return Object.keys(y).every(function (i) {
return p.indexOf(i) !== -1;
}) &&
p.every(function (i) {
return objectEquals(x[i], y[i]);
});
}
/**
*
* @param superClass
* @param subClass
*/
var extend = (function () {
var F = function () {
};
return function (superClass, subClass) {
F.prototype = superClass.prototype;
subClass.prototype = new F();//空函数避免创建超类的新实例(超类可能较庞大或有大量计算)
subClass.prototype.constructor = subClass;
subClass.superclass = superClass.prototype;//superclass减少子类与超类之间的偶合
//http://stackoverflow.com/questions/12691020/why-javascripts-extend-function-has-to-set-objects-prototypes-constructor-pro
if (superClass.prototype.constructor == Object.prototype.constructor) {
superClass.prototype.constructor = superClass;
}
return subClass;
}
})();
function updateFactory() {
var lastUpdate = 0,
_timeout = 1000 * 60 * 5,
names = {};
/**
*
* @param timeout 时间倍数,默认是1
* @param name
* @returns {boolean}
*/
this.isTimeout = function (timeout, name) {
timeout = _timeout * (timeout || 1);
name = name !== undefined ? names[name] : lastUpdate;
return !name || ( (new Date().getTime()) - name > timeout );
}
this.update = function (name) {
var now = new Date().getTime();
if (name !== undefined) {
if (names[name] === undefined) {
this.reset(name);
} else {
names[name] = now;
}
} else {
lastUpdate = now;
}
}
this.reset = function (name) {
if (name !== undefined) {
names[name] = 0;
} else {
lastUpdate = 0;
}
}
this.resetAll = function () {
names = {};
lastUpdate = 0;
}
}
/**
*
* Model
*
*
* Nested Model:
* e.g.
* var testModel = new Model({
* store: new Model({
* request: function(){
* console.log('store.request',this);
* }
* }),
* request: function(){
* console.log('request',this);
* }
* });
*
* testModel.updated(function(){
* console.log(testModel.get());
* testModel.request();
* });
* testModel.set('1');
*
* testModel.store.updated(function(){
* console.log(testModel.store.get());
* testModel.store.request();
* });
* testModel.store.set('2');
*/
function Model(option) {
Model.superclass.constructor.call(this);
this.updated = this.register;
this.refresh = this.notify;
this.data;
apply(this, option);
//数据缓存更新
this.updateFactory = updateFactory;
this.timer = new updateFactory;
}
extend(Subject, Model);
Model.prototype.store = function (storeid, data) {
this._cacheStore = this._cacheStore || {};
if (data && storeid) {
if (toString.call(data) == '[object Array]') {
this._cacheStore[storeid] = {
__STORE_ID: storeid,
data: data
};
} else {
this._cacheStore[storeid] = /function/i.test(typeof data)
? data.call(this, this._cacheStore[storeid])
: data;
if (typeof this._cacheStore[storeid] == 'object') {
this._cacheStore[storeid].__STORE_ID = storeid;
}
}
}
}
/**
*
* @param data
* @param storeid ,will cache in store,use getFromStoreById(storeid) to get access it
* @param diff ,if true,and nothing changed between the new data in the old data,data observers will not got notify
*/
Model.prototype.set = function (data, storeid, diff) {
var _data = /function/i.test(typeof data) ? data.call(this) : data;
diff = diff && objectEquals(this.data, _data);
this.data = _data;
if (storeid) {
this.store(storeid, data);
}
!diff && this.refresh();
this.timer.update();
}
/**
*
* @param clone will return a copy of the data
* @returns {*}
*/
Model.prototype.get = function (clone) {
return (clone && typeof this.data == 'object') ? JSON.parse(JSON.stringify(this.data)) : this.data;
}
/**
*
* @param clone will return a copy of the data
* @returns {*}
*/
Model.prototype.getStore = function (clone) {
return (clone && typeof this._cacheStore == 'object') ? JSON.parse(JSON.stringify(this._cacheStore)) : this._cacheStore;
}
/**
*
* @param storeid
* @param clone ,will return a copy of the data
* @returns {*|{}}
*/
Model.prototype.getFromStoreById = function (storeid, clone) {
return storeid
&& this._cacheStore
&& ( (clone && typeof this._cacheStore[storeid] == 'object')
? JSON.parse(JSON.stringify(this._cacheStore[storeid]))
: this._cacheStore[storeid]);
}
/**
*
* @param storeid
* @returns {*|{}}
*/
Model.prototype.deleteFromStoreById = function (storeid) {
storeid
&& this._cacheStore
&& delete this._cacheStore[storeid];
}
//end Model
Class = {
objectEquals: objectEquals,
apply: apply,
applyIf: applyIf,
extend: extend,
Model: Model
}
//end Class
module.exports = Class;
================================================
FILE: app/templates/app/src/core/Event.js
================================================
var Class = require('./Class');
var Pubsub = require('./Pubsub');
var Subject = require('./Subject');
function Event(Subject) {
Event.superclass.constructor.call(this, Subject);
this.on = this.subscribe;
this.off = this.unsubscribe;
this.trigger = this.publish;
}
Class.extend(Pubsub, Event);
module.exports = new Event(Subject);
================================================
FILE: app/templates/app/src/core/HashHandler.js
================================================
var HashHandler = (function () {
var lc = window.location;
function getByURL(url) {
var hash;
url && decodeURIComponent(url).replace(new RegExp('#(.*)', 'g'), function ($1, $2) {
hash = $2;
});
return hash;
}
function get() {
return getByURL(lc.hash);
}
function set(hash) {
lc.hash = hash;
}
return {
get: get,
set: set,
getByURL: getByURL
}
})();
module.exports = HashHandler;
================================================
FILE: app/templates/app/src/core/MicroTmpl.js
================================================
/**
* 模板解析
* 1. 可接收 DOM Element,不支持 DOM Element 模板里嵌套模板
* 2. 如果 DOM Element 中的元素的属性可加前缀micro-(或ntes-),如img的src改为micro-src;及内样式style改为micro-style。以避免模板没有使用前生效。最终模板将会替换掉micro-(或ntes-)前缀。
*
* e.g.
* <section>
* <script type="text/html">
* <h1><%=TITLE%></h1>
* <% for(var i=0;i<list.length;i++){ %>
* <article><%=list[i]%></article>
* <%}%>
* </script>
* </section>
*
* 如果 mustache 参数为true,默认为false,可使用{{}},不支持JS表达式
* e.g
* <section>
* <script type="text/html">
* <h1>{{TITLE}}</h1>
* </script>
* </section>
*/
var microTmpl = function (mustache) {
var intro = mustache ? '{{' : '<%',
outro = mustache ? '}}' : '%>',
tmplAttrs = ['micro-template', 'ntes-template'],
childTmplAttrs = ['micro-template-child', 'ntes-template-child'];
//http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object?answertab=votes#tab-top
function isElement(o) {
return (
typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string"
);
}
function hasChildTmplAttr(el) {
var i = 0;
for (; i < childTmplAttrs.length; i++) {
if (el.hasAttribute(childTmplAttrs[i])) {
return true;
}
}
return false;
}
function removeChildTmplAttrs(el) {
var i = 0;
for (; i < childTmplAttrs.length; i++) {
el.removeAttribute(childTmplAttrs[i]);
}
}
function getTmpl(str) {
//如果是DOM节点则取outerHTML或者innerHTML
if (isElement(str)) {
if (hasChildTmplAttr(str) || str.tagName.toLowerCase() == 'script') {
var text = str.innerHTML;
str.innerHTML = '';
removeChildTmplAttrs(str);
str = text;
} else {
str = str.outerHTML;
}
}
//将模板中所有 micro-(或者micro-template,ntes-,ntes-template)替换为空
return str && str.toString().replace(/(micro|ntes)-(template)?/g, '');
}
//http://ejohn.org/blog/javascript-micro-templating/
var cache = {};
function tmpl(str, data) {
str = getTmpl(str);
var reg1 = new RegExp('((^|' + outro + ")[^\t]*)'", 'g');
var reg2 = new RegExp('\t' + (mustache ? '' : '=') + '(.*?)' + outro, 'g');
var fn = !/\W/.test(str) ? //W大写,可以匹配任何一个字母或者数字或者下划线以外的字符
cache[str] = cache[str] :
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};"
+ "with(obj){p.push('"
+ str
.replace(/[\r\t\n]/g, " ") //将"\r\t\n"先替换成" "
//.split("<%").join("\t") //将模板开始符号"<%"全部替换成"\t"
.split(intro).join("\t")//--> split("<%").join("\t")
//.replace(/((^|%>)[^\t]*)'/g, "$1\r") //将将模板结束符号%>全部替换成\r
.replace(reg1, "$1\r")//--> replace(/((^|%>)[^\t]*)'/g, "$1\r")
//.replace(/\t=(.*?)%>/g, "',$1,'") //将=与%>之间的变量替换成",变量,"
.replace(reg2, "',$1,'")//--> replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');") //将之前替换的"\t"再替换成");"
//.split("%>").join("p.push('")
.split(outro).join("p.push('")//-->split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");
return data ? fn(data) : fn;
}
return tmpl;
};
module.exports = microTmpl;
================================================
FILE: app/templates/app/src/core/NativeBridge.js
================================================
var Navigator = require('./Navigator');
/**
* 与客户端交互
*
* 前端与客户端交互的流程主要为前端调用,客户端读取,客户端回调三个步骤:
* 前端调用客户端规则为:dejafashion://NAME(android 前端调用window.__dejafashion_NAME())
* 客户端读取前端的数据规则为 window.__dejafashion_data_NAME,前端返回JSON {default:'',...}
* 【如果有】客户端处理完逻辑回调前端的方法规则为: window.__dejafashion_after_NAME([json])
* 拿分享为例:
* 1 -------> 前端调用dejafashion://share(android 前端调用window.__dejafashion_share())
* 2 --------> 客户端接收到请求,向前端读取必要参数window.__dejafashion_data_share
* 3 ------- >【如果有】 客户端处理完逻辑回调通知前端处理完毕调用window.__dejafashion_after_share([json])
* 4 ------>前端接收客户端传回来的参数该干嘛干嘛
* 注意,客户端在调用前端方法之前一定要先做判断,如 window.__dejafashion_after_share && window.__dejafashion_after_share([json])
*
*/
function NativeBridge(protocolHandler) {
var _NB = this,
global = window,
emptyFn = function () {
},
appUA = (/Deja/ig).test(navigator.userAgent),
debug = false,
afterCallbacks = {},
Protocols = {},
baseName = 'dejafashion',
baseProtocol = baseName + '://',
baseObjName = '__' + baseName,
baseDataName = baseObjName + '_data_',
baseBeforeName = baseObjName + '_before_',
baseAfterName = baseObjName + '_after_',
baseUpdateDataName = 'set_data_for_',
baseUpdateBeforeName = 'set_before_for_';
afterCallbacks = {};
Protocols = {};
function enableDebug() {
debug = true;
}
function isApp() {
return appUA || debug;
}
function protocol(action, callback) {
protocolHandler(action, true);
//开启调试
if (debug && callback) {
var _data = action.match(/[\w]:\/\/(.*)/);
if (typeof callback == 'function') {
callback(_data && _data[1]);
}
}
}
function afterCallback(rs, callback) {
callback = callback || emptyFn;
if (typeof callback == 'function') {
callback(rs);
}
callback = emptyFn;
}
function updateData(name, data) {
if (data != null && data != undefined) {
if (!/object/i.test(typeof data)) {
data = {default: data};
}
global[baseDataName + name] = data;
}
}
function updateBefore(name, fn) {
if (/function/i.test(typeof fn)) {
global[baseBeforeName + name] = fn;
} else {
delete global[baseBeforeName + name];
}
}
/**
* set_data_for_NAME = function(data)
* @param name
* @param fn
*/
function registerUpdateDataFn(name, fn) {
var updateName = baseUpdateDataName + name;
_NB[updateName] = fn || function (data) {
updateData(name, data);
}
}
/**
* set_before_for_NAME = function(callback)
* @param name
*/
function registerBeforeFn(name) {
var beforeName = baseUpdateBeforeName + name;
_NB[beforeName] = function (fn) {
updateBefore(name, fn);
}
}
/**
* register a native API
*
* @param name
* @param fn
* @returns {*}
*/
function registerFn(name, fn) {
Protocols[name] = baseProtocol + name;
afterCallbacks[name] = emptyFn;
global[baseAfterName + name] = function (rs) {
afterCallback(rs, afterCallbacks[name]);
}
registerUpdateDataFn(name);
_NB[name] = fn
|| function (data, callback, subProtocol) {
updateData(name, data);
afterCallbacks[name] = callback;
if (isApp()) {
if (global[baseObjName] && global[baseObjName][name]) {
global[baseObjName][name]();
} else {
protocol(Protocols[name] + (subProtocol ? ('/' + subProtocol) : ''), callback);
}
}
};
return _NB[name];
}
/**
*
* execute a native API by it's name
* if it's not exist then register it and execute it
*
* @param name
*/
function trigger(name) {
var fn = _NB[name],
args = [].slice.call(arguments, 1);
if (!fn) {
fn = registerFn(name);
}
fn.apply(_NB, args);
}
this.isApp = isApp;
this.enableDebug = enableDebug;
this.trigger = trigger;
['userInfo', 'login', 'share', 'modifytitle', 'updateBarButton', 'setBgColor', 'copy', 'closeweb'].forEach(function (key, index) {
registerFn(key);
});
['facebook', 'twitter', 'instagram'].forEach(function (key, index) {
_NB['share_' + key] = function (data, callback) {
_NB['share'](data, callback, key);
}
_NB[baseUpdateDataName + 'share_' + key] = _NB[baseUpdateDataName + 'share'];
});
['unload'].forEach(function (key, index) {
registerBeforeFn(key);
});
}
module.exports = new NativeBridge(Navigator.protocol);
================================================
FILE: app/templates/app/src/core/Navigator.js
================================================
var Navigator = (function () {
var frame,
androidReg = /Android/gi,
isAndroid = androidReg.test(navigator.platform) || androidReg.test(navigator.userAgent);
/**
* iframe 元素
*
* @property {Element} frame
*/
frame = null;
/**
* append iframe
*
* @param frame
*/
function appendFrame(frame) {
frame && document.body.appendChild(frame);
}
/**
* 删除iframe
*
* @method removeFrame
* @param {Element} frame 执行的方法
*/
function removeFrame(frame) {
frame && frame.parentNode.removeChild(frame);
}
/**
* 创建iframe,帮助解决iOS的UIWebView没有JS API
*
* @method getFrame
* @return {Element} iframe
*/
function getFrame(src, name) {
var _frame = document.createElement("iframe");
_frame.setAttribute("style", "display:none;width:0;height:0;position: absolute;top:0;left:0;border:0;");
_frame.setAttribute("height", "0px");
_frame.setAttribute("width", "0px");
_frame.setAttribute("frameborder", "0");
name && _frame.setAttribute("name", name);
if (src) {
_frame.setAttribute("src", src);
} else {
appendFrame(_frame);
}
return _frame;
}
/**
* 执行与客户端交互方法的命令
*
* @method excute
* @param {String} ns 与客户端交互的协议server/类Class
* @param {String} fn 执行的方法
* @param {Object} option 参数
* @param {boolean} single 是否是使用独立的iframe,默认false
* @param {boolean} noframe 是否不通过iframe,默认false
*/
function excute(ns, fn, option, single, noframe) {
var data, command;
data = option ? JSON.stringify(option) : '';//将JSON转换成字符串
if (ns && (typeof ns == 'object') && ns[fn]) {//android
ns[fn](data);
} else {//iOS
command = ns;
if (typeof fn == 'string' && fn.length > 0) {
command += fn + '/' + data;
}
protocol(command, single, noframe);
}
}
/**
* 执行与客户端交互的协议
*
* @method protocol
* @param {String} command 执行的协议及命令
* @param {boolean} single 是否是使用独立的iframe,默认false
* @param {boolean} noframe 是否不通过iframe,默认false
*/
function protocol(command, single, noframe) {
var _frame, timer;
//不通过iframe
if (noframe) {
window.location.href = command;
return;
}
//通过iframe
if (single) {
if (isAndroid) {
_frame = getFrame();
_frame.setAttribute("src", command);
} else {
_frame = getFrame(command);
appendFrame(_frame);
}
timer = setTimeout(function () {
_frame && removeFrame(_frame);
}, 30000);
_frame.onload = _frame.onreadystatechange = function () {
timer && clearTimeout(timer);
setTimeout(function () {
_frame && removeFrame(_frame);
}, 3500);
}
} else {
frame = frame || getFrame();
frame.setAttribute("src", command);
}
}
return {
protocol: protocol,
excute: excute,
getFrame: getFrame,
appendFrame: appendFrame,
removeFrame: removeFrame
}
})();//end Object Navigator
module.exports = Navigator;
================================================
FILE: app/templates/app/src/core/Pubsub.js
================================================
function Pubsub(Subject) {
var topics = {};
function subscribe(topic, observer) {
var subject;
for (var key in topics) {
if (key === topic) {
subject = topics[key];
break;
}
}
if (!subject) {
subject = new Subject();
addTopic(topic, subject);
}
subject.register(observer);
return this;
}
function unsubscribe(topic) {
removeTopic(topic);
return this;
}
function publish(topic) {
var args = [].slice.call(arguments);
topics[topic] && topics[topic].notify.apply(topics[topic], args.slice(1));
return this;
}
function addTopic(topic, subject) {
topics[topic] = subject;
}
function removeTopic(topic) {
delete topics[topic];
}
function getTopics() {
var _topics = [];
for (var key in topics) {
(typeof key === 'string') && _topics.push(key);
}
return _topics;
}
this.getTopics = getTopics;
this.subscribe = subscribe;
this.unsubscribe = unsubscribe;
this.publish = publish;
}
module.exports = Pubsub;
================================================
FILE: app/templates/app/src/core/Router.js
================================================
var Pubsub = require('./Pubsub');
var Subject = require('./Subject');
var HashHandler = require('./HashHandler');
/**
*
* Router 初始化流程:
* init(withAction) --> onReady 是否注册有 Callback --> (是)执行所有 Callback (在关键Callback里,手动执行 run 来强制刷新是推荐的)
* --> (否)执行 run
*
*
* Hash 变化事件执行流程:
* Hash变化(或者显示调用 run,forward,back方法) --> 执行 onChanged 注册的所有事件 --> 执行 subscribe 注册的与 Hash 关联的所有事件
*
* subscribe 注册的事件回调方法传递参数:
* actionValue - 当前 action 之后的字符串,如/user/id=1&name=test 对应 action 是 /user/ ,actionValue 是 id=1&name=test
* request - { action: 当前action字符串,
valeu: actionValue,
hash: {
curHash: String,
newHash: String,
oldHash: String
},
query: actionValue的键值对,如 {id:1,name:test}
}
*
* 本 Router 暂不支持正则表达式
*/
function Router(Pubsub, HashHandler) {
var _Router = this,
subscribe = Pubsub.subscribe,
android = /Android/gi.test(navigator.userAgent),
iOS = /(iPad|iPhone|iPod)/gi.test(navigator.userAgent) && !android,
UN_SUB_NAME = '__UN_SUBSCRIBED_ACTION',
INIT_HASH_STR = formatHash(HashHandler.get()),
currentHash,
currentHashStr = INIT_HASH_STR || UN_SUB_NAME,
currentQureyStr = '',
lastActionKey,
leavePrefix = '__',
_isFroward = true,
isReady = false,
initCallback,
readyCallbacks = [],
changedCallbacks = [],
actionsHistory = [INIT_HASH_STR],
queryHistory = {},
historyPositions = {},
historyTitles = {},
anchorEl;
//iOS使用pushstate,解决iOS7没有历史的问题
if (iOS) {
window.addEventListener('popstate', locationHashChanged, false);
} else {
window.addEventListener('hashchange', locationHashChanged, false);
}
function getQuery(search) {
search = search || currentQureyStr || '';
var fn = function (str, reg) {
if (str) {
var data = {};
str.replace(reg, function ($0, $1, $2, $3) {
data[$1] = $3;
});
return data;
}
}
return fn(search, new RegExp("([^?=&]+)(=([^&]*))?", "g")) || {};
}
function saveQuery(key, query) {
queryHistory[key] = queryHistory[key] || [];
queryHistory[key].push(query);
}
function getLastQuery(key) {
return queryHistory[key]?(queryHistory[key][queryHistory[key].length-1]||{}):{};
}
function formatHash(hash) {
if (hash) {
//hash后不能带search值
hash = hash.replace(/\?.*/g, '');
}
return hash;
}
function locationHashChanged(e) {
e && e.preventDefault();
var args = arguments[0] || {},
hash;
hash = {
curHash: formatHash(HashHandler.get()),
newHash: formatHash(HashHandler.getByURL(args.newURL)),
oldHash: formatHash(HashHandler.getByURL(args.oldURL))
}
setHistoryPosition();
setHistoryTitle();
currentHash = hash;
currentHashStr = hash.curHash || UN_SUB_NAME;
setLastAction(hash.curHash);
initCallback && initCallback(hash.curHash, hash);
if (isReady) {
doChanged(hash.curHash, hash);
dispatch(hash);
}
hash.curHash && addAnchor(hash.curHash);
return false;
}
function dispatch(hash) {
var topics = Pubsub.getTopics(),
published = false;
if (hash.curHash !== undefined) {
for (var i = 0; i < topics.length; i++) {
var key = topics[i];
if (key !== UN_SUB_NAME) {
hash.curHash.replace(new RegExp('^' + key + '(.*)', 'g'), function ($1, $2) {
if ($1) {
currentQureyStr = $2;
published = true;
lastActionKey = key;
restoreHistoryTitle();
var query = getQuery($2);
Pubsub.publish(key, {
action: key,
param: $2,
hash: hash,
preQuery: getLastQuery(key),
query: query
});
saveQuery(key, query);
}
});
}
}
}
if (!published) {
lastActionKey = UN_SUB_NAME;
currentQureyStr = hash.curHash;
restoreHistoryTitle();
var query = getQuery(hash.curHash);
Pubsub.publish(UN_SUB_NAME, {
action: hash.curHash,
param: hash.curHash,
hash: hash,
preQuery: getLastQuery(UN_SUB_NAME),
query: query
});
saveQuery(UN_SUB_NAME, query);
}
}
/**
* 手动初始化
* 如在onReady里注册了很多的callback,可以通过此方法手动初始化它们
* 如果带上 withAction 可实现:
* 在所有主题被订阅之前,在页面首次加载之初,初始化一个与源hash不同且暂未被订阅的主题,最终仍然跳转到源hash
*
* 此方法并不是必要的
* @param {String} withAction 初始化的action
*/
function init(withAction) {
if ((withAction === null) || (withAction === undefined) || (withAction === '' )) {
ready();
} else {
//注意原初始化的action不应该包含在将初始化的hash里
var reg = new RegExp('^' + withAction + '(.*)', 'i');
if (INIT_HASH_STR && !reg.test(INIT_HASH_STR)) {
initCallback = function (curHash) {
if (curHash === INIT_HASH_STR) {
initCallback = null;
setTimeout(function () {
ready();
}, 0);
} else if (curHash === withAction) {
forward(INIT_HASH_STR);
}
};
forward(withAction);
} else {
ready();
}
}
return Pubsub;
}
/**
* 强制刷新
* 在无需引起 hash 变化情况下,强制执行与当前 hash 关联的所有主题一次
* 流程:
* 执行 onChanged 注册的所有事件 --> 执行 subscribe 注册的与 Hash 关联的所有事件
* 如果:action 不为空,则仅执行 subscribe 注册的与 action 关联的所有事件
* @param action {Array}|{String}
* @returns {Pubsub}
*/
function run(action) {
action ?
Pubsub.publish(action, {
action: action,
param: currentQureyStr,
hash: currentHash,
preQuery: getLastQuery(action),
query: getQuery()
})
: locationHashChanged();
return Pubsub;
}
/**
* 订阅所有没有被注册的主题
* @param {Object} observer
*/
function onUnsubscribed(enterObserver, leaveObserver) {
onSubscribe(UN_SUB_NAME, enterObserver, leaveObserver);
return Pubsub;
}
/**
* 订阅所有没有被注册的主题
* @param action {Array}|{String}
* @param {Object} observer
* @param {Object} observer
*/
function onSubscribe(action, enterObserver, leaveObserver) {
subscribe.call(Pubsub, action, enterObserver);
leaveObserver && subscribe.call(Pubsub, leavePrefix + action, leaveObserver);
return Pubsub;
}
/**
* 当hash发生变化时触发,会先于所有订阅的主题触发
*/
function onChanged(callback) {
if (typeof callback === 'function') {
changedCallbacks.push(callback);
}
return Pubsub;
}
/**
* 手动执行init方法会执行通过此方法注册的所有callback方法
* @param callback
*/
function onReady(callback) {
if (typeof callback === 'function') {
readyCallbacks.push(callback);
}
return Pubsub;
}
function ready() {
isReady = true;
//如果 onReady 方法中有回调则执行回调
//注意,onReady 的回调里需要有且仅有一个要显示调用 run 来强制执行所有主题的调回
if (readyCallbacks.length) {
while (readyCallbacks.length) {
readyCallbacks.shift().call(_Router, Pubsub)
}
}
//否则自动强制执行所有主题
else {
run();
}
}
function doChanged() {
var i = 0,
l = changedCallbacks.length;
for (; i < l; i++) {
changedCallbacks[i].apply(undefined, arguments);
}
lastActionKey && Pubsub.publish(leavePrefix + lastActionKey);
}
/**
* 跳转到一个指定的主题
* @param {String}|{Number} action
*/
function forward(action) {
_isFroward = true;
if (action === null) {
window.history.forward();
} else if (typeof action === 'number') {
if (action == -1) {
_isFroward = false;
}
window.history.go(action);
} else if (typeof action === 'string') {
if (iOS) {
window.history.pushState(null, null, '#' + action);
run();
} else {
HashHandler.set(action);
}
}
return Pubsub;
}
/**
* 返回上一主题
* action仅在解决当不确实是否有浏览历史,并且又需要跳转到一个指定的hash值时
* 优先级是: 浏览器历史 > actionsHistory > action
* @param {String}|{Number} action
*/
function back(action) {
var ac = popLastAction() || action || -1;
//如果浏览器有历史则走历史
if (window.history.length > 1) {
ac = -1;
}
forward(ac);
return Pubsub;
}
function setLastAction(action) {
var ac = [].concat.call(actionsHistory).pop();
if (ac != action) {
actionsHistory.push(action);
}
}
function getLastAction() {
var last = [].concat.call(actionsHistory);
last.pop();
return last.pop();
}
function popLastAction() {
//pop两次是因为最后一次是当前的
actionsHistory.pop();
return actionsHistory.pop();
}
function setFirstAction(action) {
var ac = [].concat.call(actionsHistory).shift();
if (ac != action) {
actionsHistory.unshift(action);
}
}
function getFirstAction() {
return actionsHistory.shift();
}
function isFroward() {
return _isFroward;
}
/**
* 解决历史滚动位置记录的问题,保证视图切换总在最顶部
* @param id
*/
function addAnchor(id) {
return;//暂停使用
if (!anchorEl) {
var st = document.createElement('style');
anchorEl = document.createElement('div');
st.innerText = '.Router-anchor{position: fixed; top: 0; left: 0;}';
anchorEl.className = 'Router-anchor';
document.body.appendChild(st);
document.body.appendChild(anchorEl);
}
var cd = document.createElement('div'),
od = document.getElementById(id);
cd.id = id;
anchorEl.appendChild(cd);
if (od) {
anchorEl.removeChild(od);
}
}
/**
* 校验是否存在与当前的 action 匹配的 action
* @param action {Array}|{String}
* @returns {boolean}
*/
function actionMatch(expected, actual) {
var ac = [], i = 0, l;
if (typeof expected === 'string') {
ac.push(expected)
} else if (toString.call(expected) == '[object Array]') {
ac = ac.concat(expected)
}
l = ac.length;
for (; i < l; i++) {
if ((new RegExp('^' + ac[i] + '(.*)', 'i')).test(actual)) {
return true;
}
}
return false;
}
/**
* 校验是否存在与当前的 action 匹配的 action
* @param action {Array}|{String}
* @returns {boolean}
*/
function currentMatch(action) {
return actionMatch(action, currentHashStr || UN_SUB_NAME);
}
/**
* 校验是否存在与上一个 action 匹配的 action
* @param action {Array}|{String}
* @returns {boolean}
*/
function lastMatch(action) {
return actionMatch(action, getLastAction() || UN_SUB_NAME);
}
function setHistoryPosition(id, position) {
id = id || currentHashStr;
if (id) {
historyPositions[id] = position || window.pageYOffset || window.scrollY || document.body.scrollTop;
}
}
function getHistoryPosition(id) {
id = id || currentHashStr;
return id && historyPositions[id];
}
function scrollToHistoryPosition(id) {
window.scrollTo(0, getHistoryPosition(id) || 1);
setHistoryPosition(id, 0);
}
function setHistoryTitle(id, title) {
id = id || currentHashStr;
if (id) {
historyTitles[id] = title || document.title;
}
}
function getHistoryTitle(id) {
id = id || currentHashStr;
return id && historyTitles[id];
}
function restoreHistoryTitle(id) {
var title = getHistoryTitle(id);
if (title) {
document.title = title;
}
}
function getCurrentHashStr() {
return currentHashStr;
}
Pubsub.initHash = INIT_HASH_STR;
Pubsub.init = init;
Pubsub.run = run;
Pubsub.forward = forward;
Pubsub.back = back;
Pubsub.isFroward = isFroward;
Pubsub.currentMatch = currentMatch;
Pubsub.lastMatch = lastMatch;
Pubsub.onReady = onReady;
Pubsub.onChanged = onChanged;
Pubsub.subscribe = onSubscribe;
Pubsub.onUnsubscribed = onUnsubscribed;
Pubsub.getQuery = getQuery;
Pubsub.getHistoryPosition = getHistoryPosition;
Pubsub.scrollToHistoryPosition = scrollToHistoryPosition;
Pubsub.getHistoryTitle = getHistoryTitle;
Pubsub.getCurrentHashStr = getCurrentHashStr;
Pubsub.getUnsubscribedAction = function () {
return UN_SUB_NAME;
};
return Pubsub;
}
module.exports = Router(new Pubsub(Subject), HashHandler);
================================================
FILE: app/templates/app/src/core/Subject.js
================================================
function Subject(subject) {
this._subject = subject;
this.observers = [];
}
Subject.prototype = {
/**
* @param {Function}|{Boject} observer
*/
register: function (observer) {
if (!observer) {
throw new Error('An observer can not be undefined!');
} else if (typeof observer === 'object' && typeof observer.update !== 'function') {
throw {
name: 'Error',
method: 'Subject.register',
message: 'An observer object can not register without an update method!'
}
}
this.unregister(observer);//防止重复注册
this.observers.push(observer);
return this;
},
/**
* @param {Function}|{Boject} observer
*/
unregister: function (observer) {
this.observers = this.observers.filter(function (obsv) {
if (obsv !== observer) {
return obsv;
}
});
return this;
},
notify: function () {
var args = [].slice.call(arguments);
this.observers.forEach(function (obsv) {
if (typeof obsv === 'function') {
obsv.apply(obsv, args);
} else {
obsv.update.apply(obsv, args);
}
});
return this;
}
}
module.exports = Subject;
================================================
FILE: app/templates/app/src/lib/Core.js
================================================
require('util/RequestAnimationFrame');
require('util/Easing');
require('util/Unveil');
require('util/VirtualDOMLite');
var Navigator = require('core/Navigator');
var Subject = require('core/Subject');
var MicroTmpl = require('core/MicroTmpl');
var Class = require('core/Class');
var NativeBridge = require('core/NativeBridge');
var Router = require('core/Router');
var HashHandler = require('core/HashHandler');
var Event = require('core/Event');
var localStorage = require('util/LocalStorage');
var LocalHost = require('util/LocalHost');
var localParam = require('util/LocalParam');
var MetaHandler = require('util/MetaHandler');
var RequestHandler = require('util/RequestHandler');
var versionCompare = require('util/versionCompare');
var FormHandler = require('util/FormHandler');
var randomList = require('util/RandomList');
var Num = require('util/Number');
var GUID = require('util/GUID');
var DateHandler = require('util/DateHandler');
var Core = {
localStorage: localStorage,
localHost: LocalHost,
localParam: localParam,
Navigator: Navigator,
MetaHandler: MetaHandler,
Subject: Subject,
microTmpl: MicroTmpl(),
Class: Class,
extend: Class.extend,
HashHandler: HashHandler,
RequestHandler: RequestHandler,
NativeBridge: NativeBridge,
versionCompare: versionCompare,
FormHandler: FormHandler,
Event: Event,
Router: Router,
Num: Num,
GUID: GUID,
randomList: randomList,
DateHandler: DateHandler,
isDebug: localParam().search['debug'] == 1
};
//enable debug model
Core.isDebug && Core.NativeBridge.enableDebug();
window.Core = Core;
module.exports = Core;
================================================
FILE: app/templates/app/src/lib/Core.standalone.js
================================================
require('util/RequestAnimationFrame');
var localStorage = require('core/LocalStorage');
var Navigator = require('core/Navigator');
var Subject = require('core/Subject');
var Class = require('core/Class');
var Event = require('core/Event');
var LocalHost = require('util/LocalHost');
var localParam = require('util/LocalParam');
var RequestHandler = require('util/RequestHandler');
var randomList = require('util/RandomList');
var Num = require('util/Number');
var DateHandler = require('util/DateHandler');
var Core = {
localStorage: localStorage,
localHost: LocalHost,
localParam: localParam,
Navigator: Navigator,
Class: Class,
extend: Class.extend,
RequestHandler: RequestHandler,
Event: Event,
Num: Num,
randomList: randomList,
DateHandler: DateHandler
};
window.Core = Core;
module.exports = Core;
================================================
FILE: app/templates/app/src/lib/diffDOM.js
================================================
"use strict";
var diffcount;
var Diff = function (options) {
var diff = this;
Object.keys(options).forEach(function (option) {
diff[option] = options[option];
});
};
Diff.prototype = {
toString: function () {
return JSON.stringify(this);
}
// TODO: compress diff output by replacing these keys with numbers or alike:
/* 'addAttribute' = 0,
'modifyAttribute' = 1,
'removeAttribute' = 2,
'modifyTextElement' = 3,
'relocateGroup' = 4,
'removeElement' = 5,
'addElement' = 6,
'removeTextElement' = 7,
'addTextElement' = 8,
'replaceElement' = 9,
'modifyValue' = 10,
'modifyChecked' = 11,
'modifySelected' = 12,
'modifyComment' = 13,
'action' = 14,
'route' = 15,
'oldValue' = 16,
'newValue' = 17,
'element' = 18,
'group' = 19,
'from' = 20,
'to' = 21,
'name' = 22,
'value' = 23,
'data' = 24,
'attributes' = 25,
'nodeName' = 26,
'childNodes' = 27,
'checked' = 28,
'selected' = 29;*/
};
var SubsetMapping = function SubsetMapping(a, b) {
this.old = a;
this.new = b;
};
SubsetMapping.prototype = {
contains: function contains(subset) {
if (subset.length < this.length) {
return subset.new >= this.new && subset.new < this.new + this.length;
}
return false;
},
toString: function toString() {
return this.length + " element subset, first mapping: old " + this.old + " → new " + this.new;
}
};
var elementDescriptors = function (el) {
var output = [];
if (el.nodeName != '#text' && el.nodeName != '#comment') {
output.push(el.nodeName);
if (el.attributes) {
if (el.attributes.class) {
output.push(el.nodeName + '.' + el.attributes.class.replace(/ /g, '.'));
}
if (el.attributes.id) {
output.push(el.nodeName + '#' + el.attributes.id);
}
}
}
return output;
};
var findUniqueDescriptors = function (li) {
var uniqueDescriptors = {},
duplicateDescriptors = {};
li.forEach(function (node) {
elementDescriptors(node).forEach(function (descriptor) {
var inUnique = descriptor in uniqueDescriptors,
inDupes = descriptor in duplicateDescriptors;
if (!inUnique && !inDupes) {
uniqueDescriptors[descriptor] = true;
} else if (inUnique) {
delete uniqueDescriptors[descriptor];
duplicateDescriptors[descriptor] = true;
}
});
});
return uniqueDescriptors;
};
var uniqueInBoth = function (l1, l2) {
var l1Unique = findUniqueDescriptors(l1),
l2Unique = findUniqueDescriptors(l2),
inBoth = {};
Object.keys(l1Unique).forEach(function (key) {
if (l2Unique[key]) {
inBoth[key] = true;
}
});
return inBoth;
};
var removeDone = function (tree) {
delete tree.outerDone;
delete tree.innerDone;
delete tree.valueDone;
if (tree.childNodes) {
return tree.childNodes.every(removeDone);
} else {
return true;
}
};
var isEqual = function (e1, e2) {
var e1Attributes, e2Attributes;
if (!['nodeName', 'value', 'checked', 'selected', 'data'].every(function (element) {
if (e1[element] !== e2[element]) {
return false;
}
return true;
})) {
return false;
}
if (Boolean(e1.attributes) !== Boolean(e2.attributes)) {
return false;
}
if (Boolean(e1.childNodes) !== Boolean(e2.childNodes)) {
return false;
}
if (e1.attributes) {
e1Attributes = Object.keys(e1.attributes);
e2Attributes = Object.keys(e2.attributes);
if (e1Attributes.length != e2Attributes.length) {
return false;
}
if (!e1Attributes.every(function (attribute) {
if (e1.attributes[attribute] !== e2.attributes[attribute]) {
return false;
}
})) {
return false;
}
}
if (e1.childNodes) {
if (e1.childNodes.length !== e2.childNodes.length) {
return false;
}
if (!e1.childNodes.every(function (childNode, index) {
return isEqual(childNode, e2.childNodes[index]);
})) {
return false;
}
}
return true;
};
var roughlyEqual = function (e1, e2, uniqueDescriptors, sameSiblings, preventRecursion) {
var childUniqueDescriptors, nodeList1, nodeList2;
if (!e1 || !e2) {
return false;
}
if (e1.nodeName !== e2.nodeName) {
return false;
}
if (e1.nodeName === '#text') {
// Note that we initially don't care what the text content of a node is,
// the mere fact that it's the same tag and "has text" means it's roughly
// equal, and then we can find out the true text difference later.
return preventRecursion ? true : e1.data === e2.data;
}
if (e1.nodeName in uniqueDescriptors) {
return true;
}
if (e1.attributes && e2.attributes) {
if (e1.attributes.id && e1.attributes.id === e2.attributes.id) {
var idDescriptor = e1.nodeName + '#' + e1.attributes.id;
if (idDescriptor in uniqueDescriptors) {
return true;
}
}
if (e1.attributes.class && e1.attributes.class === e2.attributes.class) {
var classDescriptor = e1.nodeName + '.' + e1.attributes.class.replace(/ /g, '.');
if (classDescriptor in uniqueDescriptors) {
return true;
}
}
}
if (sameSiblings) {
return true;
}
nodeList1 = e1.childNodes ? e1.childNodes.slice().reverse() : [];
nodeList2 = e2.childNodes ? e2.childNodes.slice().reverse() : [];
if (nodeList1.length !== nodeList2.length) {
return false;
}
if (preventRecursion) {
return nodeList1.every(function (element, index) {
return element.nodeName === nodeList2[index].nodeName;
});
} else {
// note: we only allow one level of recursion at any depth. If 'preventRecursion'
// was not set, we must explicitly force it to true for child iterations.
childUniqueDescriptors = uniqueInBoth(nodeList1, nodeList2);
return nodeList1.every(function (element, index) {
return roughlyEqual(element, nodeList2[index], childUniqueDescriptors, true, true);
});
}
};
var cloneObj = function (obj) {
// TODO: Do we really need to clone here? Is it not enough to just return the original object?
return JSON.parse(JSON.stringify(obj));
//return obj;
};
/**
* based on https://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Longest_common_substring#JavaScript
*/
var findCommonSubsets = function (c1, c2, marked1, marked2) {
var lcsSize = 0,
index = [],
matches = Array.apply(null, new Array(c1.length + 1)).map(function () {
return [];
}), // set up the matching table
uniqueDescriptors = uniqueInBoth(c1, c2),
// If all of the elements are the same tag, id and class, then we can
// consider them roughly the same even if they have a different number of
// children. This will reduce removing and re-adding similar elements.
subsetsSame = c1.length === c2.length,
origin, ret;
if (subsetsSame) {
c1.some(function (element, i) {
var c1Desc = elementDescriptors(element),
c2Desc = elementDescriptors(c2[i]);
if (c1Desc.length !== c2Desc.length) {
subsetsSame = false;
return true;
}
c1Desc.some(function (description, i) {
if (description !== c2Desc[i]) {
subsetsSame = false;
return true;
}
});
if (!subsetsSame) {
return true;
}
});
}
// fill the matches with distance values
c1.forEach(function (c1Element, c1Index) {
c2.forEach(function (c2Element, c2Index) {
if (!marked1[c1Index] && !marked2[c2Index] && roughlyEqual(c1Element, c2Element, uniqueDescriptors, subsetsSame)) {
matches[c1Index + 1][c2Index + 1] = (matches[c1Index][c2Index] ? matches[c1Index][c2Index] + 1 : 1);
if (matches[c1Index + 1][c2Index + 1] >= lcsSize) {
lcsSize = matches[c1Index + 1][c2Index + 1];
index = [c1Index + 1, c2Index + 1];
}
} else {
matches[c1Index + 1][c2Index + 1] = 0;
}
});
});
if (lcsSize === 0) {
return false;
}
origin = [index[0] - lcsSize, index[1] - lcsSize];
ret = new SubsetMapping(origin[0], origin[1]);
ret.length = lcsSize;
return ret;
};
/**
* This should really be a predefined function in Array...
*/
var makeArray = function (n, v) {
return Array.apply(null, new Array(n)).map(function () {
return v;
});
};
/**
* Generate arrays that indicate which node belongs to which subset,
* or whether it's actually an orphan node, existing in only one
* of the two trees, rather than somewhere in both.
*
* So if t1 = <img><canvas><br>, t2 = <canvas><br><img>.
* The longest subset is "<canvas><br>" (length 2), so it will group 0.
* The second longest is "<img>" (length 1), so it will be group 1.
* gaps1 will therefore be [1,0,0] and gaps2 [0,0,1].
*
* If an element is not part of any group, it will stay being 'true', which
* is the initial value. For example:
* t1 = <img><p></p><br><canvas>, t2 = <b></b><br><canvas><img>
*
* The "<p></p>" and "<b></b>" do only show up in one of the two and will
* therefore be marked by "true". The remaining parts are parts of the
* groups 0 and 1:
* gaps1 = [1, true, 0, 0], gaps2 = [true, 0, 0, 1]
*
*/
var getGapInformation = function (t1, t2, stable) {
var gaps1 = t1.childNodes ? makeArray(t1.childNodes.length, true) : [],
gaps2 = t2.childNodes ? makeArray(t2.childNodes.length, true) : [],
group = 0;
// give elements from the same subset the same group number
stable.forEach(function (subset) {
var i, endOld = subset.old + subset.length,
endNew = subset.new + subset.length;
for (i = subset.old; i < endOld; i += 1) {
gaps1[i] = group;
}
for (i = subset.new; i < endNew; i += 1) {
gaps2[i] = group;
}
group += 1;
});
return {
gaps1: gaps1,
gaps2: gaps2
};
};
/**
* Find all matching subsets, based on immediate child differences only.
*/
var markSubTrees = function (oldTree, newTree) {
// note: the child lists are views, and so update as we update old/newTree
var oldChildren = oldTree.childNodes ? oldTree.childNodes : [],
newChildren = newTree.childNodes ? newTree.childNodes : [],
marked1 = makeArray(oldChildren.length, false),
marked2 = makeArray(newChildren.length, false),
subsets = [],
subset = true,
returnIndex = function () {
return arguments[1];
},
markBoth = function (i) {
marked1[subset.old + i] = true;
marked2[subset.new + i] = true;
};
while (subset) {
subset = findCommonSubsets(oldChildren, newChildren, marked1, marked2);
if (subset) {
subsets.push(subset);
Array.apply(null, new Array(subset.length)).map(returnIndex).forEach(markBoth);
}
}
return subsets;
};
function swap(obj, p1, p2) {
(function (_) {
obj[p1] = obj[p2];
obj[p2] = _;
}(obj[p1]));
}
var DiffTracker = function () {
this.list = [];
};
DiffTracker.prototype = {
list: false,
add: function (diffs) {
var list = this.list;
diffs.forEach(function (diff) {
list.push(diff);
});
},
forEach: function (fn) {
this.list.forEach(fn);
}
};
var diffDOM = function (options) {
var defaults = {
debug: false,
diffcap: 10, // Limit for how many diffs are accepting when debugging. Inactive when debug is false.
maxDepth: false, // False or a numeral. If set to a numeral, limits the level of depth that the the diff mechanism looks for differences. If false, goes through the entire tree.
valueDiffing: true, // Whether to take into consideration the values of forms that differ from auto assigned values (when a user fills out a form).
// syntax: textDiff: function (node, currentValue, expectedValue, newValue)
textDiff: function () {
arguments[0].data = arguments[3];
return;
}
},
i;
if (typeof options == "undefined") {
options = {};
}
for (i in defaults) {
if (typeof options[i] == "undefined") {
this[i] = defaults[i];
} else {
this[i] = options[i];
}
}
};
diffDOM.prototype = {
// ===== Create a diff =====
diff: function (t1Node, t2Node) {
var t1 = this.nodeToObj(t1Node),
t2 = this.nodeToObj(t2Node);
diffcount = 0;
if (this.debug) {
this.t1Orig = this.nodeToObj(t1Node);
this.t2Orig = this.nodeToObj(t2Node);
}
this.tracker = new DiffTracker();
return this.findDiffs(t1, t2);
},
findDiffs: function (t1, t2) {
var diffs;
do {
if (this.debug) {
diffcount += 1;
if (diffcount > this.diffcap) {
window.diffError = [this.t1Orig, this.t2Orig];
throw new Error("surpassed diffcap:" + JSON.stringify(this.t1Orig) + " -> " + JSON.stringify(this.t2Orig));
}
}
diffs = this.findNextDiff(t1, t2, []);
if (diffs.length === 0) {
// Last check if the elements really are the same now.
// If not, remove all info about being done and start over.
// Somtimes a node can be marked as done, but the creation of subsequent diffs means that it has to be changed anyway.
if (!isEqual(t1, t2)) {
removeDone(t1);
diffs = this.findNextDiff(t1, t2, []);
}
}
if (diffs.length > 0) {
this.tracker.add(diffs);
this.applyVirtual(t1, diffs);
}
} while (diffs.length > 0);
return this.tracker.list;
},
findNextDiff: function (t1, t2, route) {
var diffs;
if (this.maxDepth && route.length > this.maxDepth) {
return [];
}
// outer differences?
if (!t1.outerDone) {
diffs = this.findOuterDiff(t1, t2, route);
if (diffs.length > 0) {
t1.outerDone = true;
return diffs;
} else {
t1.outerDone = true;
}
}
// inner differences?
if (!t1.innerDone) {
diffs = this.findInnerDiff(t1, t2, route);
if (diffs.length > 0) {
return diffs;
} else {
t1.innerDone = true;
}
}
if (this.valueDiffing && !t1.valueDone) {
// value differences?
diffs = this.findValueDiff(t1, t2, route);
if (diffs.length > 0) {
t1.valueDone = true;
return diffs;
} else {
t1.valueDone = true;
}
}
// no differences
return [];
},
findOuterDiff: function (t1, t2, route) {
var diffs = [],
attr1, attr2;
if (t1.nodeName !== t2.nodeName) {
return [new Diff({
action: 'replaceElement',
oldValue: cloneObj(t1),
newValue: cloneObj(t2),
route: route
})];
}
if (t1.data !== t2.data) {
// Comment or text node.
if (t1.nodeName === '#text') {
return [new Diff({
action: 'modifyComment',
route: route,
oldValue: t1.data,
newValue: t2.data
})];
} else {
return [new Diff({
action: 'modifyTextElement',
route: route,
oldValue: t1.data,
newValue: t2.data
})];
}
}
attr1 = t1.attributes ? Object.keys(t1.attributes).sort() : [];
attr2 = t2.attributes ? Object.keys(t2.attributes).sort() : [];
attr1.forEach(function (attr) {
var pos = attr2.indexOf(attr);
if (pos === -1) {
diffs.push(new Diff({
action: 'removeAttribute',
route: route,
name: attr,
value: t1.attributes[attr]
}));
} else {
attr2.splice(pos, 1);
if (t1.attributes[attr] !== t2.attributes[attr]) {
diffs.push(new Diff({
action: 'modifyAttribute',
route: route,
name: attr,
oldValue: t1.attributes[attr],
newValue: t2.attributes[attr]
}));
}
}
});
attr2.forEach(function (attr) {
diffs.push(new Diff({
action: 'addAttribute',
route: route,
name: attr,
value: t2.attributes[attr]
}));
});
return diffs;
},
nodeToObj: function (node) {
var objNode = {}, dobj = this;
objNode.nodeName = node.nodeName;
if (objNode.nodeName === '#text' || objNode.nodeName === '#comment') {
objNode.data = node.data;
} else {
if (node.attributes && node.attributes.length > 0) {
objNode.attributes = {};
Array.prototype.slice.call(node.attributes).forEach(
function (attribute) {
objNode.attributes[attribute.name] = attribute.value;
}
);
}
if (node.childNodes && node.childNodes.length > 0) {
objNode.childNodes = [];
Array.prototype.slice.call(node.childNodes).forEach(
function (childNode) {
objNode.childNodes.push(dobj.nodeToObj(childNode));
}
);
}
if (this.valueDiffing) {
if (node.value) {
objNode.value = node.value;
}
if (node.checked) {
objNode.checked = node.checked;
}
if (node.selected) {
objNode.selected = node.selected;
}
}
}
return objNode;
},
objToNode: function (objNode, insideSvg) {
var node, dobj = this;
if (objNode.nodeName === '#text') {
node = document.createTextNode(objNode.data);
} else if (objNode.nodeName === '#comment') {
node = document.createComment(objNode.data);
} else {
if (objNode.nodeName === 'svg' || insideSvg) {
node = document.createElementNS('http://www.w3.org/2000/svg', objNode.nodeName);
insideSvg = true;
} else {
node = document.createElement(objNode.nodeName);
}
if (objNode.attributes) {
Object.keys(objNode.attributes).forEach(function (attribute) {
node.setAttribute(attribute, objNode.attributes[attribute]);
});
}
if (objNode.childNodes) {
objNode.childNodes.forEach(function (childNode) {
node.appendChild(dobj.objToNode(childNode, insideSvg));
});
}
if (this.valueDiffing) {
if (objNode.value) {
node.value = objNode.value;
}
if (objNode.checked) {
node.checked = objNode.checked;
}
if (objNode.selected) {
node.selected = objNode.selected;
}
}
}
return node;
},
findInnerDiff: function (t1, t2, route) {
var subtrees = (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [],
t1ChildNodes = t1.childNodes ? t1.childNodes : [],
t2ChildNodes = t2.childNodes ? t2.childNodes : [],
childNodesLengthDifference, diffs = [],
index = 0,
last, e1, e2, i;
if (subtrees.length > 1) {
/* Two or more groups have been identified among the childnodes of t1
* and t2.
*/
return this.attemptGroupRelocation(t1, t2, subtrees, route);
}
/* 0 or 1 groups of similar child nodes have been found
* for t1 and t2. 1 If there is 1, it could be a sign that the
* contents are the same. When the number of groups is below 2,
* t1 and t2 are made to have the same length and each of the
* pairs of child nodes are diffed.
*/
last = Math.max(t1ChildNodes.length, t2ChildNodes.length);
if (t1ChildNodes.length !== t2ChildNodes.length) {
childNodesLengthDifference = true;
}
for (i = 0; i < last; i += 1) {
e1 = t1ChildNodes[i];
e2 = t2ChildNodes[i];
if (childNodesLengthDifference) {
/* t1 and t2 have different amounts of childNodes. Add
* and remove as necessary to obtain the same length */
if (e1 && !e2) {
if (e1.nodeName === '#text') {
diffs.push(new Diff({
action: 'removeTextElement',
route: route.concat(index),
value: e1.data
}));
index -= 1;
} else {
diffs.push(new Diff({
action: 'removeElement',
route: route.concat(index),
element: cloneObj(e1)
}));
index -= 1;
}
} else if (e2 && !e1) {
if (e2.nodeName === '#text') {
diffs.push(new Diff({
action: 'addTextElement',
route: route.concat(index),
value: e2.data
}));
} else {
diffs.push(new Diff({
action: 'addElement',
route: route.concat(index),
element: cloneObj(e2)
}));
}
}
}
/* We are now guaranteed that childNodes e1 and e2 exist,
* and that they can be diffed.
*/
/* Diffs in child nodes should not affect the parent node,
* so we let these diffs be submitted together with other
* diffs.
*/
if (e1 && e2) {
diffs = diffs.concat(this.findNextDiff(e1, e2, route.concat(index)));
}
index += 1;
}
t1.innerDone = true;
return diffs;
},
attemptGroupRelocation: function (t1, t2, subtrees, route) {
/* Either t1.childNodes and t2.childNodes have the same length, or
* there are at least two groups of similar elements can be found.
* attempts are made at equalizing t1 with t2. First all initial
* elements with no group affiliation (gaps=true) are removed (if
* only in t1) or added (if only in t2). Then the creation of a group
* relocation diff is attempted.
*/
var gapInformation = getGapInformation(t1, t2, subtrees),
gaps1 = gapInformation.gaps1,
gaps2 = gapInformation.gaps2,
shortest = Math.min(gaps1.length, gaps2.length),
destinationDifferent, toGroup,
group, node, similarNode, testI, diffs = [],
index = 0,
i, j;
for (i = 0; i < shortest; i += 1) {
if (gaps1[i] === true) {
node = t1.childNodes[i];
if (node.nodeName === '#text') {
if (t2.childNodes[i].nodeName === '#text' && node.data !== t2.childNodes[i].data) {
testI = i;
while (t1.childNodes.length > testI + 1 && t1.childNodes[testI + 1].nodeName === '#text') {
testI += 1;
if (t2.childNodes[i].data === t1.childNodes[testI].data) {
similarNode = true;
break;
}
}
if (!similarNode) {
diffs.push(new Diff({
action: 'modifyTextElement',
route: route.concat(index),
oldValue: node.data,
newValue: t2.childNodes[i].data
}));
}
}
diffs.push(new Diff({
action: 'removeTextElement',
route: route.concat(index),
value: node.data
}));
index -= 1;
} else {
diffs.push(new Diff({
action: 'removeElement',
route: route.concat(index),
element: cloneObj(node)
}));
index -= 1;
}
} else if (gaps2[i] === true) {
node = t2.childNodes[i];
if (node.nodeName === '#text') {
diffs.push(new Diff({
action: 'addTextElement',
route: route.concat(index),
value: node.data
}));
index += 1;
} else {
diffs.push(new Diff({
action: 'addElement',
route: route.concat(index),
element: cloneObj(node)
}));
index += 1;
}
} else if (gaps1[i] !== gaps2[i]) {
if (diffs.length > 0) {
return diffs;
}
// group relocation
group = subtrees[gaps1[i]];
toGroup = Math.min(group.new, (t1.childNodes.length - group.length));
if (toGroup !== group.old) {
// Check whether destination nodes are different than originating ones.
destinationDifferent = false;
for (j = 0; j < group.length; j += 1) {
if (!roughlyEqual(t1.childNodes[toGroup + j], t1.childNodes[group.old + j], [], false, true)) {
destinationDifferent = true;
}
}
if (destinationDifferent) {
return [new Diff({
action: 'relocateGroup',
groupLength: group.length,
from: group.old,
to: toGroup,
route: route
})];
}
}
}
index += 1;
}
return diffs;
},
findValueDiff: function (t1, t2, route) {
// Differences of value. Only useful if the value/selection/checked value
// differs from what is represented in the DOM. For example in the case
// of filled out forms, etc.
var diffs = [];
if (t1.selected !== t2.selected) {
diffs.push(new Diff({
action: 'modifySelected',
oldValue: t1.selected,
newValue: t2.selected,
route: route
}));
}
if ((t1.value || t2.value) && t1.value !== t2.value && t1.nodeName !== 'OPTION') {
diffs.push(new Diff({
action: 'modifyValue',
oldValue: t1.value,
newValue: t2.value,
route: route
}));
}
if (t1.checked !== t2.checked) {
diffs.push(new Diff({
action: 'modifyChecked',
oldValue: t1.checked,
newValue: t2.checked,
route: route
}));
}
return diffs;
},
// ===== Apply a virtual diff =====
applyVirtual: function (tree, diffs) {
var dobj = this;
if (diffs.length === 0) {
return true;
}
diffs.forEach(function (diff) {
// console.log(JSON.stringify(diff));
// console.log(JSON.stringify(tree));
// console.log(this.objToNode(tree).outerHTML);
dobj.applyVirtualDiff(tree, diff);
// console.log(JSON.stringify(tree));
// console.log(this.objToNode(tree).outerHTML);
});
return true;
},
getFromVirtualRoute: function (tree, route) {
var node = tree,
parentNode, nodeIndex;
route = route.slice();
while (route.length > 0) {
if (!node.childNodes) {
return false;
}
nodeIndex = route.splice(0, 1)[0];
parentNode = node;
node = node.childNodes[nodeIndex];
}
return {
node: node,
parentNode: parentNode,
nodeIndex: nodeIndex
};
},
applyVirtualDiff: function (tree, diff) {
var routeInfo = this.getFromVirtualRoute(tree, diff.route),
node = routeInfo.node,
parentNode = routeInfo.parentNode,
nodeIndex = routeInfo.nodeIndex,
newNode, route, c;
switch (diff.action) {
case 'addAttribute':
if (!node.attributes) {
node.attributes = {};
}
node.attributes[diff.name] = diff.value;
if (diff.name === 'checked') {
node.checked = true;
} else if (diff.name === 'selected') {
node.selected = true;
} else if (node.nodeName === 'INPUT' && diff.name === 'value') {
node.value = diff.value;
}
break;
case 'modifyAttribute':
node.attributes[diff.name] = diff.newValue;
if (node.nodeName === 'INPUT' && diff.name === 'value') {
node.value = diff.value;
}
break;
case 'removeAttribute':
delete node.attributes[diff.name];
if (Object.keys(node.attributes).length === 0) {
delete node.attributes;
}
if (diff.name === 'checked') {
delete node.checked;
} else if (diff.name === 'selected') {
delete node.selected;
} else if (node.nodeName === 'INPUT' && diff.name === 'value') {
delete node.value;
}
break;
case 'modifyTextElement':
node.data = diff.newValue;
if (parentNode.nodeName === 'TEXTAREA') {
parentNode.value = diff.newValue;
}
break;
case 'modifyValue':
node.value = diff.newValue;
break;
case 'modifyComment':
node.data = diff.newValue;
break;
case 'modifyChecked':
node.checked = diff.newValue;
break;
case 'modifySelected':
node.selected = diff.newValue;
break;
case 'replaceElement':
newNode = cloneObj(diff.newValue);
newNode.outerDone = true;
newNode.innerDone = true;
newNode.valueDone = true;
parentNode.childNodes[nodeIndex] = newNode;
break;
case 'relocateGroup':
node.childNodes.splice(diff.from, diff.groupLength).reverse()
.forEach(function (movedNode) {
node.childNodes.splice(diff.to, 0, movedNode);
});
break;
case 'removeElement':
parentNode.childNodes.splice(nodeIndex, 1);
break;
case 'addElement':
route = diff.route.slice();
c = route.splice(route.length - 1, 1)[0];
node = this.getFromVirtualRoute(tree, route).node;
newNode = cloneObj(diff.element);
newNode.outerDone = true;
newNode.innerDone = true;
newNode.valueDone = true;
if (!node.childNodes) {
node.childNodes = [];
}
if (c >= node.childNodes.length) {
node.childNodes.push(newNode);
} else {
node.childNodes.splice(c, 0, newNode);
}
break;
case 'removeTextElement':
parentNode.childNodes.splice(nodeIndex, 1);
if (parentNode.nodeName === 'TEXTAREA') {
delete parentNode.value;
}
break;
case 'addTextElement':
route = diff.route.slice();
c = route.splice(route.length - 1, 1)[0];
newNode = {};
newNode.nodeName = '#text';
newNode.data = diff.value;
node = this.getFromVirtualRoute(tree, route).node;
if (!node.childNodes) {
node.childNodes = [];
}
if (c >= node.childNodes.length) {
node.childNodes.push(newNode);
} else {
node.childNodes.splice(c, 0, newNode);
}
if (node.nodeName === 'TEXTAREA') {
node.value = diff.newValue;
}
break;
default:
console.log('unknown action');
}
return;
},
// ===== Apply a diff =====
apply: function (tree, diffs) {
var dobj = this;
if (diffs.length === 0) {
return true;
}
diffs.forEach(function (diff) {
if (!dobj.applyDiff(tree, diff)) {
return false;
}
});
return true;
},
getFromRoute: function (tree, route) {
route = route.slice();
var c, node = tree;
while (route.length > 0) {
if (!node.childNodes) {
return false;
}
c = route.splice(0, 1)[0];
node = node.childNodes[c];
}
return node;
},
applyDiff: function (tree, diff) {
var node = this.getFromRoute(tree, diff.route),
newNode, reference, route, c;
switch (diff.action) {
case 'addAttribute':
if (!node || !node.setAttribute) {
return false;
}
node.setAttribute(diff.name, diff.value);
break;
case 'modifyAttribute':
if (!node || !node.setAttribute) {
return false;
}
node.setAttribute(diff.name, diff.newValue);
break;
case 'removeAttribute':
if (!node || !node.removeAttribute) {
return false;
}
node.removeAttribute(diff.name);
break;
case 'modifyTextElement':
if (!node || node.nodeType !== 3) {
return false;
}
this.textDiff(node, node.data, diff.oldValue, diff.newValue);
break;
case 'modifyValue':
if (!node || typeof node.value === 'undefined') {
return false;
}
node.value = diff.newValue;
break;
case 'modifyComment':
if (!node || typeof node.data === 'undefined') {
return false;
}
node.data = diff.newValue;
break;
case 'modifyChecked':
if (!node || typeof node.checked === 'undefined') {
return false;
}
node.checked = diff.newValue;
break;
case 'modifySelected':
if (!node || typeof node.selected === 'undefined') {
return false;
}
node.selected = diff.newValue;
break;
case 'replaceElement':
node.parentNode.replaceChild(this.objToNode(diff.newValue), node);
break;
case 'relocateGroup':
Array.apply(null, new Array(diff.groupLength)).map(function () {
return node.removeChild(node.childNodes[diff.from]);
}).forEach(function (childNode, index) {
if (index === 0) {
reference = node.childNodes[diff.to];
}
node.insertBefore(childNode, reference);
});
break;
case 'removeElement':
node.parentNode.removeChild(node);
break;
case 'addElement':
route = diff.route.slice();
c = route.splice(route.length - 1, 1)[0];
node = this.getFromRoute(tree, route);
node.insertBefore(this.objToNode(diff.element), node.childNodes[c]);
break;
case 'removeTextElement':
if (!node || node.nodeType !== 3) {
return false;
}
node.parentNode.removeChild(node);
break;
case 'addTextElement':
route = diff.route.slice();
c = route.splice(route.length - 1, 1)[0];
newNode = document.createTextNode(diff.value);
node = this.getFromRoute(tree, route);
if (!node || !node.childNodes) {
return false;
}
node.insertBefore(newNode, node.childNodes[c]);
break;
default:
console.log('unknown action');
}
return true;
},
// ===== Undo a diff =====
undo: function (tree, diffs) {
diffs = diffs.slice();
var dobj = this;
if (!diffs.length) {
diffs = [diffs];
}
diffs.reverse();
diffs.forEach(function (diff) {
dobj.undoDiff(tree, diff);
});
},
undoDiff: function (tree, diff) {
switch (diff.action) {
case 'addAttribute':
diff.action = 'removeAttribute';
this.applyDiff(tree, diff);
break;
case 'modifyAttribute':
swap(diff, 'oldValue', 'newValue');
this.applyDiff(tree, diff);
break;
case 'removeAttribute':
diff.action = 'addAttribute';
this.applyDiff(tree, diff);
break;
case 'modifyTextElement':
swap(diff, 'oldValue', 'newValue');
this.applyDiff(tree, diff);
break;
case 'modifyValue':
swap(diff, 'oldValue', 'newValue');
this.applyDiff(tree, diff);
break;
case 'modifyComment':
swap(diff, 'oldValue', 'newValue');
this.applyDiff(tree, diff);
break;
case 'modifyChecked':
swap(diff, 'oldValue', 'newValue');
this.applyDiff(tree, diff);
break;
case 'modifySelected':
swap(diff, 'oldValue', 'newValue');
this.applyDiff(tree, diff);
break;
case 'replaceElement':
swap(diff, 'oldValue', 'newValue');
this.applyDiff(tree, diff);
break;
case 'relocateGroup':
swap(diff, 'from', 'to');
this.applyDiff(tree, diff);
break;
case 'removeElement':
diff.action = 'addElement';
this.applyDiff(tree, diff);
break;
case 'addElement':
diff.action = 'removeElement';
this.applyDiff(tree, diff);
break;
case 'removeTextElement':
diff.action = 'addTextElement';
this.applyDiff(tree, diff);
break;
case 'addTextElement':
diff.action = 'removeTextElement';
this.applyDiff(tree, diff);
break;
default:
console.log('unknown action');
}
}
};
window.diffDOM = diffDOM;
================================================
FILE: app/templates/app/src/lib/hammer.js
================================================
/*! Hammer.JS - v2.0.4 - 2014-09-28
* http://hammerjs.github.io/
*
* Copyright (c) 2014 Jorik Tangelder;
* Licensed under the MIT license */
;
(function (window, document, exportName, undefined) {
'use strict';
var VENDOR_PREFIXES = ['', 'webkit', 'moz', 'MS', 'ms', 'o'];
var TEST_ELEMENT = document.createElement('div');
var TYPE_FUNCTION = 'function';
var round = Math.round;
var abs = Math.abs;
var now = Date.now;
/**
* set a timeout with a given scope
* @param {Function} fn
* @param {Number} timeout
* @param {Object} context
* @returns {number}
*/
function setTimeoutContext(fn, timeout, context) {
return setTimeout(bindFn(fn, context), timeout);
}
/**
* if the argument is an array, we want to execute the fn on each entry
* if it aint an array we don't want to do a thing.
* this is used by all the methods that accept a single and array argument.
* @param {*|Array} arg
* @param {String} fn
* @param {Object} [context]
* @returns {Boolean}
*/
function invokeArrayArg(arg, fn, context) {
if (Array.isArray(arg)) {
each(arg, context[fn], context);
return true;
}
return false;
}
/**
* walk objects and arrays
* @param {Object} obj
* @param {Function} iterator
* @param {Object} context
*/
function each(obj, iterator, context) {
var i;
if (!obj) {
return;
}
if (obj.forEach) {
obj.forEach(iterator, context);
} else if (obj.length !== undefined) {
i = 0;
while (i < obj.length) {
iterator.call(context, obj[i], i, obj);
i++;
}
} else {
for (i in obj) {
obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
}
}
}
/**
* extend object.
* means that properties in dest will be overwritten by the ones in src.
* @param {Object} dest
* @param {Object} src
* @param {Boolean} [merge]
* @returns {Object} dest
*/
function extend(dest, src, merge) {
var keys = Object.keys(src);
var i = 0;
while (i < keys.length) {
if (!merge || (merge && dest[keys[i]] === undefined)) {
dest[keys[i]] =
gitextract_xg95i7qs/
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .jshintrc
├── .travis.yml
├── .yo-rc.json
├── LICENSE
├── README.md
├── app/
│ ├── index.js
│ └── templates/
│ ├── _package.json
│ ├── app/
│ │ ├── .babelrc
│ │ ├── README.md
│ │ ├── data/
│ │ │ └── user.json
│ │ ├── gulpfile.js
│ │ ├── html/
│ │ │ ├── debug/
│ │ │ │ ├── analytics.html
│ │ │ │ └── index.html
│ │ │ ├── include/
│ │ │ │ ├── cache.manifest
│ │ │ │ ├── components.html
│ │ │ │ ├── download.html
│ │ │ │ ├── footer.html
│ │ │ │ ├── htmlhead.html
│ │ │ │ ├── manifest-version.html
│ │ │ │ ├── msgbox-deja.html
│ │ │ │ ├── msgbox.html
│ │ │ │ ├── scripts-version.html
│ │ │ │ ├── styles-version.html
│ │ │ │ ├── tooltip.html
│ │ │ │ ├── view-home.html
│ │ │ │ ├── view-user.html
│ │ │ │ └── views.html
│ │ │ └── official/
│ │ │ ├── analytics.html
│ │ │ └── index.html
│ │ ├── scss/
│ │ │ ├── _animate.scss
│ │ │ ├── _box.scss
│ │ │ ├── _button.scss
│ │ │ ├── _common.scss
│ │ │ ├── _components.scss
│ │ │ ├── _fonts.scss
│ │ │ ├── _footer.scss
│ │ │ ├── _header.scss
│ │ │ ├── _icon.scss
│ │ │ ├── _list.scss
│ │ │ ├── _loading-spinner.scss
│ │ │ ├── _mixin.scss
│ │ │ ├── _msgbox-android.scss
│ │ │ ├── _msgbox-deja.scss
│ │ │ ├── _msgbox.scss
│ │ │ ├── _section-download.scss
│ │ │ ├── _slide.scss
│ │ │ ├── _sprites.scss
│ │ │ ├── _tooltip.scss
│ │ │ ├── _util.scss
│ │ │ ├── _value.scss
│ │ │ ├── _view-home.scss
│ │ │ ├── _view-user.scss
│ │ │ ├── _view.scss
│ │ │ └── styles.scss
│ │ ├── src/
│ │ │ ├── app/
│ │ │ │ ├── App.js
│ │ │ │ ├── controller/
│ │ │ │ │ ├── Controller.js
│ │ │ │ │ ├── HomeController.js
│ │ │ │ │ └── UserController.js
│ │ │ │ ├── model/
│ │ │ │ │ ├── Model.js
│ │ │ │ │ ├── RequestHelper.js
│ │ │ │ │ ├── StoreHelper.js
│ │ │ │ │ └── UserModel.js
│ │ │ │ ├── resources/
│ │ │ │ │ ├── Actions.js
│ │ │ │ │ ├── Audios.js
│ │ │ │ │ └── i18n/
│ │ │ │ │ ├── en_US/
│ │ │ │ │ │ ├── Msgbox.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── zh_CN/
│ │ │ │ │ ├── Msgbox.js
│ │ │ │ │ └── index.js
│ │ │ │ └── view/
│ │ │ │ ├── HomeView.js
│ │ │ │ ├── UserView.js
│ │ │ │ └── View.js
│ │ │ ├── core/
│ │ │ │ ├── Class.js
│ │ │ │ ├── Event.js
│ │ │ │ ├── HashHandler.js
│ │ │ │ ├── MicroTmpl.js
│ │ │ │ ├── NativeBridge.js
│ │ │ │ ├── Navigator.js
│ │ │ │ ├── Pubsub.js
│ │ │ │ ├── Router.js
│ │ │ │ └── Subject.js
│ │ │ ├── lib/
│ │ │ │ ├── Core.js
│ │ │ │ ├── Core.standalone.js
│ │ │ │ ├── diffDOM.js
│ │ │ │ ├── hammer.js
│ │ │ │ ├── impress.js
│ │ │ │ ├── rebound.js
│ │ │ │ ├── swing/
│ │ │ │ │ ├── card.js
│ │ │ │ │ ├── dom.js
│ │ │ │ │ ├── sister.js
│ │ │ │ │ ├── stack.js
│ │ │ │ │ ├── swing.js
│ │ │ │ │ └── vendor-prefix.js
│ │ │ │ ├── velocity.js
│ │ │ │ ├── velocityui.js
│ │ │ │ ├── zepto.js
│ │ │ │ └── zepto.waypoints.js
│ │ │ ├── util/
│ │ │ │ ├── AppCache.js
│ │ │ │ ├── Base64.js
│ │ │ │ ├── DateHandler.js
│ │ │ │ ├── Easing.js
│ │ │ │ ├── FacebookShare.js
│ │ │ │ ├── FormHandler.js
│ │ │ │ ├── GUID.js
│ │ │ │ ├── ImpressGenerator.js
│ │ │ │ ├── LocalHost.js
│ │ │ │ ├── LocalParam.js
│ │ │ │ ├── LocalStorage.js
│ │ │ │ ├── MetaHandler.js
│ │ │ │ ├── Number.js
│ │ │ │ ├── OpenAppInBrowser.js
│ │ │ │ ├── RandomColor.js
│ │ │ │ ├── RandomList.js
│ │ │ │ ├── RequestAnimationFrame.js
│ │ │ │ ├── RequestHandler.js
│ │ │ │ ├── Scratch.js
│ │ │ │ ├── SeededRandom.js
│ │ │ │ ├── Shake.js
│ │ │ │ ├── SimpleSlider.js
│ │ │ │ ├── Slider.js
│ │ │ │ ├── SlotMachine.js
│ │ │ │ ├── TabStatus.js
│ │ │ │ ├── ThirdVendor.js
│ │ │ │ ├── Unveil.js
│ │ │ │ ├── VersionCompare.js
│ │ │ │ ├── VirtualDOMLite.js
│ │ │ │ ├── WaypointsHandler.js
│ │ │ │ ├── WechatShare.js
│ │ │ │ └── YiXinShare.js
│ │ │ └── widget/
│ │ │ ├── Msgbox.js
│ │ │ └── Tooltip.js
│ │ └── webpack.config.js
│ ├── editorconfig
│ ├── ftppass
│ ├── gitignore
│ └── jshintrc
├── model/
│ ├── index.js
│ └── templates/
│ └── Model.js
├── module/
│ ├── index.js
│ └── templates/
│ ├── ModuleController.js
│ ├── ModuleView.js
│ ├── module.html
│ └── module.scss
├── package.json
├── test/
│ └── test-app.js
└── update/
└── index.js
SYMBOL INDEX (268 symbols across 62 files)
FILE: app/templates/app/gulpfile.js
function getProtractorBinary (line 372) | function getProtractorBinary(binaryName){
function handleError (line 400) | function handleError(err) {
FILE: app/templates/app/src/app/App.js
function App (line 11) | function App() {
FILE: app/templates/app/src/app/controller/Controller.js
function Controller (line 6) | function Controller() {
FILE: app/templates/app/src/app/controller/HomeController.js
function HomeController (line 6) | function HomeController() {
FILE: app/templates/app/src/app/controller/UserController.js
function UserController (line 7) | function UserController() {
FILE: app/templates/app/src/app/model/Model.js
function Model (line 7) | function Model() {
FILE: app/templates/app/src/app/model/RequestHelper.js
function request (line 5) | function request(action, data, callback, scope, options) {
function post (line 28) | function post(action, data, callback, scope, options) {
FILE: app/templates/app/src/app/model/StoreHelper.js
function pagingStore (line 3) | function pagingStore(action, options) {
function requestStore (line 62) | function requestStore(action, options) {
function postStore (line 73) | function postStore(action, options) {
function JSONPStore (line 84) | function JSONPStore(action, options) {
function pagingJSONPStore (line 110) | function pagingJSONPStore(action, options) {
FILE: app/templates/app/src/app/model/UserModel.js
function User (line 8) | function User() {
FILE: app/templates/app/src/app/resources/i18n/index.js
function getLangName (line 9) | function getLangName(lang) {
function i18n (line 23) | function i18n() {
function createI18n (line 28) | function createI18n(lang) {
FILE: app/templates/app/src/app/resources/i18n/zh_CN/index.js
function zh_CN (line 3) | function zh_CN() {
FILE: app/templates/app/src/app/view/HomeView.js
function HomeView (line 5) | function HomeView() {
FILE: app/templates/app/src/app/view/UserView.js
function UserView (line 5) | function UserView() {
FILE: app/templates/app/src/app/view/View.js
function View (line 8) | function View() {
FILE: app/templates/app/src/core/Class.js
function apply (line 9) | function apply(obj, config, promise) {
function applyIf (line 25) | function applyIf(obj, config, promise) {
function objectEquals (line 79) | function objectEquals(x, y) {
function updateFactory (line 146) | function updateFactory() {
function Model (line 215) | function Model(option) {
FILE: app/templates/app/src/core/Event.js
function Event (line 6) | function Event(Subject) {
FILE: app/templates/app/src/core/HashHandler.js
function getByURL (line 4) | function getByURL(url) {
function get (line 12) | function get() {
function set (line 16) | function set(hash) {
FILE: app/templates/app/src/core/MicroTmpl.js
function isElement (line 30) | function isElement(o) {
function hasChildTmplAttr (line 37) | function hasChildTmplAttr(el) {
function removeChildTmplAttrs (line 47) | function removeChildTmplAttrs(el) {
function getTmpl (line 54) | function getTmpl(str) {
function tmpl (line 73) | function tmpl(str, data) {
FILE: app/templates/app/src/core/NativeBridge.js
function NativeBridge (line 18) | function NativeBridge(protocolHandler) {
FILE: app/templates/app/src/core/Navigator.js
function appendFrame (line 16) | function appendFrame(frame) {
function removeFrame (line 26) | function removeFrame(frame) {
function getFrame (line 36) | function getFrame(src, name) {
function excute (line 61) | function excute(ns, fn, option, single, noframe) {
function protocol (line 83) | function protocol(command, single, noframe) {
FILE: app/templates/app/src/core/Pubsub.js
function Pubsub (line 1) | function Pubsub(Subject) {
FILE: app/templates/app/src/core/Router.js
function Router (line 29) | function Router(Pubsub, HashHandler) {
FILE: app/templates/app/src/core/Subject.js
function Subject (line 1) | function Subject(subject) {
FILE: app/templates/app/src/lib/diffDOM.js
function swap (line 404) | function swap(obj, p1, p2) {
FILE: app/templates/app/src/lib/hammer.js
function setTimeoutContext (line 26) | function setTimeoutContext(fn, timeout, context) {
function invokeArrayArg (line 39) | function invokeArrayArg(arg, fn, context) {
function each (line 53) | function each(obj, iterator, context) {
function extend (line 83) | function extend(dest, src, merge) {
function merge (line 102) | function merge(dest, src) {
function inherit (line 112) | function inherit(child, base, properties) {
function bindFn (line 131) | function bindFn(fn, context) {
function boolOrFn (line 144) | function boolOrFn(val, args) {
function ifUndefined (line 157) | function ifUndefined(val1, val2) {
function addEventListeners (line 167) | function addEventListeners(target, types, handler) {
function removeEventListeners (line 179) | function removeEventListeners(target, types, handler) {
function hasParent (line 192) | function hasParent(node, parent) {
function inStr (line 208) | function inStr(str, find) {
function splitStr (line 217) | function splitStr(str) {
function inArray (line 228) | function inArray(src, find, findByKey) {
function toArray (line 248) | function toArray(obj) {
function uniqueArray (line 259) | function uniqueArray(src, key, sort) {
function prefixed (line 292) | function prefixed(obj, property) {
function uniqueId (line 315) | function uniqueId() {
function getWindowForElement (line 324) | function getWindowForElement(element) {
function Input (line 367) | function Input(manager, callback) {
function createInputInstance (line 419) | function createInputInstance(manager) {
function inputHandler (line 443) | function inputHandler(manager, eventType, input) {
function computeInputData (line 475) | function computeInputData(manager, input) {
function computeDeltaXY (line 519) | function computeDeltaXY(session, input) {
function computeIntervalInputData (line 546) | function computeIntervalInputData(session, input) {
function simpleCloneInputData (line 581) | function simpleCloneInputData(input) {
function getCenter (line 608) | function getCenter(pointers) {
function getVelocity (line 639) | function getVelocity(deltaTime, x, y) {
function getDirection (line 652) | function getDirection(x, y) {
function getDistance (line 670) | function getDistance(p1, p2, props) {
function getAngle (line 687) | function getAngle(p1, p2, props) {
function getRotation (line 702) | function getRotation(start, end) {
function getScale (line 713) | function getScale(start, end) {
function MouseInput (line 731) | function MouseInput() {
function PointerEventInput (line 806) | function PointerEventInput() {
function SingleTouchInput (line 880) | function SingleTouchInput() {
function normalizeSingleTouches (line 923) | function normalizeSingleTouches(ev, type) {
function TouchInput (line 948) | function TouchInput() {
function getTouches (line 978) | function getTouches(ev, type) {
function TouchMouseInput (line 1042) | function TouchMouseInput() {
function TouchAction (line 1104) | function TouchAction(manager, value) {
function cleanTouchActions (line 1193) | function cleanTouchActions(actions) {
function Recognizer (line 1261) | function Recognizer(options) {
function emit (line 1393) | function emit(withState) {
function stateStr (line 1501) | function stateStr(state) {
function directionStr (line 1519) | function directionStr(direction) {
function getRecognizerByNameIfManager (line 1538) | function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
function AttrRecognizer (line 1551) | function AttrRecognizer() {
function PanRecognizer (line 1613) | function PanRecognizer() {
function PinchRecognizer (line 1692) | function PinchRecognizer() {
function PressRecognizer (line 1731) | function PressRecognizer() {
function RotateRecognizer (line 1802) | function RotateRecognizer() {
function SwipeRecognizer (line 1833) | function SwipeRecognizer() {
function TapRecognizer (line 1892) | function TapRecognizer() {
function Hammer (line 2003) | function Hammer(element, options) {
function Manager (line 2135) | function Manager(element, options) {
function toggleCssProps (line 2388) | function toggleCssProps(manager, add) {
function triggerDomEvent (line 2400) | function triggerDomEvent(event, data) {
FILE: app/templates/app/src/lib/rebound.js
function removeFirst (line 983) | function removeFirst(array, item) {
FILE: app/templates/app/src/lib/swing/card.js
function doMove (line 90) | function doMove() {
function cancelMove (line 105) | function cancelMove() {
FILE: app/templates/app/src/lib/swing/sister.js
function Sister (line 7) | function Sister() {
FILE: app/templates/app/src/lib/swing/vendor-prefix.js
function get (line 7) | function get(key) {
function prefix (line 11) | function prefix(key) {
function capitalize (line 30) | function capitalize(str) {
function dashedPrefix (line 34) | function dashedPrefix(key) {
FILE: app/templates/app/src/lib/velocity.js
function isArraylike (line 56) | function isArraylike(obj) {
function $makeArray (line 240) | function $makeArray(arr, results) {
function offsetParent (line 348) | function offsetParent() {
function compactSparseArray (line 484) | function compactSparseArray(array) {
function sanitizeElements (line 500) | function sanitizeElements(elements) {
function Data (line 674) | function Data(element) {
function generateStep (line 687) | function generateStep(steps) {
function generateBezier (line 694) | function generateBezier(mX1, mY1, mX2, mY2) {
function springAccelerationForState (line 834) | function springAccelerationForState(state) {
function springEvaluateStateWithDerivative (line 838) | function springEvaluateStateWithDerivative(initialState, dt, derivative) {
function springIntegrateState (line 849) | function springIntegrateState(state, dt) {
function getEasing (line 966) | function getEasing(value, duration) {
function computePropertyValue (line 1639) | function computePropertyValue(element, property) {
function getTransformFloat (line 1922) | function getTransformFloat(transformProperty) {
function getChain (line 2043) | function getChain() {
function processElement (line 2385) | function processElement() {
function tick (line 3394) | function tick(timestamp) {
function completeCall (line 3649) | function completeCall(callIndex, isStopped) {
FILE: app/templates/app/src/lib/velocityui.js
function greaterSemver (line 37) | function greaterSemver(primary, secondary) {
function animateParentHeight (line 73) | function animateParentHeight(elements, direction, totalDuration, stagger) {
function injectFinalCallbacks (line 171) | function injectFinalCallbacks() {
FILE: app/templates/app/src/lib/zepto.js
function type (line 74) | function type(obj) {
function isFunction (line 79) | function isFunction(value) {
function isWindow (line 83) | function isWindow(obj) {
function isDocument (line 87) | function isDocument(obj) {
function isObject (line 91) | function isObject(obj) {
function isPlainObject (line 95) | function isPlainObject(obj) {
function likeArray (line 99) | function likeArray(obj) {
function compact (line 103) | function compact(array) {
function flatten (line 109) | function flatten(array) {
function dasherize (line 118) | function dasherize(str) {
function classRE (line 132) | function classRE(name) {
function maybeAddPx (line 137) | function maybeAddPx(name, value) {
function defaultDisplay (line 141) | function defaultDisplay(nodeName) {
function children (line 154) | function children(element) {
function extend (line 266) | function extend(target, source, deep) {
function filtered (line 312) | function filtered(nodes, selector) {
function funcArg (line 326) | function funcArg(context, arg, idx, payload) {
function setAttribute (line 330) | function setAttribute(node, name, value) {
function className (line 335) | function className(node, value) {
function deserializeValue (line 351) | function deserializeValue(value) {
function traverseNode (line 911) | function traverseNode(node, fun) {
function zid (line 996) | function zid(element) {
function findHandlers (line 1000) | function findHandlers(element, event, fn, selector) {
function parse (line 1012) | function parse(event) {
function matcherFor (line 1017) | function matcherFor(ns) {
function eventCapture (line 1021) | function eventCapture(handler, captureSetting) {
function realEvent (line 1026) | function realEvent(type) {
function add (line 1030) | function add(element, events, fn, data, selector, delegator, capture) {
function remove (line 1060) | function remove(element, events, fn, selector, capture) {
function compatible (line 1117) | function compatible(event, source) {
function createProxy (line 1138) | function createProxy(event) {
function triggerAndReturn (line 1281) | function triggerAndReturn(context, eventName, data) {
function triggerGlobal (line 1288) | function triggerGlobal(settings, context, eventName, data) {
function ajaxStart (line 1295) | function ajaxStart(settings) {
function ajaxStop (line 1299) | function ajaxStop(settings) {
function ajaxBeforeSend (line 1304) | function ajaxBeforeSend(xhr, settings) {
function ajaxSuccess (line 1313) | function ajaxSuccess(data, xhr, settings, deferred) {
function ajaxError (line 1322) | function ajaxError(error, type, xhr, settings, deferred) {
function ajaxComplete (line 1331) | function ajaxComplete(status, xhr, settings) {
function empty (line 1339) | function empty() {
function mimeToDataType (line 1432) | function mimeToDataType(mime) {
function appendQuery (line 1440) | function appendQuery(url, query) {
function serializeData (line 1446) | function serializeData(options) {
function parseArguments (line 1562) | function parseArguments(url, data, success, dataType) {
function serialize (line 1607) | function serialize(params, obj, traditional, scope) {
function detect (line 1709) | function detect(ua, platform) {
function dasherize (line 1788) | function dasherize(str) {
function normalizeEvent (line 1792) | function normalizeEvent(name) {
function swipeDirection (line 1912) | function swipeDirection(x1, x2, y1, y2) {
function longTap (line 1917) | function longTap() {
function cancelLongTap (line 1925) | function cancelLongTap() {
function cancelAll (line 1930) | function cancelAll() {
function isPrimaryTouch (line 1939) | function isPrimaryTouch(event) {
function isPointerEventType (line 1945) | function isPointerEventType(e, type) {
function parentIfText (line 2073) | function parentIfText(node) {
function visible (line 2108) | function visible(elem) {
function process (line 2161) | function process(sel, fn) {
FILE: app/templates/app/src/lib/zepto.waypoints.js
function Waypoint (line 14) | function Waypoint(options) {
function requestAnimationFrameShim (line 171) | function requestAnimationFrameShim(callback) {
function Context (line 181) | function Context(element) {
function resizeHandler (line 226) | function resizeHandler() {
function scrollHandler (line 243) | function scrollHandler() {
function byTriggerPoint (line 473) | function byTriggerPoint(a, b) {
function byReverseTriggerPoint (line 477) | function byReverseTriggerPoint(a, b) {
function Group (line 488) | function Group(options) {
function ZeptoAdapter (line 582) | function ZeptoAdapter(element) {
function createDimensionMethod (line 610) | function createDimensionMethod($element, includeBorder) {
function createExtension (line 666) | function createExtension(framework) {
FILE: app/templates/app/src/util/DateHandler.js
function getStrDate (line 2) | function getStrDate(str) {
function dbl00 (line 11) | function dbl00(num) {
function getMeta (line 15) | function getMeta(date) {
function formatStr (line 35) | function formatStr(str) {
function fromNowTo (line 40) | function fromNowTo(date) {
function timeLogFromNowTo (line 70) | function timeLogFromNowTo(date) {
function getDaysInMonth (line 89) | function getDaysInMonth(y, m) {
FILE: app/templates/app/src/util/FacebookShare.js
function share (line 16) | function share(data) {
FILE: app/templates/app/src/util/FormHandler.js
function getForm (line 10) | function getForm(method) {
FILE: app/templates/app/src/util/GUID.js
function GUID (line 1) | function GUID(len) {
FILE: app/templates/app/src/util/ImpressGenerator.js
function initImpress (line 8) | function initImpress(option) {
function getInstance (line 31) | function getInstance(attrs, ioption) {
function setAttr (line 39) | function setAttr(el, attr) {
FILE: app/templates/app/src/util/LocalParam.js
function localParam (line 5) | function localParam(search, hash) {
FILE: app/templates/app/src/util/LocalStorage.js
function localStorage (line 1) | function localStorage() {
FILE: app/templates/app/src/util/MetaHandler.js
function init (line 26) | function init() {
function getContentStore (line 41) | function getContentStore(name) {
function updateContent (line 83) | function updateContent(name) {
FILE: app/templates/app/src/util/Number.js
function formatMoney (line 1) | function formatMoney(num) {
function countNum (line 13) | function countNum(option) {
function randomArbitrary (line 46) | function randomArbitrary(min, max) {
FILE: app/templates/app/src/util/OpenAppInBrowser.js
function redirectToPage (line 14) | function redirectToPage(link) {
function download (line 20) | function download() {
function wxOpen (line 24) | function wxOpen() {
function iOSOpen (line 28) | function iOSOpen() {
function androidOpen (line 37) | function androidOpen() {
function openAppInBrowser (line 62) | function openAppInBrowser(conf) {
FILE: app/templates/app/src/util/RandomColor.js
function pickHue (line 61) | function pickHue(options) {
function pickSaturation (line 76) | function pickSaturation(hue, options) {
function pickBrightness (line 110) | function pickBrightness(H, S, options) {
function setFormat (line 134) | function setFormat(hsv, options) {
function getMinimumBrightness (line 169) | function getMinimumBrightness(H, S) {
function getHueRange (line 194) | function getHueRange(colorInput) {
function getSaturationRange (line 220) | function getSaturationRange(hue) {
function getColorInfo (line 224) | function getColorInfo(hue) {
function randomWithin (line 242) | function randomWithin(range) {
function HSVtoHex (line 255) | function HSVtoHex(hsv) {
function defineColor (line 270) | function defineColor(name, hueRange, lowerBounds) {
function loadColorBounds (line 287) | function loadColorBounds() {
function HSVtoRGB (line 339) | function HSVtoRGB(hsv) {
function HSVtoHSL (line 402) | function HSVtoHSL(hsv) {
FILE: app/templates/app/src/util/RandomList.js
function randomList (line 4) | function randomList(list, len, verify, ratio) {
FILE: app/templates/app/src/util/RequestHandler.js
function AJAXHandler (line 15) | function AJAXHandler(option) {
function JSONP (line 42) | function JSONP(option) {
function getJSON (line 57) | function getJSON(option) {
function postJSON (line 66) | function postJSON(option) {
FILE: app/templates/app/src/util/Scratch.js
function Scratch (line 1) | function Scratch(option) {
FILE: app/templates/app/src/util/SeededRandom.js
function seededRandom (line 6) | function seededRandom(max, min, seed) {
FILE: app/templates/app/src/util/Shake.js
function onStart (line 18) | function onStart() {
function onEnd (line 23) | function onEnd() {
function _listener (line 49) | function _listener(e) {
function Shake (line 65) | function Shake(startCallback, endCallback, abortCallback, errorCallback) {
FILE: app/templates/app/src/util/SimpleSlider.js
function Slider (line 1) | function Slider(config) {
FILE: app/templates/app/src/util/Slider.js
function Slider (line 47) | function Slider(option) {
FILE: app/templates/app/src/util/SlotMachine.js
function SlotMachine (line 1) | function SlotMachine(option) {
FILE: app/templates/app/src/util/TabStatus.js
function init (line 3) | function init(){
function TabStatus (line 25) | function TabStatus(key){
FILE: app/templates/app/src/util/ThirdVendor.js
function isUA (line 7) | function isUA(name) {
FILE: app/templates/app/src/util/Unveil.js
function unveil (line 30) | function unveil() {
FILE: app/templates/app/src/util/WechatShare.js
function WechatShare (line 1) | function WechatShare() {
FILE: app/templates/app/src/util/YiXinShare.js
function share (line 9) | function share(data) {
FILE: app/templates/app/src/widget/Msgbox.js
function Msgbox (line 1) | function Msgbox(option) {
FILE: app/templates/app/src/widget/Tooltip.js
function Tooltip (line 34) | function Tooltip(options) {
FILE: model/templates/Model.js
function modelName (line 10) | function <%=modelName%>(){
FILE: module/templates/ModuleController.js
function Controller (line 6) | function <%=moduleName%>Controller(){
FILE: module/templates/ModuleView.js
function View (line 4) | function <%=moduleName%>View(){
Condensed preview — 149 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (798K chars).
[
{
"path": ".editorconfig",
"chars": 197,
"preview": "# http://editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\ncharset = utf-8\ntrim_trailing_whitespace"
},
{
"path": ".gitattributes",
"chars": 12,
"preview": "* text=auto\n"
},
{
"path": ".gitignore",
"chars": 140,
"preview": ".DS_Store\nThumbs.db\n.sass-cache\n.idea\nlib-cov\n*.seed\n*.log\n*.csv\n*.dat\n*.out\n*.pid\n*.gz\n\npids\nlogs\nresults\n\nnpm-debug.lo"
},
{
"path": ".jshintrc",
"chars": 275,
"preview": "{\n \"node\": true,\n \"esnext\": true,\n \"bitwise\": true,\n \"camelcase\": true,\n \"curly\": true,\n \"eqeqeq\": true,\n \"immed\""
},
{
"path": ".travis.yml",
"chars": 72,
"preview": "sudo: false\nlanguage: node_js\nnode_js:\n - 'iojs'\n - '0.12'\n - '0.10'\n"
},
{
"path": ".yo-rc.json",
"chars": 31,
"preview": "{\n \"generator-generator\": {}\n}"
},
{
"path": "LICENSE",
"chars": 1072,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2015 unbug\n\nPermission is hereby granted, free of charge, to any person obtaining a"
},
{
"path": "README.md",
"chars": 4652,
"preview": "[](https://nodei.co/npm/generat"
},
{
"path": "app/index.js",
"chars": 2004,
"preview": "'use strict';\nvar yeoman = require('yeoman-generator');\nvar chalk = require('chalk');\nvar yosay = require('yosay');\n\nmod"
},
{
"path": "app/templates/_package.json",
"chars": 2400,
"preview": "{\n \"name\": \"<%=projectName%>\",\n \"version\": \"0.0.1\",\n \"description\": \"Hello <%=projectName%>\",\n \"project\": {\n \"inv"
},
{
"path": "app/templates/app/.babelrc",
"chars": 34,
"preview": "{ \"presets\": [\"es2015\",\"react\"] }\n"
},
{
"path": "app/templates/app/README.md",
"chars": 2385,
"preview": "Readme\n=================\nThis project require [node](https://nodejs.org/).\nRun `npm install` to install dependencies bef"
},
{
"path": "app/templates/app/data/user.json",
"chars": 64,
"preview": "[\n {\"name\": \"Peter\"},\n {\"name\": \"Joy\"},\n {\"name\": \"Brian\"}\n]\n"
},
{
"path": "app/templates/app/gulpfile.js",
"chars": 13258,
"preview": "var spawn = require('child_process').spawn;\nvar exec = require('child_process').exec;\nvar fs = require('fs');\nvar path ="
},
{
"path": "app/templates/app/html/debug/analytics.html",
"chars": 61,
"preview": "<!DOCTYPE HTML>\n<html>\n<head>\n</head>\n<body>\n</body>\n</html>\n"
},
{
"path": "app/templates/app/html/debug/index.html",
"chars": 504,
"preview": "<!DOCTYPE HTML>\n<html>\n<head>\n <!-- htmlhead -->\n @@include('include/htmlhead.html')\n <!-- end htmlhead -->\n <!-- st"
},
{
"path": "app/templates/app/html/include/cache.manifest",
"chars": 96,
"preview": "CACHE MANIFEST\n# Version: _GLOBAL_VERSION_\n# Build: _BUILD_VERSION_\n\nCACHE:\n_FILES_\n\nNETWORK:\n*\n"
},
{
"path": "app/templates/app/html/include/components.html",
"chars": 141,
"preview": "<!-- msgbox -->\n@@include('include/msgbox.html')\n<!-- end msgbox -->\n<!-- tooltip -->\n@@include('include/tooltip.html')\n"
},
{
"path": "app/templates/app/html/include/download.html",
"chars": 370,
"preview": "<section class=\"section-download hide\" data-eventname=\"appDownload\" data-eventparams=\"0,1\">\n <div class=\"sd-logo\"><img "
},
{
"path": "app/templates/app/html/include/footer.html",
"chars": 609,
"preview": "<section class=\"footer-section hide\">\n <div class=\"stores\">\n <a class=\"apple\" data-analytics=\"store=apple\"\n hr"
},
{
"path": "app/templates/app/html/include/htmlhead.html",
"chars": 292,
"preview": "<meta charset=\"UTF-8\">\n<meta content=\"target-densitydpi=device-dpi,width=_VIEWPORT_WIDTH_\" name=\"viewport\">\n<title>_TITL"
},
{
"path": "app/templates/app/html/include/manifest-version.html",
"chars": 44,
"preview": "<html manifest=\"_GLOBAL_VERSION_.manifest\">\n"
},
{
"path": "app/templates/app/html/include/msgbox-deja.html",
"chars": 336,
"preview": "<div class=\"box-ct signin\">\n <div class=\"box-bd\">\n <div>\n <div class=\"msg fix-break-word\">Please sign in</div>\n"
},
{
"path": "app/templates/app/html/include/msgbox.html",
"chars": 1269,
"preview": "<section class=\"msgbox\">\n <div class=\"box-mask\"></div>\n <div class=\"msgbox-ct\">\n <div class=\"msgbox-bd\">\n <div"
},
{
"path": "app/templates/app/html/include/scripts-version.html",
"chars": 40,
"preview": "<script src=\"src/app.js\" defer></script>"
},
{
"path": "app/templates/app/html/include/styles-version.html",
"chars": 55,
"preview": "<link rel=\"stylesheet\" href=\"resources/css/styles.css\">"
},
{
"path": "app/templates/app/html/include/tooltip.html",
"chars": 400,
"preview": "<script type=\"text/html\" id=\"tpl_tooltip\">\n<section class=\"tooltip <%=theme%> <%=rootCls%>\" id=\"<%=rootId%>\">\n <section"
},
{
"path": "app/templates/app/html/include/view-home.html",
"chars": 165,
"preview": "<section class=\"view view-home\">\n <section class=\"main\">\n <section class=\"btn bt-default\" data-fake-link=\"#/user/\">V"
},
{
"path": "app/templates/app/html/include/view-user.html",
"chars": 366,
"preview": "<section class=\"view view-user\">\n <section class=\"users\">\n <section class=\"list user-item-default\" data-element=\"lis"
},
{
"path": "app/templates/app/html/include/views.html",
"chars": 154,
"preview": "<!-- view-home -->\n@@include('include/view-home.html')\n<!--end view-home -->\n<!-- view-user -->\n@@include('include/view-"
},
{
"path": "app/templates/app/html/official/analytics.html",
"chars": 61,
"preview": "<!DOCTYPE HTML>\n<html>\n<head>\n</head>\n<body>\n</body>\n</html>\n"
},
{
"path": "app/templates/app/html/official/index.html",
"chars": 515,
"preview": "<!DOCTYPE HTML>\n<html _MANIFEST_>\n<head>\n <!-- htmlhead -->\n @@include('include/htmlhead.html')\n <!-- end htmlhead --"
},
{
"path": "app/templates/app/scss/_animate.scss",
"chars": 8538,
"preview": "@charset \"UTF-8\";\n\n/*\n参考自 http://daneden.github.io/animate.css/\n*/\n/*\n@-webkit-keyframes rotateRight{\n @for $i from 0"
},
{
"path": "app/templates/app/scss/_box.scss",
"chars": 724,
"preview": "@charset \"UTF-8\";\n\n.box-h{\n @include box-h;\n}\n.box-h-c-c{\n @include box-h-c-c;\n}\n.box-h-c-r{\n @include box-h-c-r;\n}\n."
},
{
"path": "app/templates/app/scss/_button.scss",
"chars": 1425,
"preview": "@charset \"UTF-8\";\n.btn {\n display: inline-block;\n text-align: center;\n @include active-default;\n @include disabled-s"
},
{
"path": "app/templates/app/scss/_common.scss",
"chars": 1240,
"preview": "@charset \"UTF-8\";\n/* http://css-tricks.com/poll-results-how-do-you-order-your-css-properties/ */\nbody, html {\n text-ali"
},
{
"path": "app/templates/app/scss/_components.scss",
"chars": 506,
"preview": "@charset \"UTF-8\";\n/*debug-button.scss*/\n@import \"button.scss\";\n/*end debug-button.scss*/\n\n/*debug-slide.scss*/\n@import \""
},
{
"path": "app/templates/app/scss/_fonts.scss",
"chars": 18,
"preview": "@charset \"UTF-8\";\n"
},
{
"path": "app/templates/app/scss/_footer.scss",
"chars": 463,
"preview": "@charset \"UTF-8\";\n.footer-section {\n margin-top: -1px;\n width: 100%;\n background-color: #3d1c21;\n padding: 45px 0;\n "
},
{
"path": "app/templates/app/scss/_header.scss",
"chars": 3040,
"preview": "@charset \"UTF-8\";\n.tabs-title-default {\n @include box-h;\n -webkit-border-radius: 10px;\n background-color: #eeeeee;\n "
},
{
"path": "app/templates/app/scss/_icon.scss",
"chars": 189,
"preview": "@charset \"UTF-8\";\n/*debug-sprites.scss*/\n@import \"sprites.scss\";\n\n/*end debug-sprites.scss*/\n\n.icon {\n background-repea"
},
{
"path": "app/templates/app/scss/_list.scss",
"chars": 350,
"preview": "@charset \"UTF-8\";\n.tabs-content-default {\n display: none;\n &.show {\n display: block;\n @include animated-1s;\n }\n"
},
{
"path": "app/templates/app/scss/_loading-spinner.scss",
"chars": 2110,
"preview": "@charset \"UTF-8\";\n.loading-spinner {\n font-size: 120%;\n height: 1em;\n width: 1em;\n position: relative;\n -webkit-tra"
},
{
"path": "app/templates/app/scss/_mixin.scss",
"chars": 3984,
"preview": "@charset \"UTF-8\";\n@mixin animated-1s {\n animation-duration: 1s;\n animation-iteration-count: 1;\n animation-fill-mode: "
},
{
"path": "app/templates/app/scss/_msgbox-android.scss",
"chars": 2617,
"preview": "@charset \"UTF-8\";\n$android-border-radius: 8px;\n/* android */\n.msgbox{\n .msgbox-bd.android{\n color: #000;\n > .box-"
},
{
"path": "app/templates/app/scss/_msgbox-deja.scss",
"chars": 2660,
"preview": "@charset \"UTF-8\";\n/* deja */\n.msgbox {\n .msgbox-bd.deja{\n > .box-ct.dialog {\n $dialog-w: $layout-with * 0.82;\n "
},
{
"path": "app/templates/app/scss/_msgbox.scss",
"chars": 5821,
"preview": "@charset \"UTF-8\";\n$ios-border-radius: 30px;\n\n/* default */\n.msgbox {\n position: fixed;\n z-index: 999;\n top: 0;\n left"
},
{
"path": "app/templates/app/scss/_section-download.scss",
"chars": 437,
"preview": "@charset \"UTF-8\";\n.section-download{\n @include box-h-c-c;\n padding: 20px;\n background-color: #fdfdfd;\n .sd-logo{\n "
},
{
"path": "app/templates/app/scss/_slide.scss",
"chars": 1046,
"preview": "@charset \"UTF-8\";\n.slide {\n position: relative;\n}\n\n.slide > * {\n position: absolute;\n width: 100%;\n height: 100%;\n "
},
{
"path": "app/templates/app/scss/_sprites.scss",
"chars": 1986,
"preview": ".icon {\n background-image: url('../images/sprites.png');\n}\n\n.icon-ic_s_close_pre_2x {\n background-position: -4px -4px;"
},
{
"path": "app/templates/app/scss/_tooltip.scss",
"chars": 3607,
"preview": "@charset \"UTF-8\";\n$tooltip-color-default: #fff;\n.tooltip {\n position: fixed;\n z-index: 90;\n left: 0;\n width: 100%;\n "
},
{
"path": "app/templates/app/scss/_util.scss",
"chars": 1381,
"preview": "@charset \"UTF-8\";\n\n.ellipsis {\n text-overflow: ellipsis;\n display: block;\n white-space: nowrap;\n overflow: hidden;\n}"
},
{
"path": "app/templates/app/scss/_value.scss",
"chars": 421,
"preview": "@charset \"UTF-8\";\n/*size*/\n$layout-with: _VIEWPORT_WIDTH_;/*see viewport:viewport package.json*/\n/*end size*/\n\n/*color*/"
},
{
"path": "app/templates/app/scss/_view-home.scss",
"chars": 181,
"preview": "@charset \"UTF-8\";\n.view-home {\n width: 100%;\n min-height: 100%;\n background-color: #35161f;\n font-size: 38px;\n\n .ma"
},
{
"path": "app/templates/app/scss/_view-user.scss",
"chars": 195,
"preview": "@charset \"UTF-8\";\n.view-user {\n width: 100%;\n background-color: #fff;\n color: #292929;\n .users {\n @include box-v-"
},
{
"path": "app/templates/app/scss/_view.scss",
"chars": 519,
"preview": "body > .view {\n width: 100%;\n visibility: hidden;\n display: none;\n &.animated {\n @include animated-1s;\n -webki"
},
{
"path": "app/templates/app/scss/styles.scss",
"chars": 785,
"preview": "@charset \"UTF-8\";\n\n/*_value.scss*/\n@import \"value.scss\";\n/*end _value.scss*/\n/*_mixin.scss*/\n@import \"mixin.scss\";\n/*end"
},
{
"path": "app/templates/app/src/app/App.js",
"chars": 584,
"preview": "//require('util/AppCache');\nrequire('lib/zepto');\nrequire('lib/Core');\nrequire('app/resources/i18n');\n\nvar BasicControll"
},
{
"path": "app/templates/app/src/app/controller/Controller.js",
"chars": 10277,
"preview": "var Actions = require('app/resources/Actions');\nvar ThirdVendor = require('util/ThirdVendor');\nvar BasicModel = require("
},
{
"path": "app/templates/app/src/app/controller/HomeController.js",
"chars": 1493,
"preview": "var Actions = require('../resources/Actions');\nvar BasicModel = require('app/model/Model');\nvar BasicView = require('app"
},
{
"path": "app/templates/app/src/app/controller/UserController.js",
"chars": 1662,
"preview": "var Actions = require('../resources/Actions');\nvar BasicModel = require('app/model/Model');\nvar UserModel = require('app"
},
{
"path": "app/templates/app/src/app/model/Model.js",
"chars": 2192,
"preview": "var RequestHelper = require('app/model/RequestHelper');\nvar Actions = require('app/resources/Actions');\n\nvar Mdl = Core."
},
{
"path": "app/templates/app/src/app/model/RequestHelper.js",
"chars": 1310,
"preview": "var getJSON = Core.RequestHandler.getJSON,\n postJSON = Core.RequestHandler.postJSON,\n JSONP = Core.RequestHandler.JSON"
},
{
"path": "app/templates/app/src/app/model/StoreHelper.js",
"chars": 4547,
"preview": "var RequestHelper = require('app/model/RequestHelper');\n\nfunction pagingStore(action, options) {\n var option = {\n is"
},
{
"path": "app/templates/app/src/app/model/UserModel.js",
"chars": 382,
"preview": "var StoreHelper = require('app/model/StoreHelper');\nvar Actions = require('app/resources/Actions');\nvar Basic = require("
},
{
"path": "app/templates/app/src/app/resources/Actions.js",
"chars": 1212,
"preview": "var thisPage = window.location.href\n //注意,保留search 是为了避免微信自动追加的应用检测状态值\n //.replace(window.location.search,'')\n .repla"
},
{
"path": "app/templates/app/src/app/resources/Audios.js",
"chars": 41,
"preview": "var Audios = {}\nmodule.exports = Audios;\n"
},
{
"path": "app/templates/app/src/app/resources/i18n/en_US/Msgbox.js",
"chars": 120,
"preview": "module.exports = {\n ok: 'OK',\n no: 'Cancel',\n sure: 'Sure',\n loading: 'Loading...',\n submitting: 'Submitting...'\n}\n"
},
{
"path": "app/templates/app/src/app/resources/i18n/en_US/index.js",
"chars": 92,
"preview": "var Msgbox = require('./Msgbox');\n\nvar en_US = {\n Msgbox: Msgbox\n}\nmodule.exports = en_US;\n"
},
{
"path": "app/templates/app/src/app/resources/i18n/index.js",
"chars": 947,
"preview": "var en_US = require('./en_US');\nvar zh_CN = require('./zh_CN');\n\nvar langs = {\n zh_CN: zh_CN\n}\n\n//https://github.com/jq"
},
{
"path": "app/templates/app/src/app/resources/i18n/zh_CN/Msgbox.js",
"chars": 105,
"preview": "module.exports = {\n ok: '好的',\n no: '取消',\n sure: '确定',\n loading: '正在加载...',\n submitting: '正在提交...'\n}\n"
},
{
"path": "app/templates/app/src/app/resources/i18n/zh_CN/index.js",
"chars": 170,
"preview": "var Msgbox = require('./Msgbox');\n\nfunction zh_CN() {\n //extend from super\n zh_CN.superclass.constructor.call(this);\n\n"
},
{
"path": "app/templates/app/src/app/view/HomeView.js",
"chars": 1198,
"preview": "var BasicView = require('app/view/View');\nvar BasicModel = require('app/model/Model');\n\n\nfunction HomeView() {\n this.mo"
},
{
"path": "app/templates/app/src/app/view/UserView.js",
"chars": 1635,
"preview": "var BasicView = require('app/view/View');\nvar BasicModel = require('app/model/Model');\nvar UserModel = require('app/mode"
},
{
"path": "app/templates/app/src/app/view/View.js",
"chars": 8631,
"preview": "var Actions = require('app/resources/Actions');\nvar Msgbox = require('widget/Msgbox');\nvar WechatShare = require('util/W"
},
{
"path": "app/templates/app/src/core/Class.js",
"chars": 7815,
"preview": "var Subject = require('./Subject');\nvar Class;\n\n/**\n * @param obj\n * @param config\n * @param promise\n */\nfunction apply("
},
{
"path": "app/templates/app/src/core/Event.js",
"chars": 341,
"preview": "var Class = require('./Class');\nvar Pubsub = require('./Pubsub');\nvar Subject = require('./Subject');\n\n\nfunction Event(S"
},
{
"path": "app/templates/app/src/core/HashHandler.js",
"chars": 443,
"preview": "var HashHandler = (function () {\n var lc = window.location;\n\n function getByURL(url) {\n var hash;\n url && decode"
},
{
"path": "app/templates/app/src/core/MicroTmpl.js",
"chars": 3307,
"preview": "/**\n * 模板解析\n * 1. 可接收 DOM Element,不支持 DOM Element 模板里嵌套模板\n * 2. 如果 DOM Element 中的元素的属性可加前缀micro-(或ntes-),如img的src改为micro"
},
{
"path": "app/templates/app/src/core/NativeBridge.js",
"chars": 4502,
"preview": "var Navigator = require('./Navigator');\n\n/**\n * 与客户端交互\n *\n * 前端与客户端交互的流程主要为前端调用,客户端读取,客户端回调三个步骤:\n * 前端调用客户端规则为:dej"
},
{
"path": "app/templates/app/src/core/Navigator.js",
"chars": 3008,
"preview": "var Navigator = (function () {\n var frame,\n androidReg = /Android/gi,\n isAndroid = androidReg.test(navigator.plat"
},
{
"path": "app/templates/app/src/core/Pubsub.js",
"chars": 1057,
"preview": "function Pubsub(Subject) {\n var topics = {};\n\n function subscribe(topic, observer) {\n var subject;\n for (var key"
},
{
"path": "app/templates/app/src/core/Router.js",
"chars": 12131,
"preview": "var Pubsub = require('./Pubsub');\nvar Subject = require('./Subject');\nvar HashHandler = require('./HashHandler');\n\n/**\n "
},
{
"path": "app/templates/app/src/core/Subject.js",
"chars": 1164,
"preview": "function Subject(subject) {\n this._subject = subject;\n this.observers = [];\n}\n\nSubject.prototype = {\n /**\n * @param"
},
{
"path": "app/templates/app/src/lib/Core.js",
"chars": 1611,
"preview": "require('util/RequestAnimationFrame');\nrequire('util/Easing');\nrequire('util/Unveil');\nrequire('util/VirtualDOMLite');\n\n"
},
{
"path": "app/templates/app/src/lib/Core.standalone.js",
"chars": 831,
"preview": "require('util/RequestAnimationFrame');\n\nvar localStorage = require('core/LocalStorage');\nvar Navigator = require('core/N"
},
{
"path": "app/templates/app/src/lib/diffDOM.js",
"chars": 35998,
"preview": "\"use strict\";\n\nvar diffcount;\n\nvar Diff = function (options) {\n var diff = this;\n Object.keys(options).forEach(functio"
},
{
"path": "app/templates/app/src/lib/hammer.js",
"chars": 66813,
"preview": "/*! Hammer.JS - v2.0.4 - 2014-09-28\n * http://hammerjs.github.io/\n *\n * Copyright (c) 2014 Jorik Tangelder;\n * Licensed "
},
{
"path": "app/templates/app/src/lib/impress.js",
"chars": 28532,
"preview": "/**\n * impress.js\n *\n * impress.js is a presentation tool based on the power of CSS3 transforms and transitions\n * in mo"
},
{
"path": "app/templates/app/src/lib/rebound.js",
"chars": 35802,
"preview": "// Rebound\n// =======\n// **Rebound** is a simple library that models Spring dynamics for the\n// purpose of driving physi"
},
{
"path": "app/templates/app/src/lib/swing/card.js",
"chars": 12496,
"preview": "/* global window, navigator */\nvar global = window;\n\nvar Card,\n Sister = require('lib/swing/sister'),\n Hammer = requir"
},
{
"path": "app/templates/app/src/lib/swing/dom.js",
"chars": 436,
"preview": "var dom = {};\n\n/**\n * Return direct children elements.\n *\n * @see http://stackoverflow.com/a/27102446/368691\n * @param {"
},
{
"path": "app/templates/app/src/lib/swing/sister.js",
"chars": 1246,
"preview": "var global = window;\n\n/**\n * @link https://github.com/gajus/sister for the canonical source repository\n * @license https"
},
{
"path": "app/templates/app/src/lib/swing/stack.js",
"chars": 2195,
"preview": "var Stack,\n Sister = require('lib/swing/sister'),\n rebound = require('lib/rebound'),\n Card = require('lib/swing/card'"
},
{
"path": "app/templates/app/src/lib/swing/swing.js",
"chars": 242,
"preview": "var global = window;\n\nvar Stack = require('lib/swing/stack'),\n Card = require('lib/swing/card');\n\nglobal.gajus = global"
},
{
"path": "app/templates/app/src/lib/swing/vendor-prefix.js",
"chars": 1162,
"preview": "var style = document.createElement('p').style,\n prefixes = 'O ms Moz webkit'.split(' '),\n hasPrefix = /^(o|ms|moz|webk"
},
{
"path": "app/templates/app/src/lib/velocity.js",
"chars": 190100,
"preview": "/*! VelocityJS.org (1.2.2). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */\n\n/**************"
},
{
"path": "app/templates/app/src/lib/velocityui.js",
"chars": 30177,
"preview": "/**********************\n Velocity UI Pack\n **********************/\n\n/* VelocityJS.org UI Pack (5.0.4). (C) 2014 Julian S"
},
{
"path": "app/templates/app/src/lib/zepto.js",
"chars": 75235,
"preview": "// MODULES=\"zepto event ajax form ie detect fx touch gesture selector\" npm run-script dist\n/* Zepto 1.1.6 - zepto event "
},
{
"path": "app/templates/app/src/lib/zepto.waypoints.js",
"chars": 18888,
"preview": "/*!\n Waypoints - 4.0.0\n Copyright © 2011-2015 Caleb Troughton\n Licensed under the MIT license.\n https://github.com/imake"
},
{
"path": "app/templates/app/src/util/AppCache.js",
"chars": 535,
"preview": "/**\n * if you enable manifest in package.json,you don't need to require this module any more,gulp will auto includes it "
},
{
"path": "app/templates/app/src/util/Base64.js",
"chars": 3189,
"preview": "var Base64 = {\n // private property\n _keyStr: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",\n\n "
},
{
"path": "app/templates/app/src/util/DateHandler.js",
"chars": 2554,
"preview": "var DateHandler = (function () {\n function getStrDate(str) {\n var date;\n if (typeof str === 'string') {\n var"
},
{
"path": "app/templates/app/src/util/Easing.js",
"chars": 4032,
"preview": "/**\n * http://www.robertpenner.com/easing/\n * http://www.gizma.com/easing/\n *\n * t: current time\n * b: begInnIng value\n "
},
{
"path": "app/templates/app/src/util/FacebookShare.js",
"chars": 742,
"preview": "var MetaHandler = require('util/MetaHandler');\n\n/**\n * facebook\n * https://developers.facebook.com/docs/sharing/best-pra"
},
{
"path": "app/templates/app/src/util/FormHandler.js",
"chars": 1366,
"preview": "var Navigator = require('core/Navigator');\n\nvar FormHandler = function () {\n //MONOSTATE\n if (FormHandler.prototype.in"
},
{
"path": "app/templates/app/src/util/GUID.js",
"chars": 272,
"preview": "function GUID(len) {\n var res = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function(c) {\n var num = Math"
},
{
"path": "app/templates/app/src/util/ImpressGenerator.js",
"chars": 7868,
"preview": "var randomList = require('util/RandomList');\nvar impress = window.impress;\n\nvar ww = window.innerWidth,\n wh = window.in"
},
{
"path": "app/templates/app/src/util/LocalHost.js",
"chars": 228,
"preview": "if (!window.location.origin) {\n window.location.origin = window.location.protocol\n + \"//\" + window.location.hostname"
},
{
"path": "app/templates/app/src/util/LocalParam.js",
"chars": 545,
"preview": "/**\n * window.location.search\n * window.location.hash\n */\nfunction localParam(search, hash) {\n search = search || windo"
},
{
"path": "app/templates/app/src/util/LocalStorage.js",
"chars": 1304,
"preview": "function localStorage() {\n var lcst = window.localStorage;\n\n /**\n * 读取\n *\n * @method getLocalValue\n * @param {"
},
{
"path": "app/templates/app/src/util/MetaHandler.js",
"chars": 6817,
"preview": "var ua = navigator.userAgent,\n android = ua.match(/(Android);?[\\s\\/]+([\\d.]+)?/),\n ipad = ua.match(/(iPad).*OS\\s([\\d_]"
},
{
"path": "app/templates/app/src/util/Number.js",
"chars": 1227,
"preview": "function formatMoney(num) {\n return (num).toFixed(2).replace(/./g, function (c, i, a) {\n return i && c !== \".\" && !("
},
{
"path": "app/templates/app/src/util/OpenAppInBrowser.js",
"chars": 1457,
"preview": "var Navigator = require('core/Navigator');\n\nvar nav = navigator,\n isiOS = (/iphone|ipod/gi).test(nav.platform)||(/ipad/"
},
{
"path": "app/templates/app/src/util/RandomColor.js",
"chars": 8502,
"preview": "// randomColor by David Merfield under the MIT license\n// https://github.com/davidmerfield/randomColor/\nvar randomColor "
},
{
"path": "app/templates/app/src/util/RandomList.js",
"chars": 684,
"preview": "/**\n * 随机数组\n */\nfunction randomList(list, len, verify, ratio) {\n var rs = [], _list = list.slice(0);\n len = len || _li"
},
{
"path": "app/templates/app/src/util/RequestAnimationFrame.js",
"chars": 514,
"preview": "//http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html\nwindow.cancelRequestA"
},
{
"path": "app/templates/app/src/util/RequestHandler.js",
"chars": 1831,
"preview": "var RequestHandler = (function () {\n /**\n * AJAX管理器\n *\n * @param Object option\n * option:{\n * type : S"
},
{
"path": "app/templates/app/src/util/Scratch.js",
"chars": 4421,
"preview": "function Scratch(option) {\n option = option || {};\n var me = this,\n emptyFn = function () {\n },\n el = option."
},
{
"path": "app/templates/app/src/util/SeededRandom.js",
"chars": 385,
"preview": "/**\n * 默认基于时间,返回指定范围内的随机数\n * 当seed不固定时速度比较慢,仅用于减少重复率\n * http://indiegamr.com/generate-repeatable-random-numbers-in-js/\n "
},
{
"path": "app/templates/app/src/util/Shake.js",
"chars": 2772,
"preview": "/**\n * 摇一摇工具,如果 android 客户端则使用客户端的摇一摇接口\n *\n */\n\nvar _fn = function () {\n },\n x1 = 0, y1 = 0, z1 = 0, x2 = 0, y2 = 0, z"
},
{
"path": "app/templates/app/src/util/SimpleSlider.js",
"chars": 1990,
"preview": "function Slider(config) {\n if (!config || !config.el) {\n return null;\n }\n var _this = this;\n var efn = function ("
},
{
"path": "app/templates/app/src/util/Slider.js",
"chars": 12327,
"preview": "/**\n *\n * @param option\n * {\n * el, //list wrap element,optional if listEl is specified\n * listEl,// list element,op"
},
{
"path": "app/templates/app/src/util/SlotMachine.js",
"chars": 7190,
"preview": "function SlotMachine(option) {\n option = option || {};\n var me = this,\n emptyFn = function () {\n },\n lightEl "
},
{
"path": "app/templates/app/src/util/TabStatus.js",
"chars": 689,
"preview": "var store = {};\n\nfunction init(){\n var data = {curIdx: 0};\n this.getStatus = function () {\n return data;\n }\n thi"
},
{
"path": "app/templates/app/src/util/ThirdVendor.js",
"chars": 847,
"preview": "/**\n * 第三方平台\n */\nvar ua = window.navigator.userAgent;\nvar vendor = null;\n\nfunction isUA(name) {\n var reg = new RegExp(n"
},
{
"path": "app/templates/app/src/util/Unveil.js",
"chars": 1297,
"preview": "/**\n * jQuery Unveil\n * A very lightweight jQuery plugin to lazy load images\n * http://luis-almeida.github.com/unveil\n *"
},
{
"path": "app/templates/app/src/util/VersionCompare.js",
"chars": 1124,
"preview": "/**\n * Simply compares two string version values.\n * https://gist.github.com/alexey-bass/1115557\n *\n * Example:\n * versi"
},
{
"path": "app/templates/app/src/util/VirtualDOMLite.js",
"chars": 741,
"preview": "require('lib/diffDOM');\n\n//https://github.com/fiduswriter/diffDOM\n;(function ($) {\n $.fn.superHtml = $.fn.html;\n $.fn."
},
{
"path": "app/templates/app/src/util/WaypointsHandler.js",
"chars": 2387,
"preview": "require('lib/zepto.waypoints');\n\nvar WaypointsHandler = function (el) {\n var anim = [\"callout.bounce\", \"callout.shake\","
},
{
"path": "app/templates/app/src/util/WechatShare.js",
"chars": 1404,
"preview": "function WechatShare() {\n var meta = {\n \"appid\": \"\",\n \"img_url\": null,\n \"img_width\": \"200\",\n \"img_height\": "
},
{
"path": "app/templates/app/src/util/YiXinShare.js",
"chars": 363,
"preview": "var MetaHandler = require('util/MetaHandler');\n\n/**\n * 易信分享\n * @param data = {\n * conetnt,img\n * }\n */\nfunction"
},
{
"path": "app/templates/app/src/widget/Msgbox.js",
"chars": 7087,
"preview": "function Msgbox(option) {\n //MONOSTATE\n if (Msgbox.prototype.instance) {\n return Msgbox.prototype.instance;\n }\n o"
},
{
"path": "app/templates/app/src/widget/Tooltip.js",
"chars": 4122,
"preview": "var tpl = Core.microTmpl($('#tpl_tooltip').text());\nvar _body = $('body');\n\n/**\n *\n * @param options {\n * single: if i"
},
{
"path": "app/templates/app/webpack.config.js",
"chars": 1133,
"preview": "// For instructions about this file refer to\n// webpack and webpack-hot-middleware documentation\nvar webpack = require('"
},
{
"path": "app/templates/editorconfig",
"chars": 197,
"preview": "# http://editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\ncharset = utf-8\ntrim_trailing_whitespace"
},
{
"path": "app/templates/ftppass",
"chars": 71,
"preview": "{\n \"testServer\": {\n \"user\": \"test\",\n \"pass\": \"test\"\n }\n}\n"
},
{
"path": "app/templates/gitignore",
"chars": 146,
"preview": ".DS_Store\nThumbs.db\n.sass-cache\n.idea\nlib-cov\n*.seed\n*.log\n*.csv\n*.dat\n*.out\n*.pid\n*.gz\n\npids\nlogs\nresults\n\nnpm-debug.lo"
},
{
"path": "app/templates/jshintrc",
"chars": 275,
"preview": "{\n \"node\": true,\n \"esnext\": true,\n \"bitwise\": true,\n \"camelcase\": true,\n \"curly\": true,\n \"eqeqeq\": true,\n \"immed\""
},
{
"path": "model/index.js",
"chars": 744,
"preview": "'use strict';\nvar yeoman = require('yeoman-generator');\nvar chalk = require('chalk');\nvar yosay = require('yosay');\nvar "
},
{
"path": "model/templates/Model.js",
"chars": 921,
"preview": "var RequestHelper = require('app/model/RequestHelper');\nvar StoreHelper = require('app/model/StoreHelper');\nvar Actions "
},
{
"path": "module/index.js",
"chars": 2217,
"preview": "'use strict';\nvar yeoman = require('yeoman-generator');\nvar chalk = require('chalk');\nvar yosay = require('yosay');\nvar "
},
{
"path": "module/templates/ModuleController.js",
"chars": 1519,
"preview": "var Actions = require('../resources/Actions');\nvar BasicModel = require('app/model/Model');\nvar BasicView = require('app"
},
{
"path": "module/templates/ModuleView.js",
"chars": 1279,
"preview": "var BasicView = require('app/view/View');\nvar BasicModel = require('app/model/Model');\n\nfunction <%=moduleName%>View(){\n"
},
{
"path": "module/templates/module.html",
"chars": 132,
"preview": "<section class=\"view view-<%=lmoduleName%>\">\n <section class=\"<%=lmoduleName%>\">\n Hello <%=moduleName%>\n </section>"
},
{
"path": "module/templates/module.scss",
"chars": 212,
"preview": "@charset \"UTF-8\";\n.view-<%=lmoduleName%> {\n width: 100%;\n height: 100%;\n min-height: 100%;\n background-color: #fff;\n"
},
{
"path": "package.json",
"chars": 863,
"preview": "{\n \"name\": \"generator-webappstarter\",\n \"version\": \"2.3.4\",\n \"description\": \"Quick start a web app for mobile.Automati"
},
{
"path": "test/test-app.js",
"chars": 553,
"preview": "'use strict';\n\nvar path = require('path');\nvar assert = require('yeoman-generator').assert;\nvar helpers = require('yeoma"
},
{
"path": "update/index.js",
"chars": 4488,
"preview": "'use strict';\nvar yeoman = require('yeoman-generator');\nvar chalk = require('chalk');\nvar yosay = require('yosay');\nvar "
}
]
About this extraction
This page contains the full source code of the unbug/generator-webappstarter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 149 files (738.3 KB), approximately 193.6k tokens, and a symbol index with 268 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.