Release 4chan X v1.10.3.0.
This commit is contained in:
parent
bf8d530b29
commit
6ab3969672
10
CHANGELOG.md
10
CHANGELOG.md
@ -2,6 +2,16 @@ Sometimes the changelog has notes (not comprehensive) acknowledging people's wor
|
||||
|
||||
The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x).
|
||||
|
||||
### v1.10.3
|
||||
|
||||
**v1.10.3.0** *(2015-03-01)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.3.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.3.0/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
- Make the filename in the Quick Reply editable immediately without having to Control+click it.
|
||||
- Add a "Files" button which can be used to open the file picker even if a file has already been selected. This also fixes issues with opening the file picker via keyboard on Firefox.
|
||||
- Move the spoiler checkbox into the box containing the filename.
|
||||
- Always merely warn about disallowed file types / sizes / dimensions, rather than outright preventing them from being posted. Links to `[delete]` and `[delete all]` such posts have been added to the warning messages to make removing the files from a dumplist convenient.
|
||||
- Remove the "low on cached captchas" notifications as the 2-minute captcha expiry time has made them more annoying than useful.
|
||||
- Minor bugfixes.
|
||||
|
||||
### v1.10.2
|
||||
|
||||
**v1.10.2.8** *(2015-02-28)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.2.8/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.2.8/builds/4chan-X-noupdate.crx "Chromium version")]
|
||||
|
||||
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
// ==UserScript==
|
||||
// @name 4chan X beta
|
||||
// @version 1.10.2.8
|
||||
// @version 1.10.3.0
|
||||
// @minGMVer 1.14
|
||||
// @minFFVer 26
|
||||
// @namespace 4chan-X
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Generated by CoffeeScript
|
||||
// ==UserScript==
|
||||
// @name 4chan X beta
|
||||
// @version 1.10.2.8
|
||||
// @version 1.10.3.0
|
||||
// @minGMVer 1.14
|
||||
// @minFFVer 26
|
||||
// @namespace 4chan-X
|
||||
@ -393,7 +393,7 @@
|
||||
doc = d.documentElement;
|
||||
|
||||
g = {
|
||||
VERSION: '1.10.2.8',
|
||||
VERSION: '1.10.3.0',
|
||||
NAMESPACE: '4chan X.',
|
||||
NAME: '4chan X',
|
||||
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
|
||||
@ -3066,7 +3066,7 @@
|
||||
el: $.el('span', {
|
||||
textContent: 'Index Navigation'
|
||||
}),
|
||||
order: 98,
|
||||
order: 100,
|
||||
subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry]
|
||||
});
|
||||
$.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode");
|
||||
@ -6392,7 +6392,7 @@
|
||||
$.on(this.threadNewLink.firstElementChild, 'click', this.rethread);
|
||||
Header.menu.addEntry(this.entry = {
|
||||
el: this.controls,
|
||||
order: 98
|
||||
order: 99
|
||||
});
|
||||
Thread.callbacks.push({
|
||||
name: 'Quote Threading',
|
||||
@ -7169,6 +7169,7 @@
|
||||
if (url === null) {
|
||||
return;
|
||||
}
|
||||
QR.nodes.fileButton.focus();
|
||||
return CrossOrigin.file(url, function(blob) {
|
||||
if (blob) {
|
||||
return QR.handleFiles([blob]);
|
||||
@ -7178,7 +7179,7 @@
|
||||
});
|
||||
},
|
||||
handleFiles: function(files) {
|
||||
var file, i, k, len1;
|
||||
var file, k, len1;
|
||||
if (this !== QR) {
|
||||
files = slice.call(this.files);
|
||||
this.value = null;
|
||||
@ -7187,147 +7188,36 @@
|
||||
return;
|
||||
}
|
||||
QR.cleanNotifications();
|
||||
for (i = k = 0, len1 = files.length; k < len1; i = ++k) {
|
||||
file = files[i];
|
||||
QR.handleFile(file, i, files.length);
|
||||
for (k = 0, len1 = files.length; k < len1; k++) {
|
||||
file = files[k];
|
||||
QR.handleFile(file, files.length);
|
||||
}
|
||||
if (files.length !== 1) {
|
||||
return $.addClass(QR.nodes.el, 'dump');
|
||||
$.addClass(QR.nodes.el, 'dump');
|
||||
}
|
||||
if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) {
|
||||
return QR.nodes.filename.focus();
|
||||
}
|
||||
},
|
||||
handleFile: function(file, index, nfiles) {
|
||||
var isNewPost, isSingle, max, post, ref;
|
||||
isSingle = nfiles === 1;
|
||||
if (/^text\//.test(file.type)) {
|
||||
if (isSingle) {
|
||||
post = QR.selected;
|
||||
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) {
|
||||
handleFile: function(file, nfiles) {
|
||||
var isText, post;
|
||||
isText = /^text\//.test(file.type);
|
||||
if (nfiles === 1) {
|
||||
post = QR.selected;
|
||||
} else {
|
||||
post = QR.posts[QR.posts.length - 1];
|
||||
if ((isText ? post.com || post.pasting : post.file)) {
|
||||
post = new QR.post();
|
||||
}
|
||||
post.pasteText(file);
|
||||
}
|
||||
return post[isText ? 'pasteText' : 'setFile'](file);
|
||||
},
|
||||
openFileInput: function() {
|
||||
if (QR.nodes.fileButton.disabled) {
|
||||
return;
|
||||
}
|
||||
if (ref = file.type, indexOf.call(QR.mimeTypes, ref) < 0) {
|
||||
QR.error(file.name + ": Unsupported file type.");
|
||||
if (!isSingle) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
max = QR.nodes.fileInput.max;
|
||||
if (/^video\//.test(file.type)) {
|
||||
max = Math.min(max, QR.max_size_video);
|
||||
}
|
||||
if (file.size > max) {
|
||||
QR.error(file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ").");
|
||||
if (!isSingle) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
isNewPost = false;
|
||||
if (isSingle) {
|
||||
post = QR.selected;
|
||||
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) {
|
||||
isNewPost = true;
|
||||
post = new QR.post();
|
||||
}
|
||||
return QR.checkDimensions(file, function(pass, el) {
|
||||
if (pass || isSingle) {
|
||||
return post.setFile(file, el);
|
||||
} else if (isNewPost) {
|
||||
post.rm();
|
||||
if (el) {
|
||||
return URL.revokeObjectURL(el.src);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
checkDimensions: function(file, cb) {
|
||||
var img, video;
|
||||
if (/^image\//.test(file.type)) {
|
||||
img = new Image();
|
||||
img.onload = function() {
|
||||
var height, pass, width;
|
||||
height = img.height, width = img.width;
|
||||
pass = true;
|
||||
if (height > QR.max_height || width > QR.max_width) {
|
||||
QR.error(file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
if (height < QR.min_height || width < QR.min_width) {
|
||||
QR.error(file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
return cb(pass, img);
|
||||
};
|
||||
img.onerror = function() {
|
||||
return cb(false, null);
|
||||
};
|
||||
return img.src = URL.createObjectURL(file);
|
||||
} else if (/^video\//.test(file.type)) {
|
||||
video = $.el('video');
|
||||
$.on(video, 'loadeddata', function() {
|
||||
var duration, max_height, max_width, pass, ref, videoHeight, videoWidth;
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
videoHeight = video.videoHeight, videoWidth = video.videoWidth, duration = video.duration;
|
||||
max_height = Math.min(QR.max_height, QR.max_height_video);
|
||||
max_width = Math.min(QR.max_width, QR.max_width_video);
|
||||
pass = true;
|
||||
if (videoHeight > max_height || videoWidth > max_width) {
|
||||
QR.error(file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
|
||||
QR.error(file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
if (!isFinite(duration)) {
|
||||
QR.error(file.name + ": Video lacks duration metadata (try remuxing)");
|
||||
pass = false;
|
||||
} else if (duration > QR.max_duration_video) {
|
||||
QR.error(file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
|
||||
pass = false;
|
||||
}
|
||||
if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(video)) {
|
||||
QR.error(file.name + ": Audio not allowed");
|
||||
pass = false;
|
||||
}
|
||||
cb(pass, video);
|
||||
return cb = null;
|
||||
});
|
||||
$.on(video, 'error', function() {
|
||||
var ref;
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
if (ref = file.type, indexOf.call(QR.mimeTypes, ref) >= 0) {
|
||||
QR.error(file.name + ": Video appears corrupt");
|
||||
}
|
||||
URL.revokeObjectURL(file);
|
||||
cb(false, null);
|
||||
return cb = null;
|
||||
});
|
||||
return video.src = URL.createObjectURL(file);
|
||||
} else {
|
||||
return cb(true, null);
|
||||
}
|
||||
},
|
||||
openFileInput: function(e) {
|
||||
var ref;
|
||||
e.stopPropagation();
|
||||
if (e.shiftKey && e.type === 'click') {
|
||||
return QR.selected.rmFile();
|
||||
}
|
||||
if ((e.ctrlKey || e.metaKey) && e.type === 'click') {
|
||||
$.addClass(QR.nodes.filename, 'edit');
|
||||
QR.nodes.filename.focus();
|
||||
}
|
||||
if (e.target.nodeName === 'INPUT' || (e.keyCode && ((ref = e.keyCode) !== 32 && ref !== 13)) || e.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
return QR.nodes.fileInput.click();
|
||||
QR.nodes.fileInput.click();
|
||||
return QR.nodes.fileButton.focus();
|
||||
},
|
||||
generatePostableThreadsList: function() {
|
||||
var k, len1, list, options, ref, thread, val;
|
||||
@ -7358,7 +7248,7 @@
|
||||
var dialog, event, i, items, m, match_max, match_min, name, node, nodes, ref, rules, save, setNode;
|
||||
QR.nodes = nodes = {
|
||||
el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', {
|
||||
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=file-n-submit><span id=qr-filename-container class=field tabindex=0><span id=qr-no-file>No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><span id=\"qr-extras-container\"><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span></span><label id=qr-spoiler-label><input type=checkbox id=qr-file-spoiler title='Spoiler image'></label><input type=submit></div><input type=file multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
|
||||
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=\"file-n-submit\"><input type=\"button\" id=\"qr-file-button\" value=\"Files\"><span id=\"qr-filename-container\" class=\"field\"><span id=\"qr-no-file\">No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><label id=\"qr-spoiler-label\"><input type=\"checkbox\" id=\"qr-file-spoiler\" title=\"Spoiler image\"></label><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span><input type=\"submit\"></div><input type=\"file\" multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
|
||||
})
|
||||
};
|
||||
setNode = function(name, query) {
|
||||
@ -7380,10 +7270,10 @@
|
||||
setNode('addPost', '#add-post');
|
||||
setNode('charCount', '#char-count');
|
||||
setNode('fileSubmit', '#file-n-submit');
|
||||
setNode('fileButton', '#qr-file-button');
|
||||
setNode('noFile', '#qr-no-file');
|
||||
setNode('filename', '#qr-filename');
|
||||
setNode('fileContainer', '#qr-filename-container');
|
||||
setNode('fileRM', '#qr-filerm');
|
||||
setNode('fileExtras', '#qr-extras-container');
|
||||
setNode('spoiler', '#qr-file-spoiler');
|
||||
setNode('spoilerPar', '#qr-spoiler-label');
|
||||
setNode('status', '[type=submit]');
|
||||
@ -7437,7 +7327,8 @@
|
||||
nodes.flashTag.dataset["default"] = '4';
|
||||
$.add(nodes.form, nodes.flashTag);
|
||||
}
|
||||
$.on(nodes.filename.parentNode, 'click keydown', QR.openFileInput);
|
||||
$.on(nodes.fileButton, 'click', QR.openFileInput);
|
||||
$.on(nodes.noFile, 'click', QR.openFileInput);
|
||||
$.on(nodes.autohide, 'change', QR.toggleHide);
|
||||
$.on(nodes.close, 'click', QR.close);
|
||||
$.on(nodes.dumpButton, 'click', function() {
|
||||
@ -7448,15 +7339,9 @@
|
||||
return new QR.post(true);
|
||||
});
|
||||
$.on(nodes.form, 'submit', QR.submit);
|
||||
$.on(nodes.filename, 'blur', function() {
|
||||
return $.rmClass(this, 'edit');
|
||||
});
|
||||
$.on(nodes.fileRM, 'click', function() {
|
||||
return QR.selected.rmFile();
|
||||
});
|
||||
$.on(nodes.fileExtras, 'click', function(e) {
|
||||
return e.stopPropagation();
|
||||
});
|
||||
$.on(nodes.spoiler, 'change', function() {
|
||||
return QR.selected.nodes.spoiler.click();
|
||||
});
|
||||
@ -7626,7 +7511,7 @@
|
||||
return QR.status();
|
||||
},
|
||||
response: function() {
|
||||
var URL, _, ban, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, ref, ref1, req, resDoc, threadID;
|
||||
var URL, _, ban, err, h1, isReply, m, post, postID, postsCount, ref, ref1, req, resDoc, threadID;
|
||||
req = QR.req;
|
||||
delete QR.req;
|
||||
post = QR.posts[0];
|
||||
@ -7696,22 +7581,6 @@
|
||||
});
|
||||
postsCount = QR.posts.length - 1;
|
||||
QR.cooldown.auto = postsCount && isReply;
|
||||
if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) {
|
||||
notif = new Notification('Quick reply warning', {
|
||||
body: "You are running low on cached captchas. Cache count: " + captchasCount + ".",
|
||||
icon: Favicon.logo
|
||||
});
|
||||
notif.onclick = function() {
|
||||
QR.open();
|
||||
window.focus();
|
||||
return QR.captcha.setup(true);
|
||||
};
|
||||
notif.onshow = function() {
|
||||
return setTimeout(function() {
|
||||
return notif.close();
|
||||
}, 7 * $.SECOND);
|
||||
};
|
||||
}
|
||||
if (!(Conf['Persistent QR'] || postsCount)) {
|
||||
QR.close();
|
||||
} else {
|
||||
@ -8119,7 +7988,7 @@
|
||||
return $.on(window, 'focus', function() {
|
||||
return $.queueTask(function() {
|
||||
var checkbox;
|
||||
if (!(checkbox = $.id('recaptcha-anchor'))) {
|
||||
if (!(d.hasFocus() && (checkbox = $.id('recaptcha-anchor')))) {
|
||||
return;
|
||||
}
|
||||
if (d.activeElement !== checkbox) {
|
||||
@ -8166,7 +8035,6 @@
|
||||
if (!(this.isEnabled && (this.needed() || force))) {
|
||||
return;
|
||||
}
|
||||
$.addClass(QR.nodes.el, 'captcha-open');
|
||||
if (focus) {
|
||||
this.shouldFocus = true;
|
||||
}
|
||||
@ -8210,6 +8078,7 @@
|
||||
},
|
||||
setupIFrame: function(iframe) {
|
||||
this.setupTime = Date.now();
|
||||
$.addClass(QR.nodes.el, 'captcha-open');
|
||||
if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
|
||||
QR.nodes.el.style.top = null;
|
||||
QR.nodes.el.style.bottom = '0px';
|
||||
@ -8693,7 +8562,8 @@
|
||||
|
||||
_Class.prototype["delete"] = function() {
|
||||
$.rm(this.nodes.el);
|
||||
return URL.revokeObjectURL(this.URL);
|
||||
URL.revokeObjectURL(this.URL);
|
||||
return this.dismissErrors();
|
||||
};
|
||||
|
||||
_Class.prototype.lock = function(lock) {
|
||||
@ -8713,7 +8583,6 @@
|
||||
}
|
||||
}
|
||||
this.nodes.rm.style.visibility = lock ? 'hidden' : '';
|
||||
(lock ? $.off : $.on)(QR.nodes.filename.previousElementSibling, 'click', QR.openFileInput);
|
||||
this.nodes.spoiler.disabled = lock;
|
||||
return this.nodes.el.draggable = !lock;
|
||||
};
|
||||
@ -8799,10 +8668,82 @@
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.setFile = function(file1, el) {
|
||||
_Class.rmErrored = function(e) {
|
||||
var error, errors, k, len1, post, q, ref;
|
||||
e.stopPropagation();
|
||||
ref = QR.posts;
|
||||
for (k = ref.length - 1; k >= 0; k += -1) {
|
||||
post = ref[k];
|
||||
if (errors = post.errors) {
|
||||
for (q = 0, len1 = errors.length; q < len1; q++) {
|
||||
error = errors[q];
|
||||
if (!(doc.contains(error))) {
|
||||
continue;
|
||||
}
|
||||
post.rm();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.error = function(className, message) {
|
||||
var div, ref, rm, rmAll;
|
||||
div = $.el('div', {
|
||||
className: className
|
||||
});
|
||||
$.extend(div, {
|
||||
innerHTML: E(message) + "<br>[<a href=\"javascript:;\">delete</a>] [<a href=\"javascript:;\">delete all</a>]"
|
||||
});
|
||||
(this.errors || (this.errors = [])).push(div);
|
||||
ref = $$('a', div), rm = ref[0], rmAll = ref[1];
|
||||
$.on(div, 'click', (function(_this) {
|
||||
return function() {
|
||||
if (indexOf.call(QR.posts, _this) >= 0) {
|
||||
return _this.select();
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
$.on(rm, 'click', (function(_this) {
|
||||
return function(e) {
|
||||
e.stopPropagation();
|
||||
if (indexOf.call(QR.posts, _this) >= 0) {
|
||||
return _this.rm();
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
$.on(rmAll, 'click', QR.post.rmErrored);
|
||||
return QR.error(div);
|
||||
};
|
||||
|
||||
_Class.prototype.fileError = function(message) {
|
||||
return this.error('file-error', this.filename + ": " + message);
|
||||
};
|
||||
|
||||
_Class.prototype.dismissErrors = function(test) {
|
||||
var error, k, len1, ref;
|
||||
if (test == null) {
|
||||
test = function() {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
if (this.errors) {
|
||||
ref = this.errors;
|
||||
for (k = 0, len1 = ref.length; k < len1; k++) {
|
||||
error = ref[k];
|
||||
if (doc.contains(error) && test(error)) {
|
||||
error.parentNode.previousElementSibling.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.setFile = function(file1) {
|
||||
var ref;
|
||||
this.file = file1;
|
||||
this.filename = this.file.name;
|
||||
this.filesize = $.bytesToString(this.file.size);
|
||||
this.checkSize();
|
||||
if (QR.spoiler) {
|
||||
this.nodes.label.hidden = false;
|
||||
}
|
||||
@ -8813,10 +8754,79 @@
|
||||
} else {
|
||||
this.updateFilename();
|
||||
}
|
||||
if (el) {
|
||||
return this.setThumbnail(el);
|
||||
this.nodes.el.style.backgroundImage = null;
|
||||
if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) {
|
||||
return this.fileError('Unsupported file type.');
|
||||
} else if (/^(image|video)\//.test(this.file.type)) {
|
||||
return this.readFile();
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.checkSize = function() {
|
||||
var max;
|
||||
max = QR.nodes.fileInput.max;
|
||||
if (/^video\//.test(this.file.type)) {
|
||||
max = Math.min(max, QR.max_size_video);
|
||||
}
|
||||
if (this.file.size > max) {
|
||||
return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ").");
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.readFile = function() {
|
||||
var el, event, isVideo, onerror, onload;
|
||||
isVideo = /^video\//.test(this.file.type);
|
||||
el = $.el(isVideo ? 'video' : 'img');
|
||||
event = isVideo ? 'loadeddata' : 'load';
|
||||
onload = (function(_this) {
|
||||
return function() {
|
||||
$.off(el, event, onload);
|
||||
$.off(el, 'error', onerror);
|
||||
_this.checkDimensions(el);
|
||||
return _this.setThumbnail(el);
|
||||
};
|
||||
})(this);
|
||||
onerror = (function(_this) {
|
||||
return function() {
|
||||
$.off(el, event, onload);
|
||||
$.off(el, 'error', onerror);
|
||||
_this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt");
|
||||
return URL.revokeObjectURL(el.src);
|
||||
};
|
||||
})(this);
|
||||
$.on(el, event, onload);
|
||||
$.on(el, 'error', onerror);
|
||||
return el.src = URL.createObjectURL(this.file);
|
||||
};
|
||||
|
||||
_Class.prototype.checkDimensions = function(el) {
|
||||
var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width;
|
||||
if (el.tagName === 'IMG') {
|
||||
height = el.height, width = el.width;
|
||||
if (height > QR.max_height || width > QR.max_width) {
|
||||
this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)");
|
||||
}
|
||||
if (height < QR.min_height || width < QR.min_width) {
|
||||
return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
}
|
||||
} else {
|
||||
return this.nodes.el.style.backgroundImage = null;
|
||||
videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration;
|
||||
max_height = Math.min(QR.max_height, QR.max_height_video);
|
||||
max_width = Math.min(QR.max_width, QR.max_width_video);
|
||||
if (videoHeight > max_height || videoWidth > max_width) {
|
||||
this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
|
||||
}
|
||||
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
|
||||
this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
}
|
||||
if (!isFinite(duration)) {
|
||||
this.fileError('Video lacks duration metadata (try remuxing)');
|
||||
} else if (duration > QR.max_duration_video) {
|
||||
this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
|
||||
}
|
||||
if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) {
|
||||
return this.fileError('Audio not allowed');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -8866,23 +8876,26 @@
|
||||
delete this.filename;
|
||||
delete this.filesize;
|
||||
this.nodes.el.title = null;
|
||||
QR.nodes.fileContainer.title = '';
|
||||
QR.nodes.filename.title = '';
|
||||
this.nodes.el.style.backgroundImage = null;
|
||||
if (QR.spoiler) {
|
||||
this.nodes.label.hidden = true;
|
||||
}
|
||||
this.showFileData();
|
||||
return URL.revokeObjectURL(this.URL);
|
||||
URL.revokeObjectURL(this.URL);
|
||||
return this.dismissErrors(function(error) {
|
||||
return $.hasClass(error, 'file-error');
|
||||
});
|
||||
};
|
||||
|
||||
_Class.prototype.updateFilename = function() {
|
||||
var long;
|
||||
long = this.filename + " (" + this.filesize + ")\nCtrl/\u2318+click to edit filename. Shift+click to clear.";
|
||||
long = this.filename + " (" + this.filesize + ")";
|
||||
this.nodes.el.title = long;
|
||||
if (this !== QR.selected) {
|
||||
return;
|
||||
}
|
||||
return QR.nodes.fileContainer.title = long;
|
||||
return QR.nodes.filename.title = long;
|
||||
};
|
||||
|
||||
_Class.prototype.showFileData = function() {
|
||||
@ -8898,6 +8911,7 @@
|
||||
|
||||
_Class.prototype.pasteText = function(file) {
|
||||
var reader;
|
||||
this.pasting = true;
|
||||
reader = new FileReader();
|
||||
reader.onload = (function(_this) {
|
||||
return function(e) {
|
||||
@ -8911,7 +8925,8 @@
|
||||
if (QR.selected === _this) {
|
||||
QR.nodes.com.value = _this.com;
|
||||
}
|
||||
return _this.nodes.span.textContent = _this.com;
|
||||
_this.nodes.span.textContent = _this.com;
|
||||
return delete _this.pasting;
|
||||
};
|
||||
})(this);
|
||||
return reader.readAsText(file);
|
||||
@ -10166,7 +10181,7 @@
|
||||
$.on(this.el, 'change', this.toggle);
|
||||
return Header.menu.addEntry({
|
||||
el: prefetch,
|
||||
order: 104
|
||||
order: 98
|
||||
});
|
||||
},
|
||||
node: function() {
|
||||
@ -17020,9 +17035,6 @@
|
||||
"body.hasDropDownNav{\n" +
|
||||
" margin-top: 5px;\n" +
|
||||
"}\n" +
|
||||
"a {\n" +
|
||||
" outline: none !important;\n" +
|
||||
"}\n" +
|
||||
".painted {\n" +
|
||||
" border-radius: 3px;\n" +
|
||||
" padding: 0px 2px;\n" +
|
||||
@ -17667,7 +17679,7 @@
|
||||
" text-align: center;\n" +
|
||||
"}\n" +
|
||||
"/* /tg/ dice rolls */\n" +
|
||||
".catalog-thread > .comment > b {\n" +
|
||||
".board_tg .catalog-thread > .comment > b {\n" +
|
||||
" font-weight: normal;\n" +
|
||||
"}\n" +
|
||||
".catalog-code {\n" +
|
||||
@ -18118,17 +18130,6 @@
|
||||
" -webkit-flex-direction: row;\n" +
|
||||
" flex-direction: row;\n" +
|
||||
"}\n" +
|
||||
"#url-button, #custom-cooldown-button, #dump-button {\n" +
|
||||
" width: 10%;\n" +
|
||||
" margin: 0;\n" +
|
||||
" margin-right: 4px;\n" +
|
||||
" font: 13px sans-serif;\n" +
|
||||
" padding: 1px 0px 2px;\n" +
|
||||
" opacity: 0.6;\n" +
|
||||
"}\n" +
|
||||
"#custom-cooldown-button.disabled {\n" +
|
||||
" opacity: 0.27;\n" +
|
||||
"}\n" +
|
||||
".persona .field {\n" +
|
||||
" -webkit-flex: 1;\n" +
|
||||
" flex: 1;\n" +
|
||||
@ -18151,8 +18152,18 @@
|
||||
" text-shadow: none !important;\n" +
|
||||
"}\n" +
|
||||
"#qr textarea {\n" +
|
||||
" min-width: 100%;\n" +
|
||||
" resize: both;\n" +
|
||||
"}\n" +
|
||||
".field {\n" +
|
||||
" -moz-box-sizing: border-box;\n" +
|
||||
" margin: 0px;\n" +
|
||||
" padding: 2px 4px 3px;\n" +
|
||||
"}\n" +
|
||||
"#qr label input[type=\"checkbox\"] {\n" +
|
||||
" position: relative;\n" +
|
||||
" top: 2px;\n" +
|
||||
"}\n" +
|
||||
"/* Noscript Recaptcha */\n" +
|
||||
".captcha-img {\n" +
|
||||
" margin: 0px;\n" +
|
||||
@ -18196,111 +18207,81 @@
|
||||
" display: block;\n" +
|
||||
" width: 100%;\n" +
|
||||
"}\n" +
|
||||
".field {\n" +
|
||||
" -moz-box-sizing: border-box;\n" +
|
||||
" margin: 0px;\n" +
|
||||
" padding: 2px 4px 3px;\n" +
|
||||
"/* File Input, Submit Button */\n" +
|
||||
"#file-n-submit {\n" +
|
||||
" display: -webkit-flex;\n" +
|
||||
" display: flex;\n" +
|
||||
" -webkit-align-items: stretch;\n" +
|
||||
" align-items: stretch;\n" +
|
||||
" margin-top: 1px;\n" +
|
||||
"}\n" +
|
||||
"#qr textarea {\n" +
|
||||
" min-width: 100%;\n" +
|
||||
":root.gecko #file-n-submit > input {\n" +
|
||||
" margin: 0px -1px -1px;\n" +
|
||||
"}\n" +
|
||||
"#qr [type=\"submit\"] {\n" +
|
||||
"#file-n-submit input[type=\"submit\"] {\n" +
|
||||
" width: 25%;\n" +
|
||||
" vertical-align: top;\n" +
|
||||
"}\n" +
|
||||
":root.webkit #qr [type=\"submit\"] {\n" +
|
||||
" height: 24px;\n" +
|
||||
"}\n" +
|
||||
"#qr label input[type=\"checkbox\"] {\n" +
|
||||
"#qr-filename-container {\n" +
|
||||
" -webkit-flex: 1 1 auto;\n" +
|
||||
" flex: 1 1 auto;\n" +
|
||||
" width: 0;\n" +
|
||||
" display: -webkit-flex;\n" +
|
||||
" display: flex;\n" +
|
||||
" -webkit-align-items: center;\n" +
|
||||
" align-items: center;\n" +
|
||||
" position: relative;\n" +
|
||||
" top: 2px;\n" +
|
||||
" padding: 1px;\n" +
|
||||
"}\n" +
|
||||
"/* Fake File Input */\n" +
|
||||
"input#qr-filename {\n" +
|
||||
" border: none !important;\n" +
|
||||
" width: 80%;\n" +
|
||||
" padding: 0px 4px;\n" +
|
||||
" position: relative;\n" +
|
||||
" bottom: 1px;\n" +
|
||||
" background: none !important;\n" +
|
||||
"}\n" +
|
||||
"input#qr-filename:not(.edit) {\n" +
|
||||
" pointer-events: none;\n" +
|
||||
"}\n" +
|
||||
"#qr-filename,\n" +
|
||||
"#qr-filesize,\n" +
|
||||
".has-file #qr-no-file {\n" +
|
||||
" display: none;\n" +
|
||||
"}\n" +
|
||||
"#qr-no-file,\n" +
|
||||
".has-file #qr-filename,\n" +
|
||||
".has-file #qr-filesize {\n" +
|
||||
".has-file #qr-filename {\n" +
|
||||
" -webkit-flex: 1 1 auto;\n" +
|
||||
" flex: 1 1 auto;\n" +
|
||||
" display: inline-block;\n" +
|
||||
" margin: 0 0 2px;\n" +
|
||||
" padding: 0;\n" +
|
||||
" padding-left: 3px;\n" +
|
||||
" overflow: hidden;\n" +
|
||||
" text-overflow: ellipsis;\n" +
|
||||
" vertical-align: top;\n" +
|
||||
"}\n" +
|
||||
"#qr-no-file {\n" +
|
||||
" color: #AAA;\n" +
|
||||
" padding: 1px 4px;\n" +
|
||||
"}\n" +
|
||||
"#qr-filename-container {\n" +
|
||||
" -moz-box-sizing: border-box;\n" +
|
||||
" display: inline-block;\n" +
|
||||
" position: relative;\n" +
|
||||
" width: 100px;\n" +
|
||||
" min-width: 74.6%;\n" +
|
||||
" max-width: 74.6%;\n" +
|
||||
" margin-right: 0.4%;\n" +
|
||||
" margin-top: 1px;\n" +
|
||||
" overflow: hidden;\n" +
|
||||
" padding: 2px 1px 0;\n" +
|
||||
" height: 22px;\n" +
|
||||
"}\n" +
|
||||
"#qr-filename-container:hover {\n" +
|
||||
" cursor: text;\n" +
|
||||
"}\n" +
|
||||
"#qr-extras-container {\n" +
|
||||
" position: absolute;\n" +
|
||||
" right: 0px;\n" +
|
||||
"}\n" +
|
||||
"#qr-filerm {\n" +
|
||||
" margin-right: 3px;\n" +
|
||||
" z-index: 2;\n" +
|
||||
"}\n" +
|
||||
"#file-n-submit {\n" +
|
||||
" height: 23px;\n" +
|
||||
"}\n" +
|
||||
"#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
|
||||
" display: none;\n" +
|
||||
"}\n" +
|
||||
"#qr input[type=\"file\"] {\n" +
|
||||
" visibility: hidden;\n" +
|
||||
" position: absolute;\n" +
|
||||
"}\n" +
|
||||
"/* Thread Select / Spoiler Label */\n" +
|
||||
"#qr select[data-name=\"thread\"] {\n" +
|
||||
" float: right;\n" +
|
||||
"/* Spoiler Checkbox, QR Icons */\n" +
|
||||
"#qr-spoiler-label, #qr-filename-container > a {\n" +
|
||||
" -webkit-flex: none;\n" +
|
||||
" flex: none;\n" +
|
||||
" margin: 0;\n" +
|
||||
" margin-right: 3px;\n" +
|
||||
" font: 13px sans-serif;\n" +
|
||||
"}\n" +
|
||||
"#qr.has-spoiler .has-file #qr-spoiler-label {\n" +
|
||||
" width: 6.7%;\n" +
|
||||
" min-width: 6.7%;\n" +
|
||||
" max-width: 6.7%;\n" +
|
||||
" display: inline-block;\n" +
|
||||
" text-align: center;\n" +
|
||||
" vertical-align: top;\n" +
|
||||
"}\n" +
|
||||
"#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\n" +
|
||||
"#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label,\n" +
|
||||
".has-file #url-button,\n" +
|
||||
"#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
|
||||
" display: none;\n" +
|
||||
"}\n" +
|
||||
"#qr.has-spoiler .has-file #qr-filename-container {\n" +
|
||||
" max-width: 67.9%;\n" +
|
||||
" min-width: 67.9%;\n" +
|
||||
"#qr-file-spoiler {\n" +
|
||||
" margin: 0;\n" +
|
||||
"}\n" +
|
||||
"#qr-spoiler-label input {\n" +
|
||||
" position: relative;\n" +
|
||||
" top: 3px;\n" +
|
||||
"#url-button, #custom-cooldown-button, #dump-button {\n" +
|
||||
" opacity: 0.6;\n" +
|
||||
"}\n" +
|
||||
"#custom-cooldown-button.disabled {\n" +
|
||||
" opacity: 0.27;\n" +
|
||||
"}\n" +
|
||||
"/* Thread Select */\n" +
|
||||
"#qr select[data-name=\"thread\"] {\n" +
|
||||
" float: right;\n" +
|
||||
"}\n" +
|
||||
"/* Dumping UI */\n" +
|
||||
".dump #dump-list-container {\n" +
|
||||
|
||||
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
// Generated by CoffeeScript
|
||||
// ==UserScript==
|
||||
// @name 4chan X
|
||||
// @version 1.10.2.8
|
||||
// @version 1.10.3.0
|
||||
// @minGMVer 1.14
|
||||
// @minFFVer 26
|
||||
// @namespace 4chan-X
|
||||
@ -392,7 +392,7 @@
|
||||
doc = d.documentElement;
|
||||
|
||||
g = {
|
||||
VERSION: '1.10.2.8',
|
||||
VERSION: '1.10.3.0',
|
||||
NAMESPACE: '4chan X.',
|
||||
NAME: '4chan X',
|
||||
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
|
||||
@ -3065,7 +3065,7 @@
|
||||
el: $.el('span', {
|
||||
textContent: 'Index Navigation'
|
||||
}),
|
||||
order: 98,
|
||||
order: 100,
|
||||
subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry]
|
||||
});
|
||||
$.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode");
|
||||
@ -6391,7 +6391,7 @@
|
||||
$.on(this.threadNewLink.firstElementChild, 'click', this.rethread);
|
||||
Header.menu.addEntry(this.entry = {
|
||||
el: this.controls,
|
||||
order: 98
|
||||
order: 99
|
||||
});
|
||||
Thread.callbacks.push({
|
||||
name: 'Quote Threading',
|
||||
@ -7168,6 +7168,7 @@
|
||||
if (url === null) {
|
||||
return;
|
||||
}
|
||||
QR.nodes.fileButton.focus();
|
||||
return CrossOrigin.file(url, function(blob) {
|
||||
if (blob) {
|
||||
return QR.handleFiles([blob]);
|
||||
@ -7177,7 +7178,7 @@
|
||||
});
|
||||
},
|
||||
handleFiles: function(files) {
|
||||
var file, i, k, len1;
|
||||
var file, k, len1;
|
||||
if (this !== QR) {
|
||||
files = slice.call(this.files);
|
||||
this.value = null;
|
||||
@ -7186,147 +7187,36 @@
|
||||
return;
|
||||
}
|
||||
QR.cleanNotifications();
|
||||
for (i = k = 0, len1 = files.length; k < len1; i = ++k) {
|
||||
file = files[i];
|
||||
QR.handleFile(file, i, files.length);
|
||||
for (k = 0, len1 = files.length; k < len1; k++) {
|
||||
file = files[k];
|
||||
QR.handleFile(file, files.length);
|
||||
}
|
||||
if (files.length !== 1) {
|
||||
return $.addClass(QR.nodes.el, 'dump');
|
||||
$.addClass(QR.nodes.el, 'dump');
|
||||
}
|
||||
if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) {
|
||||
return QR.nodes.filename.focus();
|
||||
}
|
||||
},
|
||||
handleFile: function(file, index, nfiles) {
|
||||
var isNewPost, isSingle, max, post, ref;
|
||||
isSingle = nfiles === 1;
|
||||
if (/^text\//.test(file.type)) {
|
||||
if (isSingle) {
|
||||
post = QR.selected;
|
||||
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) {
|
||||
handleFile: function(file, nfiles) {
|
||||
var isText, post;
|
||||
isText = /^text\//.test(file.type);
|
||||
if (nfiles === 1) {
|
||||
post = QR.selected;
|
||||
} else {
|
||||
post = QR.posts[QR.posts.length - 1];
|
||||
if ((isText ? post.com || post.pasting : post.file)) {
|
||||
post = new QR.post();
|
||||
}
|
||||
post.pasteText(file);
|
||||
}
|
||||
return post[isText ? 'pasteText' : 'setFile'](file);
|
||||
},
|
||||
openFileInput: function() {
|
||||
if (QR.nodes.fileButton.disabled) {
|
||||
return;
|
||||
}
|
||||
if (ref = file.type, indexOf.call(QR.mimeTypes, ref) < 0) {
|
||||
QR.error(file.name + ": Unsupported file type.");
|
||||
if (!isSingle) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
max = QR.nodes.fileInput.max;
|
||||
if (/^video\//.test(file.type)) {
|
||||
max = Math.min(max, QR.max_size_video);
|
||||
}
|
||||
if (file.size > max) {
|
||||
QR.error(file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ").");
|
||||
if (!isSingle) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
isNewPost = false;
|
||||
if (isSingle) {
|
||||
post = QR.selected;
|
||||
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) {
|
||||
isNewPost = true;
|
||||
post = new QR.post();
|
||||
}
|
||||
return QR.checkDimensions(file, function(pass, el) {
|
||||
if (pass || isSingle) {
|
||||
return post.setFile(file, el);
|
||||
} else if (isNewPost) {
|
||||
post.rm();
|
||||
if (el) {
|
||||
return URL.revokeObjectURL(el.src);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
checkDimensions: function(file, cb) {
|
||||
var img, video;
|
||||
if (/^image\//.test(file.type)) {
|
||||
img = new Image();
|
||||
img.onload = function() {
|
||||
var height, pass, width;
|
||||
height = img.height, width = img.width;
|
||||
pass = true;
|
||||
if (height > QR.max_height || width > QR.max_width) {
|
||||
QR.error(file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
if (height < QR.min_height || width < QR.min_width) {
|
||||
QR.error(file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
return cb(pass, img);
|
||||
};
|
||||
img.onerror = function() {
|
||||
return cb(false, null);
|
||||
};
|
||||
return img.src = URL.createObjectURL(file);
|
||||
} else if (/^video\//.test(file.type)) {
|
||||
video = $.el('video');
|
||||
$.on(video, 'loadeddata', function() {
|
||||
var duration, max_height, max_width, pass, ref, videoHeight, videoWidth;
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
videoHeight = video.videoHeight, videoWidth = video.videoWidth, duration = video.duration;
|
||||
max_height = Math.min(QR.max_height, QR.max_height_video);
|
||||
max_width = Math.min(QR.max_width, QR.max_width_video);
|
||||
pass = true;
|
||||
if (videoHeight > max_height || videoWidth > max_width) {
|
||||
QR.error(file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
|
||||
QR.error(file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
if (!isFinite(duration)) {
|
||||
QR.error(file.name + ": Video lacks duration metadata (try remuxing)");
|
||||
pass = false;
|
||||
} else if (duration > QR.max_duration_video) {
|
||||
QR.error(file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
|
||||
pass = false;
|
||||
}
|
||||
if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(video)) {
|
||||
QR.error(file.name + ": Audio not allowed");
|
||||
pass = false;
|
||||
}
|
||||
cb(pass, video);
|
||||
return cb = null;
|
||||
});
|
||||
$.on(video, 'error', function() {
|
||||
var ref;
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
if (ref = file.type, indexOf.call(QR.mimeTypes, ref) >= 0) {
|
||||
QR.error(file.name + ": Video appears corrupt");
|
||||
}
|
||||
URL.revokeObjectURL(file);
|
||||
cb(false, null);
|
||||
return cb = null;
|
||||
});
|
||||
return video.src = URL.createObjectURL(file);
|
||||
} else {
|
||||
return cb(true, null);
|
||||
}
|
||||
},
|
||||
openFileInput: function(e) {
|
||||
var ref;
|
||||
e.stopPropagation();
|
||||
if (e.shiftKey && e.type === 'click') {
|
||||
return QR.selected.rmFile();
|
||||
}
|
||||
if ((e.ctrlKey || e.metaKey) && e.type === 'click') {
|
||||
$.addClass(QR.nodes.filename, 'edit');
|
||||
QR.nodes.filename.focus();
|
||||
}
|
||||
if (e.target.nodeName === 'INPUT' || (e.keyCode && ((ref = e.keyCode) !== 32 && ref !== 13)) || e.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
return QR.nodes.fileInput.click();
|
||||
QR.nodes.fileInput.click();
|
||||
return QR.nodes.fileButton.focus();
|
||||
},
|
||||
generatePostableThreadsList: function() {
|
||||
var k, len1, list, options, ref, thread, val;
|
||||
@ -7357,7 +7247,7 @@
|
||||
var dialog, event, i, items, m, match_max, match_min, name, node, nodes, ref, rules, save, setNode;
|
||||
QR.nodes = nodes = {
|
||||
el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', {
|
||||
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=file-n-submit><span id=qr-filename-container class=field tabindex=0><span id=qr-no-file>No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><span id=\"qr-extras-container\"><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span></span><label id=qr-spoiler-label><input type=checkbox id=qr-file-spoiler title='Spoiler image'></label><input type=submit></div><input type=file multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
|
||||
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=\"file-n-submit\"><input type=\"button\" id=\"qr-file-button\" value=\"Files\"><span id=\"qr-filename-container\" class=\"field\"><span id=\"qr-no-file\">No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><label id=\"qr-spoiler-label\"><input type=\"checkbox\" id=\"qr-file-spoiler\" title=\"Spoiler image\"></label><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span><input type=\"submit\"></div><input type=\"file\" multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
|
||||
})
|
||||
};
|
||||
setNode = function(name, query) {
|
||||
@ -7379,10 +7269,10 @@
|
||||
setNode('addPost', '#add-post');
|
||||
setNode('charCount', '#char-count');
|
||||
setNode('fileSubmit', '#file-n-submit');
|
||||
setNode('fileButton', '#qr-file-button');
|
||||
setNode('noFile', '#qr-no-file');
|
||||
setNode('filename', '#qr-filename');
|
||||
setNode('fileContainer', '#qr-filename-container');
|
||||
setNode('fileRM', '#qr-filerm');
|
||||
setNode('fileExtras', '#qr-extras-container');
|
||||
setNode('spoiler', '#qr-file-spoiler');
|
||||
setNode('spoilerPar', '#qr-spoiler-label');
|
||||
setNode('status', '[type=submit]');
|
||||
@ -7436,7 +7326,8 @@
|
||||
nodes.flashTag.dataset["default"] = '4';
|
||||
$.add(nodes.form, nodes.flashTag);
|
||||
}
|
||||
$.on(nodes.filename.parentNode, 'click keydown', QR.openFileInput);
|
||||
$.on(nodes.fileButton, 'click', QR.openFileInput);
|
||||
$.on(nodes.noFile, 'click', QR.openFileInput);
|
||||
$.on(nodes.autohide, 'change', QR.toggleHide);
|
||||
$.on(nodes.close, 'click', QR.close);
|
||||
$.on(nodes.dumpButton, 'click', function() {
|
||||
@ -7447,15 +7338,9 @@
|
||||
return new QR.post(true);
|
||||
});
|
||||
$.on(nodes.form, 'submit', QR.submit);
|
||||
$.on(nodes.filename, 'blur', function() {
|
||||
return $.rmClass(this, 'edit');
|
||||
});
|
||||
$.on(nodes.fileRM, 'click', function() {
|
||||
return QR.selected.rmFile();
|
||||
});
|
||||
$.on(nodes.fileExtras, 'click', function(e) {
|
||||
return e.stopPropagation();
|
||||
});
|
||||
$.on(nodes.spoiler, 'change', function() {
|
||||
return QR.selected.nodes.spoiler.click();
|
||||
});
|
||||
@ -7625,7 +7510,7 @@
|
||||
return QR.status();
|
||||
},
|
||||
response: function() {
|
||||
var URL, _, ban, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, ref, ref1, req, resDoc, threadID;
|
||||
var URL, _, ban, err, h1, isReply, m, post, postID, postsCount, ref, ref1, req, resDoc, threadID;
|
||||
req = QR.req;
|
||||
delete QR.req;
|
||||
post = QR.posts[0];
|
||||
@ -7695,22 +7580,6 @@
|
||||
});
|
||||
postsCount = QR.posts.length - 1;
|
||||
QR.cooldown.auto = postsCount && isReply;
|
||||
if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) {
|
||||
notif = new Notification('Quick reply warning', {
|
||||
body: "You are running low on cached captchas. Cache count: " + captchasCount + ".",
|
||||
icon: Favicon.logo
|
||||
});
|
||||
notif.onclick = function() {
|
||||
QR.open();
|
||||
window.focus();
|
||||
return QR.captcha.setup(true);
|
||||
};
|
||||
notif.onshow = function() {
|
||||
return setTimeout(function() {
|
||||
return notif.close();
|
||||
}, 7 * $.SECOND);
|
||||
};
|
||||
}
|
||||
if (!(Conf['Persistent QR'] || postsCount)) {
|
||||
QR.close();
|
||||
} else {
|
||||
@ -8118,7 +7987,7 @@
|
||||
return $.on(window, 'focus', function() {
|
||||
return $.queueTask(function() {
|
||||
var checkbox;
|
||||
if (!(checkbox = $.id('recaptcha-anchor'))) {
|
||||
if (!(d.hasFocus() && (checkbox = $.id('recaptcha-anchor')))) {
|
||||
return;
|
||||
}
|
||||
if (d.activeElement !== checkbox) {
|
||||
@ -8165,7 +8034,6 @@
|
||||
if (!(this.isEnabled && (this.needed() || force))) {
|
||||
return;
|
||||
}
|
||||
$.addClass(QR.nodes.el, 'captcha-open');
|
||||
if (focus) {
|
||||
this.shouldFocus = true;
|
||||
}
|
||||
@ -8209,6 +8077,7 @@
|
||||
},
|
||||
setupIFrame: function(iframe) {
|
||||
this.setupTime = Date.now();
|
||||
$.addClass(QR.nodes.el, 'captcha-open');
|
||||
if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
|
||||
QR.nodes.el.style.top = null;
|
||||
QR.nodes.el.style.bottom = '0px';
|
||||
@ -8692,7 +8561,8 @@
|
||||
|
||||
_Class.prototype["delete"] = function() {
|
||||
$.rm(this.nodes.el);
|
||||
return URL.revokeObjectURL(this.URL);
|
||||
URL.revokeObjectURL(this.URL);
|
||||
return this.dismissErrors();
|
||||
};
|
||||
|
||||
_Class.prototype.lock = function(lock) {
|
||||
@ -8712,7 +8582,6 @@
|
||||
}
|
||||
}
|
||||
this.nodes.rm.style.visibility = lock ? 'hidden' : '';
|
||||
(lock ? $.off : $.on)(QR.nodes.filename.previousElementSibling, 'click', QR.openFileInput);
|
||||
this.nodes.spoiler.disabled = lock;
|
||||
return this.nodes.el.draggable = !lock;
|
||||
};
|
||||
@ -8798,10 +8667,82 @@
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.setFile = function(file1, el) {
|
||||
_Class.rmErrored = function(e) {
|
||||
var error, errors, k, len1, post, q, ref;
|
||||
e.stopPropagation();
|
||||
ref = QR.posts;
|
||||
for (k = ref.length - 1; k >= 0; k += -1) {
|
||||
post = ref[k];
|
||||
if (errors = post.errors) {
|
||||
for (q = 0, len1 = errors.length; q < len1; q++) {
|
||||
error = errors[q];
|
||||
if (!(doc.contains(error))) {
|
||||
continue;
|
||||
}
|
||||
post.rm();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.error = function(className, message) {
|
||||
var div, ref, rm, rmAll;
|
||||
div = $.el('div', {
|
||||
className: className
|
||||
});
|
||||
$.extend(div, {
|
||||
innerHTML: E(message) + "<br>[<a href=\"javascript:;\">delete</a>] [<a href=\"javascript:;\">delete all</a>]"
|
||||
});
|
||||
(this.errors || (this.errors = [])).push(div);
|
||||
ref = $$('a', div), rm = ref[0], rmAll = ref[1];
|
||||
$.on(div, 'click', (function(_this) {
|
||||
return function() {
|
||||
if (indexOf.call(QR.posts, _this) >= 0) {
|
||||
return _this.select();
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
$.on(rm, 'click', (function(_this) {
|
||||
return function(e) {
|
||||
e.stopPropagation();
|
||||
if (indexOf.call(QR.posts, _this) >= 0) {
|
||||
return _this.rm();
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
$.on(rmAll, 'click', QR.post.rmErrored);
|
||||
return QR.error(div);
|
||||
};
|
||||
|
||||
_Class.prototype.fileError = function(message) {
|
||||
return this.error('file-error', this.filename + ": " + message);
|
||||
};
|
||||
|
||||
_Class.prototype.dismissErrors = function(test) {
|
||||
var error, k, len1, ref;
|
||||
if (test == null) {
|
||||
test = function() {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
if (this.errors) {
|
||||
ref = this.errors;
|
||||
for (k = 0, len1 = ref.length; k < len1; k++) {
|
||||
error = ref[k];
|
||||
if (doc.contains(error) && test(error)) {
|
||||
error.parentNode.previousElementSibling.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.setFile = function(file1) {
|
||||
var ref;
|
||||
this.file = file1;
|
||||
this.filename = this.file.name;
|
||||
this.filesize = $.bytesToString(this.file.size);
|
||||
this.checkSize();
|
||||
if (QR.spoiler) {
|
||||
this.nodes.label.hidden = false;
|
||||
}
|
||||
@ -8812,10 +8753,79 @@
|
||||
} else {
|
||||
this.updateFilename();
|
||||
}
|
||||
if (el) {
|
||||
return this.setThumbnail(el);
|
||||
this.nodes.el.style.backgroundImage = null;
|
||||
if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) {
|
||||
return this.fileError('Unsupported file type.');
|
||||
} else if (/^(image|video)\//.test(this.file.type)) {
|
||||
return this.readFile();
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.checkSize = function() {
|
||||
var max;
|
||||
max = QR.nodes.fileInput.max;
|
||||
if (/^video\//.test(this.file.type)) {
|
||||
max = Math.min(max, QR.max_size_video);
|
||||
}
|
||||
if (this.file.size > max) {
|
||||
return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ").");
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.readFile = function() {
|
||||
var el, event, isVideo, onerror, onload;
|
||||
isVideo = /^video\//.test(this.file.type);
|
||||
el = $.el(isVideo ? 'video' : 'img');
|
||||
event = isVideo ? 'loadeddata' : 'load';
|
||||
onload = (function(_this) {
|
||||
return function() {
|
||||
$.off(el, event, onload);
|
||||
$.off(el, 'error', onerror);
|
||||
_this.checkDimensions(el);
|
||||
return _this.setThumbnail(el);
|
||||
};
|
||||
})(this);
|
||||
onerror = (function(_this) {
|
||||
return function() {
|
||||
$.off(el, event, onload);
|
||||
$.off(el, 'error', onerror);
|
||||
_this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt");
|
||||
return URL.revokeObjectURL(el.src);
|
||||
};
|
||||
})(this);
|
||||
$.on(el, event, onload);
|
||||
$.on(el, 'error', onerror);
|
||||
return el.src = URL.createObjectURL(this.file);
|
||||
};
|
||||
|
||||
_Class.prototype.checkDimensions = function(el) {
|
||||
var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width;
|
||||
if (el.tagName === 'IMG') {
|
||||
height = el.height, width = el.width;
|
||||
if (height > QR.max_height || width > QR.max_width) {
|
||||
this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)");
|
||||
}
|
||||
if (height < QR.min_height || width < QR.min_width) {
|
||||
return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
}
|
||||
} else {
|
||||
return this.nodes.el.style.backgroundImage = null;
|
||||
videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration;
|
||||
max_height = Math.min(QR.max_height, QR.max_height_video);
|
||||
max_width = Math.min(QR.max_width, QR.max_width_video);
|
||||
if (videoHeight > max_height || videoWidth > max_width) {
|
||||
this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
|
||||
}
|
||||
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
|
||||
this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
}
|
||||
if (!isFinite(duration)) {
|
||||
this.fileError('Video lacks duration metadata (try remuxing)');
|
||||
} else if (duration > QR.max_duration_video) {
|
||||
this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
|
||||
}
|
||||
if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) {
|
||||
return this.fileError('Audio not allowed');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -8865,23 +8875,26 @@
|
||||
delete this.filename;
|
||||
delete this.filesize;
|
||||
this.nodes.el.title = null;
|
||||
QR.nodes.fileContainer.title = '';
|
||||
QR.nodes.filename.title = '';
|
||||
this.nodes.el.style.backgroundImage = null;
|
||||
if (QR.spoiler) {
|
||||
this.nodes.label.hidden = true;
|
||||
}
|
||||
this.showFileData();
|
||||
return URL.revokeObjectURL(this.URL);
|
||||
URL.revokeObjectURL(this.URL);
|
||||
return this.dismissErrors(function(error) {
|
||||
return $.hasClass(error, 'file-error');
|
||||
});
|
||||
};
|
||||
|
||||
_Class.prototype.updateFilename = function() {
|
||||
var long;
|
||||
long = this.filename + " (" + this.filesize + ")\nCtrl/\u2318+click to edit filename. Shift+click to clear.";
|
||||
long = this.filename + " (" + this.filesize + ")";
|
||||
this.nodes.el.title = long;
|
||||
if (this !== QR.selected) {
|
||||
return;
|
||||
}
|
||||
return QR.nodes.fileContainer.title = long;
|
||||
return QR.nodes.filename.title = long;
|
||||
};
|
||||
|
||||
_Class.prototype.showFileData = function() {
|
||||
@ -8897,6 +8910,7 @@
|
||||
|
||||
_Class.prototype.pasteText = function(file) {
|
||||
var reader;
|
||||
this.pasting = true;
|
||||
reader = new FileReader();
|
||||
reader.onload = (function(_this) {
|
||||
return function(e) {
|
||||
@ -8910,7 +8924,8 @@
|
||||
if (QR.selected === _this) {
|
||||
QR.nodes.com.value = _this.com;
|
||||
}
|
||||
return _this.nodes.span.textContent = _this.com;
|
||||
_this.nodes.span.textContent = _this.com;
|
||||
return delete _this.pasting;
|
||||
};
|
||||
})(this);
|
||||
return reader.readAsText(file);
|
||||
@ -10165,7 +10180,7 @@
|
||||
$.on(this.el, 'change', this.toggle);
|
||||
return Header.menu.addEntry({
|
||||
el: prefetch,
|
||||
order: 104
|
||||
order: 98
|
||||
});
|
||||
},
|
||||
node: function() {
|
||||
@ -17019,9 +17034,6 @@
|
||||
"body.hasDropDownNav{\n" +
|
||||
" margin-top: 5px;\n" +
|
||||
"}\n" +
|
||||
"a {\n" +
|
||||
" outline: none !important;\n" +
|
||||
"}\n" +
|
||||
".painted {\n" +
|
||||
" border-radius: 3px;\n" +
|
||||
" padding: 0px 2px;\n" +
|
||||
@ -17666,7 +17678,7 @@
|
||||
" text-align: center;\n" +
|
||||
"}\n" +
|
||||
"/* /tg/ dice rolls */\n" +
|
||||
".catalog-thread > .comment > b {\n" +
|
||||
".board_tg .catalog-thread > .comment > b {\n" +
|
||||
" font-weight: normal;\n" +
|
||||
"}\n" +
|
||||
".catalog-code {\n" +
|
||||
@ -18117,17 +18129,6 @@
|
||||
" -webkit-flex-direction: row;\n" +
|
||||
" flex-direction: row;\n" +
|
||||
"}\n" +
|
||||
"#url-button, #custom-cooldown-button, #dump-button {\n" +
|
||||
" width: 10%;\n" +
|
||||
" margin: 0;\n" +
|
||||
" margin-right: 4px;\n" +
|
||||
" font: 13px sans-serif;\n" +
|
||||
" padding: 1px 0px 2px;\n" +
|
||||
" opacity: 0.6;\n" +
|
||||
"}\n" +
|
||||
"#custom-cooldown-button.disabled {\n" +
|
||||
" opacity: 0.27;\n" +
|
||||
"}\n" +
|
||||
".persona .field {\n" +
|
||||
" -webkit-flex: 1;\n" +
|
||||
" flex: 1;\n" +
|
||||
@ -18150,8 +18151,18 @@
|
||||
" text-shadow: none !important;\n" +
|
||||
"}\n" +
|
||||
"#qr textarea {\n" +
|
||||
" min-width: 100%;\n" +
|
||||
" resize: both;\n" +
|
||||
"}\n" +
|
||||
".field {\n" +
|
||||
" -moz-box-sizing: border-box;\n" +
|
||||
" margin: 0px;\n" +
|
||||
" padding: 2px 4px 3px;\n" +
|
||||
"}\n" +
|
||||
"#qr label input[type=\"checkbox\"] {\n" +
|
||||
" position: relative;\n" +
|
||||
" top: 2px;\n" +
|
||||
"}\n" +
|
||||
"/* Noscript Recaptcha */\n" +
|
||||
".captcha-img {\n" +
|
||||
" margin: 0px;\n" +
|
||||
@ -18195,111 +18206,81 @@
|
||||
" display: block;\n" +
|
||||
" width: 100%;\n" +
|
||||
"}\n" +
|
||||
".field {\n" +
|
||||
" -moz-box-sizing: border-box;\n" +
|
||||
" margin: 0px;\n" +
|
||||
" padding: 2px 4px 3px;\n" +
|
||||
"/* File Input, Submit Button */\n" +
|
||||
"#file-n-submit {\n" +
|
||||
" display: -webkit-flex;\n" +
|
||||
" display: flex;\n" +
|
||||
" -webkit-align-items: stretch;\n" +
|
||||
" align-items: stretch;\n" +
|
||||
" margin-top: 1px;\n" +
|
||||
"}\n" +
|
||||
"#qr textarea {\n" +
|
||||
" min-width: 100%;\n" +
|
||||
":root.gecko #file-n-submit > input {\n" +
|
||||
" margin: 0px -1px -1px;\n" +
|
||||
"}\n" +
|
||||
"#qr [type=\"submit\"] {\n" +
|
||||
"#file-n-submit input[type=\"submit\"] {\n" +
|
||||
" width: 25%;\n" +
|
||||
" vertical-align: top;\n" +
|
||||
"}\n" +
|
||||
":root.webkit #qr [type=\"submit\"] {\n" +
|
||||
" height: 24px;\n" +
|
||||
"}\n" +
|
||||
"#qr label input[type=\"checkbox\"] {\n" +
|
||||
"#qr-filename-container {\n" +
|
||||
" -webkit-flex: 1 1 auto;\n" +
|
||||
" flex: 1 1 auto;\n" +
|
||||
" width: 0;\n" +
|
||||
" display: -webkit-flex;\n" +
|
||||
" display: flex;\n" +
|
||||
" -webkit-align-items: center;\n" +
|
||||
" align-items: center;\n" +
|
||||
" position: relative;\n" +
|
||||
" top: 2px;\n" +
|
||||
" padding: 1px;\n" +
|
||||
"}\n" +
|
||||
"/* Fake File Input */\n" +
|
||||
"input#qr-filename {\n" +
|
||||
" border: none !important;\n" +
|
||||
" width: 80%;\n" +
|
||||
" padding: 0px 4px;\n" +
|
||||
" position: relative;\n" +
|
||||
" bottom: 1px;\n" +
|
||||
" background: none !important;\n" +
|
||||
"}\n" +
|
||||
"input#qr-filename:not(.edit) {\n" +
|
||||
" pointer-events: none;\n" +
|
||||
"}\n" +
|
||||
"#qr-filename,\n" +
|
||||
"#qr-filesize,\n" +
|
||||
".has-file #qr-no-file {\n" +
|
||||
" display: none;\n" +
|
||||
"}\n" +
|
||||
"#qr-no-file,\n" +
|
||||
".has-file #qr-filename,\n" +
|
||||
".has-file #qr-filesize {\n" +
|
||||
".has-file #qr-filename {\n" +
|
||||
" -webkit-flex: 1 1 auto;\n" +
|
||||
" flex: 1 1 auto;\n" +
|
||||
" display: inline-block;\n" +
|
||||
" margin: 0 0 2px;\n" +
|
||||
" padding: 0;\n" +
|
||||
" padding-left: 3px;\n" +
|
||||
" overflow: hidden;\n" +
|
||||
" text-overflow: ellipsis;\n" +
|
||||
" vertical-align: top;\n" +
|
||||
"}\n" +
|
||||
"#qr-no-file {\n" +
|
||||
" color: #AAA;\n" +
|
||||
" padding: 1px 4px;\n" +
|
||||
"}\n" +
|
||||
"#qr-filename-container {\n" +
|
||||
" -moz-box-sizing: border-box;\n" +
|
||||
" display: inline-block;\n" +
|
||||
" position: relative;\n" +
|
||||
" width: 100px;\n" +
|
||||
" min-width: 74.6%;\n" +
|
||||
" max-width: 74.6%;\n" +
|
||||
" margin-right: 0.4%;\n" +
|
||||
" margin-top: 1px;\n" +
|
||||
" overflow: hidden;\n" +
|
||||
" padding: 2px 1px 0;\n" +
|
||||
" height: 22px;\n" +
|
||||
"}\n" +
|
||||
"#qr-filename-container:hover {\n" +
|
||||
" cursor: text;\n" +
|
||||
"}\n" +
|
||||
"#qr-extras-container {\n" +
|
||||
" position: absolute;\n" +
|
||||
" right: 0px;\n" +
|
||||
"}\n" +
|
||||
"#qr-filerm {\n" +
|
||||
" margin-right: 3px;\n" +
|
||||
" z-index: 2;\n" +
|
||||
"}\n" +
|
||||
"#file-n-submit {\n" +
|
||||
" height: 23px;\n" +
|
||||
"}\n" +
|
||||
"#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
|
||||
" display: none;\n" +
|
||||
"}\n" +
|
||||
"#qr input[type=\"file\"] {\n" +
|
||||
" visibility: hidden;\n" +
|
||||
" position: absolute;\n" +
|
||||
"}\n" +
|
||||
"/* Thread Select / Spoiler Label */\n" +
|
||||
"#qr select[data-name=\"thread\"] {\n" +
|
||||
" float: right;\n" +
|
||||
"/* Spoiler Checkbox, QR Icons */\n" +
|
||||
"#qr-spoiler-label, #qr-filename-container > a {\n" +
|
||||
" -webkit-flex: none;\n" +
|
||||
" flex: none;\n" +
|
||||
" margin: 0;\n" +
|
||||
" margin-right: 3px;\n" +
|
||||
" font: 13px sans-serif;\n" +
|
||||
"}\n" +
|
||||
"#qr.has-spoiler .has-file #qr-spoiler-label {\n" +
|
||||
" width: 6.7%;\n" +
|
||||
" min-width: 6.7%;\n" +
|
||||
" max-width: 6.7%;\n" +
|
||||
" display: inline-block;\n" +
|
||||
" text-align: center;\n" +
|
||||
" vertical-align: top;\n" +
|
||||
"}\n" +
|
||||
"#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\n" +
|
||||
"#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label,\n" +
|
||||
".has-file #url-button,\n" +
|
||||
"#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
|
||||
" display: none;\n" +
|
||||
"}\n" +
|
||||
"#qr.has-spoiler .has-file #qr-filename-container {\n" +
|
||||
" max-width: 67.9%;\n" +
|
||||
" min-width: 67.9%;\n" +
|
||||
"#qr-file-spoiler {\n" +
|
||||
" margin: 0;\n" +
|
||||
"}\n" +
|
||||
"#qr-spoiler-label input {\n" +
|
||||
" position: relative;\n" +
|
||||
" top: 3px;\n" +
|
||||
"#url-button, #custom-cooldown-button, #dump-button {\n" +
|
||||
" opacity: 0.6;\n" +
|
||||
"}\n" +
|
||||
"#custom-cooldown-button.disabled {\n" +
|
||||
" opacity: 0.27;\n" +
|
||||
"}\n" +
|
||||
"/* Thread Select */\n" +
|
||||
"#qr select[data-name=\"thread\"] {\n" +
|
||||
" float: right;\n" +
|
||||
"}\n" +
|
||||
"/* Dumping UI */\n" +
|
||||
".dump #dump-list-container {\n" +
|
||||
|
||||
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
// ==UserScript==
|
||||
// @name 4chan X
|
||||
// @version 1.10.2.8
|
||||
// @version 1.10.3.0
|
||||
// @minGMVer 1.14
|
||||
// @minFFVer 26
|
||||
// @namespace 4chan-X
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Generated by CoffeeScript
|
||||
// ==UserScript==
|
||||
// @name 4chan X
|
||||
// @version 1.10.2.8
|
||||
// @version 1.10.3.0
|
||||
// @minGMVer 1.14
|
||||
// @minFFVer 26
|
||||
// @namespace 4chan-X
|
||||
@ -393,7 +393,7 @@
|
||||
doc = d.documentElement;
|
||||
|
||||
g = {
|
||||
VERSION: '1.10.2.8',
|
||||
VERSION: '1.10.3.0',
|
||||
NAMESPACE: '4chan X.',
|
||||
NAME: '4chan X',
|
||||
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
|
||||
@ -3066,7 +3066,7 @@
|
||||
el: $.el('span', {
|
||||
textContent: 'Index Navigation'
|
||||
}),
|
||||
order: 98,
|
||||
order: 100,
|
||||
subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry]
|
||||
});
|
||||
$.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode");
|
||||
@ -6392,7 +6392,7 @@
|
||||
$.on(this.threadNewLink.firstElementChild, 'click', this.rethread);
|
||||
Header.menu.addEntry(this.entry = {
|
||||
el: this.controls,
|
||||
order: 98
|
||||
order: 99
|
||||
});
|
||||
Thread.callbacks.push({
|
||||
name: 'Quote Threading',
|
||||
@ -7169,6 +7169,7 @@
|
||||
if (url === null) {
|
||||
return;
|
||||
}
|
||||
QR.nodes.fileButton.focus();
|
||||
return CrossOrigin.file(url, function(blob) {
|
||||
if (blob) {
|
||||
return QR.handleFiles([blob]);
|
||||
@ -7178,7 +7179,7 @@
|
||||
});
|
||||
},
|
||||
handleFiles: function(files) {
|
||||
var file, i, k, len1;
|
||||
var file, k, len1;
|
||||
if (this !== QR) {
|
||||
files = slice.call(this.files);
|
||||
this.value = null;
|
||||
@ -7187,147 +7188,36 @@
|
||||
return;
|
||||
}
|
||||
QR.cleanNotifications();
|
||||
for (i = k = 0, len1 = files.length; k < len1; i = ++k) {
|
||||
file = files[i];
|
||||
QR.handleFile(file, i, files.length);
|
||||
for (k = 0, len1 = files.length; k < len1; k++) {
|
||||
file = files[k];
|
||||
QR.handleFile(file, files.length);
|
||||
}
|
||||
if (files.length !== 1) {
|
||||
return $.addClass(QR.nodes.el, 'dump');
|
||||
$.addClass(QR.nodes.el, 'dump');
|
||||
}
|
||||
if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) {
|
||||
return QR.nodes.filename.focus();
|
||||
}
|
||||
},
|
||||
handleFile: function(file, index, nfiles) {
|
||||
var isNewPost, isSingle, max, post, ref;
|
||||
isSingle = nfiles === 1;
|
||||
if (/^text\//.test(file.type)) {
|
||||
if (isSingle) {
|
||||
post = QR.selected;
|
||||
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) {
|
||||
handleFile: function(file, nfiles) {
|
||||
var isText, post;
|
||||
isText = /^text\//.test(file.type);
|
||||
if (nfiles === 1) {
|
||||
post = QR.selected;
|
||||
} else {
|
||||
post = QR.posts[QR.posts.length - 1];
|
||||
if ((isText ? post.com || post.pasting : post.file)) {
|
||||
post = new QR.post();
|
||||
}
|
||||
post.pasteText(file);
|
||||
}
|
||||
return post[isText ? 'pasteText' : 'setFile'](file);
|
||||
},
|
||||
openFileInput: function() {
|
||||
if (QR.nodes.fileButton.disabled) {
|
||||
return;
|
||||
}
|
||||
if (ref = file.type, indexOf.call(QR.mimeTypes, ref) < 0) {
|
||||
QR.error(file.name + ": Unsupported file type.");
|
||||
if (!isSingle) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
max = QR.nodes.fileInput.max;
|
||||
if (/^video\//.test(file.type)) {
|
||||
max = Math.min(max, QR.max_size_video);
|
||||
}
|
||||
if (file.size > max) {
|
||||
QR.error(file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ").");
|
||||
if (!isSingle) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
isNewPost = false;
|
||||
if (isSingle) {
|
||||
post = QR.selected;
|
||||
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) {
|
||||
isNewPost = true;
|
||||
post = new QR.post();
|
||||
}
|
||||
return QR.checkDimensions(file, function(pass, el) {
|
||||
if (pass || isSingle) {
|
||||
return post.setFile(file, el);
|
||||
} else if (isNewPost) {
|
||||
post.rm();
|
||||
if (el) {
|
||||
return URL.revokeObjectURL(el.src);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
checkDimensions: function(file, cb) {
|
||||
var img, video;
|
||||
if (/^image\//.test(file.type)) {
|
||||
img = new Image();
|
||||
img.onload = function() {
|
||||
var height, pass, width;
|
||||
height = img.height, width = img.width;
|
||||
pass = true;
|
||||
if (height > QR.max_height || width > QR.max_width) {
|
||||
QR.error(file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
if (height < QR.min_height || width < QR.min_width) {
|
||||
QR.error(file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
return cb(pass, img);
|
||||
};
|
||||
img.onerror = function() {
|
||||
return cb(false, null);
|
||||
};
|
||||
return img.src = URL.createObjectURL(file);
|
||||
} else if (/^video\//.test(file.type)) {
|
||||
video = $.el('video');
|
||||
$.on(video, 'loadeddata', function() {
|
||||
var duration, max_height, max_width, pass, ref, videoHeight, videoWidth;
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
videoHeight = video.videoHeight, videoWidth = video.videoWidth, duration = video.duration;
|
||||
max_height = Math.min(QR.max_height, QR.max_height_video);
|
||||
max_width = Math.min(QR.max_width, QR.max_width_video);
|
||||
pass = true;
|
||||
if (videoHeight > max_height || videoWidth > max_width) {
|
||||
QR.error(file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
|
||||
QR.error(file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
pass = false;
|
||||
}
|
||||
if (!isFinite(duration)) {
|
||||
QR.error(file.name + ": Video lacks duration metadata (try remuxing)");
|
||||
pass = false;
|
||||
} else if (duration > QR.max_duration_video) {
|
||||
QR.error(file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
|
||||
pass = false;
|
||||
}
|
||||
if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(video)) {
|
||||
QR.error(file.name + ": Audio not allowed");
|
||||
pass = false;
|
||||
}
|
||||
cb(pass, video);
|
||||
return cb = null;
|
||||
});
|
||||
$.on(video, 'error', function() {
|
||||
var ref;
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
if (ref = file.type, indexOf.call(QR.mimeTypes, ref) >= 0) {
|
||||
QR.error(file.name + ": Video appears corrupt");
|
||||
}
|
||||
URL.revokeObjectURL(file);
|
||||
cb(false, null);
|
||||
return cb = null;
|
||||
});
|
||||
return video.src = URL.createObjectURL(file);
|
||||
} else {
|
||||
return cb(true, null);
|
||||
}
|
||||
},
|
||||
openFileInput: function(e) {
|
||||
var ref;
|
||||
e.stopPropagation();
|
||||
if (e.shiftKey && e.type === 'click') {
|
||||
return QR.selected.rmFile();
|
||||
}
|
||||
if ((e.ctrlKey || e.metaKey) && e.type === 'click') {
|
||||
$.addClass(QR.nodes.filename, 'edit');
|
||||
QR.nodes.filename.focus();
|
||||
}
|
||||
if (e.target.nodeName === 'INPUT' || (e.keyCode && ((ref = e.keyCode) !== 32 && ref !== 13)) || e.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
return QR.nodes.fileInput.click();
|
||||
QR.nodes.fileInput.click();
|
||||
return QR.nodes.fileButton.focus();
|
||||
},
|
||||
generatePostableThreadsList: function() {
|
||||
var k, len1, list, options, ref, thread, val;
|
||||
@ -7358,7 +7248,7 @@
|
||||
var dialog, event, i, items, m, match_max, match_min, name, node, nodes, ref, rules, save, setNode;
|
||||
QR.nodes = nodes = {
|
||||
el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', {
|
||||
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=file-n-submit><span id=qr-filename-container class=field tabindex=0><span id=qr-no-file>No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><span id=\"qr-extras-container\"><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span></span><label id=qr-spoiler-label><input type=checkbox id=qr-file-spoiler title='Spoiler image'></label><input type=submit></div><input type=file multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
|
||||
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=\"file-n-submit\"><input type=\"button\" id=\"qr-file-button\" value=\"Files\"><span id=\"qr-filename-container\" class=\"field\"><span id=\"qr-no-file\">No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><label id=\"qr-spoiler-label\"><input type=\"checkbox\" id=\"qr-file-spoiler\" title=\"Spoiler image\"></label><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span><input type=\"submit\"></div><input type=\"file\" multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
|
||||
})
|
||||
};
|
||||
setNode = function(name, query) {
|
||||
@ -7380,10 +7270,10 @@
|
||||
setNode('addPost', '#add-post');
|
||||
setNode('charCount', '#char-count');
|
||||
setNode('fileSubmit', '#file-n-submit');
|
||||
setNode('fileButton', '#qr-file-button');
|
||||
setNode('noFile', '#qr-no-file');
|
||||
setNode('filename', '#qr-filename');
|
||||
setNode('fileContainer', '#qr-filename-container');
|
||||
setNode('fileRM', '#qr-filerm');
|
||||
setNode('fileExtras', '#qr-extras-container');
|
||||
setNode('spoiler', '#qr-file-spoiler');
|
||||
setNode('spoilerPar', '#qr-spoiler-label');
|
||||
setNode('status', '[type=submit]');
|
||||
@ -7437,7 +7327,8 @@
|
||||
nodes.flashTag.dataset["default"] = '4';
|
||||
$.add(nodes.form, nodes.flashTag);
|
||||
}
|
||||
$.on(nodes.filename.parentNode, 'click keydown', QR.openFileInput);
|
||||
$.on(nodes.fileButton, 'click', QR.openFileInput);
|
||||
$.on(nodes.noFile, 'click', QR.openFileInput);
|
||||
$.on(nodes.autohide, 'change', QR.toggleHide);
|
||||
$.on(nodes.close, 'click', QR.close);
|
||||
$.on(nodes.dumpButton, 'click', function() {
|
||||
@ -7448,15 +7339,9 @@
|
||||
return new QR.post(true);
|
||||
});
|
||||
$.on(nodes.form, 'submit', QR.submit);
|
||||
$.on(nodes.filename, 'blur', function() {
|
||||
return $.rmClass(this, 'edit');
|
||||
});
|
||||
$.on(nodes.fileRM, 'click', function() {
|
||||
return QR.selected.rmFile();
|
||||
});
|
||||
$.on(nodes.fileExtras, 'click', function(e) {
|
||||
return e.stopPropagation();
|
||||
});
|
||||
$.on(nodes.spoiler, 'change', function() {
|
||||
return QR.selected.nodes.spoiler.click();
|
||||
});
|
||||
@ -7626,7 +7511,7 @@
|
||||
return QR.status();
|
||||
},
|
||||
response: function() {
|
||||
var URL, _, ban, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, ref, ref1, req, resDoc, threadID;
|
||||
var URL, _, ban, err, h1, isReply, m, post, postID, postsCount, ref, ref1, req, resDoc, threadID;
|
||||
req = QR.req;
|
||||
delete QR.req;
|
||||
post = QR.posts[0];
|
||||
@ -7696,22 +7581,6 @@
|
||||
});
|
||||
postsCount = QR.posts.length - 1;
|
||||
QR.cooldown.auto = postsCount && isReply;
|
||||
if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) {
|
||||
notif = new Notification('Quick reply warning', {
|
||||
body: "You are running low on cached captchas. Cache count: " + captchasCount + ".",
|
||||
icon: Favicon.logo
|
||||
});
|
||||
notif.onclick = function() {
|
||||
QR.open();
|
||||
window.focus();
|
||||
return QR.captcha.setup(true);
|
||||
};
|
||||
notif.onshow = function() {
|
||||
return setTimeout(function() {
|
||||
return notif.close();
|
||||
}, 7 * $.SECOND);
|
||||
};
|
||||
}
|
||||
if (!(Conf['Persistent QR'] || postsCount)) {
|
||||
QR.close();
|
||||
} else {
|
||||
@ -8119,7 +7988,7 @@
|
||||
return $.on(window, 'focus', function() {
|
||||
return $.queueTask(function() {
|
||||
var checkbox;
|
||||
if (!(checkbox = $.id('recaptcha-anchor'))) {
|
||||
if (!(d.hasFocus() && (checkbox = $.id('recaptcha-anchor')))) {
|
||||
return;
|
||||
}
|
||||
if (d.activeElement !== checkbox) {
|
||||
@ -8166,7 +8035,6 @@
|
||||
if (!(this.isEnabled && (this.needed() || force))) {
|
||||
return;
|
||||
}
|
||||
$.addClass(QR.nodes.el, 'captcha-open');
|
||||
if (focus) {
|
||||
this.shouldFocus = true;
|
||||
}
|
||||
@ -8210,6 +8078,7 @@
|
||||
},
|
||||
setupIFrame: function(iframe) {
|
||||
this.setupTime = Date.now();
|
||||
$.addClass(QR.nodes.el, 'captcha-open');
|
||||
if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
|
||||
QR.nodes.el.style.top = null;
|
||||
QR.nodes.el.style.bottom = '0px';
|
||||
@ -8693,7 +8562,8 @@
|
||||
|
||||
_Class.prototype["delete"] = function() {
|
||||
$.rm(this.nodes.el);
|
||||
return URL.revokeObjectURL(this.URL);
|
||||
URL.revokeObjectURL(this.URL);
|
||||
return this.dismissErrors();
|
||||
};
|
||||
|
||||
_Class.prototype.lock = function(lock) {
|
||||
@ -8713,7 +8583,6 @@
|
||||
}
|
||||
}
|
||||
this.nodes.rm.style.visibility = lock ? 'hidden' : '';
|
||||
(lock ? $.off : $.on)(QR.nodes.filename.previousElementSibling, 'click', QR.openFileInput);
|
||||
this.nodes.spoiler.disabled = lock;
|
||||
return this.nodes.el.draggable = !lock;
|
||||
};
|
||||
@ -8799,10 +8668,82 @@
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.setFile = function(file1, el) {
|
||||
_Class.rmErrored = function(e) {
|
||||
var error, errors, k, len1, post, q, ref;
|
||||
e.stopPropagation();
|
||||
ref = QR.posts;
|
||||
for (k = ref.length - 1; k >= 0; k += -1) {
|
||||
post = ref[k];
|
||||
if (errors = post.errors) {
|
||||
for (q = 0, len1 = errors.length; q < len1; q++) {
|
||||
error = errors[q];
|
||||
if (!(doc.contains(error))) {
|
||||
continue;
|
||||
}
|
||||
post.rm();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.error = function(className, message) {
|
||||
var div, ref, rm, rmAll;
|
||||
div = $.el('div', {
|
||||
className: className
|
||||
});
|
||||
$.extend(div, {
|
||||
innerHTML: E(message) + "<br>[<a href=\"javascript:;\">delete</a>] [<a href=\"javascript:;\">delete all</a>]"
|
||||
});
|
||||
(this.errors || (this.errors = [])).push(div);
|
||||
ref = $$('a', div), rm = ref[0], rmAll = ref[1];
|
||||
$.on(div, 'click', (function(_this) {
|
||||
return function() {
|
||||
if (indexOf.call(QR.posts, _this) >= 0) {
|
||||
return _this.select();
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
$.on(rm, 'click', (function(_this) {
|
||||
return function(e) {
|
||||
e.stopPropagation();
|
||||
if (indexOf.call(QR.posts, _this) >= 0) {
|
||||
return _this.rm();
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
$.on(rmAll, 'click', QR.post.rmErrored);
|
||||
return QR.error(div);
|
||||
};
|
||||
|
||||
_Class.prototype.fileError = function(message) {
|
||||
return this.error('file-error', this.filename + ": " + message);
|
||||
};
|
||||
|
||||
_Class.prototype.dismissErrors = function(test) {
|
||||
var error, k, len1, ref;
|
||||
if (test == null) {
|
||||
test = function() {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
if (this.errors) {
|
||||
ref = this.errors;
|
||||
for (k = 0, len1 = ref.length; k < len1; k++) {
|
||||
error = ref[k];
|
||||
if (doc.contains(error) && test(error)) {
|
||||
error.parentNode.previousElementSibling.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.setFile = function(file1) {
|
||||
var ref;
|
||||
this.file = file1;
|
||||
this.filename = this.file.name;
|
||||
this.filesize = $.bytesToString(this.file.size);
|
||||
this.checkSize();
|
||||
if (QR.spoiler) {
|
||||
this.nodes.label.hidden = false;
|
||||
}
|
||||
@ -8813,10 +8754,79 @@
|
||||
} else {
|
||||
this.updateFilename();
|
||||
}
|
||||
if (el) {
|
||||
return this.setThumbnail(el);
|
||||
this.nodes.el.style.backgroundImage = null;
|
||||
if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) {
|
||||
return this.fileError('Unsupported file type.');
|
||||
} else if (/^(image|video)\//.test(this.file.type)) {
|
||||
return this.readFile();
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.checkSize = function() {
|
||||
var max;
|
||||
max = QR.nodes.fileInput.max;
|
||||
if (/^video\//.test(this.file.type)) {
|
||||
max = Math.min(max, QR.max_size_video);
|
||||
}
|
||||
if (this.file.size > max) {
|
||||
return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ").");
|
||||
}
|
||||
};
|
||||
|
||||
_Class.prototype.readFile = function() {
|
||||
var el, event, isVideo, onerror, onload;
|
||||
isVideo = /^video\//.test(this.file.type);
|
||||
el = $.el(isVideo ? 'video' : 'img');
|
||||
event = isVideo ? 'loadeddata' : 'load';
|
||||
onload = (function(_this) {
|
||||
return function() {
|
||||
$.off(el, event, onload);
|
||||
$.off(el, 'error', onerror);
|
||||
_this.checkDimensions(el);
|
||||
return _this.setThumbnail(el);
|
||||
};
|
||||
})(this);
|
||||
onerror = (function(_this) {
|
||||
return function() {
|
||||
$.off(el, event, onload);
|
||||
$.off(el, 'error', onerror);
|
||||
_this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt");
|
||||
return URL.revokeObjectURL(el.src);
|
||||
};
|
||||
})(this);
|
||||
$.on(el, event, onload);
|
||||
$.on(el, 'error', onerror);
|
||||
return el.src = URL.createObjectURL(this.file);
|
||||
};
|
||||
|
||||
_Class.prototype.checkDimensions = function(el) {
|
||||
var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width;
|
||||
if (el.tagName === 'IMG') {
|
||||
height = el.height, width = el.width;
|
||||
if (height > QR.max_height || width > QR.max_width) {
|
||||
this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)");
|
||||
}
|
||||
if (height < QR.min_height || width < QR.min_width) {
|
||||
return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
}
|
||||
} else {
|
||||
return this.nodes.el.style.backgroundImage = null;
|
||||
videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration;
|
||||
max_height = Math.min(QR.max_height, QR.max_height_video);
|
||||
max_width = Math.min(QR.max_width, QR.max_width_video);
|
||||
if (videoHeight > max_height || videoWidth > max_width) {
|
||||
this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
|
||||
}
|
||||
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
|
||||
this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
|
||||
}
|
||||
if (!isFinite(duration)) {
|
||||
this.fileError('Video lacks duration metadata (try remuxing)');
|
||||
} else if (duration > QR.max_duration_video) {
|
||||
this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
|
||||
}
|
||||
if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) {
|
||||
return this.fileError('Audio not allowed');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -8866,23 +8876,26 @@
|
||||
delete this.filename;
|
||||
delete this.filesize;
|
||||
this.nodes.el.title = null;
|
||||
QR.nodes.fileContainer.title = '';
|
||||
QR.nodes.filename.title = '';
|
||||
this.nodes.el.style.backgroundImage = null;
|
||||
if (QR.spoiler) {
|
||||
this.nodes.label.hidden = true;
|
||||
}
|
||||
this.showFileData();
|
||||
return URL.revokeObjectURL(this.URL);
|
||||
URL.revokeObjectURL(this.URL);
|
||||
return this.dismissErrors(function(error) {
|
||||
return $.hasClass(error, 'file-error');
|
||||
});
|
||||
};
|
||||
|
||||
_Class.prototype.updateFilename = function() {
|
||||
var long;
|
||||
long = this.filename + " (" + this.filesize + ")\nCtrl/\u2318+click to edit filename. Shift+click to clear.";
|
||||
long = this.filename + " (" + this.filesize + ")";
|
||||
this.nodes.el.title = long;
|
||||
if (this !== QR.selected) {
|
||||
return;
|
||||
}
|
||||
return QR.nodes.fileContainer.title = long;
|
||||
return QR.nodes.filename.title = long;
|
||||
};
|
||||
|
||||
_Class.prototype.showFileData = function() {
|
||||
@ -8898,6 +8911,7 @@
|
||||
|
||||
_Class.prototype.pasteText = function(file) {
|
||||
var reader;
|
||||
this.pasting = true;
|
||||
reader = new FileReader();
|
||||
reader.onload = (function(_this) {
|
||||
return function(e) {
|
||||
@ -8911,7 +8925,8 @@
|
||||
if (QR.selected === _this) {
|
||||
QR.nodes.com.value = _this.com;
|
||||
}
|
||||
return _this.nodes.span.textContent = _this.com;
|
||||
_this.nodes.span.textContent = _this.com;
|
||||
return delete _this.pasting;
|
||||
};
|
||||
})(this);
|
||||
return reader.readAsText(file);
|
||||
@ -10166,7 +10181,7 @@
|
||||
$.on(this.el, 'change', this.toggle);
|
||||
return Header.menu.addEntry({
|
||||
el: prefetch,
|
||||
order: 104
|
||||
order: 98
|
||||
});
|
||||
},
|
||||
node: function() {
|
||||
@ -17020,9 +17035,6 @@
|
||||
"body.hasDropDownNav{\n" +
|
||||
" margin-top: 5px;\n" +
|
||||
"}\n" +
|
||||
"a {\n" +
|
||||
" outline: none !important;\n" +
|
||||
"}\n" +
|
||||
".painted {\n" +
|
||||
" border-radius: 3px;\n" +
|
||||
" padding: 0px 2px;\n" +
|
||||
@ -17667,7 +17679,7 @@
|
||||
" text-align: center;\n" +
|
||||
"}\n" +
|
||||
"/* /tg/ dice rolls */\n" +
|
||||
".catalog-thread > .comment > b {\n" +
|
||||
".board_tg .catalog-thread > .comment > b {\n" +
|
||||
" font-weight: normal;\n" +
|
||||
"}\n" +
|
||||
".catalog-code {\n" +
|
||||
@ -18118,17 +18130,6 @@
|
||||
" -webkit-flex-direction: row;\n" +
|
||||
" flex-direction: row;\n" +
|
||||
"}\n" +
|
||||
"#url-button, #custom-cooldown-button, #dump-button {\n" +
|
||||
" width: 10%;\n" +
|
||||
" margin: 0;\n" +
|
||||
" margin-right: 4px;\n" +
|
||||
" font: 13px sans-serif;\n" +
|
||||
" padding: 1px 0px 2px;\n" +
|
||||
" opacity: 0.6;\n" +
|
||||
"}\n" +
|
||||
"#custom-cooldown-button.disabled {\n" +
|
||||
" opacity: 0.27;\n" +
|
||||
"}\n" +
|
||||
".persona .field {\n" +
|
||||
" -webkit-flex: 1;\n" +
|
||||
" flex: 1;\n" +
|
||||
@ -18151,8 +18152,18 @@
|
||||
" text-shadow: none !important;\n" +
|
||||
"}\n" +
|
||||
"#qr textarea {\n" +
|
||||
" min-width: 100%;\n" +
|
||||
" resize: both;\n" +
|
||||
"}\n" +
|
||||
".field {\n" +
|
||||
" -moz-box-sizing: border-box;\n" +
|
||||
" margin: 0px;\n" +
|
||||
" padding: 2px 4px 3px;\n" +
|
||||
"}\n" +
|
||||
"#qr label input[type=\"checkbox\"] {\n" +
|
||||
" position: relative;\n" +
|
||||
" top: 2px;\n" +
|
||||
"}\n" +
|
||||
"/* Noscript Recaptcha */\n" +
|
||||
".captcha-img {\n" +
|
||||
" margin: 0px;\n" +
|
||||
@ -18196,111 +18207,81 @@
|
||||
" display: block;\n" +
|
||||
" width: 100%;\n" +
|
||||
"}\n" +
|
||||
".field {\n" +
|
||||
" -moz-box-sizing: border-box;\n" +
|
||||
" margin: 0px;\n" +
|
||||
" padding: 2px 4px 3px;\n" +
|
||||
"/* File Input, Submit Button */\n" +
|
||||
"#file-n-submit {\n" +
|
||||
" display: -webkit-flex;\n" +
|
||||
" display: flex;\n" +
|
||||
" -webkit-align-items: stretch;\n" +
|
||||
" align-items: stretch;\n" +
|
||||
" margin-top: 1px;\n" +
|
||||
"}\n" +
|
||||
"#qr textarea {\n" +
|
||||
" min-width: 100%;\n" +
|
||||
":root.gecko #file-n-submit > input {\n" +
|
||||
" margin: 0px -1px -1px;\n" +
|
||||
"}\n" +
|
||||
"#qr [type=\"submit\"] {\n" +
|
||||
"#file-n-submit input[type=\"submit\"] {\n" +
|
||||
" width: 25%;\n" +
|
||||
" vertical-align: top;\n" +
|
||||
"}\n" +
|
||||
":root.webkit #qr [type=\"submit\"] {\n" +
|
||||
" height: 24px;\n" +
|
||||
"}\n" +
|
||||
"#qr label input[type=\"checkbox\"] {\n" +
|
||||
"#qr-filename-container {\n" +
|
||||
" -webkit-flex: 1 1 auto;\n" +
|
||||
" flex: 1 1 auto;\n" +
|
||||
" width: 0;\n" +
|
||||
" display: -webkit-flex;\n" +
|
||||
" display: flex;\n" +
|
||||
" -webkit-align-items: center;\n" +
|
||||
" align-items: center;\n" +
|
||||
" position: relative;\n" +
|
||||
" top: 2px;\n" +
|
||||
" padding: 1px;\n" +
|
||||
"}\n" +
|
||||
"/* Fake File Input */\n" +
|
||||
"input#qr-filename {\n" +
|
||||
" border: none !important;\n" +
|
||||
" width: 80%;\n" +
|
||||
" padding: 0px 4px;\n" +
|
||||
" position: relative;\n" +
|
||||
" bottom: 1px;\n" +
|
||||
" background: none !important;\n" +
|
||||
"}\n" +
|
||||
"input#qr-filename:not(.edit) {\n" +
|
||||
" pointer-events: none;\n" +
|
||||
"}\n" +
|
||||
"#qr-filename,\n" +
|
||||
"#qr-filesize,\n" +
|
||||
".has-file #qr-no-file {\n" +
|
||||
" display: none;\n" +
|
||||
"}\n" +
|
||||
"#qr-no-file,\n" +
|
||||
".has-file #qr-filename,\n" +
|
||||
".has-file #qr-filesize {\n" +
|
||||
".has-file #qr-filename {\n" +
|
||||
" -webkit-flex: 1 1 auto;\n" +
|
||||
" flex: 1 1 auto;\n" +
|
||||
" display: inline-block;\n" +
|
||||
" margin: 0 0 2px;\n" +
|
||||
" padding: 0;\n" +
|
||||
" padding-left: 3px;\n" +
|
||||
" overflow: hidden;\n" +
|
||||
" text-overflow: ellipsis;\n" +
|
||||
" vertical-align: top;\n" +
|
||||
"}\n" +
|
||||
"#qr-no-file {\n" +
|
||||
" color: #AAA;\n" +
|
||||
" padding: 1px 4px;\n" +
|
||||
"}\n" +
|
||||
"#qr-filename-container {\n" +
|
||||
" -moz-box-sizing: border-box;\n" +
|
||||
" display: inline-block;\n" +
|
||||
" position: relative;\n" +
|
||||
" width: 100px;\n" +
|
||||
" min-width: 74.6%;\n" +
|
||||
" max-width: 74.6%;\n" +
|
||||
" margin-right: 0.4%;\n" +
|
||||
" margin-top: 1px;\n" +
|
||||
" overflow: hidden;\n" +
|
||||
" padding: 2px 1px 0;\n" +
|
||||
" height: 22px;\n" +
|
||||
"}\n" +
|
||||
"#qr-filename-container:hover {\n" +
|
||||
" cursor: text;\n" +
|
||||
"}\n" +
|
||||
"#qr-extras-container {\n" +
|
||||
" position: absolute;\n" +
|
||||
" right: 0px;\n" +
|
||||
"}\n" +
|
||||
"#qr-filerm {\n" +
|
||||
" margin-right: 3px;\n" +
|
||||
" z-index: 2;\n" +
|
||||
"}\n" +
|
||||
"#file-n-submit {\n" +
|
||||
" height: 23px;\n" +
|
||||
"}\n" +
|
||||
"#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
|
||||
" display: none;\n" +
|
||||
"}\n" +
|
||||
"#qr input[type=\"file\"] {\n" +
|
||||
" visibility: hidden;\n" +
|
||||
" position: absolute;\n" +
|
||||
"}\n" +
|
||||
"/* Thread Select / Spoiler Label */\n" +
|
||||
"#qr select[data-name=\"thread\"] {\n" +
|
||||
" float: right;\n" +
|
||||
"/* Spoiler Checkbox, QR Icons */\n" +
|
||||
"#qr-spoiler-label, #qr-filename-container > a {\n" +
|
||||
" -webkit-flex: none;\n" +
|
||||
" flex: none;\n" +
|
||||
" margin: 0;\n" +
|
||||
" margin-right: 3px;\n" +
|
||||
" font: 13px sans-serif;\n" +
|
||||
"}\n" +
|
||||
"#qr.has-spoiler .has-file #qr-spoiler-label {\n" +
|
||||
" width: 6.7%;\n" +
|
||||
" min-width: 6.7%;\n" +
|
||||
" max-width: 6.7%;\n" +
|
||||
" display: inline-block;\n" +
|
||||
" text-align: center;\n" +
|
||||
" vertical-align: top;\n" +
|
||||
"}\n" +
|
||||
"#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\n" +
|
||||
"#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label,\n" +
|
||||
".has-file #url-button,\n" +
|
||||
"#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
|
||||
" display: none;\n" +
|
||||
"}\n" +
|
||||
"#qr.has-spoiler .has-file #qr-filename-container {\n" +
|
||||
" max-width: 67.9%;\n" +
|
||||
" min-width: 67.9%;\n" +
|
||||
"#qr-file-spoiler {\n" +
|
||||
" margin: 0;\n" +
|
||||
"}\n" +
|
||||
"#qr-spoiler-label input {\n" +
|
||||
" position: relative;\n" +
|
||||
" top: 3px;\n" +
|
||||
"#url-button, #custom-cooldown-button, #dump-button {\n" +
|
||||
" opacity: 0.6;\n" +
|
||||
"}\n" +
|
||||
"#custom-cooldown-button.disabled {\n" +
|
||||
" opacity: 0.27;\n" +
|
||||
"}\n" +
|
||||
"/* Thread Select */\n" +
|
||||
"#qr select[data-name=\"thread\"] {\n" +
|
||||
" float: right;\n" +
|
||||
"}\n" +
|
||||
"/* Dumping UI */\n" +
|
||||
".dump #dump-list-container {\n" +
|
||||
|
||||
Binary file not shown.
@ -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/4chan-X-beta.crx' version='1.10.2.8' />
|
||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.10.3.0' />
|
||||
</app>
|
||||
</gupdate>
|
||||
|
||||
|
||||
@ -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/4chan-X.crx' version='1.10.2.8' />
|
||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.10.3.0' />
|
||||
</app>
|
||||
</gupdate>
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"description": "Cross-browser userscript for maximum lurking on 4chan.",
|
||||
"meta": {
|
||||
"name": "4chan X",
|
||||
"version": "1.10.2.8",
|
||||
"version": "1.10.3.0",
|
||||
"repo": "https://github.com/ccd0/4chan-x/",
|
||||
"page": "https://github.com/ccd0/4chan-x",
|
||||
"downloads": "https://ccd0.github.io/4chan-x/builds/",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user