diff --git a/builds/appchan-x.user.js b/builds/appchan-x.user.js
index def698c86..b6948bbeb 100644
--- a/builds/appchan-x.user.js
+++ b/builds/appchan-x.user.js
@@ -11388,7 +11388,10 @@
ImageLoader = {
init: function() {
- var prefetch;
+ var prefetch, _ref;
+ if ((_ref = g.VIEW) !== 'index' && _ref !== 'thread') {
+ return;
+ }
if (!(Conf["Image Prefetching"] || Conf["Replace JPG"] || Conf["Replace PNG"] || Conf["Replace GIF"] || Conf["Replace WEBM"])) {
return;
}
@@ -11396,12 +11399,17 @@
name: 'Image Replace',
cb: this.node
});
- Thread.callbacks.push({
- name: 'Image Replace',
- cb: this.thread
+ $.on(d, 'PostsInserted', function() {
+ return g.posts.forEach(ImageLoader.prefetch);
});
+ if (Conf['Replace WEBM']) {
+ this.processVideo();
+ }
+ if (!Conf['Image Prefetching']) {
+ return;
+ }
prefetch = $.el('label', {
- innerHTML: ' Prefetch Images'
+ innerHTML: " Prefetch Images"
});
this.el = prefetch.firstElementChild;
$.on(this.el, 'change', this.toggle);
@@ -11410,65 +11418,98 @@
order: 104
});
},
- thread: function() {
- return ImageLoader.thread = this;
- },
node: function() {
- var URL, cb, file, isImage, isVideo, match, replace, style, thumb, type, _ref, _ref1;
- if (!this.file) {
+ if (this.isClone || !this.file) {
return;
}
- _ref = this.file, isImage = _ref.isImage, isVideo = _ref.isVideo;
- if (this.isClone || this.isHidden || this.thread.isHidden || !(isImage || isVideo)) {
+ if (Conf['Replace WEBM'] && this.file.isVideo) {
+ ImageLoader.replaceVideo(this);
+ }
+ return ImageLoader.prefetch(this);
+ },
+ replaceVideo: function(post) {
+ var attr, file, thumb, video, _i, _len, _ref;
+ file = post.file;
+ thumb = file.thumb;
+ video = $.el('video', {
+ preload: 'none',
+ loop: true,
+ poster: thumb.src,
+ textContent: thumb.alt,
+ className: thumb.className
+ });
+ video.dataset.md5 = thumb.dataset.md5;
+ _ref = ['height', 'width', 'maxHeight', 'maxWidth'];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ attr = _ref[_i];
+ video.style[attr] = thumb.style[attr];
+ }
+ video.src = file.URL;
+ $.replace(thumb, video);
+ file.thumb = video;
+ return file.videoThumb = true;
+ },
+ prefetch: function(post) {
+ var URL, clone, el, file, isImage, isVideo, item, match, pass, replace, thumb, type, _i, _j, _len, _len1, _ref, _ref1;
+ file = post.file;
+ if (!file) {
+ return;
+ }
+ isImage = file.isImage, isVideo = file.isVideo, thumb = file.thumb, URL = file.URL;
+ if (file.isPrefetched || !(isImage || isVideo) || post.isHidden || post.thread.isHidden) {
return;
}
- _ref1 = this.file, thumb = _ref1.thumb, URL = _ref1.URL;
- style = thumb.style;
type = (match = URL.match(/\.([^.]+)$/)[1].toUpperCase()) === 'JPEG' ? 'JPG' : match;
- replace = "Replace " + type;
- if (!((Conf[replace] && !/spoiler/.test(thumb.src)) || (Conf['prefetch'] && g.VIEW === 'thread'))) {
+ replace = Conf["Replace " + type] && !/spoiler/.test(thumb.src);
+ if (!(replace || Conf['prefetch'])) {
return;
}
- if (this.file.isSpoiler) {
- style.maxHeight = style.maxWidth = this.isReply ? '125px' : '250px';
- }
- file = $.el(isImage ? 'img' : 'video');
- if (Conf[replace]) {
- if (isVideo) {
- file.alt = thumb.alt;
- file.dataset.md5 = thumb.dataset.md5;
- file.style.height = style.height;
- file.style.width = style.width;
- file.style.maxHeight = style.maxHeight;
- file.style.maxWidth = style.maxWidth;
- file.loop = true;
- file.autoplay = Conf['Autoplay'];
- if (Conf['Image Hover']) {
- $.on(file, 'mouseover', ImageHover.mouseover);
- }
+ pass = false;
+ _ref = [post].concat(__slice.call(post.clones));
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ item = _ref[_i];
+ if (doc.contains(item.nodes.root)) {
+ pass = true;
+ break;
}
- cb = (function(_this) {
- return function() {
- $.off(file, 'load loadedmetadata', cb);
- if (isVideo) {
- $.replace(thumb, file);
- _this.file.thumb = file;
- return;
- }
- return thumb.src = URL;
- };
- })(this);
- $.on(file, 'load loadedmetadata', cb);
}
- return file.src = URL;
+ if (!pass) {
+ return;
+ }
+ file.isPrefetched = true;
+ if (file.videoThumb) {
+ _ref1 = post.clones;
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ clone = _ref1[_j];
+ clone.file.thumb.preload = 'auto';
+ }
+ thumb.preload = 'auto';
+ if (typeof chrome === "undefined" || chrome === null) {
+ $.on(thumb, 'loadeddata', function() {
+ return this.removeAttribute('poster');
+ });
+ }
+ return;
+ }
+ el = $.el(isImage ? 'img' : 'video');
+ if (replace && isImage) {
+ $.on(el, 'load', function() {
+ var _k, _len2, _ref2, _results;
+ _ref2 = post.clones;
+ _results = [];
+ for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
+ clone = _ref2[_k];
+ _results.push(clone.file.thumb.src = URL);
+ }
+ return _results;
+ });
+ thumb.src = URL;
+ }
+ return el.src = URL;
},
toggle: function() {
- var enabled;
- enabled = Conf['prefetch'] = this.checked;
- if (enabled) {
- g.BOARD.posts.forEach(function(post) {
- return ImageLoader.node.call(post);
- });
+ if (Conf['prefetch'] = this.checked) {
+ g.BOARD.posts.forEach(ImageLoader.prefetch);
}
}
};
diff --git a/builds/crx/script.js b/builds/crx/script.js
index 84049e87f..46eff96e9 100644
--- a/builds/crx/script.js
+++ b/builds/crx/script.js
@@ -11410,7 +11410,10 @@
ImageLoader = {
init: function() {
- var prefetch;
+ var prefetch, _ref;
+ if ((_ref = g.VIEW) !== 'index' && _ref !== 'thread') {
+ return;
+ }
if (!(Conf["Image Prefetching"] || Conf["Replace JPG"] || Conf["Replace PNG"] || Conf["Replace GIF"] || Conf["Replace WEBM"])) {
return;
}
@@ -11418,12 +11421,17 @@
name: 'Image Replace',
cb: this.node
});
- Thread.callbacks.push({
- name: 'Image Replace',
- cb: this.thread
+ $.on(d, 'PostsInserted', function() {
+ return g.posts.forEach(ImageLoader.prefetch);
});
+ if (Conf['Replace WEBM']) {
+ this.processVideo();
+ }
+ if (!Conf['Image Prefetching']) {
+ return;
+ }
prefetch = $.el('label', {
- innerHTML: ' Prefetch Images'
+ innerHTML: " Prefetch Images"
});
this.el = prefetch.firstElementChild;
$.on(this.el, 'change', this.toggle);
@@ -11432,65 +11440,98 @@
order: 104
});
},
- thread: function() {
- return ImageLoader.thread = this;
- },
node: function() {
- var URL, cb, file, isImage, isVideo, match, replace, style, thumb, type, _ref, _ref1;
- if (!this.file) {
+ if (this.isClone || !this.file) {
return;
}
- _ref = this.file, isImage = _ref.isImage, isVideo = _ref.isVideo;
- if (this.isClone || this.isHidden || this.thread.isHidden || !(isImage || isVideo)) {
+ if (Conf['Replace WEBM'] && this.file.isVideo) {
+ ImageLoader.replaceVideo(this);
+ }
+ return ImageLoader.prefetch(this);
+ },
+ replaceVideo: function(post) {
+ var attr, file, thumb, video, _i, _len, _ref;
+ file = post.file;
+ thumb = file.thumb;
+ video = $.el('video', {
+ preload: 'none',
+ loop: true,
+ poster: thumb.src,
+ textContent: thumb.alt,
+ className: thumb.className
+ });
+ video.dataset.md5 = thumb.dataset.md5;
+ _ref = ['height', 'width', 'maxHeight', 'maxWidth'];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ attr = _ref[_i];
+ video.style[attr] = thumb.style[attr];
+ }
+ video.src = file.URL;
+ $.replace(thumb, video);
+ file.thumb = video;
+ return file.videoThumb = true;
+ },
+ prefetch: function(post) {
+ var URL, clone, el, file, isImage, isVideo, item, match, pass, replace, thumb, type, _i, _j, _len, _len1, _ref, _ref1;
+ file = post.file;
+ if (!file) {
+ return;
+ }
+ isImage = file.isImage, isVideo = file.isVideo, thumb = file.thumb, URL = file.URL;
+ if (file.isPrefetched || !(isImage || isVideo) || post.isHidden || post.thread.isHidden) {
return;
}
- _ref1 = this.file, thumb = _ref1.thumb, URL = _ref1.URL;
- style = thumb.style;
type = (match = URL.match(/\.([^.]+)$/)[1].toUpperCase()) === 'JPEG' ? 'JPG' : match;
- replace = "Replace " + type;
- if (!((Conf[replace] && !/spoiler/.test(thumb.src)) || (Conf['prefetch'] && g.VIEW === 'thread'))) {
+ replace = Conf["Replace " + type] && !/spoiler/.test(thumb.src);
+ if (!(replace || Conf['prefetch'])) {
return;
}
- if (this.file.isSpoiler) {
- style.maxHeight = style.maxWidth = this.isReply ? '125px' : '250px';
- }
- file = $.el(isImage ? 'img' : 'video');
- if (Conf[replace]) {
- if (isVideo) {
- file.alt = thumb.alt;
- file.dataset.md5 = thumb.dataset.md5;
- file.style.height = style.height;
- file.style.width = style.width;
- file.style.maxHeight = style.maxHeight;
- file.style.maxWidth = style.maxWidth;
- file.loop = true;
- file.autoplay = Conf['Autoplay'];
- if (Conf['Image Hover']) {
- $.on(file, 'mouseover', ImageHover.mouseover);
- }
+ pass = false;
+ _ref = [post].concat(__slice.call(post.clones));
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ item = _ref[_i];
+ if (doc.contains(item.nodes.root)) {
+ pass = true;
+ break;
}
- cb = (function(_this) {
- return function() {
- $.off(file, 'load loadedmetadata', cb);
- if (isVideo) {
- $.replace(thumb, file);
- _this.file.thumb = file;
- return;
- }
- return thumb.src = URL;
- };
- })(this);
- $.on(file, 'load loadedmetadata', cb);
}
- return file.src = URL;
+ if (!pass) {
+ return;
+ }
+ file.isPrefetched = true;
+ if (file.videoThumb) {
+ _ref1 = post.clones;
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ clone = _ref1[_j];
+ clone.file.thumb.preload = 'auto';
+ }
+ thumb.preload = 'auto';
+ if (typeof chrome === "undefined" || chrome === null) {
+ $.on(thumb, 'loadeddata', function() {
+ return this.removeAttribute('poster');
+ });
+ }
+ return;
+ }
+ el = $.el(isImage ? 'img' : 'video');
+ if (replace && isImage) {
+ $.on(el, 'load', function() {
+ var _k, _len2, _ref2, _results;
+ _ref2 = post.clones;
+ _results = [];
+ for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
+ clone = _ref2[_k];
+ _results.push(clone.file.thumb.src = URL);
+ }
+ return _results;
+ });
+ thumb.src = URL;
+ }
+ return el.src = URL;
},
toggle: function() {
- var enabled;
- enabled = Conf['prefetch'] = this.checked;
- if (enabled) {
- g.BOARD.posts.forEach(function(post) {
- return ImageLoader.node.call(post);
- });
+ if (Conf['prefetch'] = this.checked) {
+ g.BOARD.posts.forEach(ImageLoader.prefetch);
}
}
};
diff --git a/src/Images/ImageLoader.coffee b/src/Images/ImageLoader.coffee
index 8934d8295..112866f4b 100755
--- a/src/Images/ImageLoader.coffee
+++ b/src/Images/ImageLoader.coffee
@@ -1,17 +1,22 @@
ImageLoader =
init: ->
- return unless Conf["Image Prefetching"] or Conf["Replace JPG"] or Conf["Replace PNG"] or Conf["Replace GIF"] or Conf["Replace WEBM"]
+ return unless g.VIEW in ['index', 'thread']
+ return unless Conf["Image Prefetching"] or
+ Conf["Replace JPG"] or Conf["Replace PNG"] or Conf["Replace GIF"] or Conf["Replace WEBM"]
Post.callbacks.push
name: 'Image Replace'
cb: @node
- Thread.callbacks.push
- name: 'Image Replace'
- cb: @thread
+ $.on d, 'PostsInserted', ->
+ g.posts.forEach ImageLoader.prefetch
+
+ @processVideo() if Conf['Replace WEBM']
+
+ return unless Conf['Image Prefetching']
prefetch = $.el 'label',
- innerHTML: ' Prefetch Images'
+ <%= html(' Prefetch Images') %>
@el = prefetch.firstElementChild
$.on @el, 'change', @toggle
@@ -20,48 +25,60 @@ ImageLoader =
el: prefetch
order: 104
- thread: ->
- ImageLoader.thread = @
-
node: ->
- return unless @file
- {isImage, isVideo} = @file
- return if @isClone or @isHidden or @thread.isHidden or !(isImage or isVideo)
- {thumb, URL} = @file
- {style} = thumb
- type = if (match = URL.match(/\.([^.]+)$/)[1].toUpperCase()) is 'JPEG' then 'JPG' else match
- replace = "Replace #{type}"
- return unless (Conf[replace] and !/spoiler/.test thumb.src) or (Conf['prefetch'] and g.VIEW is 'thread')
- if @file.isSpoiler
- # Revealed spoilers do not have height/width set, this fixes the image's dimensions.
- style.maxHeight = style.maxWidth = if @isReply then '125px' else '250px'
- file = $.el if isImage then 'img' else 'video'
- if Conf[replace]
- if isVideo
- file.alt = thumb.alt
- file.dataset.md5 = thumb.dataset.md5
- file.style.height = style.height
- file.style.width = style.width
- file.style.maxHeight = style.maxHeight
- file.style.maxWidth = style.maxWidth
- file.loop = true
- file.autoplay = Conf['Autoplay']
-
- $.on file, 'mouseover', ImageHover.mouseover if Conf['Image Hover']
+ return if @isClone or !@file
+ ImageLoader.replaceVideo @ if Conf['Replace WEBM'] and @file.isVideo
+ ImageLoader.prefetch @
- cb = =>
- $.off file, 'load loadedmetadata', cb
- # Replace the thumbnail once the file has finished loading.
- if isVideo
- $.replace thumb, file
- @file.thumb = file # XXX expanding requires the post.file.thumb node.
- return
+ replaceVideo: (post) ->
+ {file} = post
+ {thumb} = file
+ video = $.el 'video',
+ preload: 'none'
+ loop: true
+ poster: thumb.src
+ textContent: thumb.alt
+ className: thumb.className
+ video.dataset.md5 = thumb.dataset.md5
+ video.style[attr] = thumb.style[attr] for attr in ['height', 'width', 'maxHeight', 'maxWidth']
+ video.src = file.URL
+ $.replace thumb, video
+ file.thumb = video
+ file.videoThumb = true
+
+ prefetch: (post) ->
+ {file} = post
+ return unless file
+ {isImage, isVideo, thumb, URL} = file
+ return if file.isPrefetched or !(isImage or isVideo) or post.isHidden or post.thread.isHidden
+ type = if (match = URL.match(/\.([^.]+)$/)[1].toUpperCase()) is 'JPEG' then 'JPG' else match
+ replace = Conf["Replace #{type}"] and !/spoiler/.test thumb.src
+ return unless replace or Conf['prefetch']
+
+ pass = false
+ for item in [post, post.clones...]
+ if doc.contains item.nodes.root
+ pass = true
+ break
+ return unless pass
+
+ file.isPrefetched = true
+ if file.videoThumb
+ clone.file.thumb.preload = 'auto' for clone in post.clones
+ thumb.preload = 'auto'
+ # XXX Cloned video elements with poster in Firefox cause momentary display of image loading icon.
+ if !chrome?
+ $.on thumb, 'loadeddata', -> @removeAttribute 'poster'
+ return
+
+ el = $.el if isImage then 'img' else 'video'
+ if replace and isImage
+ $.on el, 'load', ->
+ clone.file.thumb.src = URL for clone in post.clones
thumb.src = URL
- $.on file, 'load loadedmetadata', cb
- file.src = URL
+ el.src = URL
toggle: ->
- enabled = Conf['prefetch'] = @checked
- if enabled
- g.BOARD.posts.forEach (post) -> ImageLoader.node.call post
+ if Conf['prefetch'] = @checked
+ g.BOARD.posts.forEach ImageLoader.prefetch
return
\ No newline at end of file