feat(config): automatically add css classes

This commit is contained in:
Andrew
2015-03-26 15:44:15 -06:00
parent d33c70ae63
commit 75b14fbe32
9 changed files with 152 additions and 124 deletions

View File

@ -5,6 +5,7 @@
"canonical-path": "0.0.2", "canonical-path": "0.0.2",
"connect": "^3.3.4", "connect": "^3.3.4",
"del": "~1.1.1", "del": "~1.1.1",
"es6-module-loader": "^0.11.2",
"gulp": "~3.8.10", "gulp": "~3.8.10",
"gulp-concat": "~2.5.0", "gulp-concat": "~2.5.0",
"gulp-debug": "~2.0.1", "gulp-debug": "~2.0.1",
@ -25,8 +26,10 @@
"q": "^1.2.0", "q": "^1.2.0",
"request": "^2.53.0", "request": "^2.53.0",
"serve-static": "~1.8.1", "serve-static": "~1.8.1",
"systemjs": "^0.11.3",
"systemjs-builder": "^0.9.1", "systemjs-builder": "^0.9.1",
"through2": "~0.6.3", "through2": "~0.6.3",
"traceur-runtime": "0.0.59",
"yargs": "^3.6.0" "yargs": "^3.6.0"
}, },
"dependencies": { "dependencies": {

View File

@ -8,12 +8,16 @@ module.exports = function(config) {
frameworks: ['jasmine'], frameworks: ['jasmine'],
files: [ files: [
// Sources and specs. 'node_modules/systemjs/dist/system.js',
// Loaded through the es6-module-loader, in `test-main.js`. 'node_modules/es6-module-loader/dist/es6-module-loader.js',
{pattern: 'dist/ionic/**/*.js', included: false}, 'node_modules/traceur-runtime/index.js',
] 'node_modules/zone.js/zone.js',
.concat(buildConfig.lib) 'node_modules/zone.js/long-stack-trace-zone.js',
.concat('scripts/test/test-main.js'), 'dist/lib/angular2.js',
'jspm-config.js',
'scripts/test/test-main.js',
{pattern: 'src/**/*.spec.js', included: false},
],
exclude: [ exclude: [
'src/**/examples/**' 'src/**/examples/**'

View File

@ -8,7 +8,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 50;
// we will call `__karma__.start()` later, once all the specs are loaded. // we will call `__karma__.start()` later, once all the specs are loaded.
__karma__.loaded = function() {}; __karma__.loaded = function() {};
System.baseURL = 'http://localhost:9876/base/dist/'; System.baseURL = 'http://localhost:9876/base/';
// So that we can import packages like `core/foo`, instead of `core/src/foo`. // So that we can import packages like `core/foo`, instead of `core/src/foo`.
// System.paths = { // System.paths = {
@ -37,7 +37,7 @@ Promise.all(
}); });
function onlySpecFiles(path) { function onlySpecFiles(path) {
return /_spec\.js$/.test(path); return /\.spec\.js$/.test(path);
} }
function file2moduleName(filePath) { function file2moduleName(filePath) {
return filePath.replace(/\\/g, '/') return filePath.replace(/\\/g, '/')

View File

@ -3,19 +3,6 @@ import {ComponentConfig} from '../../core/config/config'
import * as types from './extensions/types/types' import * as types from './extensions/types/types'
import * as gestures from './extensions/gestures/gestures'; import * as gestures from './extensions/gestures/gestures';
export let AsideConfig = new ComponentConfig()
AsideConfig.property('side')
.when('left', gestures.LeftAsideGesture)
.when('right', gestures.RightAsideGesture)
.when('top', gestures.TopAsideGesture)
.when('bottom', gestures.BottomAsideGesture)
AsideConfig.property('type')
.when('overlay', types.AsideTypeOverlay)
.when('push', types.AsideTypePush)
.when('reveal', types.AsideTypeReveal)
@Component({ @Component({
selector: 'ion-aside', selector: 'ion-aside',
bind: { bind: {
@ -31,36 +18,35 @@ AsideConfig.property('type')
export class Aside { export class Aside {
constructor( constructor(
@NgElement() element: NgElement, @NgElement() element: NgElement,
@PropertySetter('style.transform') transformSetter: Function, configFactory: AsideConfig
/* propertSetter doesn't work for classes right now */
config: AsideConfig
) { ) {
this.domElement = element.domElement this.domElement = element.domElement
// TODO inject constant instead of using domElement.getAttribute // TODO inject constant instead of using domElement.getAttribute
// TODO let config / platform handle defaults transparently // TODO let config / platform handle defaults transparently
let side = this.side = this.domElement.getAttribute('side') || 'left' this.side = this.domElement.getAttribute('side') || 'left'
let type = this.type = this.domElement.getAttribute('type') || 'overlay' this.type = this.domElement.getAttribute('type') || 'overlay'
this.delegates = config.invoke(this, { side, type })
this.config = configFactory.create(this);
this.gestureDelegate = this.config.getDelegate('gesture');
this.typeDelegate = this.config.getDelegate('type');
this.domElement.classList.add(side)
this.domElement.addEventListener('transitionend', ev => { this.domElement.addEventListener('transitionend', ev => {
this.setChanging(false) this.setChanging(false)
}) })
} }
setTransform(transform) { setTransform(transform) {
this.delegates.type.setTransform(transform) this.typeDelegate.setTransform(transform)
} }
setSliding(isSliding) { setSliding(isSliding) {
if (isSliding !== this.isSliding) { if (isSliding !== this.isSliding) {
this.delegates.type.setSliding(isSliding) this.typeDelegate.setSliding(isSliding)
} }
} }
setChanging(isChanging) { setChanging(isChanging) {
if (isChanging !== this.isChanging) { if (isChanging !== this.isChanging) {
this.isChanging = isChanging this.isChanging = isChanging
this.domElement.classList[isChanging ? 'add' : 'remove']('changing') this.domElement.classList[isChanging ? 'add' : 'remove']('changing');
} }
} }
setOpen(isOpen) { setOpen(isOpen) {
@ -68,8 +54,24 @@ export class Aside {
this.isOpen = isOpen this.isOpen = isOpen
this.setChanging(true) this.setChanging(true)
requestAnimationFrame(() => { requestAnimationFrame(() => {
this.delegates.type.setOpen(isOpen) this.typeDelegate.setOpen(isOpen)
}) })
} }
} }
} }
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)

View File

@ -2,7 +2,7 @@ $aside-width: 304px;
$aside-height: 304px; $aside-height: 304px;
$aside-transition: 0.3s linear transform; $aside-transition: 0.3s linear transform;
ion-aside { .aside {
display: block; display: block;
position: absolute; position: absolute;
@ -17,7 +17,7 @@ ion-aside {
display: none; display: none;
} }
&.left { &.aside-left {
width: $aside-width; width: $aside-width;
left: -$aside-width; left: -$aside-width;
top: 0; top: 0;
@ -25,11 +25,11 @@ ion-aside {
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
&.open, &.open,
&.type-reveal { &.aside-reveal {
transform: translate3d($aside-width,0,0); transform: translate3d($aside-width,0,0);
} }
} }
&.right { &.aside-right {
width: $aside-width; width: $aside-width;
left: 100%; left: 100%;
top: 0; top: 0;
@ -37,11 +37,11 @@ ion-aside {
transform: translate3d(0,0,0); transform: translate3d(0,0,0);
&.open, &.open,
&.type-reveal { &.aside-reveal {
transform: translate3d(-$aside-width,0,0); transform: translate3d(-$aside-width,0,0);
} }
} }
&.top { &.aside-top {
height: $aside-width; height: $aside-width;
top: -$aside-width; top: -$aside-width;
left: 0; left: 0;
@ -49,11 +49,11 @@ ion-aside {
transform: translate3d(0,0,0); transform: translate3d(0,0,0);
&.open, &.open,
&.type-reveal { &.aside-reveal {
transform: translate3d(0,$aside-width,0); transform: translate3d(0,$aside-width,0);
} }
} }
&.bottom { &.aside-bottom {
height: $aside-width; height: $aside-width;
top: 100%; top: 100%;
left: 0; left: 0;
@ -78,13 +78,3 @@ ion-aside {
transform: translate3d(-$aside-width,0,0); transform: translate3d(-$aside-width,0,0);
} }
} }
ion-aside-parent {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: block;
overflow:hidden;
}

View File

@ -1,4 +1,5 @@
import {Aside} from '../../aside'; import {Aside} from '../../aside';
//TODO: figure out way to get rid of all the ../../../../
import {SlideEdgeGesture} from '../../../../core/gestures/slide-edge-gesture'; import {SlideEdgeGesture} from '../../../../core/gestures/slide-edge-gesture';
class AsideGesture extends SlideEdgeGesture { class AsideGesture extends SlideEdgeGesture {

View File

@ -26,7 +26,7 @@ let contentManipulator = {
} }
} }
class AsideType { export class AsideType {
constructor(aside) { constructor(aside) {
this.aside = aside; this.aside = aside;

View File

@ -1,42 +1,71 @@
import {platform} from '../platform/platform'; import {platform} from '../platform/platform'
// import {ConfigCase} from './config-case'; import * as util from '../../util'
import * as util from '../../util';
/* /*
let MyConfig = new ComponentConfig(); let MyConfig = new ComponentConfig(MyComponent)
MyConfig.property('side') MyConfig.classes('classes')
.when('left', LeftSlideGesture) MyConfig.delegate('gesture')
.when('right', RightSlideGesture) .when({side: 'left'}, LeftAsideGesture)
.when('top', TopSlideGesture) .when({side: 'right'}, RightAsideGesture)
.when('bottom', BottomSlideGesture) .when({side: 'top'}, TopAsideGesture)
.when({side: 'bottom'}, BottomAsideGesture)
*/ */
export function ComponentConfig() { export function ComponentConfig(ComponentConstructor) {
let componentCssName = util.pascalCaseToDashCase(ComponentConstructor.name)
return class Config { return class Config {
static property(propertyName) { static classes() {
let self; Config.classProperties || (Config.classProperties = [])
return (self = { Config.classProperties.push.apply(Config.classProperties, arguments)
when(propertyValue, Class) {
Config.addCase(propertyName, propertyValue, Class);
return self;
}
});
} }
static addCase(property, value, Class) { static delegate(delegateName) {
Config.registry || (Config.registry = {}); let self = {
(Config.registry[property] || (Config.registry[property] = {}))[value] = Class; when(condition, DelegateConstructor) {
} Config.addCase(delegateName, condition, DelegateConstructor)
invoke(instance, properties = {}) { return self
let delegates = {};
for (let property in properties) {
let value = properties[property];
let propertyRegistry = Config.registry && Config.registry[property] || {};
if (propertyRegistry[value]) {
delegates[property] = new propertyRegistry[value](instance);
} }
} }
return delegates; return self
} }
static addCase(delegateName, condition, DelegateConstructor) {
Config.registry || (Config.registry = {})
var array = (Config.registry[delegateName] || (Config.registry[delegateName] = []))
let callback = condition
if (util.isObject(callback)) {
// Support eg `{side: 'left'}` as a condition
callback = (instance) => {
for (let key in condition) {
if (condition.hasOwnProperty(key) && instance[key] !== condition[key]) {
return false
}
}
return true
}
}
array.unshift({ callback, DelegateConstructor })
}
create(instance) {
instance.domElement.classList.add(componentCssName)
for (let i = 0; i < (Config.classProperties || []).length; i++) {
let propertyValue = instance[Config.classProperties[i]]
instance.domElement.classList.add(`${componentCssName}-${propertyValue}`)
}
return {
getDelegate(delegateName) {
let registry = Config.registry && Config.registry[delegateName] || []
for (let i = 0; i < registry.length; i++) {
let condition = registry[i]
if (condition.callback(instance)) {
return new condition.DelegateConstructor(instance)
}
}
}
}
}
} }
} }
@ -65,84 +94,84 @@ class AsideReveal {
// export class Config extends ConfigCase { // export class Config extends ConfigCase {
// constructor() { // constructor() {
// this._root = this; // this._root = this
// this._cases = {}; // this._cases = {}
// super({ // super({
// root: this, // root: this,
// parent: null, // parent: null,
// path: '' // path: ''
// }); // })
// } // }
// invoke(instance) { // invoke(instance) {
// return invokeConfig(this, instance); // return invokeConfig(this, instance)
// } // }
// _addCase(key, baseCase) { // _addCase(key, baseCase) {
// let path = baseCase._path.slice(); // let path = baseCase._path.slice()
// path.push(key); // path.push(key)
// // Remove empties & duplicates // // Remove empties & duplicates
// path = path // path = path
// .filter((value, index) => { // .filter((value, index) => {
// return value && path.indexOf(value) === index; // return value && path.indexOf(value) === index
// }) // })
// .sort(); // .sort()
// if (path.join(' ') === baseCase._path.join(' ')) { // if (path.join(' ') === baseCase._path.join(' ')) {
// return baseCase; // return baseCase
// } // }
// return this._createCase(path); // return this._createCase(path)
// } // }
// _createCase(path) { // _createCase(path) {
// if (!path.length) return this; // if (!path.length) return this
// let pathStr = path.join(' '); // let pathStr = path.join(' ')
// let configCase = this._cases[pathStr]; // let configCase = this._cases[pathStr]
// if (!configCase) { // if (!configCase) {
// let 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),
// path: path // path: path
// }); // })
// } // }
// return configCase; // return configCase
// } // }
// } // }
// export function invokeConfig(config, object) { // export function invokeConfig(config, object) {
// let platformName = platform.get().name; // let platformName = platform.get().name
// let 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)
// .sort(function(a,b) { // .sort(function(a,b) {
// return a._path.length < b._path.length ? -1 : 1; // return a._path.length < b._path.length ? -1 : 1
// }) // })
// ); // )
// // 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.
// let defaults = [object]; // let defaults = [object]
// // Also find the most specific case with a component that we should use. // // Also find the most specific case with a component that we should use.
// let ComponentToUse; // 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)
// if (passedCases[i]._component) { // if (passedCases[i]._component) {
// ComponentToUse = passedCases[i]._component; // ComponentToUse = passedCases[i]._component
// } // }
// } // }
// util.defaults.apply(null, defaults); // util.defaults.apply(null, defaults)
// return ComponentToUse; // return ComponentToUse
// function configCasePasses(configCase) { // function configCasePasses(configCase) {
// let path = configCase._path; // let path = configCase._path
// let key; // let key
// for (let i = 0, ii = path.length; i < ii; i++) { // for (let i = 0, ii = path.length i < ii i++) {
// if (platformName !== path[i]) return false; // if (platformName !== path[i]) return false
// } // }
// return true; // return true
// } // }
// } // }

View File

@ -28,19 +28,18 @@ export function defaults(dest) {
return dest; return dest;
} }
export function isString(val) { export let isString = val => typeof val === 'string';
return 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 function pascalCaseToDashCase(str = '') {
return str.charAt(0).toLowerCase() + str.substring(1).replace(/[A-Z]/g, function(match) {
return '-' + match.toLowerCase()
})
} }
export function isFunction(val) { export let array = {
return typeof val === 'function';
}
export function isDefined(val) {
return typeof val !== 'undefined';
}
export var array = {
unique(array) { unique(array) {
return array.filter(function(value, index) { return array.filter(function(value, index) {
return array.indexOf(value) === index; return array.indexOf(value) === index;