From 88b6524155a0847563fb6e611f3720e947fbefcd Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 13 Sep 2016 15:19:40 -0500 Subject: [PATCH] refactor(config): provide config setup factory --- src/config/bootstrap.ts | 91 --------- src/config/config.ts | 54 ++++-- src/config/directives.ts | 205 -------------------- src/config/modes.ts | 34 +++- src/config/providers.ts | 179 ----------------- src/config/test/config.spec.ts | 339 +++++++++++++++++++-------------- src/decorators/page.ts | 47 ----- 7 files changed, 257 insertions(+), 692 deletions(-) delete mode 100644 src/config/bootstrap.ts delete mode 100644 src/config/directives.ts delete mode 100644 src/config/providers.ts delete mode 100644 src/decorators/page.ts diff --git a/src/config/bootstrap.ts b/src/config/bootstrap.ts deleted file mode 100644 index ce5c3ced52..0000000000 --- a/src/config/bootstrap.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { bootstrap } from '@angular/platform-browser-dynamic'; -import { ComponentRef, NgZone } from '@angular/core'; - -import { AppRoot, UserComponent } from '../components/app/app'; -import { nativeRaf } from '../util/dom'; -import { ionicProviders } from './providers'; -import { Platform } from '../platform/platform'; -import { TapClick } from '../components/tap-click/tap-click'; -const _reflect: any = Reflect; - - -/** - * @name ionicBootstrap - * @description - * `ionicBootstrap` allows you to bootstrap your entire application. Similar to Angular's `bootstrap`, `ionicBootstrap` - * takes a root component in order to start the app. You can pass along any providers that you may want to inject into your - * app as an array for the second argument. You can also pass a config object as the third argument to configure your app's settings. - * - * @usage - * - * ```ts - * import { ionicBootstrap } from 'ionic-angular'; - * import { Component } from '@angular/core'; - * - * @Component({ - * templateUrl: 'build/app.html', - * }) - * export class MyClass{} - * - * ionicBootstrap(MyClass, null, {tabsPlacement: 'bottom'}) - * ``` - */ -export function ionicBootstrap(appRootComponent: any, customProviders?: Array, config?: any) { - // get all Ionic Providers - let providers = ionicProviders(customProviders, config); - providers.push({provide: UserComponent, useValue: appRootComponent}); - - return new Promise((resolve) => { - cssReady(() => { - // call angular bootstrap - bootstrap(AppRoot, providers).then(ngComponentRef => { - // ionic app has finished bootstrapping - ionicPostBootstrap(ngComponentRef); - resolve(ngComponentRef); - }); - }); - }); -} - - -/** - * @private - */ -export function ionicPostBootstrap(ngComponentRef: ComponentRef) { - // prepare platform ready - let platform: Platform = ngComponentRef.injector.get(Platform); - platform.setZone(ngComponentRef.injector.get(NgZone)); - platform.prepareReady(); - ngComponentRef.injector.get(TapClick); - - return ngComponentRef; -} - -let cssLoadAttempt = 0; -function cssReady(done: Function) { - let appEle = document.body.querySelector('ion-app'); - - if (!appEle || appEle.clientHeight > 0 || cssLoadAttempt > 300) { - done(); - - } else { - nativeRaf(() => { - cssLoadAttempt++; - cssReady(done); - }); - } -} - - -/** - * @private - */ -export function addSelector(type: any, selector: string) { - if (type) { - let annotations = _reflect.getMetadata('annotations', type); - if (annotations && !annotations[0].selector) { - annotations[0].selector = selector; - _reflect.defineMetadata('annotations', annotations, type); - } - } -} diff --git a/src/config/config.ts b/src/config/config.ts index 2d10d416c2..fa2858be53 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -5,9 +5,11 @@ * @description * Config allows you to set the modes of your components */ - +import { OpaqueToken } from '@angular/core'; import { Platform } from '../platform/platform'; +import { QueryParams } from '../platform/query-params'; import { isObject, isDefined, isFunction, isArray } from '../util/util'; +import { setupModeConfig } from './modes'; /** * @name Config @@ -111,15 +113,19 @@ import { isObject, isDefined, isFunction, isArray } from '../util/util'; **/ export class Config { private _c: any = {}; - private _s: any = {}; + private _s: any; + private _qp: QueryParams; + /** * @private */ platform: Platform; - constructor(config?: any) { + init(config: any, queryParams: QueryParams, platform: Platform) { this._s = config && isObject(config) && !isArray(config) ? config : {}; + this._qp = queryParams; + this.platform = platform; } @@ -154,7 +160,7 @@ export class Config { let configObj: any = null; if (this.platform) { - let queryStringValue = this.platform.query('ionic' + key.toLowerCase()); + const queryStringValue = this._qp.get('ionic' + key); if (isDefined(queryStringValue)) { return this._c[key] = (queryStringValue === 'true' ? true : queryStringValue === 'false' ? false : queryStringValue); } @@ -164,10 +170,10 @@ export class Config { // array of active platforms, which also knows the hierarchy, // with the last one the most important - let activePlatformKeys = this.platform.platforms(); + const activePlatformKeys = this.platform.platforms(); // loop through all of the active platforms we're on - for (let i = 0, l = activePlatformKeys.length; i < l; i++) { + for (var i = 0, ilen = activePlatformKeys.length; i < ilen; i++) { // get user defined platform values if (this._s.platforms) { @@ -249,7 +255,7 @@ export class Config { * value was `null`. Fallback value defaults to `false`. */ getBoolean(key: string, fallbackValue: boolean = false): boolean { - let val = this.get(key); + const val = this.get(key); if (val === null) { return fallbackValue; } @@ -273,7 +279,7 @@ export class Config { * value turned out to be `NaN`. Fallback value defaults to `NaN`. */ getNumber(key: string, fallbackValue: number = NaN): number { - let val = parseFloat( this.get(key) ); + const val = parseFloat( this.get(key) ); return isNaN(val) ? fallbackValue : val; } @@ -343,13 +349,6 @@ export class Config { return this; } - /** - * @private - */ - setPlatform(platform: Platform) { - this.platform = platform; - } - /** * @private */ @@ -367,3 +366,28 @@ export class Config { } let modeConfigs: any = {}; + +export const UserConfig = new OpaqueToken('USERCONFIG'); + +export function setupConfig(userConfig: any, queryParams: QueryParams, platform: Platform): Config { + setupModeConfig(); + + const config = new Config(); + config.init(userConfig, queryParams, platform); + return config; +} + +export function provideConfig(userConfig: any): any { + return [ + { provide: UserConfig, useValue: userConfig }, + { + provide: Config, + useFactory: setupConfig, + deps: [ + UserConfig, + QueryParams, + Platform + ] + } + ]; +} diff --git a/src/config/directives.ts b/src/config/directives.ts deleted file mode 100644 index f33759236c..0000000000 --- a/src/config/directives.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { CORE_DIRECTIVES } from '@angular/common'; -import { REACTIVE_FORM_DIRECTIVES } from '@angular/forms'; - -import { Menu } from '../components/menu/menu'; -import { MenuToggle } from '../components/menu/menu-toggle'; -import { MenuClose } from '../components/menu/menu-close'; -import { Backdrop } from '../components/backdrop/backdrop'; -import { Badge } from '../components/badge/badge'; -import { Button } from '../components/button/button'; -import { Content } from '../components/content/content'; -import { Img } from '../components/img/img'; -import { Scroll } from '../components/scroll/scroll'; -import { InfiniteScroll } from '../components/infinite-scroll/infinite-scroll'; -import { InfiniteScrollContent } from '../components/infinite-scroll/infinite-scroll-content'; -import { Refresher } from '../components/refresher/refresher'; -import { RefresherContent } from '../components/refresher/refresher-content'; -import { Slides, Slide, SlideLazy } from '../components/slides/slides'; -import { Tabs } from '../components/tabs/tabs'; -import { Tab } from '../components/tabs/tab'; -import { List, ListHeader } from '../components/list/list'; -import { Item, ItemContent } from '../components/item/item'; -import { ItemReorder } from '../components/item/item-reorder'; -import { ItemSliding, ItemOptions } from '../components/item/item-sliding'; -import { VirtualScroll } from '../components/virtual-scroll/virtual-scroll'; -import { VirtualItem, VirtualHeader, VirtualFooter } from '../components/virtual-scroll/virtual-item'; -import { Toolbar, Header, Footer } from '../components/toolbar/toolbar'; -import { ToolbarItem } from '../components/toolbar/toolbar-item'; -import { ToolbarTitle } from '../components/toolbar/toolbar-title'; -import { Icon } from '../components/icon/icon'; -import { Spinner } from '../components/spinner/spinner'; -import { Checkbox } from '../components/checkbox/checkbox'; -import { Select } from '../components/select/select'; -import { Option } from '../components/option/option'; -import { DateTime } from '../components/datetime/datetime'; -import { Toggle } from '../components/toggle/toggle'; -import { TextInput, TextArea } from '../components/input/input'; -import { Label } from '../components/label/label'; -import { Segment, SegmentButton } from '../components/segment/segment'; -import { RadioButton } from '../components/radio/radio-button'; -import { RadioGroup } from '../components/radio/radio-group'; -import { Range } from '../components/range/range'; -import { Searchbar } from '../components/searchbar/searchbar'; -import { Nav } from '../components/nav/nav'; -import { NavPop } from '../components/nav/nav-pop'; -import { NavPush } from '../components/nav/nav-push'; -import { NavbarTemplate, Navbar } from '../components/navbar/navbar'; -import { ShowWhen, HideWhen } from '../components/show-hide-when/show-hide-when'; -import { Typography } from '../components/typography/typography'; -import { Chip } from '../components/chip/chip'; - -/** - * @private - * @name IONIC_DIRECTIVES - * @description - * The core Ionic directives as well as Angular's `CORE_DIRECTIVES` and `FORM_DIRECTIVES` are - * available automatically when you bootstrap your app with the `ionicBootstrap`. This means - * if you are using custom components you do not need to import `IONIC_DIRECTIVES` as they - * are part of the app's default directives. - * - * - * #### Angular - * - CORE_DIRECTIVES - * - FORM_DIRECTIVES - * - * #### Ionic - * - Menu - * - MenuToggle - * - MenuClose - * - Badge - * - Button - * - Chip - * - Content - * - Scroll - * - InfiniteScroll - * - InfiniteScrollContent - * - Refresher - * - RefresherContent - * - Img - * - List - * - ListHeader - * - Item - * - ItemContent - * - ItemSliding - * - VirtualScroll - * - VirtualItem - * - VirtualHeader - * - VirtualFooter - * - Slides - * - Slide - * - SlideLazy - * - Tabs - * - Tab - * - Header - * - Footer - * - Toolbar - * - ToolbarTitle - * - ToolbarItem - * - Icon - * - Spinner - * - Searchbar - * - Segment - * - SegmentButton - * - Checkbox - * - RadioGroup - * - RadioButton - * - Select - * - Option - * - DateTime - * - Toggle - * - TextArea - * - TextInput - * - Label - * - Nav - * - NavbarTemplate - * - Navbar - * - NavPush - * - NavPop - * - IdRef - * - ShowWhen - * - HideWhen - * - Typography - */ -export const IONIC_DIRECTIVES: any[] = [ - // Angular - CORE_DIRECTIVES, - REACTIVE_FORM_DIRECTIVES, - - // Content - Menu, - MenuToggle, - MenuClose, - - Backdrop, - Badge, - Button, - Chip, - Content, - Scroll, - InfiniteScroll, - InfiniteScrollContent, - Refresher, - RefresherContent, - Img, - - // Lists - List, - ListHeader, - Item, - ItemContent, - ItemSliding, - ItemOptions, - ItemReorder, - VirtualScroll, - VirtualItem, - VirtualHeader, - VirtualFooter, - - // Slides - Slides, - Slide, - SlideLazy, - - // Tabs - Tabs, - Tab, - - // Toolbar - Header, - Footer, - Toolbar, - ToolbarTitle, - ToolbarItem, - - // Media - Icon, - Spinner, - - // Forms - Searchbar, - Segment, - SegmentButton, - Checkbox, - RadioGroup, - RadioButton, - Range, - Select, - Option, - DateTime, - Toggle, - TextArea, - TextInput, - Label, - - // Nav - Nav, - NavbarTemplate, - Navbar, - - NavPush, - NavPop, - - ShowWhen, - HideWhen, - Typography -]; diff --git a/src/config/modes.ts b/src/config/modes.ts index 88b824d99e..dea0af9cf1 100644 --- a/src/config/modes.ts +++ b/src/config/modes.ts @@ -1,9 +1,12 @@ import { Config } from './config'; +import { PageTransition } from '../transitions/page-transition'; +import { IOSTransition } from '../transitions/transition-ios'; +import { MDTransition } from '../transitions/transition-md'; +import { WPTransition } from '../transitions/transition-wp'; -// iOS Mode Settings -Config.setModeConfig('ios', { +const MODE_IOS: any = { activator: 'highlight', actionSheetEnter: 'action-sheet-slide-in', @@ -43,11 +46,10 @@ Config.setModeConfig('ios', { toastEnter: 'toast-slide-in', toastLeave: 'toast-slide-out', -}); +}; -// Material Design Mode Settings -Config.setModeConfig('md', { +const MODE_MD: any = { activator: 'ripple', actionSheetEnter: 'action-sheet-md-slide-in', @@ -87,11 +89,10 @@ Config.setModeConfig('md', { toastEnter: 'toast-md-slide-in', toastLeave: 'toast-md-slide-out', -}); +}; -// Windows Mode Settings -Config.setModeConfig('wp', { +const MODE_WP: any = { activator: 'highlight', actionSheetEnter: 'action-sheet-wp-slide-in', @@ -131,4 +132,19 @@ Config.setModeConfig('wp', { toastEnter: 'toast-wp-slide-in', toastLeave: 'toast-wp-slide-out', -}); +}; + + +export function setupModeConfig() { + // iOS Mode Settings + Config.setModeConfig('ios', MODE_IOS); + PageTransition.register('ios-transition', IOSTransition); + + // Material Design Mode Settings + Config.setModeConfig('md', MODE_MD); + PageTransition.register('md-transition', MDTransition); + + // Windows Mode Settings + Config.setModeConfig('wp', MODE_WP); + PageTransition.register('wp-transition', WPTransition); +} diff --git a/src/config/providers.ts b/src/config/providers.ts deleted file mode 100644 index 8ea64274c4..0000000000 --- a/src/config/providers.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { enableProdMode, PLATFORM_DIRECTIVES, provide } from '@angular/core'; -import { disableDeprecatedForms, provideForms } from '@angular/forms'; -import { HTTP_PROVIDERS } from '@angular/http'; -import { HAMMER_GESTURE_CONFIG } from '@angular/platform-browser'; - -import { ActionSheetController } from '../components/action-sheet/action-sheet'; -import { AlertController } from '../components/alert/alert'; -import { App } from '../components/app/app'; -import { Config } from './config'; -import { closest, nativeTimeout } from '../util/dom'; -import { Events } from '../util/events'; -import { FeatureDetect } from '../util/feature-detect'; -import { Form } from '../util/form'; -import { IonicGestureConfig } from '../gestures/ionic-gesture-config'; -import { GestureController } from '../gestures/gesture-controller'; -import { IONIC_DIRECTIVES } from './directives'; -import { isPresent } from '../util/util'; -import { Keyboard } from '../util/keyboard'; -import { LoadingController } from '../components/loading/loading'; -import { MenuController } from '../components/menu/menu-controller'; -import { ModalController } from '../components/modal/modal'; -import { PickerController } from '../components/picker/picker'; -import { Platform } from '../platform/platform'; -import { PopoverController } from '../components/popover/popover'; -import { ScrollView } from '../util/scroll-view'; -import { TapClick } from '../components/tap-click/tap-click'; -import { ToastController } from '../components/toast/toast'; -import { Translate } from '../translation/translate'; - - -/** - * @private - */ -export function ionicProviders(customProviders?: Array, config?: any): any[] { - // create an instance of Config - if (!(config instanceof Config)) { - config = new Config(config); - } - - // enable production mode if config set to true - if (config.getBoolean('prodMode')) { - enableProdMode(); - } - - // create an instance of Platform - let platform = new Platform(); - - // initialize platform - platform.setUrl(window.location.href); - platform.setUserAgent(window.navigator.userAgent); - platform.setNavigatorPlatform(window.navigator.platform); - platform.load(); - config.setPlatform(platform); - - let events = new Events(); - let featureDetect = new FeatureDetect(); - - setupDom(window, document, config, platform, featureDetect); - bindEvents(window, document, platform, events); - - let providers: any[] = [ - ActionSheetController, - AlertController, - App, - provide(Config, {useValue: config}), - disableDeprecatedForms(), - provide(Events, {useValue: events}), - provide(FeatureDetect, {useValue: featureDetect}), - Form, - GestureController, - HTTP_PROVIDERS, - Keyboard, - LoadingController, - MenuController, - ModalController, - PickerController, - PopoverController, - provide(Platform, {useValue: platform}), - provide(PLATFORM_DIRECTIVES, {useValue: IONIC_DIRECTIVES, multi: true}), - provideForms(), - TapClick, - ToastController, - Translate, - ]; - - providers.push( {provide: HAMMER_GESTURE_CONFIG, useClass: IonicGestureConfig} ); - - if (isPresent(customProviders)) { - providers.push(customProviders); - } - - return providers; -} - -function setupDom(window: Window, document: Document, config: Config, platform: Platform, featureDetect: FeatureDetect) { - let bodyEle = document.body; - let mode = config.get('mode'); - - // if dynamic mode links have been added the fire up the correct one - let modeLinkAttr = mode + '-href'; - let linkEle = document.head.querySelector('link[' + modeLinkAttr + ']'); - if (linkEle) { - let href = linkEle.getAttribute(modeLinkAttr); - linkEle.removeAttribute(modeLinkAttr); - linkEle.href = href; - } - - // set the mode class name - // ios/md/wp - bodyEle.classList.add(mode); - - // language and direction - platform.setDir(document.documentElement.dir, false); - platform.setLang(document.documentElement.lang, false); - - let versions = platform.versions(); - platform.platforms().forEach(platformName => { - // platform-ios - let platformClass = 'platform-' + platformName; - bodyEle.classList.add(platformClass); - - let platformVersion = versions[platformName]; - if (platformVersion) { - // platform-ios9 - platformClass += platformVersion.major; - bodyEle.classList.add(platformClass); - - // platform-ios9_3 - bodyEle.classList.add(platformClass + '_' + platformVersion.minor); - } - }); - - // touch devices should not use :hover CSS pseudo - // enable :hover CSS when the "hoverCSS" setting is not false - if (config.getBoolean('hoverCSS', true)) { - bodyEle.classList.add('enable-hover'); - } - - // run feature detection tests - featureDetect.run(window, document); -} - - -/** - * Bind some global events and publish on the 'app' channel - */ -function bindEvents(window: Window, document: Document, platform: Platform, events: Events) { - window.addEventListener('online', (ev) => { - events.publish('app:online', ev); - }, false); - - window.addEventListener('offline', (ev) => { - events.publish('app:offline', ev); - }, false); - - window.addEventListener('orientationchange', (ev) => { - events.publish('app:rotated', ev); - }); - - // When that status taps, we respond - window.addEventListener('statusTap', (ev) => { - // TODO: Make this more better - let el = document.elementFromPoint(platform.width() / 2, platform.height() / 2); - if (!el) { return; } - - let content = closest(el, 'scroll-content'); - if (content) { - var scroll = new ScrollView(content); - scroll.scrollTo(0, 0, 300); - } - }); - - // start listening for resizes XXms after the app starts - nativeTimeout(() => { - window.addEventListener('resize', () => { - platform.windowResize(); - }); - }, 2000); -} \ No newline at end of file diff --git a/src/config/test/config.spec.ts b/src/config/test/config.spec.ts index 09d360ef3f..3a9259f68a 100644 --- a/src/config/test/config.spec.ts +++ b/src/config/test/config.spec.ts @@ -1,125 +1,115 @@ -import { Config, Platform, ionicProviders } from '../../../src'; +import { Config } from '../config'; +import { Platform } from '../../platform/platform'; +import { QueryParams } from '../../platform/query-params'; +import { setupPlatformRegistry } from '../../platform/registry'; +import { setupModeConfig } from '../modes'; -export function run() { describe('Config', () => { it('should set activator setting to none for old Android Browser on a linux device', () => { let config = new Config(); + let qp = new QueryParams(''); let platform = new Platform(); platform.setUserAgent('Mozilla/5.0 (Linux; U; Android 4.2.2; nl-nl; GT-I9505 Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'); platform.setNavigatorPlatform('linux'); + platform.setQueryParams(qp); platform.load(); - config.setPlatform(platform); + config.init(null, qp, platform); expect(config.get('activator')).toEqual('none'); }); it('should set activator setting to ripple for Android dev tools simulation on a mac', () => { let config = new Config(); + let qp = new QueryParams(''); let platform = new Platform(); platform.setUserAgent('Mozilla/5.0 (Linux; U; Android 4.2.2; nl-nl; GT-I9505 Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'); platform.setNavigatorPlatform('MacIntel'); + platform.setQueryParams(qp); platform.load(); - config.setPlatform(platform); + config.init(null, qp, platform); expect(config.get('activator')).toEqual('ripple'); }); it('should set activator setting to none for Android Chrome versions below v36 on a linux device', () => { let config = new Config(); + let qp = new QueryParams(''); let platform = new Platform(); platform.setUserAgent('Mozilla/5.0 (Linux; Android 4.2.2; GT-I9505 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1650.59 Mobile Safari/537.36'); platform.setNavigatorPlatform('linux'); + platform.setQueryParams(qp); platform.load(); - config.setPlatform(platform); + config.init(null, qp, platform); expect(config.get('activator')).toEqual('none'); }); it('should set activator setting to ripple for Android Chrome v36 and above on a linux device', () => { let config = new Config(); + let qp = new QueryParams(''); let platform = new Platform(); platform.setUserAgent('Mozilla/5.0 (Linux; Android 4.2.2; GT-I9505 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1650.59 Mobile Safari/537.36'); platform.setNavigatorPlatform('linux'); + platform.setQueryParams(qp); platform.load(); - config.setPlatform(platform); + config.init(null, qp, platform); expect(config.get('activator')).toEqual('ripple'); }); it('should set activator setting to ripple for Android v5.0 and above on a linux device not using Chrome', () => { let config = new Config(); + let qp = new QueryParams(''); let platform = new Platform(); platform.setUserAgent('Mozilla/5.0 (Android 5.0; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0'); platform.setNavigatorPlatform('linux'); + platform.setQueryParams(qp); platform.load(); - config.setPlatform(platform); + config.init(null, qp, platform); expect(config.get('activator')).toEqual('ripple'); }); it('should set activator setting to none for Android versions below v5.0 on a linux device not using Chrome', () => { let config = new Config(); + let qp = new QueryParams(''); let platform = new Platform(); platform.setUserAgent('Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0'); platform.setNavigatorPlatform('linux'); + platform.setQueryParams(qp); platform.load(); - config.setPlatform(platform); + config.init(null, qp, platform); expect(config.get('activator')).toEqual('none'); }); - it('should create a new Config instace when no confg passed in ionicProviders', () => { - let providers = ionicProviders(); - - let config = providers.find(provider => provider.useValue instanceof Config).useValue; - - expect(config.get('mode')).toEqual('md'); - }); - - it('should used passed in Config instance in ionicProviders', () => { - let userConfig = new Config({ - mode: 'configInstance' - }); - let providers = ionicProviders(null, userConfig); - - let config = providers.find(provider => provider.useValue instanceof Config).useValue; - - expect(config.get('mode')).toEqual('configInstance'); - }); - - it('should create new Config instance from config object in ionicProviders', () => { - let providers = ionicProviders(null, { - mode: 'configObj' - }); - - let config = providers.find(provider => provider.useValue instanceof Config).useValue; - - expect(config.get('mode')).toEqual('configObj'); - }); - it('should override mode settings', () => { - let config = new Config({ + let config = new Config(); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init({ mode: 'md' - }); - let platform = new Platform(['ios']); - config.setPlatform(platform); + }, qp, platform); expect(config.get('mode')).toEqual('md'); expect(config.get('iconMode')).toEqual('md'); }); it('should override mode settings from platforms setting', () => { - let config = new Config({ + let config = new Config(); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init({ platforms: { ios: { mode: 'md' } } - }); - let platform = new Platform(['ios']); - config.setPlatform(platform); + }, qp, platform); expect(config.get('mode')).toEqual('md'); expect(config.get('iconMode')).toEqual('md'); @@ -127,42 +117,46 @@ describe('Config', () => { it('should get boolean value from querystring', () => { let config = new Config(); + let qp = new QueryParams('http://biff.com/?ionicanimate=true'); let platform = new Platform(); - platform.setUrl('http://biff.com/?ionicanimate=true'); - config.setPlatform(platform); + config.init(null, qp, platform); expect(config.get('animate')).toEqual(true); config = new Config(); + qp = new QueryParams('http://biff.com/?ionicanimate=false'); platform = new Platform(); - platform.setUrl('http://biff.com/?ionicanimate=false'); - config.setPlatform(platform); + config.init(null, qp, platform); expect(config.get('animate')).toEqual(false); }); it('should get value from case insensitive querystring key', () => { - let config = new Config({ - mode: 'a' - }); + let config = new Config(); + let qp = new QueryParams('http://biff.com/?ionicConfigKey=b'); let platform = new Platform(); - platform.setUrl('http://biff.com/?ionicConfigKey=b'); - config.setPlatform(platform); + config.init({ + mode: 'a' + }, qp, platform); expect(config.get('configKey')).toEqual('b'); }); it('should get value from querystring', () => { - let config = new Config({ - mode: 'modeA' - }); + let config = new Config(); + let qp = new QueryParams('http://biff.com/?ionicmode=modeB'); let platform = new Platform(); - platform.setUrl('http://biff.com/?ionicmode=modeB'); - config.setPlatform(platform); + config.init({ + mode: 'modeA' + }, qp, platform); expect(config.get('mode')).toEqual('modeB'); }); it('should override mode platform', () => { - let config = new Config({ + let config = new Config(); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['mobile']; + config.init({ mode: 'modeA', platforms: { mobile: { @@ -172,110 +166,130 @@ describe('Config', () => { mode: 'modeC' } } - }); - let platform = new Platform(['mobile']); - config.setPlatform(platform); + }, qp, platform); expect(config.get('mode')).toEqual('modeB'); }); it('should override mode', () => { - let config = new Config({ + let config = new Config(); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['core']; + config.init({ mode: 'modeA' - }); - let platform = new Platform(['core']); - config.setPlatform(platform); + }, qp, platform); expect(config.get('mode')).toEqual('modeA'); }); it('should get user settings after user platform settings', () => { - let config = new Config({ + let config = new Config(); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init({ hoverCSS: true - }); - let platform = new Platform(['ios']); - config.setPlatform(platform); + }, qp, platform); expect(config.get('hoverCSS')).toEqual(true); }); it('should get md mode for core platform', () => { let config = new Config(); - let platform = new Platform(['core']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['core']; + config.init(null, qp, platform); expect(config.get('mode')).toEqual('md'); }); it('should get ios mode for ipad platform', () => { let config = new Config(); - let platform = new Platform(['mobile', 'ios', 'ipad', 'tablet']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['mobile', 'ios', 'ipad', 'tablet']; + config.init(null, qp, platform); expect(config.get('mode')).toEqual('ios'); }); it('should get md mode for windows platform', () => { let config = new Config(); - let platform = new Platform(['mobile', 'windows']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['mobile', 'windows']; + config.init(null, qp, platform); expect(config.get('mode')).toEqual('wp'); }); it('should get md mode for android platform', () => { let config = new Config(); - let platform = new Platform(['mobile', 'android']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['mobile', 'android']; + config.init(null, qp, platform); expect(config.get('mode')).toEqual('md'); }); it('should override ios mode config with user platform setting', () => { - let config = new Config({ + let config = new Config(); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init({ tabsPlacement: 'hide', platforms: { ios: { tabsPlacement: 'top' } } - }); - let platform = new Platform(['ios']); - config.setPlatform(platform); + }, qp, platform); expect(config.get('tabsPlacement')).toEqual('top'); }); it('should override ios mode config with user setting', () => { - let config = new Config({ + let config = new Config(); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init({ tabsPlacement: 'top' - }); - let platform = new Platform(['ios']); - config.setPlatform(platform); + }, qp, platform); expect(config.get('tabsPlacement')).toEqual('top'); }); it('should get setting from md mode', () => { let config = new Config(); - let platform = new Platform(['android']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['android']; + config.init(null, qp, platform); expect(config.get('iconMode')).toEqual('md'); }); it('should get setting from ios mode', () => { let config = new Config(); - let platform = new Platform(['ios']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init(null, qp, platform); expect(config.get('tabsPlacement')).toEqual('bottom'); }); it('should set/get platform setting from set()', () => { let config = new Config(); - let platform = new Platform(['ios']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init(null, qp, platform); config.set('tabsPlacement', 'bottom'); config.set('ios', 'tabsPlacement', 'top'); @@ -285,8 +299,10 @@ describe('Config', () => { it('should set/get setting from set()', () => { let config = new Config(); - let platform = new Platform(['ios']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init(null, qp, platform); config.set('tabsPlacement', 'top'); @@ -295,8 +311,10 @@ describe('Config', () => { it('should set ios platform settings from settings()', () => { let config = new Config(); - let platform = new Platform(['ios']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init(null, qp, platform); config.settings('ios', { key: 'iosValue' @@ -307,44 +325,46 @@ describe('Config', () => { it('should set/get mobile setting even w/ higher priority ios', () => { let config = new Config(); - let platform = new Platform(['mobile', 'ios']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['mobile', 'ios']; - config.settings({ + config.init({ key: 'defaultValue', platforms: { mobile: { key: 'mobileValue' } } - }); + }, qp, platform); expect(config.get('key')).toEqual('mobileValue'); }); it('should set/get mobile setting even w/ higher priority ios', () => { let config = new Config(); - let platform = new Platform(['mobile', 'ios']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['mobile', 'ios']; - config.settings({ + config.init({ key: 'defaultValue', platforms: { mobile: { key: 'mobileValue' } } - }); + }, qp, platform); expect(config.get('key')).toEqual('mobileValue'); }); it('should set/get android setting w/ higher priority than mobile', () => { let config = new Config(); - let platform = new Platform(['mobile', 'android']); - config.setPlatform(platform); - - config.settings({ + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['mobile', 'android']; + config.init({ key: 'defaultValue', platforms: { mobile: { @@ -354,15 +374,17 @@ describe('Config', () => { key: 'androidValue' } } - }); + }, qp, platform); expect(config.get('key')).toEqual('androidValue'); }); it('should set/get ios setting w/ platforms set', () => { let config = new Config(); - let platform = new Platform(['ios']); - config.setPlatform(platform); + let qp = new QueryParams(''); + let platform = new Platform(); + platform._platforms = ['ios']; + config.init(null, qp, platform); config.settings({ key: 'defaultValue', @@ -411,7 +433,7 @@ describe('Config', () => { it('should get null setting', () => { let config = new Config(); - + config.init(null, null, null); expect(config.get('name')).toEqual(null); expect(config.get('name')).toEqual(null); expect(config.get('occupation')).toEqual(null); @@ -420,6 +442,7 @@ describe('Config', () => { it('should set/get single setting', () => { let config = new Config(); + config.init(null, null, null); config.set('name', 'Doc Brown'); config.set('occupation', 'Weather Man'); @@ -430,37 +453,41 @@ describe('Config', () => { }); it('should init w/ given config settings', () => { - let config = new Config({ + let config = new Config(); + config.init({ name: 'Doc Brown', occupation: 'Weather Man' - }); + }, null, null); expect(config.get('name')).toEqual('Doc Brown'); expect(config.get('occupation')).toEqual('Weather Man'); }); it('should get a fallback value', () => { - let config = new Config({ + let config = new Config(); + config.init({ name: 'Doc Brown' - }); + }, null, null); expect(config.get('name', 'Marty')).toEqual('Doc Brown'); expect(config.get('occupation', 'Weather Man')).toEqual('Weather Man'); }); it('should get a boolean value with a boolean config value', () => { - let config = new Config({ + let config = new Config(); + config.init({ key1: true, key2: false - }); + }, null, null); expect(config.getBoolean('key1')).toEqual(true); expect(config.getBoolean('key2')).toEqual(false); }); it('should get a boolean value with a string config value', () => { - let config = new Config({ + let config = new Config(); + config.init({ key1: 'true', key2: 'false', key3: 'whatever' - }); + }, null, null); expect(config.getBoolean('key1')).toEqual(true); expect(config.getBoolean('key2')).toEqual(false); expect(config.getBoolean('key3')).toEqual(false); @@ -469,39 +496,43 @@ describe('Config', () => { }); it('should get a boolean value with a number config value', () => { - let config = new Config({ + let config = new Config(); + config.init({ key1: 0, key2: 1, key3: 'whatever' - }); + }, null, null); expect(config.getBoolean('key1')).toEqual(false); expect(config.getBoolean('key2')).toEqual(true); }); it('should get a number value with a number config value', () => { - let config = new Config({ + let config = new Config(); + config.init({ key: 6 - }); + }, null, null); expect(config.getNumber('key')).toEqual(6); }); it('should get a number value with a string config value', () => { - let config = new Config({ + let config = new Config(); + config.init({ key: '6', numThenString: '6baymax', stringThenNum: 'baymax6' - }); + }, null, null); expect(config.getNumber('key', 5)).toEqual(6); expect(config.getNumber('numThenString', 4)).toEqual(6); expect( isNaN(config.getNumber('stringThenNum')) ).toEqual(true); }); it('should get a number NaN value with a NaN config value', () => { - let config = new Config({ + let config = new Config(); + config.init({ allString: 'allstring', imNull: null, imUndefined: undefined - }); + }, null, null); expect( isNaN(config.getNumber('notfound'))).toEqual(true); expect( isNaN(config.getNumber('allString'))).toEqual(true); expect( isNaN(config.getNumber('imNull'))).toEqual(true); @@ -509,22 +540,25 @@ describe('Config', () => { }); it('should get a number fallback value with a NaN config value', () => { - let config = new Config({ + let config = new Config(); + config.init({ allString: 'allstring', imNull: null, imUndefined: undefined - }); + }, null, null); expect( config.getNumber('notfound', 6)).toEqual(6); expect( config.getNumber('allString', 6)).toEqual(6); expect( config.getNumber('imNull', 6)).toEqual(6); expect( config.getNumber('imUndefined', 6)).toEqual(6); + }); it('should get settings object', () => { - let config = new Config({ + let config = new Config(); + config.init({ name: 'Doc Brown', occupation: 'Weather Man' - }); + }, null, null); expect(config.settings()).toEqual({ name: 'Doc Brown', @@ -533,37 +567,50 @@ describe('Config', () => { }); it('should create default config w/ bad settings value', () => { - let config = new Config(null); - expect(config.settings()).toEqual({}); - - config = new Config(undefined); + let config = new Config(); + config.init(null, null, null); expect(config.settings()).toEqual({}); config = new Config(); + config.init(null, null, null); expect(config.settings()).toEqual({}); - config = new Config([1, 2, 3]); + config = new Config(); + config.init(null, null, null); expect(config.settings()).toEqual({}); - config = new Config('im bad, you know it'); + config = new Config(); + config.init(null, null, null); expect(config.settings()).toEqual({}); - config = new Config(8675309); + config = new Config(); + config.init(null, null, null); expect(config.settings()).toEqual({}); - config = new Config(true); + config = new Config(); + config.init(null, null, null); expect(config.settings()).toEqual({}); - config = new Config(false); + config = new Config(); + config.init(null, null, null); expect(config.settings()).toEqual({}); - config = new Config(1); + config = new Config(); + config.init(null, null, null); expect(config.settings()).toEqual({}); - config = new Config(function(){}); + config = new Config(); + config.init(null, null, null); + expect(config.settings()).toEqual({}); + + config = new Config(); + config.init(null, null, null); expect(config.settings()).toEqual({}); }); -}); + beforeEach(() => { + setupModeConfig(); + setupPlatformRegistry(); + }); -} +}); diff --git a/src/decorators/page.ts b/src/decorators/page.ts deleted file mode 100644 index f76ed24c93..0000000000 --- a/src/decorators/page.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation, Type } from '@angular/core'; - -const _reflect: any = Reflect; - -export interface PageMetadata { - selector?: string; - inputs?: string[]; - outputs?: string[]; - properties?: string[]; - events?: string[]; - host?: { - [key: string]: string; - }; - providers?: any[]; - directives?: Array; - pipes?: Array; - exportAs?: string; - queries?: { - [key: string]: any; - }; - template?: string; - templateUrl?: string; - moduleId?: string; - styleUrls?: string[]; - styles?: string[]; - changeDetection?: ChangeDetectionStrategy; - encapsulation?: ViewEncapsulation; -} - -/** - * @private - */ -export function Page(config: PageMetadata) { - return function(cls: any) { - // deprecated warning: added beta.8 2016-05-27 - console.warn('@Page decorator has been deprecated. Please use Angular\'s @Component instead.\nimport { Component} from \'@angular/core\';'); - - config.selector = 'ion-page'; - config.host = config.host || {}; - config.host['[hidden]'] = '_hidden'; - config.host['[class.tab-subpage]'] = '_tabSubPage'; - var annotations = _reflect.getMetadata('annotations', cls) || []; - annotations.push(new Component(config)); - _reflect.defineMetadata('annotations', annotations, cls); - return cls; - }; -}