mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 03:32:21 +08:00
feat(config): automatically add css classes
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
"canonical-path": "0.0.2",
|
||||
"connect": "^3.3.4",
|
||||
"del": "~1.1.1",
|
||||
"es6-module-loader": "^0.11.2",
|
||||
"gulp": "~3.8.10",
|
||||
"gulp-concat": "~2.5.0",
|
||||
"gulp-debug": "~2.0.1",
|
||||
@ -25,8 +26,10 @@
|
||||
"q": "^1.2.0",
|
||||
"request": "^2.53.0",
|
||||
"serve-static": "~1.8.1",
|
||||
"systemjs": "^0.11.3",
|
||||
"systemjs-builder": "^0.9.1",
|
||||
"through2": "~0.6.3",
|
||||
"traceur-runtime": "0.0.59",
|
||||
"yargs": "^3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -8,12 +8,16 @@ module.exports = function(config) {
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
files: [
|
||||
// Sources and specs.
|
||||
// Loaded through the es6-module-loader, in `test-main.js`.
|
||||
{pattern: 'dist/ionic/**/*.js', included: false},
|
||||
]
|
||||
.concat(buildConfig.lib)
|
||||
.concat('scripts/test/test-main.js'),
|
||||
'node_modules/systemjs/dist/system.js',
|
||||
'node_modules/es6-module-loader/dist/es6-module-loader.js',
|
||||
'node_modules/traceur-runtime/index.js',
|
||||
'node_modules/zone.js/zone.js',
|
||||
'node_modules/zone.js/long-stack-trace-zone.js',
|
||||
'dist/lib/angular2.js',
|
||||
'jspm-config.js',
|
||||
'scripts/test/test-main.js',
|
||||
{pattern: 'src/**/*.spec.js', included: false},
|
||||
],
|
||||
|
||||
exclude: [
|
||||
'src/**/examples/**'
|
||||
|
@ -8,7 +8,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 50;
|
||||
// we will call `__karma__.start()` later, once all the specs are loaded.
|
||||
__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`.
|
||||
// System.paths = {
|
||||
@ -37,7 +37,7 @@ Promise.all(
|
||||
});
|
||||
|
||||
function onlySpecFiles(path) {
|
||||
return /_spec\.js$/.test(path);
|
||||
return /\.spec\.js$/.test(path);
|
||||
}
|
||||
function file2moduleName(filePath) {
|
||||
return filePath.replace(/\\/g, '/')
|
||||
|
@ -3,19 +3,6 @@ import {ComponentConfig} from '../../core/config/config'
|
||||
import * as types from './extensions/types/types'
|
||||
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({
|
||||
selector: 'ion-aside',
|
||||
bind: {
|
||||
@ -31,36 +18,35 @@ AsideConfig.property('type')
|
||||
export class Aside {
|
||||
constructor(
|
||||
@NgElement() element: NgElement,
|
||||
@PropertySetter('style.transform') transformSetter: Function,
|
||||
/* propertSetter doesn't work for classes right now */
|
||||
config: AsideConfig
|
||||
configFactory: AsideConfig
|
||||
) {
|
||||
this.domElement = element.domElement
|
||||
|
||||
// TODO inject constant instead of using domElement.getAttribute
|
||||
// TODO let config / platform handle defaults transparently
|
||||
let side = this.side = this.domElement.getAttribute('side') || 'left'
|
||||
let type = this.type = this.domElement.getAttribute('type') || 'overlay'
|
||||
this.delegates = config.invoke(this, { side, type })
|
||||
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');
|
||||
|
||||
this.domElement.classList.add(side)
|
||||
this.domElement.addEventListener('transitionend', ev => {
|
||||
this.setChanging(false)
|
||||
})
|
||||
}
|
||||
|
||||
setTransform(transform) {
|
||||
this.delegates.type.setTransform(transform)
|
||||
this.typeDelegate.setTransform(transform)
|
||||
}
|
||||
setSliding(isSliding) {
|
||||
if (isSliding !== this.isSliding) {
|
||||
this.delegates.type.setSliding(isSliding)
|
||||
this.typeDelegate.setSliding(isSliding)
|
||||
}
|
||||
}
|
||||
setChanging(isChanging) {
|
||||
if (isChanging !== this.isChanging) {
|
||||
this.isChanging = isChanging
|
||||
this.domElement.classList[isChanging ? 'add' : 'remove']('changing')
|
||||
this.domElement.classList[isChanging ? 'add' : 'remove']('changing');
|
||||
}
|
||||
}
|
||||
setOpen(isOpen) {
|
||||
@ -68,8 +54,24 @@ export class Aside {
|
||||
this.isOpen = isOpen
|
||||
this.setChanging(true)
|
||||
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)
|
||||
|
||||
|
@ -2,7 +2,7 @@ $aside-width: 304px;
|
||||
$aside-height: 304px;
|
||||
$aside-transition: 0.3s linear transform;
|
||||
|
||||
ion-aside {
|
||||
.aside {
|
||||
display: block;
|
||||
position: absolute;
|
||||
|
||||
@ -17,7 +17,7 @@ ion-aside {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.left {
|
||||
&.aside-left {
|
||||
width: $aside-width;
|
||||
left: -$aside-width;
|
||||
top: 0;
|
||||
@ -25,11 +25,11 @@ ion-aside {
|
||||
|
||||
transform: translate3d(0, 0, 0);
|
||||
&.open,
|
||||
&.type-reveal {
|
||||
&.aside-reveal {
|
||||
transform: translate3d($aside-width,0,0);
|
||||
}
|
||||
}
|
||||
&.right {
|
||||
&.aside-right {
|
||||
width: $aside-width;
|
||||
left: 100%;
|
||||
top: 0;
|
||||
@ -37,11 +37,11 @@ ion-aside {
|
||||
|
||||
transform: translate3d(0,0,0);
|
||||
&.open,
|
||||
&.type-reveal {
|
||||
&.aside-reveal {
|
||||
transform: translate3d(-$aside-width,0,0);
|
||||
}
|
||||
}
|
||||
&.top {
|
||||
&.aside-top {
|
||||
height: $aside-width;
|
||||
top: -$aside-width;
|
||||
left: 0;
|
||||
@ -49,11 +49,11 @@ ion-aside {
|
||||
|
||||
transform: translate3d(0,0,0);
|
||||
&.open,
|
||||
&.type-reveal {
|
||||
&.aside-reveal {
|
||||
transform: translate3d(0,$aside-width,0);
|
||||
}
|
||||
}
|
||||
&.bottom {
|
||||
&.aside-bottom {
|
||||
height: $aside-width;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
@ -78,13 +78,3 @@ ion-aside {
|
||||
transform: translate3d(-$aside-width,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
ion-aside-parent {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: block;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {Aside} from '../../aside';
|
||||
//TODO: figure out way to get rid of all the ../../../../
|
||||
import {SlideEdgeGesture} from '../../../../core/gestures/slide-edge-gesture';
|
||||
|
||||
class AsideGesture extends SlideEdgeGesture {
|
||||
|
@ -26,7 +26,7 @@ let contentManipulator = {
|
||||
}
|
||||
}
|
||||
|
||||
class AsideType {
|
||||
export class AsideType {
|
||||
constructor(aside) {
|
||||
this.aside = aside;
|
||||
|
||||
|
@ -1,42 +1,71 @@
|
||||
import {platform} from '../platform/platform';
|
||||
// import {ConfigCase} from './config-case';
|
||||
import * as util from '../../util';
|
||||
import {platform} from '../platform/platform'
|
||||
import * as util from '../../util'
|
||||
|
||||
|
||||
/*
|
||||
let MyConfig = new ComponentConfig();
|
||||
MyConfig.property('side')
|
||||
.when('left', LeftSlideGesture)
|
||||
.when('right', RightSlideGesture)
|
||||
.when('top', TopSlideGesture)
|
||||
.when('bottom', BottomSlideGesture)
|
||||
let MyConfig = new ComponentConfig(MyComponent)
|
||||
MyConfig.classes('classes')
|
||||
MyConfig.delegate('gesture')
|
||||
.when({side: 'left'}, LeftAsideGesture)
|
||||
.when({side: 'right'}, RightAsideGesture)
|
||||
.when({side: 'top'}, TopAsideGesture)
|
||||
.when({side: 'bottom'}, BottomAsideGesture)
|
||||
*/
|
||||
export function ComponentConfig() {
|
||||
export function ComponentConfig(ComponentConstructor) {
|
||||
let componentCssName = util.pascalCaseToDashCase(ComponentConstructor.name)
|
||||
|
||||
return class Config {
|
||||
static property(propertyName) {
|
||||
let self;
|
||||
return (self = {
|
||||
when(propertyValue, Class) {
|
||||
Config.addCase(propertyName, propertyValue, Class);
|
||||
return self;
|
||||
static classes() {
|
||||
Config.classProperties || (Config.classProperties = [])
|
||||
Config.classProperties.push.apply(Config.classProperties, arguments)
|
||||
}
|
||||
});
|
||||
}
|
||||
static addCase(property, value, Class) {
|
||||
Config.registry || (Config.registry = {});
|
||||
(Config.registry[property] || (Config.registry[property] = {}))[value] = Class;
|
||||
}
|
||||
invoke(instance, properties = {}) {
|
||||
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);
|
||||
static delegate(delegateName) {
|
||||
let self = {
|
||||
when(condition, DelegateConstructor) {
|
||||
Config.addCase(delegateName, condition, DelegateConstructor)
|
||||
return self
|
||||
}
|
||||
}
|
||||
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 {
|
||||
// constructor() {
|
||||
// this._root = this;
|
||||
// this._cases = {};
|
||||
// this._root = this
|
||||
// this._cases = {}
|
||||
// super({
|
||||
// root: this,
|
||||
// parent: null,
|
||||
// path: ''
|
||||
// });
|
||||
// })
|
||||
// }
|
||||
// invoke(instance) {
|
||||
// return invokeConfig(this, instance);
|
||||
// return invokeConfig(this, instance)
|
||||
// }
|
||||
// _addCase(key, baseCase) {
|
||||
// let path = baseCase._path.slice();
|
||||
// path.push(key);
|
||||
// let path = baseCase._path.slice()
|
||||
// path.push(key)
|
||||
|
||||
// // Remove empties & duplicates
|
||||
// path = path
|
||||
// .filter((value, index) => {
|
||||
// return value && path.indexOf(value) === index;
|
||||
// return value && path.indexOf(value) === index
|
||||
// })
|
||||
// .sort();
|
||||
// .sort()
|
||||
|
||||
// if (path.join(' ') === baseCase._path.join(' ')) {
|
||||
// return baseCase;
|
||||
// return baseCase
|
||||
// }
|
||||
// return this._createCase(path);
|
||||
// return this._createCase(path)
|
||||
// }
|
||||
// _createCase(path) {
|
||||
// if (!path.length) return this;
|
||||
// let pathStr = path.join(' ');
|
||||
// let configCase = this._cases[pathStr];
|
||||
// if (!path.length) return this
|
||||
// let pathStr = path.join(' ')
|
||||
// let configCase = this._cases[pathStr]
|
||||
// if (!configCase) {
|
||||
// let parentPath = path.slice(0, path.length - 1);
|
||||
// let parentPath = path.slice(0, path.length - 1)
|
||||
// configCase = this._cases[pathStr] = new ConfigCase({
|
||||
// root: this,
|
||||
// parent: this._createCase(parentPath),
|
||||
// path: path
|
||||
// });
|
||||
// })
|
||||
// }
|
||||
// return configCase;
|
||||
// return configCase
|
||||
// }
|
||||
// }
|
||||
|
||||
// export function invokeConfig(config, object) {
|
||||
// let platformName = platform.get().name;
|
||||
// let platformName = platform.get().name
|
||||
|
||||
// let 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;
|
||||
// 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.
|
||||
// let defaults = [object];
|
||||
// let defaults = [object]
|
||||
// // 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++) {
|
||||
// defaults.push(passedCases[i]._values);
|
||||
// let ComponentToUse
|
||||
// for (let i = 0, ii = passedCases.length i < ii i++) {
|
||||
// defaults.push(passedCases[i]._values)
|
||||
// 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) {
|
||||
// let path = configCase._path;
|
||||
// let key;
|
||||
// for (let i = 0, ii = path.length; i < ii; i++) {
|
||||
// if (platformName !== path[i]) return false;
|
||||
// let path = configCase._path
|
||||
// let key
|
||||
// for (let i = 0, ii = path.length i < ii i++) {
|
||||
// if (platformName !== path[i]) return false
|
||||
// }
|
||||
// return true;
|
||||
// return true
|
||||
// }
|
||||
|
||||
// }
|
||||
|
21
src/util.js
21
src/util.js
@ -28,19 +28,18 @@ export function defaults(dest) {
|
||||
return dest;
|
||||
}
|
||||
|
||||
export function isString(val) {
|
||||
return typeof val === 'string';
|
||||
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 function pascalCaseToDashCase(str = '') {
|
||||
return str.charAt(0).toLowerCase() + str.substring(1).replace(/[A-Z]/g, function(match) {
|
||||
return '-' + match.toLowerCase()
|
||||
})
|
||||
}
|
||||
|
||||
export function isFunction(val) {
|
||||
return typeof val === 'function';
|
||||
}
|
||||
|
||||
export function isDefined(val) {
|
||||
return typeof val !== 'undefined';
|
||||
}
|
||||
|
||||
export var array = {
|
||||
export let array = {
|
||||
unique(array) {
|
||||
return array.filter(function(value, index) {
|
||||
return array.indexOf(value) === index;
|
||||
|
Reference in New Issue
Block a user