From 628898fd741c871007507bc241443c243d15ac80 Mon Sep 17 00:00:00 2001 From: Jordan Bates Date: Fri, 26 Apr 2013 14:23:00 -0700 Subject: [PATCH] Imaging -> Images --- src/Images/FappeTyme.coffee | 27 +++++ src/Images/ImageExpand.coffee | 195 +++++++++++++++++++++++++++++++ src/Images/ImageHover.coffee | 48 ++++++++ src/Images/ImageReplace.coffee | 21 ++++ src/Images/RevealSpoilers.coffee | 12 ++ 5 files changed, 303 insertions(+) create mode 100644 src/Images/FappeTyme.coffee create mode 100644 src/Images/ImageExpand.coffee create mode 100644 src/Images/ImageHover.coffee create mode 100644 src/Images/ImageReplace.coffee create mode 100644 src/Images/RevealSpoilers.coffee diff --git a/src/Images/FappeTyme.coffee b/src/Images/FappeTyme.coffee new file mode 100644 index 000000000..20f51caee --- /dev/null +++ b/src/Images/FappeTyme.coffee @@ -0,0 +1,27 @@ +FappeTyme = + init: -> + return if !Conf['Fappe Tyme'] or g.VIEW is 'catalog' or g.BOARD is 'f' + el = $.el 'label', + innerHTML: " Fappe Tyme" + title: 'Fappe Tyme' + + FappeTyme.input = input = el.firstElementChild + + $.on input, 'change', FappeTyme.toggle + + $.event 'AddMenuEntry', + type: 'header' + el: el + order: 97 + + Post::callbacks.push + name: 'Fappe Tyme' + cb: @node + + node: -> + return if @file + $.addClass @nodes.root, "noFile" + + toggle: -> + $.event 'CloseMenu' + (if @checked then $.addClass else $.rmClass) doc, 'fappeTyme' \ No newline at end of file diff --git a/src/Images/ImageExpand.coffee b/src/Images/ImageExpand.coffee new file mode 100644 index 000000000..87eb99755 --- /dev/null +++ b/src/Images/ImageExpand.coffee @@ -0,0 +1,195 @@ +ImageExpand = + init: -> + return if g.VIEW is 'catalog' or !Conf['Image Expansion'] + + @EAI = $.el 'a', + className: 'expand-all-shortcut' + textContent: 'EAI' + title: 'Expand All Images' + href: 'javascript:;' + $.on @EAI, 'click', ImageExpand.cb.toggleAll + Header.addShortcut @EAI + + Post::callbacks.push + name: 'Image Expansion' + cb: @node + node: -> + return unless @file?.isImage + {thumb} = @file + $.on thumb.parentNode, 'click', ImageExpand.cb.toggle + if @isClone and $.hasClass thumb, 'expanding' + # If we clone a post where the image is still loading, + # make it loading in the clone too. + ImageExpand.contract @ + ImageExpand.expand @ + return + if ImageExpand.on and !@isHidden + 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' + ImageExpand.EAI.title = 'Contract All Images' + func = ImageExpand.expand + else + ImageExpand.EAI.className = 'expand-all-shortcut' + ImageExpand.EAI.title = 'Expand All Images' + func = ImageExpand.contract + for ID, post of g.posts + for post in [post].concat post.clones + {file} = post + 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) + continue + $.queueTask func, post + return + setFitness: -> + {checked} = @ + (if checked then $.addClass else $.rmClass) doc, @name.toLowerCase().replace /\s+/g, '-' + return unless @name is 'Fit height' + if checked + $.on window, 'resize', ImageExpand.resize + unless ImageExpand.style + ImageExpand.style = $.addStyle null + ImageExpand.resize() + else + $.off window, 'resize', ImageExpand.resize + + toggle: (post) -> + {thumb} = post.file + unless post.file.isExpanded or $.hasClass thumb, 'expanding' + ImageExpand.expand post + return + ImageExpand.contract post + rect = post.nodes.root.getBoundingClientRect() + return unless rect.top <= 0 or rect.left <= 0 + + {top} = rect + if Conf['Fixed Header'] and not Conf['Bottom Header'] + headRect = Header.bar.getBoundingClientRect() + top += - headRect.top - headRect.height + + root = <% if (type === 'crx') { %>d.body<% } else { %>doc<% } %> + + root.scrollTop += top if rect.top < 0 + root.scrollLeft = 0 if rect.left < 0 + + contract: (post) -> + $.rmClass post.nodes.root, 'expanded-image' + $.rmClass post.file.thumb, 'expanding' + post.file.isExpanded = false + + expand: (post, src) -> + # Do not expand images of hidden/filtered replies, or already expanded pictures. + {thumb} = post.file + return if post.isHidden or post.file.isExpanded or $.hasClass thumb, 'expanding' + $.addClass thumb, 'expanding' + if post.file.fullImage + # Expand already-loaded/ing picture. + $.asap (-> post.file.fullImage.naturalHeight), -> + ImageExpand.completeExpand post + return + post.file.fullImage = img = $.el 'img', + className: 'full-image' + src: src or post.file.URL + $.on img, 'error', ImageExpand.error + $.asap (-> post.file.fullImage.naturalHeight), -> + ImageExpand.completeExpand post + $.after thumb, img + + completeExpand: (post) -> + {thumb} = post.file + return unless $.hasClass thumb, 'expanding' # contracted before the image loaded + post.file.isExpanded = true + 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 + prev = post.nodes.root.getBoundingClientRect() + $.queueTask -> + $.addClass post.nodes.root, 'expanded-image' + $.rmClass post.file.thumb, 'expanding' + return unless prev.top + prev.height <= 0 + root = <% if (type === 'crx') { %>d.body<% } else { %>doc<% } %> + curr = post.nodes.root.getBoundingClientRect() + root.scrollTop += curr.height - prev.height + curr.top - prev.top + + error: -> + post = Get.postFromNode @ + $.rm @ + delete post.file.fullImage + # Images can error: + # - before the image started loading. + # - after the image started loading. + unless $.hasClass(post.file.thumb, 'expanding') or $.hasClass post.nodes.root, 'expanded-image' + # Don't try to re-expend if it was already contracted. + return + ImageExpand.contract post + + src = @src.split '/' + if src[2] is 'images.4chan.org' + if URL = Redirect.image src[3], src[5] + setTimeout ImageExpand.expand, 10000, post, URL + return + if g.DEAD or post.isDead or post.file.isDead + return + + timeoutID = setTimeout ImageExpand.expand, 10000, post + # XXX CORS for images.4chan.org WHEN? + $.ajax "//api.4chan.org/#{post.board}/res/#{post.thread}.json", onload: -> + return if @status isnt 200 + for postObj in JSON.parse(@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 g.VIEW is 'catalog' or !Conf['Image Expansion'] + + el = $.el 'span', + textContent: 'Image Expansion' + className: 'image-expansion-link' + + {createSubEntry} = ImageExpand.menu + subEntries = [] + for key, conf of Config.imageExpansion + subEntries.push createSubEntry key, conf + + $.event 'AddMenuEntry', + type: 'header' + el: el + order: 105 + subEntries: subEntries + + createSubEntry: (type, config) -> + label = $.el 'label', + innerHTML: " #{type}" + input = label.firstElementChild + if type in ['Fit width', 'Fit height'] + $.on input, 'change', ImageExpand.cb.setFitness + if config + label.title = config[1] + input.checked = Conf[type] + $.event 'change', null, input + $.on input, 'change', $.cb.checked + el: label + + resize: -> + ImageExpand.style.textContent = ":root.fit-height .full-image {max-height:#{doc.clientHeight}px}" + + menuToggle: (e) -> + ImageExpand.opmenu.toggle e, @, g \ No newline at end of file diff --git a/src/Images/ImageHover.coffee b/src/Images/ImageHover.coffee new file mode 100644 index 000000000..639f37e0a --- /dev/null +++ b/src/Images/ImageHover.coffee @@ -0,0 +1,48 @@ +ImageHover = + init: -> + return if g.VIEW is 'catalog' or !Conf['Image Hover'] + + Post::callbacks.push + name: 'Image Hover' + cb: @node + node: -> + return unless @file?.isImage + $.on @file.thumb, 'mouseover', ImageHover.mouseover + mouseover: (e) -> + post = Get.postFromNode @ + el = $.el 'img', + id: 'ihover' + src: post.file.URL + el.setAttribute 'data-fullid', post.fullID + $.add Header.hover, el + UI.hover + root: @ + el: el + latestEvent: e + endEvents: 'mouseout click' + asapTest: -> el.naturalHeight + $.on el, 'error', ImageHover.error + error: -> + return unless doc.contains @ + post = g.posts[@dataset.fullid] + + src = @src.split '/' + if src[2] is 'images.4chan.org' + if URL = Redirect.image src[3], src[5].replace /\?.+$/, '' + @src = URL + return + if g.DEAD or post.isDead or post.file.isDead + return + + timeoutID = setTimeout (=> @src = post.file.URL + '?' + Date.now()), 3000 + # XXX CORS for images.4chan.org WHEN? + $.ajax "//api.4chan.org/#{post.board}/res/#{post.thread}.json", onload: -> + return if @status isnt 200 + for postObj in JSON.parse(@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 \ No newline at end of file diff --git a/src/Images/ImageReplace.coffee b/src/Images/ImageReplace.coffee new file mode 100644 index 000000000..ffd53b88e --- /dev/null +++ b/src/Images/ImageReplace.coffee @@ -0,0 +1,21 @@ +ImageReplace = + init: -> + return if g.VIEW is 'catalog' + + Post::callbacks.push + name: 'Image Replace' + cb: @node + + node: -> + return if @isClone or @isHidden or @thread.isHidden or !@file?.isImage + {thumb, URL} = @file + return unless Conf["Replace #{if (type = (URL.match /\w{3}$/)[0].toUpperCase()) is 'PEG' then 'JPG' else type}"] and !/spoiler/.test thumb.src + if @file.isSpoiler + # Revealed spoilers do not have height/width set, this fixes auto-gifs dimensions. + {style} = thumb + style.maxHeight = style.maxWidth = if @isReply then '125px' else '250px' + img = $.el 'img' + $.on img, 'load', -> + # Replace the thumbnail once the GIF has finished loading. + thumb.src = URL + img.src = URL \ No newline at end of file diff --git a/src/Images/RevealSpoilers.coffee b/src/Images/RevealSpoilers.coffee new file mode 100644 index 000000000..99d4fbd21 --- /dev/null +++ b/src/Images/RevealSpoilers.coffee @@ -0,0 +1,12 @@ +RevealSpoilers = + init: -> + return if g.VIEW is 'catalog' or !Conf['Reveal Spoilers'] + + Post::callbacks.push + name: 'Reveal Spoilers' + cb: @node + node: -> + return if @isClone or !@file?.isSpoiler + {thumb} = @file + thumb.removeAttribute 'style' + thumb.src = @file.thumbURL \ No newline at end of file