diff --git a/src/General/Header.coffee b/src/General/Header.coffee index f76da0383..10359d471 100644 --- a/src/General/Header.coffee +++ b/src/General/Header.coffee @@ -247,12 +247,28 @@ Header = return unless /^p\d+$/.test(hash) and post = $.id hash return if (Get.postFromRoot post).isHidden Header.scrollTo post - scrollTo: (root) -> + scrollTo: (root, down, needed) -> + if down + x = Header.getBottomOf root + window.scrollBy 0, -x unless needed and x >= 0 + else + x = Header.getTopOf root + window.scrollBy 0, x unless needed and x >= 0 + scrollToIfNeeded: (root, down) -> + Header.scrollTo root, down, true + getTopOf: (root) -> {top} = root.getBoundingClientRect() unless Conf['Bottom header'] headRect = Header.toggle.getBoundingClientRect() - top -= headRect.top + headRect.height - window.scrollBy 0, top + top -= headRect.top + headRect.height + top + getBottomOf: (root) -> + {clientHeight} = doc + bottom = clientHeight - root.getBoundingClientRect().bottom + if Conf['Bottom header'] + headRect = Header.toggle.getBoundingClientRect() + bottom -= clientHeight - headRect.bottom + headRect.height + bottom addShortcut: (el, index) -> shortcut = $.el 'span', diff --git a/src/General/Index.coffee b/src/General/Index.coffee index 336e2c3f9..c9a8b5134 100644 --- a/src/General/Index.coffee +++ b/src/General/Index.coffee @@ -50,7 +50,7 @@ Index = className: 'pagelist' hidden: true innerHTML: <%= importHTML('General/Index-pagelist') %> - Index.currentPage = Index.getCurrentPage() + @currentPage = @getCurrentPage() $.on window, 'popstate', @cb.popstate $.on @pagelist, 'click', @cb.pageNav $.asap (-> $('.pagelist', doc) or d.readyState isnt 'loading'), -> @@ -81,7 +81,7 @@ Index = Index.pageNav +a.pathname.split('/')[2] scrollToIndex: -> - Header.scrollTo Index.root if Index.root.getBoundingClientRect().top < 0 + Header.scrollToIfNeeded Index.root getCurrentPage: -> +window.location.pathname.split('/')[2] diff --git a/src/Images/ImageExpand.coffee b/src/Images/ImageExpand.coffee index c21bef490..60382bb73 100644 --- a/src/Images/ImageExpand.coffee +++ b/src/Images/ImageExpand.coffee @@ -45,7 +45,7 @@ ImageExpand = continue unless file and file.isImage and doc.contains post.nodes.root if ImageExpand.on and (!Conf['Expand spoilers'] and file.isSpoiler or - Conf['Expand from here'] and file.thumb.getBoundingClientRect().top < 0) + Conf['Expand from here'] and Header.getTopOf(file.thumb) < 0) continue $.queueTask func, post return @@ -60,13 +60,10 @@ ImageExpand = # Scroll back to the thumbnail when contracting the image # to avoid being left miles away from the relevant post. - rect = post.nodes.root.getBoundingClientRect() - if rect.top < 0 - y = rect.top - unless Conf['Bottom header'] - headRect = Header.toggle.getBoundingClientRect() - y -= headRect.top + headRect.height - if rect.left < 0 + top = Header.getTopOf post.nodes.root + if top < 0 + y = top + if post.nodes.root.getBoundingClientRect().left < 0 x = -window.scrollX window.scrollBy x, y if x or y ImageExpand.contract post @@ -104,13 +101,12 @@ ImageExpand = $.addClass post.nodes.root, 'expanded-image' $.rmClass post.file.thumb, 'expanding' return - prev = post.nodes.root.getBoundingClientRect() + {bottom} = post.nodes.root.getBoundingClientRect() $.queueTask -> $.addClass post.nodes.root, 'expanded-image' $.rmClass post.file.thumb, 'expanding' - return unless prev.top + prev.height <= 0 - curr = post.nodes.root.getBoundingClientRect() - window.scrollBy 0, curr.height - prev.height + curr.top - prev.top + return unless bottom <= 0 + window.scrollBy 0, post.nodes.root.getBoundingClientRect().bottom - bottom error: -> post = Get.postFromNode @ diff --git a/src/Miscellaneous/Keybinds.coffee b/src/Miscellaneous/Keybinds.coffee index d59d771e7..00ee147cd 100644 --- a/src/Miscellaneous/Keybinds.coffee +++ b/src/Miscellaneous/Keybinds.coffee @@ -183,43 +183,31 @@ Keybinds = location.href = url hl: (delta, thread) -> + postEl = $ '.reply.highlight', thread + unless delta - if postEl = $ '.reply.highlight', thread - $.rmClass postEl, 'highlight' + $.rmClass postEl, 'highlight' if postEl return - if Conf['Bottom header'] - topMargin = 0 - else - headRect = Header.toggle.getBoundingClientRect() - topMargin = headRect.top + headRect.height - if postEl = $ '.reply.highlight', thread - $.rmClass postEl, 'highlight' - rect = postEl.getBoundingClientRect() - if rect.bottom >= topMargin and rect.top <= doc.clientHeight # We're at least partially visible + + if postEl + {height} = postEl.getBoundingClientRect() + if Header.getTopOf(postEl) >= -height and Header.getBottomOf(postEl) >= -height # We're at least partially visible root = postEl.parentNode axe = if delta is +1 'following' else 'preceding' - next = $.x "#{axe}-sibling::div[contains(@class,'replyContainer')][1]/child::div[contains(@class,'reply')]", root - unless next - @focus postEl - return - return unless g.VIEW is 'thread' or $.x('ancestor::div[parent::div[@class="board"]]', next) is thread - rect = next.getBoundingClientRect() - if rect.top < 0 or rect.bottom > doc.clientHeight - if delta is -1 - window.scrollBy 0, rect.top - topMargin - else - next.scrollIntoView false + return unless next = $.x "#{axe}-sibling::div[contains(@class,'replyContainer')][1]/child::div[contains(@class,'reply')]", root + Header.scrollToIfNeeded next, delta is +1 @focus next + $.rmClass postEl, 'highlight' return + $.rmClass postEl, 'highlight' replies = $$ '.reply', thread replies.reverse() if delta is -1 for reply in replies - rect = reply.getBoundingClientRect() - if delta is +1 and rect.top >= topMargin or delta is -1 and rect.bottom <= doc.clientHeight + if delta is +1 and Header.getTopOf(reply) > 0 or delta is -1 and Header.getBottomOf(reply) > 0 @focus reply return diff --git a/src/Miscellaneous/Nav.coffee b/src/Miscellaneous/Nav.coffee index 2b7e23354..3620080f0 100644 --- a/src/Miscellaneous/Nav.coffee +++ b/src/Miscellaneous/Nav.coffee @@ -38,29 +38,24 @@ Nav = else Nav.scroll +1 - getThread: (full) -> - if Conf['Bottom header'] - topMargin = 0 - else - headRect = Header.toggle.getBoundingClientRect() - topMargin = headRect.top + headRect.height - threads = $$('.thread').filter (thread) -> - thread = Get.threadFromRoot thread - !(thread.isHidden and !thread.stub) - for thread, i in threads - rect = thread.getBoundingClientRect() - if rect.bottom > topMargin # not scrolled past - return if full then [threads, thread, i, rect, topMargin] else thread + getThread: -> + for threadRoot in $$ '.thread' + thread = Get.threadFromRoot threadRoot + continue if thread.isHidden and !thread.stub + if Header.getTopOf(threadRoot) >= -threadRoot.getBoundingClientRect().height # not scrolled past + return threadRoot return $ '.board' scroll: (delta) -> - [threads, thread, i, rect, topMargin] = Nav.getThread true - top = rect.top - topMargin - - # unless we're not at the beginning of the current thread - # (and thus wanting to move to beginning) - # or we're above the first thread and don't want to skip it - if (delta is -1 and top > -5) or (delta is +1 and top < 5) - top = threads[i + delta]?.getBoundingClientRect().top - topMargin - - window.scrollBy 0, top + thread = Nav.getThread() + axe = if delta is +1 + 'following' + else + 'preceding' + if next = $.x "#{axe}-sibling::div[contains(@class,'thread')][1]", thread + # Unless we're not at the beginning of the current thread, + # and thus wanting to move to beginning, + # or we're above the first thread and don't want to skip it. + top = Header.getTopOf thread + thread = next if delta is +1 and top < 5 or delta is -1 and top > -5 + Header.scrollTo thread diff --git a/src/Monitoring/ThreadUpdater.coffee b/src/Monitoring/ThreadUpdater.coffee index b35f9502e..0ef1d04bf 100644 --- a/src/Monitoring/ThreadUpdater.coffee +++ b/src/Monitoring/ThreadUpdater.coffee @@ -246,8 +246,7 @@ ThreadUpdater = ThreadUpdater.lastPost = posts[count - 1].ID Main.callbackNodes Post, posts - scroll = Conf['Auto Scroll'] and ThreadUpdater.scrollBG() and - ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25 + scroll = Conf['Auto Scroll'] and ThreadUpdater.scrollBG() and Header.getBottomOf(ThreadUpdater.root) > -25 $.add ThreadUpdater.root, nodes sendEvent() if scroll diff --git a/src/Monitoring/Unread.coffee b/src/Monitoring/Unread.coffee index 2898c6c69..9ca6ce402 100644 --- a/src/Monitoring/Unread.coffee +++ b/src/Monitoring/Unread.coffee @@ -42,18 +42,16 @@ Unread = while root = $.x 'preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root break unless (post = Get.postFromRoot root).isHidden return unless root - onload = -> root.scrollIntoView false if checkPosition root + down = true else # Scroll to the last read post. posts = Object.keys Unread.thread.posts {root} = Unread.thread.posts[posts[posts.length - 1]].nodes - onload = -> Header.scrollTo root if checkPosition root - checkPosition = (target) -> - # Scroll to the target unless we scrolled past it. - target.getBoundingClientRect().bottom > doc.clientHeight # Prevent the browser to scroll back to # the previous scroll location on page load. - $.on window, 'load', onload + $.on window, 'load', -> + # Scroll to the target unless we scrolled past it. + Header.scrollTo root, down if Header.getBottomOf(root) < 0 sync: -> lastReadPost = Unread.db.get @@ -102,7 +100,7 @@ Unread = body: post.info.comment icon: Favicon.logo notif.onclick = -> - Header.scrollTo post.nodes.root + Header.scrollToIfNeeded post.nodes.root, true window.focus() notif.onshow = -> setTimeout -> @@ -132,9 +130,8 @@ Unread = read: (e) -> return if d.hidden or !Unread.posts.length - height = doc.clientHeight for post, i in Unread.posts - break if post.nodes.root.getBoundingClientRect().bottom > height # post is not completely read + break if Header.getBottomOf(post.nodes.root) <= 0 # post is not completely read return unless i Unread.lastReadPost = Unread.posts.splice(0, i)[i - 1].ID