diff --git a/packages/core/src/components/content/content.tsx b/packages/core/src/components/content/content.tsx index 7f29cb326a..cb88e9233b 100644 --- a/packages/core/src/components/content/content.tsx +++ b/packages/core/src/components/content/content.tsx @@ -49,14 +49,6 @@ export class Content { this.scrollEl = null; } - hostData() { - return { - class: { - 'statusbar-padding': this.config.getBoolean('statusbarPadding') - } - }; - } - /** * Scroll to the top of the content component. * @@ -79,7 +71,17 @@ export class Content { return this.scrollEl.scrollToBottom(duration); } - resize() { + @Method() + scrollByPoint(x: number, y: number, duration: number, done?: Function): Promise { + return this.scrollEl.scrollByPoint(x, y, duration, done); + } + + @Method() + scrollToPoint(x: number, y: number, duration: number, done?: Function): Promise { + return this.scrollEl.scrollToPoint(x, y, duration, done); + } + + private resize() { if (!this.scrollEl) { return; } @@ -114,6 +116,14 @@ export class Content { } } + hostData() { + return { + class: { + 'statusbar-padding': this.config.getBoolean('statusbarPadding') + } + }; + } + render() { this.resize(); diff --git a/packages/core/src/components/content/readme.md b/packages/core/src/components/content/readme.md index 3c4622cd0d..b0a2e96a6c 100644 --- a/packages/core/src/components/content/readme.md +++ b/packages/core/src/components/content/readme.md @@ -56,6 +56,9 @@ to transparent. ## Methods +#### scrollByPoint() + + #### scrollToBottom() Scroll to the bottom of the content component. @@ -64,6 +67,9 @@ Duration of the scroll animation in milliseconds. Defaults to `300`. Returns a promise which is resolved when the scroll has completed. +#### scrollToPoint() + + #### scrollToTop() Scroll to the top of the content component. diff --git a/packages/core/src/components/input-shims/hacks/common.ts b/packages/core/src/components/input-shims/hacks/common.ts new file mode 100644 index 0000000000..d7f2b7a9a8 --- /dev/null +++ b/packages/core/src/components/input-shims/hacks/common.ts @@ -0,0 +1,96 @@ +const RELOCATED_KEY= '$ionRelocated'; + +export function relocateInput( + componentEl: HTMLElement, + inputEl: HTMLInputElement, + shouldRelocate: boolean, + inputRelativeY: number = 0 +) { + if ((componentEl as any)[RELOCATED_KEY] === shouldRelocate) { + return; + } + console.debug(`native-input, hideCaret, shouldHideCaret: ${shouldRelocate}, input value: ${inputEl.value}`); + if (shouldRelocate) { + // this allows for the actual input to receive the focus from + // the user's touch event, but before it receives focus, it + // moves the actual input to a location that will not screw + // up the app's layout, and does not allow the native browser + // to attempt to scroll the input into place (messing up headers/footers) + // the cloned input fills the area of where native input should be + // while the native input fakes out the browser by relocating itself + // before it receives the actual focus event + // We hide the focused input (with the visible caret) invisiable by making it scale(0), + cloneInputComponent(componentEl, inputEl); + const tx = document.dir === 'rtl' ? 9999 : -9999; + inputEl.style.transform= `translate3d(${tx}px,${inputRelativeY}px,0)`; + // TODO + // inputEle.style.opacity = '0'; + } else { + removeClone(componentEl, inputEl); + } + (componentEl as any)[RELOCATED_KEY] = shouldRelocate; +} + + +export function isFocused(input: HTMLInputElement): boolean { + return input === document.activeElement; +} + +function removeClone(componentEl: HTMLElement, inputEl: HTMLElement) { + if (componentEl && componentEl.parentElement) { + const clonedInputEles = componentEl.parentElement.querySelectorAll('.cloned-input'); + for (let i = 0; i < clonedInputEles.length; i++) { + clonedInputEles[i].parentNode.removeChild(clonedInputEles[i]); + } + componentEl.style.pointerEvents = ''; + } + (inputEl.style)['transform'] = ''; + inputEl.style.opacity = ''; +} + +function cloneInputComponent(componentEl: HTMLElement, inputEl: HTMLInputElement) { + // Make sure we kill all the clones before creating new ones + // It is a defensive, removeClone() should do nothing + // removeClone(plt, srcComponentEle, srcNativeInputEle); + // given a native or