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