mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix(all): js hardening (strict + tslint sonar)
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -40,7 +40,7 @@ export class HideWhen implements DisplayWhen {
|
||||
}
|
||||
|
||||
render() {
|
||||
return <slot></slot>
|
||||
return <slot></slot>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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)`;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
|
||||
@@ -150,9 +150,6 @@ export class Popover {
|
||||
|
||||
@Listen('ionBackdropTap')
|
||||
protected onBackdropTap() {
|
||||
// const opts: NavOptions = {
|
||||
// minClickBlockDuration: 400
|
||||
// };
|
||||
this.dismiss();
|
||||
}
|
||||
|
||||
|
||||
@@ -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' : '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -40,7 +40,7 @@ export class ShowWhen implements DisplayWhen {
|
||||
}
|
||||
|
||||
render() {
|
||||
return <slot></slot>
|
||||
return <slot></slot>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 /
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user