From 33c69d5870136560e792febeda08789feebca9b9 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 3 Aug 2015 11:24:47 -0500 Subject: [PATCH] checkbox updates --- ionic/components.ts | 1 + ionic/components/app/app.ts | 2 +- ionic/components/app/normalize.scss | 4 +- ionic/components/checkbox/checkbox.scss | 1 + ionic/components/checkbox/checkbox.ts | 60 ++++++------ ionic/components/checkbox/test/basic/index.ts | 20 +++- .../components/checkbox/test/basic/main.html | 53 +++++----- .../show-hide-when/show-hide-when.ts | 98 +++++++++++++++++++ .../show-hide-when/test/basic/e2e.ts | 4 + .../show-hide-when/test/basic/index.ts | 44 +++++++++ .../show-hide-when/test/basic/main.html | 59 +++++++++++ ionic/config/annotations.ts | 4 + ionic/platform/platform.ts | 22 ++++- 13 files changed, 307 insertions(+), 65 deletions(-) create mode 100644 ionic/components/show-hide-when/show-hide-when.ts create mode 100644 ionic/components/show-hide-when/test/basic/e2e.ts create mode 100644 ionic/components/show-hide-when/test/basic/index.ts create mode 100644 ionic/components/show-hide-when/test/basic/main.html diff --git a/ionic/components.ts b/ionic/components.ts index df34c25a0a..a37b3540ad 100644 --- a/ionic/components.ts +++ b/ionic/components.ts @@ -14,6 +14,7 @@ export * from 'ionic/components/form/text-input' export * from 'ionic/components/form/tap-input' export * from 'ionic/components/form/label' export * from 'ionic/components/list/list' +export * from 'ionic/components/show-hide-when/show-hide-when' // Material components/effects export * from 'ionic/components/material/button' diff --git a/ionic/components/app/app.ts b/ionic/components/app/app.ts index 390c1ad94b..b260ff7e38 100644 --- a/ionic/components/app/app.ts +++ b/ionic/components/app/app.ts @@ -135,7 +135,7 @@ function initApp(window, document, config) { Platform.load(config); // on resize be sure to clear out existing window dimensions - window.addEventListener('resize', Platform.resetDimensions); + window.addEventListener('resize', Platform.winResize); return app; } diff --git a/ionic/components/app/normalize.scss b/ionic/components/app/normalize.scss index eabad42a8c..e6cd4ccdfd 100644 --- a/ionic/components/app/normalize.scss +++ b/ionic/components/app/normalize.scss @@ -31,9 +31,9 @@ audio:not([controls]) { // Address `[hidden]` styling not present in IE 8/9/10. // Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. -[hidden][hidden], +[hidden], template { - display: none; + display: none !important; } diff --git a/ionic/components/checkbox/checkbox.scss b/ionic/components/checkbox/checkbox.scss index 66665275a9..77c371ba02 100644 --- a/ionic/components/checkbox/checkbox.scss +++ b/ionic/components/checkbox/checkbox.scss @@ -18,6 +18,7 @@ } .checkbox[aria-disabled=true] { + pointer-events: none; opacity: 0.5; color: gray; } diff --git a/ionic/components/checkbox/checkbox.ts b/ionic/components/checkbox/checkbox.ts index 93da4d149b..7dffa356c5 100644 --- a/ionic/components/checkbox/checkbox.ts +++ b/ionic/components/checkbox/checkbox.ts @@ -15,6 +15,11 @@ import {TapClick} from '../button/button'; @IonicComponent({ selector: 'ion-checkbox', + properties: [ + 'value', + 'checked', + 'disabled' + ], host: { 'class': 'item', 'role': 'checkbox', @@ -22,7 +27,8 @@ import {TapClick} from '../button/button'; '[attr.aria-disabled]': 'input.disabled', '[attr.aria-labelledby]': 'labelId', '(^click)': 'click($event)' - } + }, + exportAs: 'checkbox' }) @IonicView({ template: @@ -42,49 +48,43 @@ export class Checkbox extends IonInputItem { tapClick: TapClick ) { super(elementRef, config); + this.tapClick = tapClick; + this.onChange = (_) => {}; this.onTouched = (_) => {}; - this.tapClick = tapClick; + this.cd = cd; if (cd) cd.valueAccessor = this; } - click(ev) { - if (this.tapClick.allowClick(ev)) { - ev.preventDefault(); - ev.stopPropagation(); - this.input.checked = !this.input.checked; - } - } - onInit() { super.onInit(); this.labelId = 'label-' + this.id; } + onAllChangesDone() { + this.input.checked = this.checked; + this.input.disabled = this.disabled; + this.input.value = this.value; + } + + toggle() { + this.input.checked = this.checked = !this.input.checked; + this.onChange(this.checked); + } + + click(ev) { + if (this.tapClick.allowClick(ev)) { + ev.preventDefault(); + ev.stopPropagation(); + this.toggle(); + } + } + // Called by the model (Control) to update the view writeValue(modelValue) { - let type = typeof modelValue; - switch (type) { - case "boolean": - // don't set input.value here, do it in onAllChangesDone - // because they might have set it in the view - this._checked = modelValue; break; - case "object": - if (modelValue.checked !== void 0) this._checked = !!modelValue.checked; - if (modelValue.value !== void 0) this._value = modelValue.value.toString(); - break; - default: - // don't set input.checked here, do it in onAllChangesDone - // because they might have set it in the view - this._value = modelValue.toString(); - } - - //TODO we want to set input.checked directly after the first time - console.log("writeValue, " + this.input.id + " checked: " + this._checked); - console.log("writeValue " + this.input.id + " value: " + this._value); - + this.input.checked = modelValue; } // Used by the view to update the model (Control) diff --git a/ionic/components/checkbox/test/basic/index.ts b/ionic/components/checkbox/test/basic/index.ts index e906bafacf..40e35c35b2 100644 --- a/ionic/components/checkbox/test/basic/index.ts +++ b/ionic/components/checkbox/test/basic/index.ts @@ -18,15 +18,27 @@ import { class IonicApp { constructor() { this.fruitsForm = new ControlGroup({ - "appleCtrl": new Control({"checked": false, "value": "apple"}), + "appleCtrl": new Control(), "bananaCtrl": new Control(true), - "cherryCtrl": new Control({"checked": false, "value": 12}), - "grapeCtrl": new Control("grape") + "cherryCtrl": new Control(false), + "grapeCtrl": new Control(true) }); + + this.grapeDisabled = true; + this.grapeChecked = true; + } + + toggleGrapeChecked() { + this.grapeChecked = !this.grapeChecked; + } + + toggleGrapeDisabled() { + this.grapeDisabled = !this.grapeDisabled; } doSubmit(ev) { console.log('Submitting form', this.fruitsForm.value); - event.preventDefault(); + this.formResults = JSON.stringify(this.fruitsForm.value); + ev.preventDefault(); } } diff --git a/ionic/components/checkbox/test/basic/main.html b/ionic/components/checkbox/test/basic/main.html index 6ee83b8ff7..82ca261f7b 100644 --- a/ionic/components/checkbox/test/basic/main.html +++ b/ionic/components/checkbox/test/basic/main.html @@ -8,42 +8,43 @@ - - Apple + + Apple, value=apple, init checked - + + Grape, value=grape, init checked, disabled + - + - + + + + diff --git a/ionic/components/show-hide-when/show-hide-when.ts b/ionic/components/show-hide-when/show-hide-when.ts new file mode 100644 index 0000000000..ae4a269006 --- /dev/null +++ b/ionic/components/show-hide-when/show-hide-when.ts @@ -0,0 +1,98 @@ +import {Directive, Attribute, NgZone} from 'angular2/angular2' + +import {Platform} from '../../platform/platform'; + + +class DisplayWhen { + + constructor(conditions, ngZone) { + this.isMatch = false; + + if (!conditions) return; + + this.conditions = conditions.split(','); + + // check if its one of the matching platforms first + // a platform does not change during the life of an app + for (let i = 0; i < this.conditions.length; i++) { + if (this.conditions[i] && Platform.is(this.conditions[i])) { + this.isMatch = true; + return; + } + } + + if ( this.orientation() ) { + // add window resize listener + Platform.onResize(() => { + ngZone.run(() => { + this.orientation(); + }); + }); + return; + } + + } + + orientation() { + for (let i = 0; i < this.conditions.length; i++) { + var condition = this.conditions[i]; + + if (condition == 'portrait') { + this.isMatch = Platform.isPortrait(); + return true; + } + + if (condition == 'landscape') { + this.isMatch = Platform.isLandscape(); + return true; + } + + } + } + +} + + +@Directive({ + selector: '[show-when]', + host: { + '[hidden]': 'hidden' + } +}) +export class ShowWhen extends DisplayWhen { + + constructor( + @Attribute('show-when') showWhen: string, + ngZone: NgZone + ) { + super(showWhen, ngZone); + } + + get hidden() { + return !this.isMatch; + } + +} + + +@Directive({ + selector: '[hide-when]', + host: { + '[hidden]': 'hidden' + } +}) +export class HideWhen extends DisplayWhen { + + constructor( + @Attribute('hide-when') hideWhen: string, + ngZone: NgZone + ) { + super(hideWhen, ngZone); + } + + get hidden() { + return this.isMatch; + } + +} + diff --git a/ionic/components/show-hide-when/test/basic/e2e.ts b/ionic/components/show-hide-when/test/basic/e2e.ts new file mode 100644 index 0000000000..3e340014f6 --- /dev/null +++ b/ionic/components/show-hide-when/test/basic/e2e.ts @@ -0,0 +1,4 @@ + +it('should toggle checkbox state with label click', function() { + element(by.css('#appleLabel')).click(); +}); diff --git a/ionic/components/show-hide-when/test/basic/index.ts b/ionic/components/show-hide-when/test/basic/index.ts new file mode 100644 index 0000000000..40e35c35b2 --- /dev/null +++ b/ionic/components/show-hide-when/test/basic/index.ts @@ -0,0 +1,44 @@ +import {App} from 'ionic/ionic'; +import { + Control, + ControlGroup, + NgForm, + formDirectives, + Validators, + NgControl, + ControlValueAccessor, + NgControlName, + NgFormModel, + FormBuilder +} from 'angular2/forms'; + +@App({ + templateUrl: 'main.html' +}) +class IonicApp { + constructor() { + this.fruitsForm = new ControlGroup({ + "appleCtrl": new Control(), + "bananaCtrl": new Control(true), + "cherryCtrl": new Control(false), + "grapeCtrl": new Control(true) + }); + + this.grapeDisabled = true; + this.grapeChecked = true; + } + + toggleGrapeChecked() { + this.grapeChecked = !this.grapeChecked; + } + + toggleGrapeDisabled() { + this.grapeDisabled = !this.grapeDisabled; + } + + doSubmit(ev) { + console.log('Submitting form', this.fruitsForm.value); + this.formResults = JSON.stringify(this.fruitsForm.value); + ev.preventDefault(); + } +} diff --git a/ionic/components/show-hide-when/test/basic/main.html b/ionic/components/show-hide-when/test/basic/main.html new file mode 100644 index 0000000000..95313396f0 --- /dev/null +++ b/ionic/components/show-hide-when/test/basic/main.html @@ -0,0 +1,59 @@ + +Show/Hide When + + + + +

+ show-when="ios" +

+ +

+ show-when="android" +

+ +

+ show-when="android,ios" +

+ +

+ show-when="core" +

+ +

+ show-when="mobile" +

+ +

+ show-when="phablet" +

+ +

+ show-when="tablet" +

+ +

+ show-when="iphone" +

+ +

+ show-when="landscape" +

+ +

+ show-when="portrait" +

+ +

+ hide-when="ios" +

+ +

+ hide-when="android" +

+ +

+ hide-when="android,ios" +

+ +
diff --git a/ionic/config/annotations.ts b/ionic/config/annotations.ts index 6beddb1f4d..62c3a9fd89 100644 --- a/ionic/config/annotations.ts +++ b/ionic/config/annotations.ts @@ -19,6 +19,7 @@ import { Nav, NavbarTemplate, Navbar, NavPush, NavPop, TapClick, TapDisabled, Register, + ShowWhen, HideWhen, MaterialButton } from '../ionic'; @@ -82,6 +83,9 @@ export const IonicDirectives = [ forwardRef(() => NavPop), forwardRef(() => Register), + forwardRef(() => ShowWhen), + forwardRef(() => HideWhen), + // Gestures forwardRef(() => TapClick), forwardRef(() => TapDisabled), diff --git a/ionic/platform/platform.ts b/ionic/platform/platform.ts index 324d4c4c97..d33139b1c0 100644 --- a/ionic/platform/platform.ts +++ b/ionic/platform/platform.ts @@ -10,6 +10,7 @@ export class PlatformCtrl { this._versions = {}; this._registry = {}; this._default = null; + this._onResizes = []; this._readyPromise = new Promise(res => { this._readyResolve = res; } ); } @@ -137,8 +138,25 @@ export class PlatformCtrl { return !this.isPortrait(); } - resetDimensions() { - this._w = this._h = 0; + winResize() { + Platform._w = Platform._h = 0; + + clearTimeout(Platform._resizeTimer); + + Platform._resizeTimer = setTimeout(() => { + for (let i = 0; i < Platform._onResizes.length; i++) { + try { + Platform._onResizes[i](); + } catch (e) { + console.error(e); + } + } + }, 500); + } + + onResize(cb) { + // TODO: Make more good + this._onResizes.push(cb); }