From d577e24e9d65cd08d2ffd707666f8a14c125bf8b Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Thu, 24 Sep 2015 10:54:33 -0500 Subject: [PATCH] perf(button): no reflows on button onInit --- ionic/components/button/button.ts | 68 +++++++++++++++++++++++-------- ionic/components/icon/icon.ts | 42 +------------------ 2 files changed, 53 insertions(+), 57 deletions(-) diff --git a/ionic/components/button/button.ts b/ionic/components/button/button.ts index 917f99d78d..7d7269069d 100644 --- a/ionic/components/button/button.ts +++ b/ionic/components/button/button.ts @@ -1,30 +1,64 @@ -import {Directive} from 'angular2/angular2'; +import {Directive, ElementRef, Renderer} from 'angular2/angular2'; + +import {IonicConfig} from '../../config/config'; /** * TODO */ @Directive({ - selector: 'button,[button]', - host: { - '[class.icon-left]': 'iconLeft', - '[class.icon-right]': 'iconRight', - '[class.icon-only]': 'iconOnly' - } + selector: 'button,[button]' }) export class Button { - constructor() { + constructor( + config: IonicConfig, + elementRef: ElementRef, + renderer: Renderer + ) { this.iconLeft = this.iconRight = this.iconOnly = false; + + if (config.setting('hoverCSS') === false) { + renderer.setElementClass(elementRef, 'disable-hover', true); + } + + // figure out if and where the icon lives in the button + let childNodes = elementRef.nativeElement.childNodes; + let childNode; + let nodes = []; + for (let i = 0, l = childNodes.length; i < l; i++) { + childNode = childNodes[i]; + if (childNode.nodeType === 3) { + // text node + if (childNode.textContent.trim() !== '') { + nodes.push(TEXT); + } + + } else if (childNode.nodeName === 'ICON') { + // element node + nodes.push(ICON); + + } else { + // element other than an + nodes.push(TEXT); + + } + } + + if (nodes.length > 1) { + if (nodes[0] === ICON && nodes[1] === TEXT) { + renderer.setElementClass(elementRef, 'icon-left', true); + + } else if (nodes[0] === TEXT && nodes[1] === ICON) { + renderer.setElementClass(elementRef, 'icon-right', true); + } + } else if (nodes.length === 1 && nodes[0] === ICON) { + renderer.setElementClass(elementRef, 'icon-only', true); + } + } - /** - * TODO - * @param {TODO} icon TODO - */ - registerIcon(icon) { - this.iconLeft = icon.iconLeft; - this.iconRight = icon.iconRight; - this.iconOnly = icon.iconOnly; - } } + +const TEXT = 1; +const ICON = 2; diff --git a/ionic/components/icon/icon.ts b/ionic/components/icon/icon.ts index aec90ce05c..d76d3be9af 100644 --- a/ionic/components/icon/icon.ts +++ b/ionic/components/icon/icon.ts @@ -1,9 +1,6 @@ -import {Directive, View, NgClass, ElementRef, Optional, Host, Attribute, Renderer} from 'angular2/angular2'; +import {Directive, ElementRef, Attribute, Renderer} from 'angular2/angular2'; import {IonicConfig} from '../../config/config'; -import {IonicComponent} from '../../config/decorators'; -import {Ion} from '../ion'; -import {Button} from '../button/button'; /** @@ -19,7 +16,6 @@ import {Button} from '../button/button'; ], host: { '[attr.aria-label]': 'label', - '[attr.aria-hidden]': 'ariaHidden', 'role': 'img' } }) @@ -27,24 +23,18 @@ export class Icon { /** * TODO * @param {ElementRef} elementRef TODO - * @param {Button} hostButton TODO * @param {IonicConfig} config TODO * @param {Renderer} renderer TODO */ constructor( private elementRef: ElementRef, - @Optional() @Host() hostButton: Button, config: IonicConfig, private renderer: Renderer ) { this.eleRef = elementRef; - this.hostButton = hostButton; this.config = config; this.mode = config.setting('iconMode'); - - this.iconLeft = this.iconRight = this.iconOnly = false; - this.ariaHidden = true; } /** @@ -78,29 +68,6 @@ export class Icon { this.name = 'ion-' + this.mode + '-' + this.name; } - if (this.hostButton) { - // check if there is a sibling element (that's not aria hidden) - let hasPreviousSiblingElement = !!ele.previousElementSibling; - let hasNextSiblingElement = ele.nextElementSibling && ele.nextElementSibling.getAttribute('aria-hidden') !== 'true'; - - if (!hasPreviousSiblingElement && !hasNextSiblingElement) { - // this icon is within a button, and doesn't have a sibling element - // check for text nodes to the right and left of this icon element - this.iconLeft = (ele.nextSibling && ele.nextSibling.textContent || '').trim() !== ''; - this.iconRight = (ele.previousSibling && ele.previousSibling.textContent || '').trim() !== ''; - this.iconOnly = !this.iconLeft && !this.iconRight; - } - - // tell the button there's a child icon - // the button will set the correct css classes on itself - this.hostButton.registerIcon(this); - } - - - // hide the icon when it's within a button - // and the button isn't an icon only button - this.ariaHidden = (this.hostButton && !this.iconOnly); - this.update(); } @@ -113,7 +80,6 @@ export class Icon { this.update(); } - update() { if (this.name && this.mode == 'ios') { @@ -135,11 +101,7 @@ export class Icon { this._name = this.name; this.renderer.setElementClass(this.elementRef, this.name, true); - if (!this.ariaHidden) { - // the icon is either not within a button - // or the icon is within a button, and its an icon only button - this.label = this.name.replace('ion-', '').replace('ios-', '').replace('md-', '').replace('-', ' '); - } + this.label = this.name.replace('ion-', '').replace('ios-', '').replace('md-', '').replace('-', ' '); } }