mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 11:41:20 +08:00
update to latest ng
This commit is contained in:
17
gulpfile.js
17
gulpfile.js
@ -88,9 +88,20 @@ gulp.task('ng2-rename', function(done) {
|
|||||||
});
|
});
|
||||||
gulp.task('ng2', ['ng2-rename'], function() {
|
gulp.task('ng2', ['ng2-rename'], function() {
|
||||||
var builder = new SystemJsBuilder();
|
var builder = new SystemJsBuilder();
|
||||||
return builder.loadConfig('jspm-config.js')
|
builder.config({
|
||||||
.then(function() {
|
traceurOptions: {
|
||||||
return builder.build('dist/lib/angular2/angular2', 'dist/lib/angular2.js');
|
'sourceMaps': true,
|
||||||
|
'annotations': true,
|
||||||
|
'types': true,
|
||||||
|
'script': false,
|
||||||
|
'memberVariables': true,
|
||||||
|
'modules': 'instantiate'
|
||||||
|
},
|
||||||
|
baseURL: 'dist/lib',
|
||||||
|
map: {
|
||||||
|
rx: __dirname + '/node_modules/rx'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
return builder.build('angular2/angular2', 'dist/lib/angular2.js');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,26 +1,23 @@
|
|||||||
System.config({
|
System.config({
|
||||||
"paths": {
|
'paths': {
|
||||||
"*": "*.js",
|
'*': '*.js',
|
||||||
"dist/*": "/dist",
|
'angular2/*': '/dist/lib/angular2/*.js'
|
||||||
"node_modules/*": "/node_modules/*",
|
|
||||||
},
|
},
|
||||||
"traceurOptions": {
|
'traceurOptions': {
|
||||||
"sourceMaps": true,
|
'sourceMaps': true,
|
||||||
"annotations": true,
|
'annotations': true,
|
||||||
"types": true,
|
'types': true,
|
||||||
"script": false,
|
'script': false,
|
||||||
"memberVariables": true,
|
'memberVariables': true,
|
||||||
"modules": "instantiate"
|
'modules': 'instantiate'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
System.config({
|
System.config({
|
||||||
"map": {
|
'map': {
|
||||||
"angular2": "dist/lib/angular2",
|
'hammer': '/node_modules/hammerjs/hammer',
|
||||||
"hammer": "node_modules/hammerjs/hammer.js",
|
'rx': '/node_modules/rx',
|
||||||
"rtts_assert": "dist/lib/rtts_assert",
|
'ionic2': '/src',
|
||||||
"rx": "node_modules/rx",
|
|
||||||
"ionic2": "/src",
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,12 +4,6 @@ import {PrivateComponentLoader} from 'angular2/src/core/compiler/private_compone
|
|||||||
import {PrivateComponentLocation} from 'angular2/src/core/compiler/private_component_location';
|
import {PrivateComponentLocation} from 'angular2/src/core/compiler/private_component_location';
|
||||||
import {RedBgStyler, BlueTextStyler} from './components/stylers';
|
import {RedBgStyler, BlueTextStyler} from './components/stylers';
|
||||||
|
|
||||||
class Testy {
|
|
||||||
constructor(@Inject() element: NgElement) {
|
|
||||||
element.domElement.style.border = '3px solid pink;'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DynamicComponent({
|
@DynamicComponent({
|
||||||
selector: 'dynamic-component',
|
selector: 'dynamic-component',
|
||||||
services: [PrivateComponentLoader, PrivateComponentLocation]
|
services: [PrivateComponentLoader, PrivateComponentLocation]
|
||||||
@ -20,12 +14,8 @@ class MyDynamic {
|
|||||||
loader:PrivateComponentLoader,
|
loader:PrivateComponentLoader,
|
||||||
location:PrivateComponentLocation
|
location:PrivateComponentLocation
|
||||||
) {
|
) {
|
||||||
// loader.load(RedBgStyler, location);
|
loader.load(RedBgStyler, location);
|
||||||
// loader.load(BlueTextStyler, location);
|
loader.load(BlueTextStyler, location);
|
||||||
Testy.annotations = [
|
|
||||||
new Component({ selector: 'testy' }),
|
|
||||||
new Template({ inline: 'testy-template' })
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import {Component, Template, Inject, Parent, NgElement} from 'angular2/angular2';
|
import {Component, Template, Inject, Parent, NgElement} from 'angular2/angular2';
|
||||||
import {Ion} from '../ion';
|
import {Ion} from '../ion';
|
||||||
import {IonConfig} from '../../config';
|
import {Config} from '../../core/config/config';
|
||||||
import {SlideEdgeGesture} from '../../core/gestures/slide-edge-gesture';
|
import {SlideEdgeGesture} from '../../core/gestures/slide-edge-gesture';
|
||||||
import * as util from '../../util';
|
import * as util from '../../util';
|
||||||
|
|
||||||
export var asideConfig = new IonConfig('aside');
|
export var asideConfig = new Config('aside');
|
||||||
|
|
||||||
// TODO defaults or bindings?
|
// TODO defaults or bindings?
|
||||||
asideConfig.set({
|
asideConfig.set({
|
||||||
@ -12,6 +12,13 @@ asideConfig.set({
|
|||||||
dragThreshold: 50
|
dragThreshold: 50
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
class AndroidAside {}
|
||||||
|
class IosAside {}
|
||||||
|
|
||||||
|
asideConfig.platform('android').component(AndroidAside);
|
||||||
|
asideConfig.platform('ios').component(IosAside);
|
||||||
|
|
||||||
// AsideParent is just a temporary directive
|
// AsideParent is just a temporary directive
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ion-aside-parent'
|
selector: 'ion-aside-parent'
|
||||||
@ -49,7 +56,9 @@ export class Aside {
|
|||||||
|
|
||||||
// TODO: remove this. setTimeout has to be done so the bindings can be applied
|
// TODO: remove this. setTimeout has to be done so the bindings can be applied
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// asideConfig.invoke(this);
|
let Comp = asideConfig.invoke(this);
|
||||||
|
console.log('using', Comp);
|
||||||
|
|
||||||
let GestureConstructor = {
|
let GestureConstructor = {
|
||||||
left: LeftAsideSlideGesture,
|
left: LeftAsideSlideGesture,
|
||||||
top: TopAsideSlideGesture,
|
top: TopAsideSlideGesture,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import * as Platform from '../platform';
|
|
||||||
import * as util from '../util';
|
import * as util from '../util';
|
||||||
|
|
||||||
export class Ion {}
|
export class Ion {}
|
||||||
|
180
src/config.js
180
src/config.js
@ -1,180 +0,0 @@
|
|||||||
import * as Platform from './platform';
|
|
||||||
import * as util from './util';
|
|
||||||
|
|
||||||
// TODO stop hardcoding platforms and media sizes
|
|
||||||
|
|
||||||
/*
|
|
||||||
config
|
|
||||||
.set({ side: 'left' })
|
|
||||||
.set('threshold', 50)
|
|
||||||
.platform('ios')
|
|
||||||
.set('side', 'top')
|
|
||||||
.unset('threshold')
|
|
||||||
.media('lg')
|
|
||||||
.set('side', 'right')
|
|
||||||
|
|
||||||
config.platform('ios')
|
|
||||||
.behavior(function() {
|
|
||||||
do something
|
|
||||||
})
|
|
||||||
.defaults({
|
|
||||||
side: 'right'
|
|
||||||
})
|
|
||||||
|
|
||||||
config.platform('ios').media('tablet')
|
|
||||||
.defaults({
|
|
||||||
side: 'bottom'
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
User wants to remove the default behavior for sidemenu, but that's stuck under `.platform('ios').`
|
|
||||||
|
|
||||||
config.platform('ios').media('tablet') === config.media('tablet').platform('ios')
|
|
||||||
*/
|
|
||||||
var QUERIES = {
|
|
||||||
sm: true,
|
|
||||||
md: true,
|
|
||||||
lg: true
|
|
||||||
};
|
|
||||||
var PLATFORMS = {
|
|
||||||
ios: true,
|
|
||||||
android: true
|
|
||||||
};
|
|
||||||
|
|
||||||
function isPlatform(key = '') {
|
|
||||||
return key.toLowerCase() in PLATFORMS;
|
|
||||||
}
|
|
||||||
function isMedia(key = '') {
|
|
||||||
return key.toLowerCase() in QUERIES;
|
|
||||||
}
|
|
||||||
class ConfigCase {
|
|
||||||
constructor({ root, parent, path }) {
|
|
||||||
this._root = root;
|
|
||||||
this._parent = parent;
|
|
||||||
this._path = path || [];
|
|
||||||
this._values = {};
|
|
||||||
this.behaviors = [];
|
|
||||||
}
|
|
||||||
platform(key = '') {
|
|
||||||
if (isPlatform(key)) return this._root._addCase(key, this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
media(key = '') {
|
|
||||||
if (isMedia(key)) return this._root._addCase(key, this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
when(condition = '') {
|
|
||||||
if (isPlatform(condition) || isMedia(condition)) {
|
|
||||||
return this._root._addCase(condition, this);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
behavior(fn) {
|
|
||||||
this.behaviors.push(fn);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
set(a, b) {
|
|
||||||
if (util.isString(a)) {
|
|
||||||
this._values[a] = b;
|
|
||||||
} else {
|
|
||||||
util.extend(this._values, a || {});
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
unset(key) {
|
|
||||||
delete this._values[key];
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
get(key) {
|
|
||||||
return util.isDefined(this._values[key]) ?
|
|
||||||
this._values[key] :
|
|
||||||
(this._parent ? this._parent.get(key) : undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class IonConfig extends ConfigCase {
|
|
||||||
constructor() {
|
|
||||||
this._root = this;
|
|
||||||
this._cases = {};
|
|
||||||
super({
|
|
||||||
root: this,
|
|
||||||
parent: null,
|
|
||||||
path: ''
|
|
||||||
});
|
|
||||||
}
|
|
||||||
invoke(instance) {
|
|
||||||
return invokeConfig(this, instance);
|
|
||||||
}
|
|
||||||
_addCase(key, baseCase) {
|
|
||||||
var path = baseCase._path.slice();
|
|
||||||
path.push(key);
|
|
||||||
|
|
||||||
// Remove empties & duplicates
|
|
||||||
path = path
|
|
||||||
.filter((value, index) => {
|
|
||||||
return value && path.indexOf(value) === index;
|
|
||||||
})
|
|
||||||
.sort();
|
|
||||||
|
|
||||||
if (path.join(' ') === baseCase._path.join(' ')) {
|
|
||||||
return baseCase;
|
|
||||||
}
|
|
||||||
return this._createCase(path);
|
|
||||||
}
|
|
||||||
_createCase(path) {
|
|
||||||
if (!path.length) return this;
|
|
||||||
var pathStr = path.join(' ');
|
|
||||||
var configCase = this._cases[pathStr];
|
|
||||||
if (!configCase) {
|
|
||||||
var parentPath = path.slice(0, path.length - 1);
|
|
||||||
configCase = this._cases[pathStr] = new ConfigCase({
|
|
||||||
root: this,
|
|
||||||
parent: this._createCase(parentPath),
|
|
||||||
path: path
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return configCase;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function invokeConfig(config, object, opts = {}) {
|
|
||||||
util.defaults(opts, { media: 'lg', platform: 'ios' });
|
|
||||||
var { platform, media } = opts;
|
|
||||||
|
|
||||||
var passedCases = [config].concat(
|
|
||||||
Object.keys(config._cases)
|
|
||||||
.map(name => config._cases[name])
|
|
||||||
.filter(configCasePasses)
|
|
||||||
.sort(function(a,b) {
|
|
||||||
return a._path.length < b._path.length ? -1 : 1;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// Extend the given object with the values of all the passed cases, starting with the
|
|
||||||
// most specific.
|
|
||||||
var defaults = [object];
|
|
||||||
var behaviors = [];
|
|
||||||
for (let i = 0, ii = passedCases.length; i < ii; i++) {
|
|
||||||
defaults.push(passedCases[i]._values);
|
|
||||||
// Avoid allocating a new array for each passed case's array of behaviors
|
|
||||||
behaviors.push.apply(behaviors, passedCases[i].behaviors);
|
|
||||||
}
|
|
||||||
|
|
||||||
util.defaults.apply(null, defaults);
|
|
||||||
|
|
||||||
for (let i = 0, ii = behaviors.length; i < ii; i++) {
|
|
||||||
behaviors[i].call(object, object);
|
|
||||||
}
|
|
||||||
|
|
||||||
function configCasePasses(configCase) {
|
|
||||||
var path = configCase._path;
|
|
||||||
var key;
|
|
||||||
for (let i = 0, ii = path.length; i < ii; i++) {
|
|
||||||
if (!(media === path[i] || platform === path[i])) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,138 +0,0 @@
|
|||||||
import {IonConfig} from './config';
|
|
||||||
|
|
||||||
// TODO stop hardcoding platforms and media sizes
|
|
||||||
export function main() {
|
|
||||||
var rootConfig;
|
|
||||||
beforeEach(() => {
|
|
||||||
rootConfig = new IonConfig();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create a config one level down', () => {
|
|
||||||
var sub = rootConfig.platform('ios');
|
|
||||||
expect(sub._parent).toBe(rootConfig);
|
|
||||||
expect(sub._path).toEqual(['ios']);
|
|
||||||
expect(rootConfig._cases.ios).toBe(sub);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create a config two levels down', () => {
|
|
||||||
var sub1 = rootConfig.platform('ios');
|
|
||||||
var sub2 = sub1.media('lg');
|
|
||||||
expect(sub2._parent).toBe(sub1);
|
|
||||||
expect(sub1._parent).toBe(rootConfig);
|
|
||||||
expect(rootConfig._cases['ios lg']).toBe(sub2);
|
|
||||||
expect(rootConfig._cases.ios).toBe(sub1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('set should be chainable', () => {
|
|
||||||
expect(rootConfig.set()).toBe(rootConfig);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set values on the root', () => {
|
|
||||||
rootConfig.set({
|
|
||||||
letter: 'a'
|
|
||||||
});
|
|
||||||
expect(rootConfig.get('letter')).toBe('a');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should always return the same object for the same key', () => {
|
|
||||||
expect(rootConfig.platform('android')).toBe(rootConfig.platform('android'));
|
|
||||||
expect(rootConfig.platform('ios')).toBe(rootConfig.platform('ios'));
|
|
||||||
expect(rootConfig.media('lg')).toBe(rootConfig.media('lg'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the same object when nesting in different order', () => {
|
|
||||||
var sub1 = rootConfig.platform('ios').media('sm');
|
|
||||||
var sub2 = rootConfig.media('sm').platform('ios');
|
|
||||||
expect(sub1).toBe(sub2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the same object when nesting in different order for huge queries', () => {
|
|
||||||
var sub1 = rootConfig.platform('ios').media('sm').platform('android').media('lg');
|
|
||||||
var sub2 = rootConfig.media('sm').media('lg').platform('android').platform('ios');
|
|
||||||
expect(sub1).toBe(sub2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set values one level down and be chainable', () => {
|
|
||||||
rootConfig.set({ letter: 'a' });
|
|
||||||
var sub1 = rootConfig.platform('ios');
|
|
||||||
expect(sub1.get('letter')).toBe('a');
|
|
||||||
expect( sub1.set({ letter: 'b' }) ).toBe(sub1);
|
|
||||||
expect(sub1.get('letter')).toBe('b');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set values two levels down and be chainable', () => {
|
|
||||||
rootConfig.set({ letter: 'a' });
|
|
||||||
var sub1 = rootConfig.platform('ios');
|
|
||||||
sub1.set({ letter: 'b' });
|
|
||||||
var sub2 = sub1.media('lg');
|
|
||||||
expect(sub2.get('letter')).toBe('b');
|
|
||||||
expect( sub2.set({ letter: 'c' }) ).toBe(sub2);
|
|
||||||
expect(sub2.get('letter')).toBe('c');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use parent\'s value if its later set to undefined', () => {
|
|
||||||
rootConfig.set({ letter: 'a' });
|
|
||||||
var sub1 = rootConfig.platform('ios');
|
|
||||||
sub1.set({ letter: 'b' });
|
|
||||||
expect(sub1.get('letter')).toBe('b');
|
|
||||||
expect( sub1.unset('letter') ).toBe(sub1);
|
|
||||||
expect(sub1.get('letter')).toBe('a');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('when() as alias for media()', () => {
|
|
||||||
expect(rootConfig.when('lg')).toBe(rootConfig.media('lg'));
|
|
||||||
expect(rootConfig.when('bad')).toBe(rootConfig);
|
|
||||||
expect(rootConfig.when('lg')).not.toBe(rootConfig.when('ios'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('when() as alias for platform()', () => {
|
|
||||||
expect(rootConfig.platform('ios')).toBe(rootConfig.when('ios'));
|
|
||||||
expect(rootConfig.when('bad')).toBe(rootConfig);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('invokeConfig', function() {
|
|
||||||
|
|
||||||
it('should invoke defaults', () => {
|
|
||||||
var obj = {};
|
|
||||||
rootConfig.set('foo', 'bar');
|
|
||||||
rootConfig.invoke(obj);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should invoke defaults in nested whens', () => {
|
|
||||||
var obj = {};
|
|
||||||
rootConfig.set({ a: 'root', b: 'root' });
|
|
||||||
rootConfig.when('ios').set({b: 'ios', c: 'ios'});
|
|
||||||
rootConfig.when('ios').when('lg').set({ c: 'ios-lg', d: 'ios-lg' });
|
|
||||||
|
|
||||||
rootConfig.invoke(obj);
|
|
||||||
expect(obj).toEqual({
|
|
||||||
a: 'root',
|
|
||||||
b: 'ios',
|
|
||||||
c: 'ios-lg',
|
|
||||||
d: 'ios-lg'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should run behaviors', () => {
|
|
||||||
var obj = {};
|
|
||||||
rootConfig.behavior(instance => {
|
|
||||||
instance.foo = 'bar';
|
|
||||||
});
|
|
||||||
rootConfig.invoke(obj);
|
|
||||||
expect(obj.foo).toBe('bar');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should invoke behaviors in nested whens', () => {
|
|
||||||
var obj = {};
|
|
||||||
rootConfig.when('ios')
|
|
||||||
.behavior(o => o.ios = true)
|
|
||||||
.when('lg')
|
|
||||||
.behavior(o => o.lg = true)
|
|
||||||
rootConfig.invoke(obj);
|
|
||||||
expect(obj).toEqual({
|
|
||||||
ios: true,
|
|
||||||
lg: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
47
src/core/config/config-case.js
Normal file
47
src/core/config/config-case.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import * as util from '../../util';
|
||||||
|
import {platform} from '../platform/platform';
|
||||||
|
|
||||||
|
function isPlatform(key = '') {
|
||||||
|
return platform.isRegistered(key.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ConfigCase {
|
||||||
|
constructor({ root, parent, path }) {
|
||||||
|
this._root = root;
|
||||||
|
this._parent = parent;
|
||||||
|
this._path = path || [];
|
||||||
|
this._values = {};
|
||||||
|
this._component = null;
|
||||||
|
}
|
||||||
|
platform(key = '') {
|
||||||
|
if (isPlatform(key)) return this._root._addCase(key, this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
// media(key = '') {
|
||||||
|
// if (isMedia(key)) return this._root._addCase(key, this);
|
||||||
|
// return this;
|
||||||
|
// }
|
||||||
|
when(condition = '') {
|
||||||
|
if (isPlatform(condition)) {
|
||||||
|
return this._root._addCase(condition, this);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
component(Class) {
|
||||||
|
this._component = Class;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
set(obj) {
|
||||||
|
util.extend(this._values, obj);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
unset(key) {
|
||||||
|
delete this._values[key];
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
get(key) {
|
||||||
|
return util.isDefined(this._values[key]) ?
|
||||||
|
this._values[key] :
|
||||||
|
(this._parent ? this._parent.get(key) : undefined);
|
||||||
|
}
|
||||||
|
}
|
@ -1,100 +1,29 @@
|
|||||||
import getPlatform from '../platform/platform';
|
import {platform} from '../platform/platform';
|
||||||
|
import {ConfigCase} from './config-case';
|
||||||
import * as util from '../../util';
|
import * as util from '../../util';
|
||||||
|
|
||||||
// TODO stop hardcoding platforms and media sizes
|
// TODO stop hardcoding platforms and media sizes
|
||||||
|
|
||||||
/*
|
/*
|
||||||
config
|
@ConfigPlatform({
|
||||||
.set({ side: 'left' })
|
for: AsideBase
|
||||||
.set('threshold', 50)
|
platform: 'android',
|
||||||
.platform('ios')
|
defaults: {
|
||||||
.set('side', 'top')
|
type: 'reveal'
|
||||||
.unset('threshold')
|
}
|
||||||
.media('lg')
|
})
|
||||||
.set('side', 'right')
|
class AndroidAside extends AsideBase {}
|
||||||
|
|
||||||
config.platform('ios')
|
```@ConfigCase({
|
||||||
.behavior(function() {
|
for: AsideBase,
|
||||||
do something
|
condition: instance => instance.type === 'reveal'
|
||||||
})
|
})
|
||||||
.defaults({
|
class AsideReveal {
|
||||||
side: 'right'
|
constructor(aside: AsideBase) {}
|
||||||
})
|
}
|
||||||
|
|
||||||
config.platform('ios').media('tablet')
|
|
||||||
.defaults({
|
|
||||||
side: 'bottom'
|
|
||||||
});
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export class Config extends ConfigCase {
|
||||||
/*
|
|
||||||
User wants to remove the default behavior for sidemenu, but that's stuck under `.platform('ios').`
|
|
||||||
|
|
||||||
config.platform('ios').media('tablet') === config.media('tablet').platform('ios')
|
|
||||||
*/
|
|
||||||
var QUERIES = {
|
|
||||||
sm: true,
|
|
||||||
md: true,
|
|
||||||
lg: true
|
|
||||||
};
|
|
||||||
var PLATFORMS = {
|
|
||||||
ios: true,
|
|
||||||
android: true
|
|
||||||
};
|
|
||||||
|
|
||||||
function isPlatform(key = '') {
|
|
||||||
return key.toLowerCase() in PLATFORMS;
|
|
||||||
}
|
|
||||||
function isMedia(key = '') {
|
|
||||||
return key.toLowerCase() in QUERIES;
|
|
||||||
}
|
|
||||||
class ConfigCase {
|
|
||||||
constructor({ root, parent, path }) {
|
|
||||||
this._root = root;
|
|
||||||
this._parent = parent;
|
|
||||||
this._path = path || [];
|
|
||||||
this._values = {};
|
|
||||||
this.behaviors = [];
|
|
||||||
}
|
|
||||||
platform(key = '') {
|
|
||||||
if (isPlatform(key)) return this._root._addCase(key, this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
media(key = '') {
|
|
||||||
if (isMedia(key)) return this._root._addCase(key, this);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
when(condition = '') {
|
|
||||||
if (isPlatform(condition) || isMedia(condition)) {
|
|
||||||
return this._root._addCase(condition, this);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
behavior(fn) {
|
|
||||||
this.behaviors.push(fn);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
set(a, b) {
|
|
||||||
if (util.isString(a)) {
|
|
||||||
this._values[a] = b;
|
|
||||||
} else {
|
|
||||||
util.extend(this._values, a || {});
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
unset(key) {
|
|
||||||
delete this._values[key];
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
get(key) {
|
|
||||||
return util.isDefined(this._values[key]) ?
|
|
||||||
this._values[key] :
|
|
||||||
(this._parent ? this._parent.get(key) : undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class IonConfig extends ConfigCase {
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._root = this;
|
this._root = this;
|
||||||
this._cases = {};
|
this._cases = {};
|
||||||
@ -108,7 +37,7 @@ export class IonConfig extends ConfigCase {
|
|||||||
return invokeConfig(this, instance);
|
return invokeConfig(this, instance);
|
||||||
}
|
}
|
||||||
_addCase(key, baseCase) {
|
_addCase(key, baseCase) {
|
||||||
var path = baseCase._path.slice();
|
let path = baseCase._path.slice();
|
||||||
path.push(key);
|
path.push(key);
|
||||||
|
|
||||||
// Remove empties & duplicates
|
// Remove empties & duplicates
|
||||||
@ -125,10 +54,10 @@ export class IonConfig extends ConfigCase {
|
|||||||
}
|
}
|
||||||
_createCase(path) {
|
_createCase(path) {
|
||||||
if (!path.length) return this;
|
if (!path.length) return this;
|
||||||
var pathStr = path.join(' ');
|
let pathStr = path.join(' ');
|
||||||
var configCase = this._cases[pathStr];
|
let configCase = this._cases[pathStr];
|
||||||
if (!configCase) {
|
if (!configCase) {
|
||||||
var parentPath = path.slice(0, path.length - 1);
|
let parentPath = path.slice(0, path.length - 1);
|
||||||
configCase = this._cases[pathStr] = new ConfigCase({
|
configCase = this._cases[pathStr] = new ConfigCase({
|
||||||
root: this,
|
root: this,
|
||||||
parent: this._createCase(parentPath),
|
parent: this._createCase(parentPath),
|
||||||
@ -139,11 +68,10 @@ export class IonConfig extends ConfigCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invokeConfig(config, object, opts = {}) {
|
export function invokeConfig(config, object) {
|
||||||
util.defaults(opts, { media: 'lg', platform: 'ios' });
|
let platformName = platform.get().name;
|
||||||
var { platform, media } = opts;
|
|
||||||
|
|
||||||
var passedCases = [config].concat(
|
let passedCases = [config].concat(
|
||||||
Object.keys(config._cases)
|
Object.keys(config._cases)
|
||||||
.map(name => config._cases[name])
|
.map(name => config._cases[name])
|
||||||
.filter(configCasePasses)
|
.filter(configCasePasses)
|
||||||
@ -154,25 +82,25 @@ export function invokeConfig(config, object, opts = {}) {
|
|||||||
|
|
||||||
// Extend the given object with the values of all the passed cases, starting with the
|
// Extend the given object with the values of all the passed cases, starting with the
|
||||||
// most specific.
|
// most specific.
|
||||||
var defaults = [object];
|
let defaults = [object];
|
||||||
var behaviors = [];
|
// Also find the most specific case with a component that we should use.
|
||||||
|
let ComponentToUse;
|
||||||
for (let i = 0, ii = passedCases.length; i < ii; i++) {
|
for (let i = 0, ii = passedCases.length; i < ii; i++) {
|
||||||
defaults.push(passedCases[i]._values);
|
defaults.push(passedCases[i]._values);
|
||||||
// Avoid allocating a new array for each passed case's array of behaviors
|
if (passedCases[i]._component) {
|
||||||
behaviors.push.apply(behaviors, passedCases[i].behaviors);
|
ComponentToUse = passedCases[i]._component;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
util.defaults.apply(null, defaults);
|
util.defaults.apply(null, defaults);
|
||||||
|
|
||||||
for (let i = 0, ii = behaviors.length; i < ii; i++) {
|
return ComponentToUse;
|
||||||
behaviors[i].call(object, object);
|
|
||||||
}
|
|
||||||
|
|
||||||
function configCasePasses(configCase) {
|
function configCasePasses(configCase) {
|
||||||
var path = configCase._path;
|
let path = configCase._path;
|
||||||
var key;
|
let key;
|
||||||
for (let i = 0, ii = path.length; i < ii; i++) {
|
for (let i = 0, ii = path.length; i < ii; i++) {
|
||||||
if (!(media === path[i] || platform === path[i])) return false;
|
if (platformName !== path[i]) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
var platforms = [];
|
import * as util from '../../util';
|
||||||
|
|
||||||
// TODO(ajoslin): move this to a facade somewhere else?
|
|
||||||
var ua = window.navigator.userAgent;
|
|
||||||
|
|
||||||
class Platform {
|
class Platform {
|
||||||
constructor({
|
constructor(options) {
|
||||||
name,
|
util.extend(this, options);
|
||||||
matcher
|
|
||||||
}) {
|
|
||||||
this.name = name;
|
|
||||||
this.matcher = matcher;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlatformController {
|
class PlatformController {
|
||||||
|
current: Platform;
|
||||||
constructor() {
|
constructor() {
|
||||||
this.registry = [];
|
this.registry = [];
|
||||||
}
|
}
|
||||||
@ -21,11 +15,19 @@ class PlatformController {
|
|||||||
this.current = platform;
|
this.current = platform;
|
||||||
}
|
}
|
||||||
get() {
|
get() {
|
||||||
return platform;
|
return this.current;
|
||||||
}
|
}
|
||||||
register(platform) {
|
register(platform) {
|
||||||
|
if (!platform instanceof Platform) {
|
||||||
|
platform = new Platform(platform);
|
||||||
|
}
|
||||||
this.registry.push(platform);
|
this.registry.push(platform);
|
||||||
}
|
}
|
||||||
|
isRegistered(platformName) {
|
||||||
|
return this.registry.some(platform => {
|
||||||
|
return platform.name === platformName;
|
||||||
|
});
|
||||||
|
}
|
||||||
detect() {
|
detect() {
|
||||||
for (let platform of this.registry) {
|
for (let platform of this.registry) {
|
||||||
if (platform.matcher()) {
|
if (platform.matcher()) {
|
||||||
@ -37,18 +39,23 @@ class PlatformController {
|
|||||||
|
|
||||||
export let platform = new PlatformController();
|
export let platform = new PlatformController();
|
||||||
|
|
||||||
platform.register(new Platform({
|
// TODO(ajoslin): move this to a facade somewhere else?
|
||||||
name: 'android',
|
var ua = window.navigator.userAgent;
|
||||||
matcher: () => {
|
|
||||||
return /android/i.test(ua)
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
platform.register(new Platform({
|
|
||||||
name: 'ios',
|
|
||||||
matcher: () => {
|
|
||||||
return /iPhone|iPad|iPod/.test(ua)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
function detectPlatform() {
|
// TODO(ajoslin): move these to their own files
|
||||||
}
|
platform.register({
|
||||||
|
name: 'android',
|
||||||
|
matcher() {
|
||||||
|
return /android/i.test(ua);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
platform.register({
|
||||||
|
name: 'ios',
|
||||||
|
// For now always default to ios
|
||||||
|
matcher() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
platform.set( platform.detect() );
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
|
|
||||||
export function getPlatform() {
|
|
||||||
return 'android';
|
|
||||||
}
|
|
Reference in New Issue
Block a user