242 lines
8.1 KiB
CoffeeScript
242 lines
8.1 KiB
CoffeeScript
ImageExpand =
|
|
init: ->
|
|
return if !Conf['Image Expansion']
|
|
|
|
@EAI = $.el 'a',
|
|
className: 'expand-all-shortcut fa fa-expand'
|
|
title: 'Expand All Images'
|
|
href: 'javascript:;'
|
|
$.on @EAI, 'click', @cb.toggleAll
|
|
Header.addShortcut @EAI, 3
|
|
$.on d, 'scroll visibilitychange', @cb.playVideos
|
|
|
|
Post.callbacks.push
|
|
name: 'Image Expansion'
|
|
cb: @node
|
|
node: ->
|
|
return unless @file and (@file.isImage or @file.isVideo)
|
|
$.on @file.thumb.parentNode, 'click', ImageExpand.cb.toggle
|
|
if @isClone
|
|
if @file.error
|
|
@file.error = $ '.warning', @file.thumb.parentNode
|
|
else if @file.isExpanding or @file.isExpanded
|
|
# Re-expand to make sure everything works/loads fine.
|
|
ImageExpand.contract @
|
|
ImageExpand.expand @
|
|
return
|
|
if ImageExpand.on and !@isHidden and (Conf['Expand spoilers'] or !@file.isSpoiler)
|
|
ImageExpand.expand @
|
|
cb:
|
|
toggle: (e) ->
|
|
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
|
|
e.preventDefault()
|
|
ImageExpand.toggle Get.postFromNode @
|
|
toggleAll: ->
|
|
$.event 'CloseMenu'
|
|
if ImageExpand.on = $.hasClass ImageExpand.EAI, 'expand-all-shortcut'
|
|
ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress'
|
|
ImageExpand.EAI.title = 'Contract All Images'
|
|
func = ImageExpand.expand
|
|
else
|
|
ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand'
|
|
ImageExpand.EAI.title = 'Expand All Images'
|
|
func = ImageExpand.contract
|
|
for ID, post of g.posts when post.file and (post.file.isImage or post.file.isVideo)
|
|
for post in [post].concat post.clones
|
|
if ImageExpand.on and (
|
|
post.isHidden or
|
|
!Conf['Expand spoilers'] and post.file.isSpoiler or
|
|
!doc.contains(post.nodes.root) or
|
|
Conf['Expand from here'] and Header.getTopOf(post.file.thumb) < 0)
|
|
continue
|
|
$.queueTask func, post
|
|
return
|
|
playVideos: (e) ->
|
|
for fullID, post of g.posts
|
|
continue unless post.file and post.file.isVideo and post.file.isExpanded
|
|
for post in [post].concat post.clones
|
|
play = !d.hidden and !post.isHidden and doc.contains(post.nodes.root) and Header.isNodeVisible post.nodes.root
|
|
if play then post.file.fullImage.play() else post.file.fullImage.pause()
|
|
return
|
|
setFitness: ->
|
|
(if @checked then $.addClass else $.rmClass) doc, @name.toLowerCase().replace /\s+/g, '-'
|
|
|
|
toggle: (post) ->
|
|
{thumb} = post.file
|
|
unless post.file.isExpanded or post.file.isExpanding
|
|
ImageExpand.expand post
|
|
return
|
|
|
|
# Scroll back to the thumbnail when contracting the image
|
|
# to avoid being left miles away from the relevant post.
|
|
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
|
|
|
|
contract: (post) ->
|
|
$.rmClass post.nodes.root, 'expanded-image'
|
|
$.rmClass post.file.thumb, 'expanding'
|
|
delete post.file.isExpanding
|
|
delete post.file.isExpanded
|
|
post.file.fullImage.pause() if post.file.isVideo and post.file.fullImage
|
|
|
|
expand: (post, src) ->
|
|
# Do not expand images of hidden/filtered replies, or already expanded pictures.
|
|
return if post.file.isExpanding or post.file.isExpanded
|
|
if post.file.fullImage
|
|
# Expand already-loaded/ing picture.
|
|
ImageExpand.waitExpand post
|
|
return
|
|
post.file.fullImage = file = if post.file.isImage
|
|
$.el 'img'
|
|
else
|
|
$.el 'video',
|
|
loop: true
|
|
file.className = 'full-image'
|
|
file.src = src or post.file.URL
|
|
$.on file, 'error', ImageExpand.error
|
|
ImageExpand.waitExpand post
|
|
if post.file.error
|
|
$.rm post.file.error
|
|
delete post.file.error
|
|
$.after post.file.thumb, file
|
|
|
|
waitExpand: (post) ->
|
|
post.file.isExpanding = true
|
|
if post.file.isReady
|
|
ImageExpand.completeExpand post
|
|
return
|
|
|
|
$.addClass post.file.thumb, 'expanding'
|
|
file = post.file.fullImage
|
|
|
|
if post.file.isImage
|
|
$.asap (-> if post.file.isExpanding then file.naturalHeight else true), ->
|
|
ImageExpand.completeExpand post
|
|
return
|
|
|
|
# Expand the video when the first frame is available.
|
|
if file.readyState >= file.HAVE_CURRENT_DATA
|
|
ImageExpand.completeExpand post
|
|
return
|
|
|
|
complete = ->
|
|
$.off file, 'loadeddata', complete
|
|
ImageExpand.completeExpand post
|
|
$.on file, 'loadeddata', complete
|
|
|
|
completeExpand: (post) ->
|
|
return unless post.file.isExpanding # contracted before the image loaded
|
|
delete post.file.isExpanding
|
|
post.file.isReady = true
|
|
post.file.isExpanded = true
|
|
if post.file.isVideo and !d.hidden and (post.isClone and !post.nodes.root.parentNode or Header.isNodeVisible post.nodes.root)
|
|
# Play the video if it's in a clone that hasn't been inserted yet,
|
|
# otherwise, check if it's in the viewport as usual.
|
|
post.file.fullImage.play()
|
|
unless post.nodes.root.parentNode
|
|
# Image might start/finish loading before the post is inserted.
|
|
# Don't scroll when it's expanded in a QP for example.
|
|
$.addClass post.nodes.root, 'expanded-image'
|
|
$.rmClass post.file.thumb, 'expanding'
|
|
return
|
|
{bottom} = post.nodes.root.getBoundingClientRect()
|
|
$.queueTask ->
|
|
$.addClass post.nodes.root, 'expanded-image'
|
|
$.rmClass post.file.thumb, 'expanding'
|
|
return unless bottom <= 0
|
|
window.scrollBy 0, post.nodes.root.getBoundingClientRect().bottom - bottom
|
|
|
|
error: ->
|
|
post = Get.postFromNode @
|
|
$.rm @
|
|
delete post.file.isReady
|
|
delete post.file.fullImage
|
|
# Images can error:
|
|
# - before the image started loading.
|
|
# - after the image started loading.
|
|
unless post.file.isExpanding or post.file.isExpanded
|
|
# Don't try to re-expand if it was already contracted.
|
|
return
|
|
ImageExpand.contract post
|
|
|
|
if @error and @error.code isnt @error.MEDIA_ERR_NETWORK # video
|
|
error = switch @error.code
|
|
when 1 then 'MEDIA_ERR_ABORTED'
|
|
when 3 then 'MEDIA_ERR_DECODE'
|
|
when 4 then 'MEDIA_ERR_SRC_NOT_SUPPORTED'
|
|
when 5 then 'MEDIA_ERR_ENCRYPTED'
|
|
post.file.error = $.el 'div',
|
|
textContent: "Playback error: #{error}"
|
|
className: 'warning'
|
|
$.after post.file.thumb, post.file.error
|
|
return
|
|
|
|
src = @src.split '/'
|
|
if src[2] is 'i.4cdn.org'
|
|
URL = Redirect.to 'file',
|
|
boardID: src[3]
|
|
filename: src[4].replace /\?.+$/, ''
|
|
if URL
|
|
setTimeout ImageExpand.expand, 10000, post, URL
|
|
return
|
|
if g.DEAD or post.isDead or post.file.isDead
|
|
return
|
|
|
|
timeoutID = setTimeout ImageExpand.expand, 10000, post
|
|
<% if (type === 'crx') { %>
|
|
$.ajax post.file.URL,
|
|
onloadend: ->
|
|
return if @status isnt 404
|
|
clearTimeout timeoutID
|
|
post.kill true
|
|
,
|
|
type: 'head'
|
|
<% } else { %>
|
|
# XXX CORS for i.4cdn.org WHEN?
|
|
$.ajax "//a.4cdn.org/#{post.board}/thread/#{post.thread}.json", onload: ->
|
|
return if @status isnt 200
|
|
for postObj in @response.posts
|
|
break if postObj.no is post.ID
|
|
if postObj.no isnt post.ID
|
|
clearTimeout timeoutID
|
|
post.kill()
|
|
else if postObj.filedeleted
|
|
clearTimeout timeoutID
|
|
post.kill true
|
|
<% } %>
|
|
|
|
menu:
|
|
init: ->
|
|
return if !Conf['Image Expansion']
|
|
|
|
el = $.el 'span',
|
|
textContent: 'Image Expansion'
|
|
className: 'image-expansion-link'
|
|
|
|
{createSubEntry} = ImageExpand.menu
|
|
subEntries = []
|
|
for name, conf of Config.imageExpansion
|
|
subEntries.push createSubEntry name, conf[1]
|
|
|
|
Header.menu.addEntry
|
|
el: el
|
|
order: 80
|
|
subEntries: subEntries
|
|
|
|
createSubEntry: (name, desc) ->
|
|
label = $.el 'label',
|
|
innerHTML: "<input type=checkbox name='#{name}'> #{name}"
|
|
title: desc
|
|
input = label.firstElementChild
|
|
if name in ['Fit width', 'Fit height']
|
|
$.on input, 'change', ImageExpand.cb.setFitness
|
|
input.checked = Conf[name]
|
|
$.event 'change', null, input
|
|
$.on input, 'change', $.cb.checked
|
|
el: label
|