diff --git a/LICENSE b/LICENSE index d88c9e07f..2c4251113 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.2.8 - 2013-05-21 +* 4chan X - Version 1.2.8 - 2013-05-23 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.js b/builds/4chan-X.js index ac9c6657b..af1c96010 100644 --- a/builds/4chan-X.js +++ b/builds/4chan-X.js @@ -19,7 +19,7 @@ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC // ==/UserScript== /* -* 4chan X - Version 1.2.8 - 2013-05-21 +* 4chan X - Version 1.2.8 - 2013-05-23 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -109,7 +109,7 @@ * */ (function() { - var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, Header, IDColor, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, + var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, __slice = [].slice, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, @@ -162,6 +162,7 @@ 'Replace GIF': [false, 'Replace thumbnail of gifs with its actual image.'], 'Replace PNG': [false, 'Replace pngs.'], 'Replace JPG': [false, 'Replace jpgs.'], + 'Image Prefetching': [false, 'Preload images'], 'Fappe Tyme': [false, 'Hide posts without images. *hint* *hint*'] }, 'Menu': { @@ -6476,24 +6477,42 @@ } }; - ImageReplace = { + ImageLoader = { init: function() { + var prefetch; + if (g.VIEW === 'catalog') { return; } - return Post.prototype.callbacks.push({ + if (!(Conf["Image Prefetching"] || Conf["Replace JPG"] || Conf["Replace PNG"] || Conf["Replace GIF"])) { + return; + } + Post.prototype.callbacks.push({ name: 'Image Replace', cb: this.node }); + if (!(Conf['Image Prefetching'] && g.VIEW === 'thread')) { + return; + } + prefetch = $.el('label', { + innerHTML: ' Prefetch Images' + }); + this.el = prefetch.firstElementChild; + $.on(this.el, 'change', this.toggle); + return $.event('AddMenuEntry', { + type: 'header', + el: prefetch, + order: 120 + }); }, node: function() { - var URL, img, style, thumb, type, _ref, _ref1; + var URL, img, string, style, thumb, type, _ref, _ref1; if (this.isClone || this.isHidden || this.thread.isHidden || !((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } _ref1 = this.file, thumb = _ref1.thumb, URL = _ref1.URL; - if (!(Conf["Replace " + ((type = (URL.match(/\w{3}$/))[0].toUpperCase()) === 'PEG' ? 'JPG' : type)] && !/spoiler/.test(thumb.src))) { + if (!((Conf[string = "Replace " + ((type = (URL.match(/\w{3}$/))[0].toUpperCase()) === 'PEG' ? 'JPG' : type)] && !/spoiler/.test(thumb.src)) || Conf['prefetch'])) { return; } if (this.file.isSpoiler) { @@ -6501,10 +6520,24 @@ style.maxHeight = style.maxWidth = this.isReply ? '125px' : '250px'; } img = $.el('img'); - $.on(img, 'load', function() { - return thumb.src = URL; - }); + if (Conf[string]) { + $.on(img, 'load', function() { + return thumb.src = URL; + }); + } return img.src = URL; + }, + toggle: function() { + var enabled, id, post, _ref; + + enabled = Conf['prefetch'] = this.checked; + if (enabled) { + _ref = g.threads["" + g.BOARD.ID + "." + g.THREADID].posts; + for (id in _ref) { + post = _ref[id]; + ImageLoader.node.call(post); + } + } } }; @@ -10190,7 +10223,7 @@ 'Image Expansion': ImageExpand, 'Image Expansion (Menu)': ImageExpand.menu, 'Reveal Spoilers': RevealSpoilers, - 'Image Replace': ImageReplace, + 'Image Loading': ImageLoader, 'Image Hover': ImageHover, 'Comment Expansion': ExpandComment, 'Thread Expansion': ExpandThread, diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 8dfb5ba54..2cb5d67f5 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -19,7 +19,7 @@ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC // ==/UserScript== /* -* 4chan X - Version 1.2.8 - 2013-05-21 +* 4chan X - Version 1.2.8 - 2013-05-23 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -109,7 +109,7 @@ * */ (function() { - var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, Header, IDColor, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, + var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, __slice = [].slice, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, @@ -162,6 +162,7 @@ 'Replace GIF': [false, 'Replace thumbnail of gifs with its actual image.'], 'Replace PNG': [false, 'Replace pngs.'], 'Replace JPG': [false, 'Replace jpgs.'], + 'Image Prefetching': [false, 'Preload images'], 'Fappe Tyme': [false, 'Hide posts without images. *hint* *hint*'] }, 'Menu': { @@ -6485,24 +6486,42 @@ } }; - ImageReplace = { + ImageLoader = { init: function() { + var prefetch; + if (g.VIEW === 'catalog') { return; } - return Post.prototype.callbacks.push({ + if (!(Conf["Image Prefetching"] || Conf["Replace JPG"] || Conf["Replace PNG"] || Conf["Replace GIF"])) { + return; + } + Post.prototype.callbacks.push({ name: 'Image Replace', cb: this.node }); + if (!(Conf['Image Prefetching'] && g.VIEW === 'thread')) { + return; + } + prefetch = $.el('label', { + innerHTML: ' Prefetch Images' + }); + this.el = prefetch.firstElementChild; + $.on(this.el, 'change', this.toggle); + return $.event('AddMenuEntry', { + type: 'header', + el: prefetch, + order: 120 + }); }, node: function() { - var URL, img, style, thumb, type, _ref, _ref1; + var URL, img, string, style, thumb, type, _ref, _ref1; if (this.isClone || this.isHidden || this.thread.isHidden || !((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } _ref1 = this.file, thumb = _ref1.thumb, URL = _ref1.URL; - if (!(Conf["Replace " + ((type = (URL.match(/\w{3}$/))[0].toUpperCase()) === 'PEG' ? 'JPG' : type)] && !/spoiler/.test(thumb.src))) { + if (!((Conf[string = "Replace " + ((type = (URL.match(/\w{3}$/))[0].toUpperCase()) === 'PEG' ? 'JPG' : type)] && !/spoiler/.test(thumb.src)) || Conf['prefetch'])) { return; } if (this.file.isSpoiler) { @@ -6510,10 +6529,24 @@ style.maxHeight = style.maxWidth = this.isReply ? '125px' : '250px'; } img = $.el('img'); - $.on(img, 'load', function() { - return thumb.src = URL; - }); + if (Conf[string]) { + $.on(img, 'load', function() { + return thumb.src = URL; + }); + } return img.src = URL; + }, + toggle: function() { + var enabled, id, post, _ref; + + enabled = Conf['prefetch'] = this.checked; + if (enabled) { + _ref = g.threads["" + g.BOARD.ID + "." + g.THREADID].posts; + for (id in _ref) { + post = _ref[id]; + ImageLoader.node.call(post); + } + } } }; @@ -10201,7 +10234,7 @@ 'Image Expansion': ImageExpand, 'Image Expansion (Menu)': ImageExpand.menu, 'Reveal Spoilers': RevealSpoilers, - 'Image Replace': ImageReplace, + 'Image Loading': ImageLoader, 'Image Hover': ImageHover, 'Comment Expansion': ExpandComment, 'Thread Expansion': ExpandThread, diff --git a/builds/crx/script.js b/builds/crx/script.js index 72657e197..43f52827f 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.2.8 - 2013-05-21 +* 4chan X - Version 1.2.8 - 2013-05-23 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -90,7 +90,7 @@ * */ (function() { - var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, Header, IDColor, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, + var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, __slice = [].slice, __hasProp = {}.hasOwnProperty, @@ -143,6 +143,7 @@ 'Replace GIF': [false, 'Replace thumbnail of gifs with its actual image.'], 'Replace PNG': [false, 'Replace pngs.'], 'Replace JPG': [false, 'Replace jpgs.'], + 'Image Prefetching': [false, 'Preload images'], 'Fappe Tyme': [false, 'Hide posts without images. *hint* *hint*'] }, 'Menu': { @@ -6463,24 +6464,42 @@ } }; - ImageReplace = { + ImageLoader = { init: function() { + var prefetch; + if (g.VIEW === 'catalog') { return; } - return Post.prototype.callbacks.push({ + if (!(Conf["Image Prefetching"] || Conf["Replace JPG"] || Conf["Replace PNG"] || Conf["Replace GIF"])) { + return; + } + Post.prototype.callbacks.push({ name: 'Image Replace', cb: this.node }); + if (!(Conf['Image Prefetching'] && g.VIEW === 'thread')) { + return; + } + prefetch = $.el('label', { + innerHTML: ' Prefetch Images' + }); + this.el = prefetch.firstElementChild; + $.on(this.el, 'change', this.toggle); + return $.event('AddMenuEntry', { + type: 'header', + el: prefetch, + order: 120 + }); }, node: function() { - var URL, img, style, thumb, type, _ref, _ref1; + var URL, img, string, style, thumb, type, _ref, _ref1; if (this.isClone || this.isHidden || this.thread.isHidden || !((_ref = this.file) != null ? _ref.isImage : void 0)) { return; } _ref1 = this.file, thumb = _ref1.thumb, URL = _ref1.URL; - if (!(Conf["Replace " + ((type = (URL.match(/\w{3}$/))[0].toUpperCase()) === 'PEG' ? 'JPG' : type)] && !/spoiler/.test(thumb.src))) { + if (!((Conf[string = "Replace " + ((type = (URL.match(/\w{3}$/))[0].toUpperCase()) === 'PEG' ? 'JPG' : type)] && !/spoiler/.test(thumb.src)) || Conf['prefetch'])) { return; } if (this.file.isSpoiler) { @@ -6488,10 +6507,24 @@ style.maxHeight = style.maxWidth = this.isReply ? '125px' : '250px'; } img = $.el('img'); - $.on(img, 'load', function() { - return thumb.src = URL; - }); + if (Conf[string]) { + $.on(img, 'load', function() { + return thumb.src = URL; + }); + } return img.src = URL; + }, + toggle: function() { + var enabled, id, post, _ref; + + enabled = Conf['prefetch'] = this.checked; + if (enabled) { + _ref = g.threads["" + g.BOARD.ID + "." + g.THREADID].posts; + for (id in _ref) { + post = _ref[id]; + ImageLoader.node.call(post); + } + } } }; @@ -10182,7 +10215,7 @@ 'Image Expansion': ImageExpand, 'Image Expansion (Menu)': ImageExpand.menu, 'Reveal Spoilers': RevealSpoilers, - 'Image Replace': ImageReplace, + 'Image Loading': ImageLoader, 'Image Hover': ImageHover, 'Comment Expansion': ExpandComment, 'Thread Expansion': ExpandThread, diff --git a/src/General/Config.coffee b/src/General/Config.coffee index 8067d29f9..173038f73 100644 --- a/src/General/Config.coffee +++ b/src/General/Config.coffee @@ -155,6 +155,10 @@ Config = false 'Replace jpgs.' ] + 'Image Prefetching': [ + false + 'Preload images' + ] 'Fappe Tyme': [ false 'Hide posts without images. *hint* *hint*' diff --git a/src/General/Main.coffee b/src/General/Main.coffee index 3776a0add..8c66f027d 100644 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -113,7 +113,7 @@ Main = 'Image Expansion': ImageExpand 'Image Expansion (Menu)': ImageExpand.menu 'Reveal Spoilers': RevealSpoilers - 'Image Replace': ImageReplace + 'Image Loading': ImageLoader 'Image Hover': ImageHover 'Comment Expansion': ExpandComment 'Thread Expansion': ExpandThread diff --git a/src/Images/ImageLoader.coffee b/src/Images/ImageLoader.coffee new file mode 100644 index 000000000..4146116b5 --- /dev/null +++ b/src/Images/ImageLoader.coffee @@ -0,0 +1,42 @@ +ImageLoader = + init: -> + return if g.VIEW is 'catalog' + return unless Conf["Image Prefetching"] or Conf["Replace JPG"] or Conf["Replace PNG"] or Conf["Replace GIF"] + + Post::callbacks.push + name: 'Image Replace' + cb: @node + + return unless Conf['Image Prefetching'] and g.VIEW is 'thread' + + prefetch = $.el 'label', + innerHTML: ' Prefetch Images' + + @el = prefetch.firstElementChild + $.on @el, 'change', @toggle + + $.event 'AddMenuEntry', + type: 'header' + el: prefetch + order: 120 + + node: -> + return if @isClone or @isHidden or @thread.isHidden or !@file?.isImage + {thumb, URL} = @file + return unless (Conf[string = "Replace #{if (type = (URL.match /\w{3}$/)[0].toUpperCase()) is 'PEG' then 'JPG' else type}"] and !/spoiler/.test thumb.src) or Conf['prefetch'] + if @file.isSpoiler + # Revealed spoilers do not have height/width set, this fixes the image's dimensions. + {style} = thumb + style.maxHeight = style.maxWidth = if @isReply then '125px' else '250px' + img = $.el 'img' + if Conf[string] + $.on img, 'load', -> + # Replace the thumbnail once the GIF has finished loading. + thumb.src = URL + img.src = URL + + toggle: -> + enabled = Conf['prefetch'] = @checked + if enabled + ImageLoader.node.call post for id, post of g.threads["#{g.BOARD.ID}.#{g.THREADID}"].posts + return \ No newline at end of file diff --git a/src/Images/ImageReplace.coffee b/src/Images/ImageReplace.coffee deleted file mode 100644 index ffd53b88e..000000000 --- a/src/Images/ImageReplace.coffee +++ /dev/null @@ -1,21 +0,0 @@ -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