mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-14 16:52:26 +08:00
fix(scroll-assist): set correct scroll padding (#27261)
Issue number: resolves #27257 --------- <!-- Please refer to our contributing documentation for any questions on submitting a pull request, or let us know here if you need any help: https://ionicframework.com/docs/building/contributing --> <!-- Some docs updates need to be made in the `ionic-docs` repo, in a separate PR. See https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation for details. --> <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> 1. Scroll assist was appending padding data every time it ran which caused the amount of padding to infinitely grow until an input was blurred 2. Calling `inputEl.focus()` caused scroll assist to run again which caused unexpected scrolls ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - `currentPadding` is either preserved or set, never incremented - Added a special attribute to inputs that are manually focused so scroll assist knows not to re-run ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. -->
This commit is contained in:
@ -9,6 +9,8 @@ import { setScrollPadding, setClearScrollPaddingListener } from './scroll-paddin
|
||||
|
||||
let currentPadding = 0;
|
||||
|
||||
const SKIP_SCROLL_ASSIST = 'data-ionic-skip-scroll-assist';
|
||||
|
||||
export const enableScrollAssist = (
|
||||
componentEl: HTMLElement,
|
||||
inputEl: HTMLInputElement | HTMLTextAreaElement,
|
||||
@ -37,6 +39,16 @@ export const enableScrollAssist = (
|
||||
* mobile Safari from adjusting the viewport.
|
||||
*/
|
||||
const focusIn = async () => {
|
||||
/**
|
||||
* Scroll assist should not run again
|
||||
* on inputs that have been manually
|
||||
* focused inside of the scroll assist
|
||||
* implementation.
|
||||
*/
|
||||
if (inputEl.hasAttribute(SKIP_SCROLL_ASSIST)) {
|
||||
inputEl.removeAttribute(SKIP_SCROLL_ASSIST);
|
||||
return;
|
||||
}
|
||||
jsSetFocus(componentEl, inputEl, contentEl, footerEl, keyboardHeight, addScrollPadding, disableClonedInput);
|
||||
};
|
||||
componentEl.addEventListener('focusin', focusIn, true);
|
||||
@ -46,6 +58,24 @@ export const enableScrollAssist = (
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Use this function when you want to manually
|
||||
* focus an input but not have scroll assist run again.
|
||||
*/
|
||||
const setManualFocus = (el: HTMLElement) => {
|
||||
/**
|
||||
* If element is already focused then
|
||||
* a new focusin event will not be dispatched
|
||||
* to remove the SKIL_SCROLL_ASSIST attribute.
|
||||
*/
|
||||
if (document.activeElement === el) {
|
||||
return;
|
||||
}
|
||||
|
||||
el.setAttribute(SKIP_SCROLL_ASSIST, 'true');
|
||||
el.focus();
|
||||
};
|
||||
|
||||
const jsSetFocus = async (
|
||||
componentEl: HTMLElement,
|
||||
inputEl: HTMLInputElement | HTMLTextAreaElement,
|
||||
@ -63,7 +93,7 @@ const jsSetFocus = async (
|
||||
if (contentEl && Math.abs(scrollData.scrollAmount) < 4) {
|
||||
// the text input is in a safe position that doesn't
|
||||
// require it to be scrolled into view, just set focus now
|
||||
inputEl.focus();
|
||||
setManualFocus(inputEl);
|
||||
|
||||
/**
|
||||
* Even though the input does not need
|
||||
@ -75,7 +105,6 @@ const jsSetFocus = async (
|
||||
* see the page jump.
|
||||
*/
|
||||
if (enableScrollPadding && contentEl !== null) {
|
||||
currentPadding += scrollData.scrollPadding;
|
||||
setScrollPadding(contentEl, currentPadding);
|
||||
setClearScrollPaddingListener(inputEl, contentEl, () => (currentPadding = 0));
|
||||
}
|
||||
@ -87,7 +116,7 @@ const jsSetFocus = async (
|
||||
// doesn't freak out while it's trying to get the input in place
|
||||
// at this point the native text input still does not have focus
|
||||
relocateInput(componentEl, inputEl, true, scrollData.inputSafeY, disableClonedInput);
|
||||
inputEl.focus();
|
||||
setManualFocus(inputEl);
|
||||
|
||||
/**
|
||||
* Relocating/Focusing input causes the
|
||||
@ -103,7 +132,7 @@ const jsSetFocus = async (
|
||||
* the keyboard.
|
||||
*/
|
||||
if (enableScrollPadding && contentEl) {
|
||||
currentPadding += scrollData.scrollPadding;
|
||||
currentPadding = scrollData.scrollPadding;
|
||||
setScrollPadding(contentEl, currentPadding);
|
||||
}
|
||||
|
||||
@ -128,7 +157,7 @@ const jsSetFocus = async (
|
||||
relocateInput(componentEl, inputEl, false, scrollData.inputSafeY);
|
||||
|
||||
// ensure this is the focused input
|
||||
inputEl.focus();
|
||||
setManualFocus(inputEl);
|
||||
|
||||
/**
|
||||
* When the input is about to be blurred
|
||||
|
Reference in New Issue
Block a user