From 4ba305305f9aa9f1ff0de02a1a7c87d3657337f8 Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 31 Mar 2015 11:35:45 -0600 Subject: [PATCH] new config, aside config --- src/components/aside/aside.js | 66 ++++++++++++++++------------ src/components/aside/aside.scss | 14 +++--- src/config/component.js | 78 +++++++++++++++++++++++++++++++++ src/platform/platform.js | 11 +++-- src/util.js | 9 ++-- 5 files changed, 136 insertions(+), 42 deletions(-) create mode 100644 src/config/component.js diff --git a/src/components/aside/aside.js b/src/components/aside/aside.js index 5a90efc5df..ecba2f51da 100644 --- a/src/components/aside/aside.js +++ b/src/components/aside/aside.js @@ -2,22 +2,7 @@ import {Component, Template, Inject, Parent, NgElement} from 'angular2/angular2' import {ComponentConfig} from 'ionic2/config/component-config' import * as types from 'ionic2/components/aside/extensions/types' import * as gestures from 'ionic2/components/aside/extensions/gestures'; - -export let AsideConfig = new ComponentConfig('aside') - -AsideConfig.classes('side', 'type') - -AsideConfig.delegate('gesture') - .when({side: 'left'}, gestures.LeftAsideGesture) - .when({side: 'right'}, gestures.RightAsideGesture) - .when({side: 'top'}, gestures.TopAsideGesture) - .when({side: 'bottom'}, gestures.BottomAsideGesture) - -AsideConfig.delegate('type') - .when({type: 'overlay'}, types.AsideTypeOverlay) - .when({type: 'push'}, types.AsideTypePush) - .when({type: 'reveal'}, types.AsideTypeReveal) - +import {IonicComponent} from 'ionic2/config/component' @Component({ selector: 'ion-aside', @@ -25,26 +10,23 @@ AsideConfig.delegate('type') content: 'content', side: 'side', dragThreshold: 'dragThreshold' - }, - services: [AsideConfig] + } }) @Template({ inline: `` }) export class Aside { constructor( - @NgElement() element: NgElement, - configFactory: AsideConfig + @NgElement() element: NgElement ) { this.domElement = element.domElement - // TODO inject constant instead of using domElement.getAttribute - // TODO let config / platform handle defaults transparently - this.side = this.domElement.getAttribute('side') || 'left' - this.type = this.domElement.getAttribute('type') || 'overlay' - this.config = configFactory.create(this); - this.gestureDelegate = this.config.getDelegate('gesture'); - this.typeDelegate = this.config.getDelegate('type'); + // FIXME(ajoslin): have to wait for setTimeout for bindings to apply. + setTimeout(() => { + this.config = Aside.config.invoke(this) + this.gestureDelegate = this.config.getDelegate('gesture'); + this.typeDelegate = this.config.getDelegate('type'); + }) this.domElement.addEventListener('transitionend', ev => { this.setChanging(false) @@ -75,3 +57,33 @@ export class Aside { } } } + +new IonicComponent(Aside, { + bind: { + side: { + default: 'left' + }, + type: { + ios: 'reveal', + android: 'overlay', + default: 'overlay', + }, + dragThreshold: {}, + content: {}, + }, + delegates: { + gesture: [ + [instance => instance.side == 'top', gestures.TopAsideGesture], + [instance => instance.side == 'bottom', gestures.BottomAsideGesture], + [instance => instance.side == 'right', gestures.RightAsideGesture], + [instance => instance.side == 'left', gestures.LeftAsideGesture] + ], + type: [ + [instance => instance.type == 'overlay', types.AsideTypeOverlay], + [instance => instance.type == 'reveal', types.AsideTypeReveal], + [instance => instance.type == 'push', types.AsideTypePush], + ] + } +}) + + diff --git a/src/components/aside/aside.scss b/src/components/aside/aside.scss index c111f414b9..b7a2b9ac8a 100644 --- a/src/components/aside/aside.scss +++ b/src/components/aside/aside.scss @@ -17,7 +17,7 @@ $aside-transition: 0.3s linear transform; display: none; } - &.aside-left { + &[side=left] { width: $aside-width; left: -$aside-width; top: 0; @@ -25,11 +25,11 @@ $aside-transition: 0.3s linear transform; transform: translate3d(0, 0, 0); &.open, - &.aside-reveal { + &[type=reveal] { transform: translate3d($aside-width,0,0); } } - &.aside-right { + &[side=right] { width: $aside-width; left: 100%; top: 0; @@ -37,11 +37,11 @@ $aside-transition: 0.3s linear transform; transform: translate3d(0,0,0); &.open, - &.aside-reveal { + &[type=reveal] { transform: translate3d(-$aside-width,0,0); } } - &.aside-top { + &[side=top] { height: $aside-width; top: -$aside-width; left: 0; @@ -49,11 +49,11 @@ $aside-transition: 0.3s linear transform; transform: translate3d(0,0,0); &.open, - &.aside-reveal { + &[type=reveal] { transform: translate3d(0,$aside-width,0); } } - &.aside-bottom { + &[side=bottom] { height: $aside-width; top: 100%; left: 0; diff --git a/src/config/component.js b/src/config/component.js new file mode 100644 index 0000000000..0349cea5bf --- /dev/null +++ b/src/config/component.js @@ -0,0 +1,78 @@ +import * as util from 'ionic2/util' +import {platform} from 'ionic2/platform/platform' + +let platforms = Object.keys(platform.registry) +let platformName = platform.getName() + +export class IonicComponent { + constructor(ComponentClass, { + bind, + delegates + }) { + // TODO give errors if not providing valid delegates + ComponentClass.config = this + this.componentCssName = util.pascalCaseToDashCase(ComponentClass.name) + + this.bind = bind || (bind = {}) + for (let attrName in bind) { + let binding = bind[attrName] + if (util.isObject(binding)) { + binding.property || (binding.property = attrName) + // TODO recompute defaultValue when user possibly adds a binding + binding._defaultValue = binding[platformName] || binding.default; + } + } + + this.delegates = delegates || (delegates = {}) + // for (let delegateName of delegates) { + // let delegate = delegates[delegateName] + // } + } + _computeDefaultValue(binding = {}) { + } + + invoke(instance) { + let config = this + instance.domElement.classList.add(this.componentCssName) + instance.domElement.classList.add(`${this.componentCssName}-${platformName}`) + + for (let attrName in this.bind) { + let binding = this.bind[attrName] + let defaultValue = binding._defaultValue + if (!instance[binding.property] && defaultValue) { + instance[binding.property] = defaultValue + instance.domElement.setAttribute(attrName, defaultValue) + } + } + + return { + getDelegate(delegateName) { + let cases = (config.delegates || {})[delegateName] || [] + for (let i = 0; i < cases.length; i++) { + let delegateCase = cases[i] + try { + if (util.isArray(delegateCase)) { + if (delegateCase[0](instance)) return new delegateCase[1](instance) + } else { + return new delegateCase(instance) + } + }catch(e){debugger;} + } + } + } + } + +} + +/* +@IonicComponent({ + selector: 'ion-back-button', + bind: { + icon: { + ios: 'ion-back-ios', + android: 'ion-back-android', + default: 'ion-back' + } + } +}) +*/ diff --git a/src/platform/platform.js b/src/platform/platform.js index 2bce00da3f..ceb5d8184f 100644 --- a/src/platform/platform.js +++ b/src/platform/platform.js @@ -11,7 +11,7 @@ class Platform { class PlatformController { current: Platform; constructor() { - this.registry = [] + this.registry = {} } set(platform) { @@ -21,10 +21,13 @@ class PlatformController { get() { return this.current } + getName() { + return this.current && this.current.name + } register(platform) { if (!platform instanceof Platform) platform = new Platform(platform) - this.registry.push(platform) + this.registry[platform.name] = platform } setDefaultPlatform(platform) { @@ -39,8 +42,8 @@ class PlatformController { } detect() { - for (let platform of this.registry) { - if (platform.matcher()) { + for (let name in this.registry) { + if (this.registry[name].matcher()) { return platform } } diff --git a/src/util.js b/src/util.js index cd4290e881..c0ff70d90d 100644 --- a/src/util.js +++ b/src/util.js @@ -28,10 +28,11 @@ export function defaults(dest) { return dest; } -export let isString = val => typeof val === 'string' -export let isFunction = val => typeof val === 'function' -export let isDefined = val => typeof val === 'undefined' -export let isObject = val => typeof val === 'object' +export const isString = val => typeof val === 'string' +export const isFunction = val => typeof val === 'function' +export const isDefined = val => typeof val === 'undefined' +export const isObject = val => typeof val === 'object' +export const isArray = Array.isArray export function pascalCaseToDashCase(str = '') { return str.charAt(0).toLowerCase() + str.substring(1).replace(/[A-Z]/g, match => {