From daa0e284c32cc8c97006e3a1701ab96ddfabfd30 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 25 Sep 2019 00:21:55 +0300 Subject: forgotten file --- src/services/offset_finder/offset_finder.service.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/services/offset_finder/offset_finder.service.js (limited to 'src/services/offset_finder') diff --git a/src/services/offset_finder/offset_finder.service.js b/src/services/offset_finder/offset_finder.service.js new file mode 100644 index 00000000..edee6412 --- /dev/null +++ b/src/services/offset_finder/offset_finder.service.js @@ -0,0 +1,20 @@ +export const findOffset = (child, parent, { top = 0, left = 0 } = {}, ignorePadding = true) => { + const result = { + top: top + child.offsetTop, + left: left + child.offsetLeft + } + if (!ignorePadding && child !== window) { + const topPaddingStr = window.getComputedStyle(child)['padding-top'] + const topPadding = Number(topPaddingStr.substring(0, topPaddingStr.length - 2)) + const leftPaddingStr = window.getComputedStyle(child)['padding-left'] + const leftPadding = Number(leftPaddingStr.substring(0, leftPaddingStr.length - 2)) + result.top += ignorePadding ? 0 : topPadding + result.left += ignorePadding ? 0 : leftPadding + } + + if (child.offsetParent && (parent === window || parent.contains(child.offsetParent))) { + return findOffset(child.offsetParent, parent, result, false) + } else { + return result + } +} -- cgit v1.2.3-70-g09d2 From 4f563e6efb135e74454cf744eb9ce170ae7a4024 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 25 Sep 2019 08:36:30 +0300 Subject: account for parent padding, too --- src/services/offset_finder/offset_finder.service.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/services/offset_finder') diff --git a/src/services/offset_finder/offset_finder.service.js b/src/services/offset_finder/offset_finder.service.js index edee6412..1c45bb1a 100644 --- a/src/services/offset_finder/offset_finder.service.js +++ b/src/services/offset_finder/offset_finder.service.js @@ -4,17 +4,27 @@ export const findOffset = (child, parent, { top = 0, left = 0 } = {}, ignorePadd left: left + child.offsetLeft } if (!ignorePadding && child !== window) { - const topPaddingStr = window.getComputedStyle(child)['padding-top'] - const topPadding = Number(topPaddingStr.substring(0, topPaddingStr.length - 2)) - const leftPaddingStr = window.getComputedStyle(child)['padding-left'] - const leftPadding = Number(leftPaddingStr.substring(0, leftPaddingStr.length - 2)) + const { topPadding, leftPadding } = findPadding(child) result.top += ignorePadding ? 0 : topPadding result.left += ignorePadding ? 0 : leftPadding } - if (child.offsetParent && (parent === window || parent.contains(child.offsetParent))) { + console.log('eee', parent, child.offsetParent) + if (child.offsetParent && (parent === window || parent.contains(child.offsetParent) || parent === child.offsetParent)) { return findOffset(child.offsetParent, parent, result, false) } else { + const { topPadding, leftPadding } = findPadding(parent) + result.top += topPadding + result.left += leftPadding return result } } + +const findPadding = (el) => { + const topPaddingStr = window.getComputedStyle(el)['padding-top'] + const topPadding = Number(topPaddingStr.substring(0, topPaddingStr.length - 2)) + const leftPaddingStr = window.getComputedStyle(el)['padding-left'] + const leftPadding = Number(leftPaddingStr.substring(0, leftPaddingStr.length - 2)) + + return { topPadding, leftPadding } +} -- cgit v1.2.3-70-g09d2 From 0f55359b49b0abc157957d42f98e3f7b4d25ca18 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 25 Sep 2019 08:43:02 +0300 Subject: fix --- src/services/offset_finder/offset_finder.service.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/services/offset_finder') diff --git a/src/services/offset_finder/offset_finder.service.js b/src/services/offset_finder/offset_finder.service.js index 1c45bb1a..a8e438b5 100644 --- a/src/services/offset_finder/offset_finder.service.js +++ b/src/services/offset_finder/offset_finder.service.js @@ -13,9 +13,11 @@ export const findOffset = (child, parent, { top = 0, left = 0 } = {}, ignorePadd if (child.offsetParent && (parent === window || parent.contains(child.offsetParent) || parent === child.offsetParent)) { return findOffset(child.offsetParent, parent, result, false) } else { - const { topPadding, leftPadding } = findPadding(parent) - result.top += topPadding - result.left += leftPadding + if (parent !== window) { + const { topPadding, leftPadding } = findPadding(parent) + result.top += topPadding + result.left += leftPadding + } return result } } -- cgit v1.2.3-70-g09d2 From 0d6a9f5a629c8a181e4dbd3e2060236773c2337a Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 25 Sep 2019 19:30:55 +0300 Subject: comment, cleanup and improve autoresize/autoscroll --- .../post_status_form/post_status_form.js | 83 +++++++++++++--------- .../offset_finder/offset_finder.service.js | 1 - 2 files changed, 49 insertions(+), 35 deletions(-) (limited to 'src/services/offset_finder') diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index aaecf088..6ba7e7e1 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -277,6 +277,8 @@ const PostStatusForm = { resize (e) { const target = e.target || e if (!(target instanceof window.Element)) { return } + + // Reset to default height for empty form, nothing else to do here. if (target.value === '') { target.style.height = null this.$refs['emoji-input'].resize() @@ -284,61 +286,74 @@ const PostStatusForm = { } const rootRef = this.$refs['root'] - const scroller = this.$el.closest('.sidebar-scroller') || + /* Scroller is either `window` (replies in TL), sidebar (main post form, + * replies in notifs) or mobile post form. Note that getting and setting + * scroll is different for `Window` and `Element`s + */ + const scrollerRef = this.$el.closest('.sidebar-scroller') || this.$el.closest('.post-form-modal-view') || window + // Getting info about padding we have to account for, removing 'px' part const topPaddingStr = window.getComputedStyle(target)['padding-top'] const bottomPaddingStr = window.getComputedStyle(target)['padding-bottom'] - // Remove "px" at the end of the values const topPadding = Number(topPaddingStr.substring(0, topPaddingStr.length - 2)) const bottomPadding = Number(bottomPaddingStr.substring(0, bottomPaddingStr.length - 2)) const vertPadding = topPadding + bottomPadding + const oldHeightStr = target.style.height || '' const oldHeight = Number(oldHeightStr.substring(0, oldHeightStr.length - 2)) - const tempScroll = scroller === window ? scroller.scrollY : scroller.scrollTop + /* Explanation: + * + * https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight + * scrollHeight returns element's scrollable content height, i.e. visible + * element + overscrolled parts of it. We use it to determine when text + * inside the textarea exceeded its height, so we can set height to prevent + * overscroll, i.e. make textarea grow with the text. HOWEVER, since we + * explicitly set new height, scrollHeight won't go below that, so we can't + * SHRINK the textarea when there's extra space. To workaround that we set + * height to 'auto' which makes textarea tiny again, so that scrollHeight + * will match text height again. HOWEVER, shrinking textarea can screw with + * the scroll since there might be not enough padding around root to even + * varrant a scroll, so it will jump to 0 and refuse to move anywhere, + * so we check current scroll position before shrinking and then restore it + * with needed delta. + */ + + // this part has to be BEFORE the content size update + const currentScroll = scrollerRef === window + ? scrollerRef.scrollY + : scrollerRef.scrollTop + const scrollerHeight = scrollerRef === window + ? scrollerRef.innerHeight + : scrollerRef.offsetHeight + const scrollerBottomBorder = currentScroll + scrollerHeight - // Auto is needed to make textbox shrink when removing lines + // BEGIN content size update target.style.height = 'auto' const newHeight = target.scrollHeight - vertPadding - target.style.height = `${oldHeight}px` - - if (scroller === window) { - scroller.scroll(0, tempScroll) - } else { - scroller.scrollTop = tempScroll - } - - const currentScroll = scroller === window ? scroller.scrollY : scroller.scrollTop - const scrollerHeight = scroller === window ? scroller.innerHeight : scroller.offsetHeight - const scrollerBottomBorder = currentScroll + scrollerHeight + target.style.height = `${newHeight}px` + // END content size update - const rootBottomBorder = rootRef.offsetHeight + - findOffset(rootRef, scroller).top + // We check where the bottom border of root element is, this uses findOffset + // to find offset relative to scrollable container (scroller) + const rootBottomBorder = rootRef.offsetHeight + findOffset(rootRef, scrollerRef).top const textareaSizeChangeDelta = newHeight - oldHeight || 0 - const rootChangeDelta = rootBottomBorder - scrollerBottomBorder + textareaSizeChangeDelta + const isBottomObstructed = scrollerBottomBorder < rootBottomBorder + const rootChangeDelta = rootBottomBorder - scrollerBottomBorder + const totalDelta = textareaSizeChangeDelta + + (isBottomObstructed ? rootChangeDelta : 0) + + const targetScroll = currentScroll + totalDelta - // console.log('CURRENT SCROLL', currentScroll) - console.log('BOTTOM BORDERS', rootBottomBorder, scrollerBottomBorder) - console.log('BOTTOM DELTA', rootBottomBorder - scrollerBottomBorder) - const targetScroll = scrollerBottomBorder < rootBottomBorder - ? currentScroll + rootChangeDelta - : currentScroll + textareaSizeChangeDelta - if (scroller === window) { - scroller.scroll(0, targetScroll) + if (scrollerRef === window) { + scrollerRef.scroll(0, targetScroll) } else { - scroller.scrollTop = targetScroll + scrollerRef.scrollTop = targetScroll } - target.style.height = `${newHeight}px` - console.log(scroller, rootRef) - // console.log('SCROLL TO BUTTON', scrollerBottomBorder < rootBottomBorder) - // console.log('DELTA B', rootChangeDelta) - // console.log('DELTA D', textareaSizeChangeDelta) - // console.log('TARGET', targetScroll) - // console.log('ACTUAL', scroller.scrollTop || scroller.scrollY || 0) this.$refs['emoji-input'].resize() }, showEmojiPicker () { diff --git a/src/services/offset_finder/offset_finder.service.js b/src/services/offset_finder/offset_finder.service.js index a8e438b5..9034f8c8 100644 --- a/src/services/offset_finder/offset_finder.service.js +++ b/src/services/offset_finder/offset_finder.service.js @@ -9,7 +9,6 @@ export const findOffset = (child, parent, { top = 0, left = 0 } = {}, ignorePadd result.left += ignorePadding ? 0 : leftPadding } - console.log('eee', parent, child.offsetParent) if (child.offsetParent && (parent === window || parent.contains(child.offsetParent) || parent === child.offsetParent)) { return findOffset(child.offsetParent, parent, result, false) } else { -- cgit v1.2.3-70-g09d2