fix(all): js hardening (strict + tslint sonar)

This commit is contained in:
Manu Mtz.-Almeida
2018-02-21 13:14:20 +01:00
parent ef7c978544
commit de2f44cbaa
31 changed files with 269 additions and 325 deletions

View File

@@ -109,75 +109,6 @@ export class ActionSheet {
*/
@Event() ionActionSheetDidUnload: EventEmitter<ActionSheetEventDetail>;
/**
* Present the action sheet overlay after it has been created.
*/
@Method()
present() {
if (this.animation) {
this.animation.destroy();
this.animation = null;
}
this.ionActionSheetWillPresent.emit();
this.el.style.zIndex = `${20000 + this.actionSheetId}`;
// get the user's animation fn if one was provided
const animationBuilder = this.enterAnimation || this.config.get('actionSheetEnter', this.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation);
// build the animation and kick it off
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
// Check if prop animate is false or if the config for animate is defined/false
if (!this.willAnimate || (isDef(this.config.get('willAnimate')) && this.config.get('willAnimate') === false)) {
// if the duration is 0, it won't actually animate I don't think
// TODO - validate this
this.animation = animation.duration(0);
}
return playAnimationAsync(animation);
}).then((animation) => {
animation.destroy();
this.ionActionSheetDidPresent.emit();
});
}
/**
* Dismiss the action sheet overlay after it has been presented.
*/
@Method()
dismiss(data?: any, role?: string) {
if (this.animation) {
this.animation.destroy();
this.animation = null;
}
this.ionActionSheetWillDismiss.emit({
data,
role
});
const animationBuilder = this.leaveAnimation || this.config.get('actionSheetLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation);
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
if (!this.willAnimate || (isDef(this.config.get('willAnimate')) && this.config.get('willAnimate') === false)) {
this.animation = animation.duration(0);
}
return playAnimationAsync(animation);
}).then((animation) => {
animation.destroy();
this.ionActionSheetDidDismiss.emit({
data,
role
});
}).then(() => {
return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el);
});
});
}
componentDidLoad() {
this.ionActionSheetDidLoad.emit();
@@ -200,6 +131,61 @@ export class ActionSheet {
this.dismiss();
}
/**
* Present the action sheet overlay after it has been created.
*/
@Method()
present() {
this.ionActionSheetWillPresent.emit();
this.el.style.zIndex = `${20000 + this.actionSheetId}`;
// get the user's animation fn if one was provided
const animationBuilder = this.enterAnimation || this.config.get('actionSheetEnter', this.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation);
// build the animation and kick it off
return this.playAnimation(animationBuilder).then(() => {
this.ionActionSheetDidPresent.emit();
});
}
/**
* Dismiss the action sheet overlay after it has been presented.
*/
@Method()
dismiss(data?: any, role?: string) {
this.ionActionSheetWillDismiss.emit({data, role});
const animationBuilder = this.leaveAnimation || this.config.get('actionSheetLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation);
return this.playAnimation(animationBuilder).then(() => {
this.ionActionSheetDidDismiss.emit({data, role});
return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el);
});
});
}
private playAnimation(animationBuilder: AnimationBuilder) {
if (this.animation) {
this.animation.destroy();
this.animation = null;
}
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
// Check if prop animate is false or if the config for animate is defined/false
if (!this.willAnimate || (isDef(this.config.get('willAnimate')) && this.config.get('willAnimate') === false)) {
// if the duration is 0, it won't actually animate I don't think
// TODO - validate this
this.animation = animation.duration(0);
}
return playAnimationAsync(animation);
}).then((animation) => {
animation.destroy();
this.animation = null;
});
}
protected buttonClick(button: ActionSheetButton) {
let shouldDismiss = true;
if (button.handler) {

View File

@@ -1,4 +1,4 @@
import { Component, CssClassMap, Element, Event, EventEmitter, Method, Prop, Listen } from '@stencil/core';
import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers';
@@ -123,75 +123,6 @@ export class Alert {
*/
@Event() ionAlertDidUnload: EventEmitter<AlertEventDetail>;
/**
* Present the alert overlay after it has been created.
*/
@Method()
present() {
if (this.animation) {
this.animation.destroy();
this.animation = null;
}
this.ionAlertWillPresent.emit();
this.el.style.zIndex = `${20000 + this.alertId}`;
// get the user's animation fn if one was provided
const animationBuilder = this.enterAnimation || this.config.get('alertEnter', this.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation);
// build the animation and kick it off
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
if (!this.willAnimate) {
// if the duration is 0, it won't actually animate I don't think
// TODO - validate this
this.animation = animation.duration(0);
}
return playAnimationAsync(animation);
}).then((animation) => {
animation.destroy();
const firstInput = this.el.querySelector('[tabindex]') as HTMLElement;
if (firstInput) {
firstInput.focus();
}
this.ionAlertDidPresent.emit();
});
}
/**
* Dismiss the alert overlay after it has been presented.
*/
@Method()
dismiss(data?: any, role?: string) {
if (this.animation) {
this.animation.destroy();
this.animation = null;
}
this.ionAlertWillDismiss.emit({
data: data,
role: role
});
// get the user's animation fn if one was provided
const animationBuilder = this.leaveAnimation || this.config.get('alertLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation);
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
return playAnimationAsync(animation);
}).then((animation) => {
animation.destroy();
this.ionAlertDidDismiss.emit({
data: data,
role: role
});
}).then(() => {
return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el);
});
});
}
componentDidLoad() {
this.ionAlertDidLoad.emit();
}
@@ -209,7 +140,46 @@ export class Alert {
this.dismiss(null, BACKDROP);
}
rbClick(inputIndex: number) {
/**
* Present the alert overlay after it has been created.
*/
@Method()
present() {
this.ionAlertWillPresent.emit();
this.el.style.zIndex = `${20000 + this.alertId}`;
// get the user's animation fn if one was provided
const animationBuilder = this.enterAnimation || this.config.get('alertEnter', this.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation);
// build the animation and kick it off
return this.playAnimation(animationBuilder).then(() => {
const firstInput = this.el.querySelector('[tabindex]') as HTMLElement;
if (firstInput) {
firstInput.focus();
}
this.ionAlertDidPresent.emit();
});
}
/**
* Dismiss the alert overlay after it has been presented.
*/
@Method()
dismiss(data?: any, role?: string) {
this.ionAlertWillDismiss.emit({data, role});
// get the user's animation fn if one was provided
const animationBuilder = this.leaveAnimation || this.config.get('alertLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation);
return this.playAnimation(animationBuilder).then(() => {
return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el);
});
});
}
private rbClick(inputIndex: number) {
this.inputs = this.inputs.map((input, index) => {
input.checked = (inputIndex === index);
return input;
@@ -223,7 +193,7 @@ export class Alert {
}
}
cbClick(inputIndex: number) {
private cbClick(inputIndex: number) {
this.inputs = this.inputs.map((input, index) => {
if (inputIndex === index) {
input.checked = !input.checked;
@@ -237,7 +207,7 @@ export class Alert {
}
}
buttonClick(button: any) {
private buttonClick(button: any) {
let shouldDismiss = true;
if (button.handler) {
@@ -254,7 +224,7 @@ export class Alert {
}
}
getValues(): any {
private getValues(): any {
if (this.inputType === 'radio') {
// this is an alert with radio buttons (single value select)
// return the one value which is checked, otherwise undefined
@@ -287,8 +257,27 @@ export class Alert {
return values;
}
private playAnimation(animationBuilder: AnimationBuilder) {
if (this.animation) {
this.animation.destroy();
this.animation = null;
}
renderCheckbox(inputs: AlertInput[]) {
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
if (!this.willAnimate) {
// if the duration is 0, it won't actually animate I don't think
animation.duration(0);
}
return playAnimationAsync(animation);
}).then(animation => {
animation.destroy();
this.animation = null;
});
}
private renderCheckbox(inputs: AlertInput[]) {
if (inputs.length === 0) return null;
return (
@@ -307,7 +296,7 @@ export class Alert {
);
}
renderRadio(inputs: AlertInput[]) {
private renderRadio(inputs: AlertInput[]) {
if (inputs.length === 0) return null;
return (
@@ -326,7 +315,7 @@ export class Alert {
);
}
renderInput(inputs: AlertInput[]) {
private renderInput(inputs: AlertInput[]) {
if (inputs.length === 0) return null;
return (

View File

@@ -133,7 +133,7 @@ export class App {
}
@Method()
getNavByIdOrName(nameOrId: number | string): PublicNav {
getNavByIdOrName(nameOrId: number | string): PublicNav|null {
const navs = Array.from(rootNavs.values());
for (const navContainer of navs) {
const match = getNavByIdOrNameImpl(navContainer, nameOrId);
@@ -222,12 +222,12 @@ export class App {
}
@Listen('document:paused')
appResume(): void {
appResume(): null {
return null;
}
@Listen('document:resume')
appPaused(): void {
appPaused(): null {
return null;
}

View File

@@ -1,4 +1,4 @@
import { Component, Listen, EventEmitter, Event, Prop } from '@stencil/core';
import { Component, Event, EventEmitter, Listen, Prop } from '@stencil/core';
import { now } from '../../utils/helpers';
@Component({
@@ -29,13 +29,13 @@ export class Backdrop {
@Listen('mousedown', {passive: false, capture: true})
protected onMouseDown(ev: TouchEvent) {
if(this.lastClick < now(ev) - 2500) {
if (this.lastClick < now(ev) - 2500) {
this.emitTap(ev);
}
}
private emitTap(ev: Event) {
if(this.stopPropagation) {
if (this.stopPropagation) {
ev.preventDefault();
ev.stopPropagation();
}

View File

@@ -1,4 +1,4 @@
import { Component, Method, EventEmitter, Event } from "@stencil/core";
import { Component, Event, EventEmitter, Method } from '@stencil/core';
@Component({
@@ -82,21 +82,11 @@ export class GestureController {
}
disableScroll(id: number) {
// let isEnabled = !this.isScrollDisabled();
this.disabledScroll.add(id);
// if (this._app && isEnabled && this.isScrollDisabled()) {
// console.debug('GestureController: Disabling scrolling');
// this._app._setDisableScroll(true);
// }
}
enableScroll(id: number) {
// let isDisabled = this.isScrollDisabled();
this.disabledScroll.delete(id);
// if (this._app && isDisabled && !this.isScrollDisabled()) {
// console.debug('GestureController: Enabling scrolling');
// this._app._setDisableScroll(false);
// }
}
canStart(gestureName: string): boolean {

View File

@@ -1,6 +1,6 @@
import { Component, Event, EventEmitter, EventListenerEnable, Listen, Prop, Watch } from '@stencil/core';
import { ElementRef, assert, now, updateDetail } from '../../utils/helpers';
import { BlockerDelegate, GestureDelegate, BlockerConfig, BLOCK_ALL } from '../gesture-controller/gesture-controller';
import { BLOCK_ALL, BlockerConfig, BlockerDelegate, GestureDelegate } from '../gesture-controller/gesture-controller';
import { DomController } from '../../index';
import { PanRecognizer } from './recognizers';
@@ -348,6 +348,7 @@ export class Gesture {
// END *************************
@Listen('touchcancel', { passive: true, enabled: false })
@Listen('touchend', { passive: true, enabled: false })
onTouchCancel(ev: TouchEvent) {
this.lastTouch = this.detail.timeStamp = now(ev);
@@ -355,16 +356,6 @@ export class Gesture {
this.enableTouch(false);
}
@Listen('touchend', { passive: true, enabled: false })
onTouchEnd(ev: TouchEvent) {
this.lastTouch = this.detail.timeStamp = now(ev);
this.pointerUp(ev);
this.enableTouch(false);
}
@Listen('document:mouseup', { passive: true, enabled: false })
onMouseUp(ev: TouchEvent) {
const timeStamp = now(ev);

View File

@@ -40,7 +40,7 @@ export class HideWhen implements DisplayWhen {
}
render() {
return <slot></slot>
return <slot></slot>;
}
}

View File

@@ -85,7 +85,7 @@ export class InfiniteScroll {
componentWillLoad() {
const scrollEl = this.el.closest('ion-scroll');
return scrollEl.componentOnReady().then((el) => {
this.scrollEl = el as HTMLIonScrollElement;
this.scrollEl = el;
});
}

View File

@@ -1,6 +1,6 @@
import { assert } from "../../utils/helpers";
import { CSS_PROP } from "../animation-controller/constants";
import { App } from "../..";
import { assert } from '../../utils/helpers';
import { CSS_PROP } from '../animation-controller/constants';
import { App } from '../..';
const SCROLL_DATA_MAP = new WeakMap<HTMLElement, ScrollData>();
const SCROLL_ASSIST_SPEED = 0.3;
@@ -81,21 +81,27 @@ export function enableScrollPadding(_componentEl: HTMLElement, inputEl: HTMLElem
return () => {
inputEl.removeEventListener('focus', onFocus);
}
};
}
export function enableScrollMove(
componentEl: HTMLElement,
inputEl: HTMLElement,
contentEl: HTMLIonContentElement,
keyboardHeight: number
) {
console.debug('Input: enableAutoScroll');
this.ionFocus.subscribe(() => {
const scrollData = getScrollData(componentEl, contentEl, keyboardHeight)
const onFocus = () => {
const scrollData = getScrollData(componentEl, contentEl, keyboardHeight);
if (Math.abs(scrollData.scrollAmount) > 4) {
contentEl.scrollBy(0, scrollData.scrollAmount);
}
});
};
inputEl.addEventListener('focus', onFocus);
return () => {
inputEl.removeEventListener('focus', onFocus);
};
}
const SKIP_BLURRING = ['INPUT', 'TEXTAREA', 'ION-INPUT', 'ION-TEXTAREA'];
@@ -150,7 +156,7 @@ export function enableInputBlurring(app: App) {
return () => {
document.removeEventListener('focusin', onFocusin, true);
document.removeEventListener('touchend', onTouchend, false);
}
};
}
export function enableHideCaretOnScroll(componentEl: HTMLElement, inputEl: HTMLInputElement, scrollEl: HTMLIonScrollElement) {
@@ -158,7 +164,7 @@ export function enableHideCaretOnScroll(componentEl: HTMLElement, inputEl: HTMLI
console.debug('Input: enableHideCaretOnScroll');
function scrollHideCaret(shouldHideCaret: boolean) {
if(isFocused(inputEl)) {
if (isFocused(inputEl)) {
relocateInput(componentEl, inputEl, shouldHideCaret);
}
}
@@ -168,12 +174,12 @@ export function enableHideCaretOnScroll(componentEl: HTMLElement, inputEl: HTMLI
const showCaret = () => scrollHideCaret(false);
scrollEl.addEventListener('ionScrollStart', hideCaret);
scrollEl.addEventListener('ionScrollEnd',showCaret);
scrollEl.addEventListener('ionScrollEnd', showCaret);
inputEl.addEventListener('blur', onBlur);
return () => {
scrollEl.removeEventListener('ionScrollStart', hideCaret);
scrollEl.removeEventListener('ionScrollEnd',showCaret);
scrollEl.removeEventListener('ionScrollEnd', showCaret);
inputEl.addEventListener('ionBlur', onBlur);
};
}
@@ -196,11 +202,13 @@ function cloneInputComponent(componentEle: HTMLElement, nativeInputEle: HTMLInpu
// Make sure we kill all the clones before creating new ones
// It is a defensive, removeClone() should do nothing
// removeClone(plt, srcComponentEle, srcNativeInputEle);
assert(componentEle.parentElement.querySelector('.cloned-input') === null, 'leaked cloned input');
// given a native <input> or <textarea> element
// find its parent wrapping component like <ion-input> or <ion-textarea>
// then clone the entire component
if (componentEle) {
const parentElement = componentEle.parentElement;
if (componentEle && parentElement) {
assert(parentElement.querySelector('.cloned-input') === null, 'leaked cloned input');
// DOM READ
const srcTop = componentEle.offsetTop;
const srcLeft = componentEle.offsetLeft;
@@ -225,7 +233,7 @@ function cloneInputComponent(componentEle: HTMLElement, nativeInputEle: HTMLInpu
clonedNativeInputEle.tabIndex = -1;
clonedComponentEle.appendChild(clonedNativeInputEle);
componentEle.parentNode.appendChild(clonedComponentEle);
parentElement.appendChild(clonedComponentEle);
clonedComponentEle.style.pointerEvents = 'none';
}
@@ -250,7 +258,10 @@ function relocateInput(componentEl: HTMLElement, inputEle: HTMLInputElement, sho
// before it receives the actual focus event
// We hide the focused input (with the visible caret) invisiable by making it scale(0),
cloneInputComponent(componentEl, inputEle);
const inputRelativeY = this._getScrollData().inputSafeY;
// TODO
// const inputRelativeY = this._getScrollData().inputSafeY;
const inputRelativeY = 0;
// fix for #11817
const tx = document.dir === 'rtl' ? 9999 : -9999;
(inputEle.style as any)[CSS_PROP.transformProp] = `translate3d(${tx}px,${inputRelativeY}px,0)`;

View File

@@ -42,12 +42,6 @@ export class ItemOption {
*/
@Prop() href: string;
notCaptured() {
// if (!clickedOptionButton(ev)) {
// this.closeOpened();
// }
}
clickedOptionButton(ev: Event): boolean {
const el = (ev.target as HTMLElement).closest('ion-item-option');
return !!el;

View File

@@ -57,7 +57,7 @@ export class ItemSliding {
componentDidLoad() {
this.item = this.el.querySelector('ion-item');
this.list = this.el.closest('ion-list') as HTMLIonListElement;
this.list = this.el.closest('ion-list');
this.updateOptions();
}

View File

@@ -161,11 +161,6 @@ export class Loading {
*/
@Method()
present() {
if (this.animation) {
this.animation.destroy();
this.animation = null;
}
this.ionLoadingWillPresent.emit();
this.el.style.zIndex = `${20000 + this.loadingId}`;
@@ -174,16 +169,7 @@ export class Loading {
const animationBuilder = this.enterAnimation || this.config.get('loadingEnter', this.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation);
// build the animation and kick it off
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
if (!this.willAnimate) {
// if the duration is 0, it won't actually animate I don't think
// TODO - validate this
this.animation = animation.duration(0);
}
return playAnimationAsync(animation);
}).then((animation) => {
animation.destroy();
return this.playAnimation(animationBuilder).then(() => {
this.componentDidEnter();
});
}
@@ -195,36 +181,35 @@ export class Loading {
dismiss(data?: any, role?: string) {
clearTimeout(this.durationTimeout);
this.ionLoadingWillDismiss.emit({data, role});
const animationBuilder = this.leaveAnimation || this.config.get('loadingLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation);
return this.playAnimation(animationBuilder).then(() => {
this.ionLoadingDidDismiss.emit({data, role});
return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el);
});
});
}
private playAnimation(animationBuilder: AnimationBuilder) {
if (this.animation) {
this.animation.destroy();
this.animation = null;
}
this.ionLoadingWillDismiss.emit({
data,
role
});
const animationBuilder = this.leaveAnimation || this.config.get('loadingLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation);
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
if (!this.willAnimate) {
// if the duration is 0, it won't actually animate I don't think
// TODO - validate this
this.animation = animation.duration(0);
animation.duration(0);
}
return playAnimationAsync(animation);
}).then((animation) => {
}).then(animation => {
animation.destroy();
this.ionLoadingDidDismiss.emit({
data,
role
});
}).then(() => {
return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el);
});
this.animation = null;
});
}

View File

@@ -224,7 +224,7 @@ export class MenuController {
const side = menu.side;
this.menus
.filter(m => m.side === side && m !== menu)
.map(m => m.disabled = true);
.forEach(m => m.disabled = true);
}
/**

View File

@@ -15,7 +15,7 @@ import { Side, assert, checkEdgeSide, isRightSide } from '../../utils/helpers';
export class Menu {
private gestureBlocker: string;
private animation: Animation;
private animation: Animation|undefined;
private isPane = false;
private _isOpen = false;
private lastOnEnd = 0;
@@ -23,12 +23,12 @@ export class Menu {
mode: string;
color: string;
isAnimating = false;
width: number = null;
width: number;
backdropEl: HTMLElement;
menuInnerEl: HTMLElement;
contentEl: HTMLElement;
menuCtrl: HTMLIonMenuControllerElement;
backdropEl: HTMLElement|undefined;
menuInnerEl: HTMLElement|undefined;
contentEl: HTMLElement|undefined;
menuCtrl: HTMLIonMenuControllerElement|undefined;
@Element() el: HTMLIonMenuElement;
@@ -67,7 +67,7 @@ export class Menu {
// Remove effects of previous animations
this.menuInnerEl.removeAttribute('style');
}
this.animation = null;
this.animation = undefined;
}
/**
@@ -129,7 +129,7 @@ export class Menu {
componentWillLoad() {
return this.lazyMenuCtrl.componentOnReady().then(menu => {
this.menuCtrl = menu as HTMLIonMenuControllerElement;
this.menuCtrl = menu;
});
}
@@ -141,7 +141,7 @@ export class Menu {
? '#' + this.contentId
: '[main]';
const parent = el.parentElement;
const content = this.contentEl = parent.querySelector(contentQuery) as HTMLElement;
const content = this.contentEl = parent.querySelector(contentQuery);
if (!content || !content.tagName) {
// requires content element
return console.error('Menu: must have a "content" element to listen for drag events on.');
@@ -170,8 +170,8 @@ export class Menu {
this.menuCtrl._unregister(this);
this.animation && this.animation.destroy();
this.menuCtrl = this.animation = null;
this.contentEl = this.backdropEl = this.menuInnerEl = null;
this.menuCtrl = this.animation = undefined;
this.contentEl = this.backdropEl = this.menuInnerEl = undefined;
}
@Listen('body:ionSplitPaneVisible')

View File

@@ -10,7 +10,7 @@ export class NavPop {
@Listen('child:click')
pop(): Promise<NavResult> {
const nav = this.element.closest('ion-nav') as HTMLIonNavElement;
const nav = this.element.closest('ion-nav');
if (nav) {
return nav.pop();
}

View File

@@ -13,7 +13,7 @@ export class NavPush {
@Listen('child:click')
push(): Promise<NavResult> {
const nav = this.element.closest('ion-nav') as HTMLIonNavElement;
const nav = this.element.closest('ion-nav');
if (nav) {
const toPush = this.url || this.component;
return nav.push(toPush, this.data);

View File

@@ -13,7 +13,7 @@ export class NavSetRoot {
@Listen('child:click')
push(): Promise<NavResult> {
const nav = this.element.closest('ion-nav') as HTMLIonNavElement;
const nav = this.element.closest('ion-nav');
if (nav) {
const toPush = this.url || this.component;
return nav.setRoot(toPush, this.data);

View File

@@ -603,7 +603,7 @@ export function setPages(nav: Nav, delegate: FrameworkDelegate, animation: Anima
export function preprocessTransaction(ti: TransitionInstruction): Promise<NavResult> {
if (isUrl(ti.component)) {
if (ti.method === PUSH || ti.method === POP || ti.method === SET_ROOT) {
return navigateToUrl(ti.nav, normalizeUrl(ti.component) as string, ti.method);
return navigateToUrl(ti.nav, normalizeUrl(ti.component), ti.method);
} else {
return Promise.reject(new Error('only push, pop, and setRoot methods support urls'));
}

View File

@@ -150,9 +150,6 @@ export class Popover {
@Listen('ionBackdropTap')
protected onBackdropTap() {
// const opts: NavOptions = {
// minClickBlockDuration: 400
// };
this.dismiss();
}

View File

@@ -336,11 +336,13 @@ export class Refresher {
private setCss(y: number, duration: string, overflowVisible: boolean, delay: string) {
this.appliedStyles = (y > 0);
this.dom.write(() => {
const style = this.scrollEl.style;
style.transform = ((y > 0) ? 'translateY(' + y + 'px) translateZ(0px)' : 'translateZ(0px)');
style.transitionDuration = duration;
style.transitionDelay = delay;
style.overflow = (overflowVisible ? 'hidden' : '');
if (this.scrollEl) {
const style = this.scrollEl.style;
style.transform = ((y > 0) ? 'translateY(' + y + 'px) translateZ(0px)' : 'translateZ(0px)');
style.transitionDuration = duration;
style.transitionDelay = delay;
style.overflow = (overflowVisible ? 'hidden' : '');
}
});
}

View File

@@ -66,8 +66,8 @@ export class ReorderGroup {
}
componentDidLoad() {
this.containerEl = this.el.querySelector('ion-gesture') as HTMLElement;
this.scrollEl = this.el.closest('ion-scroll') as HTMLElement;
this.containerEl = this.el.querySelector('ion-gesture');
this.scrollEl = this.el.closest('ion-scroll');
if (!this.disabled) {
this.disabledChanged(false);
}
@@ -82,7 +82,7 @@ export class ReorderGroup {
return false;
}
const target = ev.event.target as HTMLElement;
const reorderEl = target.closest('ion-reorder') as HTMLElement;
const reorderEl = target.closest('ion-reorder');
if (!reorderEl) {
return false;
}

View File

@@ -62,7 +62,7 @@ export class Router {
}
private writeNavStateRoot(): Promise<any> {
const node = document.querySelector('ion-app') as HTMLElement;
const node = document.querySelector('ion-app');
const currentPath = this.readPath();
const direction = window.history.state >= this.state ? 1 : -1;
if (currentPath) {

View File

@@ -75,7 +75,7 @@ export class Scroll {
if (this.forceOverscroll === undefined) {
this.forceOverscroll = this.mode === 'ios' && ('ontouchstart' in window);
}
this.app = this.el.closest('ion-app') as HTMLIonAppElement;
this.app = this.el.closest('ion-app');
}
componentDidUnload() {

View File

@@ -40,7 +40,7 @@ export class ShowWhen implements DisplayWhen {
}
render() {
return <slot></slot>
return <slot></slot>;
}
}

View File

@@ -26,7 +26,7 @@ export class Tabbar {
@Prop({ context: 'dom' }) dom: DomController;
@Prop() placement = 'bottom';
@Prop() selectedTab: HTMLIonTabElement;
@Prop() scrollable: Boolean;
@Prop() scrollable: boolean;
@Prop() tabs: HTMLIonTabElement[];
private scrollEl: HTMLIonScrollElement;

View File

@@ -13,7 +13,7 @@ export class TranslucentPageTab {
@Element() element: HTMLElement;
getTabs() {
return this.element.closest('ion-tabs') as HTMLIonTabsElement;
return this.element.closest('ion-tabs');
}
setLayout(value: string) {

View File

@@ -8,7 +8,7 @@ import { now, pointerCoordX, pointerCoordY } from '../../utils/helpers';
export class TapClick {
private app: HTMLIonAppElement;
private lastTouch = -MOUSE_WAIT*10;
private lastTouch = -MOUSE_WAIT * 10;
private lastActivated = 0;
private cancelled = false;
@@ -26,7 +26,7 @@ export class TapClick {
if (this.isServer) {
return;
}
this.app = this.el.closest('ion-app') as HTMLIonAppElement;
this.app = this.el.closest('ion-app');
}
@Listen('body:click', {passive: false, capture: true})

View File

@@ -49,7 +49,6 @@ export type DomRenderFn = (dom: VirtualNode[], height: number) => void;
export function updateVDom(dom: VirtualNode[], heightIndex: Uint32Array, cells: Cell[], range: Range) {
// reset dom
for (const node of dom) {
// node.top = -9999;
node.change = NodeChange.NoChange;
node.d = true;
}
@@ -76,7 +75,6 @@ export function updateVDom(dom: VirtualNode[], heightIndex: Uint32Array, cells:
// needs to append
const pool = dom.filter((n) => n.d);
// console.log('toMutate', toMutate.length);
for (const cell of toMutate) {
const node = pool.find(n => n.d && n.cell.type === cell.type);
const index = cell.index;

View File

@@ -111,7 +111,7 @@ export class VirtualScroll {
}
componentDidLoad() {
this.scrollEl = this.el.closest('ion-scroll') as HTMLElement;
this.scrollEl = this.el.closest('ion-scroll');
if (!this.scrollEl) {
console.error('virtual-scroll must be used inside ion-scroll/ion-content');
return;
@@ -203,58 +203,61 @@ export class VirtualScroll {
this.timerUpdate = null;
}
this.dom.read(() => {
let topOffset = 0;
let node: HTMLElement | null = this.el;
while (node && node !== this.scrollEl) {
topOffset += node.offsetTop;
node = node.parentElement;
this.dom.read(this.readVS.bind(this));
this.dom.read(this.writeVS.bind(this));
}
private readVS() {
let topOffset = 0;
let node: HTMLElement | null = this.el;
while (node && node !== this.scrollEl) {
topOffset += node.offsetTop;
node = node.parentElement;
}
this.viewportOffset = topOffset;
if (this.scrollEl) {
this.currentScrollTop = this.scrollEl.scrollTop;
}
}
private writeVS() {
const dirtyIndex = this.indexDirty;
// get visible viewport
const scrollTop = this.currentScrollTop - this.viewportOffset;
const viewport = getViewport(scrollTop, this.viewportHeight, 100);
// compute lazily the height index
const heightIndex = this.getHeightIndex(viewport);
// get array bounds of visible cells base in the viewport
const range = getRange(heightIndex, viewport, 2);
// fast path, do nothing
const shouldUpdate = getShouldUpdate(dirtyIndex, this.range, range);
if (!shouldUpdate) {
return;
}
this.range = range;
// in place mutation of the virtual DOM
updateVDom(
this.virtualDom,
heightIndex,
this.cells,
range
);
// write DOM
if (this.itemRender) {
doRender(this.el, this.itemRender, this.virtualDom, this.updateCellHeight.bind(this));
if (this.heightChanged) {
this.el.style.height = this.totalHeight + 'px';
this.heightChanged = false;
}
this.viewportOffset = topOffset;
if (this.scrollEl) {
this.currentScrollTop = this.scrollEl.scrollTop;
}
});
this.dom.write(() => {
const dirtyIndex = this.indexDirty;
// get visible viewport
const scrollTop = this.currentScrollTop - this.viewportOffset;
const viewport = getViewport(scrollTop, this.viewportHeight, 100);
// compute lazily the height index
const heightIndex = this.getHeightIndex(viewport);
// get array bounds of visible cells base in the viewport
const range = getRange(heightIndex, viewport, 2);
// fast path, do nothing
const shouldUpdate = getShouldUpdate(dirtyIndex, this.range, range);
if (!shouldUpdate) {
return;
}
this.range = range;
// in place mutation of the virtual DOM
updateVDom(
this.virtualDom,
heightIndex,
this.cells,
range
);
// write DOM
if (this.itemRender) {
doRender(this.el, this.itemRender, this.virtualDom, this.updateCellHeight.bind(this));
if (this.heightChanged) {
this.el.style.height = this.totalHeight + 'px';
this.heightChanged = false;
}
} else if (this.domRender) {
this.domRender(this.virtualDom, this.totalHeight);
}
});
} else if (this.domRender) {
this.domRender(this.virtualDom, this.totalHeight);
}
}
private updateCellHeight(cell: Cell, node: HTMLStencilElement | HTMLElement) {

View File

@@ -266,10 +266,8 @@ export function reorderArray(array: any[], indexes: {from: number, to: number}):
}
export function playAnimationAsync(animation: Animation): Promise<Animation> {
return new Promise((resolve) => {
animation.onFinish((ani) => {
resolve(ani);
});
return new Promise(resolve => {
animation.onFinish(resolve);
animation.play();
});
}
@@ -308,7 +306,7 @@ export function getNavAsChildIfExists(element: HTMLElement): HTMLIonNavElement|n
return null;
}
export function normalizeUrl(url: string) {
export function normalizeUrl(url: string): string {
url = url.trim();
if (url.charAt(0) !== '/') {
// ensure first char is a /

View File

@@ -80,7 +80,7 @@ export function getTestResult(displayWhen: DisplayWhen) {
}
export function isOrientationMatch(orientation: string) {
if (orientation == 'portrait') {
if (orientation === 'portrait') {
return isPortrait();
} else if (orientation === 'landscape') {
return !isPortrait();
@@ -110,4 +110,4 @@ export interface DisplayWhen {
passesTest: boolean;
platform: string;
size: string;
}
}