Introduce Header.{scrollToIfNeeded,getTopOf,getBottomOf}() and use them.
4chan X - now with proper bottom header support.
This commit is contained in:
parent
54eaa9adea
commit
81a2b096a1
@ -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',
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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 @
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user