diff --git a/CHANGELOG.md b/CHANGELOG.md index e4ca46ecc..4ba18eaa2 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,3 @@ -### v1.7.2 -*2014-04-07* - **ccd0** - Restore thread expansion with JSON navigation disabled. diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index f5d1d9425..dfb988903 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -2485,6 +2485,11 @@ } return bottom; }, + isNodeVisible: function(node) { + var height; + height = node.getBoundingClientRect().height; + return Header.getTopOf(node) + height >= 0 && Header.getBottomOf(node) + height >= 0; + }, isHidden: function() { var top; top = Header.bar.getBoundingClientRect().top; @@ -7932,26 +7937,33 @@ title: 'Expand All Images', href: 'javascript:;' }); - $.on(this.EAI, 'click', ImageExpand.cb.toggleAll); + $.on(this.EAI, 'click', this.cb.toggleAll); Header.addShortcut(this.EAI, 3); + $.on(d, 'scroll visibilitychange', this.cb.playVideos); return Post.callbacks.push({ name: 'Image Expansion', cb: this.node }); }, node: function() { - var thumb, _ref, _ref1; - if (!(((_ref = this.file) != null ? _ref.isImage : void 0) || ((_ref1 = this.file) != null ? _ref1.isVideo : void 0))) { + var thumb; + if (!(this.file && (this.file.isImage || this.file.isVideo))) { return; } thumb = this.file.thumb; $.on(thumb.parentNode, 'click', ImageExpand.cb.toggle); - if (this.isClone && $.hasClass(thumb, 'expanding')) { - ImageExpand.contract(this); - return ImageExpand.expand(this); - } else if (this.isClone && this.file.isExpanded && this.file.isVideo) { - return ImageExpand.setupVideoControls(this); - } else if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler)) { + if (this.isClone) { + if (this.file.isImage && this.file.isExpanding) { + ImageExpand.contract(this); + ImageExpand.expand(this); + return; + } + if (this.file.isExpanded && this.file.isVideo) { + ImageExpand.setupVideoControls(this); + return; + } + } + if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler)) { return ImageExpand.expand(this); } }, @@ -7989,13 +8001,33 @@ if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) { return; } - if (ImageExpand.on && !post.isHidden && (!Conf['Expand spoilers'] && file.isSpoiler || Conf['Expand from here'] && Header.getTopOf(file.thumb) < 0)) { + if (ImageExpand.on && (post.isHidden || !Conf['Expand spoilers'] && post.file.isSpoiler || !doc.contains(post.nodes.root) || Conf['Expand from here'] && Header.getTopOf(post.file.thumb) < 0)) { return; } $.queueTask(func, post); } }); }, + playVideos: function(e) { + var fullID, play, post, _i, _len, _ref, _ref1; + _ref = g.posts; + for (fullID in _ref) { + post = _ref[fullID]; + if (!(post.file && post.file.isVideo && post.file.isExpanded)) { + continue; + } + _ref1 = [post].concat(post.clones); + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + post = _ref1[_i]; + play = !d.hidden && !post.isHidden && doc.contains(post.nodes.root) && Header.isNodeVisible(post.nodes.root); + if (play) { + post.file.fullImage.play(); + } else { + post.file.fullImage.pause(); + } + } + } + }, setFitness: function() { return (this.checked ? $.addClass : $.rmClass)(doc, this.name.toLowerCase().replace(/\s+/g, '-')); } @@ -8003,7 +8035,7 @@ toggle: function(post) { var headRect, left, root, thumb, top, x, y, _ref; thumb = post.file.thumb; - if (!(post.file.isExpanded || $.hasClass(thumb, 'expanding'))) { + if (!(post.file.isExpanded || post.file.isExpanding)) { ImageExpand.expand(post); return; } @@ -8051,6 +8083,7 @@ } $.rmClass(post.nodes.root, 'expanded-image'); $.rmClass(post.file.thumb, 'expanding'); + delete post.file.isExpanding; return post.file.isExpanded = false; }, expand: function(post, src) { @@ -8082,34 +8115,36 @@ }); }, completeExpand: function(post) { - var bottom, thumb; + var bottom, complete, thumb; thumb = post.file.thumb; if (!$.hasClass(thumb, 'expanding')) { return; } + delete post.file.isExpanding; + post.file.isExpanded = true; + complete = function() { + $.addClass(post.nodes.root, 'expanded-image'); + $.rmClass(post.file.thumb, 'expanding'); + if (post.file.isVideo) { + return ImageExpand.setupVideo(post); + } + }; if (!post.nodes.root.parentNode) { - ImageExpand.completeExpand2(post); + complete(); return; } + if (post.file.isVideo && !d.hidden && Header.isNodeVisible(post.nodes.root)) { + post.file.fullImage.play(); + } bottom = post.nodes.root.getBoundingClientRect().bottom; return $.queueTask(function() { - ImageExpand.completeExpand2(post); + complete(); if (!(bottom <= 0)) { return; } return window.scrollBy(0, post.nodes.root.getBoundingClientRect().bottom - bottom); }); }, - completeExpand2: function(post) { - var thumb; - thumb = post.file.thumb; - $.addClass(post.nodes.root, 'expanded-image'); - $.rmClass(post.file.thumb, 'expanding'); - post.file.isExpanded = true; - if (post.file.isVideo) { - return ImageExpand.setupVideo(post); - } - }, videoCB: { click: function(e) { if (this.paused && !this.controls) { @@ -8188,9 +8223,10 @@ error: function() { var URL, post, src, timeoutID; post = Get.postFromNode(this); + post.file.isReady = false; $.rm(this); delete post.file.fullImage; - if (!($.hasClass(post.file.thumb, 'expanding') || $.hasClass(post.nodes.root, 'expanded-image'))) { + if (!(post.file.isExpanding || post.file.isExpanded)) { return; } ImageExpand.contract(post); diff --git a/builds/crx/script.js b/builds/crx/script.js index d34a679b7..83ef2a85f 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -2546,6 +2546,11 @@ } return bottom; }, + isNodeVisible: function(node) { + var height; + height = node.getBoundingClientRect().height; + return Header.getTopOf(node) + height >= 0 && Header.getBottomOf(node) + height >= 0; + }, isHidden: function() { var top; top = Header.bar.getBoundingClientRect().top; @@ -7971,26 +7976,33 @@ title: 'Expand All Images', href: 'javascript:;' }); - $.on(this.EAI, 'click', ImageExpand.cb.toggleAll); + $.on(this.EAI, 'click', this.cb.toggleAll); Header.addShortcut(this.EAI, 3); + $.on(d, 'scroll visibilitychange', this.cb.playVideos); return Post.callbacks.push({ name: 'Image Expansion', cb: this.node }); }, node: function() { - var thumb, _ref, _ref1; - if (!(((_ref = this.file) != null ? _ref.isImage : void 0) || ((_ref1 = this.file) != null ? _ref1.isVideo : void 0))) { + var thumb; + if (!(this.file && (this.file.isImage || this.file.isVideo))) { return; } thumb = this.file.thumb; $.on(thumb.parentNode, 'click', ImageExpand.cb.toggle); - if (this.isClone && $.hasClass(thumb, 'expanding')) { - ImageExpand.contract(this); - return ImageExpand.expand(this); - } else if (this.isClone && this.file.isExpanded && this.file.isVideo) { - return ImageExpand.setupVideoControls(this); - } else if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler)) { + if (this.isClone) { + if (this.file.isImage && this.file.isExpanding) { + ImageExpand.contract(this); + ImageExpand.expand(this); + return; + } + if (this.file.isExpanded && this.file.isVideo) { + ImageExpand.setupVideoControls(this); + return; + } + } + if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler)) { return ImageExpand.expand(this); } }, @@ -8028,13 +8040,33 @@ if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) { return; } - if (ImageExpand.on && !post.isHidden && (!Conf['Expand spoilers'] && file.isSpoiler || Conf['Expand from here'] && Header.getTopOf(file.thumb) < 0)) { + if (ImageExpand.on && (post.isHidden || !Conf['Expand spoilers'] && post.file.isSpoiler || !doc.contains(post.nodes.root) || Conf['Expand from here'] && Header.getTopOf(post.file.thumb) < 0)) { return; } $.queueTask(func, post); } }); }, + playVideos: function(e) { + var fullID, play, post, _i, _len, _ref, _ref1; + _ref = g.posts; + for (fullID in _ref) { + post = _ref[fullID]; + if (!(post.file && post.file.isVideo && post.file.isExpanded)) { + continue; + } + _ref1 = [post].concat(post.clones); + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + post = _ref1[_i]; + play = !d.hidden && !post.isHidden && doc.contains(post.nodes.root) && Header.isNodeVisible(post.nodes.root); + if (play) { + post.file.fullImage.play(); + } else { + post.file.fullImage.pause(); + } + } + } + }, setFitness: function() { return (this.checked ? $.addClass : $.rmClass)(doc, this.name.toLowerCase().replace(/\s+/g, '-')); } @@ -8042,7 +8074,7 @@ toggle: function(post) { var headRect, left, root, thumb, top, x, y, _ref; thumb = post.file.thumb; - if (!(post.file.isExpanded || $.hasClass(thumb, 'expanding'))) { + if (!(post.file.isExpanded || post.file.isExpanding)) { ImageExpand.expand(post); return; } @@ -8090,6 +8122,7 @@ } $.rmClass(post.nodes.root, 'expanded-image'); $.rmClass(post.file.thumb, 'expanding'); + delete post.file.isExpanding; return post.file.isExpanded = false; }, expand: function(post, src) { @@ -8121,34 +8154,36 @@ }); }, completeExpand: function(post) { - var bottom, thumb; + var bottom, complete, thumb; thumb = post.file.thumb; if (!$.hasClass(thumb, 'expanding')) { return; } + delete post.file.isExpanding; + post.file.isExpanded = true; + complete = function() { + $.addClass(post.nodes.root, 'expanded-image'); + $.rmClass(post.file.thumb, 'expanding'); + if (post.file.isVideo) { + return ImageExpand.setupVideo(post); + } + }; if (!post.nodes.root.parentNode) { - ImageExpand.completeExpand2(post); + complete(); return; } + if (post.file.isVideo && !d.hidden && Header.isNodeVisible(post.nodes.root)) { + post.file.fullImage.play(); + } bottom = post.nodes.root.getBoundingClientRect().bottom; return $.queueTask(function() { - ImageExpand.completeExpand2(post); + complete(); if (!(bottom <= 0)) { return; } return window.scrollBy(0, post.nodes.root.getBoundingClientRect().bottom - bottom); }); }, - completeExpand2: function(post) { - var thumb; - thumb = post.file.thumb; - $.addClass(post.nodes.root, 'expanded-image'); - $.rmClass(post.file.thumb, 'expanding'); - post.file.isExpanded = true; - if (post.file.isVideo) { - return ImageExpand.setupVideo(post); - } - }, videoCB: { click: function(e) { if (this.paused && !this.controls) { @@ -8227,9 +8262,10 @@ error: function() { var URL, post, src, timeoutID; post = Get.postFromNode(this); + post.file.isReady = false; $.rm(this); delete post.file.fullImage; - if (!($.hasClass(post.file.thumb, 'expanding') || $.hasClass(post.nodes.root, 'expanded-image'))) { + if (!(post.file.isExpanding || post.file.isExpanded)) { return; } ImageExpand.contract(post); diff --git a/src/General/Header.coffee b/src/General/Header.coffee index 558829751..2ab23870e 100755 --- a/src/General/Header.coffee +++ b/src/General/Header.coffee @@ -421,6 +421,9 @@ Header = headRect = Header.toggle.getBoundingClientRect() bottom -= clientHeight - headRect.bottom + headRect.height bottom + isNodeVisible: (node) -> + {height} = node.getBoundingClientRect() + Header.getTopOf(node) + height >= 0 and Header.getBottomOf(node) + height >= 0 isHidden: -> {top} = Header.bar.getBoundingClientRect() if Conf['Bottom header'] diff --git a/src/Images/ImageExpand.coffee b/src/Images/ImageExpand.coffee index 975f65f8b..7d7a56c3a 100755 --- a/src/Images/ImageExpand.coffee +++ b/src/Images/ImageExpand.coffee @@ -7,25 +7,31 @@ ImageExpand = textContent: 'EAI' title: 'Expand All Images' href: 'javascript:;' - $.on @EAI, 'click', ImageExpand.cb.toggleAll + $.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?.isImage or @file?.isVideo + return unless @file and (@file.isImage or @file.isVideo) {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 @ - else if @isClone and @file.isExpanded and @file.isVideo - ImageExpand.setupVideoControls @ - else if ImageExpand.on and !@isHidden and (Conf['Expand spoilers'] or !@file.isSpoiler) + if @isClone + if @file.isImage and @file.isExpanding + # If we clone a post where the image is still loading, + # make it loading in the clone too. + ImageExpand.contract @ + ImageExpand.expand @ + return + if @file.isExpanded and @file.isVideo + ImageExpand.setupVideoControls @ + 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 @@ -49,19 +55,29 @@ ImageExpand = for post in [post].concat post.clones {file} = post return unless file and (file.isImage or file.isVideo) and doc.contains post.nodes.root - if ImageExpand.on and !post.isHidden and - (!Conf['Expand spoilers'] and file.isSpoiler or - Conf['Expand from here'] and Header.getTopOf(file.thumb) < 0) + 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) return $.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 $.hasClass thumb, 'expanding' + unless post.file.isExpanded or post.file.isExpanding ImageExpand.expand post return @@ -101,6 +117,7 @@ ImageExpand = delete post.file.videoControls $.rmClass post.nodes.root, 'expanded-image' $.rmClass post.file.thumb, 'expanding' + delete post.file.isExpanding post.file.isExpanded = false expand: (post, src) -> @@ -124,24 +141,27 @@ ImageExpand = completeExpand: (post) -> {thumb} = post.file return unless $.hasClass thumb, 'expanding' # contracted before the image loaded + delete post.file.isExpanding + post.file.isExpanded = true + + complete = -> + $.addClass post.nodes.root, 'expanded-image' + $.rmClass post.file.thumb, 'expanding' + ImageExpand.setupVideo post if post.file.isVideo + 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. - ImageExpand.completeExpand2 post + complete() return + + post.file.fullImage.play() if post.file.isVideo and !d.hidden and Header.isNodeVisible post.nodes.root {bottom} = post.nodes.root.getBoundingClientRect() $.queueTask -> - ImageExpand.completeExpand2 post + complete() return unless bottom <= 0 window.scrollBy 0, post.nodes.root.getBoundingClientRect().bottom - bottom - completeExpand2: (post) -> - {thumb} = post.file - $.addClass post.nodes.root, 'expanded-image' - $.rmClass post.file.thumb, 'expanding' - post.file.isExpanded = true - ImageExpand.setupVideo post if post.file.isVideo - videoCB: click: (e) -> if @paused and not @controls @@ -197,12 +217,13 @@ ImageExpand = error: -> post = Get.postFromNode @ + post.file.isReady = false $.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' + unless post.file.isExpanding or post.file.isExpanded # Don't try to re-expend if it was already contracted. return ImageExpand.contract post