Merge branch 'ccd0' into v3

Rebase ImageExpand implemention off ccd0's

Conflicts:
	CHANGELOG.md
	builds/4chan-X.user.js
	builds/crx.crx
	builds/crx/script.js
	src/Images/ImageExpand.coffee
This commit is contained in:
Zixaphir 2014-04-08 14:46:15 -07:00
commit b00390b980
12 changed files with 258 additions and 271 deletions

View File

@ -1,3 +1,19 @@
<<<<<<< HEAD
=======
### v1.7.3
*2014-04-07*
**ccd0**
- Fix behavior of .webm videos expanded within inline quotes.
- Contract thumbnails in quoted previews to avoid crashes caused by videos in quoted previews on some systems.
- Change interface when both `Autoplay` and `Show Controls` are unchecked. In this mode, videos are now activated by clicking on them. The first click expands the video, the second click plays the video, and the third click contracts it.
- Add item `Expand videos` in `Image Expansion` menu, which enables expansion of videos by `Expand All Images`. Disabled by default. Previously videos were expanded.
- Disable autoplay for videos expanded by `Expand All Images`.
### v1.7.2
*2014-04-07*
>>>>>>> ccd0
**ccd0**
- Restore thread expansion with JSON navigation disabled.
@ -36,13 +52,15 @@
**ccd0**:
- Support hover for .webm videos.
- Add .webm to supported posting types.
- Add option to enable/disable sound.
- Add option `Allow Sound` to enable/disable sound. Enabled by default.
## v1.5.0
*2014-04-04*
**ccd0**:
- Support expansion of .webm videos.
- New setting: `Autoplay`, enabled by default. Causes videos to play immediately when expanded.
- New setting: `Show Controls`, enabled by default. Shows native controls on videos.
### v1.4.7
*2014-04-03*

View File

@ -1,5 +1,5 @@
/*
* 4chan X - Version 1.7.2 - 2014-04-07
* 4chan X - Version 1.7.3 - 2014-04-08
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE

View File

@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X
// @version 1.7.2
// @version 1.7.3
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
// @version 1.7.2
// @version 1.7.3
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@ -24,7 +24,7 @@
// ==/UserScript==
/*
* 4chan X - Version 1.7.2 - 2014-04-07
* 4chan X - Version 1.7.3 - 2014-04-08
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
@ -244,6 +244,7 @@
'Fit width': [false, ''],
'Fit height': [false, ''],
'Expand spoilers': [true, 'Expand all images along with spoilers.'],
'Expand videos': [false, 'Expand all images also expands videos (no autoplay).'],
'Expand from here': [false, 'Expand all images only from current position to thread end.'],
'Advance on contract': [false, 'Advance to next post when contracting an expanded image.']
},
@ -373,7 +374,7 @@
doc = d.documentElement;
g = {
VERSION: '1.7.2',
VERSION: '1.7.3',
NAMESPACE: '4chan X.',
boards: {}
};
@ -7928,7 +7929,7 @@
ImageExpand = {
init: function() {
if (!Conf['Image Expansion']) {
if (g.VIEW === 'catalog' || !Conf['Image Expansion']) {
return;
}
this.EAI = $.el('a', {
@ -7937,34 +7938,33 @@
title: 'Expand All Images',
href: 'javascript:;'
});
$.on(this.EAI, 'click', this.cb.toggleAll);
$.on(this.EAI, 'click', ImageExpand.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;
if (!(this.file && (this.file.isImage || this.file.isVideo))) {
var clone, thumb, _ref, _ref1;
if (!(((_ref = this.file) != null ? _ref.isImage : void 0) || ((_ref1 = this.file) != null ? _ref1.isVideo : void 0))) {
return;
}
thumb = this.file.thumb;
$.on(thumb.parentNode, 'click', ImageExpand.cb.toggle);
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)) {
if (this.isClone && $.hasClass(thumb, 'expanding')) {
ImageExpand.contract(this);
return ImageExpand.expand(this);
} else if (this.isClone && this.file.isExpanded && this.file.isVideo) {
clone = this;
ImageExpand.setupVideoControls(clone);
if (!clone.origin.file.fullImage.paused) {
return $.queueTask(function() {
return ImageExpand.startVideo(clone);
});
}
} else if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler) && (Conf['Expand videos'] || !this.file.isVideo)) {
return ImageExpand.expand(this, null, true);
}
},
cb: {
@ -7981,53 +7981,40 @@
return ImageExpand.toggle(post);
},
toggleAll: function() {
var func;
var func, toggle;
$.event('CloseMenu');
toggle = function(post) {
var file;
file = post.file;
if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) {
return;
}
if (ImageExpand.on && (!Conf['Expand spoilers'] && file.isSpoiler || !Conf['Expand videos'] && file.isVideo || Conf['Expand from here'] && Header.getTopOf(file.thumb) < 0)) {
return;
}
return $.queueTask(func, post);
};
if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) {
ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress';
ImageExpand.EAI.title = 'Contract All Images';
func = ImageExpand.expand;
func = function(post) {
return ImageExpand.expand(post, null, true);
};
} else {
ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand';
ImageExpand.EAI.title = 'Expand All Images';
func = ImageExpand.contract;
}
return g.posts.forEach(function(post) {
var file, _i, _len, _ref;
_ref = [post].concat(post.clones);
var _i, _len, _ref;
toggle(post);
_ref = post.clones;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
post = _ref[_i];
file = post.file;
if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) {
return;
}
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);
toggle(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, '-'));
}
@ -8035,7 +8022,7 @@
toggle: function(post) {
var headRect, left, root, thumb, top, x, y, _ref;
thumb = post.file.thumb;
if (!(post.file.isExpanded || post.file.isExpanding)) {
if (!(post.file.isExpanded || $.hasClass(thumb, 'expanding'))) {
ImageExpand.expand(post);
return;
}
@ -8083,10 +8070,9 @@
}
$.rmClass(post.nodes.root, 'expanded-image');
$.rmClass(post.file.thumb, 'expanding');
delete post.file.isExpanding;
return post.file.isExpanded = false;
},
expand: function(post, src) {
expand: function(post, src, disableAutoplay) {
var el, isVideo, thumb, _ref;
_ref = post.file, thumb = _ref.thumb, isVideo = _ref.isVideo;
if (post.isHidden || post.file.isExpanded || $.hasClass(thumb, 'expanding')) {
@ -8109,42 +8095,49 @@
$.after(thumb, el);
}
return $.asap((function() {
return el.videoHeight || el.naturalHeight;
if (isVideo) {
return el.videoHeight;
} else {
return el.naturalHeight;
}
}), function() {
return ImageExpand.completeExpand(post);
return ImageExpand.completeExpand(post, disableAutoplay);
});
},
completeExpand: function(post) {
var bottom, complete, thumb;
completeExpand: function(post, disableAutoplay) {
var bottom, 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) {
complete();
ImageExpand.completeExpand2(post);
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() {
complete();
ImageExpand.completeExpand2(post, disableAutoplay);
if (!(bottom <= 0)) {
return;
}
return window.scrollBy(0, post.nodes.root.getBoundingClientRect().bottom - bottom);
});
},
completeExpand2: function(post, disableAutoplay) {
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) {
ImageExpand.setupVideoControls(post);
post.file.fullImage.muted = !Conf['Allow Sound'];
post.file.fullImage.controls = Conf['Show Controls'];
if (Conf['Autoplay'] && !disableAutoplay) {
return ImageExpand.startVideo(post);
}
}
},
videoCB: {
click: function(e) {
if (this.paused && !this.controls) {
@ -8199,34 +8192,29 @@
}
return $.add(file.text, file.videoControls);
},
setupVideo: function(post) {
var file, video;
ImageExpand.setupVideoControls(post);
startVideo: function(post) {
var controls, file, video;
file = post.file;
video = file.fullImage;
video.muted = !Conf['Allow Sound'];
video.controls = Conf['Show Controls'];
if (Conf['Autoplay']) {
video.controls = false;
video.play();
if (Conf['Show Controls']) {
return $.asap((function() {
return (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || !file.isExpanded;
}), function() {
if (file.isExpanded) {
return video.controls = true;
}
}, 500);
}
controls = video.controls;
video.controls = false;
video.play();
if (controls) {
return $.asap((function() {
return (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || !file.isExpanded;
}), function() {
if (file.isExpanded) {
return video.controls = true;
}
}, 500);
}
},
error: function() {
var URL, post, src, timeoutID;
post = Get.postFromNode(this);
post.file.isReady = false;
$.rm(this);
delete post.file.fullImage;
if (!(post.file.isExpanding || post.file.isExpanded)) {
if (!($.hasClass(post.file.thumb, 'expanding') || $.hasClass(post.nodes.root, 'expanded-image'))) {
return;
}
ImageExpand.contract(post);
@ -8271,7 +8259,7 @@
menu: {
init: function() {
var conf, createSubEntry, el, name, subEntries, _ref;
if (!Conf['Image Expansion']) {
if (g.VIEW === 'catalog' || !Conf['Image Expansion']) {
return;
}
el = $.el('span', {
@ -12964,7 +12952,7 @@
return;
}
$.event('CloseMenu');
html = "<nav><div class=sections-list></div><p class='imp-exp-result warning'></p><div class=credits><a class=export>Export</a>&nbsp|&nbsp<a class=import>Import</a>&nbsp|&nbsp<a class=reset>Reset Settings</a>&nbsp|&nbsp<input type=file hidden><a href='https://github.com/ccd0/4chan-x' target=_blank>4chan X</a> |<a href='https://github.com/ccd0/4chan-x/blob/master/CHANGELOG.md' target=_blank>" + g.VERSION + "</a> |<a href='https://github.com/ccd0/4chan-x/blob/master/README.md#reporting-bugs-and-suggestions' target=_blank>Issues</a> |<a href=javascript:; class='close fa fa-times' title=Close></a></div></nav><div class=section-container><section></section></div>";
html = "<nav><div class=sections-list></div><p class='imp-exp-result warning'></p><div class=credits><a class=export>Export</a>&nbsp|&nbsp<a class=import>Import</a>&nbsp|&nbsp<a class=reset>Reset Settings</a>&nbsp|&nbsp<input type=file hidden><a href='https://github.com/ccd0/4chan-x' target=_blank>4chan X</a>&nbsp|&nbsp<a href='https://github.com/ccd0/4chan-x/blob/master/CHANGELOG.md' target=_blank>" + g.VERSION + "</a>&nbsp|&nbsp<a href='https://github.com/ccd0/4chan-x/issues' target=_blank>Issues</a>&nbsp|&nbsp<a href=javascript:; class='close fa fa-times' title=Close></a></div></nav><div class=section-container><section></section></div>";
Settings.overlay = overlay = $.el('div', {
id: 'overlay'
});

View File

@ -1,6 +1,6 @@
{
"name": "4chan X",
"version": "1.7.2",
"version": "1.7.3",
"manifest_version": 2,
"description": "Cross-browser userscript for maximum lurking on 4chan.",
"icons": {

View File

@ -1,6 +1,6 @@
// Generated by CoffeeScript
/*
* 4chan X - Version 1.7.2 - 2014-04-07
* 4chan X - Version 1.7.3 - 2014-04-08
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
@ -220,6 +220,7 @@
'Fit width': [false, ''],
'Fit height': [false, ''],
'Expand spoilers': [true, 'Expand all images along with spoilers.'],
'Expand videos': [false, 'Expand all images also expands videos (no autoplay).'],
'Expand from here': [false, 'Expand all images only from current position to thread end.'],
'Advance on contract': [false, 'Advance to next post when contracting an expanded image.']
},
@ -349,7 +350,7 @@
doc = d.documentElement;
g = {
VERSION: '1.7.2',
VERSION: '1.7.3',
NAMESPACE: '4chan X.',
boards: {}
};
@ -7967,7 +7968,7 @@
ImageExpand = {
init: function() {
if (!Conf['Image Expansion']) {
if (g.VIEW === 'catalog' || !Conf['Image Expansion']) {
return;
}
this.EAI = $.el('a', {
@ -7976,34 +7977,33 @@
title: 'Expand All Images',
href: 'javascript:;'
});
$.on(this.EAI, 'click', this.cb.toggleAll);
$.on(this.EAI, 'click', ImageExpand.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;
if (!(this.file && (this.file.isImage || this.file.isVideo))) {
var clone, thumb, _ref, _ref1;
if (!(((_ref = this.file) != null ? _ref.isImage : void 0) || ((_ref1 = this.file) != null ? _ref1.isVideo : void 0))) {
return;
}
thumb = this.file.thumb;
$.on(thumb.parentNode, 'click', ImageExpand.cb.toggle);
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)) {
if (this.isClone && $.hasClass(thumb, 'expanding')) {
ImageExpand.contract(this);
return ImageExpand.expand(this);
} else if (this.isClone && this.file.isExpanded && this.file.isVideo) {
clone = this;
ImageExpand.setupVideoControls(clone);
if (!clone.origin.file.fullImage.paused) {
return $.queueTask(function() {
return ImageExpand.startVideo(clone);
});
}
} else if (ImageExpand.on && !this.isHidden && (Conf['Expand spoilers'] || !this.file.isSpoiler) && (Conf['Expand videos'] || !this.file.isVideo)) {
return ImageExpand.expand(this, null, true);
}
},
cb: {
@ -8020,53 +8020,40 @@
return ImageExpand.toggle(post);
},
toggleAll: function() {
var func;
var func, toggle;
$.event('CloseMenu');
toggle = function(post) {
var file;
file = post.file;
if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) {
return;
}
if (ImageExpand.on && (!Conf['Expand spoilers'] && file.isSpoiler || !Conf['Expand videos'] && file.isVideo || Conf['Expand from here'] && Header.getTopOf(file.thumb) < 0)) {
return;
}
return $.queueTask(func, post);
};
if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) {
ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress';
ImageExpand.EAI.title = 'Contract All Images';
func = ImageExpand.expand;
func = function(post) {
return ImageExpand.expand(post, null, true);
};
} else {
ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand';
ImageExpand.EAI.title = 'Expand All Images';
func = ImageExpand.contract;
}
return g.posts.forEach(function(post) {
var file, _i, _len, _ref;
_ref = [post].concat(post.clones);
var _i, _len, _ref;
toggle(post);
_ref = post.clones;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
post = _ref[_i];
file = post.file;
if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) {
return;
}
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);
toggle(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, '-'));
}
@ -8074,7 +8061,7 @@
toggle: function(post) {
var headRect, left, root, thumb, top, x, y, _ref;
thumb = post.file.thumb;
if (!(post.file.isExpanded || post.file.isExpanding)) {
if (!(post.file.isExpanded || $.hasClass(thumb, 'expanding'))) {
ImageExpand.expand(post);
return;
}
@ -8122,10 +8109,9 @@
}
$.rmClass(post.nodes.root, 'expanded-image');
$.rmClass(post.file.thumb, 'expanding');
delete post.file.isExpanding;
return post.file.isExpanded = false;
},
expand: function(post, src) {
expand: function(post, src, disableAutoplay) {
var el, isVideo, thumb, _ref;
_ref = post.file, thumb = _ref.thumb, isVideo = _ref.isVideo;
if (post.isHidden || post.file.isExpanded || $.hasClass(thumb, 'expanding')) {
@ -8148,42 +8134,49 @@
$.after(thumb, el);
}
return $.asap((function() {
return el.videoHeight || el.naturalHeight;
if (isVideo) {
return el.videoHeight;
} else {
return el.naturalHeight;
}
}), function() {
return ImageExpand.completeExpand(post);
return ImageExpand.completeExpand(post, disableAutoplay);
});
},
completeExpand: function(post) {
var bottom, complete, thumb;
completeExpand: function(post, disableAutoplay) {
var bottom, 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) {
complete();
ImageExpand.completeExpand2(post);
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() {
complete();
ImageExpand.completeExpand2(post, disableAutoplay);
if (!(bottom <= 0)) {
return;
}
return window.scrollBy(0, post.nodes.root.getBoundingClientRect().bottom - bottom);
});
},
completeExpand2: function(post, disableAutoplay) {
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) {
ImageExpand.setupVideoControls(post);
post.file.fullImage.muted = !Conf['Allow Sound'];
post.file.fullImage.controls = Conf['Show Controls'];
if (Conf['Autoplay'] && !disableAutoplay) {
return ImageExpand.startVideo(post);
}
}
},
videoCB: {
click: function(e) {
if (this.paused && !this.controls) {
@ -8238,34 +8231,29 @@
}
return $.add(file.text, file.videoControls);
},
setupVideo: function(post) {
var file, video;
ImageExpand.setupVideoControls(post);
startVideo: function(post) {
var controls, file, video;
file = post.file;
video = file.fullImage;
video.muted = !Conf['Allow Sound'];
video.controls = Conf['Show Controls'];
if (Conf['Autoplay']) {
video.controls = false;
video.play();
if (Conf['Show Controls']) {
return $.asap((function() {
return (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || !file.isExpanded;
}), function() {
if (file.isExpanded) {
return video.controls = true;
}
}, 500);
}
controls = video.controls;
video.controls = false;
video.play();
if (controls) {
return $.asap((function() {
return (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || !file.isExpanded;
}), function() {
if (file.isExpanded) {
return video.controls = true;
}
}, 500);
}
},
error: function() {
var URL, post, src, timeoutID;
post = Get.postFromNode(this);
post.file.isReady = false;
$.rm(this);
delete post.file.fullImage;
if (!(post.file.isExpanding || post.file.isExpanded)) {
if (!($.hasClass(post.file.thumb, 'expanding') || $.hasClass(post.nodes.root, 'expanded-image'))) {
return;
}
ImageExpand.contract(post);
@ -8284,7 +8272,7 @@
}
}
timeoutID = setTimeout(ImageExpand.expand, 10000, post);
return $.ajax(post.file.URL, {
return $.ajax(this.src, {
onloadend: function() {
if (this.status !== 404) {
return;
@ -8299,7 +8287,7 @@
menu: {
init: function() {
var conf, createSubEntry, el, name, subEntries, _ref;
if (!Conf['Image Expansion']) {
if (g.VIEW === 'catalog' || !Conf['Image Expansion']) {
return;
}
el = $.el('span', {
@ -12985,7 +12973,7 @@
return;
}
$.event('CloseMenu');
html = "<nav><div class=sections-list></div><p class='imp-exp-result warning'></p><div class=credits><a class=export>Export</a>&nbsp|&nbsp<a class=import>Import</a>&nbsp|&nbsp<a class=reset>Reset Settings</a>&nbsp|&nbsp<input type=file hidden><a href='https://github.com/ccd0/4chan-x' target=_blank>4chan X</a> |<a href='https://github.com/ccd0/4chan-x/blob/master/CHANGELOG.md' target=_blank>" + g.VERSION + "</a> |<a href='https://github.com/ccd0/4chan-x/blob/master/README.md#reporting-bugs-and-suggestions' target=_blank>Issues</a> |<a href=javascript:; class='close fa fa-times' title=Close></a></div></nav><div class=section-container><section></section></div>";
html = "<nav><div class=sections-list></div><p class='imp-exp-result warning'></p><div class=credits><a class=export>Export</a>&nbsp|&nbsp<a class=import>Import</a>&nbsp|&nbsp<a class=reset>Reset Settings</a>&nbsp|&nbsp<input type=file hidden><a href='https://github.com/ccd0/4chan-x' target=_blank>4chan X</a>&nbsp|&nbsp<a href='https://github.com/ccd0/4chan-x/blob/master/CHANGELOG.md' target=_blank>" + g.VERSION + "</a>&nbsp|&nbsp<a href='https://github.com/ccd0/4chan-x/issues' target=_blank>Issues</a>&nbsp|&nbsp<a href=javascript:; class='close fa fa-times' title=Close></a></div></nav><div class=section-container><section></section></div>";
Settings.overlay = overlay = $.el('div', {
id: 'overlay'
});

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/crx.crx' version='1.7.2' />
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/crx.crx' version='1.7.3' />
</app>
</gupdate>

View File

@ -1 +1 @@
postMessage({version:'1.7.2'},'*')
postMessage({version:'1.7.3'},'*')

View File

@ -1,6 +1,6 @@
{
"name": "4chan-X",
"version": "1.7.2",
"version": "1.7.3",
"description": "Cross-browser userscript for maximum lurking on 4chan.",
"meta": {
"name": "4chan X",

View File

@ -409,6 +409,10 @@ Config =
true
'Expand all images along with spoilers.'
]
'Expand videos': [
false
'Expand all images also expands videos (no autoplay).'
]
'Expand from here': [
false
'Expand all images only from current position to thread end.'

View File

@ -6,10 +6,10 @@
<a class=import>Import</a>&nbsp|&nbsp
<a class=reset>Reset Settings</a>&nbsp|&nbsp
<input type=file hidden>
<a href='<%= meta.page %>' target=_blank><%= meta.name %></a> |
<a href='<%= meta.repo %>blob/<%= meta.mainBranch %>/CHANGELOG.md' target=_blank>#{g.VERSION}</a> |
<a href='<%= meta.repo %>blob/<%= meta.mainBranch %>/README.md#reporting-bugs-and-suggestions' target=_blank>Issues</a> |
<a href='<%= meta.page %>' target=_blank><%= meta.name %></a>&nbsp|&nbsp
<a href='<%= meta.repo %>blob/<%= meta.mainBranch %>/CHANGELOG.md' target=_blank>#{g.VERSION}</a>&nbsp|&nbsp
<a href='<%= meta.repo %>issues' target=_blank>Issues</a>&nbsp|&nbsp
<a href=javascript:; class='close fa fa-times' title=Close></a>
</div>
</nav>
<div class=section-container><section></section></div>
<div class=section-container><section></section></div>

View File

@ -1,37 +1,36 @@
ImageExpand =
init: ->
return if !Conf['Image Expansion']
return if g.VIEW is 'catalog' or !Conf['Image Expansion']
@EAI = $.el 'a',
className: 'expand-all-shortcut fa fa-expand'
textContent: 'EAI'
title: 'Expand All Images'
href: 'javascript:;'
$.on @EAI, 'click', @cb.toggleAll
$.on @EAI, 'click', ImageExpand.cb.toggleAll
Header.addShortcut @EAI, 3
$.on d, 'scroll visibilitychange', @cb.playVideos
Post.callbacks.push
name: 'Image Expansion'
cb: @node
node: ->
return unless @file and (@file.isImage or @file.isVideo)
return unless @file?.isImage or @file?.isVideo
{thumb} = @file
$.on thumb.parentNode, 'click', ImageExpand.cb.toggle
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)
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
clone = @
ImageExpand.setupVideoControls clone
unless clone.origin.file.fullImage.paused
$.queueTask -> ImageExpand.startVideo clone
else if ImageExpand.on and !@isHidden and
(Conf['Expand spoilers'] or !@file.isSpoiler) and
(Conf['Expand videos'] or !@file.isVideo)
ImageExpand.expand @, null, true
cb:
toggle: (e) ->
return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0
@ -42,42 +41,36 @@ ImageExpand =
toggleAll: ->
$.event 'CloseMenu'
toggle = (post) ->
{file} = post
return unless file and (file.isImage or file.isVideo) and doc.contains post.nodes.root
if ImageExpand.on and
(!Conf['Expand spoilers'] and file.isSpoiler or
!Conf['Expand videos'] and file.isVideo or
Conf['Expand from here'] and Header.getTopOf(file.thumb) < 0)
return
$.queueTask func, post
if ImageExpand.on = $.hasClass ImageExpand.EAI, 'expand-all-shortcut'
ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress'
ImageExpand.EAI.title = 'Contract All Images'
func = ImageExpand.expand
func = (post) -> ImageExpand.expand post, null, true
else
ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand'
ImageExpand.EAI.title = 'Expand All Images'
func = ImageExpand.contract
g.posts.forEach (post) ->
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 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
toggle post
toggle post for post in post.clones
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 post.file.isExpanding
unless post.file.isExpanded or $.hasClass thumb, 'expanding'
ImageExpand.expand post
return
@ -117,10 +110,9 @@ 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) ->
expand: (post, src, disableAutoplay) ->
# Do not expand images of hidden/filtered replies, or already expanded pictures.
{thumb, isVideo} = post.file
return if post.isHidden or post.file.isExpanded or $.hasClass thumb, 'expanding'
@ -135,33 +127,34 @@ ImageExpand =
$.on el, 'error', ImageExpand.error
el.src = src or post.file.URL
$.after thumb, el unless el is thumb.nextSibling
$.asap (-> el.videoHeight or el.naturalHeight), ->
ImageExpand.completeExpand post
$.asap (-> if isVideo then el.videoHeight else el.naturalHeight), ->
ImageExpand.completeExpand post, disableAutoplay
completeExpand: (post) ->
completeExpand: (post, disableAutoplay) ->
{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.
complete()
ImageExpand.completeExpand2 post
return
post.file.fullImage.play() if post.file.isVideo and !d.hidden and Header.isNodeVisible post.nodes.root
{bottom} = post.nodes.root.getBoundingClientRect()
$.queueTask ->
complete()
ImageExpand.completeExpand2 post, disableAutoplay
return unless bottom <= 0
window.scrollBy 0, post.nodes.root.getBoundingClientRect().bottom - bottom
completeExpand2: (post, disableAutoplay) ->
{thumb} = post.file
$.addClass post.nodes.root, 'expanded-image'
$.rmClass post.file.thumb, 'expanding'
post.file.isExpanded = true
if post.file.isVideo
ImageExpand.setupVideoControls post
post.file.fullImage.muted = !Conf['Allow Sound']
post.file.fullImage.controls = Conf['Show Controls']
ImageExpand.startVideo post if Conf['Autoplay'] and not disableAutoplay
videoCB:
click: (e) ->
if @paused and not @controls
@ -170,9 +163,9 @@ ImageExpand =
# dragging to the left contracts the video
mousedown: (e) -> @dataset.mousedown = 'true' if e.button is 0
mouseup: (e) -> @dataset.mousedown = 'false' if e.button is 0
mouseup: (e) -> @dataset.mousedown = 'false' if e.button is 0
mouseover: (e) -> @dataset.mousedown = 'false'
mouseout: (e) ->
mouseout: (e) ->
if @dataset.mousedown is 'true' and e.clientX <= @getBoundingClientRect().left
ImageExpand.contract (Get.postFromNode @)
@ -200,30 +193,26 @@ ImageExpand =
$.add file.videoControls, [$.tn('\u00A0'), contract]
$.add file.text, file.videoControls
setupVideo: (post) ->
ImageExpand.setupVideoControls post
startVideo: (post) ->
{file} = post
video = file.fullImage
video.muted = !Conf['Allow Sound']
video.controls = Conf['Show Controls']
if Conf['Autoplay']
video.controls = false
video.play()
# Hacky workaround for Firefox forever-loading bug for very short videos
if Conf['Show Controls']
$.asap (-> (video.readyState >= 3 and video.currentTime <= Math.max 0.1, (video.duration - 0.5)) or !file.isExpanded), ->
video.controls = true if file.isExpanded
, 500
{controls} = video
video.controls = false
video.play()
# Hacky workaround for Firefox forever-loading bug for very short videos
if controls
$.asap (-> (video.readyState >= 3 and video.currentTime <= Math.max 0.1, (video.duration - 0.5)) or !file.isExpanded), ->
video.controls = true if file.isExpanded
, 500
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 post.file.isExpanding or post.file.isExpanded
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
@ -241,7 +230,7 @@ ImageExpand =
timeoutID = setTimeout ImageExpand.expand, 10000, post
<% if (type === 'crx') { %>
$.ajax post.file.URL,
$.ajax @src,
onloadend: ->
return if @status isnt 404
clearTimeout timeoutID
@ -264,7 +253,7 @@ ImageExpand =
menu:
init: ->
return if !Conf['Image Expansion']
return if g.VIEW is 'catalog' or !Conf['Image Expansion']
el = $.el 'span',
textContent: 'Image Expansion'