├── .gitignore ├── LICENSE ├── README.rst ├── aurelia-f7-todo ├── .babelrc ├── README.rst ├── app │ ├── app.html │ ├── app.js │ ├── main.js │ ├── pages │ │ ├── list-todos │ │ │ ├── list-todos.html │ │ │ └── list-todos.js │ │ └── todo │ │ │ ├── todo.html │ │ │ └── todo.js │ └── services │ │ ├── f7.js │ │ └── storage.js ├── config.xml ├── hooks │ └── README.md ├── index.html ├── index.prod.html ├── package.json ├── styles │ └── style.css ├── webpack.config.js ├── webpack.prod.config.js └── www │ └── index.html ├── aurelia-ux-todo ├── .editorconfig ├── .gitignore ├── assets │ ├── aurelia-icon-128x128.png │ ├── css │ │ └── font-awesome.min.css │ └── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 ├── aurelia_project │ ├── aurelia.json │ ├── environments │ │ ├── dev.ts │ │ ├── prod.ts │ │ └── stage.ts │ ├── generators │ │ ├── attribute.json │ │ ├── attribute.ts │ │ ├── binding-behavior.json │ │ ├── binding-behavior.ts │ │ ├── element.json │ │ ├── element.ts │ │ ├── generator.json │ │ ├── generator.ts │ │ ├── task.json │ │ ├── task.ts │ │ ├── value-converter.json │ │ └── value-converter.ts │ └── tasks │ │ ├── build.json │ │ ├── build.ts │ │ ├── process-css.ts │ │ ├── process-markup.ts │ │ ├── run.json │ │ ├── run.ts │ │ ├── test.json │ │ ├── test.ts │ │ ├── transpile.ts │ │ └── update-ux.ts ├── custom_typings │ └── aurelia-protractor.d.ts ├── favicon.ico ├── index.html ├── karma.conf.js ├── package-lock.json ├── package.json ├── scripts │ ├── require.js │ └── text.js ├── src │ ├── app.css │ ├── app.html │ ├── app.ts │ ├── common.css │ ├── environment.ts │ ├── main.ts │ ├── models │ │ └── todo.ts │ ├── pages │ │ ├── edit.html │ │ ├── edit.ts │ │ ├── list.html │ │ └── list.ts │ ├── reset.css │ ├── routes.ts │ └── services │ │ └── storage.ts ├── test │ ├── aurelia-karma.js │ └── unit │ │ ├── app.spec.ts │ │ └── setup.ts ├── tsconfig.json ├── tslint.json └── typings.json └── ionic2-todo ├── README.rst ├── app ├── app.ts ├── models.ts ├── pages │ ├── list-todos │ │ ├── list-todos.html │ │ ├── list-todos.scss │ │ └── list-todos.ts │ └── todo │ │ ├── todo.html │ │ └── todo.ts └── theme │ ├── app.core.scss │ ├── app.ios.scss │ ├── app.md.scss │ ├── app.variables.scss │ └── app.wp.scss ├── config.xml ├── gulpfile.js ├── hooks ├── README.md └── after_prepare │ └── 010_add_platform_class.js ├── ionic.config.js ├── package.json ├── resources ├── android │ ├── icon │ │ ├── drawable-hdpi-icon.png │ │ ├── drawable-ldpi-icon.png │ │ ├── drawable-mdpi-icon.png │ │ ├── drawable-xhdpi-icon.png │ │ ├── drawable-xxhdpi-icon.png │ │ └── drawable-xxxhdpi-icon.png │ └── splash │ │ ├── drawable-land-hdpi-screen.png │ │ ├── drawable-land-ldpi-screen.png │ │ ├── drawable-land-mdpi-screen.png │ │ ├── drawable-land-xhdpi-screen.png │ │ ├── drawable-land-xxhdpi-screen.png │ │ ├── drawable-land-xxxhdpi-screen.png │ │ ├── drawable-port-hdpi-screen.png │ │ ├── drawable-port-ldpi-screen.png │ │ ├── drawable-port-mdpi-screen.png │ │ ├── drawable-port-xhdpi-screen.png │ │ ├── drawable-port-xxhdpi-screen.png │ │ └── drawable-port-xxxhdpi-screen.png ├── icon.png ├── ios │ ├── icon │ │ ├── icon-40.png │ │ ├── icon-40@2x.png │ │ ├── icon-50.png │ │ ├── icon-50@2x.png │ │ ├── icon-60.png │ │ ├── icon-60@2x.png │ │ ├── icon-60@3x.png │ │ ├── icon-72.png │ │ ├── icon-72@2x.png │ │ ├── icon-76.png │ │ ├── icon-76@2x.png │ │ ├── icon-small.png │ │ ├── icon-small@2x.png │ │ ├── icon-small@3x.png │ │ ├── icon.png │ │ └── icon@2x.png │ └── splash │ │ ├── Default-568h@2x~iphone.png │ │ ├── Default-667h.png │ │ ├── Default-736h.png │ │ ├── Default-Landscape-736h.png │ │ ├── Default-Landscape@2x~ipad.png │ │ ├── Default-Landscape~ipad.png │ │ ├── Default-Portrait@2x~ipad.png │ │ ├── Default-Portrait~ipad.png │ │ ├── Default@2x~iphone.png │ │ └── Default~iphone.png └── splash.png ├── tsconfig.json ├── typings.json ├── webpack.config.js └── www └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Specifies files to intentionally ignore when using Git 2 | # http://git-scm.com/docs/gitignore 3 | 4 | node_modules/ 5 | ionic2-todo/www/build/ 6 | aurelia-f7-todo/www/ 7 | platforms/ 8 | plugins/ 9 | typings 10 | ionic.project 11 | *.swp 12 | .DS_Store 13 | Thumbs.db 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Julien Enselme 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | This repository contains my comparison of Ionic2/Angular2 and Aurelia/Framework7 2 | to build mobile hybrid applications. The ionic2 app is in the *ionic2-todo* 3 | folder and the Aurelia app is in *aurelia-f7-todo*. Both applications are basic 4 | todo list applications that can: 5 | 6 | - List all the saved todos (home page) 7 | - Edit an existing todo 8 | - Add a todo 9 | - Mark a todo as done on the home page. Done todos must have their title 10 | strike-through on the home page. 11 | 12 | All todos must be stored in the permanent SqlStorage of the phone. 13 | 14 | In additions to these features, both applications must work on a browser (for 15 | debug and development purposes), on an android emulator and on an android 16 | phone. 17 | 18 | See the README file in each subfolder to know how to launch and install the 19 | applications and what features they have. 20 | -------------------------------------------------------------------------------- /aurelia-f7-todo/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-1"], 3 | "plugins": ["transform-decorators-legacy"] 4 | } 5 | -------------------------------------------------------------------------------- /aurelia-f7-todo/README.rst: -------------------------------------------------------------------------------- 1 | Requiremts 2 | ========== 3 | 4 | - cordova 5 | - webpack 6 | - webpack-dev-server 7 | 8 | 9 | Setup 10 | ===== 11 | 12 | - Install node dependencies: ``npm install`` 13 | 14 | 15 | Run in browser 16 | ============== 17 | 18 | - Launch ``npm run dev`` to launch the webpack debug server (with live reload). 19 | 20 | 21 | Build for android 22 | ================= 23 | 24 | - Add platform: ``cordova platform add browser`` 25 | - Add platform: ``cordova platform add android`` 26 | - Run on browser (with cordova for debug): ``cardova run browser`` 27 | - Build for phone: ``cordova build android`` 28 | -------------------------------------------------------------------------------- /aurelia-f7-todo/app/app.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /aurelia-f7-todo/app/app.js: -------------------------------------------------------------------------------- 1 | export class App { 2 | configureRouter(config, router) { 3 | config.title = 'Aurelia'; 4 | config.map([ 5 | { 6 | route: ['', 'todos'], 7 | name: 'todos', 8 | moduleId: 'pages/list-todos/list-todos', 9 | nav: true, 10 | title: 'todos' 11 | }, { 12 | route: ['todo', 'todo/:id'], 13 | name: 'todo', 14 | moduleId: 'pages/todo/todo', 15 | nav: true, 16 | title: 'View Todo', 17 | } 18 | ]); 19 | 20 | this.router = router; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /aurelia-f7-todo/app/main.js: -------------------------------------------------------------------------------- 1 | import {bootstrap} from 'aurelia-bootstrapper-webpack'; 2 | 3 | import 'framework7/dist/css/framework7.material.css' 4 | import 'framework7/dist/css/framework7.material.colors.css' 5 | import 'framework7/dist/js/framework7.js' 6 | import '../styles/style.css'; 7 | 8 | 9 | bootstrap(function (aurelia) { 10 | aurelia.use 11 | .standardConfiguration() 12 | .plugin('aurelia-validation') 13 | .developmentLogging(); 14 | 15 | aurelia.start().then(() => aurelia.setRoot('app', document.body)); 16 | }); 17 | -------------------------------------------------------------------------------- /aurelia-f7-todo/app/pages/list-todos/list-todos.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /aurelia-f7-todo/app/pages/list-todos/list-todos.js: -------------------------------------------------------------------------------- 1 | import { Storage } from '../../services/storage'; 2 | import { F7 } from '../../services/f7'; 3 | import {inject} from 'aurelia-framework'; 4 | import { Router } from 'aurelia-router'; 5 | 6 | 7 | @inject(F7, Router, Storage) 8 | export class ListTodosPage { 9 | heading = 'Welcome to the Aurelia Framework 7 TODO App'; 10 | 11 | constructor(f7, router, storage) { 12 | this.f7 = f7; 13 | this.router = router; 14 | this.storage = storage; 15 | this.todos = []; 16 | 17 | this.storage.getTodos().then(todos => this.todos = todos); 18 | } 19 | 20 | viewTodo(todo) { 21 | this.router.navigateToRoute('todo', {id: todo.id}); 22 | } 23 | 24 | addTodo() { 25 | this.router.navigate('/todo'); 26 | } 27 | 28 | toggleDone(todo, event) { 29 | event.stopPropagation(); 30 | 31 | if (todo.done === true || todo.done === 'true') { 32 | todo.done = 'false'; 33 | } else { 34 | todo.done = 'true'; 35 | } 36 | 37 | this.storage.saveTodo(todo); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /aurelia-f7-todo/app/pages/todo/todo.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /aurelia-f7-todo/app/pages/todo/todo.js: -------------------------------------------------------------------------------- 1 | import { inject, ObserverLocator } from 'aurelia-framework'; 2 | import { Router } from 'aurelia-router'; 3 | import { ValidationControllerFactory, ValidationRules, Validator, validateTrigger } from 'aurelia-validation'; 4 | 5 | import { Storage } from '../../services/storage'; 6 | 7 | 8 | /** 9 | * Custom validator that complies with the Validator interface: 10 | * https://github.com/aurelia/validation/blob/master/src/validator.ts 11 | */ 12 | class TodoValidator { 13 | constructor(validator, cb) { 14 | this.validator = validator; 15 | this.cb = cb; 16 | } 17 | 18 | /** 19 | * This method will be called by the controller when validating a specific field. For instance, 20 | * when the user is interacting with the title input. So, we need to validate the whole form 21 | * and call our callback in order for TodoPage.canSave to be correctly updated. 22 | */ 23 | validateProperty(object, propertyName, rules) { 24 | let validationDefered = this.validator.validateProperty(object, propertyName, rules); 25 | validationDefered.then(() => this.validateObject(object, rules)); 26 | 27 | return validationDefered; 28 | } 29 | 30 | /** 31 | * Each time the whole form is validated, we call the registered callback to do whatever 32 | * the user wants to do with the results of the validation. In our case: update 33 | * TodoPage.canSave. 34 | */ 35 | validateObject(object, rules) { 36 | return this.validator.validateObject(object, rules).then(results => { 37 | this.cb(results); 38 | return results; 39 | }); 40 | } 41 | 42 | /** 43 | * Implemented so the interface is complete. 44 | */ 45 | ruleExists(rules, rule) { 46 | return this.validator(rules, rule); 47 | } 48 | } 49 | 50 | 51 | @inject(Router, Storage, ValidationControllerFactory, Validator, ObserverLocator) 52 | export class TodoPage { 53 | constructor(router, storage, controllerFactory, validator, ol) { 54 | this.router = router; 55 | this.storage = storage; 56 | 57 | this.validator = new TodoValidator(validator, results => this.updateCanSave(results)); 58 | this.controller = controllerFactory.createForCurrentScope(this.validator); 59 | this.controller.validateTrigger = validateTrigger.changeOrBlur; 60 | 61 | // We don't know if we can save. This will be updated when the view is activated (the form 62 | // should be valid if we are editing an existing todo but invalid if we are creating a 63 | // new one). 64 | this.canSave = false; 65 | } 66 | 67 | activate(params) { 68 | if (params.id) { 69 | // In this case, we are editing a TODO. We fetch it from the storage and assign it to 70 | // the todo property. We can then setup validation on this property. If we had set it 71 | // up in the constructor, validation would become uneffective: we replaced the object 72 | // in this.todo by another one. ValidationRules.on is not tracking the right object. 73 | // Once this is done, we setup validation and validate the form so this.canSave is 74 | // true if the edited TODO is valid. If the user modifies the TODO, then the 75 | // controller will handle the validation and this.canSave will be updated accordingly. 76 | this.storage.getTodo(params.id) 77 | .then(todo => this.todo = todo) 78 | .then(() => { 79 | this.setupValidation(); 80 | this.validate(); 81 | }); 82 | } else { 83 | // We are creating a new todo. We just need to initialize this.todo and validation. 84 | this.todo = {}; 85 | this.setupValidation(); 86 | } 87 | } 88 | 89 | setupValidation() { 90 | ValidationRules 91 | .ensure('title').required().minLength(3).withMessage('Title must at least be 3 chars long.') 92 | .on(this.todo); 93 | } 94 | 95 | validate() { 96 | this.validator.validateObject(this.todo); 97 | } 98 | 99 | updateCanSave(validationResults) { 100 | let valid = true; 101 | 102 | for (let result of validationResults) { 103 | valid = valid && result.valid; 104 | } 105 | 106 | this.canSave = valid; 107 | } 108 | 109 | saveTodo() { 110 | this.storage.saveTodo(this.todo) 111 | .then(() => this.router.navigateToRoute('todos')); 112 | } 113 | 114 | cancel() { 115 | this.router.navigateToRoute('todos'); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /aurelia-f7-todo/app/services/f7.js: -------------------------------------------------------------------------------- 1 | import 'framework7'; 2 | 3 | 4 | export const F7 = new Framework7({ 5 | material: true, 6 | }); 7 | -------------------------------------------------------------------------------- /aurelia-f7-todo/app/services/storage.js: -------------------------------------------------------------------------------- 1 | import * as localforage from '../../node_modules/localforage/dist/localforage.js'; 2 | 3 | 4 | export class Storage { 5 | constructor() { 6 | this.storage = localforage; 7 | } 8 | 9 | getTodos() { 10 | return this.storage.getItem('todos') 11 | .then(todos => JSON.parse(todos)) 12 | .then(todos => todos ? todos : []); 13 | } 14 | 15 | saveTodo(todo) { 16 | let prepareTodos; 17 | if (!todo.id) { 18 | prepareTodos = this.getTodos() 19 | .then(todos => { 20 | todo.id = todos.length; 21 | todos.push(todo); 22 | return todos; 23 | }); 24 | } else { 25 | prepareTodos = this.getTodos() 26 | .then(todos => { 27 | let index = todo.id; 28 | todos[index] = todo; 29 | 30 | return todos; 31 | }); 32 | } 33 | 34 | return prepareTodos.then(todos => this.storage.setItem('todos', JSON.stringify(todos))); 35 | } 36 | 37 | getTodo(id) { 38 | return this.getTodos() 39 | .then(todos => todos[id]); 40 | } 41 | } -------------------------------------------------------------------------------- /aurelia-f7-todo/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Aurelia F7 TODO 4 | 5 | A sample Apache Cordova application made with Aurelia and Framework 7. 6 | 7 | 8 | Julien Enselme 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /aurelia-f7-todo/hooks/README.md: -------------------------------------------------------------------------------- 1 | 21 | # Cordova Hooks 22 | 23 | Cordova Hooks represent special scripts which could be added by application and plugin developers or even by your own build system to customize cordova commands. See Hooks Guide for more details: http://cordova.apache.org/docs/en/edge/guide_appdev_hooks_index.md.html#Hooks%20Guide. 24 | -------------------------------------------------------------------------------- /aurelia-f7-todo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | TODO Application 11 | 12 | 13 | 14 |
15 |
Aurelia Navigation Skeleton
16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /aurelia-f7-todo/index.prod.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Aurelia 5 | 6 | 7 | 8 |
9 |
Aurelia Navigation Skeleton
10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /aurelia-f7-todo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-f7-todo", 3 | "version": "0.1.0", 4 | "description": "A starter kit for building a standard navigation-style app with Aurelia and webpack.", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack-dev-server --config webpack.config.js --inline --progress --devtool eval", 8 | "build": "webpack --config webpack.config.js --progress --profile", 9 | "build-android": "webpack -p --config webpack.prod.config.js --progress && cordova build android", 10 | "test": "karma start" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+ssh://git@github.com/aurelia/skeleton-navigation.git" 15 | }, 16 | "keywords": [ 17 | "aurelia", 18 | "skeleton", 19 | "navigation", 20 | "webpack" 21 | ], 22 | "author": "Julien Enselme", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/aurelia/skeleton-navigation/issues" 26 | }, 27 | "homepage": "https://github.com/aurelia/skeleton-navigation#readme", 28 | "aurelia": { 29 | "build": { 30 | "moduleRootOverride": { 31 | "aurelia-templating-resources": "dist/commonjs" 32 | } 33 | } 34 | }, 35 | "dependencies": { 36 | "aurelia-bootstrapper-webpack": "1.1.0", 37 | "aurelia-event-aggregator": "1.0.1", 38 | "aurelia-fetch-client": "1.1.0", 39 | "aurelia-framework": "1.0.8", 40 | "aurelia-history-browser": "1.0.0", 41 | "aurelia-logging-console": "1.0.0", 42 | "aurelia-pal-browser": "1.1.0", 43 | "aurelia-polyfills": "1.1.1", 44 | "aurelia-router": "1.1.1", 45 | "aurelia-templating-binding": "1.2.0", 46 | "aurelia-templating-resources": "1.2.0", 47 | "aurelia-templating-router": "1.0.1", 48 | "aurelia-validation": "1.0.0-beta.1.0.1", 49 | "bootstrap": "3.3.7", 50 | "font-awesome": "4.7.0", 51 | "framework7": "1.5.2", 52 | "isomorphic-fetch": "^2.2.1", 53 | "localforage": "1.4.3" 54 | }, 55 | "devDependencies": { 56 | "aurelia-tools": "1.0.0", 57 | "aurelia-webpack-plugin": "1.2.0", 58 | "babel-core": "6.22.1", 59 | "babel-eslint": "7.1.1", 60 | "babel-plugin-syntax-flow": "6.18.0", 61 | "babel-plugin-transform-decorators-legacy": "1.3.4", 62 | "babel-plugin-transform-es2015-modules-amd": "6.8.0", 63 | "babel-plugin-transform-es2015-modules-commonjs": "6.18.0", 64 | "babel-plugin-transform-flow-strip-types": "6.18.0", 65 | "babel-polyfill": "6.16.0", 66 | "babel-preset-es2015": "6.18.0", 67 | "babel-preset-es2015-loose": "8.0.0", 68 | "babel-preset-stage-1": "6.16.0", 69 | "babel-register": "6.18.0", 70 | "babel-runtime": "6.18.0", 71 | "babel-loader": "6.2.10", 72 | "css-loader": "0.26.1", 73 | "eslint": "3.14.0", 74 | "file-loader": "0.9.0", 75 | "html-webpack-plugin": "2.26.0", 76 | "jasmine-core": "2.5.2", 77 | "karma": "1.4.0", 78 | "karma-babel-preprocessor": "6.0.1", 79 | "karma-chrome-launcher": "2.0.0", 80 | "karma-jasmine": "^1.1.0", 81 | "karma-webpack": "2.0.1", 82 | "protractor": "5.0.0", 83 | "html-loader": "^0.4.4", 84 | "raw-loader": "0.5.1", 85 | "style-loader": "0.13.1", 86 | "url-loader": "0.5.7", 87 | "webpack": "3.0.0", 88 | "webpack-dev-server": "2.5.0" 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /aurelia-f7-todo/styles/style.css: -------------------------------------------------------------------------------- 1 | .navbar .center { 2 | margin: auto; 3 | } 4 | 5 | .done { 6 | text-decoration: line-through; 7 | } 8 | -------------------------------------------------------------------------------- /aurelia-f7-todo/webpack.config.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable no-var*/ 2 | 3 | var path = require('path'); 4 | var AureliaWebpackPlugin = require('aurelia-webpack-plugin'); 5 | 6 | module.exports = { 7 | devServer: { 8 | host: 'localhost', 9 | port: 3000 10 | }, 11 | entry: { 12 | main: [ 13 | './app/main' 14 | ] 15 | }, 16 | output: { 17 | path: path.join(__dirname, 'build'), 18 | filename: 'bundle.js' 19 | }, 20 | plugins: [ 21 | new AureliaWebpackPlugin({ 22 | src: path.resolve('./app/'), 23 | }) 24 | ], 25 | module: { 26 | loaders: [ 27 | { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, 28 | { test: /\.css?$/, use: [{loader: 'style-loader'}, {loader: 'css-loader'}] }, 29 | { test: /\.html$/, loader: 'html-loader' }, 30 | { test: /\.(png|gif|jpg)$/, loader: 'url-loader?limit=8192' }, 31 | { test: /\.woff2(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&minetype=application/font-woff2' }, 32 | { test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&minetype=application/font-woff' }, 33 | { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file-loader' } 34 | ] 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /aurelia-f7-todo/webpack.prod.config.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable no-var*/ 2 | 3 | var path = require('path'); 4 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | var AureliaWebpackPlugin = require('aurelia-webpack-plugin'); 6 | var pkg = require('./package.json'); 7 | 8 | var outputFileTemplateSuffix = '-' + pkg.version; 9 | 10 | module.exports = { 11 | entry: { 12 | main: [ 13 | './app/main' 14 | ] 15 | }, 16 | output: { 17 | path: path.join(__dirname, 'www/'), 18 | filename: 'bundle.js', 19 | }, 20 | plugins: [ 21 | new AureliaWebpackPlugin({ 22 | src: path.resolve('./app/'), 23 | }), 24 | ], 25 | resolve: { 26 | root: [ 27 | path.resolve('./') 28 | ] 29 | }, 30 | module: { 31 | loaders: [ 32 | { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, 33 | { test: /\.css?$/, use: [{loader: 'style-loader'}, {loader: 'css-loader'}] }, 34 | { test: /\.html$/, loader: 'html-loader' }, 35 | { test: /\.(png|gif|jpg)$/, loader: 'url-loader?limit=8192' }, 36 | { test: /\.woff2(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&minetype=application/font-woff2' }, 37 | { test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&minetype=application/font-woff' }, 38 | { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file-loader' } 39 | ] 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /aurelia-f7-todo/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | TODO Application 41 | 42 | 43 | 44 |
45 |
Aurelia Navigation Skeleton
46 | 47 |
48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /aurelia-ux-todo/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # 2 space indentation 12 | [**.*] 13 | indent_style = space 14 | indent_size = 2 -------------------------------------------------------------------------------- /aurelia-ux-todo/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | .DS_STORE 4 | scripts/* 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/assets/aurelia-icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/aurelia-ux-todo/assets/aurelia-icon-128x128.png -------------------------------------------------------------------------------- /aurelia-ux-todo/assets/css/font-awesome.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/assets/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/aurelia-ux-todo/assets/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /aurelia-ux-todo/assets/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/aurelia-ux-todo/assets/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /aurelia-ux-todo/assets/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/aurelia-ux-todo/assets/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /aurelia-ux-todo/assets/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/aurelia-ux-todo/assets/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /aurelia-ux-todo/assets/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/aurelia-ux-todo/assets/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/aurelia.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-ux-showcase", 3 | "type": "project:application", 4 | "platform": { 5 | "id": "web", 6 | "displayName": "Web", 7 | "output": "scripts", 8 | "index": "index.html" 9 | }, 10 | "transpiler": { 11 | "id": "typescript", 12 | "displayName": "TypeScript", 13 | "fileExtension": ".ts", 14 | "dtsSource": [ 15 | "./typings/**/*.d.ts", 16 | "./custom_typings/**/*.d.ts" 17 | ], 18 | "source": "src/**/*.ts" 19 | }, 20 | "markupProcessor": { 21 | "id": "none", 22 | "displayName": "None", 23 | "fileExtension": ".html", 24 | "source": "src/**/*.html" 25 | }, 26 | "cssProcessor": { 27 | "id": "none", 28 | "displayName": "None", 29 | "fileExtension": ".css", 30 | "source": "src/**/*.css" 31 | }, 32 | "editor": { 33 | "id": "vscode", 34 | "displayName": "Visual Studio Code" 35 | }, 36 | "unitTestRunner": { 37 | "id": "karma", 38 | "displayName": "Karma", 39 | "source": "test/unit/**/*.ts" 40 | }, 41 | "paths": { 42 | "root": "src", 43 | "resources": "src/resources", 44 | "elements": "src/resources/elements", 45 | "attributes": "src/resources/attributes", 46 | "valueConverters": "src/resources/value-converters", 47 | "bindingBehaviors": "src/resources/binding-behaviors" 48 | }, 49 | "testFramework": { 50 | "id": "jasmine", 51 | "displayName": "Jasmine" 52 | }, 53 | "build": { 54 | "targets": [ 55 | { 56 | "id": "web", 57 | "displayName": "Web", 58 | "output": "scripts", 59 | "index": "index.html" 60 | } 61 | ], 62 | "loader": { 63 | "type": "require", 64 | "configTarget": "vendor-bundle.js", 65 | "includeBundleMetadataInConfig": "auto", 66 | "plugins": [ 67 | { 68 | "name": "text", 69 | "extensions": [ 70 | ".html", 71 | ".css" 72 | ], 73 | "stub": true 74 | } 75 | ] 76 | }, 77 | "options": { 78 | "minify": "stage & prod", 79 | "sourcemaps": "dev & stage" 80 | }, 81 | "bundles": [ 82 | { 83 | "name": "app-bundle.js", 84 | "source": [ 85 | "[**/*.js]", 86 | "**/*.{css,html}" 87 | ] 88 | }, 89 | { 90 | "name": "vendor-bundle.js", 91 | "prepend": [ 92 | "node_modules/bluebird/js/browser/bluebird.core.js", 93 | "scripts/require.js" 94 | ], 95 | "dependencies": [ 96 | "aurelia-binding", 97 | "aurelia-bootstrapper", 98 | "aurelia-dependency-injection", 99 | "aurelia-event-aggregator", 100 | "aurelia-framework", 101 | "aurelia-history", 102 | "aurelia-history-browser", 103 | "aurelia-loader", 104 | "aurelia-loader-default", 105 | "aurelia-logging", 106 | "aurelia-logging-console", 107 | "aurelia-metadata", 108 | "aurelia-pal", 109 | "aurelia-pal-browser", 110 | "aurelia-path", 111 | "aurelia-polyfills", 112 | "aurelia-route-recognizer", 113 | "aurelia-router", 114 | "aurelia-task-queue", 115 | "aurelia-templating", 116 | "aurelia-templating-binding", 117 | { 118 | "name": "text", 119 | "path": "../scripts/text" 120 | }, 121 | { 122 | "name": "aurelia-templating-resources", 123 | "path": "../node_modules/aurelia-templating-resources/dist/amd", 124 | "main": "aurelia-templating-resources" 125 | }, 126 | { 127 | "name": "aurelia-templating-router", 128 | "path": "../node_modules/aurelia-templating-router/dist/amd", 129 | "main": "aurelia-templating-router" 130 | }, 131 | { 132 | "name": "aurelia-testing", 133 | "path": "../node_modules/aurelia-testing/dist/amd", 134 | "main": "aurelia-testing", 135 | "env": "dev" 136 | }, 137 | { 138 | "name": "aurelia-validation", 139 | "path": "../node_modules/aurelia-validation/dist/amd", 140 | "main": "aurelia-validation" 141 | }, 142 | { 143 | "name": "aurelia-ux", 144 | "path": "../node_modules/aurelia-ux/dist/amd", 145 | "main": "index", 146 | "resources": ["**/*.{css,html}"] 147 | } 148 | ] 149 | } 150 | ] 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/environments/dev.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | debug: true, 3 | testing: true 4 | }; 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/environments/prod.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | debug: false, 3 | testing: false 4 | }; 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/environments/stage.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | debug: true, 3 | testing: false 4 | }; 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/attribute.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "attribute", 3 | "description": "Creates a custom attribute class and places it in the project resources." 4 | } 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/attribute.ts: -------------------------------------------------------------------------------- 1 | import {inject} from 'aurelia-dependency-injection'; 2 | import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli'; 3 | 4 | @inject(Project, CLIOptions, UI) 5 | export default class AttributeGenerator { 6 | constructor(private project: Project, private options: CLIOptions, private ui: UI) { } 7 | 8 | execute() { 9 | return this.ui 10 | .ensureAnswer(this.options.args[0], 'What would you like to call the custom attribute?') 11 | .then(name => { 12 | let fileName = this.project.makeFileName(name); 13 | let className = this.project.makeClassName(name); 14 | 15 | this.project.attributes.add( 16 | ProjectItem.text(`${fileName}.ts`, this.generateSource(className)) 17 | ); 18 | 19 | return this.project.commitChanges() 20 | .then(() => this.ui.log(`Created ${fileName}.`)); 21 | }); 22 | } 23 | 24 | generateSource(className) { 25 | return `import {autoinject} from 'aurelia-framework'; 26 | 27 | @autoinject() 28 | export class ${className}CustomAttribute { 29 | constructor(private element: Element) { } 30 | 31 | valueChanged(newValue, oldValue) { 32 | 33 | } 34 | } 35 | 36 | ` 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/binding-behavior.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "binding-behavior", 3 | "description": "Creates a binding behavior class and places it in the project resources." 4 | } 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/binding-behavior.ts: -------------------------------------------------------------------------------- 1 | import {inject} from 'aurelia-dependency-injection'; 2 | import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli'; 3 | 4 | @inject(Project, CLIOptions, UI) 5 | export default class BindingBehaviorGenerator { 6 | constructor(private project: Project, private options: CLIOptions, private ui: UI) { } 7 | 8 | execute() { 9 | return this.ui 10 | .ensureAnswer(this.options.args[0], 'What would you like to call the binding behavior?') 11 | .then(name => { 12 | let fileName = this.project.makeFileName(name); 13 | let className = this.project.makeClassName(name); 14 | 15 | this.project.bindingBehaviors.add( 16 | ProjectItem.text(`${fileName}.ts`, this.generateSource(className)) 17 | ); 18 | 19 | return this.project.commitChanges() 20 | .then(() => this.ui.log(`Created ${fileName}.`)); 21 | }); 22 | } 23 | 24 | generateSource(className) { 25 | return `export class ${className}BindingBehavior { 26 | bind(binding, source) { 27 | 28 | } 29 | 30 | unbind(binding, source) { 31 | 32 | } 33 | } 34 | 35 | ` 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/element.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "element", 3 | "description": "Creates a custom element class and template, placing them in the project resources." 4 | } 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/element.ts: -------------------------------------------------------------------------------- 1 | import {inject} from 'aurelia-dependency-injection'; 2 | import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli'; 3 | 4 | @inject(Project, CLIOptions, UI) 5 | export default class ElementGenerator { 6 | constructor(private project: Project, private options: CLIOptions, private ui: UI) { } 7 | 8 | execute() { 9 | return this.ui 10 | .ensureAnswer(this.options.args[0], 'What would you like to call the custom element?') 11 | .then(name => { 12 | let fileName = this.project.makeFileName(name); 13 | let className = this.project.makeClassName(name); 14 | 15 | this.project.elements.add( 16 | ProjectItem.text(`${fileName}.ts`, this.generateJSSource(className)), 17 | ProjectItem.text(`${fileName}.html`, this.generateHTMLSource(className)) 18 | ); 19 | 20 | return this.project.commitChanges() 21 | .then(() => this.ui.log(`Created ${fileName}.`)); 22 | }); 23 | } 24 | 25 | generateJSSource(className) { 26 | return `import {bindable} from 'aurelia-framework'; 27 | 28 | export class ${className} { 29 | @bindable value; 30 | 31 | valueChanged(newValue, oldValue) { 32 | 33 | } 34 | } 35 | 36 | ` 37 | } 38 | 39 | generateHTMLSource(className) { 40 | return `` 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator", 3 | "description": "Creates a generator class and places it in the project generators folder." 4 | } 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/generator.ts: -------------------------------------------------------------------------------- 1 | import {inject} from 'aurelia-dependency-injection'; 2 | import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli'; 3 | 4 | @inject(Project, CLIOptions, UI) 5 | export default class GeneratorGenerator { 6 | constructor(private project: Project, private options: CLIOptions, private ui: UI) { } 7 | 8 | execute() { 9 | return this.ui 10 | .ensureAnswer(this.options.args[0], 'What would you like to call the generator?') 11 | .then(name => { 12 | let fileName = this.project.makeFileName(name); 13 | let className = this.project.makeClassName(name); 14 | 15 | this.project.generators.add( 16 | ProjectItem.text(`${fileName}.ts`, this.generateSource(className)) 17 | ); 18 | 19 | return this.project.commitChanges() 20 | .then(() => this.ui.log(`Created ${fileName}.`)); 21 | }); 22 | } 23 | 24 | generateSource(className) { 25 | return `import {autoinject} from 'aurelia-dependency-injection'; 26 | import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli'; 27 | 28 | @autoinject() 29 | export default class ${className}Generator { 30 | constructor(private project: Project, private options: CLIOptions, private ui: UI) { } 31 | 32 | execute() { 33 | return this.ui 34 | .ensureAnswer(this.options.args[0], 'What would you like to call the new item?') 35 | .then(name => { 36 | let fileName = this.project.makeFileName(name); 37 | let className = this.project.makeClassName(name); 38 | 39 | this.project.elements.add( 40 | ProjectItem.text(\`\${fileName}.js\`, this.generateSource(className)) 41 | ); 42 | 43 | return this.project.commitChanges() 44 | .then(() => this.ui.log(\`Created \${fileName}.\`)); 45 | }); 46 | } 47 | 48 | generateSource(className) { 49 | return \`import {bindable} from 'aurelia-framework'; 50 | 51 | export class \${className} { 52 | @bindable value; 53 | 54 | valueChanged(newValue, oldValue) { 55 | 56 | } 57 | } 58 | 59 | \` 60 | } 61 | } 62 | 63 | ` 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/task.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "task", 3 | "description": "Creates a task and places it in the project tasks folder." 4 | } 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/task.ts: -------------------------------------------------------------------------------- 1 | import {inject} from 'aurelia-dependency-injection'; 2 | import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli'; 3 | 4 | @inject(Project, CLIOptions, UI) 5 | export default class TaskGenerator { 6 | constructor(private project: Project, private options: CLIOptions, private ui: UI) { } 7 | 8 | execute() { 9 | return this.ui 10 | .ensureAnswer(this.options.args[0], 'What would you like to call the task?') 11 | .then(name => { 12 | let fileName = this.project.makeFileName(name); 13 | let functionName = this.project.makeFunctionName(name); 14 | 15 | this.project.tasks.add( 16 | ProjectItem.text(`${fileName}.ts`, this.generateSource(functionName)) 17 | ); 18 | 19 | return this.project.commitChanges() 20 | .then(() => this.ui.log(`Created ${fileName}.`)); 21 | }); 22 | } 23 | 24 | generateSource(functionName) { 25 | return `import * as gulp from 'gulp'; 26 | import * as changed from 'gulp-changed'; 27 | import * as project from '../aurelia.json'; 28 | 29 | export default function ${functionName}() { 30 | return gulp.src(project.paths.???) 31 | .pipe(changed(project.paths.output, {extension: '.???'})) 32 | .pipe(gulp.dest(project.paths.output)); 33 | } 34 | 35 | ` 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/value-converter.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "value-converter", 3 | "description": "Creates a value converter class and places it in the project resources." 4 | } 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/generators/value-converter.ts: -------------------------------------------------------------------------------- 1 | import {inject} from 'aurelia-dependency-injection'; 2 | import {Project, ProjectItem, CLIOptions, UI} from 'aurelia-cli'; 3 | 4 | @inject(Project, CLIOptions, UI) 5 | export default class ValueConverterGenerator { 6 | constructor(private project: Project, private options: CLIOptions, private ui: UI) { } 7 | 8 | execute() { 9 | return this.ui 10 | .ensureAnswer(this.options.args[0], 'What would you like to call the value converter?') 11 | .then(name => { 12 | let fileName = this.project.makeFileName(name); 13 | let className = this.project.makeClassName(name); 14 | 15 | this.project.valueConverters.add( 16 | ProjectItem.text(`${fileName}.ts`, this.generateSource(className)) 17 | ); 18 | 19 | return this.project.commitChanges() 20 | .then(() => this.ui.log(`Created ${fileName}.`)); 21 | }); 22 | } 23 | 24 | generateSource(className) { 25 | return `export class ${className}ValueConverter { 26 | toView(value) { 27 | 28 | } 29 | 30 | fromView(value) { 31 | 32 | } 33 | } 34 | 35 | ` 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "build", 3 | "description": "Builds and processes all application assets.", 4 | "flags": [ 5 | { 6 | "name": "env", 7 | "description": "Sets the build environment.", 8 | "type": "string" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/build.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import transpile from './transpile'; 3 | import processMarkup from './process-markup'; 4 | import processCSS from './process-css'; 5 | import {build} from 'aurelia-cli'; 6 | import * as project from '../aurelia.json'; 7 | 8 | export default gulp.series( 9 | readProjectConfiguration, 10 | gulp.parallel( 11 | transpile, 12 | processMarkup, 13 | processCSS 14 | ), 15 | writeBundles 16 | ); 17 | 18 | function readProjectConfiguration() { 19 | return build.src(project); 20 | } 21 | 22 | function writeBundles() { 23 | return build.dest(); 24 | } 25 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/process-css.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as changedInPlace from 'gulp-changed-in-place'; 3 | import * as project from '../aurelia.json'; 4 | import {build} from 'aurelia-cli'; 5 | 6 | export default function processCSS() { 7 | return gulp.src(project.cssProcessor.source) 8 | .pipe(changedInPlace({firstPass:true})) 9 | .pipe(build.bundle()); 10 | }; 11 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/process-markup.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as changedInPlace from 'gulp-changed-in-place'; 3 | import * as project from '../aurelia.json'; 4 | import {build} from 'aurelia-cli'; 5 | 6 | export default function processMarkup() { 7 | return gulp.src(project.markupProcessor.source) 8 | .pipe(changedInPlace({firstPass:true})) 9 | .pipe(build.bundle()); 10 | } 11 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/run.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "run", 3 | "description": "Builds the application and serves up the assets via a local web server, watching files for changes as you work.", 4 | "flags": [ 5 | { 6 | "name": "env", 7 | "description": "Sets the build environment.", 8 | "type": "string" 9 | }, 10 | { 11 | "name": "watch", 12 | "description": "Watches source files for changes and refreshes the app automatically.", 13 | "type": "boolean" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/run.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as browserSync from 'browser-sync'; 3 | import * as historyApiFallback from 'connect-history-api-fallback/lib'; 4 | import * as project from '../aurelia.json'; 5 | import build from './build'; 6 | import {CLIOptions} from 'aurelia-cli'; 7 | 8 | function onChange(path) { 9 | console.log(`File Changed: ${path}`); 10 | } 11 | 12 | function reload(done) { 13 | browserSync.reload(); 14 | done(); 15 | } 16 | 17 | let serve = gulp.series( 18 | build, 19 | done => { 20 | browserSync({ 21 | online: false, 22 | open: false, 23 | port: 9000, 24 | logLevel: 'silent', 25 | server: { 26 | baseDir: ['.'], 27 | middleware: [historyApiFallback(), function(req, res, next) { 28 | res.setHeader('Access-Control-Allow-Origin', '*'); 29 | next(); 30 | }] 31 | } 32 | }, function (err, bs) { 33 | let urls = bs.options.get('urls').toJS(); 34 | console.log(`Application Available At: ${urls.local}`); 35 | console.log(`BrowserSync Available At: ${urls.ui}`); 36 | done(); 37 | }); 38 | } 39 | ); 40 | 41 | let refresh = gulp.series( 42 | build, 43 | reload 44 | ); 45 | 46 | let watch = function() { 47 | gulp.watch(project.transpiler.source, refresh).on('change', onChange); 48 | gulp.watch(project.markupProcessor.source, refresh).on('change', onChange); 49 | gulp.watch(project.cssProcessor.source, refresh).on('change', onChange); 50 | } 51 | 52 | let run; 53 | 54 | if (CLIOptions.hasFlag('watch')) { 55 | run = gulp.series( 56 | serve, 57 | watch 58 | ); 59 | } else { 60 | run = serve; 61 | } 62 | 63 | export default run; 64 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "description": "Runs all unit tests and reports the results.", 4 | "flags": [ 5 | { 6 | "name": "env", 7 | "description": "Sets the build environment.", 8 | "type": "string" 9 | }, 10 | { 11 | "name": "watch", 12 | "description": "Watches test files for changes and re-runs the tests automatically.", 13 | "type": "boolean" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/test.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import {Server as Karma} from 'karma'; 3 | import {CLIOptions} from 'aurelia-cli'; 4 | 5 | export function unit(done) { 6 | new Karma({ 7 | configFile: __dirname + '/../../karma.conf.js', 8 | singleRun: !CLIOptions.hasFlag('watch') 9 | }, done).start(); 10 | } 11 | 12 | export default unit; 13 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/transpile.ts: -------------------------------------------------------------------------------- 1 | import * as gulp from 'gulp'; 2 | import * as changedInPlace from 'gulp-changed-in-place'; 3 | import * as plumber from 'gulp-plumber'; 4 | import * as sourcemaps from 'gulp-sourcemaps'; 5 | import * as notify from 'gulp-notify'; 6 | import * as rename from 'gulp-rename'; 7 | import * as ts from 'gulp-typescript'; 8 | import * as project from '../aurelia.json'; 9 | import {CLIOptions, build} from 'aurelia-cli'; 10 | import * as eventStream from 'event-stream'; 11 | 12 | function configureEnvironment() { 13 | let env = CLIOptions.getEnvironment(); 14 | 15 | return gulp.src(`aurelia_project/environments/${env}.ts`) 16 | .pipe(changedInPlace({firstPass:true})) 17 | .pipe(rename('environment.ts')) 18 | .pipe(gulp.dest(project.paths.root)); 19 | } 20 | 21 | var typescriptCompiler = typescriptCompiler || null; 22 | 23 | function buildTypeScript() { 24 | if(!typescriptCompiler) { 25 | typescriptCompiler = ts.createProject('tsconfig.json', { 26 | "typescript": require('typescript') 27 | }); 28 | } 29 | 30 | let dts = gulp.src(project.transpiler.dtsSource); 31 | 32 | let src = gulp.src(project.transpiler.source) 33 | .pipe(changedInPlace({firstPass: true})); 34 | 35 | return eventStream.merge(dts, src) 36 | .pipe(plumber({ errorHandler: notify.onError('Error: <%= error.message %>') })) 37 | .pipe(sourcemaps.init()) 38 | .pipe(ts(typescriptCompiler)) 39 | .pipe(build.bundle()); 40 | } 41 | 42 | export default gulp.series( 43 | configureEnvironment, 44 | buildTypeScript 45 | ); 46 | -------------------------------------------------------------------------------- /aurelia-ux-todo/aurelia_project/tasks/update-ux.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | 4 | function mkdir(dir) { 5 | // making directory without exception if exists 6 | try { 7 | fs.mkdirSync(dir); 8 | } catch(e) { 9 | if(e.code != "EEXIST") { 10 | throw e; 11 | } 12 | } 13 | }; 14 | 15 | function copyDir(src, dest) { 16 | try{ 17 | mkdir(dest); 18 | let files = fs.readdirSync(src); 19 | for(let i = 0; i < files.length; i++) { 20 | let current = fs.lstatSync(path.join(src, files[i])); 21 | if(current.isDirectory()) { 22 | copyDir(path.join(src, files[i]), path.join(dest, files[i])); 23 | } else if(current.isSymbolicLink()) { 24 | let symlink = fs.readlinkSync(path.join(src, files[i])); 25 | fs.symlinkSync(symlink, path.join(dest, files[i])); 26 | } else { 27 | copy(path.join(src, files[i]), path.join(dest, files[i])); 28 | } 29 | } 30 | } catch(error){ 31 | console.log(error); 32 | } 33 | }; 34 | 35 | function copy(src, dest) { 36 | var oldFile = fs.createReadStream(src); 37 | var newFile = fs.createWriteStream(dest); 38 | console.log(`Copying from ${src} to ${dest}.`); 39 | oldFile.pipe(newFile); 40 | }; 41 | 42 | export default function updateUX() { 43 | copyDir('../ux/dist/amd', './node_modules/aurelia-ux/dist/amd/') 44 | } 45 | -------------------------------------------------------------------------------- /aurelia-ux-todo/custom_typings/aurelia-protractor.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Aurelia Protractor extensions 2 | // Project: https://github.com/aurelia/skeleton-navigation 3 | // Definitions by: Enrapt , Kirill Grishin 4 | 5 | // Extend existing interfaces with additional functionality from Aurelia Protractor Extender (aurelia.protractor.js) 6 | 7 | declare module protractor { 8 | interface IBrowser extends protractor.Protractor { 9 | loadAndWaitForAureliaPage(url: string): protractor.Protractor; 10 | waitForRouterComplete(); 11 | } 12 | 13 | interface IProtractorLocatorStrategy { 14 | valueBind(bindTarget: string): webdriver.Locator; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /aurelia-ux-todo/favicon.ico: -------------------------------------------------------------------------------- 1 | �PNG 2 |  3 | IHDR szz�bKGD�C� pHYs  �� vpAg ����TIDATXå�y�W��?���[�u�Pk��K�4�օ��AVqXZ6Q���Z�*��-BEaA�"��*�� mSMm�Xm�E�����03�w��?���Y=�ͽ����~��{ν�]T����f������*�p�1k��xd���}��n��x��M\��MT�x�g�����{��H�]g j: 8b���v�uޠ+�,��v�;fm��fm�#��G�;�x�ƈ�i!,i��t�ڳ\��>�1!�+��ܐ�M`{� �US7WBP�yM��w�Zu� ���x��������qk�8���5�\0��IS���žZJ7������&j��������Vwv��;b��2f[���;Pۢ�ϝQY�9j��X9�bǔO�R`v� 4 | p�=�7�^�y���O=�BsZ�M�c���Eg���|��P��k+�}�~�;V�e(@D ���̮Zq �cvՊ^��"�\F���Ӏor�vS�5I.�i����rͤ��O��r���;ܿ2��-���[� �4\���Y��������]k��AZrh�P�h�h�>��C��;�=�~������e���W�VN�.�O�aA��i��1�]s��Y�N`:pЧ�Y�džo��j��>�]֧��1�1�p.���n���*��|p�"�B�r(eu�V�e~D N�U��'=�o*��C�[�ՎX���%�����oN�}�4@b7�rvh�5|TY��})�X��@$BN�ȭ y� ��ƚ�m�ޱ�{M��e��.x_,&�׎�d{����)}>��&��/z��-U1�bL�59���������U����և\�����Y���5��؈�9�w��������Qa̠�S����祇��ݪ�R� y��=������-o�pH>;�,Ag�� r�ܵ#�9f n���r�� �Z?-��Z5���'� �3�0q��ò�RcI��Y��(|�X�'����,�o�w�[����O 2 | 3 | 4 | 5 | 6 | Aurelia 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /aurelia-ux-todo/karma.conf.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const path = require('path'); 3 | const project = require('./aurelia_project/aurelia.json'); 4 | const tsconfig = require('./tsconfig.json'); 5 | 6 | let testSrc = [ 7 | { pattern: project.unitTestRunner.source, included: false }, 8 | 'test/aurelia-karma.js' 9 | ]; 10 | 11 | let output = project.platform.output; 12 | let appSrc = project.build.bundles.map(x => path.join(output, x.name)); 13 | let entryIndex = appSrc.indexOf(path.join(output, project.build.loader.configTarget)); 14 | let entryBundle = appSrc.splice(entryIndex, 1)[0]; 15 | let files = [entryBundle].concat(testSrc).concat(appSrc); 16 | 17 | module.exports = function(config) { 18 | config.set({ 19 | basePath: '', 20 | frameworks: [project.testFramework.id], 21 | files: files, 22 | exclude: [], 23 | preprocessors: { 24 | [project.unitTestRunner.source]: [project.transpiler.id] 25 | }, 26 | typescriptPreprocessor: { 27 | typescript: require('typescript'), 28 | options: tsconfig.compilerOptions 29 | }, 30 | reporters: ['progress'], 31 | port: 9876, 32 | colors: true, 33 | logLevel: config.LOG_INFO, 34 | autoWatch: true, 35 | browsers: ['Chrome'], 36 | singleRun: false, 37 | // client.args must be a array of string. 38 | // Leave 'aurelia-root', project.paths.root in this order so we can find 39 | // the root of the aurelia project. 40 | client: { 41 | args: ['aurelia-root', project.paths.root] 42 | } 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /aurelia-ux-todo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-ux-showcase", 3 | "description": "An Aurelia client application.", 4 | "version": "0.1.0", 5 | "repository": { 6 | "type": "???", 7 | "url": "???" 8 | }, 9 | "scripts": { 10 | "dev": "au run --watch", 11 | "test": "au test" 12 | }, 13 | "license": "MIT", 14 | "dependencies": { 15 | "aurelia-animator-css": "^1.0.0", 16 | "aurelia-bootstrapper": "^1.0.0", 17 | "aurelia-fetch-client": "^1.0.0", 18 | "aurelia-ux": "^0.2.0", 19 | "aurelia-validation": "^1.1.1", 20 | "bluebird": "^3.4.1" 21 | }, 22 | "peerDependencies": {}, 23 | "devDependencies": { 24 | "aurelia-cli": "^0.21.0", 25 | "aurelia-testing": "^1.0.0-beta.2.0.0", 26 | "aurelia-tools": "^0.2.2", 27 | "browser-sync": "^2.13.0", 28 | "connect-history-api-fallback": "^1.2.0", 29 | "gulp": "github:gulpjs/gulp#4.0", 30 | "gulp-changed-in-place": "^2.0.3", 31 | "gulp-plumber": "^1.1.0", 32 | "gulp-rename": "^1.2.2", 33 | "gulp-sourcemaps": "^2.0.0-alpha", 34 | "gulp-notify": "^2.2.0", 35 | "minimatch": "^3.0.2", 36 | "through2": "^2.0.1", 37 | "uglify-js": "^2.6.3", 38 | "vinyl-fs": "^2.4.3", 39 | "event-stream": "^3.3.3", 40 | "gulp-typescript": "^2.13.6", 41 | "gulp-tslint": "^5.0.0", 42 | "tslint": "^3.11.0", 43 | "typescript": ">=1.9.0-dev || ^2.0.0", 44 | "typings": "^1.3.0", 45 | "jasmine-core": "^2.4.1", 46 | "karma": "^0.13.22", 47 | "karma-chrome-launcher": "^1.0.1", 48 | "karma-jasmine": "^1.0.2", 49 | "karma-typescript-preprocessor": "^0.2.1" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /aurelia-ux-todo/scripts/require.js: -------------------------------------------------------------------------------- 1 | /* 2 | RequireJS 2.2.0 Copyright jQuery Foundation and other contributors. 3 | Released under MIT license, http://github.com/requirejs/requirejs/LICENSE 4 | */ 5 | var requirejs,require,define; 6 | (function(ga){function ka(b,c,d,g){return g||""}function K(b){return"[object Function]"===Q.call(b)}function L(b){return"[object Array]"===Q.call(b)}function y(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(K(k)){if(this.events.error&&this.map.isDefine||g.onError!== 18 | ha)try{h=l.execCb(c,k,b,h)}catch(d){a=d}else h=l.execCb(c,k,b,h);this.map.isDefine&&void 0===h&&((b=this.module)?h=b.exports:this.usingExports&&(h=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",A(this.error=a)}else h=k;this.exports=h;if(this.map.isDefine&&!this.ignore&&(v[c]=h,g.onResourceLoad)){var f=[];y(this.depMaps,function(a){f.push(a.normalizedMap||a)});g.onResourceLoad(l,this.map,f)}C(c); 19 | this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}},callPlugin:function(){var a=this.map,b=a.id,d=q(a.prefix);this.depMaps.push(d);w(d,"defined",z(this,function(h){var k,f,d=e(fa,this.map.id),M=this.map.name,r=this.map.parentMap?this.map.parentMap.name:null,m=l.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(h.normalize&&(M=h.normalize(M,function(a){return c(a,r,!0)})|| 20 | ""),f=q(a.prefix+"!"+M,this.map.parentMap),w(f,"defined",z(this,function(a){this.map.normalizedMap=f;this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),h=e(t,f.id)){this.depMaps.push(f);if(this.events.error)h.on("error",z(this,function(a){this.emit("error",a)}));h.enable()}}else d?(this.map.url=l.nameToUrl(d),this.load()):(k=z(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),k.error=z(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];D(t,function(a){0=== 21 | a.map.id.indexOf(b+"_unnormalized")&&C(a.map.id)});A(a)}),k.fromText=z(this,function(h,c){var d=a.name,f=q(d),M=S;c&&(h=c);M&&(S=!1);u(f);x(p.config,b)&&(p.config[d]=p.config[b]);try{g.exec(h)}catch(e){return A(F("fromtexteval","fromText eval for "+b+" failed: "+e,e,[b]))}M&&(S=!0);this.depMaps.push(f);l.completeLoad(d);m([d],k)}),h.load(a.name,m,k,p))}));l.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){Z[this.map.id]=this;this.enabling=this.enabled=!0;y(this.depMaps,z(this,function(a, 22 | b){var c,h;if("string"===typeof a){a=q(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=e(R,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;w(a,"defined",z(this,function(a){this.undefed||(this.defineDep(b,a),this.check())}));this.errback?w(a,"error",z(this,this.errback)):this.events.error&&w(a,"error",z(this,function(a){this.emit("error",a)}))}c=a.id;h=t[c];x(R,c)||!h||h.enabled||l.enable(a,this)}));D(this.pluginMaps,z(this,function(a){var b=e(t,a.id); 23 | b&&!b.enabled&&l.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){y(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};l={config:p,contextName:b,registry:t,defined:v,urlFetched:W,defQueue:G,defQueueMap:{},Module:da,makeModuleMap:q,nextTick:g.nextTick,onError:A,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");if("string"===typeof a.urlArgs){var b= 24 | a.urlArgs;a.urlArgs=function(a,c){return(-1===c.indexOf("?")?"?":"&")+b}}var c=p.shim,h={paths:!0,bundles:!0,config:!0,map:!0};D(a,function(a,b){h[b]?(p[b]||(p[b]={}),Y(p[b],a,!0,!0)):p[b]=a});a.bundles&&D(a.bundles,function(a,b){y(a,function(a){a!==b&&(fa[a]=b)})});a.shim&&(D(a.shim,function(a,b){L(a)&&(a={deps:a});!a.exports&&!a.init||a.exportsFn||(a.exportsFn=l.makeShimExports(a));c[b]=a}),p.shim=c);a.packages&&y(a.packages,function(a){var b;a="string"===typeof a?{name:a}:a;b=a.name;a.location&& 25 | (p.paths[b]=a.location);p.pkgs[b]=a.name+"/"+(a.main||"main").replace(na,"").replace(U,"")});D(t,function(a,b){a.inited||a.map.unnormalized||(a.map=q(b,null,!0))});(a.deps||a.callback)&&l.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ga,arguments));return b||a.exports&&ia(a.exports)}},makeRequire:function(a,n){function m(c,d,f){var e,r;n.enableBuildCallback&&d&&K(d)&&(d.__requireJsBuild=!0);if("string"===typeof c){if(K(d))return A(F("requireargs", 26 | "Invalid require call"),f);if(a&&x(R,c))return R[c](t[a.id]);if(g.get)return g.get(l,c,a,m);e=q(c,a,!1,!0);e=e.id;return x(v,e)?v[e]:A(F("notloaded",'Module name "'+e+'" has not been loaded yet for context: '+b+(a?"":". Use require([])")))}P();l.nextTick(function(){P();r=u(q(null,a));r.skipMap=n.skipMap;r.init(c,d,f,{enabled:!0});H()});return m}n=n||{};Y(m,{isBrowser:E,toUrl:function(b){var d,f=b.lastIndexOf("."),g=b.split("/")[0];-1!==f&&("."!==g&&".."!==g||1e.attachEvent.toString().indexOf("[native code")||ca?(e.addEventListener("load",b.onScriptLoad,!1),e.addEventListener("error",b.onScriptError,!1)):(S=!0,e.attachEvent("onreadystatechange",b.onScriptLoad));e.src=d;if(m.onNodeCreated)m.onNodeCreated(e,m,c,d);P=e;H?C.insertBefore(e,H):C.appendChild(e);P=null;return e}if(ja)try{setTimeout(function(){}, 35 | 0),importScripts(d),b.completeLoad(c)}catch(q){b.onError(F("importscripts","importScripts failed for "+c+" at "+d,q,[c]))}};E&&!w.skipDataMain&&X(document.getElementsByTagName("script"),function(b){C||(C=b.parentNode);if(O=b.getAttribute("data-main"))return u=O,w.baseUrl||-1!==u.indexOf("!")||(I=u.split("/"),u=I.pop(),T=I.length?I.join("/")+"/":"./",w.baseUrl=T),u=u.replace(U,""),g.jsExtRegExp.test(u)&&(u=O),w.deps=w.deps?w.deps.concat(u):[u],!0});define=function(b,c,d){var e,g;"string"!==typeof b&& 36 | (d=c,c=b,b=null);L(c)||(d=c,c=null);!c&&K(d)&&(c=[],d.length&&(d.toString().replace(qa,ka).replace(ra,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));S&&(e=P||pa())&&(b||(b=e.getAttribute("data-requiremodule")),g=J[e.getAttribute("data-requirecontext")]);g?(g.defQueue.push([b,c,d]),g.defQueueMap[b]=!0):V.push([b,c,d])};define.amd={jQuery:!0};g.exec=function(b){return eval(b)};g(w)}})(this); 37 | -------------------------------------------------------------------------------- /aurelia-ux-todo/scripts/text.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license RequireJS text 2.0.14 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved. 3 | * Available via the MIT or new BSD license. 4 | * see: http://github.com/requirejs/text for details 5 | */ 6 | /*jslint regexp: true */ 7 | /*global require, XMLHttpRequest, ActiveXObject, 8 | define, window, process, Packages, 9 | java, location, Components, FileUtils */ 10 | 11 | define(['module'], function (module) { 12 | 'use strict'; 13 | 14 | var text, fs, Cc, Ci, xpcIsWindows, 15 | progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], 16 | xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, 17 | bodyRegExp = /]*>\s*([\s\S]+)\s*<\/body>/im, 18 | hasLocation = typeof location !== 'undefined' && location.href, 19 | defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''), 20 | defaultHostName = hasLocation && location.hostname, 21 | defaultPort = hasLocation && (location.port || undefined), 22 | buildMap = {}, 23 | masterConfig = (module.config && module.config()) || {}; 24 | 25 | text = { 26 | version: '2.0.14', 27 | 28 | strip: function (content) { 29 | //Strips declarations so that external SVG and XML 30 | //documents can be added to a document without worry. Also, if the string 31 | //is an HTML document, only the part inside the body tag is returned. 32 | if (content) { 33 | content = content.replace(xmlRegExp, ""); 34 | var matches = content.match(bodyRegExp); 35 | if (matches) { 36 | content = matches[1]; 37 | } 38 | } else { 39 | content = ""; 40 | } 41 | return content; 42 | }, 43 | 44 | jsEscape: function (content) { 45 | return content.replace(/(['\\])/g, '\\$1') 46 | .replace(/[\f]/g, "\\f") 47 | .replace(/[\b]/g, "\\b") 48 | .replace(/[\n]/g, "\\n") 49 | .replace(/[\t]/g, "\\t") 50 | .replace(/[\r]/g, "\\r") 51 | .replace(/[\u2028]/g, "\\u2028") 52 | .replace(/[\u2029]/g, "\\u2029"); 53 | }, 54 | 55 | createXhr: masterConfig.createXhr || function () { 56 | //Would love to dump the ActiveX crap in here. Need IE 6 to die first. 57 | var xhr, i, progId; 58 | if (typeof XMLHttpRequest !== "undefined") { 59 | return new XMLHttpRequest(); 60 | } else if (typeof ActiveXObject !== "undefined") { 61 | for (i = 0; i < 3; i += 1) { 62 | progId = progIds[i]; 63 | try { 64 | xhr = new ActiveXObject(progId); 65 | } catch (e) {} 66 | 67 | if (xhr) { 68 | progIds = [progId]; // so faster next time 69 | break; 70 | } 71 | } 72 | } 73 | 74 | return xhr; 75 | }, 76 | 77 | /** 78 | * Parses a resource name into its component parts. Resource names 79 | * look like: module/name.ext!strip, where the !strip part is 80 | * optional. 81 | * @param {String} name the resource name 82 | * @returns {Object} with properties "moduleName", "ext" and "strip" 83 | * where strip is a boolean. 84 | */ 85 | parseName: function (name) { 86 | var modName, ext, temp, 87 | strip = false, 88 | index = name.lastIndexOf("."), 89 | isRelative = name.indexOf('./') === 0 || 90 | name.indexOf('../') === 0; 91 | 92 | if (index !== -1 && (!isRelative || index > 1)) { 93 | modName = name.substring(0, index); 94 | ext = name.substring(index + 1); 95 | } else { 96 | modName = name; 97 | } 98 | 99 | temp = ext || modName; 100 | index = temp.indexOf("!"); 101 | if (index !== -1) { 102 | //Pull off the strip arg. 103 | strip = temp.substring(index + 1) === "strip"; 104 | temp = temp.substring(0, index); 105 | if (ext) { 106 | ext = temp; 107 | } else { 108 | modName = temp; 109 | } 110 | } 111 | 112 | return { 113 | moduleName: modName, 114 | ext: ext, 115 | strip: strip 116 | }; 117 | }, 118 | 119 | xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/, 120 | 121 | /** 122 | * Is an URL on another domain. Only works for browser use, returns 123 | * false in non-browser environments. Only used to know if an 124 | * optimized .js version of a text resource should be loaded 125 | * instead. 126 | * @param {String} url 127 | * @returns Boolean 128 | */ 129 | useXhr: function (url, protocol, hostname, port) { 130 | var uProtocol, uHostName, uPort, 131 | match = text.xdRegExp.exec(url); 132 | if (!match) { 133 | return true; 134 | } 135 | uProtocol = match[2]; 136 | uHostName = match[3]; 137 | 138 | uHostName = uHostName.split(':'); 139 | uPort = uHostName[1]; 140 | uHostName = uHostName[0]; 141 | 142 | return (!uProtocol || uProtocol === protocol) && 143 | (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) && 144 | ((!uPort && !uHostName) || uPort === port); 145 | }, 146 | 147 | finishLoad: function (name, strip, content, onLoad) { 148 | content = strip ? text.strip(content) : content; 149 | if (masterConfig.isBuild) { 150 | buildMap[name] = content; 151 | } 152 | onLoad(content); 153 | }, 154 | 155 | load: function (name, req, onLoad, config) { 156 | //Name has format: some.module.filext!strip 157 | //The strip part is optional. 158 | //if strip is present, then that means only get the string contents 159 | //inside a body tag in an HTML string. For XML/SVG content it means 160 | //removing the declarations so the content can be inserted 161 | //into the current doc without problems. 162 | 163 | // Do not bother with the work if a build and text will 164 | // not be inlined. 165 | if (config && config.isBuild && !config.inlineText) { 166 | onLoad(); 167 | return; 168 | } 169 | 170 | masterConfig.isBuild = config && config.isBuild; 171 | 172 | var parsed = text.parseName(name), 173 | nonStripName = parsed.moduleName + 174 | (parsed.ext ? '.' + parsed.ext : ''), 175 | url = req.toUrl(nonStripName), 176 | useXhr = (masterConfig.useXhr) || 177 | text.useXhr; 178 | 179 | // Do not load if it is an empty: url 180 | if (url.indexOf('empty:') === 0) { 181 | onLoad(); 182 | return; 183 | } 184 | 185 | //Load the text. Use XHR if possible and in a browser. 186 | if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) { 187 | text.get(url, function (content) { 188 | text.finishLoad(name, parsed.strip, content, onLoad); 189 | }, function (err) { 190 | if (onLoad.error) { 191 | onLoad.error(err); 192 | } 193 | }); 194 | } else { 195 | //Need to fetch the resource across domains. Assume 196 | //the resource has been optimized into a JS module. Fetch 197 | //by the module name + extension, but do not include the 198 | //!strip part to avoid file system issues. 199 | req([nonStripName], function (content) { 200 | text.finishLoad(parsed.moduleName + '.' + parsed.ext, 201 | parsed.strip, content, onLoad); 202 | }); 203 | } 204 | }, 205 | 206 | write: function (pluginName, moduleName, write, config) { 207 | if (buildMap.hasOwnProperty(moduleName)) { 208 | var content = text.jsEscape(buildMap[moduleName]); 209 | write.asModule(pluginName + "!" + moduleName, 210 | "define(function () { return '" + 211 | content + 212 | "';});\n"); 213 | } 214 | }, 215 | 216 | writeFile: function (pluginName, moduleName, req, write, config) { 217 | var parsed = text.parseName(moduleName), 218 | extPart = parsed.ext ? '.' + parsed.ext : '', 219 | nonStripName = parsed.moduleName + extPart, 220 | //Use a '.js' file name so that it indicates it is a 221 | //script that can be loaded across domains. 222 | fileName = req.toUrl(parsed.moduleName + extPart) + '.js'; 223 | 224 | //Leverage own load() method to load plugin value, but only 225 | //write out values that do not have the strip argument, 226 | //to avoid any potential issues with ! in file names. 227 | text.load(nonStripName, req, function (value) { 228 | //Use own write() method to construct full module value. 229 | //But need to create shell that translates writeFile's 230 | //write() to the right interface. 231 | var textWrite = function (contents) { 232 | return write(fileName, contents); 233 | }; 234 | textWrite.asModule = function (moduleName, contents) { 235 | return write.asModule(moduleName, fileName, contents); 236 | }; 237 | 238 | text.write(pluginName, nonStripName, textWrite, config); 239 | }, config); 240 | } 241 | }; 242 | 243 | if (masterConfig.env === 'node' || (!masterConfig.env && 244 | typeof process !== "undefined" && 245 | process.versions && 246 | !!process.versions.node && 247 | !process.versions['node-webkit'] && 248 | !process.versions['atom-shell'])) { 249 | //Using special require.nodeRequire, something added by r.js. 250 | fs = require.nodeRequire('fs'); 251 | 252 | text.get = function (url, callback, errback) { 253 | try { 254 | var file = fs.readFileSync(url, 'utf8'); 255 | //Remove BOM (Byte Mark Order) from utf8 files if it is there. 256 | if (file[0] === '\uFEFF') { 257 | file = file.substring(1); 258 | } 259 | callback(file); 260 | } catch (e) { 261 | if (errback) { 262 | errback(e); 263 | } 264 | } 265 | }; 266 | } else if (masterConfig.env === 'xhr' || (!masterConfig.env && 267 | text.createXhr())) { 268 | text.get = function (url, callback, errback, headers) { 269 | var xhr = text.createXhr(), header; 270 | xhr.open('GET', url, true); 271 | 272 | //Allow plugins direct access to xhr headers 273 | if (headers) { 274 | for (header in headers) { 275 | if (headers.hasOwnProperty(header)) { 276 | xhr.setRequestHeader(header.toLowerCase(), headers[header]); 277 | } 278 | } 279 | } 280 | 281 | //Allow overrides specified in config 282 | if (masterConfig.onXhr) { 283 | masterConfig.onXhr(xhr, url); 284 | } 285 | 286 | xhr.onreadystatechange = function (evt) { 287 | var status, err; 288 | //Do not explicitly handle errors, those should be 289 | //visible via console output in the browser. 290 | if (xhr.readyState === 4) { 291 | status = xhr.status || 0; 292 | if (status > 399 && status < 600) { 293 | //An http 4xx or 5xx error. Signal an error. 294 | err = new Error(url + ' HTTP status: ' + status); 295 | err.xhr = xhr; 296 | if (errback) { 297 | errback(err); 298 | } 299 | } else { 300 | callback(xhr.responseText); 301 | } 302 | 303 | if (masterConfig.onXhrComplete) { 304 | masterConfig.onXhrComplete(xhr, url); 305 | } 306 | } 307 | }; 308 | xhr.send(null); 309 | }; 310 | } else if (masterConfig.env === 'rhino' || (!masterConfig.env && 311 | typeof Packages !== 'undefined' && typeof java !== 'undefined')) { 312 | //Why Java, why is this so awkward? 313 | text.get = function (url, callback) { 314 | var stringBuffer, line, 315 | encoding = "utf-8", 316 | file = new java.io.File(url), 317 | lineSeparator = java.lang.System.getProperty("line.separator"), 318 | input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), 319 | content = ''; 320 | try { 321 | stringBuffer = new java.lang.StringBuffer(); 322 | line = input.readLine(); 323 | 324 | // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 325 | // http://www.unicode.org/faq/utf_bom.html 326 | 327 | // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: 328 | // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 329 | if (line && line.length() && line.charAt(0) === 0xfeff) { 330 | // Eat the BOM, since we've already found the encoding on this file, 331 | // and we plan to concatenating this buffer with others; the BOM should 332 | // only appear at the top of a file. 333 | line = line.substring(1); 334 | } 335 | 336 | if (line !== null) { 337 | stringBuffer.append(line); 338 | } 339 | 340 | while ((line = input.readLine()) !== null) { 341 | stringBuffer.append(lineSeparator); 342 | stringBuffer.append(line); 343 | } 344 | //Make sure we return a JavaScript string and not a Java string. 345 | content = String(stringBuffer.toString()); //String 346 | } finally { 347 | input.close(); 348 | } 349 | callback(content); 350 | }; 351 | } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env && 352 | typeof Components !== 'undefined' && Components.classes && 353 | Components.interfaces)) { 354 | //Avert your gaze! 355 | Cc = Components.classes; 356 | Ci = Components.interfaces; 357 | Components.utils['import']('resource://gre/modules/FileUtils.jsm'); 358 | xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc); 359 | 360 | text.get = function (url, callback) { 361 | var inStream, convertStream, fileObj, 362 | readData = {}; 363 | 364 | if (xpcIsWindows) { 365 | url = url.replace(/\//g, '\\'); 366 | } 367 | 368 | fileObj = new FileUtils.File(url); 369 | 370 | //XPCOM, you so crazy 371 | try { 372 | inStream = Cc['@mozilla.org/network/file-input-stream;1'] 373 | .createInstance(Ci.nsIFileInputStream); 374 | inStream.init(fileObj, 1, 0, false); 375 | 376 | convertStream = Cc['@mozilla.org/intl/converter-input-stream;1'] 377 | .createInstance(Ci.nsIConverterInputStream); 378 | convertStream.init(inStream, "utf-8", inStream.available(), 379 | Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); 380 | 381 | convertStream.readString(inStream.available(), readData); 382 | convertStream.close(); 383 | inStream.close(); 384 | callback(readData.value); 385 | } catch (e) { 386 | throw new Error((fileObj && fileObj.path || '') + ': ' + e); 387 | } 388 | }; 389 | } 390 | return text; 391 | }); 392 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/app.css: -------------------------------------------------------------------------------- 1 | /* From https://raw.githubusercontent.com/aurelia/app-ux-showcase/master/src/app.css */ 2 | 3 | * { 4 | box-sizing: border-box; 5 | } 6 | 7 | html, body { 8 | width: 100%; 9 | height: 100%; 10 | overflow: hidden; 11 | font-family: 'Source Sans Pro', sans-serif; 12 | } 13 | 14 | body { 15 | display: flex; 16 | flex-direction: row; 17 | } 18 | 19 | code { 20 | font-family: 'Source Code Pro', monospace; 21 | } 22 | 23 | em { 24 | font-style: italic; 25 | } 26 | 27 | styles.clickable { 28 | cursor: pointer; 29 | } 30 | 31 | styles.main { 32 | display: flex; 33 | flex-direction: column; 34 | flex: 1; 35 | } 36 | 37 | styles.header { 38 | background: ${$design.primary}; 39 | color: ${$design.primaryForeground}; 40 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26); 41 | padding: 16px; 42 | font-size: 24px; 43 | line-height: 32px; 44 | height: 64px; 45 | } 46 | 47 | styles.header-h1 { 48 | display: inline-block; 49 | } 50 | 51 | styles.header-burger { 52 | float: right; 53 | } 54 | 55 | styles.nav { 56 | width: 275px; 57 | background: ${$swatches.grey.p200}; 58 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26); 59 | 60 | display: flex; 61 | flex-direction: column; 62 | align-items: center; 63 | } 64 | 65 | styles.nav-list { 66 | align-self: stretch; 67 | margin-top: 24px; 68 | padding-top: 16px; 69 | border-top: 1px solid ${$swatches.grey.p300}; 70 | display: flex; 71 | flex-direction: column; 72 | } 73 | 74 | styles.nav-category { 75 | padding: 12px 0 12px 24px; 76 | } 77 | 78 | styles.nav-item { 79 | transition: all 300ms; 80 | } 81 | 82 | styles.nav-item:hover { 83 | background: ${$swatches.grey.p300}; 84 | } 85 | 86 | styles.nav-item > a { 87 | text-decoration: none; 88 | text-transform: uppercase; 89 | font-size: 16px; 90 | color: ${$design.primary}; 91 | display: block; 92 | transition: all 300ms; 93 | padding: 12px 0; 94 | margin-left: 24px; 95 | } 96 | 97 | styles.nav-item > a:before { 98 | content: '.'; 99 | display: inline-block; 100 | color: transparent; 101 | width: 2px; 102 | margin-right: 8px; 103 | } 104 | 105 | styles.nav-item.active > a { 106 | color: ${$design.accent}; 107 | } 108 | 109 | styles.nav-item.active > a:before { 110 | background-color: ${$design.accent}; 111 | } 112 | 113 | styles.logo { 114 | margin: 16px 0; 115 | } 116 | 117 | styles.product-name { 118 | font-size: 28px; 119 | } 120 | 121 | styles.page { 122 | overflow-y: scroll; 123 | flex: 1; 124 | } 125 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/app.html: -------------------------------------------------------------------------------- 1 | 40 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/app.ts: -------------------------------------------------------------------------------- 1 | import { AureliaUX } from 'aurelia-ux'; 2 | import { autoinject } from 'aurelia-dependency-injection'; 3 | import { routes } from './routes'; 4 | 5 | 6 | const MAIN_THEME = { 7 | primary: '#009688', 8 | accent: '#4CAF50', 9 | }; 10 | const ALTERNATE_THEME = { 11 | primary: '#4CAF50', 12 | accent: '#009688', 13 | }; 14 | 15 | @autoinject 16 | export class App { 17 | router; 18 | showNavigationMenu: Boolean; 19 | public theme: Boolean; 20 | 21 | constructor(private ux: AureliaUX) { 22 | ux.design.primary = MAIN_THEME.primary; 23 | ux.design.accent = MAIN_THEME.accent; 24 | 25 | this.showNavigationMenu = false; 26 | } 27 | 28 | configureRouter(config, router) { 29 | this.router = router; 30 | config.map(routes); 31 | } 32 | 33 | toggleNavigationMenu() { 34 | this.showNavigationMenu = !this.showNavigationMenu; 35 | } 36 | 37 | themeChanged() { 38 | if (this.theme) { 39 | this.ux.design.primary = ALTERNATE_THEME.primary; 40 | this.ux.design.accent = ALTERNATE_THEME.accent; 41 | } else { 42 | this.ux.design.primary = MAIN_THEME.primary; 43 | this.ux.design.accent = MAIN_THEME.accent; 44 | } 45 | } 46 | } 47 | 48 | 49 | export class CategoriesValueConverter { 50 | toView(navModels) { 51 | let categories = new Map(); 52 | 53 | for (let model of navModels) { 54 | let routes = categories.get(model.settings.category); 55 | 56 | if (!routes) { 57 | categories.set(model.settings.category, routes = []); 58 | } 59 | 60 | routes.push(model); 61 | } 62 | 63 | return categories; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/common.css: -------------------------------------------------------------------------------- 1 | /* From https://github.com/aurelia/app-ux-showcase/blob/master/src/common.css */ 2 | 3 | styles.main { 4 | padding: 40px 40px 40px; 5 | } 6 | 7 | styles.header { 8 | font-size: 34px; 9 | font-weight: 400; 10 | line-height: 32px; 11 | margin-bottom: 30px; 12 | color: ${$design.primary}; 13 | } 14 | 15 | styles.description { 16 | font-size: 20px; 17 | font-weight: 400; 18 | line-height: 32px; 19 | max-width: 940px; 20 | color: ${$swatches.black}; 21 | margin-bottom: 40px; 22 | } 23 | 24 | styles.alignright { 25 | text-align: right; 26 | } 27 | 28 | styles.center { 29 | text-align: center; 30 | } 31 | 32 | styles.todo { 33 | border-bottom: gray solid; 34 | border-width: 1px; 35 | padding-bottom: 15px; 36 | padding-top: 15px; 37 | } 38 | 39 | button { 40 | cursor: pointer; 41 | } 42 | 43 | .done { 44 | text-decoration: line-through; 45 | } 46 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/environment.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | debug: true, 3 | testing: true 4 | }; 5 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/main.ts: -------------------------------------------------------------------------------- 1 | import { Aurelia } from 'aurelia-framework' 2 | import environment from './environment'; 3 | 4 | //Configure Bluebird Promises. 5 | (Promise).config({ 6 | warnings: { 7 | wForgottenReturn: false 8 | } 9 | }); 10 | 11 | export function configure(aurelia: Aurelia) { 12 | aurelia.use 13 | .standardConfiguration() 14 | .plugin('aurelia-validation') 15 | .plugin('aurelia-ux'); 16 | 17 | if (environment.debug) { 18 | aurelia.use.developmentLogging(); 19 | } 20 | 21 | if (environment.testing) { 22 | aurelia.use.plugin('aurelia-testing'); 23 | } 24 | 25 | aurelia.start().then(() => aurelia.setRoot()); 26 | } 27 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/models/todo.ts: -------------------------------------------------------------------------------- 1 | export class Todo { 2 | id: number; 3 | title: string; 4 | description: string; 5 | done: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/pages/edit.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/pages/edit.ts: -------------------------------------------------------------------------------- 1 | import { autoinject } from 'aurelia-framework'; 2 | import { Router } from 'aurelia-router'; 3 | import { 4 | Validator, 5 | ValidationController, 6 | ValidationControllerFactory, 7 | ValidationRules, 8 | validateTrigger, 9 | } from 'aurelia-validation'; 10 | 11 | import { Todo } from '../models/todo'; 12 | import { Storage } from '../services/storage'; 13 | 14 | 15 | @autoinject 16 | export class Add { 17 | public todo: Todo; 18 | public canSave: Boolean; 19 | private controller: ValidationController; 20 | 21 | constructor(private router: Router, private storage: Storage, private validator: Validator, controllerFactory: ValidationControllerFactory) { 22 | this.controller = controllerFactory.createForCurrentScope(validator); 23 | this.controller.validateTrigger = validateTrigger.changeOrBlur; 24 | this.controller.subscribe(event => this.validateWhole()); 25 | } 26 | 27 | private validateWhole() { 28 | this.validator.validateObject(this.todo) 29 | .then(results => this.canSave = results.every(result => result.valid)); 30 | } 31 | 32 | public activate(params) { 33 | if (params.id) { 34 | this.todo = this.storage.getTodo(params.id); 35 | } else { 36 | this.todo = new Todo(); 37 | } 38 | 39 | this.setupValidation(); 40 | } 41 | 42 | public setupValidation() { 43 | ValidationRules 44 | .ensure('title').required().minLength(3).withMessage('Title must at least be 3 chars long.') 45 | .ensure('description').required().minLength(3).withMessage('Description must at least be 3 chars long.') 46 | .on(this.todo); 47 | } 48 | 49 | public save() { 50 | if (!this.canSave) { 51 | return; 52 | } 53 | 54 | this.storage.saveTodo(this.todo); 55 | this.router.navigateToRoute('list'); 56 | } 57 | 58 | public cancel() { 59 | this.router.navigateToRoute('list'); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/pages/list.html: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/pages/list.ts: -------------------------------------------------------------------------------- 1 | import { Todo } from '../models/todo'; 2 | import { Storage } from '../services/storage'; 3 | import { autoinject } from 'aurelia-framework'; 4 | import { Router } from 'aurelia-router'; 5 | 6 | 7 | @autoinject 8 | export class List { 9 | public todos: Todo[]; 10 | 11 | constructor(private storage: Storage, private router: Router) { 12 | this.todos = this.storage.getTodos(); 13 | } 14 | 15 | public viewTodo(todo: Todo) { 16 | this.router.navigateToRoute('edit', {id: todo.id}); 17 | } 18 | 19 | public addTodo() { 20 | this.router.navigate('/add'); 21 | } 22 | 23 | toggleDone(todo: Todo) { 24 | if (todo.done) { 25 | todo.done = false; 26 | } else { 27 | todo.done = true; 28 | } 29 | 30 | this.storage.saveTodo(todo); 31 | } 32 | } -------------------------------------------------------------------------------- /aurelia-ux-todo/src/reset.css: -------------------------------------------------------------------------------- 1 | /* From https://github.com/aurelia/app-ux-showcase/blob/master/src/reset.css */ 2 | 3 | /* http://meyerweb.com/eric/tools/css/reset/ 4 | v2.0 | 20110126 5 | License: none (public domain) 6 | */ 7 | 8 | html, body, div, span, applet, object, iframe, 9 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 10 | a, abbr, acronym, address, big, cite, code, 11 | del, dfn, em, img, ins, kbd, q, s, samp, 12 | small, strike, strong, sub, sup, tt, var, 13 | b, u, i, center, 14 | dl, dt, dd, ol, ul, li, 15 | fieldset, form, label, legend, 16 | table, caption, tbody, tfoot, thead, tr, th, td, 17 | article, aside, canvas, details, embed, 18 | figure, figcaption, footer, header, hgroup, 19 | menu, nav, output, ruby, section, summary, 20 | time, mark, audio, video { 21 | margin: 0; 22 | padding: 0; 23 | border: 0; 24 | font-size: 100%; 25 | font: inherit; 26 | vertical-align: baseline; 27 | } 28 | /* HTML5 display-role reset for older browsers */ 29 | article, aside, details, figcaption, figure, 30 | footer, header, hgroup, menu, nav, section { 31 | display: block; 32 | } 33 | body { 34 | line-height: 1; 35 | } 36 | ol, ul { 37 | list-style: none; 38 | } 39 | blockquote, q { 40 | quotes: none; 41 | } 42 | blockquote:before, blockquote:after, 43 | q:before, q:after { 44 | content: ''; 45 | content: none; 46 | } 47 | table { 48 | border-collapse: collapse; 49 | border-spacing: 0; 50 | } 51 | 52 | /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */ 53 | 54 | /* Document 55 | ========================================================================== */ 56 | 57 | /** 58 | * 1. Change the default font family in all browsers (opinionated). 59 | * 2. Correct the line height in all browsers. 60 | * 3. Prevent adjustments of font size after orientation changes in 61 | * IE on Windows Phone and in iOS. 62 | */ 63 | 64 | html { 65 | font-family: sans-serif; /* 1 */ 66 | line-height: 1.15; /* 2 */ 67 | -ms-text-size-adjust: 100%; /* 3 */ 68 | -webkit-text-size-adjust: 100%; /* 3 */ 69 | } 70 | 71 | /* Forms 72 | ========================================================================== */ 73 | 74 | /** 75 | * 1. Change the font styles in all browsers (opinionated). 76 | * 2. Remove the margin in Firefox and Safari. 77 | */ 78 | 79 | button, 80 | input, 81 | optgroup, 82 | select, 83 | textarea { 84 | font-family: sans-serif; /* 1 */ 85 | font-size: 100%; /* 1 */ 86 | line-height: 1.15; /* 1 */ 87 | margin: 0; /* 2 */ 88 | } 89 | 90 | /** 91 | * Show the overflow in IE. 92 | * 1. Show the overflow in Edge. 93 | */ 94 | 95 | button, 96 | input { /* 1 */ 97 | overflow: visible; 98 | } 99 | 100 | /** 101 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 102 | * 1. Remove the inheritance of text transform in Firefox. 103 | */ 104 | 105 | button, 106 | select { /* 1 */ 107 | text-transform: none; 108 | } 109 | 110 | /** 111 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 112 | * controls in Android 4. 113 | * 2. Correct the inability to style clickable types in iOS and Safari. 114 | */ 115 | 116 | button, 117 | html [type="button"], /* 1 */ 118 | [type="reset"], 119 | [type="submit"] { 120 | -webkit-appearance: button; /* 2 */ 121 | } 122 | 123 | /** 124 | * Remove the inner border and padding in Firefox. 125 | */ 126 | 127 | button::-moz-focus-inner, 128 | [type="button"]::-moz-focus-inner, 129 | [type="reset"]::-moz-focus-inner, 130 | [type="submit"]::-moz-focus-inner { 131 | border-style: none; 132 | padding: 0; 133 | } 134 | 135 | /** 136 | * Restore the focus styles unset by the previous rule. 137 | */ 138 | 139 | button:-moz-focusring, 140 | [type="button"]:-moz-focusring, 141 | [type="reset"]:-moz-focusring, 142 | [type="submit"]:-moz-focusring { 143 | outline: 1px dotted ButtonText; 144 | } 145 | 146 | /** 147 | * Change the border, margin, and padding in all browsers (opinionated). 148 | */ 149 | 150 | fieldset { 151 | border: 1px solid #c0c0c0; 152 | margin: 0 2px; 153 | padding: 0.35em 0.625em 0.75em; 154 | } 155 | 156 | /** 157 | * 1. Correct the text wrapping in Edge and IE. 158 | * 2. Correct the color inheritance from `fieldset` elements in IE. 159 | * 3. Remove the padding so developers are not caught out when they zero out 160 | * `fieldset` elements in all browsers. 161 | */ 162 | 163 | legend { 164 | box-sizing: border-box; /* 1 */ 165 | color: inherit; /* 2 */ 166 | display: table; /* 1 */ 167 | max-width: 100%; /* 1 */ 168 | padding: 0; /* 3 */ 169 | white-space: normal; /* 1 */ 170 | } 171 | 172 | /** 173 | * 1. Add the correct display in IE 9-. 174 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. 175 | */ 176 | 177 | progress { 178 | display: inline-block; /* 1 */ 179 | vertical-align: baseline; /* 2 */ 180 | } 181 | 182 | /** 183 | * Remove the default vertical scrollbar in IE. 184 | */ 185 | 186 | textarea { 187 | overflow: auto; 188 | } 189 | 190 | /** 191 | * 1. Add the correct box sizing in IE 10-. 192 | * 2. Remove the padding in IE 10-. 193 | */ 194 | 195 | [type="checkbox"], 196 | [type="radio"] { 197 | box-sizing: border-box; /* 1 */ 198 | padding: 0; /* 2 */ 199 | } 200 | 201 | /** 202 | * Correct the cursor style of increment and decrement buttons in Chrome. 203 | */ 204 | 205 | [type="number"]::-webkit-inner-spin-button, 206 | [type="number"]::-webkit-outer-spin-button { 207 | height: auto; 208 | } 209 | 210 | /** 211 | * 1. Correct the odd appearance in Chrome and Safari. 212 | * 2. Correct the outline style in Safari. 213 | */ 214 | 215 | [type="search"] { 216 | -webkit-appearance: textfield; /* 1 */ 217 | outline-offset: -2px; /* 2 */ 218 | } 219 | 220 | /** 221 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. 222 | */ 223 | 224 | [type="search"]::-webkit-search-cancel-button, 225 | [type="search"]::-webkit-search-decoration { 226 | -webkit-appearance: none; 227 | } 228 | 229 | /** 230 | * 1. Correct the inability to style clickable types in iOS and Safari. 231 | * 2. Change font properties to `inherit` in Safari. 232 | */ 233 | 234 | ::-webkit-file-upload-button { 235 | -webkit-appearance: button; /* 1 */ 236 | font: inherit; /* 2 */ 237 | } 238 | 239 | 0 240 | Looking 241 | 242 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/routes.ts: -------------------------------------------------------------------------------- 1 | let todoCategory = { 2 | title: 'TODO', 3 | }; 4 | 5 | 6 | export let routes = [ 7 | { route: '', redirect: 'list' }, 8 | { settings: { category: todoCategory }, route: 'list', moduleId: './pages/list', name: 'list', title: 'TODO list', nav: true }, 9 | 10 | { settings: { category: todoCategory }, route: 'add', moduleId: './pages/edit', name: 'add', title: 'Add todo', nav: true }, 11 | { route: 'edit', moduleId: './pages/edit', name: 'edit', title: 'Edit todo' }, 12 | ]; 13 | -------------------------------------------------------------------------------- /aurelia-ux-todo/src/services/storage.ts: -------------------------------------------------------------------------------- 1 | import { Todo } from '../models/todo'; 2 | 3 | 4 | const TODO_SAVE_KEY = 'todos'; 5 | 6 | export class Storage { 7 | getTodos(): Todo[] { 8 | let todos = localStorage.getItem(TODO_SAVE_KEY); 9 | if (todos === null) { 10 | return []; 11 | } 12 | 13 | return JSON.parse(todos); 14 | } 15 | 16 | saveTodo(todo: Todo) { 17 | let todos; 18 | if (todo.id === undefined) { 19 | todos = this.getTodos(); 20 | todo.id = todos.length; 21 | todos.push(todo); 22 | } else { 23 | todos = this.getTodos(); 24 | let index = todo.id; 25 | todos[index] = todo; 26 | } 27 | 28 | localStorage.setItem(TODO_SAVE_KEY, JSON.stringify(todos)); 29 | } 30 | 31 | getTodo(id): Todo { 32 | return this.getTodos()[id]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /aurelia-ux-todo/test/aurelia-karma.js: -------------------------------------------------------------------------------- 1 | (function(global) { 2 | var karma = global.__karma__; 3 | var requirejs = global.requirejs 4 | var locationPathname = global.location.pathname; 5 | var root = 'src'; 6 | karma.config.args.forEach(function(value, index) { 7 | if (value === 'aurelia-root') { 8 | root = karma.config.args[index + 1]; 9 | } 10 | }); 11 | 12 | if (!karma || !requirejs) { 13 | return; 14 | } 15 | 16 | function normalizePath(path) { 17 | var normalized = [] 18 | var parts = path 19 | .split('?')[0] // cut off GET params, used by noext requirejs plugin 20 | .split('/') 21 | 22 | for (var i = 0; i < parts.length; i++) { 23 | if (parts[i] === '.') { 24 | continue 25 | } 26 | 27 | if (parts[i] === '..' && normalized.length && normalized[normalized.length - 1] !== '..') { 28 | normalized.pop() 29 | continue 30 | } 31 | 32 | normalized.push(parts[i]) 33 | } 34 | 35 | return normalized.join('/') 36 | } 37 | 38 | function patchRequireJS(files, originalLoadFn, locationPathname) { 39 | var IS_DEBUG = /debug\.html$/.test(locationPathname) 40 | 41 | requirejs.load = function (context, moduleName, url) { 42 | url = normalizePath(url) 43 | 44 | if (files.hasOwnProperty(url) && !IS_DEBUG) { 45 | url = url + '?' + files[url] 46 | } 47 | 48 | if (url.indexOf('/base') !== 0) { 49 | url = '/base/' + url; 50 | } 51 | 52 | return originalLoadFn.call(this, context, moduleName, url) 53 | } 54 | 55 | var originalDefine = global.define; 56 | global.define = function(name, deps, m) { 57 | if (typeof name === 'string') { 58 | originalDefine('/base/' + root + '/' + name, [name], function (result) { return result; }); 59 | } 60 | 61 | return originalDefine(name, deps, m); 62 | } 63 | } 64 | 65 | function requireTests() { 66 | var TEST_REGEXP = /(spec)\.js$/i; 67 | var allTestFiles = ['/base/test/unit/setup.js']; 68 | 69 | Object.keys(window.__karma__.files).forEach(function(file) { 70 | if (TEST_REGEXP.test(file)) { 71 | allTestFiles.push(file); 72 | } 73 | }); 74 | 75 | require(allTestFiles, window.__karma__.start); 76 | } 77 | 78 | karma.loaded = function() {}; // make it async 79 | patchRequireJS(karma.files, requirejs.load, locationPathname); 80 | requireTests(); 81 | })(window); 82 | -------------------------------------------------------------------------------- /aurelia-ux-todo/test/unit/app.spec.ts: -------------------------------------------------------------------------------- 1 | import {App} from '../../src/app'; 2 | 3 | class UX { 4 | public design = { 5 | primary: '', 6 | accent: '', 7 | }; 8 | } 9 | 10 | 11 | describe('the app', () => { 12 | it('says hello', () => { 13 | let ux = new UX(); 14 | let sut = new App(ux); 15 | expect(ux.design.primary).toBe('#009688'); 16 | expect(ux.design.accent).toBe('#4CAF50'); 17 | expect(sut.showNavigationMenu).toBe(false); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /aurelia-ux-todo/test/unit/setup.ts: -------------------------------------------------------------------------------- 1 | import 'aurelia-polyfills'; 2 | import {initialize} from 'aurelia-pal-browser'; 3 | initialize(); 4 | -------------------------------------------------------------------------------- /aurelia-ux-todo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "sourceMap": true, 5 | "target": "es5", 6 | "module": "amd", 7 | "declaration": false, 8 | "noImplicitAny": false, 9 | "removeComments": true, 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "moduleResolution": "node", 13 | "lib": ["es2015", "dom"] 14 | }, 15 | "exclude": [ 16 | "node_modules" 17 | ], 18 | "filesGlob": [ 19 | "./src/**/*.ts", 20 | "./test/**/*.ts", 21 | "./typings/index.d.ts", 22 | "./custom_typings/**/*.d.ts" 23 | ], 24 | "atom": { 25 | "rewriteTsconfig": false 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /aurelia-ux-todo/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /aurelia-ux-todo/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-ux-showcase", 3 | "dependencies": {}, 4 | "globalDevDependencies": { 5 | "angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459", 6 | "jasmine": "registry:dt/jasmine#2.2.0+20160505161446", 7 | "node": "registry:dt/node", 8 | "selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654" 9 | }, 10 | "globalDependencies": { 11 | "localforage": "registry:dt/localforage#0.0.0+20161102134758" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ionic2-todo/README.rst: -------------------------------------------------------------------------------- 1 | Requirements 2 | ============ 3 | 4 | - ionic2 5 | - cordova 6 | - typings 7 | 8 | 9 | Setup 10 | ===== 11 | 12 | - Install node dependencies: ``npm install`` 13 | - Install typings information: ``typings install`` 14 | 15 | 16 | Run in browser 17 | ============== 18 | 19 | - Launch ``ionic serve`` to serve the application in a browser. It supports live 20 | reload. To rebuild the files when they are modified, launch in another 21 | terminal ``gulp watch``. 22 | 23 | 24 | Run in emulator 25 | =============== 26 | 27 | - Add platform: ``ionic platform add android`` 28 | - Launch ``ionic run android`` 29 | - Build for phone: ``ionic build android`` 30 | -------------------------------------------------------------------------------- /ionic2-todo/app/app.ts: -------------------------------------------------------------------------------- 1 | import {App, Platform} from 'ionic-angular'; 2 | import {ListTodosPage} from './pages/list-todos/list-todos'; 3 | 4 | // https://angular.io/docs/ts/latest/api/core/Type-interface.html 5 | import {Type} from 'angular2/core'; 6 | 7 | 8 | @App({ 9 | template: '', 10 | config: {} // http://ionicframework.com/docs/v2/api/config/Config/ 11 | }) 12 | export class MyApp { 13 | rootPage: Type = ListTodosPage; 14 | 15 | constructor(platform: Platform) { 16 | platform.ready().then(() => { 17 | // The platform is now ready. Note: if this callback fails to fire, follow 18 | // the Troubleshooting guide for a number of possible solutions: 19 | // 20 | // Okay, so the platform is ready and our plugins are available. 21 | // Here you can do any higher level native things you might need. 22 | // 23 | // First, let's hide the keyboard accessory bar (only works natively) since 24 | // that's a better default: 25 | // 26 | // Keyboard.setAccessoryBarVisible(false); 27 | // 28 | // For example, we might change the StatusBar color. This one below is 29 | // good for dark backgrounds and light text: 30 | // StatusBar.setStyle(StatusBar.LIGHT_CONTENT) 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ionic2-todo/app/models.ts: -------------------------------------------------------------------------------- 1 | export class Todo { 2 | public id: number; 3 | public title: string; 4 | public description: string; 5 | public done: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /ionic2-todo/app/pages/list-todos/list-todos.html: -------------------------------------------------------------------------------- 1 | 2 | TODO list 3 | 4 | 5 | 6 | 7 | 8 | {{ todo.title }} 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ionic2-todo/app/pages/list-todos/list-todos.scss: -------------------------------------------------------------------------------- 1 | .done { 2 | text-decoration: line-through; 3 | } 4 | 5 | .clickable { 6 | cursor: pointer; 7 | } 8 | -------------------------------------------------------------------------------- /ionic2-todo/app/pages/list-todos/list-todos.ts: -------------------------------------------------------------------------------- 1 | import {Page, NavController, Storage, SqlStorage} from 'ionic-angular'; 2 | import {Todo} from '../../models'; 3 | import { TodoPage } from '../todo/todo'; 4 | 5 | 6 | @Page({ 7 | templateUrl: 'build/pages/list-todos/list-todos.html', 8 | }) 9 | export class ListTodosPage { 10 | private todos: Todo[]; 11 | private storage: Storage; 12 | 13 | constructor(private nav: NavController) { 14 | this.storage = new Storage(SqlStorage); 15 | this.todos = []; 16 | this.storage.query('CREATE TABLE IF NOT EXISTS todos(id integer primary key unique, title VARCHAR(10), description TEXT, done BOOLEAN)') 17 | .then(() => this.storage.query('SELECT * FROM todos')) 18 | .then(results => { 19 | for (let result of results.res.rows) { 20 | console.log(result) 21 | this.todos.push(result); 22 | } 23 | }) 24 | .catch(err => console.log(err)); 25 | } 26 | 27 | private viewTodo(index) { 28 | this.nav.push(TodoPage, { 29 | todo: this.todos[index], 30 | index: index, 31 | }); 32 | } 33 | 34 | private addTodo() { 35 | this.nav.push(TodoPage); 36 | } 37 | 38 | private markTodoDone(todo) { 39 | let done; 40 | if (todo.done == true || todo.done === 'true') { 41 | done = 'false'; 42 | } else { 43 | done = 'true'; 44 | } 45 | 46 | this.storage.query('UPDATE todos SET done = ?', [done]) 47 | .then(() => todo.done = done) 48 | .catch(err => console.log(err)); 49 | } 50 | 51 | private getClass(todo) { 52 | // When retrieved from SQLStorage, done is not a boolean but a string. 53 | return (todo.done == true || todo.done === 'true') ? 'done clickable' : 'clickable'; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ionic2-todo/app/pages/todo/todo.html: -------------------------------------------------------------------------------- 1 | 2 | TODO {{ todo.title }} 3 | 4 | 5 | 6 |
7 | 8 | Title 9 | 10 | 11 |
13 | * Title is required! 14 |
15 | 16 | Description 17 | 18 | 19 | 20 | Done 21 | 22 | 23 | 24 | 25 | 26 |
27 |
-------------------------------------------------------------------------------- /ionic2-todo/app/pages/todo/todo.ts: -------------------------------------------------------------------------------- 1 | import { 2 | FORM_DIRECTIVES, 3 | AbstractControl, 4 | ControlGroup, 5 | Validators, 6 | Control, 7 | } from 'angular2/common'; 8 | import {Page, NavController, NavParams, Storage, SqlStorage} from 'ionic-angular'; 9 | import {Todo} from '../../models'; 10 | import { ListTodosPage } from '../list-todos/list-todos'; 11 | 12 | 13 | @Page({ 14 | templateUrl: 'build/pages/todo/todo.html', 15 | }) 16 | export class TodoPage { 17 | private todo: Todo; 18 | private index: number; 19 | private todoForm: ControlGroup; 20 | private title: AbstractControl; 21 | private description: AbstractControl; 22 | private done: AbstractControl; 23 | private storage: Storage; 24 | 25 | constructor(private nav: NavController, navParams: NavParams) { 26 | this.storage = new Storage(SqlStorage); 27 | 28 | if (navParams.data.todo) { 29 | this.todo = navParams.data.todo; 30 | } else { 31 | this.todo = new Todo(); 32 | } 33 | 34 | this.index = navParams.data.index; 35 | 36 | // When retrieved from SQLStorage, done is not a boolean but a string. 37 | let done = this.todo.done == true || this.todo.done === 'true'; 38 | let group: {[key: string]: Control} = { 39 | title: new Control(this.todo.title, Validators.compose([Validators.required])), 40 | description: new Control(this.todo.description), 41 | done: new Control(done), 42 | }; 43 | 44 | this.todoForm = new ControlGroup(group); 45 | this.title = this.todoForm.controls['title']; 46 | this.description = this.todoForm.controls['description']; 47 | this.done = this.todoForm.controls['done']; 48 | } 49 | 50 | private save(todoValues) { 51 | if (this.todo.id === undefined) { 52 | this.storage.query( 53 | 'INSERT INTO todos (title, description, done) VALUES (?, ?, ?);', 54 | [todoValues.title, todoValues.description, todoValues.done] 55 | ) 56 | .then(() => this.nav.push(ListTodosPage)) 57 | .catch(err => console.log(err)); 58 | } else { 59 | this.storage.query( 60 | 'UPDATE todos SET title = ?, description = ?, done = ? WHERE id = ?', 61 | [todoValues.title, todoValues.description, todoValues.done, this.todo.id] 62 | ) 63 | .then(() => this.nav.push(ListTodosPage)) 64 | .catch(err => console.log(err)); 65 | } 66 | } 67 | 68 | private cancel() { 69 | this.nav.push(ListTodosPage); 70 | } 71 | } -------------------------------------------------------------------------------- /ionic2-todo/app/theme/app.core.scss: -------------------------------------------------------------------------------- 1 | // http://ionicframework.com/docs/v2/theming/ 2 | 3 | 4 | // App Shared Imports 5 | // -------------------------------------------------- 6 | // These are the imports which make up the design of this app. 7 | // By default each design mode includes these shared imports. 8 | // App Shared Sass variables belong in app.variables.scss. 9 | 10 | @import "../pages/list-todos/list-todos.scss"; 11 | -------------------------------------------------------------------------------- /ionic2-todo/app/theme/app.ios.scss: -------------------------------------------------------------------------------- 1 | 2 | // http://ionicframework.com/docs/v2/theming/ 3 | 4 | 5 | // App Shared Variables 6 | // -------------------------------------------------- 7 | // Shared Sass variables go in the app.variables.scss file 8 | @import 'app.variables'; 9 | 10 | 11 | // App iOS Variables 12 | // -------------------------------------------------- 13 | // iOS only Sass variables can go here 14 | 15 | 16 | // Ionic iOS Sass 17 | // -------------------------------------------------- 18 | // Custom App variables must be declared before importing Ionic. 19 | // Ionic will use its default values when a custom variable isn't provided. 20 | @import 'ionic.ios'; 21 | 22 | 23 | // App Shared Sass 24 | // -------------------------------------------------- 25 | // All Sass files that make up this app goes into the app.core.scss file. 26 | // For simpler CSS overrides, custom app CSS must come after Ionic's CSS. 27 | @import 'app.core'; 28 | 29 | 30 | // App iOS Only Sass 31 | // -------------------------------------------------- 32 | // CSS that should only apply to the iOS app 33 | -------------------------------------------------------------------------------- /ionic2-todo/app/theme/app.md.scss: -------------------------------------------------------------------------------- 1 | // http://ionicframework.com/docs/v2/theming/ 2 | 3 | 4 | // App Shared Variables 5 | // -------------------------------------------------- 6 | // Shared Sass variables go in the app.variables.scss file 7 | @import 'app.variables'; 8 | 9 | 10 | // App Material Design Variables 11 | // -------------------------------------------------- 12 | // Material Design only Sass variables can go here 13 | 14 | 15 | // Ionic Material Design Sass 16 | // -------------------------------------------------- 17 | // Custom App variables must be declared before importing Ionic. 18 | // Ionic will use its default values when a custom variable isn't provided. 19 | @import 'ionic.md'; 20 | 21 | 22 | // App Shared Sass 23 | // -------------------------------------------------- 24 | // All Sass files that make up this app goes into the app.core.scss file. 25 | // For simpler CSS overrides, custom app CSS must come after Ionic's CSS. 26 | @import 'app.core'; 27 | 28 | 29 | // App Material Design Only Sass 30 | // -------------------------------------------------- 31 | // CSS that should only apply to the Material Design app 32 | -------------------------------------------------------------------------------- /ionic2-todo/app/theme/app.variables.scss: -------------------------------------------------------------------------------- 1 | // http://ionicframework.com/docs/v2/theming/ 2 | 3 | 4 | // App Shared Variables 5 | // -------------------------------------------------- 6 | // To customize the look and feel of this app, you can override 7 | // the Sass variables found in Ionic's source scss files. Setting 8 | // variables before Ionic's Sass will use these variables rather than 9 | // Ionic's default Sass variable values. App Shared Sass imports belong 10 | // in the app.core.scss file and not this file. Sass variables specific 11 | // to the mode belong in either the app.ios.scss or app.md.scss files. 12 | 13 | 14 | // App Shared Color Variables 15 | // -------------------------------------------------- 16 | // It's highly recommended to change the default colors 17 | // to match your app's branding. Ionic uses a Sass map of 18 | // colors so you can add, rename and remove colors as needed. 19 | // The "primary" color is the only required color in the map. 20 | // Both iOS and MD colors can be further customized if colors 21 | // are different per mode. 22 | 23 | $colors: ( 24 | primary: #387ef5, 25 | secondary: #32db64, 26 | danger: #f53d3d, 27 | light: #f4f4f4, 28 | dark: #222, 29 | favorite: #69BB7B 30 | ); 31 | -------------------------------------------------------------------------------- /ionic2-todo/app/theme/app.wp.scss: -------------------------------------------------------------------------------- 1 | // http://ionicframework.com/docs/v2/theming/ 2 | 3 | 4 | // App Shared Variables 5 | // -------------------------------------------------- 6 | // Shared Sass variables go in the app.variables.scss file 7 | @import 'app.variables'; 8 | 9 | 10 | // App Windows Variables 11 | // -------------------------------------------------- 12 | // Windows only Sass variables can go here 13 | 14 | 15 | // Ionic Windows Sass 16 | // -------------------------------------------------- 17 | // Custom App variables must be declared before importing Ionic. 18 | // Ionic will use its default values when a custom variable isn't provided. 19 | @import "ionic.wp"; 20 | 21 | 22 | // App Shared Sass 23 | // -------------------------------------------------- 24 | // All Sass files that make up this app goes into the app.core.scss file. 25 | // For simpler CSS overrides, custom app CSS must come after Ionic's CSS. 26 | @import 'app.core'; 27 | 28 | 29 | // App Windows Only Sass 30 | // -------------------------------------------------- 31 | // CSS that should only apply to the Windows app 32 | -------------------------------------------------------------------------------- /ionic2-todo/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ionic todo 4 | TODO application to test Ionic Framework 2 and Cordova. 5 | Julien Enselme 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ionic2-todo/gulpfile.js: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Gulpfile 3 | * Be sure to run `npm install` for `gulp` and the following tasks to be 4 | * available from the command line. All tasks are run using `gulp taskName`. 5 | ******************************************************************************/ 6 | var gulp = require('gulp'), 7 | webpack = require('webpack'), 8 | sass = require('gulp-sass'), 9 | autoprefixer = require('gulp-autoprefixer'), 10 | watch = require('gulp-watch'), 11 | del = require('del'); 12 | 13 | 14 | var IONIC_DIR = "node_modules/ionic-angular/" 15 | 16 | 17 | /****************************************************************************** 18 | * watch 19 | * Build the app and watch for source file changes. 20 | ******************************************************************************/ 21 | gulp.task('watch', ['sass', 'copy.fonts', 'copy.html'], function(done) { 22 | watch('app/**/*.scss', function(){ 23 | gulp.start('sass'); 24 | }); 25 | watch('app/**/*.html', function(){ 26 | gulp.start('copy.html'); 27 | }); 28 | bundle(true, done); 29 | }); 30 | 31 | 32 | /****************************************************************************** 33 | * build 34 | * Build the app once, without watching for source file changes. 35 | ******************************************************************************/ 36 | gulp.task('build', ['sass', 'copy.fonts', 'copy.html'], function(done) { 37 | bundle(false, done); 38 | }); 39 | 40 | 41 | /****************************************************************************** 42 | * sass 43 | * Convert Sass files to a single bundled CSS file. Uses auto-prefixer 44 | * to automatically add required vendor prefixes when needed. 45 | ******************************************************************************/ 46 | gulp.task('sass', function(){ 47 | var autoprefixerOpts = { 48 | browsers: [ 49 | 'last 2 versions', 50 | 'iOS >= 7', 51 | 'Android >= 4', 52 | 'Explorer >= 10', 53 | 'ExplorerMobile >= 11' 54 | ], 55 | cascade: false 56 | }; 57 | 58 | return gulp.src('app/theme/app.+(ios|md).scss') 59 | .pipe(sass({ 60 | includePaths: [ 61 | IONIC_DIR, 62 | 'node_modules/ionicons/dist/scss' 63 | ] 64 | })) 65 | .on('error', function(err){ 66 | console.error(err.message); 67 | this.emit('end'); 68 | }) 69 | .pipe(autoprefixer(autoprefixerOpts)) 70 | .pipe(gulp.dest('www/build/css')) 71 | }); 72 | 73 | 74 | /****************************************************************************** 75 | * copy.fonts 76 | * Copy Ionic font files to build directory. 77 | ******************************************************************************/ 78 | gulp.task('copy.fonts', function() { 79 | return gulp.src(IONIC_DIR + 'fonts/**/*.+(ttf|woff|woff2)') 80 | .pipe(gulp.dest('www/build/fonts')); 81 | }); 82 | 83 | 84 | /****************************************************************************** 85 | * copy.html 86 | * Copy html files to build directory. 87 | ******************************************************************************/ 88 | gulp.task('copy.html', function(){ 89 | return gulp.src('app/**/*.html') 90 | .pipe(gulp.dest('www/build')); 91 | }); 92 | 93 | 94 | /****************************************************************************** 95 | * clean 96 | * Delete previous build files. 97 | ******************************************************************************/ 98 | gulp.task('clean', function(done) { 99 | del(['www/build'], done); 100 | }); 101 | 102 | 103 | /****************************************************************************** 104 | * Bundle 105 | * Transpiles source files and bundles them into build directory using webpack. 106 | ******************************************************************************/ 107 | function bundle(watch, cb) { 108 | // prevent gulp calling done callback more than once when watching 109 | var firstTime = true; 110 | 111 | // load webpack config 112 | var config = require('./webpack.config.js'); 113 | 114 | // https://github.com/webpack/docs/wiki/node.js-api#statstojsonoptions 115 | var statsOptions = { 116 | 'colors': true, 117 | 'modules': false, 118 | 'chunks': false, 119 | 'exclude': ['node_modules'] 120 | } 121 | 122 | var compiler = webpack(config); 123 | if (watch) { 124 | compiler.watch(null, compileHandler); 125 | } else { 126 | compiler.run(compileHandler); 127 | } 128 | 129 | function compileHandler(err, stats){ 130 | if (firstTime) { 131 | firstTime = false; 132 | cb(); 133 | } 134 | 135 | // print build stats and errors 136 | console.log(stats.toString(statsOptions)); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /ionic2-todo/hooks/README.md: -------------------------------------------------------------------------------- 1 | 21 | # Cordova Hooks 22 | 23 | Cordova Hooks represent special scripts which could be added by application and plugin developers or even by your own build system to customize cordova commands. Hook scripts could be defined by adding them to the special predefined folder (`/hooks`) or via configuration files (`config.xml` and `plugin.xml`) and run serially in the following order: 24 | * Application hooks from `/hooks`; 25 | * Application hooks from `config.xml`; 26 | * Plugin hooks from `plugins/.../plugin.xml`. 27 | 28 | __Remember__: Make your scripts executable. 29 | 30 | __Note__: `.cordova/hooks` directory is also supported for backward compatibility, but we don't recommend using it as it is deprecated. 31 | 32 | ## Supported hook types 33 | The following hook types are supported: 34 | 35 | after_build/ 36 | after_compile/ 37 | after_docs/ 38 | after_emulate/ 39 | after_platform_add/ 40 | after_platform_rm/ 41 | after_platform_ls/ 42 | after_plugin_add/ 43 | after_plugin_ls/ 44 | after_plugin_rm/ 45 | after_plugin_search/ 46 | after_plugin_install/ <-- Plugin hooks defined in plugin.xml are executed exclusively for a plugin being installed 47 | after_prepare/ 48 | after_run/ 49 | after_serve/ 50 | before_build/ 51 | before_compile/ 52 | before_docs/ 53 | before_emulate/ 54 | before_platform_add/ 55 | before_platform_rm/ 56 | before_platform_ls/ 57 | before_plugin_add/ 58 | before_plugin_ls/ 59 | before_plugin_rm/ 60 | before_plugin_search/ 61 | before_plugin_install/ <-- Plugin hooks defined in plugin.xml are executed exclusively for a plugin being installed 62 | before_plugin_uninstall/ <-- Plugin hooks defined in plugin.xml are executed exclusively for a plugin being uninstalled 63 | before_prepare/ 64 | before_run/ 65 | before_serve/ 66 | pre_package/ <-- Windows 8 and Windows Phone only. 67 | 68 | ## Ways to define hooks 69 | ### Via '/hooks' directory 70 | To execute custom action when corresponding hook type is fired, use hook type as a name for a subfolder inside 'hooks' directory and place you script file here, for example: 71 | 72 | # script file will be automatically executed after each build 73 | hooks/after_build/after_build_custom_action.js 74 | 75 | 76 | ### Config.xml 77 | 78 | Hooks can be defined in project's `config.xml` using `` elements, for example: 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | ... 89 | 90 | 91 | 92 | 93 | 94 | 95 | ... 96 | 97 | 98 | ### Plugin hooks (plugin.xml) 99 | 100 | As a plugin developer you can define hook scripts using `` elements in a `plugin.xml` like that: 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | ... 109 | 110 | 111 | `before_plugin_install`, `after_plugin_install`, `before_plugin_uninstall` plugin hooks will be fired exclusively for the plugin being installed/uninstalled. 112 | 113 | ## Script Interface 114 | 115 | ### Javascript 116 | 117 | If you are writing hooks in Javascript you should use the following module definition: 118 | ```javascript 119 | module.exports = function(context) { 120 | ... 121 | } 122 | ``` 123 | 124 | You can make your scipts async using Q: 125 | ```javascript 126 | module.exports = function(context) { 127 | var Q = context.requireCordovaModule('q'); 128 | var deferral = new Q.defer(); 129 | 130 | setTimeout(function(){ 131 | console.log('hook.js>> end'); 132 | deferral.resolve(); 133 | }, 1000); 134 | 135 | return deferral.promise; 136 | } 137 | ``` 138 | 139 | `context` object contains hook type, executed script full path, hook options, command-line arguments passed to Cordova and top-level "cordova" object: 140 | ```json 141 | { 142 | "hook": "before_plugin_install", 143 | "scriptLocation": "c:\\script\\full\\path\\appBeforePluginInstall.js", 144 | "cmdLine": "The\\exact\\command\\cordova\\run\\with arguments", 145 | "opts": { 146 | "projectRoot":"C:\\path\\to\\the\\project", 147 | "cordova": { 148 | "platforms": ["wp8"], 149 | "plugins": ["com.plugin.withhooks"], 150 | "version": "0.21.7-dev" 151 | }, 152 | "plugin": { 153 | "id": "com.plugin.withhooks", 154 | "pluginInfo": { 155 | ... 156 | }, 157 | "platform": "wp8", 158 | "dir": "C:\\path\\to\\the\\project\\plugins\\com.plugin.withhooks" 159 | } 160 | }, 161 | "cordova": {...} 162 | } 163 | 164 | ``` 165 | `context.opts.plugin` object will only be passed to plugin hooks scripts. 166 | 167 | You can also require additional Cordova modules in your script using `context.requireCordovaModule` in the following way: 168 | ```javascript 169 | var Q = context.requireCordovaModule('q'); 170 | ``` 171 | 172 | __Note__: new module loader script interface is used for the `.js` files defined via `config.xml` or `plugin.xml` only. 173 | For compatibility reasons hook files specified via `/hooks` folders are run via Node child_process spawn, see 'Non-javascript' section below. 174 | 175 | ### Non-javascript 176 | 177 | Non-javascript scripts are run via Node child_process spawn from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables: 178 | 179 | * CORDOVA_VERSION - The version of the Cordova-CLI. 180 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios). 181 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer) 182 | * CORDOVA_HOOK - Path to the hook that is being executed. 183 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate) 184 | 185 | If a script returns a non-zero exit code, then the parent cordova command will be aborted. 186 | 187 | ## Writing hooks 188 | 189 | We highly recommend writing your hooks using Node.js so that they are 190 | cross-platform. Some good examples are shown here: 191 | 192 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/) 193 | 194 | Also, note that even if you are working on Windows, and in case your hook scripts aren't bat files (which is recommended, if you want your scripts to work in non-Windows operating systems) Cordova CLI will expect a shebang line as the first line for it to know the interpreter it needs to use to launch the script. The shebang line should match the following example: 195 | 196 | #!/usr/bin/env [name_of_interpreter_executable] 197 | -------------------------------------------------------------------------------- /ionic2-todo/hooks/after_prepare/010_add_platform_class.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Add Platform Class 4 | // v1.0 5 | // Automatically adds the platform class to the body tag 6 | // after the `prepare` command. By placing the platform CSS classes 7 | // directly in the HTML built for the platform, it speeds up 8 | // rendering the correct layout/style for the specific platform 9 | // instead of waiting for the JS to figure out the correct classes. 10 | 11 | var fs = require('fs'); 12 | var path = require('path'); 13 | 14 | var rootdir = process.argv[2]; 15 | 16 | function addPlatformBodyTag(indexPath, platform) { 17 | // add the platform class to the body tag 18 | try { 19 | var platformClass = 'platform-' + platform; 20 | var cordovaClass = 'platform-cordova platform-webview'; 21 | 22 | var html = fs.readFileSync(indexPath, 'utf8'); 23 | 24 | var bodyTag = findBodyTag(html); 25 | if(!bodyTag) return; // no opening body tag, something's wrong 26 | 27 | if(bodyTag.indexOf(platformClass) > -1) return; // already added 28 | 29 | var newBodyTag = bodyTag; 30 | 31 | var classAttr = findClassAttr(bodyTag); 32 | if(classAttr) { 33 | // body tag has existing class attribute, add the classname 34 | var endingQuote = classAttr.substring(classAttr.length-1); 35 | var newClassAttr = classAttr.substring(0, classAttr.length-1); 36 | newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote; 37 | newBodyTag = bodyTag.replace(classAttr, newClassAttr); 38 | 39 | } else { 40 | // add class attribute to the body tag 41 | newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">'); 42 | } 43 | 44 | html = html.replace(bodyTag, newBodyTag); 45 | 46 | fs.writeFileSync(indexPath, html, 'utf8'); 47 | 48 | process.stdout.write('add to body class: ' + platformClass + '\n'); 49 | } catch(e) { 50 | process.stdout.write(e); 51 | } 52 | } 53 | 54 | function findBodyTag(html) { 55 | // get the body tag 56 | try{ 57 | return html.match(/])(.*?)>/gi)[0]; 58 | }catch(e){} 59 | } 60 | 61 | function findClassAttr(bodyTag) { 62 | // get the body tag's class attribute 63 | try{ 64 | return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0]; 65 | }catch(e){} 66 | } 67 | 68 | if (rootdir) { 69 | 70 | // go through each of the platform directories that have been prepared 71 | var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []); 72 | 73 | for(var x=0; x= 7', 36 | 'Android >= 4', 37 | 'Explorer >= 10', 38 | 'ExplorerMobile >= 11' 39 | ], 40 | cascade: false 41 | }, 42 | 43 | // hooks execute before or after all project-related Ionic commands 44 | // (so not for start, docs, but serve, run, etc.) and take in the arguments 45 | // passed to the command as a parameter 46 | // 47 | // The format is 'before' or 'after' + commandName (uppercased) 48 | // ex: beforeServe, afterRun, beforePrepare, etc. 49 | hooks: { 50 | beforeServe: function(argv) { 51 | //console.log('beforeServe'); 52 | } 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /ionic2-todo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "angular2": "2.0.0-beta.6", 4 | "es6-promise": "3.0.2", 5 | "es6-shim": "0.33.13", 6 | "ionic-angular": "2.0.0-beta.3", 7 | "ionicons": "3.0.0-alpha.3", 8 | "reflect-metadata": "0.1.2", 9 | "rxjs": "5.0.0-beta.0", 10 | "zone.js": "0.5.14" 11 | }, 12 | "devDependencies": { 13 | "awesome-typescript-loader": "0.15.10", 14 | "del": "2.2.0", 15 | "gulp": "3.9.1", 16 | "gulp-autoprefixer": "^3.1.0", 17 | "gulp-sass": "2.2.0", 18 | "gulp-watch": "4.3.5", 19 | "strip-sourcemap-loader": "0.0.1", 20 | "typescript": "1.8.7", 21 | "webpack": "1.12.14" 22 | }, 23 | "name": "ionic2-todo", 24 | "description": "ionic2-todo: An Ionic project", 25 | "cordovaPlugins": [ 26 | "cordova-plugin-device", 27 | "cordova-plugin-console", 28 | "cordova-plugin-whitelist", 29 | "cordova-plugin-splashscreen", 30 | "cordova-plugin-statusbar", 31 | "ionic-plugin-keyboard" 32 | ], 33 | "cordovaPlatforms": [ 34 | "android" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /ionic2-todo/resources/android/icon/drawable-hdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/icon/drawable-hdpi-icon.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/icon/drawable-ldpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/icon/drawable-ldpi-icon.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/icon/drawable-mdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/icon/drawable-mdpi-icon.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/icon/drawable-xhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/icon/drawable-xhdpi-icon.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/icon/drawable-xxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/icon/drawable-xxhdpi-icon.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/icon/drawable-xxxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/icon/drawable-xxxhdpi-icon.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-land-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-land-hdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-land-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-land-ldpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-land-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-land-mdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-land-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-land-xhdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-land-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-land-xxhdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-land-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-land-xxxhdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-port-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-port-hdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-port-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-port-ldpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-port-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-port-mdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-port-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-port-xhdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-port-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-port-xxhdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/android/splash/drawable-port-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/android/splash/drawable-port-xxxhdpi-screen.png -------------------------------------------------------------------------------- /ionic2-todo/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/icon.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-40.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-40@2x.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-50.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-50@2x.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-60.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-60@2x.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-60@3x.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-72.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-72@2x.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-76.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-76@2x.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-small.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-small@2x.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon-small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon-small@3x.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/icon/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/icon/icon@2x.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default-568h@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default-568h@2x~iphone.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default-667h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default-667h.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default-736h.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default-Landscape-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default-Landscape-736h.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default-Landscape@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default-Landscape@2x~ipad.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default-Landscape~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default-Landscape~ipad.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default-Portrait@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default-Portrait@2x~ipad.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default-Portrait~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default-Portrait~ipad.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default@2x~iphone.png -------------------------------------------------------------------------------- /ionic2-todo/resources/ios/splash/Default~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/ios/splash/Default~iphone.png -------------------------------------------------------------------------------- /ionic2-todo/resources/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jenselme/tests-ionic2-and-aurelia-framework7/fea62c4f7cda6d99045a90af81971d448d4c68ad/ionic2-todo/resources/splash.png -------------------------------------------------------------------------------- /ionic2-todo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true 7 | }, 8 | "filesGlob": [ 9 | "**/*.ts", 10 | "!node_modules/**/*" 11 | ], 12 | "exclude": [ 13 | "node_modules", 14 | "typings/main", 15 | "typings/main.d.ts" 16 | ], 17 | "compileOnSave": false, 18 | "atom": { 19 | "rewriteTsconfig": false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ionic2-todo/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": {}, 3 | "devDependencies": {}, 4 | "ambientDependencies": { 5 | "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#4de74cb527395c13ba20b438c3a7a419ad931f1c" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ionic2-todo/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | 4 | module.exports = { 5 | entry: [ 6 | path.normalize('es6-shim/es6-shim.min'), 7 | 'reflect-metadata', 8 | path.normalize('zone.js/dist/zone-microtask'), 9 | path.resolve('app/app') 10 | ], 11 | output: { 12 | path: path.resolve('www/build/js'), 13 | filename: 'app.bundle.js', 14 | pathinfo: false // show module paths in the bundle, handy for debugging 15 | }, 16 | module: { 17 | loaders: [ 18 | { 19 | test: /\.ts$/, 20 | loader: 'awesome-typescript', 21 | query: { 22 | doTypeCheck: true, 23 | resolveGlobs: false, 24 | externals: ['typings/browser.d.ts'] 25 | }, 26 | include: path.resolve('app'), 27 | exclude: /node_modules/ 28 | }, 29 | { 30 | test: /\.js$/, 31 | include: path.resolve('node_modules/angular2'), 32 | loader: 'strip-sourcemap' 33 | } 34 | ], 35 | noParse: [ 36 | /es6-shim/, 37 | /reflect-metadata/, 38 | /zone\.js(\/|\\)dist(\/|\\)zone-microtask/ 39 | ] 40 | }, 41 | resolve: { 42 | root: ['app'], 43 | alias: { 44 | 'angular2': path.resolve('node_modules/angular2') 45 | }, 46 | extensions: ["", ".js", ".ts"] 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /ionic2-todo/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ionic 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------