├── .gitignore
├── LICENSE
├── README.md
├── elementtest
├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── README.md
├── build
│ ├── build.js
│ ├── dev-client.js
│ ├── dev-server.js
│ ├── utils.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
├── index.html
├── package.json
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ └── Hello.vue
│ └── main.js
└── static
│ └── .gitkeep
├── riot_babel
├── README.md
├── build
│ ├── app.js
│ ├── app.js.map
│ ├── vendor.js
│ └── vendor.js.map
├── index.html
├── js
│ ├── app.html
│ ├── helpers.js
│ └── index.js
└── package.json
├── riot_dragdrop
├── .editorconfig
├── .gitignore
├── README.md
├── dist
│ ├── bundle.js
│ └── tacit.min.css
├── index.html
├── package.json
├── src
│ ├── app.html
│ └── index.js
└── webpack.config.js
├── riot_flux
├── README.md
├── css
│ ├── main.css
│ └── uikit.almost-flat.min.css
├── img
│ ├── ipad-mini.png
│ ├── sucker.png
│ └── t-shirt.png
├── index.html
└── js
│ ├── CartStore.js
│ ├── ProductStore.js
│ ├── RiotControl.js
│ ├── cart.html
│ └── products.html
├── riot_ramjet
├── .gitignore
├── index.html
├── js
│ └── app.htm
├── node_modules
│ ├── ramjet
│ │ └── dist
│ │ │ └── ramjet.umd.min.js
│ └── riot
│ │ └── riot+compiler.min.js
└── package.json
├── riot_todo
├── .gitignore
├── README.md
├── index.html
├── js
│ ├── app.js
│ ├── store.js
│ └── todo.html
├── node_modules
│ ├── riot
│ │ ├── riot+compiler.min.js
│ │ └── riot.min.js
│ ├── todomvc-app-css
│ │ └── index.css
│ └── todomvc-common
│ │ ├── base.css
│ │ └── base.js
└── package.json
├── riot_vue
├── .lightserverrc
├── README.md
├── app.tag
├── img
│ ├── hn.png
│ └── todomvc.png
├── index.html
├── main.css
├── package.json
└── tags
│ ├── firebase.html
│ ├── githubcommits.html
│ ├── gridcomponent.html
│ ├── hackernews.html
│ ├── imageslider.html
│ ├── markdown.html
│ ├── modal.html
│ ├── svggraph.html
│ ├── todomvc.html
│ └── treeview.html
├── riot_webpack
├── .editorconfig
├── .eslintrc
├── .gitignore
├── README.md
├── dist
│ ├── bundle.js
│ └── vendor.bundle.js
├── index.html
├── package.json
├── src
│ ├── RiotControl.js
│ ├── app.html
│ ├── component
│ │ └── postcell.html
│ ├── css
│ │ └── tacit.min.css
│ ├── index.js
│ ├── riotTags.js
│ ├── store
│ │ └── blogstore.js
│ ├── stores.js
│ ├── vendor.js
│ └── view
│ │ ├── categories-view.html
│ │ ├── detail-view.html
│ │ └── posts-view.html
└── webpack.config.js
├── riot_webpack_async
├── .babelrc
├── .editorconfig
├── .eslintrc
├── .gitignore
├── README.md
├── dist
│ ├── bundle.js
│ └── vendor.bundle.js
├── index.html
├── package.json
├── src
│ ├── RiotControl.js
│ ├── app.html
│ ├── component
│ │ └── postcell.html
│ ├── css
│ │ └── tacit.min.css
│ ├── index.js
│ ├── riotTags.js
│ ├── store
│ │ └── blogstore.js
│ ├── stores.js
│ ├── vendor.js
│ └── view
│ │ ├── categories-view.html
│ │ ├── detail-view.html
│ │ └── posts-view.html
└── webpack.config.js
├── s_login
├── .gitignore
├── README.md
├── index.html
├── js
│ └── app.htm
├── node_modules
│ ├── riot
│ │ ├── riot+compiler.min.js
│ │ └── riot.min.js
│ └── whatwg-fetch
│ │ └── fetch.js
└── package.json
└── vue_webpack
├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── README.md
├── index.html
├── package.json
├── src
├── App.vue
├── component
│ └── postcell.vue
├── main.css
├── main.js
├── vendor.js
├── view
│ ├── categories-view.vue
│ ├── detail-view.vue
│ └── posts-view.vue
└── vuex
│ ├── middlewares.js
│ ├── mutation-types.js
│ └── store.js
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # Compiled binary addons (http://nodejs.org/api/addons.html)
20 | build/Release
21 |
22 | # Dependency directory
23 | # Commenting this out is preferred by some people, see
24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
25 | node_modules
26 |
27 | # Users Environment Variables
28 | .lock-wscript
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Tianxiang Chen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Frontend Play
2 |
3 | This repository contains small examples I made during my javascript frameworks/libraries learning.
4 |
5 | ### Examples list:
6 | * riot_flux - use riotjs and riotcontrol to implement flux
7 | * riot_todo - implement todomvc using riotjs
8 | * riot_vue - implement vuejs' examples using riotjs
9 | * riot_babel - use babel and riotjs to build web app
10 | * riot_webpack - use webpack, ES6, riot and riotcontrol to build app
11 | * riot_webpack_async - use webpack, ES7, riot and riotcontrol to build app
12 | * s_login - pure js with google account login
13 | * vue_webpack - use vue, vuex, vue-router, ES6 to build app
14 |
--------------------------------------------------------------------------------
/elementtest/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-2"],
3 | "plugins": ["transform-runtime"],
4 | "comments": false
5 | }
6 |
--------------------------------------------------------------------------------
/elementtest/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/elementtest/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*.js
2 | config/*.js
3 |
--------------------------------------------------------------------------------
/elementtest/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: 'babel-eslint',
4 | parserOptions: {
5 | sourceType: 'module'
6 | },
7 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
8 | extends: 'standard',
9 | // required to lint *.vue files
10 | plugins: [
11 | 'html'
12 | ],
13 | // add your custom rules here
14 | 'rules': {
15 | // allow paren-less arrow functions
16 | 'arrow-parens': 0,
17 | // allow async-await
18 | 'generator-star-spacing': 0,
19 | // allow debugger during development
20 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/elementtest/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log
5 |
--------------------------------------------------------------------------------
/elementtest/README.md:
--------------------------------------------------------------------------------
1 | # elementtest
2 |
3 | > A Vue.js project
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 | ```
17 |
18 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
19 |
--------------------------------------------------------------------------------
/elementtest/build/build.js:
--------------------------------------------------------------------------------
1 | // https://github.com/shelljs/shelljs
2 | require('shelljs/global')
3 | env.NODE_ENV = 'production'
4 |
5 | var path = require('path')
6 | var config = require('../config')
7 | var ora = require('ora')
8 | var webpack = require('webpack')
9 | var webpackConfig = require('./webpack.prod.conf')
10 |
11 | console.log(
12 | ' Tip:\n' +
13 | ' Built files are meant to be served over an HTTP server.\n' +
14 | ' Opening index.html over file:// won\'t work.\n'
15 | )
16 |
17 | var spinner = ora('building for production...')
18 | spinner.start()
19 |
20 | var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
21 | rm('-rf', assetsPath)
22 | mkdir('-p', assetsPath)
23 | cp('-R', 'static/*', assetsPath)
24 |
25 | webpack(webpackConfig, function (err, stats) {
26 | spinner.stop()
27 | if (err) throw err
28 | process.stdout.write(stats.toString({
29 | colors: true,
30 | modules: false,
31 | children: false,
32 | chunks: false,
33 | chunkModules: false
34 | }) + '\n')
35 | })
36 |
--------------------------------------------------------------------------------
/elementtest/build/dev-client.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | require('eventsource-polyfill')
3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
4 |
5 | hotClient.subscribe(function (event) {
6 | if (event.action === 'reload') {
7 | window.location.reload()
8 | }
9 | })
10 |
--------------------------------------------------------------------------------
/elementtest/build/dev-server.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var express = require('express')
3 | var webpack = require('webpack')
4 | var config = require('../config')
5 | var opn = require('opn')
6 | var proxyMiddleware = require('http-proxy-middleware')
7 | var webpackConfig = require('./webpack.dev.conf')
8 |
9 | // default port where dev server listens for incoming traffic
10 | var port = process.env.PORT || config.dev.port
11 | // Define HTTP proxies to your custom API backend
12 | // https://github.com/chimurai/http-proxy-middleware
13 | var proxyTable = config.dev.proxyTable
14 |
15 | var app = express()
16 | var compiler = webpack(webpackConfig)
17 |
18 | var devMiddleware = require('webpack-dev-middleware')(compiler, {
19 | publicPath: webpackConfig.output.publicPath,
20 | stats: {
21 | colors: true,
22 | chunks: false
23 | }
24 | })
25 |
26 | var hotMiddleware = require('webpack-hot-middleware')(compiler)
27 | // force page reload when html-webpack-plugin template changes
28 | compiler.plugin('compilation', function (compilation) {
29 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
30 | hotMiddleware.publish({ action: 'reload' })
31 | cb()
32 | })
33 | })
34 |
35 | // proxy api requests
36 | Object.keys(proxyTable).forEach(function (context) {
37 | var options = proxyTable[context]
38 | if (typeof options === 'string') {
39 | options = { target: options }
40 | }
41 | app.use(proxyMiddleware(context, options))
42 | })
43 |
44 | // handle fallback for HTML5 history API
45 | app.use(require('connect-history-api-fallback')())
46 |
47 | // serve webpack bundle output
48 | app.use(devMiddleware)
49 |
50 | // enable hot-reload and state-preserving
51 | // compilation error display
52 | app.use(hotMiddleware)
53 |
54 | // serve pure static assets
55 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
56 | app.use(staticPath, express.static('./static'))
57 |
58 | module.exports = app.listen(port, function (err) {
59 | if (err) {
60 | console.log(err)
61 | return
62 | }
63 | var uri = 'http://localhost:' + port
64 | console.log('Listening at ' + uri + '\n')
65 | opn(uri)
66 | })
67 |
--------------------------------------------------------------------------------
/elementtest/build/utils.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var config = require('../config')
3 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
4 |
5 | exports.assetsPath = function (_path) {
6 | var assetsSubDirectory = process.env.NODE_ENV === 'production'
7 | ? config.build.assetsSubDirectory
8 | : config.dev.assetsSubDirectory
9 | return path.posix.join(assetsSubDirectory, _path)
10 | }
11 |
12 | exports.cssLoaders = function (options) {
13 | options = options || {}
14 | // generate loader string to be used with extract text plugin
15 | function generateLoaders (loaders) {
16 | var sourceLoader = loaders.map(function (loader) {
17 | var extraParamChar
18 | if (/\?/.test(loader)) {
19 | loader = loader.replace(/\?/, '-loader?')
20 | extraParamChar = '&'
21 | } else {
22 | loader = loader + '-loader'
23 | extraParamChar = '?'
24 | }
25 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
26 | }).join('!')
27 |
28 | if (options.extract) {
29 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
30 | } else {
31 | return ['vue-style-loader', sourceLoader].join('!')
32 | }
33 | }
34 |
35 | // http://vuejs.github.io/vue-loader/configurations/extract-css.html
36 | return {
37 | css: generateLoaders(['css']),
38 | postcss: generateLoaders(['css']),
39 | less: generateLoaders(['css', 'less']),
40 | sass: generateLoaders(['css', 'sass?indentedSyntax']),
41 | scss: generateLoaders(['css', 'sass']),
42 | stylus: generateLoaders(['css', 'stylus']),
43 | styl: generateLoaders(['css', 'stylus'])
44 | }
45 | }
46 |
47 | // Generate loaders for standalone style files (outside of .vue)
48 | exports.styleLoaders = function (options) {
49 | var output = []
50 | var loaders = exports.cssLoaders(options)
51 | for (var extension in loaders) {
52 | var loader = loaders[extension]
53 | output.push({
54 | test: new RegExp('\\.' + extension + '$'),
55 | loader: loader
56 | })
57 | }
58 | return output
59 | }
60 |
--------------------------------------------------------------------------------
/elementtest/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var config = require('../config')
3 | var utils = require('./utils')
4 | var projectRoot = path.resolve(__dirname, '../')
5 |
6 | module.exports = {
7 | entry: {
8 | app: './src/main.js'
9 | },
10 | output: {
11 | path: config.build.assetsRoot,
12 | publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
13 | filename: '[name].js'
14 | },
15 | resolve: {
16 | extensions: ['', '.js', '.vue'],
17 | fallback: [path.join(__dirname, '../node_modules')],
18 | alias: {
19 | 'vue': 'vue/dist/vue.common.js',
20 | 'src': path.resolve(__dirname, '../src'),
21 | 'assets': path.resolve(__dirname, '../src/assets'),
22 | 'components': path.resolve(__dirname, '../src/components')
23 | }
24 | },
25 | resolveLoader: {
26 | fallback: [path.join(__dirname, '../node_modules')]
27 | },
28 | module: {
29 | preLoaders: [
30 | {
31 | test: /\.vue$/,
32 | loader: 'eslint',
33 | include: projectRoot,
34 | exclude: /node_modules/
35 | },
36 | {
37 | test: /\.js$/,
38 | loader: 'eslint',
39 | include: projectRoot,
40 | exclude: /node_modules/
41 | }
42 | ],
43 | loaders: [
44 | {
45 | test: /\.vue$/,
46 | loader: 'vue'
47 | },
48 | {
49 | test: /\.js$/,
50 | loader: 'babel',
51 | include: projectRoot,
52 | exclude: /node_modules/
53 | },
54 | {
55 | test: /\.json$/,
56 | loader: 'json'
57 | },
58 | {
59 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
60 | loader: 'url',
61 | query: {
62 | limit: 10000,
63 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
64 | }
65 | },
66 | {
67 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
68 | loader: 'url',
69 | query: {
70 | limit: 10000,
71 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
72 | }
73 | }
74 | ]
75 | },
76 | eslint: {
77 | formatter: require('eslint-friendly-formatter')
78 | },
79 | vue: {
80 | loaders: utils.cssLoaders(),
81 | postcss: [
82 | require('autoprefixer')({
83 | browsers: ['last 2 versions']
84 | })
85 | ]
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/elementtest/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | var config = require('../config')
2 | var webpack = require('webpack')
3 | var merge = require('webpack-merge')
4 | var utils = require('./utils')
5 | var baseWebpackConfig = require('./webpack.base.conf')
6 | var HtmlWebpackPlugin = require('html-webpack-plugin')
7 |
8 | // add hot-reload related code to entry chunks
9 | Object.keys(baseWebpackConfig.entry).forEach(function (name) {
10 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
11 | })
12 |
13 | module.exports = merge(baseWebpackConfig, {
14 | module: {
15 | loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
16 | },
17 | // eval-source-map is faster for development
18 | devtool: '#eval-source-map',
19 | plugins: [
20 | new webpack.DefinePlugin({
21 | 'process.env': config.dev.env
22 | }),
23 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
24 | new webpack.optimize.OccurenceOrderPlugin(),
25 | new webpack.HotModuleReplacementPlugin(),
26 | new webpack.NoErrorsPlugin(),
27 | // https://github.com/ampedandwired/html-webpack-plugin
28 | new HtmlWebpackPlugin({
29 | filename: 'index.html',
30 | template: 'index.html',
31 | inject: true
32 | })
33 | ]
34 | })
35 |
--------------------------------------------------------------------------------
/elementtest/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var config = require('../config')
3 | var utils = require('./utils')
4 | var webpack = require('webpack')
5 | var merge = require('webpack-merge')
6 | var baseWebpackConfig = require('./webpack.base.conf')
7 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
8 | var HtmlWebpackPlugin = require('html-webpack-plugin')
9 | var env = config.build.env
10 |
11 | var webpackConfig = merge(baseWebpackConfig, {
12 | module: {
13 | loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true })
14 | },
15 | devtool: config.build.productionSourceMap ? '#source-map' : false,
16 | output: {
17 | path: config.build.assetsRoot,
18 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
19 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
20 | },
21 | vue: {
22 | loaders: utils.cssLoaders({
23 | sourceMap: config.build.productionSourceMap,
24 | extract: true
25 | })
26 | },
27 | plugins: [
28 | // http://vuejs.github.io/vue-loader/workflow/production.html
29 | new webpack.DefinePlugin({
30 | 'process.env': env
31 | }),
32 | new webpack.optimize.UglifyJsPlugin({
33 | compress: {
34 | warnings: false
35 | }
36 | }),
37 | new webpack.optimize.OccurenceOrderPlugin(),
38 | // extract css into its own file
39 | new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')),
40 | // generate dist index.html with correct asset hash for caching.
41 | // you can customize output by editing /index.html
42 | // see https://github.com/ampedandwired/html-webpack-plugin
43 | new HtmlWebpackPlugin({
44 | filename: config.build.index,
45 | template: 'index.html',
46 | inject: true,
47 | minify: {
48 | removeComments: true,
49 | collapseWhitespace: true,
50 | removeAttributeQuotes: true
51 | // more options:
52 | // https://github.com/kangax/html-minifier#options-quick-reference
53 | },
54 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
55 | chunksSortMode: 'dependency'
56 | }),
57 | // split vendor js into its own file
58 | new webpack.optimize.CommonsChunkPlugin({
59 | name: 'vendor',
60 | minChunks: function (module, count) {
61 | // any required modules inside node_modules are extracted to vendor
62 | return (
63 | module.resource &&
64 | /\.js$/.test(module.resource) &&
65 | module.resource.indexOf(
66 | path.join(__dirname, '../node_modules')
67 | ) === 0
68 | )
69 | }
70 | }),
71 | // extract webpack runtime and module manifest to its own file in order to
72 | // prevent vendor hash from being updated whenever app bundle is updated
73 | new webpack.optimize.CommonsChunkPlugin({
74 | name: 'manifest',
75 | chunks: ['vendor']
76 | })
77 | ]
78 | })
79 |
80 | if (config.build.productionGzip) {
81 | var CompressionWebpackPlugin = require('compression-webpack-plugin')
82 |
83 | webpackConfig.plugins.push(
84 | new CompressionWebpackPlugin({
85 | asset: '[path].gz[query]',
86 | algorithm: 'gzip',
87 | test: new RegExp(
88 | '\\.(' +
89 | config.build.productionGzipExtensions.join('|') +
90 | ')$'
91 | ),
92 | threshold: 10240,
93 | minRatio: 0.8
94 | })
95 | )
96 | }
97 |
98 | module.exports = webpackConfig
99 |
--------------------------------------------------------------------------------
/elementtest/config/dev.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var prodEnv = require('./prod.env')
3 |
4 | module.exports = merge(prodEnv, {
5 | NODE_ENV: '"development"'
6 | })
7 |
--------------------------------------------------------------------------------
/elementtest/config/index.js:
--------------------------------------------------------------------------------
1 | // see http://vuejs-templates.github.io/webpack for documentation.
2 | var path = require('path')
3 |
4 | module.exports = {
5 | build: {
6 | env: require('./prod.env'),
7 | index: path.resolve(__dirname, '../dist/index.html'),
8 | assetsRoot: path.resolve(__dirname, '../dist'),
9 | assetsSubDirectory: 'static',
10 | assetsPublicPath: '/',
11 | productionSourceMap: true,
12 | // Gzip off by default as many popular static hosts such as
13 | // Surge or Netlify already gzip all static assets for you.
14 | // Before setting to `true`, make sure to:
15 | // npm install --save-dev compression-webpack-plugin
16 | productionGzip: false,
17 | productionGzipExtensions: ['js', 'css']
18 | },
19 | dev: {
20 | env: require('./dev.env'),
21 | port: 8080,
22 | assetsSubDirectory: 'static',
23 | assetsPublicPath: '/',
24 | proxyTable: {},
25 | // CSS Sourcemaps off by default because relative paths are "buggy"
26 | // with this option, according to the CSS-Loader README
27 | // (https://github.com/webpack/css-loader#sourcemaps)
28 | // In our experience, they generally work as expected,
29 | // just be aware of this issue when enabling this option.
30 | cssSourceMap: false
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/elementtest/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"'
3 | }
4 |
--------------------------------------------------------------------------------
/elementtest/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | elementtest
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/elementtest/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "elementtest",
3 | "version": "1.0.0",
4 | "description": "A Vue.js project",
5 | "author": "Tianxiang Chen ",
6 | "private": true,
7 | "scripts": {
8 | "dev": "node build/dev-server.js",
9 | "build": "node build/build.js",
10 | "lint": "eslint --ext .js,.vue src"
11 | },
12 | "dependencies": {
13 | "element-ui": "^1.0.0-rc.5",
14 | "vue": "^2.0.1"
15 | },
16 | "devDependencies": {
17 | "autoprefixer": "^6.4.0",
18 | "babel-core": "^6.0.0",
19 | "babel-eslint": "^7.0.0",
20 | "babel-loader": "^6.0.0",
21 | "babel-plugin-transform-runtime": "^6.0.0",
22 | "babel-preset-es2015": "^6.0.0",
23 | "babel-preset-stage-2": "^6.0.0",
24 | "babel-register": "^6.0.0",
25 | "connect-history-api-fallback": "^1.1.0",
26 | "css-loader": "^0.25.0",
27 | "eslint": "^3.7.1",
28 | "eslint-friendly-formatter": "^2.0.5",
29 | "eslint-loader": "^1.5.0",
30 | "eslint-plugin-html": "^1.3.0",
31 | "eslint-config-standard": "^6.1.0",
32 | "eslint-plugin-promise": "^2.0.1",
33 | "eslint-plugin-standard": "^2.0.1",
34 | "eventsource-polyfill": "^0.9.6",
35 | "express": "^4.13.3",
36 | "extract-text-webpack-plugin": "^1.0.1",
37 | "file-loader": "^0.9.0",
38 | "function-bind": "^1.0.2",
39 | "html-webpack-plugin": "^2.8.1",
40 | "http-proxy-middleware": "^0.17.2",
41 | "json-loader": "^0.5.4",
42 | "opn": "^4.0.2",
43 | "ora": "^0.3.0",
44 | "shelljs": "^0.7.4",
45 | "url-loader": "^0.5.7",
46 | "vue-loader": "^9.4.0",
47 | "vue-style-loader": "^1.0.0",
48 | "webpack": "^1.13.2",
49 | "webpack-dev-middleware": "^1.8.3",
50 | "webpack-hot-middleware": "^2.12.2",
51 | "webpack-merge": "^0.14.1"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/elementtest/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Welcome to your Vue.js app!
7 |
8 |
9 | To get a better understanding of how this boilerplate works, check out
10 | its documentation .
11 | It is also recommended to go through the docs for
12 | Webpack and
13 | vue-loader .
14 | If you have any issues with the setup, please file an issue at this boilerplate's
15 | repository .
16 |
17 |
18 | You may also want to checkout
19 | vue-router for routing and
20 | vuex for state management.
21 |
22 |
23 |
24 |
25 |
34 |
35 |
65 |
--------------------------------------------------------------------------------
/elementtest/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txchen/feplay/6de713d706dcc691e27314c7c8a4f11201a00d44/elementtest/src/assets/logo.png
--------------------------------------------------------------------------------
/elementtest/src/components/Hello.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 |
6 |
7 |
12 | {{ row.a }}
13 | {{ row.b }}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
36 |
37 |
38 |
43 |
--------------------------------------------------------------------------------
/elementtest/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import App from './App'
5 | import Popover from 'element-ui/lib/popover'
6 | import 'element-ui/lib/theme-default/popover.css'
7 | import Button from 'element-ui/lib/button'
8 | import 'element-ui/lib/theme-default/button.css'
9 | import Table from 'element-ui/lib/table'
10 | import 'element-ui/lib/theme-default/table.css'
11 | import TableColumn from 'element-ui/lib/table-column'
12 | import 'element-ui/lib/theme-default/table-column.css'
13 |
14 | Vue.component(Button.name, Button)
15 | Vue.component(Popover.name, Popover)
16 | Vue.component(Table.name, Table)
17 | Vue.component(TableColumn.name, TableColumn)
18 |
19 | /* eslint-disable no-new */
20 | new Vue({
21 | el: '#app',
22 | render: h => h(App)
23 | })
24 |
--------------------------------------------------------------------------------
/elementtest/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txchen/feplay/6de713d706dcc691e27314c7c8a4f11201a00d44/elementtest/static/.gitkeep
--------------------------------------------------------------------------------
/riot_babel/README.md:
--------------------------------------------------------------------------------
1 | ## Use Babel(6to5) with Riotjs
2 |
3 | This tiny example shows how to write ES6 with Riotjs, and use browserify to build the bundled target js to run in the browser environment.
4 |
5 | Online demo: http://txchen.github.io/feplay/riot_babel/
6 |
7 | ### ---- A better choice, maybe ----
8 |
9 | riot-loader + webpack might be a better choice, here is another example for that: https://github.com/txchen/feplay/tree/gh-pages/riot_webpack
10 |
11 | ### To write ES6 in tag script
12 |
13 | The change is simple, just set the `type` to `es6` in the `script` elemnt:
14 |
15 | ```html
16 |
17 |
18 |
19 |
22 |
23 | ```
24 |
25 | It is not recommended to use babel in browser environment to compile the es6 to es5, so we will not use riot+compiler, instead, we use `browserify` or other packing tool to process the scripts.
26 |
27 | Riot's default mini-ES6 method syntax cannot work when we are using babel, so we need to change:
28 |
29 | ```js
30 | // This would not work with babel
31 | buttonHandler(e) {
32 | // code
33 | }
34 |
35 | // Change to this
36 | this.buttonHandler = (e) => {
37 | // code
38 | }
39 | ```
40 |
41 | That's it, now you can use ES6 features, for example, the lambda in your tag:
42 |
43 | ```js
44 | this.data.forEach(d => d *= 5)
45 | ```
46 |
47 | ES6's template string cannot work in Riot's expression, but you can wrap it with function, for example:
48 |
49 | ```html
50 |
51 | { summary() }
52 |
57 |
58 | ```
59 |
60 | ### Build with browserify
61 |
62 | Now let's build the app with browserify. All your tags and javascripts will be bundled into one single js.
63 |
64 | And there is a small optimization here: Usually, your app needs to use external packages, riotjs is one of them. And during development, these external packages rarely change. We can bundle all the external packages into vendor.js, and all of our own code into app.js. This will make the browserify build faster.
65 |
66 | Before the build, we need these dev-dependencies:
67 | * babel
68 | * babelify (if you have .js written in ES6)
69 | * browserify
70 | * riot
71 | * riotify
72 |
73 | Firstly, build the vendor bundle, use `-r` option to tell browserify our dependencies:
74 |
75 | ```bash
76 | browserify -r babel/polyfill -r riot -r co -d \
77 | -p [minifyify --map vendor.js.map --output build/vendor.js.map] \
78 | -o build/vendor.js
79 | ```
80 |
81 | In this example, we bundle 3 external packages into vendor.js. To make sure the vendor.js is minified, we use minifyify to compress the output, and generate the source map file.
82 |
83 | Now, build our own app code, use `-x` to exclude external packages, otherwise they will be generated in your app.js:
84 |
85 | ```bash
86 | browserify -x babel/polyfill -x riot -x co \
87 | -t babelify -t [riotify --ext html] \
88 | js/index.js -o build/app.js
89 | ```
90 |
91 | In this example, `js/index.js` is our entry, and we use .html as Riot's tag file extention. You can add `-d -p [minifyify --map app.js.map --output build/app.js.map]` to enable minify and sourcemap generation.
92 |
93 | That's it, now you will have vendor.js and app.js, include them in your html and it's done. My package.json is using a tool to monitor the source code change and auto trigger build and reload browser, should be very useful during development. Of course, you can use gulp or grunt to do the same.
94 |
95 | Now you can write your entire app in ES6 with Riotjs.
96 |
97 | ### Use some advanced/experimental babel/ES6 features
98 |
99 | With the default setup, not every feature in babel is available. For example, if we want to use generator and co to write better async handling, we need some more work.
100 |
101 | We need the `co` package to execute the generator, so install it as dev dependency.
102 |
103 | And, we need `babel/polyfill`, require it in the begining of your entry js:
104 |
105 | ```js
106 | require("babel/polyfill")
107 | ```
108 |
109 | Now you can use it:
110 |
111 | ```js
112 | sleepFunc = (ms) => {
113 | return (callback) => {
114 | setTimeout(callback, ms)
115 | }
116 | }
117 |
118 | this.sleepSomeTime = () => {
119 | co(function* (){
120 | self.sleep.innerHTML = "sleeping"
121 | yield sleepFunc(1000)
122 | self.sleep.innerHTML = "done with sleep"
123 | })
124 | }
125 | ```
126 |
127 | Finally we have the sleep in js:)
128 |
129 | It's recommended to generate the co and babel/polyfill into vendor.js, and you should be aware that these two would make your js bigger.
130 |
--------------------------------------------------------------------------------
/riot_babel/build/app.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o*5 the world Remove last ES6+co Sleep some time sleepES7 Show dialog { summary() }
{ max() }
Modal Dialog This is a modal window. You can do the following things with it:
Read: Modal windows will probably tell you something important so don\'t forget to read what it says. Look: modal windows enjoy a certain kind of attention; just look at it and appreciate its presence. Close: click on the button below to close the modal. Close me!
','app .md-modal, [riot-tag="app"] .md-modal{ position: fixed; top: 50%; left: 50%; width: 50%; max-width: 630px; min-width: 320px; height: auto; z-index: 2000; visibility: hidden; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-transform: translateX(-50%) translateY(-50%); transform: translateX(-50%) translateY(-50%); } app .md-show, [riot-tag="app"] .md-show{ visibility: visible; } app .md-overlay, [riot-tag="app"] .md-overlay{ position: fixed; width: 100%; height: 100%; visibility: hidden; top: 0; left: 0; z-index: 1000; opacity: 0; background: rgba(143,27,15,0.8); -webkit-transition: all 0.3s; transition: all 0.3s; } app .md-effect-1 .md-content, [riot-tag="app"] .md-effect-1 .md-content{ -webkit-transform: scale(0.7); -moz-transform: scale(0.7); -ms-transform: scale(0.7); transform: scale(0.7); opacity: 0; -webkit-transition: all 0.3s; -moz-transition: all 0.3s; transition: all 0.3s; } app .md-show.md-effect-1 .md-content, [riot-tag="app"] .md-show.md-effect-1 .md-content{ -webkit-transform: scale(1); -moz-transform: scale(1); -ms-transform: scale(1); transform: scale(1); opacity: 1; } app .md-show ~ .md-overlay, [riot-tag="app"] .md-show ~ .md-overlay{ opacity: 1; visibility: visible; }',function(t){var e=this,i=require("co");e.data=[{v:1},{v:2},{v:3},{v:4}],e.insleeping=!1,this.fivetimesdata=function(t){e.data.forEach(function(t){return t.v*=5})},this.removeLast=function(){e.data.splice(e.data.length-1)},this.showDialog=function(){e.dialogShowing=!0},this.submitDialog=function(){console.log("submit dialog"),e.dialogShowing=!1},this.closeDialog=function(){e.dialogShowing=!1},sleepFunc=function(t){return function(e){setTimeout(function(){e(null,t)},t)}},fakeFetch=function(){return regeneratorRuntime.mark(function t(){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,sleepFunc(1e3);case 2:return t.abrupt("return",Promise.resolve("es6"));case 3:case"end":return t.stop()}},t,this)})},this.sleepSomeTime=function(){i(regeneratorRuntime.mark(function t(){var i,n;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return e.sleep.innerHTML="sleeping",e.insleeping=!0,t.next=4,sleepFunc(1e3);case 4:return i=t.sent,e.sleep.innerHTML="slept for "+i+"ms, now fetch something",t.next=8,fakeFetch();case 8:n=t.sent,e.sleep.innerHTML="got: "+n,e.insleeping=!1,e.update();case 12:case"end":return t.stop()}},t,this)}))},this.summary=function(){return"there are "+e.data.length+" elements,\nsum = "+e.data.map(function(t){return t.v}).reduce(function(t,e){return t+e})},this.max=function(){return"max = "+window.helpers.max(e.data.map(function(t){return t.v}))}});
3 | },{"co":"co","riot":"riot"}],2:[function(require,module,exports){
4 | "use strict";var helpers={max:function(e){return e.reduce(function(e,r){return e>r?e:r})}};module.exports=helpers;
5 | },{}],3:[function(require,module,exports){
6 | "use strict";require("babel/polyfill"),window.helpers=require("./helpers.js"),require("./app.html"),require("riot").mount("app");
7 | },{"./app.html":1,"./helpers.js":2,"babel/polyfill":"babel/polyfill","riot":"riot"}]},{},[3])
8 |
9 |
10 | //# sourceMappingURL=app.js.map
--------------------------------------------------------------------------------
/riot_babel/build/app.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","js/index.js","js/app.html","js/helpers.js"],"names":["require","window","helpers","mount","riot","module","exports","tag","opts","self","this","co","data","v","insleeping","fivetimesdata","e","forEach","d","removeLast","splice","length","showDialog","dialogShowing","submitDialog","console","log","closeDialog","sleepFunc","ms","cb","setTimeout","fakeFetch","regeneratorRuntime","mark","callee$1$0","wrap","context$2$0","prev","next","abrupt","Promise","resolve","stop","sleepSomeTime","sleptTime","result","sleep","innerHTML","sent","update","summary","map","reduce","a","b","max","array"],"mappings":"AAAA;AEAA,GAAII,MAAOJ,QAAQ,OACnBK,QAAOC,QAAUF,KAAKG,IAAI,MAAO,ulCAAwlC,qtCAAstC,SAASC,GACx1E,GAAIC,GAAOC,KACPC,EAAKX,QAAQ,KACjBS,GAAKG,OAAUC,EAAG,IAAOA,EAAG,IAAOA,EAAG,IAAOA,EAAG,IAChDJ,EAAKK,YAAa,EAElBJ,KAAKK,cAAgB,SAAUC,GAC7BP,EAAKG,KAAKK,QAAQ,SAAUC,GAC1B,MAAOA,GAAEL,GAAK,KAIlBH,KAAKS,WAAa,WAChBV,EAAKG,KAAKQ,OAAOX,EAAKG,KAAKS,OAAS,IAGtCX,KAAKY,WAAa,WAChBb,EAAKc,eAAgB,GAGvBb,KAAKc,aAAe,WAClBC,QAAQC,IAAI,iBACZjB,EAAKc,eAAgB,GAGvBb,KAAKiB,YAAc,WACjBlB,EAAKc,eAAgB,GAGvBK,UAAY,SAAUC,GACpB,MAAO,UAAUC,GAEfC,WAAW,WACTD,EAAG,KAAMD,IACRA,KAIPG,UAAY,WACV,MAAOC,oBAAmBC,KAAK,QAASC,KACtC,MAAOF,oBAAmBG,KAAK,SAAqBC,GAClD,OAAU,OAAQA,EAAYC,KAAOD,EAAYE,MAC/C,IAAK,GAEH,MADAF,GAAYE,KAAO,EACZX,UAAU,IAEnB,KAAK,GACH,MAAOS,GAAYG,OAAO,SAAUC,QAAQC,QAAQ,OAEtD,KAAK,GACL,IAAK,MACH,MAAOL,GAAYM,SAEtBR,EAAYzB,SAInBA,KAAKkC,cAAgB,WACnBjC,EAAGsB,mBAAmBC,KAAK,QAASC,KAClC,GAAIU,GAAWC,CACf,OAAOb,oBAAmBG,KAAK,SAAqBC,GAClD,OAAU,OAAQA,EAAYC,KAAOD,EAAYE,MAC/C,IAAK,GAIH,MAHA9B,GAAKsC,MAAMC,UAAY,WACvBvC,EAAKK,YAAa,EAClBuB,EAAYE,KAAO,EACZX,UAAU,IAEnB,KAAK,GAKH,MAJAiB,GAAYR,EAAYY,KAExBxC,EAAKsC,MAAMC,UAAY,aAAeH,EAAY,0BAClDR,EAAYE,KAAO,EACZP,WAET,KAAK,GACHc,EAAST,EAAYY,KAErBxC,EAAKsC,MAAMC,UAAY,QAAUF,EACjCrC,EAAKK,YAAa,EAClBL,EAAKyC,QAEP,KAAK,IACL,IAAK,MACH,MAAOb,GAAYM,SAEtBR,EAAYzB,UAmBnBA,KAAKyC,QAAU,WACb,MAAO,aAAe1C,EAAKG,KAAKS,OAAS,qBAAuBZ,EAAKG,KAAKwC,IAAI,SAAUlC,GACtF,MAAOA,GAAEL,IACRwC,OAAO,SAAUC,EAAGC,GACrB,MAAOD,GAAIC,KAIf7C,KAAK8C,IAAM,WACT,MAAO,SAAWvD,OAAOC,QAAQsD,IAAI/C,EAAKG,KAAKwC,IAAI,SAAUlC,GAC3D,MAAOA,GAAEL;;ACpHb,YAAY,AACZ,CADY,GACRX,UACFsD,IAAG,SAACC,GACF,MAAOA,GAAMJ,OAAO,SAACC,EAAGC,SAAMD,GAAIC,EAAID,EAAIC,KAI9ClD,QAAOC,QAAUJ;AANjB,IAAI,OAAO,GAAG;AACZ,KAAG,EAAA,KFDLF,QECM,CFDE,IECG,EAAE,YFAbC,OAAOC,QAAUF,QAAQ,gBACzBA,QAAQ,cACRA,QAAQ,QAAQG,MAAM;AEDlB,WAAO,KAAK,CAAC,MAAM,CAAC,UAAC,CAAC,EAAE,CAAC;aAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;AFF/C,KEE+C,CAAC,CAAA,AFFzC,CAAC,gBAAgB,CAAC,CAAA;AACzB,GEEG,GFFG,CAAC,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;AACxC,CEEC,CAAA,KFFM,CAAC,YAAY,CAAC,CAAA;AACrB,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AEG5B,MAAM,CAAC,OAAO,GAAG,OAAO,CAAA","file":"bundle.js","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o*5 the world Remove last ES6+co Sleep some time sleepES7 Show dialog { summary() }
{ max() }
Modal Dialog This is a modal window. You can do the following things with it:
Read: Modal windows will probably tell you something important so don\\'t forget to read what it says. Look: modal windows enjoy a certain kind of attention; just look at it and appreciate its presence. Close: click on the button below to close the modal. Close me!
', 'app .md-modal, [riot-tag=\"app\"] .md-modal{ position: fixed; top: 50%; left: 50%; width: 50%; max-width: 630px; min-width: 320px; height: auto; z-index: 2000; visibility: hidden; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-transform: translateX(-50%) translateY(-50%); transform: translateX(-50%) translateY(-50%); } app .md-show, [riot-tag=\"app\"] .md-show{ visibility: visible; } app .md-overlay, [riot-tag=\"app\"] .md-overlay{ position: fixed; width: 100%; height: 100%; visibility: hidden; top: 0; left: 0; z-index: 1000; opacity: 0; background: rgba(143,27,15,0.8); -webkit-transition: all 0.3s; transition: all 0.3s; } app .md-effect-1 .md-content, [riot-tag=\"app\"] .md-effect-1 .md-content{ -webkit-transform: scale(0.7); -moz-transform: scale(0.7); -ms-transform: scale(0.7); transform: scale(0.7); opacity: 0; -webkit-transition: all 0.3s; -moz-transition: all 0.3s; transition: all 0.3s; } app .md-show.md-effect-1 .md-content, [riot-tag=\"app\"] .md-show.md-effect-1 .md-content{ -webkit-transform: scale(1); -moz-transform: scale(1); -ms-transform: scale(1); transform: scale(1); opacity: 1; } app .md-show ~ .md-overlay, [riot-tag=\"app\"] .md-show ~ .md-overlay{ opacity: 1; visibility: visible; }', function(opts) {\nvar self = this;\nvar co = require('co');\nself.data = [{ v: 1 }, { v: 2 }, { v: 3 }, { v: 4 }];\nself.insleeping = false;\n\nthis.fivetimesdata = function (e) {\n self.data.forEach(function (d) {\n return d.v *= 5;\n });\n};\n\nthis.removeLast = function () {\n self.data.splice(self.data.length - 1);\n};\n\nthis.showDialog = function () {\n self.dialogShowing = true;\n};\n\nthis.submitDialog = function () {\n console.log('submit dialog');\n self.dialogShowing = false;\n};\n\nthis.closeDialog = function () {\n self.dialogShowing = false;\n};\n\nsleepFunc = function (ms) {\n return function (cb) {\n // return a thunk\n setTimeout(function () {\n cb(null, ms); // null means error\n }, ms);\n };\n};\n\nfakeFetch = function () {\n return regeneratorRuntime.mark(function callee$1$0() {\n return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {\n while (1) switch (context$2$0.prev = context$2$0.next) {\n case 0:\n context$2$0.next = 2;\n return sleepFunc(1000);\n\n case 2:\n return context$2$0.abrupt('return', Promise.resolve(\"es6\"));\n\n case 3:\n case 'end':\n return context$2$0.stop();\n }\n }, callee$1$0, this);\n });\n};\n\nthis.sleepSomeTime = function () {\n co(regeneratorRuntime.mark(function callee$1$0() {\n var sleptTime, result;\n return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {\n while (1) switch (context$2$0.prev = context$2$0.next) {\n case 0:\n self.sleep.innerHTML = \"sleeping\";\n self.insleeping = true;\n context$2$0.next = 4;\n return sleepFunc(1000);\n\n case 4:\n sleptTime = context$2$0.sent;\n\n self.sleep.innerHTML = \"slept for \" + sleptTime + \"ms, now fetch something\";\n context$2$0.next = 8;\n return fakeFetch();\n\n case 8:\n result = context$2$0.sent;\n\n self.sleep.innerHTML = \"got: \" + result;\n self.insleeping = false;\n self.update();\n\n case 12:\n case 'end':\n return context$2$0.stop();\n }\n }, callee$1$0, this);\n }));\n};\n\n// asyncSleep = async (ms) => {\n// return new Promise((resolve, reject) => {\n// setTimeout(() => resolve(), ms)\n// })\n// }\n//\n// this.fetchES7 = async () => {\n// self.sleep.innerHTML = \"sleeping\"\n// self.insleeping = true\n// await asyncSleep(1000)\n// self.sleep.innerHTML = \"sleep finished\"\n// self.insleeping = false\n// self.update()\n// }\n\nthis.summary = function () {\n return 'there are ' + self.data.length + ' elements,\\nsum = ' + self.data.map(function (d) {\n return d.v;\n }).reduce(function (a, b) {\n return a + b;\n });\n};\n\nthis.max = function () {\n return 'max = ' + window.helpers.max(self.data.map(function (d) {\n return d.v;\n }));\n};\n});\n","'use strict'\nvar helpers = {\n max(array) {\n return array.reduce((a, b) => a > b ? a : b)\n }\n}\n\nmodule.exports = helpers\n"]}
--------------------------------------------------------------------------------
/riot_babel/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Riot Babel Test
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/riot_babel/js/app.html:
--------------------------------------------------------------------------------
1 |
2 |
60 |
61 | *5 the world
62 | Remove last
63 | ES6+co Sleep some time
64 | sleepES7
65 | Show dialog
66 |
69 | { summary() }
70 | { max() }
71 |
72 |
73 |
74 |
75 |
76 |
Modal Dialog
77 |
78 |
This is a modal window. You can do the following things with it:
79 |
80 | Read: Modal windows will probably tell you something important so don't forget to read what it says.
81 | Look: modal windows enjoy a certain kind of attention; just look at it and appreciate its presence.
82 | Close: click on the button below to close the modal.
83 |
84 |
Close me!
85 |
86 |
87 |
88 |
89 |
90 |
166 |
167 |
--------------------------------------------------------------------------------
/riot_babel/js/helpers.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | var helpers = {
3 | max(array) {
4 | return array.reduce((a, b) => a > b ? a : b)
5 | }
6 | }
7 |
8 | module.exports = helpers
9 |
--------------------------------------------------------------------------------
/riot_babel/js/index.js:
--------------------------------------------------------------------------------
1 | // to use co and regeneratorRuntime
2 | require("babel/polyfill")
3 | window.helpers = require('./helpers.js')
4 | require('./app.html')
5 | require('riot').mount('app')
6 |
--------------------------------------------------------------------------------
/riot_babel/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "devDependencies": {
4 | "babel": "^5.8.23",
5 | "babelify": "^6.3.0",
6 | "browserify": "^11.1.0",
7 | "co": "^4.6.0",
8 | "light-server": "^1.0.6",
9 | "minifyify": "^7.0.6",
10 | "riot": "^2.2.4",
11 | "riotify": "0.1.2"
12 | },
13 | "scripts": {
14 | "build:vendor": "browserify -r babel/polyfill -r riot -r co -d -p [minifyify --map vendor.js.map --output build/vendor.js.map] -o build/vendor.js",
15 | "build:app": "browserify -x babel/polyfill -x riot -x co -t babelify -t [riotify --ext html] js/index.js -o build/app.js",
16 | "build": "npm run build:vendor && npm run build:app",
17 | "build:dist": "npm run build:vendor && npm run build:app -- -d -p [minifyify --map app.js.map --output build/app.js.map]",
18 | "dev": "light-server -s . -w 'js/** # npm run build:app'"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/riot_dragdrop/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig file (see http://EditorConfig.org)
2 |
3 | root = true
4 |
5 | # All files.
6 | [*]
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 | indent_style = space
11 | indent_size = 2
12 |
--------------------------------------------------------------------------------
/riot_dragdrop/.gitignore:
--------------------------------------------------------------------------------
1 | bundle.js.map
2 |
--------------------------------------------------------------------------------
/riot_dragdrop/README.md:
--------------------------------------------------------------------------------
1 | ## Drag and drop in riotjs
2 |
3 | Online demo: http://txchen.github.io/feplay/riot_dragdrop/
4 |
--------------------------------------------------------------------------------
/riot_dragdrop/dist/tacit.min.css:
--------------------------------------------------------------------------------
1 | th{font-weight:600}td,th{border-bottom:1.08px solid #ccc;padding:14.85px 18px}thead th{border-bottom-width:2.16px;padding-bottom:6.3px}table{display:block;max-width:100%;overflow-x:auto}input,textarea,select,button{display:block;padding:9.9px}label{display:block;margin-bottom:14.76px}input[type="submit"],input[type="reset"],button{background:#b3b3b3;border-radius:3.6px;color:#fff;cursor:pointer;display:inline;margin-bottom:18px;margin-right:7.2px;padding:6.525px 23.4px;text-align:center}input[type="submit"]:hover,input[type="reset"]:hover,button:hover{background:#a6a6a6;color:#bfbfbf}input[type="submit"],button[type="submit"]{background:#367ac3;color:#fff}input[type="submit"]:hover,button[type="submit"]:hover{background:#255587;color:#bfbfbf}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="phone"],input[type="tel"],input[type="number"],input[type="datetime"],input[type="date"],input[type="month"],input[type="color"],input[type="time"],input[type="search"],input[type="range"],input[type="file"],input[type="datetime-local"],select,textarea{border:1px solid #ccc;margin-bottom:18px;padding:5.4px 6.3px}input[type="checkbox"]{float:left;line-height:36px;margin-right:9px;margin-top:8.1px}pre,code,kbd,samp,var,output{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:16.2px}pre{border-left:1.8px solid #96bbe2;line-height:25.2px;margin-top:29.7px;overflow:auto;padding-left:18px}pre code{background:none;border:0;line-height:29.7px;padding:0}code{background:#ededed;border:1.8px solid #ccc;border-radius:3.6px;display:inline-block;line-height:18px;padding:3px 6px 2px}h1,h2,h3,h4,h5,h6{color:#000}h1{font-size:36px;font-weight:500;margin-bottom:18px;margin-top:36px}h2{font-size:25.2px;font-weight:400;margin-bottom:18px;margin-top:27px}h3{font-size:18px;margin-bottom:18px;margin-top:21.6px}h4,h5,h6{font-size:36px;margin-bottom:18px;margin-top:36px}a{color:#367ac3;text-decoration:none}a:hover{text-decoration:underline}hr{border-bottom:1px solid #ccc}small{font-size:15.3px}em,i{font-style:italic}strong,b{font-weight:500}*{border:0;border-collapse:separate;border-spacing:0;box-sizing:border-box;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:18px;font-stretch:normal;font-style:normal;font-weight:300;line-height:29.7px;margin:0;outline:0;padding:0;text-align:left;vertical-align:baseline}body{background:#f5f5f5;color:#1a1a1a;padding:36px}p,ul,ol,dl,blockquote,hr,pre,table,form,fieldset,figure,address{margin-bottom:29.7px}section{margin-left:auto;margin-right:auto;max-width:100%;width:900px}article{background:#fff;border:1.8px solid #d9d9d9;border-radius:7.2px;padding:43.2px}header{margin-bottom:36px}footer{margin-top:36px}nav{text-align:center}nav ul{list-style:none;text-align:center}nav ul li{display:inline;margin-left:9px;margin-right:9px}@media (max-width: 767px){body{padding:18px}article{border-radius:0;margin:-18px;padding:18px}textarea,input,select{max-width:100%}fieldset{min-width:0}@-moz-document url-prefix(){fieldset{display:table-cell}}section{width:auto}}
2 | /*# sourceMappingURL=tacit-0.3.5.min.css.map */
3 |
--------------------------------------------------------------------------------
/riot_dragdrop/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Riotjs drag and drop
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/riot_dragdrop/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "webpack-dev-server",
5 | "dist": "webpack -p -d"
6 | },
7 | "devDependencies": {
8 | "dragula": "^3.1.0",
9 | "node-libs-browser": "^0.5.2",
10 | "riot": "^2.2.4",
11 | "riotjs-loader": "^1.1.3",
12 | "webpack": "^1.12.1",
13 | "webpack-dev-server": "^1.10.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/riot_dragdrop/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | {name} |
8 |
9 |
10 | Move Last To First
11 |
12 |
44 |
45 |
--------------------------------------------------------------------------------
/riot_dragdrop/src/index.js:
--------------------------------------------------------------------------------
1 | require('./app.html')
2 | riot.mount('app')
3 |
--------------------------------------------------------------------------------
/riot_dragdrop/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 |
3 | module.exports = {
4 | cache: true,
5 | entry: './src/index.js',
6 | output: {
7 | path: './dist/',
8 | publicPath: '/dist/',
9 | filename: 'bundle.js'
10 | },
11 | module: {
12 | loaders: [
13 | { test: /\.html$/, include: /src/, loader: 'riotjs' }
14 | ]
15 | },
16 | plugins: [
17 | new webpack.ProvidePlugin({
18 | riot: 'riot'
19 | })
20 | ],
21 | devServer: {
22 | port: 7654
23 | },
24 | devtool: "source-map"
25 | }
26 |
--------------------------------------------------------------------------------
/riot_flux/README.md:
--------------------------------------------------------------------------------
1 | ## Riot Flux demo by using [RiotControl](https://github.com/jimsparkman/RiotControl)
2 |
3 | Online demo: http://txchen.github.io/feplay/riot_flux/
4 |
5 | RiotControl cannot be simpler, it just has 17 lines of code! And it can act as a dispatcher with RiotJs, in flux architecture. Just wonderful!
6 |
7 | I followed RiotControl's demo to create this sample app, it is another implementation of [this](https://github.com/voronianski/flux-comparison) project.
8 |
9 | As you can see, the code is much simpler and easier to understand, than any of ReactJS implementations. Besides, the total js size is much smaller than React.
10 |
11 | Why not give [RiotJs](http://riotjs.com/) 5 minutes?
12 |
--------------------------------------------------------------------------------
/riot_flux/css/main.css:
--------------------------------------------------------------------------------
1 | .shop-wrap {
2 | max-width: 900px;
3 | width: 60%;
4 | margin: 20px 25px;
5 | }
6 | .cart {
7 | position: fixed;
8 | right: 50px;
9 | top: 30px;
10 | }
11 |
--------------------------------------------------------------------------------
/riot_flux/img/ipad-mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txchen/feplay/6de713d706dcc691e27314c7c8a4f11201a00d44/riot_flux/img/ipad-mini.png
--------------------------------------------------------------------------------
/riot_flux/img/sucker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txchen/feplay/6de713d706dcc691e27314c7c8a4f11201a00d44/riot_flux/img/sucker.png
--------------------------------------------------------------------------------
/riot_flux/img/t-shirt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txchen/feplay/6de713d706dcc691e27314c7c8a4f11201a00d44/riot_flux/img/t-shirt.png
--------------------------------------------------------------------------------
/riot_flux/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Riot Flux Demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
26 |
27 |
--------------------------------------------------------------------------------
/riot_flux/js/CartStore.js:
--------------------------------------------------------------------------------
1 | function CartStore() {
2 | if (!(this instanceof CartStore)) return new CartStore()
3 |
4 | riot.observable(this)
5 |
6 | var self = this
7 |
8 | self.productsInCart = {}
9 |
10 | self.on('ve_add_to_cart', function(product) {
11 | var id = product.id
12 | if (id in self.productsInCart) {
13 | self.productsInCart[id].quantity += 1
14 | } else {
15 | self.productsInCart[id] = {"quantity": 1, "title": product.title, "price": product.price,
16 | "image": product.image, "id": id}
17 | }
18 | self.trigger('se_cart_changed', self.productsInCart)
19 | })
20 |
21 | self.on('ve_checkout', function() {
22 | // call backend service to checkout, if success, then
23 | console.log('you have purchased:', self.productsInCart)
24 | self.productsInCart = {}
25 | self.trigger('se_cart_changed', self.productsInCart)
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/riot_flux/js/ProductStore.js:
--------------------------------------------------------------------------------
1 | function ProductStore() {
2 | if (!(this instanceof ProductStore)) return new ProductStore()
3 |
4 | riot.observable(this)
5 |
6 | var self = this
7 |
8 | // Could pull this from a server API.
9 | self.products = [
10 | {"id": 1, "title": "iPad 4 Mini", "price": 500.01, "inventory": 2, "image": "img/ipad-mini.png"},
11 | {"id": 2, "title": "H&M T-Shirt White", "price": 10.99, "inventory": 10, "image": "img/t-shirt.png"},
12 | {"id": 3, "title": "Charli XCX - Sucker CD", "price": 19.99, "inventory": 5, "image": "img/sucker.png"}
13 | ]
14 |
15 | self.on('ve_add_to_cart', function(product) {
16 | self.products.some(function(p) {
17 | if (p.id === product.id) {
18 | p.inventory = p.inventory > 0 ? p.inventory - 1 : 0
19 | return true
20 | }
21 | })
22 | self.trigger('se_products_changed', self.products)
23 | })
24 |
25 | self.on('ve_product_list_init', function() {
26 | // here it can query server in real scenario
27 | self.trigger('se_products_changed', self.products)
28 | })
29 | }
30 |
--------------------------------------------------------------------------------
/riot_flux/js/RiotControl.js:
--------------------------------------------------------------------------------
1 | var RiotControl = {
2 | _stores: [],
3 | addStore: function(store) {
4 | this._stores.push(store);
5 | }
6 | };
7 |
8 | ['on','one','off','trigger'].forEach(function(api){
9 | RiotControl[api] = function() {
10 | var args = [].slice.call(arguments);
11 | this._stores.forEach(function(el){
12 | el[api].apply(el, args);
13 | });
14 | };
15 | });
16 |
17 | if (typeof(module) !== 'undefined') module.exports = RiotControl;
18 |
--------------------------------------------------------------------------------
/riot_flux/js/cart.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Your Cart
4 |
5 | Please add some products to cart.
6 |
7 |
8 |
{title} - €{price} x {quantity}
9 |
10 |
Total: €{ totalPrice() }
11 |
13 | Checkout
14 |
15 |
16 |
17 |
42 |
43 |
--------------------------------------------------------------------------------
/riot_flux/js/products.html:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
24 |
25 |
26 |
27 |
28 |
29 |
{ product.title } - €{ product.price }
30 |
33 | { product.inventory > 0 ? 'Add to cart' : 'Sold Out' }
34 |
35 |
36 |
43 |
44 |
--------------------------------------------------------------------------------
/riot_ramjet/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | !node_modules/ramjet/dist/ramjet.umd.min.js
4 | !node_modules/riot/riot+compiler.min.js
5 |
--------------------------------------------------------------------------------
/riot_ramjet/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Play ramjet with riot
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/riot_ramjet/js/app.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 | Ramjet with riot, click 'a' or 'c'
4 |
5 | a
6 | b
7 | c
8 |
9 |
10 |
11 |
31 |
32 |
--------------------------------------------------------------------------------
/riot_ramjet/node_modules/ramjet/dist/ramjet.umd.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.ramjet=t()}(this,function(){"use strict";function e(){document.body.appendChild(w),T=!0}function t(e,n,o){var i=o?o(e,n):e.cloneNode();if("undefined"!=typeof i){var r=void 0,a=void 0,s=void 0,d=void 0;if(1===e.nodeType)for(r=window.getComputedStyle(e),g.forEach(function(e){i.style[e]=r[e]}),a=e.childNodes.length,s=0;a>s;s+=1)d=t(e.childNodes[s],n+1,o),d&&i.appendChild(d);return i}}function n(e,n,o,i){var r=e.namespaceURI===b,a=e.getBoundingClientRect(),s=a.left,d=a.right,l=a.top,c=a.bottom,u=window.getComputedStyle(e),f=t(e,0,o),m={node:e,clone:f,isSvg:r,cx:(s+d)/2,cy:(l+c)/2,width:d-s,height:c-l,transform:null,borderRadius:null};if(r){var p=e.getScreenCTM();m.transform="matrix("+[p.a,p.b,p.c,p.d,p.e,p.f].join(",")+")",m.borderRadius=[0,0,0,0],w.appendChild(f)}else{if(n)f.style.position="fixed",f.style.top=l-parseInt(u.marginTop,10)+"px",f.style.left=s-parseInt(u.marginLeft,10)+"px";else{var y=e.offsetParent;if(null===y||y===document.body||i){var h=document.documentElement;f.style.position="absolute",f.style.top=l+window.pageYOffset-h.clientTop-parseInt(u.marginTop,10)+"px",f.style.left=s+window.pageXOffset-h.clientLeft-parseInt(u.marginLeft,10)+"px"}else{var v=window.getComputedStyle(y),g=y.getBoundingClientRect();f.style.position="absolute",f.style.top=l-parseInt(u.marginTop,10)-(g.top-parseInt(v.marginTop,10))+"px",f.style.left=s-parseInt(u.marginLeft,10)-(g.left-parseInt(v.marginLeft,10))+"px"}}m.transform="",m.borderRadius=[parseFloat(u.borderTopLeftRadius),parseFloat(u.borderTopRightRadius),parseFloat(u.borderBottomRightRadius),parseFloat(u.borderBottomLeftRadius)],i?document.body.appendChild(f):e.parentNode.appendChild(f)}return m}function o(e){e.__ramjetOriginalTransition__=e.style.transition,e.style.transition="",e.style.opacity=0}function i(e){e.style.transition="",e.style.opacity=1,e.__ramjetOriginalTransition__&&setTimeout(function(){e.style.transition=e.__ramjetOriginalTransition__})}function r(e){for(;null!==e;){if("fixed"===window.getComputedStyle(e).position)return!0;e=e.namespaceURI===b?e.parentNode:e.offsetParent}return!1}function a(e,t,n,o,i,r,a,s,d){var l=e?"translate("+t+" "+n+") scale("+(1+d*r)+" "+(1+d*a)+") translate("+-t+" "+-n+") translate("+s*o+" "+s*i+")":"translate("+s*o+"px,"+s*i+"px) scale("+(1+d*r)+","+(1+d*a)+")";return l}function s(e,t,n,o,i){var r=1+i*n,a=1+i*o;return e.map(function(e,n){var o=t[n],s=(e+i*(o-e))/r,d=(e+i*(o-e))/a;return s+"px "+d+"px"})}function d(e){return e}function l(e){return Math.pow(e,3)}function c(e){return Math.pow(e-1,3)+1}function u(e){return(e/=.5)<1?.5*Math.pow(e,3):.5*(Math.pow(e-2,3)+2)}function f(e,t){e.style.borderTopLeftRadius=t[0],e.style.borderTopRightRadius=t[1],e.style.borderBottomRightRadius=t[2],e.style.borderBottomLeftRadius=t[3]}function m(e){var t=document.createElement("style");t.type="text/css";var n=document.getElementsByTagName("head")[0],o=t.styleSheet;return o?o.cssText=e:t.innerHTML=e,n.appendChild(t),function(){return n.removeChild(t)}}function p(e,t,n){function o(n,o,i){var d=e.cx+r*o,p=e.cy+l*o,y=s(e.borderRadius,t.borderRadius,c,u,o),h=s(t.borderRadius,e.borderRadius,f,m,1-o),b=a(!1,d,p,r,l,c,u,o,i)+" "+e.transform,w=a(!1,d,p,-r,-l,f,m,1-o,1-i)+" "+t.transform;v.push("\n "+n+"% {\n opacity: "+(1-o)+";\n border-top-left-radius: "+y[0]+";\n border-top-right-radius: "+y[1]+";\n border-bottom-right-radius: "+y[2]+";\n border-bottom-left-radius: "+y[3]+";\n "+A+": "+b+";\n }"),g.push("\n "+n+"% {\n opacity: "+o+";\n border-top-left-radius: "+h[0]+";\n border-top-right-radius: "+h[1]+";\n border-bottom-right-radius: "+h[2]+";\n border-bottom-left-radius: "+h[3]+";\n "+A+": "+w+";\n }")}var i,r=t.cx-e.cx,l=t.cy-e.cy,c=t.width/e.width-1,u=t.height/e.height-1,f=e.width/t.width-1,m=e.height/t.height-1,p=n.easing||d,y=n.easingScale||p,h=n.duration/50,v=[],g=[];for(i=0;h>i;i+=1){var b=100*(i/h),w=p(i/h),C=y(i/h);o(b,w,C)}return o(100,1,1),v=v.join("\n"),g=g.join("\n"),{fromKeyframes:v,toKeyframes:g}}var y={};y.classCallCheck=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")};var h=["length","parentRule"],v=void 0;v="undefined"!=typeof CSS2Properties?Object.keys(CSS2Properties.prototype):Object.keys(document.createElement("div").style).filter(function(e){return!~h.indexOf(e)});var g=v,b="http://www.w3.org/2000/svg",w=void 0;try{w=document.createElementNS(b,"svg"),w.style.position="fixed",w.style.top=w.style.left="0",w.style.width=w.style.height="100%",w.style.overflow="visible",w.style.pointerEvents="none",w.setAttribute("class","mogrify-svg")}catch(C){console.log("The current browser doesn't support SVG")}var T=!1,R=window.requestAnimationFrame||window.webkitRequestAnimationFrame||function(e){return setTimeout(e,16)},x=function D(e,t,n){function o(){var d=Date.now(),y=d-p;if(y>h)return e.clone.parentNode.removeChild(e.clone),t.clone.parentNode.removeChild(t.clone),void(n.done&&n.done());var b=v(y/h),w=g(y/h);e.clone.style.opacity=1-b,t.clone.style.opacity=b;var C=s(e.borderRadius,t.borderRadius,l,c,b),T=s(t.borderRadius,e.borderRadius,u,m,1-b);f(e.clone,C),f(t.clone,T);var x=e.cx+i*b,S=e.cy+r*b,k=a(e.isSvg,x,S,i,r,l,c,b,w)+" "+e.transform,A=a(t.isSvg,x,S,-i,-r,u,m,1-b,1-w)+" "+t.transform;e.isSvg?e.clone.setAttribute("transform",k):e.clone.style.transform=e.clone.style.webkitTransform=e.clone.style.msTransform=k,t.isSvg?t.clone.setAttribute("transform",A):t.clone.style.transform=t.clone.style.webkitTransform=t.clone.style.msTransform=A,R(o)}y.classCallCheck(this,D);var i=t.cx-e.cx,r=t.cy-e.cy,l=t.width/e.width-1,c=t.height/e.height-1,u=e.width/t.width-1,m=e.height/t.height-1,p=Date.now(),h=n.duration||400,v=n.easing||d,g=n.easingScale||v;o()},S=document.createElement("div"),k=!0,A=void 0,E=void 0,I=void 0,_=void 0,N=void 0,j=void 0,L=void 0,O=void 0,B=!window.ActiveXObject&&"ActiveXObject"in window;!B&&("transform"in S.style||"webkitTransform"in S.style)&&("animation"in S.style||"webkitAnimation"in S.style)?(k=!0,A="transform"in S.style?"transform":"-webkit-transform","animation"in S.style?(E="@keyframes",I="animationDirection",_="animationDuration",N="animationIterationCount",j="animationName",L="animationTimingFunction",O="animationend"):(E="@-webkit-keyframes",I="webkitAnimationDirection",_="webkitAnimationDuration",N="webkitAnimationIterationCount",j="webkitAnimationName",L="webkitAnimationTimingFunction",O="webkitAnimationEnd")):k=!1;var F=function K(e,t,n){function o(){u&&f&&(e.clone.parentNode.removeChild(e.clone),t.clone.parentNode.removeChild(t.clone),n.done&&n.done(),c())}y.classCallCheck(this,K);var i=p(e,t,n),r=i.fromKeyframes,a=i.toKeyframes,s="_"+~~(1e6*Math.random()),d="_"+~~(1e6*Math.random()),l=E+" "+s+" { "+r+" } "+E+" "+d+" { "+a+" }",c=m(l);e.clone.style[I]="alternate",e.clone.style[_]=n.duration/1e3+"s",e.clone.style[N]=1,e.clone.style[j]=s,e.clone.style[L]="linear",t.clone.style[I]="alternate",t.clone.style[_]=n.duration/1e3+"s",t.clone.style[N]=1,t.clone.style[j]=d,t.clone.style[L]="linear";var u=void 0,f=void 0;e.clone.addEventListener(O,function(){u=!0,o()}),t.clone.addEventListener(O,function(){f=!0,o()})},M={transform:function(t,o){var i=arguments.length<=2||void 0===arguments[2]?{}:arguments[2];"function"==typeof i&&(i={done:i}),"duration"in i||(i.duration=400);var a=!!i.appendToBody,s=r(o),d=n(t,s,i.overrideClone,a),l=n(o,s,i.overrideClone,a);return(d.isSvg||l.isSvg&&!T)&&e(),!k||i.useTimer||d.isSvg||l.isSvg?new x(d,l,i):new F(d,l,i)},hide:function(){for(var e=arguments.length,t=Array(e),n=0;e>n;n++)t[n]=arguments[n];t.forEach(o)},show:function(){for(var e=arguments.length,t=Array(e),n=0;e>n;n++)t[n]=arguments[n];t.forEach(i)},linear:d,easeIn:l,easeOut:c,easeInOut:u};return M});
2 | //# sourceMappingURL=/www/ramjet/.gobble-build/11-uglifyjs/.cache/ramjet.umd.js.map
3 |
--------------------------------------------------------------------------------
/riot_ramjet/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "dependencies": {
4 | "ramjet": "^0.5.0",
5 | "riot": "^2.3.15"
6 | },
7 | "devDependencies": {
8 | "light-server": "^1.1.5"
9 | },
10 | "scripts": {
11 | "dev": "light-server -s . -w 'js/**'"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/riot_todo/.gitignore:
--------------------------------------------------------------------------------
1 | !node_modules
2 |
3 | node_modules/todomvc-app-css/*
4 | !node_modules/todomvc-app-css/index.css
5 |
6 | node_modules/todomvc-common/*
7 | !node_modules/todomvc-common/base.css
8 | !node_modules/todomvc-common/base.js
9 |
10 | node_modules/.bin
11 | node_modules/riot/*
12 | !node_modules/riot/riot.min.js
13 | !node_modules/riot/riot+compiler.min.js
14 |
15 | node_modules/light-server
16 |
--------------------------------------------------------------------------------
/riot_todo/README.md:
--------------------------------------------------------------------------------
1 | ## TodoMVC by Riotjs
2 |
3 | Online demo: http://txchen.github.io/feplay/riot_todo/
4 |
5 | The official riotjs todomvc implementation can be found here: https://github.com/tastejs/todomvc/tree/gh-pages/examples/riotjs
6 |
7 | The official todomvc one follows todomvc's style but this repo follows riotjs' style, IMHO, is more cleaner.
8 |
--------------------------------------------------------------------------------
/riot_todo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Riot.js • TodoMVC
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/riot_todo/js/app.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict'
3 | riot.mount('todo', { data: todoStorage.fetch() })
4 | }())
5 |
--------------------------------------------------------------------------------
/riot_todo/js/store.js:
--------------------------------------------------------------------------------
1 | (function (exports) {
2 | 'use strict'
3 |
4 | var STORAGE_KEY = 'todos-riotjs'
5 |
6 | exports.todoStorage = {
7 | fetch: function () {
8 | return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
9 | },
10 | save: function (todos) {
11 | localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
12 | }
13 | }
14 |
15 | })(window)
16 |
--------------------------------------------------------------------------------
/riot_todo/js/todo.html:
--------------------------------------------------------------------------------
1 |
2 |
27 |
32 |
102 |
103 |
104 |
105 |
106 |
107 | { opts.todo.title }
108 |
109 |
110 |
111 |
162 |
163 |
--------------------------------------------------------------------------------
/riot_todo/node_modules/todomvc-app-css/index.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | button {
8 | margin: 0;
9 | padding: 0;
10 | border: 0;
11 | background: none;
12 | font-size: 100%;
13 | vertical-align: baseline;
14 | font-family: inherit;
15 | font-weight: inherit;
16 | color: inherit;
17 | -webkit-appearance: none;
18 | appearance: none;
19 | -webkit-font-smoothing: antialiased;
20 | -moz-font-smoothing: antialiased;
21 | font-smoothing: antialiased;
22 | }
23 |
24 | body {
25 | font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
26 | line-height: 1.4em;
27 | background: #f5f5f5;
28 | color: #4d4d4d;
29 | min-width: 230px;
30 | max-width: 550px;
31 | margin: 0 auto;
32 | -webkit-font-smoothing: antialiased;
33 | -moz-font-smoothing: antialiased;
34 | font-smoothing: antialiased;
35 | font-weight: 300;
36 | }
37 |
38 | button,
39 | input[type="checkbox"] {
40 | outline: none;
41 | }
42 |
43 | .hidden {
44 | display: none;
45 | }
46 |
47 | .todoapp {
48 | background: #fff;
49 | margin: 130px 0 40px 0;
50 | position: relative;
51 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
52 | 0 25px 50px 0 rgba(0, 0, 0, 0.1);
53 | }
54 |
55 | .todoapp input::-webkit-input-placeholder {
56 | font-style: italic;
57 | font-weight: 300;
58 | color: #e6e6e6;
59 | }
60 |
61 | .todoapp input::-moz-placeholder {
62 | font-style: italic;
63 | font-weight: 300;
64 | color: #e6e6e6;
65 | }
66 |
67 | .todoapp input::input-placeholder {
68 | font-style: italic;
69 | font-weight: 300;
70 | color: #e6e6e6;
71 | }
72 |
73 | .todoapp h1 {
74 | position: absolute;
75 | top: -155px;
76 | width: 100%;
77 | font-size: 100px;
78 | font-weight: 100;
79 | text-align: center;
80 | color: rgba(175, 47, 47, 0.15);
81 | -webkit-text-rendering: optimizeLegibility;
82 | -moz-text-rendering: optimizeLegibility;
83 | text-rendering: optimizeLegibility;
84 | }
85 |
86 | .new-todo,
87 | .edit {
88 | position: relative;
89 | margin: 0;
90 | width: 100%;
91 | font-size: 24px;
92 | font-family: inherit;
93 | font-weight: inherit;
94 | line-height: 1.4em;
95 | border: 0;
96 | outline: none;
97 | color: inherit;
98 | padding: 6px;
99 | border: 1px solid #999;
100 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
101 | box-sizing: border-box;
102 | -webkit-font-smoothing: antialiased;
103 | -moz-font-smoothing: antialiased;
104 | font-smoothing: antialiased;
105 | }
106 |
107 | .new-todo {
108 | padding: 16px 16px 16px 60px;
109 | border: none;
110 | background: rgba(0, 0, 0, 0.003);
111 | box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
112 | }
113 |
114 | .main {
115 | position: relative;
116 | z-index: 2;
117 | border-top: 1px solid #e6e6e6;
118 | }
119 |
120 | label[for='toggle-all'] {
121 | display: none;
122 | }
123 |
124 | .toggle-all {
125 | position: absolute;
126 | top: -55px;
127 | left: -12px;
128 | width: 60px;
129 | height: 34px;
130 | text-align: center;
131 | border: none; /* Mobile Safari */
132 | }
133 |
134 | .toggle-all:before {
135 | content: '❯';
136 | font-size: 22px;
137 | color: #e6e6e6;
138 | padding: 10px 27px 10px 27px;
139 | }
140 |
141 | .toggle-all:checked:before {
142 | color: #737373;
143 | }
144 |
145 | .todo-list {
146 | margin: 0;
147 | padding: 0;
148 | list-style: none;
149 | }
150 |
151 | .todo-list li {
152 | position: relative;
153 | font-size: 24px;
154 | border-bottom: 1px solid #ededed;
155 | }
156 |
157 | .todo-list li:last-child {
158 | border-bottom: none;
159 | }
160 |
161 | .todo-list li.editing {
162 | border-bottom: none;
163 | padding: 0;
164 | }
165 |
166 | .todo-list li.editing .edit {
167 | display: block;
168 | width: 506px;
169 | padding: 13px 17px 12px 17px;
170 | margin: 0 0 0 43px;
171 | }
172 |
173 | .todo-list li.editing .view {
174 | display: none;
175 | }
176 |
177 | .todo-list li .toggle {
178 | text-align: center;
179 | width: 40px;
180 | /* auto, since non-WebKit browsers doesn't support input styling */
181 | height: auto;
182 | position: absolute;
183 | top: 0;
184 | bottom: 0;
185 | margin: auto 0;
186 | border: none; /* Mobile Safari */
187 | -webkit-appearance: none;
188 | appearance: none;
189 | }
190 |
191 | .todo-list li .toggle:after {
192 | content: url('data:image/svg+xml;utf8, ');
193 | }
194 |
195 | .todo-list li .toggle:checked:after {
196 | content: url('data:image/svg+xml;utf8, ');
197 | }
198 |
199 | .todo-list li label {
200 | white-space: pre;
201 | word-break: break-word;
202 | padding: 15px 60px 15px 15px;
203 | margin-left: 45px;
204 | display: block;
205 | line-height: 1.2;
206 | transition: color 0.4s;
207 | }
208 |
209 | .todo-list li.completed label {
210 | color: #d9d9d9;
211 | text-decoration: line-through;
212 | }
213 |
214 | .todo-list li .destroy {
215 | display: none;
216 | position: absolute;
217 | top: 0;
218 | right: 10px;
219 | bottom: 0;
220 | width: 40px;
221 | height: 40px;
222 | margin: auto 0;
223 | font-size: 30px;
224 | color: #cc9a9a;
225 | margin-bottom: 11px;
226 | transition: color 0.2s ease-out;
227 | }
228 |
229 | .todo-list li .destroy:hover {
230 | color: #af5b5e;
231 | }
232 |
233 | .todo-list li .destroy:after {
234 | content: '×';
235 | }
236 |
237 | .todo-list li:hover .destroy {
238 | display: block;
239 | }
240 |
241 | .todo-list li .edit {
242 | display: none;
243 | }
244 |
245 | .todo-list li.editing:last-child {
246 | margin-bottom: -1px;
247 | }
248 |
249 | .footer {
250 | color: #777;
251 | padding: 10px 15px;
252 | height: 20px;
253 | text-align: center;
254 | border-top: 1px solid #e6e6e6;
255 | }
256 |
257 | .footer:before {
258 | content: '';
259 | position: absolute;
260 | right: 0;
261 | bottom: 0;
262 | left: 0;
263 | height: 50px;
264 | overflow: hidden;
265 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
266 | 0 8px 0 -3px #f6f6f6,
267 | 0 9px 1px -3px rgba(0, 0, 0, 0.2),
268 | 0 16px 0 -6px #f6f6f6,
269 | 0 17px 2px -6px rgba(0, 0, 0, 0.2);
270 | }
271 |
272 | .todo-count {
273 | float: left;
274 | text-align: left;
275 | }
276 |
277 | .todo-count strong {
278 | font-weight: 300;
279 | }
280 |
281 | .filters {
282 | margin: 0;
283 | padding: 0;
284 | list-style: none;
285 | position: absolute;
286 | right: 0;
287 | left: 0;
288 | }
289 |
290 | .filters li {
291 | display: inline;
292 | }
293 |
294 | .filters li a {
295 | color: inherit;
296 | margin: 3px;
297 | padding: 3px 7px;
298 | text-decoration: none;
299 | border: 1px solid transparent;
300 | border-radius: 3px;
301 | }
302 |
303 | .filters li a.selected,
304 | .filters li a:hover {
305 | border-color: rgba(175, 47, 47, 0.1);
306 | }
307 |
308 | .filters li a.selected {
309 | border-color: rgba(175, 47, 47, 0.2);
310 | }
311 |
312 | .clear-completed,
313 | html .clear-completed:active {
314 | float: right;
315 | position: relative;
316 | line-height: 20px;
317 | text-decoration: none;
318 | cursor: pointer;
319 | position: relative;
320 | }
321 |
322 | .clear-completed:hover {
323 | text-decoration: underline;
324 | }
325 |
326 | .info {
327 | margin: 65px auto 0;
328 | color: #bfbfbf;
329 | font-size: 10px;
330 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
331 | text-align: center;
332 | }
333 |
334 | .info p {
335 | line-height: 1;
336 | }
337 |
338 | .info a {
339 | color: inherit;
340 | text-decoration: none;
341 | font-weight: 400;
342 | }
343 |
344 | .info a:hover {
345 | text-decoration: underline;
346 | }
347 |
348 | /*
349 | Hack to remove background from Mobile Safari.
350 | Can't use it globally since it destroys checkboxes in Firefox
351 | */
352 | @media screen and (-webkit-min-device-pixel-ratio:0) {
353 | .toggle-all,
354 | .todo-list li .toggle {
355 | background: none;
356 | }
357 |
358 | .todo-list li .toggle {
359 | height: 40px;
360 | }
361 |
362 | .toggle-all {
363 | -webkit-transform: rotate(90deg);
364 | transform: rotate(90deg);
365 | -webkit-appearance: none;
366 | appearance: none;
367 | }
368 | }
369 |
370 | @media (max-width: 430px) {
371 | .footer {
372 | height: 50px;
373 | }
374 |
375 | .filters {
376 | bottom: 10px;
377 | }
378 | }
379 |
--------------------------------------------------------------------------------
/riot_todo/node_modules/todomvc-common/base.css:
--------------------------------------------------------------------------------
1 | hr {
2 | margin: 20px 0;
3 | border: 0;
4 | border-top: 1px dashed #c5c5c5;
5 | border-bottom: 1px dashed #f7f7f7;
6 | }
7 |
8 | .learn a {
9 | font-weight: normal;
10 | text-decoration: none;
11 | color: #b83f45;
12 | }
13 |
14 | .learn a:hover {
15 | text-decoration: underline;
16 | color: #787e7e;
17 | }
18 |
19 | .learn h3,
20 | .learn h4,
21 | .learn h5 {
22 | margin: 10px 0;
23 | font-weight: 500;
24 | line-height: 1.2;
25 | color: #000;
26 | }
27 |
28 | .learn h3 {
29 | font-size: 24px;
30 | }
31 |
32 | .learn h4 {
33 | font-size: 18px;
34 | }
35 |
36 | .learn h5 {
37 | margin-bottom: 0;
38 | font-size: 14px;
39 | }
40 |
41 | .learn ul {
42 | padding: 0;
43 | margin: 0 0 30px 25px;
44 | }
45 |
46 | .learn li {
47 | line-height: 20px;
48 | }
49 |
50 | .learn p {
51 | font-size: 15px;
52 | font-weight: 300;
53 | line-height: 1.3;
54 | margin-top: 0;
55 | margin-bottom: 0;
56 | }
57 |
58 | #issue-count {
59 | display: none;
60 | }
61 |
62 | .quote {
63 | border: none;
64 | margin: 20px 0 60px 0;
65 | }
66 |
67 | .quote p {
68 | font-style: italic;
69 | }
70 |
71 | .quote p:before {
72 | content: '“';
73 | font-size: 50px;
74 | opacity: .15;
75 | position: absolute;
76 | top: -20px;
77 | left: 3px;
78 | }
79 |
80 | .quote p:after {
81 | content: '”';
82 | font-size: 50px;
83 | opacity: .15;
84 | position: absolute;
85 | bottom: -42px;
86 | right: 3px;
87 | }
88 |
89 | .quote footer {
90 | position: absolute;
91 | bottom: -40px;
92 | right: 0;
93 | }
94 |
95 | .quote footer img {
96 | border-radius: 3px;
97 | }
98 |
99 | .quote footer a {
100 | margin-left: 5px;
101 | vertical-align: middle;
102 | }
103 |
104 | .speech-bubble {
105 | position: relative;
106 | padding: 10px;
107 | background: rgba(0, 0, 0, .04);
108 | border-radius: 5px;
109 | }
110 |
111 | .speech-bubble:after {
112 | content: '';
113 | position: absolute;
114 | top: 100%;
115 | right: 30px;
116 | border: 13px solid transparent;
117 | border-top-color: rgba(0, 0, 0, .04);
118 | }
119 |
120 | .learn-bar > .learn {
121 | position: absolute;
122 | width: 272px;
123 | top: 8px;
124 | left: -300px;
125 | padding: 10px;
126 | border-radius: 5px;
127 | background-color: rgba(255, 255, 255, .6);
128 | transition-property: left;
129 | transition-duration: 500ms;
130 | }
131 |
132 | @media (min-width: 899px) {
133 | .learn-bar {
134 | width: auto;
135 | padding-left: 300px;
136 | }
137 |
138 | .learn-bar > .learn {
139 | left: 8px;
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/riot_todo/node_modules/todomvc-common/base.js:
--------------------------------------------------------------------------------
1 | /* global _ */
2 | (function () {
3 | 'use strict';
4 |
5 | /* jshint ignore:start */
6 | // Underscore's Template Module
7 | // Courtesy of underscorejs.org
8 | var _ = (function (_) {
9 | _.defaults = function (object) {
10 | if (!object) {
11 | return object;
12 | }
13 | for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
14 | var iterable = arguments[argsIndex];
15 | if (iterable) {
16 | for (var key in iterable) {
17 | if (object[key] == null) {
18 | object[key] = iterable[key];
19 | }
20 | }
21 | }
22 | }
23 | return object;
24 | }
25 |
26 | // By default, Underscore uses ERB-style template delimiters, change the
27 | // following template settings to use alternative delimiters.
28 | _.templateSettings = {
29 | evaluate : /<%([\s\S]+?)%>/g,
30 | interpolate : /<%=([\s\S]+?)%>/g,
31 | escape : /<%-([\s\S]+?)%>/g
32 | };
33 |
34 | // When customizing `templateSettings`, if you don't want to define an
35 | // interpolation, evaluation or escaping regex, we need one that is
36 | // guaranteed not to match.
37 | var noMatch = /(.)^/;
38 |
39 | // Certain characters need to be escaped so that they can be put into a
40 | // string literal.
41 | var escapes = {
42 | "'": "'",
43 | '\\': '\\',
44 | '\r': 'r',
45 | '\n': 'n',
46 | '\t': 't',
47 | '\u2028': 'u2028',
48 | '\u2029': 'u2029'
49 | };
50 |
51 | var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
52 |
53 | // JavaScript micro-templating, similar to John Resig's implementation.
54 | // Underscore templating handles arbitrary delimiters, preserves whitespace,
55 | // and correctly escapes quotes within interpolated code.
56 | _.template = function(text, data, settings) {
57 | var render;
58 | settings = _.defaults({}, settings, _.templateSettings);
59 |
60 | // Combine delimiters into one regular expression via alternation.
61 | var matcher = new RegExp([
62 | (settings.escape || noMatch).source,
63 | (settings.interpolate || noMatch).source,
64 | (settings.evaluate || noMatch).source
65 | ].join('|') + '|$', 'g');
66 |
67 | // Compile the template source, escaping string literals appropriately.
68 | var index = 0;
69 | var source = "__p+='";
70 | text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
71 | source += text.slice(index, offset)
72 | .replace(escaper, function(match) { return '\\' + escapes[match]; });
73 |
74 | if (escape) {
75 | source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
76 | }
77 | if (interpolate) {
78 | source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
79 | }
80 | if (evaluate) {
81 | source += "';\n" + evaluate + "\n__p+='";
82 | }
83 | index = offset + match.length;
84 | return match;
85 | });
86 | source += "';\n";
87 |
88 | // If a variable is not specified, place data values in local scope.
89 | if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
90 |
91 | source = "var __t,__p='',__j=Array.prototype.join," +
92 | "print=function(){__p+=__j.call(arguments,'');};\n" +
93 | source + "return __p;\n";
94 |
95 | try {
96 | render = new Function(settings.variable || 'obj', '_', source);
97 | } catch (e) {
98 | e.source = source;
99 | throw e;
100 | }
101 |
102 | if (data) return render(data, _);
103 | var template = function(data) {
104 | return render.call(this, data, _);
105 | };
106 |
107 | // Provide the compiled function source as a convenience for precompilation.
108 | template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
109 |
110 | return template;
111 | };
112 |
113 | return _;
114 | })({});
115 |
116 | if (location.hostname === 'todomvc.com') {
117 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
118 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
119 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
120 | })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
121 | ga('create', 'UA-31081062-1', 'auto');
122 | ga('send', 'pageview');
123 | }
124 | /* jshint ignore:end */
125 |
126 | function redirect() {
127 | if (location.hostname === 'tastejs.github.io') {
128 | location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
129 | }
130 | }
131 |
132 | function findRoot() {
133 | var base = location.href.indexOf('examples/');
134 | return location.href.substr(0, base);
135 | }
136 |
137 | function getFile(file, callback) {
138 | if (!location.host) {
139 | return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.');
140 | }
141 |
142 | var xhr = new XMLHttpRequest();
143 |
144 | xhr.open('GET', findRoot() + file, true);
145 | xhr.send();
146 |
147 | xhr.onload = function () {
148 | if (xhr.status === 200 && callback) {
149 | callback(xhr.responseText);
150 | }
151 | };
152 | }
153 |
154 | function Learn(learnJSON, config) {
155 | if (!(this instanceof Learn)) {
156 | return new Learn(learnJSON, config);
157 | }
158 |
159 | var template, framework;
160 |
161 | if (typeof learnJSON !== 'object') {
162 | try {
163 | learnJSON = JSON.parse(learnJSON);
164 | } catch (e) {
165 | return;
166 | }
167 | }
168 |
169 | if (config) {
170 | template = config.template;
171 | framework = config.framework;
172 | }
173 |
174 | if (!template && learnJSON.templates) {
175 | template = learnJSON.templates.todomvc;
176 | }
177 |
178 | if (!framework && document.querySelector('[data-framework]')) {
179 | framework = document.querySelector('[data-framework]').dataset.framework;
180 | }
181 |
182 | this.template = template;
183 |
184 | if (learnJSON.backend) {
185 | this.frameworkJSON = learnJSON.backend;
186 | this.frameworkJSON.issueLabel = framework;
187 | this.append({
188 | backend: true
189 | });
190 | } else if (learnJSON[framework]) {
191 | this.frameworkJSON = learnJSON[framework];
192 | this.frameworkJSON.issueLabel = framework;
193 | this.append();
194 | }
195 |
196 | this.fetchIssueCount();
197 | }
198 |
199 | Learn.prototype.append = function (opts) {
200 | var aside = document.createElement('aside');
201 | aside.innerHTML = _.template(this.template, this.frameworkJSON);
202 | aside.className = 'learn';
203 |
204 | if (opts && opts.backend) {
205 | // Remove demo link
206 | var sourceLinks = aside.querySelector('.source-links');
207 | var heading = sourceLinks.firstElementChild;
208 | var sourceLink = sourceLinks.lastElementChild;
209 | // Correct link path
210 | var href = sourceLink.getAttribute('href');
211 | sourceLink.setAttribute('href', href.substr(href.lastIndexOf('http')));
212 | sourceLinks.innerHTML = heading.outerHTML + sourceLink.outerHTML;
213 | } else {
214 | // Localize demo links
215 | var demoLinks = aside.querySelectorAll('.demo-link');
216 | Array.prototype.forEach.call(demoLinks, function (demoLink) {
217 | if (demoLink.getAttribute('href').substr(0, 4) !== 'http') {
218 | demoLink.setAttribute('href', findRoot() + demoLink.getAttribute('href'));
219 | }
220 | });
221 | }
222 |
223 | document.body.className = (document.body.className + ' learn-bar').trim();
224 | document.body.insertAdjacentHTML('afterBegin', aside.outerHTML);
225 | };
226 |
227 | Learn.prototype.fetchIssueCount = function () {
228 | var issueLink = document.getElementById('issue-count-link');
229 | if (issueLink) {
230 | var url = issueLink.href.replace('https://github.com', 'https://api.github.com/repos');
231 | var xhr = new XMLHttpRequest();
232 | xhr.open('GET', url, true);
233 | xhr.onload = function (e) {
234 | var parsedResponse = JSON.parse(e.target.responseText);
235 | if (parsedResponse instanceof Array) {
236 | var count = parsedResponse.length;
237 | if (count !== 0) {
238 | issueLink.innerHTML = 'This app has ' + count + ' open issues';
239 | document.getElementById('issue-count').style.display = 'inline';
240 | }
241 | }
242 | };
243 | xhr.send();
244 | }
245 | };
246 |
247 | redirect();
248 | getFile('learn.json', Learn);
249 | })();
250 |
--------------------------------------------------------------------------------
/riot_todo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "dependencies": {
4 | "todomvc-app-css": "^2.0.1",
5 | "todomvc-common": "^1.0.2",
6 | "riot": "^2.3.0"
7 | },
8 | "devDependencies": {
9 | "light-server": "^1.1.0"
10 | },
11 | "scripts": {
12 | "dev": "light-server -s . -w 'js/**'"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/riot_vue/.lightserverrc:
--------------------------------------------------------------------------------
1 | {
2 | "serveDir": ".",
3 | "watchexps": [
4 | "tags/*.html",
5 | "app.tag"
6 | ]
7 | }
--------------------------------------------------------------------------------
/riot_vue/README.md:
--------------------------------------------------------------------------------
1 | Implement vue's examples by using [riotjs](http://riotjs.com).
2 |
3 | Online demo: http://txchen.github.io/feplay/riot_vue
4 |
5 | Vue's examples: http://vuejs.org/examples/
6 |
--------------------------------------------------------------------------------
/riot_vue/app.tag:
--------------------------------------------------------------------------------
1 |
2 |
3 | Examples
4 |
11 | Source Code
12 | RiotJs Ver: { riot.version }
13 | Vuejs versions
14 |
15 |
16 |
{ currentExample.title }
17 |
18 | { currentExample.desc }
19 |
20 |
21 |
22 |
23 |
55 |
56 |
--------------------------------------------------------------------------------
/riot_vue/img/hn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txchen/feplay/6de713d706dcc691e27314c7c8a4f11201a00d44/riot_vue/img/hn.png
--------------------------------------------------------------------------------
/riot_vue/img/todomvc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txchen/feplay/6de713d706dcc691e27314c7c8a4f11201a00d44/riot_vue/img/todomvc.png
--------------------------------------------------------------------------------
/riot_vue/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Riot vue
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/riot_vue/main.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 0;
3 | height: 100%;
4 | font-family: 'Helvetica Neue', Arial, sans-serif;
5 | color: #333;
6 | }
7 | #sidenavs {
8 | position: absolute;
9 | z-index: 10;
10 | top: 0;
11 | left: 0;
12 | bottom: 0;
13 | overflow-y: scroll;
14 | padding: 1.2em 20px 20px;
15 | width: 240px;
16 | }
17 | #example {
18 | margin: 0 auto;
19 | }
20 | #sidenavs ul, a.vuelink {
21 | line-height: 1.8em;
22 | }
23 | #sidenavs ul {
24 | list-style-type: none;
25 | margin: 0;
26 | padding-left: 1em;
27 | }
28 | #sidenavs a, a.vuelink {
29 | text-decoration: none;
30 | color: #7f8c8d;
31 | }
32 | #sidenavs a:hover,
33 | a:hover.vuelink,
34 | #sidenavs a.current {
35 | border-bottom: 2px solid #42b983;
36 | }
37 | #example-content {
38 | box-sizing: border-box;
39 | width: 100%;
40 | height: 100%;
41 | padding: 2.2em 20px 20px 300px;
42 | margin: 0 auto;
43 | }
44 | #example-content h1 {
45 | margin: 0 0 1em;
46 | }
47 | #example-content blockquote {
48 | margin: 2em 0;
49 | padding-left: 20px;
50 | border-left: 4px solid #42b983;
51 | }
52 |
--------------------------------------------------------------------------------
/riot_vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "dependencies": {
4 | },
5 | "devDependencies": {
6 | "light-server": "^1.1.5"
7 | },
8 | "scripts": {
9 | "dev": "light-server -c .lightserverrc"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/riot_vue/tags/firebase.html:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 | { name } - { email }
27 | X
28 |
29 |
30 |
37 |
38 | Name cannot be empty.
39 | Please provide a valid email address.
40 |
41 |
42 |
101 |
102 |
--------------------------------------------------------------------------------
/riot_vue/tags/githubcommits.html:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 | Latest riotjs Commits
17 |
18 |
20 | { name }
21 |
22 | muut/riotjs@{ currentBranch }
23 |
24 |
25 | { sha.slice(0, 7) }
26 | - { parent.truncate(commit.message) }
27 | by { commit.author.name }
28 | at { parent.formatDate(commit.author.date) }
29 |
30 |
31 |
32 |
68 |
69 |
--------------------------------------------------------------------------------
/riot_vue/tags/gridcomponent.html:
--------------------------------------------------------------------------------
1 |
2 |
56 |
57 | Search
58 |
59 |
60 |
61 | { name }
63 |
64 |
65 |
66 |
67 |
68 |
69 | { value }
70 |
71 |
72 |
73 |
74 |
117 |
118 |
--------------------------------------------------------------------------------
/riot_vue/tags/hackernews.html:
--------------------------------------------------------------------------------
1 |
2 | It uses npm to manage tasks in development, and uses browserify to pack all the javascript files and tag files into one single output js.
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/riot_vue/tags/imageslider.html:
--------------------------------------------------------------------------------
1 |
2 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/riot_vue/tags/markdown.html:
--------------------------------------------------------------------------------
1 |
2 |
32 |
36 |
37 |
43 |
44 |
--------------------------------------------------------------------------------
/riot_vue/tags/modal.html:
--------------------------------------------------------------------------------
1 |
2 | Show Modal
3 |
4 |
5 |
6 |
11 |
12 |
13 | Riot body
14 |
15 |
16 |
22 |
23 |
24 |
32 |
33 |
34 |
35 |
42 |
43 |
99 |
100 |
--------------------------------------------------------------------------------
/riot_vue/tags/svggraph.html:
--------------------------------------------------------------------------------
1 |
2 |
25 | * input[type="range"] requires IE10 or above.
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | { label }
37 |
38 | { value }
39 | X
40 |
41 |
45 |
46 |
{ JSON.stringify(stats, null, 2) }
47 |
48 |
49 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/riot_vue/tags/todomvc.html:
--------------------------------------------------------------------------------
1 |
2 | Compare this with the ones in http://todomvc.com/ , see if you like the style and count the lines of code.
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/riot_vue/tags/treeview.html:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 | (You can double click on an item to turn it into a folder.)
17 |
23 |
24 |
54 |
55 |
56 |
57 |
58 | { name }
59 | [{open ? '-' : '+'}]
60 |
61 |
62 |
63 |
64 |
65 |
66 | +
67 |
68 |
69 |
97 |
98 |
--------------------------------------------------------------------------------
/riot_webpack/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig file (see http://EditorConfig.org)
2 |
3 | root = true
4 |
5 | # All files.
6 | [*]
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 | indent_style = space
11 | indent_size = 2
12 |
--------------------------------------------------------------------------------
/riot_webpack/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb/base",
3 | "plugins": ["riot"],
4 | "rules" : {
5 | "semi": [2, "never"],
6 | "no-param-reassign": [2, {"props": false}],
7 | "no-unused-vars": [2, {"args": "after-used", "argsIgnorePattern": "^_"}],
8 | },
9 | "globals": {
10 | "riot": true,
11 | "opts": true,
12 | },
13 | }
14 |
--------------------------------------------------------------------------------
/riot_webpack/.gitignore:
--------------------------------------------------------------------------------
1 | bundle.js.map
2 | vendor.bundle.js.map
3 |
--------------------------------------------------------------------------------
/riot_webpack/README.md:
--------------------------------------------------------------------------------
1 | ## Use webpack and ES6(babel) to build Riotjs app
2 |
3 | This tiny example shows how to write ES6 with Riotjs, and use webpack to build the bundled target js to run in the browser environment.
4 |
5 | Online demo: http://txchen.github.io/feplay/riot_webpack/
6 |
7 | Features:
8 | * Javascript in ES6
9 | * Riot tag script in ES6
10 | * Use route, view and component to structure the app
11 | * Use RiotControl to enable the flux-like app architecture
12 |
13 | ### To use Async/Await with babel
14 |
15 | Checkout [riot_webpack_async](../riot_webpack_async)
16 |
17 | ### To write ES6 in tag script
18 |
19 | The change is simple, just set the `type` to `es6` in the `script` element:
20 |
21 | ```html
22 |
23 |
24 |
25 |
28 |
29 | ```
30 |
31 | Riot's default mini-ES6 method syntax cannot work when we are using babel, so we need to change:
32 |
33 | ```js
34 | // This would not work with babel
35 | buttonHandler(e) {
36 | // code
37 | }
38 |
39 | // Change to this
40 | this.buttonHandler = e => {
41 | // code
42 | }
43 | ```
44 |
45 | ### Setup webpack to compile riot tags
46 |
47 | `riotjs-loader` is needed, install it as devDependencies, then configure in `webpack.config.js`.
48 |
49 | You don't have to import 'riot' everywhere, instead, use `webpack.ProvidePlugin` to make it available everywhere.
50 |
51 | ### Workflow
52 |
53 | During development, use webpack-dev-server.
54 |
55 | Before shipping, use `webpack -d -p`. See `package.json` and `webpack.config.js` for detailed configurations.
56 |
--------------------------------------------------------------------------------
/riot_webpack/dist/bundle.js:
--------------------------------------------------------------------------------
1 | webpackJsonp([1],[/*!**********************!*\
2 | !*** ./src/index.js ***!
3 | \**********************/
4 | function(t,o,e){(function(t){"use strict";e(8),e(2),e(9),t.mount("app")}).call(o,e(1))},,/*!***********************!*\
5 | !*** ./src/stores.js ***!
6 | \***********************/
7 | function(t,o,e){"use strict";function i(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(o,"__esModule",{value:!0});var n=e(10),s=i(n),a={blog:s["default"]};o["default"]=a},/*!**********************!*\
8 | !*** ./src/app.html ***!
9 | \**********************/
10 | function(t,o,e){(function(t){"use strict";t.tag2("app",'',"","",function(o){var e=this;this._currentView=null,this.resetData=function(){t.control.trigger(t.VE.RESET_DATA)},this.loadView=function(o,i){e._currentView&&e._currentView.unmount(!0),e._currentView=t.mount("div#mainview",o,{data:i})[0]},this.studyRoute=function(t,o){switch(t){case"categories":e.loadView("categories-view");break;case"detail":e.loadView("detail-view",o);break;case"posts":e.loadView("posts-view");break;default:e.loadView("posts-view")}},t.route(this.studyRoute),this.on("mount",function(){t.route.start(!0)})})}).call(o,e(1))},/*!*************************************!*\
11 | !*** ./src/component/postcell.html ***!
12 | \*************************************/
13 | function(t,o,e){(function(t){"use strict";t.tag2("postcell",'',"","",function(o){this.likePost=function(){t.control.trigger(t.VE.LIKE_POST,o.data.postId)}})}).call(o,e(1))},/*!***************************************!*\
14 | !*** ./src/view/categories-view.html ***!
15 | \***************************************/
16 | function(t,o,e){(function(t){"use strict";t.tag2("categories-view",'',"","",function(o){var e=this;this.mixin("controlMixin"),this._postsInCategories={},this.on("mount",function(){t.control.trigger(t.VE.LOAD_POSTS)}),this.onControl(t.SE.POSTS_CHANGED,function(t){e._postsInCategories=t.reduce(function(t,o){return t[o.category]=t[o.category]||[],t[o.category].push(o),t},{}),e.update()})})}).call(o,e(1))},/*!***********************************!*\
17 | !*** ./src/view/detail-view.html ***!
18 | \***********************************/
19 | function(t,o,e){(function(t){"use strict";function o(t){return t&&t.__esModule?t:{"default":t}}var i=e(2),n=o(i);t.tag2("detail-view",'{_post.title} {_post.content}
{_post.likes} Likes
Previous Post | Next Post ',"","",function(o){var e=this;this.mixin("controlMixin"),this.onControl(t.SE.POSTS_CHANGED,function(t){e.readData()}),this.readData=function(){e._post=n["default"].blog.getPostById(Number(o.data)),e._total=n["default"].blog._posts.length,e.update()},this.readData()})}).call(o,e(1))},/*!**********************************!*\
20 | !*** ./src/view/posts-view.html ***!
21 | \**********************************/
22 | function(t,o,e){(function(t){"use strict";t.tag2("posts-view",' ',"","",function(o){var e=this;this.mixin("controlMixin"),this._posts=[],this.on("mount",function(){t.control.trigger(t.VE.LOAD_POSTS)}),this.onControl(t.SE.POSTS_CHANGED,function(t){e._posts=t,e.update()})})}).call(o,e(1))},/*!****************************!*\
23 | !*** ./src/RiotControl.js ***!
24 | \****************************/
25 | function(t,o,e){(function(t){"use strict";var o=["on","one","off","trigger"],e={_stores:[],addStore:function(t){this._stores.push(t)}};o.forEach(function(t){e[t]=function(){for(var o=arguments.length,e=Array(o),i=0;o>i;i++)e[i]=arguments[i];this._stores.forEach(function(o){return o[t].apply(null,e)})}}),t.control=e,t.SE={POSTS_CHANGED:"se_posts_changed"},t.VE={RESET_DATA:"ve_reset_data",LIKE_POST:"ve_like_post",LOAD_POSTS:"ve_load_posts"},t.mixin("controlMixin",{onControl:function(o,e){t.control.on(o,e),this.on("unmount",function(){return t.control.off(o,e)})}})}).call(o,e(1))},/*!*************************!*\
26 | !*** ./src/riotTags.js ***!
27 | \*************************/
28 | function(t,o,e){"use strict";e(4),e(7),e(5),e(6),e(3)},/*!********************************!*\
29 | !*** ./src/store/blogstore.js ***!
30 | \********************************/
31 | function(t,o,e){(function(t){"use strict";function e(t,o){if(!(t instanceof o))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(o,"__esModule",{value:!0});var i="riot-webpack-demo",n=function(){function o(){e(this,o),t.observable(this);var n=window.localStorage.getItem(i);n?this._posts=n&&JSON.parse(n)||[]:this.initData()}return o.prototype.getPostById=function(t){return this._posts.filter(function(o){return o.postId===t})[0]},o.prototype.initData=function(){var t=[{postId:1,title:"Best xbox games",content:"Halo, GOW",category:"collection",likes:10},{postId:2,title:"Best ps games",content:"Uncharted, The Last of US",category:"collection",likes:20},{postId:3,title:"Best wii games",content:"Zelda, Mario",category:"collection",likes:16},{postId:4,title:"Review of Halo",content:"yes, cortana",category:"review",likes:11},{postId:5,title:"Review of Titanfall",content:"where is the local game?",category:"review",likes:7},{postId:6,title:"Review of portal",content:"I don't blame you",category:"review",likes:40}];this._posts=t,this.saveToStorage()},o.prototype.saveToStorage=function(){window.localStorage.setItem(i,JSON.stringify(this._posts))},o}(),s=new n;s.on(t.VE.LOAD_POSTS,function(){s.trigger(t.SE.POSTS_CHANGED,s._posts)}),s.on(t.VE.RESET_DATA,function(){s.initData(),s.trigger(t.SE.POSTS_CHANGED,s._posts)}),s.on(t.VE.LIKE_POST,function(o){s._posts.forEach(function(t){t.postId===o&&(t.likes=t.likes+1)}),s.saveToStorage(),s.trigger(t.SE.POSTS_CHANGED,s._posts)}),t.control.addStore(s),o["default"]=s}).call(o,e(1))}]);
32 | //# sourceMappingURL=bundle.js.map
--------------------------------------------------------------------------------
/riot_webpack/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Riotjs webpack demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/riot_webpack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "webpack-dev-server",
5 | "dist": "webpack -p -d",
6 | "viewdist": "light-server -s . -p 7000",
7 | "lint": "eslint --ext .js,.es6,.html src/*"
8 | },
9 | "devDependencies": {
10 | "babel-core": "^6.7.2",
11 | "babel-eslint": "^5.0.0",
12 | "babel-loader": "^6.2.4",
13 | "babel-preset-es2015-riot": "^1.0.3",
14 | "css-loader": "^0.23.1",
15 | "eslint": "^2.2.0",
16 | "eslint-config-airbnb": "^6.0.2",
17 | "eslint-plugin-riot": "^0.1.4",
18 | "light-server": "^1.1.5",
19 | "riot": "^2.3.16",
20 | "riotjs-loader": "^3.0.0",
21 | "style-loader": "^0.13.0",
22 | "webpack": "^1.12.1",
23 | "webpack-dev-server": "^1.10.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/riot_webpack/src/RiotControl.js:
--------------------------------------------------------------------------------
1 | /* global riot */
2 | const _RiotControlApi = ['on', 'one', 'off', 'trigger']
3 | const RiotControl = {
4 | _stores: [],
5 | addStore(store) {
6 | this._stores.push(store)
7 | },
8 | }
9 | _RiotControlApi.forEach(api => {
10 | RiotControl[api] = function apiHandler(...args) {
11 | this._stores.forEach(el => el[api].apply(null, args))
12 | }
13 | })
14 |
15 | // since riot is auto loaded by ProvidePlugin, merge the control into the riot object
16 | riot.control = RiotControl
17 | // store events
18 | riot.SE = {
19 | POSTS_CHANGED: 'se_posts_changed',
20 | }
21 | // view events
22 | riot.VE = {
23 | RESET_DATA: 've_reset_data',
24 | LIKE_POST: 've_like_post',
25 | LOAD_POSTS: 've_load_posts',
26 | }
27 |
28 | // register global tag mixin for using RiotControl
29 | riot.mixin('controlMixin', {
30 | onControl(signal, func) {
31 | riot.control.on(signal, func)
32 | this.on('unmount', () => riot.control.off(signal, func))
33 | },
34 | })
35 |
--------------------------------------------------------------------------------
/riot_webpack/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
57 |
58 |
--------------------------------------------------------------------------------
/riot_webpack/src/component/postcell.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Id: {opts.data.postId}
4 |
Title: {opts.data.title}
5 |
{opts.data.likes} Likes
6 |
Like
7 |
8 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/riot_webpack/src/css/tacit.min.css:
--------------------------------------------------------------------------------
1 | th{font-weight:600}td,th{border-bottom:1.08px solid #ccc;padding:14.85px 18px}thead th{border-bottom-width:2.16px;padding-bottom:6.3px}table{display:block;max-width:100%;overflow-x:auto}input,textarea,select,button{display:block;padding:9.9px}label{display:block;margin-bottom:14.76px}input[type="submit"],input[type="reset"],button{background:#b3b3b3;border-radius:3.6px;color:#fff;cursor:pointer;display:inline;margin-bottom:18px;margin-right:7.2px;padding:6.525px 23.4px;text-align:center}input[type="submit"]:hover,input[type="reset"]:hover,button:hover{background:#a6a6a6;color:#bfbfbf}input[type="submit"],button[type="submit"]{background:#367ac3;color:#fff}input[type="submit"]:hover,button[type="submit"]:hover{background:#255587;color:#bfbfbf}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="phone"],input[type="tel"],input[type="number"],input[type="datetime"],input[type="date"],input[type="month"],input[type="color"],input[type="time"],input[type="search"],input[type="range"],input[type="file"],input[type="datetime-local"],select,textarea{border:1px solid #ccc;margin-bottom:18px;padding:5.4px 6.3px}input[type="checkbox"]{float:left;line-height:36px;margin-right:9px;margin-top:8.1px}pre,code,kbd,samp,var,output{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:16.2px}pre{border-left:1.8px solid #96bbe2;line-height:25.2px;margin-top:29.7px;overflow:auto;padding-left:18px}pre code{background:none;border:0;line-height:29.7px;padding:0}code{background:#ededed;border:1.8px solid #ccc;border-radius:3.6px;display:inline-block;line-height:18px;padding:3px 6px 2px}h1,h2,h3,h4,h5,h6{color:#000}h1{font-size:36px;font-weight:500;margin-bottom:18px;margin-top:36px}h2{font-size:25.2px;font-weight:400;margin-bottom:18px;margin-top:27px}h3{font-size:18px;margin-bottom:18px;margin-top:21.6px}h4,h5,h6{font-size:36px;margin-bottom:18px;margin-top:36px}a{color:#367ac3;text-decoration:none}a:hover{text-decoration:underline}hr{border-bottom:1px solid #ccc}small{font-size:15.3px}em,i{font-style:italic}strong,b{font-weight:500}*{border:0;border-collapse:separate;border-spacing:0;box-sizing:border-box;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:18px;font-stretch:normal;font-style:normal;font-weight:300;line-height:29.7px;margin:0;outline:0;padding:0;text-align:left;vertical-align:baseline}body{background:#f5f5f5;color:#1a1a1a;padding:36px}p,ul,ol,dl,blockquote,hr,pre,table,form,fieldset,figure,address{margin-bottom:29.7px}section{margin-left:auto;margin-right:auto;max-width:100%;width:900px}article{background:#fff;border:1.8px solid #d9d9d9;border-radius:7.2px;padding:43.2px}header{margin-bottom:36px}footer{margin-top:36px}nav{text-align:center}nav ul{list-style:none;text-align:center}nav ul li{display:inline;margin-left:9px;margin-right:9px}@media (max-width: 767px){body{padding:18px}article{border-radius:0;margin:-18px;padding:18px}textarea,input,select{max-width:100%}fieldset{min-width:0}@-moz-document url-prefix(){fieldset{display:table-cell}}section{width:auto}}
2 | /*# sourceMappingURL=tacit-0.3.5.min.css.map */
3 |
--------------------------------------------------------------------------------
/riot_webpack/src/index.js:
--------------------------------------------------------------------------------
1 | import './RiotControl.js'
2 | import './stores.js'
3 | import './riotTags.js'
4 |
5 | riot.mount('app')
6 |
--------------------------------------------------------------------------------
/riot_webpack/src/riotTags.js:
--------------------------------------------------------------------------------
1 | import './component/postcell.html'
2 |
3 | import './view/posts-view.html'
4 | import './view/categories-view.html'
5 | import './view/detail-view.html'
6 |
7 | import './app.html'
8 |
--------------------------------------------------------------------------------
/riot_webpack/src/store/blogstore.js:
--------------------------------------------------------------------------------
1 | const LOCALSTORAGE_KEY = 'riot-webpack-demo'
2 |
3 | class BlogStore {
4 | constructor() {
5 | riot.observable(this)
6 |
7 | const json = window.localStorage.getItem(LOCALSTORAGE_KEY)
8 | if (!json) {
9 | this.initData()
10 | } else {
11 | this._posts = (json && JSON.parse(json)) || []
12 | }
13 | }
14 |
15 | getPostById(id) {
16 | return this._posts.filter(post => post.postId === id)[0]
17 | }
18 |
19 | initData() {
20 | const defaultPosts = [
21 | { postId: 1, title: 'Best xbox games', content: 'Halo, GOW',
22 | category: 'collection', likes: 10 },
23 | { postId: 2, title: 'Best ps games', content: 'Uncharted, The Last of US',
24 | category: 'collection', likes: 20 },
25 | { postId: 3, title: 'Best wii games', content: 'Zelda, Mario',
26 | category: 'collection', likes: 16 },
27 | { postId: 4, title: 'Review of Halo', content: 'yes, cortana',
28 | category: 'review', likes: 11 },
29 | { postId: 5, title: 'Review of Titanfall', content: 'where is the local game?',
30 | category: 'review', likes: 7 },
31 | { postId: 6, title: 'Review of portal', content: 'I don\'t blame you',
32 | category: 'review', likes: 40 },
33 | ]
34 | this._posts = defaultPosts
35 | this.saveToStorage()
36 | }
37 |
38 | saveToStorage() {
39 | window.localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(this._posts))
40 | }
41 | }
42 |
43 | const instance = new BlogStore()
44 |
45 | instance.on(riot.VE.LOAD_POSTS, () => {
46 | instance.trigger(riot.SE.POSTS_CHANGED, instance._posts)
47 | })
48 |
49 | instance.on(riot.VE.RESET_DATA, () => {
50 | instance.initData()
51 | instance.trigger(riot.SE.POSTS_CHANGED, instance._posts)
52 | })
53 |
54 | instance.on(riot.VE.LIKE_POST, id => {
55 | instance._posts.forEach(post => {
56 | if (post.postId === id) {
57 | post.likes = post.likes + 1
58 | }
59 | })
60 | instance.saveToStorage()
61 | instance.trigger(riot.SE.POSTS_CHANGED, instance._posts)
62 | })
63 |
64 | // register to riot control by myself
65 | riot.control.addStore(instance)
66 | export default instance
67 |
--------------------------------------------------------------------------------
/riot_webpack/src/stores.js:
--------------------------------------------------------------------------------
1 | import blog from './store/blogstore'
2 |
3 | const stores = { blog }
4 |
5 | export default stores
6 |
--------------------------------------------------------------------------------
/riot_webpack/src/vendor.js:
--------------------------------------------------------------------------------
1 | import './css/tacit.min.css'
2 | import 'riot'
3 |
--------------------------------------------------------------------------------
/riot_webpack/src/view/categories-view.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{category}
4 |
5 |
6 |
7 |
8 |
25 |
26 |
--------------------------------------------------------------------------------
/riot_webpack/src/view/detail-view.html:
--------------------------------------------------------------------------------
1 | import stores from '../stores'
2 |
3 | {_post.title}
4 | {_post.content}
5 | {_post.likes} Likes
6 | 1 } href="#detail/{ opts.data - 1 }">Previous Post |
7 | Next Post
8 |
9 |
24 |
25 |
--------------------------------------------------------------------------------
/riot_webpack/src/view/posts-view.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/riot_webpack/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 |
3 | module.exports = {
4 | cache: true,
5 | entry: {
6 | app: './src/index.js',
7 | vendor: './src/vendor.js',
8 | },
9 | output: {
10 | path: './dist/',
11 | publicPath: '/dist/',
12 | filename: 'bundle.js',
13 | },
14 | module: {
15 | preLoaders: [
16 | { test: /\.html$/, include: /src/, loader: 'riotjs', query: { type: 'none' } },
17 | ],
18 | loaders: [
19 | { test: /\.css$/, include: /src/, loader: 'style!css' },
20 | { test: /\.js$|\.html$/, include: /src/, loader: 'babel', query: { presets: 'es2015-riot' } },
21 | ],
22 | },
23 | babel: {
24 | presets: ['es2015'],
25 | },
26 | plugins: [
27 | new webpack.ProvidePlugin({
28 | riot: 'riot',
29 | }),
30 | new webpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.bundle.js'),
31 | ],
32 | devServer: {
33 | port: 5555,
34 | },
35 | devtool: 'source-map',
36 | }
37 |
--------------------------------------------------------------------------------
/riot_webpack_async/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015-riot", "stage-0"]
3 | }
4 |
--------------------------------------------------------------------------------
/riot_webpack_async/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig file (see http://EditorConfig.org)
2 |
3 | root = true
4 |
5 | # All files.
6 | [*]
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 | indent_style = space
11 | indent_size = 2
12 |
--------------------------------------------------------------------------------
/riot_webpack_async/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb/base",
3 | "parser": "babel-eslint",
4 | "plugins": ["riot"],
5 | "rules" : {
6 | "semi": [2, "never"],
7 | "no-underscore-dangle": 0,
8 | "no-unused-vars": [2, {"args": "after-used", "argsIgnorePattern": "^_"}],
9 | "no-param-reassign": [2, {"props": false}],
10 | },
11 | "globals": {
12 | "riot": true,
13 | "opts": true,
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/riot_webpack_async/.gitignore:
--------------------------------------------------------------------------------
1 | bundle.js.map
2 | vendor.bundle.js.map
3 |
--------------------------------------------------------------------------------
/riot_webpack_async/README.md:
--------------------------------------------------------------------------------
1 | ## Use webpack and ES7 to build Riotjs app
2 |
3 | This tiny example shows how to write ES7(ES6 + async) with Riotjs, and use webpack to build the bundled target js to run in the browser environment.
4 |
5 | Online demo: http://txchen.github.io/feplay/riot_webpack_async/
6 |
7 | Features:
8 | * Javascript and riot tag script in ES7, including async/await
9 | * Use route, view and component to structure the app
10 | * Use RiotControl to enable the flux-like app architecture
11 |
12 | ### To use async/await
13 |
14 | * In detail page, double click the like number. It will count the word and mimic some delay.
15 | * By including babel-polyfill, the js bundle size will increase about 85kb.
16 |
17 | ### To write ES6 in tag script
18 |
19 | Riot's default mini-ES6 method syntax cannot work when we are using babel, so we need to change:
20 |
21 | ```js
22 | // This would not work with babel
23 | buttonHandler(e) {
24 | // code
25 | }
26 |
27 | // Change to this
28 | this.buttonHandler = e => {
29 | // code
30 | }
31 | ```
32 |
33 | ### Setup webpack to compile riot tags
34 |
35 | `tag-loader` is needed, install it as devDependencies, then configure in `webpack.config.js`.
36 |
37 | You don't have to import 'riot' everywhere, instead, use `webpack.ProvidePlugin` to make it available everywhere.
38 |
39 | ### Workflow
40 |
41 | During development, use webpack-dev-server.
42 |
43 | Before shipping, use `webpack -d -p`. See `package.json` and `webpack.config.js` for detailed configurations.
44 |
--------------------------------------------------------------------------------
/riot_webpack_async/dist/bundle.js:
--------------------------------------------------------------------------------
1 | webpackJsonp([1],{0:/*!**********************!*\
2 | !*** ./src/index.js ***!
3 | \**********************/
4 | function(t,e,o){(function(t){"use strict";o(/*! ./RiotControl.js */116),o(/*! ./stores.js */87),o(/*! ./riotTags.js */117),t.mount("app")}).call(e,o(/*! riot */29))},87:/*!***********************!*\
5 | !*** ./src/stores.js ***!
6 | \***********************/
7 | function(t,e,o){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(e,"__esModule",{value:!0});var i=o(/*! ./store/blogstore */118),s=n(i),a={blog:s["default"]};e["default"]=a},116:/*!****************************!*\
8 | !*** ./src/RiotControl.js ***!
9 | \****************************/
10 | function(t,e,o){(function(t){"use strict";var e=["on","one","off","trigger"],o={_stores:[],addStore:function(t){this._stores.push(t)}};e.forEach(function(t){o[t]=function(){for(var e=arguments.length,o=Array(e),n=0;n
',"","",function(t){"use strict";var e=this;this._currentView=null,this.resetData=function(){n.control.trigger(n.VE.RESET_DATA)},this.loadView=function(t,o){e._currentView&&e._currentView.unmount(!0),console.log(t),e._currentView=n.mount("div#mainview",t,{data:o})[0]},this.studyRoute=function(t,o){switch(t){case"categories":e.loadView("categories-view");break;case"detail":e.loadView("detail-view",o);break;case"posts":e.loadView("posts-view");break;default:e.loadView("posts-view")}},n.route(this.studyRoute),this.on("mount",function(){n.route.start(!0)})})},308:/*!*************************************!*\
20 | !*** ./src/component/postcell.html ***!
21 | \*************************************/
22 | function(t,e,o){var n=o(/*! riot */29);n.tag2("postcell",'',"","",function(t){"use strict";this.likePost=function(){n.control.trigger(n.VE.LIKE_POST,t.data.postId)}})},309:/*!***************************************!*\
23 | !*** ./src/view/categories-view.html ***!
24 | \***************************************/
25 | function(t,e,o){var n=o(/*! riot */29);n.tag2("categories-view",'',"","",function(t){"use strict";var e=this;this.mixin("controlMixin"),this._postsInCategories={},this.on("mount",function(){n.control.trigger(n.VE.LOAD_POSTS)}),this.onControl(n.SE.POSTS_CHANGED,function(t){e._postsInCategories=t.reduce(function(t,e){return t[e.category]=t[e.category]||[],t[e.category].push(e),t},{}),e.update()})})},310:/*!***********************************!*\
26 | !*** ./src/view/detail-view.html ***!
27 | \***********************************/
28 | function(t,e,o){var n=o(/*! riot */29);n.tag2("detail-view",'{_post.title} {_post.content}
{_post.likes} Likes
{_wordsCount} words
Previous Post | Next Post ',"","",function(t){"use strict";function e(t){return t&&t.__esModule?t:{"default":t}}function i(t){return function(){var e=t.apply(this,arguments);return new Promise(function(t,o){function n(i,s){try{var a=e[i](s),r=a.value}catch(c){return void o(c)}return a.done?void t(r):Promise.resolve(r).then(function(t){return n("next",t)},function(t){return n("throw",t)})}return n("next")})}}var s=this,a=o(/*! ../stores */87),r=e(a);this.mixin("controlMixin"),this.onControl(n.SE.POSTS_CHANGED,function(t){s.readData()}),this.readData=function(){s._post=r["default"].blog.getPostById(Number(t.data)),s._total=r["default"].blog._posts.length,s.update()},this.sleep=function(){var t=arguments.length<=0||void 0===arguments[0]?0:arguments[0];return new Promise(function(e){return setTimeout(e,t)})},this.countWord=i(regeneratorRuntime.mark(function c(){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,s.sleep(500);case 2:return s._wordsCount=s._post.content.split(" ").length,t.next=5,s.sleep(500);case 5:s.update();case 6:case"end":return t.stop()}},c,s)})),this.readData()})},311:/*!**********************************!*\
29 | !*** ./src/view/posts-view.html ***!
30 | \**********************************/
31 | function(t,e,o){var n=o(/*! riot */29);n.tag2("posts-view",' ',"","",function(t){"use strict";var e=this;this.mixin("controlMixin"),this._posts=[],this.on("mount",function(){n.control.trigger(n.VE.LOAD_POSTS)}),this.onControl(n.SE.POSTS_CHANGED,function(t){e._posts=t,e.update()})})}});
32 | //# sourceMappingURL=bundle.js.map
--------------------------------------------------------------------------------
/riot_webpack_async/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Riotjs webpack demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/riot_webpack_async/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "webpack-dev-server",
5 | "dist": "webpack -p -d",
6 | "viewdist": "light-server -s . -p 7001",
7 | "lint": "eslint --ext .js,.html src/*"
8 | },
9 | "devDependencies": {
10 | "babel-core": "^6.11.4",
11 | "babel-eslint": "^6.1.2",
12 | "babel-loader": "^6.2.4",
13 | "babel-polyfill": "^6.9.1",
14 | "babel-preset-es2015-riot": "^1.1.0",
15 | "babel-preset-stage-0": "^6.5.0",
16 | "css-loader": "^0.23.1",
17 | "eslint": "^3.1.1",
18 | "eslint-config-airbnb": "^9.0.1",
19 | "eslint-plugin-import": "^1.12.0",
20 | "eslint-plugin-riot": "^0.1.4",
21 | "light-server": "^1.1.5",
22 | "riot": "^2.5.0",
23 | "style-loader": "^0.13.0",
24 | "tag-loader": "^0.3.0",
25 | "webpack": "^1.12.14",
26 | "webpack-dev-server": "^1.14.1"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/RiotControl.js:
--------------------------------------------------------------------------------
1 | const _RiotControlApi = ['on', 'one', 'off', 'trigger']
2 | const RiotControl = {
3 | _stores: [],
4 | addStore(store) {
5 | this._stores.push(store)
6 | },
7 | }
8 | _RiotControlApi.forEach(api => {
9 | RiotControl[api] = function apiHandler(...args) {
10 | this._stores.forEach(el => el[api].apply(null, args))
11 | }
12 | })
13 |
14 | // since riot is auto loaded by ProvidePlugin, merge the control into the riot object
15 | riot.control = RiotControl
16 | // store events
17 | riot.SE = {
18 | POSTS_CHANGED: 'se_posts_changed',
19 | }
20 | // view events
21 | riot.VE = {
22 | RESET_DATA: 've_reset_data',
23 | LIKE_POST: 've_like_post',
24 | LOAD_POSTS: 've_load_posts',
25 | }
26 |
27 | // register global tag mixin for using RiotControl
28 | riot.mixin('controlMixin', {
29 | onControl(signal, func) {
30 | riot.control.on(signal, func)
31 | this.on('unmount', () => riot.control.off(signal, func))
32 | },
33 | })
34 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
59 |
60 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/component/postcell.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Id: {opts.data.postId}
4 |
Title: {opts.data.title}
5 |
{opts.data.likes} Likes
6 |
Like
7 |
8 |
9 |
14 |
15 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/css/tacit.min.css:
--------------------------------------------------------------------------------
1 | th{font-weight:600}td,th{border-bottom:1.08px solid #ccc;padding:14.85px 18px}thead th{border-bottom-width:2.16px;padding-bottom:6.3px}table{display:block;max-width:100%;overflow-x:auto}input,textarea,select,button{display:block;padding:9.9px}label{display:block;margin-bottom:14.76px}input[type="submit"],input[type="reset"],button{background:#b3b3b3;border-radius:3.6px;color:#fff;cursor:pointer;display:inline;margin-bottom:18px;margin-right:7.2px;padding:6.525px 23.4px;text-align:center}input[type="submit"]:hover,input[type="reset"]:hover,button:hover{background:#a6a6a6;color:#bfbfbf}input[type="submit"],button[type="submit"]{background:#367ac3;color:#fff}input[type="submit"]:hover,button[type="submit"]:hover{background:#255587;color:#bfbfbf}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="phone"],input[type="tel"],input[type="number"],input[type="datetime"],input[type="date"],input[type="month"],input[type="color"],input[type="time"],input[type="search"],input[type="range"],input[type="file"],input[type="datetime-local"],select,textarea{border:1px solid #ccc;margin-bottom:18px;padding:5.4px 6.3px}input[type="checkbox"]{float:left;line-height:36px;margin-right:9px;margin-top:8.1px}pre,code,kbd,samp,var,output{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:16.2px}pre{border-left:1.8px solid #96bbe2;line-height:25.2px;margin-top:29.7px;overflow:auto;padding-left:18px}pre code{background:none;border:0;line-height:29.7px;padding:0}code{background:#ededed;border:1.8px solid #ccc;border-radius:3.6px;display:inline-block;line-height:18px;padding:3px 6px 2px}h1,h2,h3,h4,h5,h6{color:#000}h1{font-size:36px;font-weight:500;margin-bottom:18px;margin-top:36px}h2{font-size:25.2px;font-weight:400;margin-bottom:18px;margin-top:27px}h3{font-size:18px;margin-bottom:18px;margin-top:21.6px}h4,h5,h6{font-size:36px;margin-bottom:18px;margin-top:36px}a{color:#367ac3;text-decoration:none}a:hover{text-decoration:underline}hr{border-bottom:1px solid #ccc}small{font-size:15.3px}em,i{font-style:italic}strong,b{font-weight:500}*{border:0;border-collapse:separate;border-spacing:0;box-sizing:border-box;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:18px;font-stretch:normal;font-style:normal;font-weight:300;line-height:29.7px;margin:0;outline:0;padding:0;text-align:left;vertical-align:baseline}body{background:#f5f5f5;color:#1a1a1a;padding:36px}p,ul,ol,dl,blockquote,hr,pre,table,form,fieldset,figure,address{margin-bottom:29.7px}section{margin-left:auto;margin-right:auto;max-width:100%;width:900px}article{background:#fff;border:1.8px solid #d9d9d9;border-radius:7.2px;padding:43.2px}header{margin-bottom:36px}footer{margin-top:36px}nav{text-align:center}nav ul{list-style:none;text-align:center}nav ul li{display:inline;margin-left:9px;margin-right:9px}@media (max-width: 767px){body{padding:18px}article{border-radius:0;margin:-18px;padding:18px}textarea,input,select{max-width:100%}fieldset{min-width:0}@-moz-document url-prefix(){fieldset{display:table-cell}}section{width:auto}}
2 | /*# sourceMappingURL=tacit-0.3.5.min.css.map */
3 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/index.js:
--------------------------------------------------------------------------------
1 | import './RiotControl.js'
2 | import './stores.js'
3 | import './riotTags.js'
4 |
5 | riot.mount('app')
6 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/riotTags.js:
--------------------------------------------------------------------------------
1 | import './component/postcell.html'
2 |
3 | import './view/posts-view.html'
4 | import './view/categories-view.html'
5 | import './view/detail-view.html'
6 |
7 | import './app.html'
8 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/store/blogstore.js:
--------------------------------------------------------------------------------
1 | const LOCALSTORAGE_KEY = 'riot-webpack-demo'
2 |
3 | class BlogStore {
4 | constructor() {
5 | riot.observable(this)
6 |
7 | const json = window.localStorage.getItem(LOCALSTORAGE_KEY)
8 | if (!json) {
9 | this.initData()
10 | } else {
11 | this._posts = (json && JSON.parse(json)) || []
12 | }
13 | }
14 |
15 | getPostById(id) {
16 | return this._posts.filter(post => post.postId === id)[0]
17 | }
18 |
19 | initData() {
20 | const defaultPosts = [
21 | { postId: 1, title: 'Best xbox games', content: 'Halo, GOW',
22 | category: 'collection', likes: 10 },
23 | { postId: 2, title: 'Best ps games', content: 'Uncharted, The Last of US',
24 | category: 'collection', likes: 20 },
25 | { postId: 3, title: 'Best wii games', content: 'Zelda, Mario',
26 | category: 'collection', likes: 16 },
27 | { postId: 4, title: 'Review of Halo', content: 'yes, cortana',
28 | category: 'review', likes: 11 },
29 | { postId: 5, title: 'Review of Titanfall', content: 'where is the local game?',
30 | category: 'review', likes: 7 },
31 | { postId: 6, title: 'Review of portal', content: 'I don\'t blame you',
32 | category: 'review', likes: 40 },
33 | ]
34 | this._posts = defaultPosts
35 | this.saveToStorage()
36 | }
37 |
38 | saveToStorage() {
39 | window.localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(this._posts))
40 | }
41 | }
42 |
43 | const instance = new BlogStore()
44 |
45 | instance.on(riot.VE.LOAD_POSTS, () => {
46 | instance.trigger(riot.SE.POSTS_CHANGED, instance._posts)
47 | })
48 |
49 | instance.on(riot.VE.RESET_DATA, () => {
50 | instance.initData()
51 | instance.trigger(riot.SE.POSTS_CHANGED, instance._posts)
52 | })
53 |
54 | instance.on(riot.VE.LIKE_POST, id => {
55 | instance._posts.forEach(post => {
56 | if (post.postId === id) {
57 | post.likes = post.likes + 1
58 | }
59 | })
60 | instance.saveToStorage()
61 | instance.trigger(riot.SE.POSTS_CHANGED, instance._posts)
62 | })
63 |
64 | // register to riot control by myself
65 | riot.control.addStore(instance)
66 | export default instance
67 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/stores.js:
--------------------------------------------------------------------------------
1 | import blog from './store/blogstore'
2 |
3 | const stores = { blog }
4 |
5 | export default stores
6 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/vendor.js:
--------------------------------------------------------------------------------
1 | import './css/tacit.min.css'
2 | import 'riot'
3 | import 'babel-polyfill'
4 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/view/categories-view.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{category}
4 |
5 |
6 |
7 |
8 |
25 |
26 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/view/detail-view.html:
--------------------------------------------------------------------------------
1 |
2 | {_post.title}
3 | {_post.content}
4 | { _post.likes } Likes
5 | { _wordsCount } words
6 | 1 } href="#detail/{ opts.data - 1 }">Previous Post |
7 | Next Post
8 |
9 |
34 |
35 |
--------------------------------------------------------------------------------
/riot_webpack_async/src/view/posts-view.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/riot_webpack_async/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 |
3 | module.exports = {
4 | cache: true,
5 | entry: {
6 | app: './src/index.js',
7 | vendor: './src/vendor.js',
8 | },
9 | output: {
10 | path: './dist/',
11 | publicPath: '/dist/',
12 | filename: 'bundle.js',
13 | },
14 | module: {
15 | loaders: [
16 | { test: /\.css$/, include: /src/, loader: 'style!css' },
17 | {
18 | test: /\.js?$/,
19 | loader: 'babel-loader',
20 | include: /src/
21 | },
22 | {
23 | test: /\.html?$/,
24 | loader: 'tag-loader',
25 | include: /src/,
26 | query: {
27 | type: 'babel'
28 | }
29 | },
30 | ],
31 | },
32 | plugins: [
33 | new webpack.ProvidePlugin({
34 | riot: 'riot',
35 | }),
36 | new webpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.bundle.js'),
37 | ],
38 | devServer: {
39 | port: 5555,
40 | },
41 | devtool: 'source-map',
42 | }
43 |
--------------------------------------------------------------------------------
/s_login/.gitignore:
--------------------------------------------------------------------------------
1 | !node_modules
2 |
3 | node_modules/.bin
4 | node_modules/light-server
5 | node_modules/whatwg-fetch/*
6 | !node_modules/whatwg-fetch/fetch.js
7 | node_modules/riot/*
8 | !node_modules/riot/riot.min.js
9 | !node_modules/riot/riot+compiler.min.js
10 |
--------------------------------------------------------------------------------
/s_login/README.md:
--------------------------------------------------------------------------------
1 | ## Pure client side js calling google api
2 |
3 | This simple sample calls google api with no backend, by using client side OAuth.
4 |
5 | Online demo: http://txchen.github.io/feplay/s_login/
6 |
7 | The flow:
8 | * redirect to google auth endpoint
9 | * user login and confirm
10 | * redirect back to this page, with access token in the hash
11 | * parse the hash, verify the access token, and get the email from the verify response
12 | * save the access token and user email in local storage
13 | * get the access token and user email from local storage, call google tasks api
14 | * show the tasks
15 |
--------------------------------------------------------------------------------
/s_login/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Static page Google login example
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/s_login/js/app.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello: { _userName } Logout
6 | Login
7 |
8 |
9 | {listName}
10 |
13 |
14 |
15 | {_errorMessage}
16 |
17 |
18 |
19 |
125 |
126 |
--------------------------------------------------------------------------------
/s_login/node_modules/riot/riot.min.js:
--------------------------------------------------------------------------------
1 | /* Riot v2.2.4, @license MIT, (c) 2015 Muut Inc. + contributors */
2 | (function(e,t){"use strict";var n={version:"v2.2.4",settings:{}},i=0,r="riot-",o=r+"tag",u="string",f="object",a="undefined",s="function",c=/^(?:opt(ion|group)|tbody|col|t[rhd])$/,l=["_item","_id","update","root","mount","unmount","mixin","isMounted","isLoop","tags","parent","opts","trigger","on","off","one"],p=(e&&e.document||{}).documentMode|0,d=Array.isArray;n.observable=function(e){e=e||{};var t={},n=0;e.on=function(i,r){if(M(r)){if(typeof r.id===a)r._id=n++;i.replace(/\S+/g,function(e,n){(t[e]=t[e]||[]).push(r);r.typed=n>0})}return e};e.off=function(n,i){if(n=="*")t={};else{n.replace(/\S+/g,function(e){if(i){var n=t[e];for(var r=0,o;o=n&&n[r];++r){if(o._id==i._id)n.splice(r--,1)}}else{t[e]=[]}})}return e};e.one=function(t,n){function i(){e.off(t,i);n.apply(e,arguments)}return e.on(t,i)};e.trigger=function(n){var i=[].slice.call(arguments,1),r=t[n]||[];for(var o=0,u;u=r[o];++o){if(!u.busy){u.busy=1;u.apply(e,u.typed?[n].concat(i):i);if(r[o]!==u){o--}u.busy=0}}if(t.all&&n!="all"){e.trigger.apply(e,["all",n].concat(i))}return e};return e};n.mixin=function(){var e={};return function(t,n){if(!n)return e[t];e[t]=n}}();(function(e,t,n){if(!n)return;var i=n.location,r=e.observable(),o=false,u;function f(){return i.href.split("#")[1]||""}function a(e){return e.split("/")}function s(e){if(e.type)e=f();if(e!=u){r.trigger.apply(null,["H"].concat(a(e)));u=e}}var c=e.route=function(e){if(e[0]){i.hash=e;s(e)}else{r.on("H",e)}};c.exec=function(e){e.apply(null,a(f()))};c.parser=function(e){a=e};c.stop=function(){if(o){if(n.removeEventListener)n.removeEventListener(t,s,false);else n.detachEvent("on"+t,s);r.off("*");o=false}};c.start=function(){if(!o){if(n.addEventListener)n.addEventListener(t,s,false);else n.attachEvent("on"+t,s);o=true}};c.start()})(n,"hashchange",e);var g=function(e){var t,i,r,o=/[{}]/g;return function(u){var f=n.settings.brackets||e;if(t!==f){t=f;r=f.split(" ");i=r.map(function(e){return e.replace(/(?=.)/g,"\\")})}return u instanceof RegExp?f===e?u:new RegExp(u.source.replace(o,function(e){return i[~~(e==="}")]}),u.global?"g":""):r[u]}}("{ }");var m=function(){var t={},n='"in d?d:'+(e?"window).":"global)."),i=/(['"\/])(?:[^\\]*?|\\.|.)*?\1|\.\w*|\w*:|\b(?:(?:new|typeof|in|instanceof) |(?:this|true|false|null|undefined)\b|function\s*\()|([A-Za-z_$]\w*)/g;return function(e,n){return e&&(t[e]||(t[e]=r(e)))(n)};function r(e,t){if(e.indexOf(g(0))<0){e=e.replace(/\n|\r\n?/g,"\n");return function(){return e}}e=e.replace(g(/\\{/g),"").replace(g(/\\}/g),"");t=f(e,a(e,g(/{/),g(/}/)));e=t.length===2&&!t[0]?o(t[1]):"["+t.map(function(e,t){return t%2?o(e,true):'"'+e.replace(/\n|\r\n?/g,"\\n").replace(/"/g,'\\"')+'"'}).join(",")+'].join("")';return new Function("d","return "+e.replace(/\uFFF0/g,g(0)).replace(/\uFFF1/g,g(1))+";")}function o(e,t){e=e.replace(/\n|\r\n?/g," ").replace(g(/^[{ ]+|[ }]+$|\/\*.+?\*\//g),"");return/^\s*[\w- "']+ *:/.test(e)?"["+a(e,/["' ]*[\w- ]+["' ]*:/,/,(?=["' ]*[\w- ]+["' ]*:)|}|$/).map(function(e){return e.replace(/^[ "']*(.+?)[ "']*: *(.+?),? *$/,function(e,t,n){return n.replace(/[^&|=!><]+/g,u)+'?"'+t+'":"",'})}).join("")+'].join(" ").trim()':u(e,t)}function u(e,t){e=e.trim();return!e?"":"(function(v){try{v="+e.replace(i,function(e,t,i){return i?'(("'+i+n+i+")":e})+"}catch(e){}return "+(t===true?'!v&&v!==0?"":v':"v")+"}).call(d)"}function f(e,t){var n=[];t.map(function(t,i){i=e.indexOf(t);n.push(e.slice(0,i),t);e=e.slice(i+t.length)});if(e)n.push(e);return n}function a(e,t,n){var i,r=0,o=[],u=new RegExp("("+t.source+")|("+n.source+")","g");e.replace(u,function(t,n,u,f){if(!r&&n)i=f;r+=n?1:-1;if(!r&&u!=null)o.push(e.slice(i,f+u.length))});return o}}();var v=function(e){var t={tr:"tbody",th:"tr",td:"tr",tbody:"table",col:"colgroup"},n="div";e=e&&e<10;function i(i){var o=i&&i.match(/^\s*<([-\w]+)/),u=o&&o[1].toLowerCase(),f=t[u]||n,a=R(f);a.stub=true;if(e&&u&&(o=u.match(c)))r(a,i,u,!!o[1]);else a.innerHTML=i;return a}function r(e,t,i,r){var o=R(n),u=r?"select>":"table>",f;o.innerHTML="<"+u+t+""+u;f=o.getElementsByTagName(i)[0];if(f)e.appendChild(f)}return i}(p);function h(e){var t=g(0),n=e.trim().slice(t.length).match(/^\s*(\S+?)\s*(?:,\s*(\S+))?\s+in\s+(.+)$/);return n?{key:n[1],pos:n[2],val:t+n[3]}:{val:e}}function y(e,t,n){var i={};i[e.key]=t;if(e.pos)i[e.pos]=n;return i}function b(e,t,n){A(e,"each");var i=S(e),r=e.outerHTML,o=!!U[i],u=U[i]||{tmpl:r},f=e.parentNode,a=document.createComment("riot placeholder"),s=[],l=O(e),p;f.insertBefore(a,e);n=h(n);t.one("premount",function(){if(f.stub)f=t.root;e.parentNode.removeChild(e)}).on("update",function(){var r=m(n.val,t);if(!d(r)){p=r?JSON.stringify(r):"";r=!r?[]:Object.keys(r).map(function(e){return y(n,e,r[e])})}var g=document.createDocumentFragment(),v=s.length,h=r.length;while(v>h){s[--v].unmount();s.splice(v,1)}for(v=0;v=0){var r={dom:e,expr:t};n.push(k(r,i))}}F(e,function(e){var n=e.nodeType;if(n==3&&e.parentNode.tagName!="STYLE")i(e,e.nodeValue);if(n!=1)return;var r=e.getAttribute("each");if(r){b(e,t,r);return false}C(e.attributes,function(t){var n=t.name,r=n.split("__")[1];i(e,t.value,{attr:r||n,bool:r});if(r){A(e,n);return false}});if(O(e))return false})}function _(e,r,o){var s=n.observable(this),c=q(r.opts)||{},p=v(e.tmpl),h=r.parent,y=r.isLoop,b=r.hasImpl,_=j(r.item),N=[],x=[],A=r.root,O=e.fn,E=A.tagName.toLowerCase(),S={},F=[];if(O&&A._tag){A._tag.unmount(true)}this.isMounted=false;A.isLoop=y;A._tag=this;this._id=i++;k(this,{parent:h,root:A,opts:c,tags:{}},_);C(A.attributes,function(e){var t=e.value;if(g(/{.*}/).test(t))S[e.name]=t});if(p.innerHTML&&!/^(select|optgroup|table|tbody|tr|col(?:group)?)$/.test(E))p.innerHTML=D(p.innerHTML,o);function R(){var e=b&&y?s:h||s;C(A.attributes,function(t){c[t.name]=m(t.value,e)});C(Object.keys(S),function(t){c[t]=m(S[t],e)})}function I(e){for(var t in _){if(typeof s[t]!==a)s[t]=e[t]}}function V(){if(!s.parent||!y)return;C(Object.keys(s.parent),function(e){var t=!~l.indexOf(e)&&~F.indexOf(e);if(typeof s[e]===a||t){if(!t)F.push(e);s[e]=s.parent[e]}})}this.update=function(e){e=j(e);V();if(e&&typeof _===f){I(e);_=e}k(s,e);R();s.trigger("update",e);T(N,s);s.trigger("updated")};this.mixin=function(){C(arguments,function(e){e=typeof e===u?n.mixin(e):e;C(Object.keys(e),function(t){if(t!="init")s[t]=M(e[t])?e[t].bind(s):e[t]});if(e.init)e.init.bind(s)()})};this.mount=function(){R();if(O)O.call(s,c);L(p,s,N);z(true);if(e.attrs||b){$(e.attrs,function(e,t){A.setAttribute(e,t)});L(s.root,s,N)}if(!s.parent||y)s.update(_);s.trigger("premount");if(y&&!b){s.root=A=p.firstChild}else{while(p.firstChild)A.appendChild(p.firstChild);if(A.stub)s.root=A=h.root}if(!s.parent||s.parent.isMounted){s.isMounted=true;s.trigger("mount")}else s.parent.one("mount",function(){if(!B(s.root)){s.parent.isMounted=s.isMounted=true;s.trigger("mount")}})};this.unmount=function(e){var n=A,i=n.parentNode,r;if(i){if(h){r=H(h);if(d(r.tags[E]))C(r.tags[E],function(e,t){if(e._id==s._id)r.tags[E].splice(t,1)});else r.tags[E]=t}else while(n.firstChild)n.removeChild(n.firstChild);if(!e)i.removeChild(n);else i.removeAttribute("riot-tag")}s.trigger("unmount");z();s.off("*");A._tag=null};function z(e){C(x,function(t){t[e?"mount":"unmount"]()});if(h){var t=e?"on":"off";if(y)h[t]("unmount",s.unmount);else h[t]("update",s.update)[t]("unmount",s.unmount)}}w(p,this,x)}function N(t,n,i,r){i[t]=function(t){var o=r._item,u=r.parent,f;if(!o)while(u&&!o){o=u._item;u=u.parent}t=t||e.event;try{t.currentTarget=i;if(!t.target)t.target=t.srcElement;if(!t.which)t.which=t.charCode||t.keyCode}catch(a){}t.item=o;if(n.call(r,t)!==true&&!/radio|check/.test(i.type)){if(t.preventDefault)t.preventDefault();t.returnValue=false}if(!t.preventUpdate){f=o?H(u):r;f.update()}}}function x(e,t,n){if(e){e.insertBefore(n,t);e.removeChild(t)}}function T(e,t){C(e,function(e,n){var i=e.dom,u=e.attr,a=m(e.expr,t),s=e.dom.parentNode;if(e.bool)a=a?u:false;else if(a==null)a="";if(s&&s.tagName=="TEXTAREA")a=(""+a).replace(/riot-/g,"");if(e.value===a)return;e.value=a;if(!u){i.nodeValue=""+a;return}A(i,u);if(M(a)){N(u,a,i,t)}else if(u=="if"){var c=e.stub,l=function(){x(c.parentNode,c,i)},p=function(){x(i.parentNode,i,c)};if(a){if(c){l();i.inStub=false;if(!B(i)){F(i,function(e){if(e._tag&&!e._tag.isMounted)e._tag.isMounted=!!e._tag.trigger("mount")})}}}else{c=e.stub=c||document.createTextNode("");if(i.parentNode)p();else(t.parent||t).one("updated",p);i.inStub=true}}else if(/^(show|hide)$/.test(u)){if(u=="hide")a=!a;i.style.display=a?"":"none"}else if(u=="value"){i.value=a}else if(J(u,r)&&u!=o){if(a)i.setAttribute(u.slice(r.length),a)}else{if(e.bool){i[u]=a;if(!a)return}if(typeof a!==f)i.setAttribute(u,a)}})}function C(e,t){for(var n=0,i=(e||[]).length,r;n(<\/\1>)?/gi,t||"")}function I(e,t){return(t||document).querySelectorAll(e)}function V(e,t){return(t||document).querySelector(e)}function q(e){function t(){}t.prototype=e;return new t}function z(e,t,n){if(e._visited)return;var i,r=e.getAttribute("id")||e.getAttribute("name");if(r){if(n.indexOf(r)<0){i=t[r];if(!i)t[r]=e;else if(d(i))i.push(e);else t[r]=[i,e]}e._visited=true}}function J(e,t){return e.slice(0,t.length)===t}var P=[],U={},W;function X(e){if(n.render)return;if(!W){W=R("style");W.setAttribute("type","text/css")}var t=document.head||document.getElementsByTagName("head")[0];if(W.styleSheet)W.styleSheet.cssText+=e;else W.innerHTML+=e;if(!W._rendered)if(W.styleSheet){document.body.appendChild(W)}else{var i=V("style[type=riot]");if(i){i.parentNode.insertBefore(W,i);i.parentNode.removeChild(i)}else t.appendChild(W)}W._rendered=true}function Y(e,t,n){var i=U[t],r=e._innerHTML=e._innerHTML||e.innerHTML;e.innerHTML="";if(i&&e)i=new _(i,{root:e,opts:n},r);if(i&&i.mount){i.mount();P.push(i);return i.on("unmount",function(){P.splice(P.indexOf(i),1)})}}n.tag=function(e,t,n,i,r){if(M(i)){r=i;if(/^[\w\-]+\s?=/.test(n)){i=n;n=""}else i=""}if(n){if(M(n))r=n;else X(n)}U[e]={name:e,tmpl:t,attrs:i,fn:r};return e};n.mount=function(e,t,n){var i,r,a=[];function s(e){var t="";C(e,function(e){t+=", *["+o+'="'+e.trim()+'"]'});return t}function c(){var e=Object.keys(U);return e+s(e)}function l(e){var i;if(e.tagName){if(t&&(!(i=e.getAttribute(o))||i!=t))e.setAttribute(o,t);var r=Y(e,t||e.getAttribute(o)||e.tagName.toLowerCase(),n);if(r)a.push(r)}else if(e.length){C(e,l)}}if(typeof t===f){n=t;t=0}if(typeof e===u){if(e==="*")e=r=c();else e+=s(e.split(","));i=I(e)}else i=e;if(t==="*"){t=r||c();if(i.tagName)i=I(t,i);else{var p=[];C(i,function(e){p.push(I(t,e))});i=p}t=0}if(i.tagName)l(i);else C(i,l);return a};n.update=function(){return C(P,function(e){e.update()})};n.mountTo=n.mount;n.util={brackets:g,tmpl:m};if(typeof exports===f)module.exports=n;else if(typeof define==="function"&&define.amd)define(function(){return e.riot=n});else e.riot=n})(typeof window!="undefined"?window:void 0);
3 |
--------------------------------------------------------------------------------
/s_login/node_modules/whatwg-fetch/fetch.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | 'use strict';
3 |
4 | if (self.fetch) {
5 | return
6 | }
7 |
8 | function normalizeName(name) {
9 | if (typeof name !== 'string') {
10 | name = name.toString();
11 | }
12 | if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
13 | throw new TypeError('Invalid character in header field name')
14 | }
15 | return name.toLowerCase()
16 | }
17 |
18 | function normalizeValue(value) {
19 | if (typeof value !== 'string') {
20 | value = value.toString();
21 | }
22 | return value
23 | }
24 |
25 | function Headers(headers) {
26 | this.map = {}
27 |
28 | if (headers instanceof Headers) {
29 | headers.forEach(function(value, name) {
30 | this.append(name, value)
31 | }, this)
32 |
33 | } else if (headers) {
34 | Object.getOwnPropertyNames(headers).forEach(function(name) {
35 | this.append(name, headers[name])
36 | }, this)
37 | }
38 | }
39 |
40 | Headers.prototype.append = function(name, value) {
41 | name = normalizeName(name)
42 | value = normalizeValue(value)
43 | var list = this.map[name]
44 | if (!list) {
45 | list = []
46 | this.map[name] = list
47 | }
48 | list.push(value)
49 | }
50 |
51 | Headers.prototype['delete'] = function(name) {
52 | delete this.map[normalizeName(name)]
53 | }
54 |
55 | Headers.prototype.get = function(name) {
56 | var values = this.map[normalizeName(name)]
57 | return values ? values[0] : null
58 | }
59 |
60 | Headers.prototype.getAll = function(name) {
61 | return this.map[normalizeName(name)] || []
62 | }
63 |
64 | Headers.prototype.has = function(name) {
65 | return this.map.hasOwnProperty(normalizeName(name))
66 | }
67 |
68 | Headers.prototype.set = function(name, value) {
69 | this.map[normalizeName(name)] = [normalizeValue(value)]
70 | }
71 |
72 | Headers.prototype.forEach = function(callback, thisArg) {
73 | Object.getOwnPropertyNames(this.map).forEach(function(name) {
74 | this.map[name].forEach(function(value) {
75 | callback.call(thisArg, value, name, this)
76 | }, this)
77 | }, this)
78 | }
79 |
80 | function consumed(body) {
81 | if (body.bodyUsed) {
82 | return Promise.reject(new TypeError('Already read'))
83 | }
84 | body.bodyUsed = true
85 | }
86 |
87 | function fileReaderReady(reader) {
88 | return new Promise(function(resolve, reject) {
89 | reader.onload = function() {
90 | resolve(reader.result)
91 | }
92 | reader.onerror = function() {
93 | reject(reader.error)
94 | }
95 | })
96 | }
97 |
98 | function readBlobAsArrayBuffer(blob) {
99 | var reader = new FileReader()
100 | reader.readAsArrayBuffer(blob)
101 | return fileReaderReady(reader)
102 | }
103 |
104 | function readBlobAsText(blob) {
105 | var reader = new FileReader()
106 | reader.readAsText(blob)
107 | return fileReaderReady(reader)
108 | }
109 |
110 | var support = {
111 | blob: 'FileReader' in self && 'Blob' in self && (function() {
112 | try {
113 | new Blob();
114 | return true
115 | } catch(e) {
116 | return false
117 | }
118 | })(),
119 | formData: 'FormData' in self
120 | }
121 |
122 | function Body() {
123 | this.bodyUsed = false
124 |
125 |
126 | this._initBody = function(body) {
127 | this._bodyInit = body
128 | if (typeof body === 'string') {
129 | this._bodyText = body
130 | } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
131 | this._bodyBlob = body
132 | } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
133 | this._bodyFormData = body
134 | } else if (!body) {
135 | this._bodyText = ''
136 | } else {
137 | throw new Error('unsupported BodyInit type')
138 | }
139 | }
140 |
141 | if (support.blob) {
142 | this.blob = function() {
143 | var rejected = consumed(this)
144 | if (rejected) {
145 | return rejected
146 | }
147 |
148 | if (this._bodyBlob) {
149 | return Promise.resolve(this._bodyBlob)
150 | } else if (this._bodyFormData) {
151 | throw new Error('could not read FormData body as blob')
152 | } else {
153 | return Promise.resolve(new Blob([this._bodyText]))
154 | }
155 | }
156 |
157 | this.arrayBuffer = function() {
158 | return this.blob().then(readBlobAsArrayBuffer)
159 | }
160 |
161 | this.text = function() {
162 | var rejected = consumed(this)
163 | if (rejected) {
164 | return rejected
165 | }
166 |
167 | if (this._bodyBlob) {
168 | return readBlobAsText(this._bodyBlob)
169 | } else if (this._bodyFormData) {
170 | throw new Error('could not read FormData body as text')
171 | } else {
172 | return Promise.resolve(this._bodyText)
173 | }
174 | }
175 | } else {
176 | this.text = function() {
177 | var rejected = consumed(this)
178 | return rejected ? rejected : Promise.resolve(this._bodyText)
179 | }
180 | }
181 |
182 | if (support.formData) {
183 | this.formData = function() {
184 | return this.text().then(decode)
185 | }
186 | }
187 |
188 | this.json = function() {
189 | return this.text().then(JSON.parse)
190 | }
191 |
192 | return this
193 | }
194 |
195 | // HTTP methods whose capitalization should be normalized
196 | var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
197 |
198 | function normalizeMethod(method) {
199 | var upcased = method.toUpperCase()
200 | return (methods.indexOf(upcased) > -1) ? upcased : method
201 | }
202 |
203 | function Request(url, options) {
204 | options = options || {}
205 | this.url = url
206 |
207 | this.credentials = options.credentials || 'omit'
208 | this.headers = new Headers(options.headers)
209 | this.method = normalizeMethod(options.method || 'GET')
210 | this.mode = options.mode || null
211 | this.referrer = null
212 |
213 | if ((this.method === 'GET' || this.method === 'HEAD') && options.body) {
214 | throw new TypeError('Body not allowed for GET or HEAD requests')
215 | }
216 | this._initBody(options.body)
217 | }
218 |
219 | function decode(body) {
220 | var form = new FormData()
221 | body.trim().split('&').forEach(function(bytes) {
222 | if (bytes) {
223 | var split = bytes.split('=')
224 | var name = split.shift().replace(/\+/g, ' ')
225 | var value = split.join('=').replace(/\+/g, ' ')
226 | form.append(decodeURIComponent(name), decodeURIComponent(value))
227 | }
228 | })
229 | return form
230 | }
231 |
232 | function headers(xhr) {
233 | var head = new Headers()
234 | var pairs = xhr.getAllResponseHeaders().trim().split('\n')
235 | pairs.forEach(function(header) {
236 | var split = header.trim().split(':')
237 | var key = split.shift().trim()
238 | var value = split.join(':').trim()
239 | head.append(key, value)
240 | })
241 | return head
242 | }
243 |
244 | Body.call(Request.prototype)
245 |
246 | function Response(bodyInit, options) {
247 | if (!options) {
248 | options = {}
249 | }
250 |
251 | this._initBody(bodyInit)
252 | this.type = 'default'
253 | this.url = null
254 | this.status = options.status
255 | this.ok = this.status >= 200 && this.status < 300
256 | this.statusText = options.statusText
257 | this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers)
258 | this.url = options.url || ''
259 | }
260 |
261 | Body.call(Response.prototype)
262 |
263 | self.Headers = Headers;
264 | self.Request = Request;
265 | self.Response = Response;
266 |
267 | self.fetch = function(input, init) {
268 | // TODO: Request constructor should accept input, init
269 | var request
270 | if (Request.prototype.isPrototypeOf(input) && !init) {
271 | request = input
272 | } else {
273 | request = new Request(input, init)
274 | }
275 |
276 | return new Promise(function(resolve, reject) {
277 | var xhr = new XMLHttpRequest()
278 |
279 | function responseURL() {
280 | if ('responseURL' in xhr) {
281 | return xhr.responseURL
282 | }
283 |
284 | // Avoid security warnings on getResponseHeader when not allowed by CORS
285 | if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {
286 | return xhr.getResponseHeader('X-Request-URL')
287 | }
288 |
289 | return;
290 | }
291 |
292 | xhr.onload = function() {
293 | var status = (xhr.status === 1223) ? 204 : xhr.status
294 | if (status < 100 || status > 599) {
295 | reject(new TypeError('Network request failed'))
296 | return
297 | }
298 | var options = {
299 | status: status,
300 | statusText: xhr.statusText,
301 | headers: headers(xhr),
302 | url: responseURL()
303 | }
304 | var body = 'response' in xhr ? xhr.response : xhr.responseText;
305 | resolve(new Response(body, options))
306 | }
307 |
308 | xhr.onerror = function() {
309 | reject(new TypeError('Network request failed'))
310 | }
311 |
312 | xhr.open(request.method, request.url, true)
313 |
314 | if (request.credentials === 'include') {
315 | xhr.withCredentials = true
316 | }
317 |
318 | if ('responseType' in xhr && support.blob) {
319 | xhr.responseType = 'blob'
320 | }
321 |
322 | request.headers.forEach(function(value, name) {
323 | xhr.setRequestHeader(name, value)
324 | })
325 |
326 | xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
327 | })
328 | }
329 | self.fetch.polyfill = true
330 | })();
331 |
--------------------------------------------------------------------------------
/s_login/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "dependencies": {
4 | "riot": "^2.2.4",
5 | "whatwg-fetch": "^0.9.0"
6 | },
7 | "devDependencies": {
8 | "light-server": "^1.0.6"
9 | },
10 | "scripts": {
11 | "dev": "light-server -s . -w 'js/**'"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/vue_webpack/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-2"],
3 | "plugins": ["transform-runtime"],
4 | "comments": false
5 | }
6 |
--------------------------------------------------------------------------------
/vue_webpack/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig file (see http://EditorConfig.org)
2 |
3 | root = true
4 |
5 | # All files.
6 | [*]
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 | indent_style = space
11 | indent_size = 2
12 |
--------------------------------------------------------------------------------
/vue_webpack/.eslintignore:
--------------------------------------------------------------------------------
1 | *.css
2 |
--------------------------------------------------------------------------------
/vue_webpack/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: 'airbnb/base',
4 | // required to lint *.vue files
5 | plugins: [
6 | 'html'
7 | ],
8 | 'rules': {
9 | 'semi': [2, 'never'],
10 | "no-param-reassign": [2, { "props": false }],
11 | },
12 | }
13 |
--------------------------------------------------------------------------------
/vue_webpack/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log
5 |
--------------------------------------------------------------------------------
/vue_webpack/README.md:
--------------------------------------------------------------------------------
1 | ## Use Vue and ES6(babel) to build app
2 |
3 | This tiny example shows how to write ES6 with vue, vuex, vue-router to write an SPA.
4 |
5 | The app logic is copied from [riot_webpack](../riot_webpack), which is implemented with riotjs. So you can see to write a same app, which one do you prefer.
--------------------------------------------------------------------------------
/vue_webpack/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Vue webpack demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/vue_webpack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue_webpack",
3 | "description": "Sample vue webpack project",
4 | "author": "Tianxiang Chen ",
5 | "private": true,
6 | "scripts": {
7 | "dev": "webpack-dev-server --inline --hot",
8 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
9 | "viewdist": "light-server -s . -p 8080",
10 | "lint": "eslint --ext .js,.vue --quiet src/*"
11 | },
12 | "dependencies": {
13 | "vue": "^1.0.0"
14 | },
15 | "devDependencies": {
16 | "babel-core": "^6.0.0",
17 | "babel-loader": "^6.0.0",
18 | "babel-plugin-transform-runtime": "^6.0.0",
19 | "babel-preset-es2015": "^6.0.0",
20 | "babel-preset-stage-2": "^6.0.0",
21 | "cross-env": "^1.0.6",
22 | "css-loader": "^0.23.1",
23 | "eslint": "^2.4.0",
24 | "eslint-config-airbnb": "^6.2.0",
25 | "eslint-loader": "^1.3.0",
26 | "eslint-plugin-html": "^1.4.0",
27 | "file-loader": "^0.8.4",
28 | "json-loader": "^0.5.4",
29 | "light-server": "^1.1.6",
30 | "url-loader": "^0.5.7",
31 | "vue-hot-reload-api": "^1.2.0",
32 | "vue-html-loader": "^1.0.0",
33 | "vue-loader": "^8.2.1",
34 | "vue-router": "^0.7.11",
35 | "vue-style-loader": "^1.0.0",
36 | "vuex": "^0.6.2",
37 | "vuex-router-sync": "^1.0.0",
38 | "webpack": "^1.12.2",
39 | "webpack-dev-server": "^1.12.0"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/vue_webpack/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
35 |
--------------------------------------------------------------------------------
/vue_webpack/src/component/postcell.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Id: {{ post.postId }}
4 |
Title: {{ post.title }}
5 |
{{ post.likes }} Likes
6 |
Like
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/vue_webpack/src/main.css:
--------------------------------------------------------------------------------
1 | th{font-weight:600}td,th{border-bottom:1.08px solid #ccc;padding:14.85px 18px}thead th{border-bottom-width:2.16px;padding-bottom:6.3px}table{display:block;max-width:100%;overflow-x:auto}input,textarea,select,button{display:block;padding:9.9px}label{display:block;margin-bottom:14.76px}input[type="submit"],input[type="reset"],button{background:#b3b3b3;border-radius:3.6px;color:#fff;cursor:pointer;display:inline;margin-bottom:18px;margin-right:7.2px;padding:6.525px 23.4px;text-align:center}input[type="submit"]:hover,input[type="reset"]:hover,button:hover{background:#a6a6a6;color:#bfbfbf}input[type="submit"],button[type="submit"]{background:#367ac3;color:#fff}input[type="submit"]:hover,button[type="submit"]:hover{background:#255587;color:#bfbfbf}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="phone"],input[type="tel"],input[type="number"],input[type="datetime"],input[type="date"],input[type="month"],input[type="color"],input[type="time"],input[type="search"],input[type="range"],input[type="file"],input[type="datetime-local"],select,textarea{border:1px solid #ccc;margin-bottom:18px;padding:5.4px 6.3px}input[type="checkbox"]{float:left;line-height:36px;margin-right:9px;margin-top:8.1px}pre,code,kbd,samp,var,output{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:16.2px}pre{border-left:1.8px solid #96bbe2;line-height:25.2px;margin-top:29.7px;overflow:auto;padding-left:18px}pre code{background:none;border:0;line-height:29.7px;padding:0}code{background:#ededed;border:1.8px solid #ccc;border-radius:3.6px;display:inline-block;line-height:18px;padding:3px 6px 2px}h1,h2,h3,h4,h5,h6{color:#000}h1{font-size:36px;font-weight:500;margin-bottom:18px;margin-top:36px}h2{font-size:25.2px;font-weight:400;margin-bottom:18px;margin-top:27px}h3{font-size:18px;margin-bottom:18px;margin-top:21.6px}h4,h5,h6{font-size:36px;margin-bottom:18px;margin-top:36px}a{color:#367ac3;text-decoration:none}a:hover{text-decoration:underline}hr{border-bottom:1px solid #ccc}small{font-size:15.3px}em,i{font-style:italic}strong,b{font-weight:500}*{border:0;border-collapse:separate;border-spacing:0;box-sizing:border-box;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:18px;font-stretch:normal;font-style:normal;font-weight:300;line-height:29.7px;margin:0;outline:0;padding:0;text-align:left;vertical-align:baseline}body{background:#f5f5f5;color:#1a1a1a;padding:36px}p,ul,ol,dl,blockquote,hr,pre,table,form,fieldset,figure,address{margin-bottom:29.7px}section{margin-left:auto;margin-right:auto;max-width:100%;width:900px}article{background:#fff;border:1.8px solid #d9d9d9;border-radius:7.2px;padding:43.2px}header{margin-bottom:36px}footer{margin-top:36px}nav{text-align:center}nav ul{list-style:none;text-align:center}nav ul li{display:inline;margin-left:9px;margin-right:9px}@media (max-width: 767px){body{padding:18px}article{border-radius:0;margin:-18px;padding:18px}textarea,input,select{max-width:100%}fieldset{min-width:0}@-moz-document url-prefix(){fieldset{display:table-cell}}section{width:auto}}
2 | /*# sourceMappingURL=tacit-0.3.5.min.css.map */
--------------------------------------------------------------------------------
/vue_webpack/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import { sync } from 'vuex-router-sync'
4 | import store from './vuex/store'
5 | import CategoriesView from './view/categories-view.vue'
6 | import DetailView from './view/detail-view.vue'
7 | import PostsView from './view/posts-view.vue'
8 | import App from './app.vue'
9 |
10 | Vue.use(VueRouter)
11 | // Vue.config.debug = true
12 |
13 | const router = new VueRouter()
14 |
15 | router.map({
16 | '/categories': {
17 | component: CategoriesView,
18 | },
19 | '/detail/:postId': {
20 | component: DetailView,
21 | },
22 | '/posts': {
23 | component: PostsView,
24 | },
25 | })
26 |
27 | router.redirect({
28 | '*': '/posts',
29 | })
30 |
31 | sync(store, router)
32 |
33 | router.start(App, 'app')
34 |
--------------------------------------------------------------------------------
/vue_webpack/src/vendor.js:
--------------------------------------------------------------------------------
1 | import './main.css'
2 | import 'vue'
3 | import 'vue-router'
4 | import 'vuex'
5 | import 'vuex-router-sync'
6 |
--------------------------------------------------------------------------------
/vue_webpack/src/view/categories-view.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ category }}
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/vue_webpack/src/view/detail-view.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ currentPost.title }}
3 | {{ currentPost.content }}
4 | {{ currentPost.likes }} Likes
5 | Previous Post |
6 | Next Post
7 |
8 |
9 |
21 |
--------------------------------------------------------------------------------
/vue_webpack/src/view/posts-view.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/vue_webpack/src/vuex/middlewares.js:
--------------------------------------------------------------------------------
1 | import { STORAGE_KEY } from './store'
2 |
3 | const localStorageMiddleware = {
4 | onMutation(mutation, { posts }) {
5 | localStorage.setItem(STORAGE_KEY, JSON.stringify(posts))
6 | },
7 | }
8 |
9 | export default [localStorageMiddleware]
10 |
--------------------------------------------------------------------------------
/vue_webpack/src/vuex/mutation-types.js:
--------------------------------------------------------------------------------
1 | export const RESET_DATA = 'RESET_DATA'
2 | export const LIKE_POST = 'LIKE_POST'
3 |
--------------------------------------------------------------------------------
/vue_webpack/src/vuex/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import { RESET_DATA, LIKE_POST } from './mutation-types'
4 | import middlewares from './middlewares'
5 |
6 | Vue.use(Vuex)
7 |
8 | export const STORAGE_KEY = 'vue-webpack'
9 |
10 | function getDefaultData() {
11 | return [
12 | { postId: 1, title: 'Best xbox games', content: 'Halo, GOW',
13 | category: 'collection', likes: 10 },
14 | { postId: 2, title: 'Best ps games', content: 'Uncharted, The Last of US',
15 | category: 'collection', likes: 20 },
16 | { postId: 3, title: 'Best wii games', content: 'Zelda, Mario',
17 | category: 'collection', likes: 16 },
18 | { postId: 4, title: 'Review of Halo', content: 'yes, cortana',
19 | category: 'review', likes: 11 },
20 | { postId: 5, title: 'Review of Titanfall', content: 'where is the local game?',
21 | category: 'review', likes: 7 },
22 | { postId: 6, title: 'Review of portal', content: 'I don\'t blame you',
23 | category: 'review', likes: 40 },
24 | ]
25 | }
26 | const mutations = {
27 | [RESET_DATA](state) {
28 | state.posts = getDefaultData()
29 | },
30 | [LIKE_POST](state, post) {
31 | post.likes++
32 | },
33 | }
34 |
35 | const state = {
36 | posts: JSON.parse(localStorage.getItem(STORAGE_KEY) || 'null') || getDefaultData(),
37 | }
38 |
39 | export default new Vuex.Store({
40 | state,
41 | mutations,
42 | middlewares,
43 | })
44 |
--------------------------------------------------------------------------------
/vue_webpack/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 |
4 | module.exports = {
5 | entry: {
6 | main: './src/main.js',
7 | vendor: './src/vendor.js',
8 | },
9 | output: {
10 | path: path.resolve(__dirname, './dist'),
11 | publicPath: '/dist/',
12 | filename: 'build.js',
13 | },
14 | resolveLoader: {
15 | root: path.join(__dirname, 'node_modules'),
16 | },
17 | module: {
18 | preLoaders: [
19 | {
20 | test: /\.vue$/,
21 | loader: 'eslint',
22 | exclude: /node_modules/,
23 | },
24 | {
25 | test: /\.js$/,
26 | loader: 'eslint',
27 | exclude: /node_modules/,
28 | },
29 | ],
30 | loaders: [
31 | {
32 | test: /\.css$/,
33 | loader: 'vue-style!css',
34 | },
35 | {
36 | test: /\.vue$/,
37 | loader: 'vue',
38 | },
39 | {
40 | test: /\.js$/,
41 | loader: 'babel',
42 | exclude: /node_modules/,
43 | },
44 | {
45 | test: /\.json$/,
46 | loader: 'json',
47 | },
48 | {
49 | test: /\.html$/,
50 | loader: 'vue-html',
51 | },
52 | {
53 | test: /\.(png|jpg|gif|svg)$/,
54 | loader: 'url',
55 | query: {
56 | limit: 10000,
57 | name: '[name].[ext]?[hash]',
58 | },
59 | },
60 | ],
61 | },
62 | plugins: [
63 | new webpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.bundle.js'),
64 | ],
65 | devServer: {
66 | historyApiFallback: true,
67 | noInfo: true,
68 | },
69 | devtool: 'eval-source-map',
70 | }
71 |
72 | if (process.env.NODE_ENV === 'production') {
73 | module.exports.devtool = 'source-map'
74 | // http://vuejs.github.io/vue-loader/workflow/production.html
75 | module.exports.plugins = (module.exports.plugins || []).concat([
76 | new webpack.DefinePlugin({
77 | 'process.env': {
78 | NODE_ENV: '"production"',
79 | },
80 | }),
81 | new webpack.optimize.UglifyJsPlugin({
82 | compress: {
83 | warnings: false,
84 | },
85 | }),
86 | new webpack.optimize.OccurenceOrderPlugin(),
87 | ])
88 | }
89 |
--------------------------------------------------------------------------------