diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2263db28..e07bbc313 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ The links to individual versions below are to copies of the script with the upda
## v1.11.0
+**v1.11.0.8** *(2015-06-21)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.8/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.8/builds/4chan-X-noupdate.crx "Chromium version")]
+- Support noscript version of Recaptcha v1.
+- Captcha-related bugfixes/improvements.
+
**v1.11.0.7** *(2015-06-21)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.7/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.7/builds/4chan-X-noupdate.crx "Chromium version")]
- Add `Use Recaptcha v1` option to use the old text-based captchas in the Quick Reply.
diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx
index df1d14615..d8242d82f 100644
Binary files a/builds/4chan-X-beta.crx and b/builds/4chan-X-beta.crx differ
diff --git a/builds/4chan-X-beta.meta.js b/builds/4chan-X-beta.meta.js
index 63a668f0f..87ec7d95f 100644
--- a/builds/4chan-X-beta.meta.js
+++ b/builds/4chan-X-beta.meta.js
@@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X beta
-// @version 1.11.0.7
+// @version 1.11.0.8
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -15,6 +15,7 @@
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
+// @match *://www.google.com/recaptcha/api/noscript?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
diff --git a/builds/4chan-X-beta.user.js b/builds/4chan-X-beta.user.js
index db361c661..3b0985d84 100644
--- a/builds/4chan-X-beta.user.js
+++ b/builds/4chan-X-beta.user.js
@@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X beta
-// @version 1.11.0.7
+// @version 1.11.0.8
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -16,6 +16,7 @@
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
+// @match *://www.google.com/recaptcha/api/noscript?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
@@ -401,7 +402,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.11.0.7',
+ VERSION: '1.11.0.8',
NAMESPACE: '4chan X.',
boards: {}
};
@@ -2064,13 +2065,21 @@
$.on(window, 'message', this.onMessage);
}
+ Connection.prototype.targetWindow = function() {
+ if (this.target instanceof window.HTMLIFrameElement) {
+ return this.target.contentWindow;
+ } else {
+ return this.target;
+ }
+ };
+
Connection.prototype.send = function(data) {
- return this.target.postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin);
+ return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin);
};
Connection.prototype.onMessage = function(e) {
var base1, data, type, value;
- if (!(e.source === this.target && e.origin === this.origin && typeof e.data === 'string' && e.data.slice(0, g.NAMESPACE.length) === g.NAMESPACE)) {
+ if (!(e.source === this.targetWindow() && e.origin === this.origin && typeof e.data === 'string' && e.data.slice(0, g.NAMESPACE.length) === g.NAMESPACE)) {
return;
}
data = JSON.parse(e.data.slice(g.NAMESPACE.length));
@@ -6672,7 +6681,7 @@
QR = {
mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'],
init: function() {
- var sc, version;
+ var noscript, sc, version;
if (!Conf['Quick Reply']) {
return;
}
@@ -6681,7 +6690,7 @@
if (g.VIEW === 'archive') {
return;
}
- version = Conf['Use Recaptcha v1'] ? 'v1' : 'v2';
+ version = Conf['Use Recaptcha v1'] ? (noscript = Conf['Force Noscript Captcha'] || !$.hasClass(doc, 'js-enabled'), noscript ? 'noscript' : 'v1') : 'v2';
this.captcha = Captcha[version];
$.on(d, '4chanXInitFinished', this.initReady);
Post.callbacks.push({
@@ -6835,7 +6844,7 @@
QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement);
QR.nodes.el.classList.toggle('focus', QR.hasFocus);
}
- if (QR.captcha.isEnabled && !QR.captcha.noscript) {
+ if (QR.captcha.isEnabled && QR.captcha === Captcha.v2 && !QR.captcha.noscript) {
if (QR.inCaptcha()) {
QR.scrollY = window.scrollY;
return $.on(d, 'scroll', QR.scrollLock);
@@ -7797,6 +7806,341 @@
}
};
+ Captcha.noscript = {
+ lifetime: 10 * $.MINUTE,
+ init: function() {
+ var container, input;
+ if (d.cookie.indexOf('pass_enabled=1') >= 0) {
+ return;
+ }
+ if (!(this.isEnabled = !!$.id('g-recaptcha'))) {
+ return;
+ }
+ container = $.el('div', {
+ className: 'captcha-img',
+ title: 'Reload reCAPTCHA'
+ });
+ input = $.el('input', {
+ className: 'captcha-input field',
+ title: 'Verification',
+ autocomplete: 'off',
+ spellcheck: false
+ });
+ this.nodes = {
+ container: container,
+ input: input
+ };
+ $.on(input, 'keydown', this.keydown.bind(this));
+ $.on(this.nodes.container, 'click', (function(_this) {
+ return function() {
+ _this.reload();
+ return _this.nodes.input.focus();
+ };
+ })(this));
+ this.conn = new Connection(null, location.protocol + "//www.google.com", {
+ challenge: this.load.bind(this),
+ token: this.save.bind(this),
+ error: this.error.bind(this)
+ });
+ $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1', 'noscript-captcha');
+ $.after(QR.nodes.com.parentNode, [container, input]);
+ this.captchas = [];
+ $.get('captchas', [], function(arg) {
+ var captchas;
+ captchas = arg.captchas;
+ QR.captcha.sync(captchas);
+ return QR.captcha.clear();
+ });
+ $.sync('captchas', this.sync);
+ this.beforeSetup();
+ return this.setup();
+ },
+ initFrame: function() {
+ var cb, conn, img, ref, ref1;
+ conn = new Connection(window.parent, location.protocol + "//boards.4chan.org", {
+ response: function(response) {
+ $.id('recaptcha_response_field').value = response;
+ return HTMLFormElement.prototype.submit.call($('form'));
+ }
+ });
+ if (location.hash === '#response') {
+ conn.send({
+ token: (ref = $('textarea')) != null ? ref.value : void 0,
+ error: (ref1 = $('.recaptcha_input_area')) != null ? ref1.textContent.replace(/:$/, '') : void 0
+ });
+ }
+ if (!(img = $('img'))) {
+ return;
+ }
+ $('form').action = '#response';
+ cb = function() {
+ var canvas;
+ canvas = $.el('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ canvas.getContext('2d').drawImage(img, 0, 0);
+ return conn.send({
+ challenge: canvas.toDataURL()
+ });
+ };
+ if (img.complete) {
+ return cb();
+ } else {
+ return $.on(img, 'load', cb);
+ }
+ },
+ timers: {},
+ iframeURL: function() {
+ var lang, url;
+ url = '//www.google.com/recaptcha/api/noscript?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc';
+ if (lang = Conf['captchaLanguage'].trim()) {
+ url += "&hl=" + (encodeURIComponent(lang));
+ }
+ return url;
+ },
+ cb: {
+ focus: function() {
+ return QR.captcha.setup(false, true);
+ }
+ },
+ beforeSetup: function() {
+ var container, input, ref;
+ ref = this.nodes, container = ref.container, input = ref.input;
+ container.hidden = true;
+ input.value = '';
+ input.placeholder = 'Focus to load reCAPTCHA';
+ this.count();
+ return $.on(input, 'focus click', this.cb.focus);
+ },
+ needed: function() {
+ var captchaCount, postsCount;
+ captchaCount = this.captchas.length;
+ if (QR.req) {
+ captchaCount++;
+ }
+ postsCount = QR.posts.length;
+ if (postsCount === 1 && !Conf['Auto-load captcha'] && !QR.posts[0].com && !QR.posts[0].file) {
+ postsCount = 0;
+ }
+ return captchaCount < postsCount;
+ },
+ onNewPost: function() {},
+ onPostChange: function() {},
+ setup: function(focus, force) {
+ if (!(this.isEnabled && (this.needed() || force))) {
+ return;
+ }
+ if (!this.nodes.iframe) {
+ this.nodes.iframe = $.el('iframe', {
+ id: 'qr-captcha-iframe',
+ src: this.iframeURL()
+ });
+ $.add(QR.nodes.el, this.nodes.iframe);
+ this.conn.target = this.nodes.iframe;
+ } else if (!this.occupied || force) {
+ this.nodes.iframe.src = this.iframeURL();
+ }
+ this.occupied = true;
+ if (focus) {
+ return this.nodes.input.focus();
+ }
+ },
+ afterSetup: function() {
+ var container, input, ref;
+ ref = this.nodes, container = ref.container, input = ref.input;
+ container.hidden = false;
+ input.placeholder = 'Verification';
+ this.count();
+ $.off(input, 'focus click', this.cb.focus);
+ if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
+ QR.nodes.el.style.top = '';
+ return QR.nodes.el.style.bottom = '0px';
+ }
+ },
+ destroy: function() {
+ if (!this.isEnabled) {
+ return;
+ }
+ if (this.nodes.img) {
+ $.rm(this.nodes.img);
+ }
+ delete this.nodes.img;
+ if (this.nodes.iframe) {
+ $.rm(this.nodes.iframe);
+ }
+ delete this.nodes.iframe;
+ delete this.occupied;
+ return this.beforeSetup();
+ },
+ sync: function(captchas) {
+ if (captchas == null) {
+ captchas = [];
+ }
+ QR.captcha.captchas = captchas;
+ return QR.captcha.count();
+ },
+ getOne: function() {
+ var captcha;
+ this.clear();
+ if (captcha = this.captchas.shift()) {
+ this.count();
+ $.set('captchas', this.captchas);
+ return {
+ challenge: captcha.response,
+ response: 'manual_challenge'
+ };
+ } else if (/\S/.test(this.nodes.input.value)) {
+ return (function(_this) {
+ return function(cb) {
+ _this.submitCB = cb;
+ return _this.sendResponse();
+ };
+ })(this);
+ } else {
+ return null;
+ }
+ },
+ sendResponse: function() {
+ var response;
+ response = this.nodes.input.value;
+ if (/\S/.test(response)) {
+ return this.conn.send({
+ response: response
+ });
+ }
+ },
+ save: function(token) {
+ delete this.occupied;
+ this.nodes.input.value = '';
+ if (this.submitCB) {
+ this.submitCB({
+ challenge: token,
+ response: 'manual_challenge'
+ });
+ delete this.submitCB;
+ if (this.needed()) {
+ return this.reload();
+ } else {
+ return this.destroy();
+ }
+ } else {
+ $.forceSync('captchas');
+ this.captchas.push({
+ response: token,
+ timeout: this.timeout
+ });
+ this.count();
+ $.set('captchas', this.captchas);
+ return this.reload();
+ }
+ },
+ error: function(message) {
+ this.occupied = true;
+ this.nodes.input.value = '';
+ if (this.submitCB) {
+ this.submitCB();
+ delete this.submitCB;
+ }
+ return QR.error("Captcha Error: " + message);
+ },
+ clear: function() {
+ var captcha, i, k, len1, now, ref;
+ if (!this.captchas.length) {
+ return;
+ }
+ $.forceSync('captchas');
+ now = Date.now();
+ ref = this.captchas;
+ for (i = k = 0, len1 = ref.length; k < len1; i = ++k) {
+ captcha = ref[i];
+ if (captcha.timeout > now) {
+ break;
+ }
+ }
+ if (!i) {
+ return;
+ }
+ this.captchas = this.captchas.slice(i);
+ this.count();
+ return $.set('captchas', this.captchas);
+ },
+ load: function(src) {
+ var container, img, input, ref;
+ ref = this.nodes, container = ref.container, input = ref.input, img = ref.img;
+ this.occupied = true;
+ this.timeout = Date.now() + this.lifetime;
+ if (!img) {
+ img = this.nodes.img = new Image();
+ $.one(img, 'load', this.afterSetup.bind(this));
+ $.on(img, 'load', function() {
+ return this.hidden = false;
+ });
+ $.add(container, img);
+ }
+ img.src = src;
+ input.value = '';
+ this.clear();
+ clearTimeout(this.timers.expire);
+ return this.timers.expire = setTimeout(this.expire.bind(this), this.lifetime);
+ },
+ count: function() {
+ var count, placeholder;
+ count = this.captchas ? this.captchas.length : 0;
+ placeholder = this.nodes.input.placeholder.replace(/\ \(.*\)$/, '');
+ placeholder += (function() {
+ switch (count) {
+ case 0:
+ if (placeholder === 'Verification') {
+ return ' (Shift + Enter to cache)';
+ } else {
+ return '';
+ }
+ break;
+ case 1:
+ return ' (1 cached captcha)';
+ default:
+ return " (" + count + " cached captchas)";
+ }
+ })();
+ this.nodes.input.placeholder = placeholder;
+ this.nodes.input.alt = count;
+ clearTimeout(this.timers.clear);
+ if (this.captchas.length) {
+ return this.timers.clear = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now());
+ }
+ },
+ expire: function() {
+ if (!this.nodes.iframe) {
+ return;
+ }
+ if (!d.hidden && (this.needed() || d.activeElement === this.nodes.input)) {
+ return this.reload();
+ } else {
+ return this.destroy();
+ }
+ },
+ reload: function() {
+ var ref;
+ this.nodes.iframe.src = this.iframeURL();
+ this.occupied = true;
+ return (ref = this.nodes.img) != null ? ref.hidden = true : void 0;
+ },
+ keydown: function(e) {
+ if (e.keyCode === 8 && !this.nodes.input.value) {
+ if (this.nodes.iframe) {
+ this.reload();
+ } else {
+ this.setup();
+ }
+ } else if (e.keyCode === 13 && e.shiftKey) {
+ this.sendResponse();
+ } else {
+ return;
+ }
+ return e.preventDefault();
+ }
+ };
+
Captcha.v1 = {
init: function() {
var captchaContainer, imgContainer, input, script;
@@ -7836,7 +8180,7 @@
$.on(input, 'focus', QR.focusin);
$.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha));
$.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha));
- $.addClass(QR.nodes.el, 'has-captcha');
+ $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1');
$.after(QR.nodes.com.parentNode, [imgContainer, input]);
this.captchas = [];
new MutationObserver(this.afterSetup).observe($.id('captchaContainer'), {
@@ -8002,7 +8346,7 @@
counter: counter
};
this.count();
- $.addClass(QR.nodes.el, 'has-captcha');
+ $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2');
$.after(QR.nodes.com.parentNode, root);
$.on(counter, 'click', this.toggle.bind(this));
return $.on(window, 'captcha:success', (function(_this) {
@@ -8105,7 +8449,7 @@
src: this.noscriptURL()
});
$.add(this.nodes.container, iframe);
- return this.conn.target = iframe.contentWindow;
+ return this.conn.target = iframe;
},
setupJS: function() {
return $.globalEval('(function() {\n function render() {\n var container = document.querySelector("#qr .captcha-container");\n container.dataset.widgetID = window.grecaptcha.render(container, {\n sitekey: \'6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc\',\n theme: document.documentElement.classList.contains(\'tomorrow\') ? \'dark\' : \'light\',\n callback: function(response) {\n window.dispatchEvent(new CustomEvent("captcha:success", {detail: response}));\n }\n });\n }\n if (window.grecaptcha) {\n render();\n } else {\n var cbNative = window.onRecaptchaLoaded;\n window.onRecaptchaLoaded = function() {\n render();\n cbNative();\n }\n }\n})();');
@@ -16313,6 +16657,12 @@
init: function() {
var db, flatten, k, len1, pathname, ref, ref1, ref2;
if (location.hostname === 'www.google.com') {
+ if (location.pathname === '/recaptcha/api/noscript') {
+ $.ready(function() {
+ return Captcha.noscript.initFrame();
+ });
+ return;
+ }
if (location.pathname === '/recaptcha/api/fallback') {
$.ready(function() {
return Captcha.v2.initFrame();
@@ -18535,10 +18885,13 @@
" min-height: 59px;\n" +
" min-width: 302px;\n" +
"}\n" +
-".captcha-input{\n" +
+".captcha-input {\n" +
" width: 100%;\n" +
" margin: 1px 0 0;\n" +
"}\n" +
+"#qr.captcha-v1 #qr-captcha-iframe {\n" +
+" display: none;\n" +
+"}\n" +
"/* Recaptcha v2 */\n" +
"#qr .captcha-root {\n" +
" position: relative;\n" +
@@ -18563,7 +18916,7 @@
" display: block;\n" +
" width: 100%;\n" +
"}\n" +
-"#qr-captcha-iframe {\n" +
+"#qr.captcha-v2 #qr-captcha-iframe {\n" +
" width: 302px;\n" +
" height: 423px;\n" +
" border: 0;\n" +
diff --git a/builds/4chan-X-noupdate.crx b/builds/4chan-X-noupdate.crx
index 5f87d0f0b..ba6bfd8e0 100644
Binary files a/builds/4chan-X-noupdate.crx and b/builds/4chan-X-noupdate.crx differ
diff --git a/builds/4chan-X-noupdate.user.js b/builds/4chan-X-noupdate.user.js
index 364c59861..cf885a54a 100644
--- a/builds/4chan-X-noupdate.user.js
+++ b/builds/4chan-X-noupdate.user.js
@@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
-// @version 1.11.0.7
+// @version 1.11.0.8
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -16,6 +16,7 @@
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
+// @match *://www.google.com/recaptcha/api/noscript?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
@@ -400,7 +401,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.11.0.7',
+ VERSION: '1.11.0.8',
NAMESPACE: '4chan X.',
boards: {}
};
@@ -2063,13 +2064,21 @@
$.on(window, 'message', this.onMessage);
}
+ Connection.prototype.targetWindow = function() {
+ if (this.target instanceof window.HTMLIFrameElement) {
+ return this.target.contentWindow;
+ } else {
+ return this.target;
+ }
+ };
+
Connection.prototype.send = function(data) {
- return this.target.postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin);
+ return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin);
};
Connection.prototype.onMessage = function(e) {
var base1, data, type, value;
- if (!(e.source === this.target && e.origin === this.origin && typeof e.data === 'string' && e.data.slice(0, g.NAMESPACE.length) === g.NAMESPACE)) {
+ if (!(e.source === this.targetWindow() && e.origin === this.origin && typeof e.data === 'string' && e.data.slice(0, g.NAMESPACE.length) === g.NAMESPACE)) {
return;
}
data = JSON.parse(e.data.slice(g.NAMESPACE.length));
@@ -6671,7 +6680,7 @@
QR = {
mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'],
init: function() {
- var sc, version;
+ var noscript, sc, version;
if (!Conf['Quick Reply']) {
return;
}
@@ -6680,7 +6689,7 @@
if (g.VIEW === 'archive') {
return;
}
- version = Conf['Use Recaptcha v1'] ? 'v1' : 'v2';
+ version = Conf['Use Recaptcha v1'] ? (noscript = Conf['Force Noscript Captcha'] || !$.hasClass(doc, 'js-enabled'), noscript ? 'noscript' : 'v1') : 'v2';
this.captcha = Captcha[version];
$.on(d, '4chanXInitFinished', this.initReady);
Post.callbacks.push({
@@ -6834,7 +6843,7 @@
QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement);
QR.nodes.el.classList.toggle('focus', QR.hasFocus);
}
- if (QR.captcha.isEnabled && !QR.captcha.noscript) {
+ if (QR.captcha.isEnabled && QR.captcha === Captcha.v2 && !QR.captcha.noscript) {
if (QR.inCaptcha()) {
QR.scrollY = window.scrollY;
return $.on(d, 'scroll', QR.scrollLock);
@@ -7796,6 +7805,341 @@
}
};
+ Captcha.noscript = {
+ lifetime: 10 * $.MINUTE,
+ init: function() {
+ var container, input;
+ if (d.cookie.indexOf('pass_enabled=1') >= 0) {
+ return;
+ }
+ if (!(this.isEnabled = !!$.id('g-recaptcha'))) {
+ return;
+ }
+ container = $.el('div', {
+ className: 'captcha-img',
+ title: 'Reload reCAPTCHA'
+ });
+ input = $.el('input', {
+ className: 'captcha-input field',
+ title: 'Verification',
+ autocomplete: 'off',
+ spellcheck: false
+ });
+ this.nodes = {
+ container: container,
+ input: input
+ };
+ $.on(input, 'keydown', this.keydown.bind(this));
+ $.on(this.nodes.container, 'click', (function(_this) {
+ return function() {
+ _this.reload();
+ return _this.nodes.input.focus();
+ };
+ })(this));
+ this.conn = new Connection(null, location.protocol + "//www.google.com", {
+ challenge: this.load.bind(this),
+ token: this.save.bind(this),
+ error: this.error.bind(this)
+ });
+ $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1', 'noscript-captcha');
+ $.after(QR.nodes.com.parentNode, [container, input]);
+ this.captchas = [];
+ $.get('captchas', [], function(arg) {
+ var captchas;
+ captchas = arg.captchas;
+ QR.captcha.sync(captchas);
+ return QR.captcha.clear();
+ });
+ $.sync('captchas', this.sync);
+ this.beforeSetup();
+ return this.setup();
+ },
+ initFrame: function() {
+ var cb, conn, img, ref, ref1;
+ conn = new Connection(window.parent, location.protocol + "//boards.4chan.org", {
+ response: function(response) {
+ $.id('recaptcha_response_field').value = response;
+ return HTMLFormElement.prototype.submit.call($('form'));
+ }
+ });
+ if (location.hash === '#response') {
+ conn.send({
+ token: (ref = $('textarea')) != null ? ref.value : void 0,
+ error: (ref1 = $('.recaptcha_input_area')) != null ? ref1.textContent.replace(/:$/, '') : void 0
+ });
+ }
+ if (!(img = $('img'))) {
+ return;
+ }
+ $('form').action = '#response';
+ cb = function() {
+ var canvas;
+ canvas = $.el('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ canvas.getContext('2d').drawImage(img, 0, 0);
+ return conn.send({
+ challenge: canvas.toDataURL()
+ });
+ };
+ if (img.complete) {
+ return cb();
+ } else {
+ return $.on(img, 'load', cb);
+ }
+ },
+ timers: {},
+ iframeURL: function() {
+ var lang, url;
+ url = '//www.google.com/recaptcha/api/noscript?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc';
+ if (lang = Conf['captchaLanguage'].trim()) {
+ url += "&hl=" + (encodeURIComponent(lang));
+ }
+ return url;
+ },
+ cb: {
+ focus: function() {
+ return QR.captcha.setup(false, true);
+ }
+ },
+ beforeSetup: function() {
+ var container, input, ref;
+ ref = this.nodes, container = ref.container, input = ref.input;
+ container.hidden = true;
+ input.value = '';
+ input.placeholder = 'Focus to load reCAPTCHA';
+ this.count();
+ return $.on(input, 'focus click', this.cb.focus);
+ },
+ needed: function() {
+ var captchaCount, postsCount;
+ captchaCount = this.captchas.length;
+ if (QR.req) {
+ captchaCount++;
+ }
+ postsCount = QR.posts.length;
+ if (postsCount === 1 && !Conf['Auto-load captcha'] && !QR.posts[0].com && !QR.posts[0].file) {
+ postsCount = 0;
+ }
+ return captchaCount < postsCount;
+ },
+ onNewPost: function() {},
+ onPostChange: function() {},
+ setup: function(focus, force) {
+ if (!(this.isEnabled && (this.needed() || force))) {
+ return;
+ }
+ if (!this.nodes.iframe) {
+ this.nodes.iframe = $.el('iframe', {
+ id: 'qr-captcha-iframe',
+ src: this.iframeURL()
+ });
+ $.add(QR.nodes.el, this.nodes.iframe);
+ this.conn.target = this.nodes.iframe;
+ } else if (!this.occupied || force) {
+ this.nodes.iframe.src = this.iframeURL();
+ }
+ this.occupied = true;
+ if (focus) {
+ return this.nodes.input.focus();
+ }
+ },
+ afterSetup: function() {
+ var container, input, ref;
+ ref = this.nodes, container = ref.container, input = ref.input;
+ container.hidden = false;
+ input.placeholder = 'Verification';
+ this.count();
+ $.off(input, 'focus click', this.cb.focus);
+ if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
+ QR.nodes.el.style.top = '';
+ return QR.nodes.el.style.bottom = '0px';
+ }
+ },
+ destroy: function() {
+ if (!this.isEnabled) {
+ return;
+ }
+ if (this.nodes.img) {
+ $.rm(this.nodes.img);
+ }
+ delete this.nodes.img;
+ if (this.nodes.iframe) {
+ $.rm(this.nodes.iframe);
+ }
+ delete this.nodes.iframe;
+ delete this.occupied;
+ return this.beforeSetup();
+ },
+ sync: function(captchas) {
+ if (captchas == null) {
+ captchas = [];
+ }
+ QR.captcha.captchas = captchas;
+ return QR.captcha.count();
+ },
+ getOne: function() {
+ var captcha;
+ this.clear();
+ if (captcha = this.captchas.shift()) {
+ this.count();
+ $.set('captchas', this.captchas);
+ return {
+ challenge: captcha.response,
+ response: 'manual_challenge'
+ };
+ } else if (/\S/.test(this.nodes.input.value)) {
+ return (function(_this) {
+ return function(cb) {
+ _this.submitCB = cb;
+ return _this.sendResponse();
+ };
+ })(this);
+ } else {
+ return null;
+ }
+ },
+ sendResponse: function() {
+ var response;
+ response = this.nodes.input.value;
+ if (/\S/.test(response)) {
+ return this.conn.send({
+ response: response
+ });
+ }
+ },
+ save: function(token) {
+ delete this.occupied;
+ this.nodes.input.value = '';
+ if (this.submitCB) {
+ this.submitCB({
+ challenge: token,
+ response: 'manual_challenge'
+ });
+ delete this.submitCB;
+ if (this.needed()) {
+ return this.reload();
+ } else {
+ return this.destroy();
+ }
+ } else {
+ $.forceSync('captchas');
+ this.captchas.push({
+ response: token,
+ timeout: this.timeout
+ });
+ this.count();
+ $.set('captchas', this.captchas);
+ return this.reload();
+ }
+ },
+ error: function(message) {
+ this.occupied = true;
+ this.nodes.input.value = '';
+ if (this.submitCB) {
+ this.submitCB();
+ delete this.submitCB;
+ }
+ return QR.error("Captcha Error: " + message);
+ },
+ clear: function() {
+ var captcha, i, k, len1, now, ref;
+ if (!this.captchas.length) {
+ return;
+ }
+ $.forceSync('captchas');
+ now = Date.now();
+ ref = this.captchas;
+ for (i = k = 0, len1 = ref.length; k < len1; i = ++k) {
+ captcha = ref[i];
+ if (captcha.timeout > now) {
+ break;
+ }
+ }
+ if (!i) {
+ return;
+ }
+ this.captchas = this.captchas.slice(i);
+ this.count();
+ return $.set('captchas', this.captchas);
+ },
+ load: function(src) {
+ var container, img, input, ref;
+ ref = this.nodes, container = ref.container, input = ref.input, img = ref.img;
+ this.occupied = true;
+ this.timeout = Date.now() + this.lifetime;
+ if (!img) {
+ img = this.nodes.img = new Image();
+ $.one(img, 'load', this.afterSetup.bind(this));
+ $.on(img, 'load', function() {
+ return this.hidden = false;
+ });
+ $.add(container, img);
+ }
+ img.src = src;
+ input.value = '';
+ this.clear();
+ clearTimeout(this.timers.expire);
+ return this.timers.expire = setTimeout(this.expire.bind(this), this.lifetime);
+ },
+ count: function() {
+ var count, placeholder;
+ count = this.captchas ? this.captchas.length : 0;
+ placeholder = this.nodes.input.placeholder.replace(/\ \(.*\)$/, '');
+ placeholder += (function() {
+ switch (count) {
+ case 0:
+ if (placeholder === 'Verification') {
+ return ' (Shift + Enter to cache)';
+ } else {
+ return '';
+ }
+ break;
+ case 1:
+ return ' (1 cached captcha)';
+ default:
+ return " (" + count + " cached captchas)";
+ }
+ })();
+ this.nodes.input.placeholder = placeholder;
+ this.nodes.input.alt = count;
+ clearTimeout(this.timers.clear);
+ if (this.captchas.length) {
+ return this.timers.clear = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now());
+ }
+ },
+ expire: function() {
+ if (!this.nodes.iframe) {
+ return;
+ }
+ if (!d.hidden && (this.needed() || d.activeElement === this.nodes.input)) {
+ return this.reload();
+ } else {
+ return this.destroy();
+ }
+ },
+ reload: function() {
+ var ref;
+ this.nodes.iframe.src = this.iframeURL();
+ this.occupied = true;
+ return (ref = this.nodes.img) != null ? ref.hidden = true : void 0;
+ },
+ keydown: function(e) {
+ if (e.keyCode === 8 && !this.nodes.input.value) {
+ if (this.nodes.iframe) {
+ this.reload();
+ } else {
+ this.setup();
+ }
+ } else if (e.keyCode === 13 && e.shiftKey) {
+ this.sendResponse();
+ } else {
+ return;
+ }
+ return e.preventDefault();
+ }
+ };
+
Captcha.v1 = {
init: function() {
var captchaContainer, imgContainer, input, script;
@@ -7835,7 +8179,7 @@
$.on(input, 'focus', QR.focusin);
$.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha));
$.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha));
- $.addClass(QR.nodes.el, 'has-captcha');
+ $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1');
$.after(QR.nodes.com.parentNode, [imgContainer, input]);
this.captchas = [];
new MutationObserver(this.afterSetup).observe($.id('captchaContainer'), {
@@ -8001,7 +8345,7 @@
counter: counter
};
this.count();
- $.addClass(QR.nodes.el, 'has-captcha');
+ $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2');
$.after(QR.nodes.com.parentNode, root);
$.on(counter, 'click', this.toggle.bind(this));
return $.on(window, 'captcha:success', (function(_this) {
@@ -8104,7 +8448,7 @@
src: this.noscriptURL()
});
$.add(this.nodes.container, iframe);
- return this.conn.target = iframe.contentWindow;
+ return this.conn.target = iframe;
},
setupJS: function() {
return $.globalEval('(function() {\n function render() {\n var container = document.querySelector("#qr .captcha-container");\n container.dataset.widgetID = window.grecaptcha.render(container, {\n sitekey: \'6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc\',\n theme: document.documentElement.classList.contains(\'tomorrow\') ? \'dark\' : \'light\',\n callback: function(response) {\n window.dispatchEvent(new CustomEvent("captcha:success", {detail: response}));\n }\n });\n }\n if (window.grecaptcha) {\n render();\n } else {\n var cbNative = window.onRecaptchaLoaded;\n window.onRecaptchaLoaded = function() {\n render();\n cbNative();\n }\n }\n})();');
@@ -16312,6 +16656,12 @@
init: function() {
var db, flatten, k, len1, pathname, ref, ref1, ref2;
if (location.hostname === 'www.google.com') {
+ if (location.pathname === '/recaptcha/api/noscript') {
+ $.ready(function() {
+ return Captcha.noscript.initFrame();
+ });
+ return;
+ }
if (location.pathname === '/recaptcha/api/fallback') {
$.ready(function() {
return Captcha.v2.initFrame();
@@ -18534,10 +18884,13 @@
" min-height: 59px;\n" +
" min-width: 302px;\n" +
"}\n" +
-".captcha-input{\n" +
+".captcha-input {\n" +
" width: 100%;\n" +
" margin: 1px 0 0;\n" +
"}\n" +
+"#qr.captcha-v1 #qr-captcha-iframe {\n" +
+" display: none;\n" +
+"}\n" +
"/* Recaptcha v2 */\n" +
"#qr .captcha-root {\n" +
" position: relative;\n" +
@@ -18562,7 +18915,7 @@
" display: block;\n" +
" width: 100%;\n" +
"}\n" +
-"#qr-captcha-iframe {\n" +
+"#qr.captcha-v2 #qr-captcha-iframe {\n" +
" width: 302px;\n" +
" height: 423px;\n" +
" border: 0;\n" +
diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx
index 206dfffff..aede57ed8 100644
Binary files a/builds/4chan-X.crx and b/builds/4chan-X.crx differ
diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js
index c83e2ea68..e2f04beba 100644
--- a/builds/4chan-X.meta.js
+++ b/builds/4chan-X.meta.js
@@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X
-// @version 1.11.0.7
+// @version 1.11.0.8
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -15,6 +15,7 @@
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
+// @match *://www.google.com/recaptcha/api/noscript?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js
index df7e98a17..be661b546 100644
--- a/builds/4chan-X.user.js
+++ b/builds/4chan-X.user.js
@@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
-// @version 1.11.0.7
+// @version 1.11.0.8
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -16,6 +16,7 @@
// @match https://www.google.com/recaptcha/api2/anchor?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match https://www.google.com/recaptcha/api2/frame?*&k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @match *://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
+// @match *://www.google.com/recaptcha/api/noscript?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
@@ -401,7 +402,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.11.0.7',
+ VERSION: '1.11.0.8',
NAMESPACE: '4chan X.',
boards: {}
};
@@ -2064,13 +2065,21 @@
$.on(window, 'message', this.onMessage);
}
+ Connection.prototype.targetWindow = function() {
+ if (this.target instanceof window.HTMLIFrameElement) {
+ return this.target.contentWindow;
+ } else {
+ return this.target;
+ }
+ };
+
Connection.prototype.send = function(data) {
- return this.target.postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin);
+ return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin);
};
Connection.prototype.onMessage = function(e) {
var base1, data, type, value;
- if (!(e.source === this.target && e.origin === this.origin && typeof e.data === 'string' && e.data.slice(0, g.NAMESPACE.length) === g.NAMESPACE)) {
+ if (!(e.source === this.targetWindow() && e.origin === this.origin && typeof e.data === 'string' && e.data.slice(0, g.NAMESPACE.length) === g.NAMESPACE)) {
return;
}
data = JSON.parse(e.data.slice(g.NAMESPACE.length));
@@ -6672,7 +6681,7 @@
QR = {
mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'],
init: function() {
- var sc, version;
+ var noscript, sc, version;
if (!Conf['Quick Reply']) {
return;
}
@@ -6681,7 +6690,7 @@
if (g.VIEW === 'archive') {
return;
}
- version = Conf['Use Recaptcha v1'] ? 'v1' : 'v2';
+ version = Conf['Use Recaptcha v1'] ? (noscript = Conf['Force Noscript Captcha'] || !$.hasClass(doc, 'js-enabled'), noscript ? 'noscript' : 'v1') : 'v2';
this.captcha = Captcha[version];
$.on(d, '4chanXInitFinished', this.initReady);
Post.callbacks.push({
@@ -6835,7 +6844,7 @@
QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement);
QR.nodes.el.classList.toggle('focus', QR.hasFocus);
}
- if (QR.captcha.isEnabled && !QR.captcha.noscript) {
+ if (QR.captcha.isEnabled && QR.captcha === Captcha.v2 && !QR.captcha.noscript) {
if (QR.inCaptcha()) {
QR.scrollY = window.scrollY;
return $.on(d, 'scroll', QR.scrollLock);
@@ -7797,6 +7806,341 @@
}
};
+ Captcha.noscript = {
+ lifetime: 10 * $.MINUTE,
+ init: function() {
+ var container, input;
+ if (d.cookie.indexOf('pass_enabled=1') >= 0) {
+ return;
+ }
+ if (!(this.isEnabled = !!$.id('g-recaptcha'))) {
+ return;
+ }
+ container = $.el('div', {
+ className: 'captcha-img',
+ title: 'Reload reCAPTCHA'
+ });
+ input = $.el('input', {
+ className: 'captcha-input field',
+ title: 'Verification',
+ autocomplete: 'off',
+ spellcheck: false
+ });
+ this.nodes = {
+ container: container,
+ input: input
+ };
+ $.on(input, 'keydown', this.keydown.bind(this));
+ $.on(this.nodes.container, 'click', (function(_this) {
+ return function() {
+ _this.reload();
+ return _this.nodes.input.focus();
+ };
+ })(this));
+ this.conn = new Connection(null, location.protocol + "//www.google.com", {
+ challenge: this.load.bind(this),
+ token: this.save.bind(this),
+ error: this.error.bind(this)
+ });
+ $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1', 'noscript-captcha');
+ $.after(QR.nodes.com.parentNode, [container, input]);
+ this.captchas = [];
+ $.get('captchas', [], function(arg) {
+ var captchas;
+ captchas = arg.captchas;
+ QR.captcha.sync(captchas);
+ return QR.captcha.clear();
+ });
+ $.sync('captchas', this.sync);
+ this.beforeSetup();
+ return this.setup();
+ },
+ initFrame: function() {
+ var cb, conn, img, ref, ref1;
+ conn = new Connection(window.parent, location.protocol + "//boards.4chan.org", {
+ response: function(response) {
+ $.id('recaptcha_response_field').value = response;
+ return HTMLFormElement.prototype.submit.call($('form'));
+ }
+ });
+ if (location.hash === '#response') {
+ conn.send({
+ token: (ref = $('textarea')) != null ? ref.value : void 0,
+ error: (ref1 = $('.recaptcha_input_area')) != null ? ref1.textContent.replace(/:$/, '') : void 0
+ });
+ }
+ if (!(img = $('img'))) {
+ return;
+ }
+ $('form').action = '#response';
+ cb = function() {
+ var canvas;
+ canvas = $.el('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ canvas.getContext('2d').drawImage(img, 0, 0);
+ return conn.send({
+ challenge: canvas.toDataURL()
+ });
+ };
+ if (img.complete) {
+ return cb();
+ } else {
+ return $.on(img, 'load', cb);
+ }
+ },
+ timers: {},
+ iframeURL: function() {
+ var lang, url;
+ url = '//www.google.com/recaptcha/api/noscript?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc';
+ if (lang = Conf['captchaLanguage'].trim()) {
+ url += "&hl=" + (encodeURIComponent(lang));
+ }
+ return url;
+ },
+ cb: {
+ focus: function() {
+ return QR.captcha.setup(false, true);
+ }
+ },
+ beforeSetup: function() {
+ var container, input, ref;
+ ref = this.nodes, container = ref.container, input = ref.input;
+ container.hidden = true;
+ input.value = '';
+ input.placeholder = 'Focus to load reCAPTCHA';
+ this.count();
+ return $.on(input, 'focus click', this.cb.focus);
+ },
+ needed: function() {
+ var captchaCount, postsCount;
+ captchaCount = this.captchas.length;
+ if (QR.req) {
+ captchaCount++;
+ }
+ postsCount = QR.posts.length;
+ if (postsCount === 1 && !Conf['Auto-load captcha'] && !QR.posts[0].com && !QR.posts[0].file) {
+ postsCount = 0;
+ }
+ return captchaCount < postsCount;
+ },
+ onNewPost: function() {},
+ onPostChange: function() {},
+ setup: function(focus, force) {
+ if (!(this.isEnabled && (this.needed() || force))) {
+ return;
+ }
+ if (!this.nodes.iframe) {
+ this.nodes.iframe = $.el('iframe', {
+ id: 'qr-captcha-iframe',
+ src: this.iframeURL()
+ });
+ $.add(QR.nodes.el, this.nodes.iframe);
+ this.conn.target = this.nodes.iframe;
+ } else if (!this.occupied || force) {
+ this.nodes.iframe.src = this.iframeURL();
+ }
+ this.occupied = true;
+ if (focus) {
+ return this.nodes.input.focus();
+ }
+ },
+ afterSetup: function() {
+ var container, input, ref;
+ ref = this.nodes, container = ref.container, input = ref.input;
+ container.hidden = false;
+ input.placeholder = 'Verification';
+ this.count();
+ $.off(input, 'focus click', this.cb.focus);
+ if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
+ QR.nodes.el.style.top = '';
+ return QR.nodes.el.style.bottom = '0px';
+ }
+ },
+ destroy: function() {
+ if (!this.isEnabled) {
+ return;
+ }
+ if (this.nodes.img) {
+ $.rm(this.nodes.img);
+ }
+ delete this.nodes.img;
+ if (this.nodes.iframe) {
+ $.rm(this.nodes.iframe);
+ }
+ delete this.nodes.iframe;
+ delete this.occupied;
+ return this.beforeSetup();
+ },
+ sync: function(captchas) {
+ if (captchas == null) {
+ captchas = [];
+ }
+ QR.captcha.captchas = captchas;
+ return QR.captcha.count();
+ },
+ getOne: function() {
+ var captcha;
+ this.clear();
+ if (captcha = this.captchas.shift()) {
+ this.count();
+ $.set('captchas', this.captchas);
+ return {
+ challenge: captcha.response,
+ response: 'manual_challenge'
+ };
+ } else if (/\S/.test(this.nodes.input.value)) {
+ return (function(_this) {
+ return function(cb) {
+ _this.submitCB = cb;
+ return _this.sendResponse();
+ };
+ })(this);
+ } else {
+ return null;
+ }
+ },
+ sendResponse: function() {
+ var response;
+ response = this.nodes.input.value;
+ if (/\S/.test(response)) {
+ return this.conn.send({
+ response: response
+ });
+ }
+ },
+ save: function(token) {
+ delete this.occupied;
+ this.nodes.input.value = '';
+ if (this.submitCB) {
+ this.submitCB({
+ challenge: token,
+ response: 'manual_challenge'
+ });
+ delete this.submitCB;
+ if (this.needed()) {
+ return this.reload();
+ } else {
+ return this.destroy();
+ }
+ } else {
+ $.forceSync('captchas');
+ this.captchas.push({
+ response: token,
+ timeout: this.timeout
+ });
+ this.count();
+ $.set('captchas', this.captchas);
+ return this.reload();
+ }
+ },
+ error: function(message) {
+ this.occupied = true;
+ this.nodes.input.value = '';
+ if (this.submitCB) {
+ this.submitCB();
+ delete this.submitCB;
+ }
+ return QR.error("Captcha Error: " + message);
+ },
+ clear: function() {
+ var captcha, i, k, len1, now, ref;
+ if (!this.captchas.length) {
+ return;
+ }
+ $.forceSync('captchas');
+ now = Date.now();
+ ref = this.captchas;
+ for (i = k = 0, len1 = ref.length; k < len1; i = ++k) {
+ captcha = ref[i];
+ if (captcha.timeout > now) {
+ break;
+ }
+ }
+ if (!i) {
+ return;
+ }
+ this.captchas = this.captchas.slice(i);
+ this.count();
+ return $.set('captchas', this.captchas);
+ },
+ load: function(src) {
+ var container, img, input, ref;
+ ref = this.nodes, container = ref.container, input = ref.input, img = ref.img;
+ this.occupied = true;
+ this.timeout = Date.now() + this.lifetime;
+ if (!img) {
+ img = this.nodes.img = new Image();
+ $.one(img, 'load', this.afterSetup.bind(this));
+ $.on(img, 'load', function() {
+ return this.hidden = false;
+ });
+ $.add(container, img);
+ }
+ img.src = src;
+ input.value = '';
+ this.clear();
+ clearTimeout(this.timers.expire);
+ return this.timers.expire = setTimeout(this.expire.bind(this), this.lifetime);
+ },
+ count: function() {
+ var count, placeholder;
+ count = this.captchas ? this.captchas.length : 0;
+ placeholder = this.nodes.input.placeholder.replace(/\ \(.*\)$/, '');
+ placeholder += (function() {
+ switch (count) {
+ case 0:
+ if (placeholder === 'Verification') {
+ return ' (Shift + Enter to cache)';
+ } else {
+ return '';
+ }
+ break;
+ case 1:
+ return ' (1 cached captcha)';
+ default:
+ return " (" + count + " cached captchas)";
+ }
+ })();
+ this.nodes.input.placeholder = placeholder;
+ this.nodes.input.alt = count;
+ clearTimeout(this.timers.clear);
+ if (this.captchas.length) {
+ return this.timers.clear = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now());
+ }
+ },
+ expire: function() {
+ if (!this.nodes.iframe) {
+ return;
+ }
+ if (!d.hidden && (this.needed() || d.activeElement === this.nodes.input)) {
+ return this.reload();
+ } else {
+ return this.destroy();
+ }
+ },
+ reload: function() {
+ var ref;
+ this.nodes.iframe.src = this.iframeURL();
+ this.occupied = true;
+ return (ref = this.nodes.img) != null ? ref.hidden = true : void 0;
+ },
+ keydown: function(e) {
+ if (e.keyCode === 8 && !this.nodes.input.value) {
+ if (this.nodes.iframe) {
+ this.reload();
+ } else {
+ this.setup();
+ }
+ } else if (e.keyCode === 13 && e.shiftKey) {
+ this.sendResponse();
+ } else {
+ return;
+ }
+ return e.preventDefault();
+ }
+ };
+
Captcha.v1 = {
init: function() {
var captchaContainer, imgContainer, input, script;
@@ -7836,7 +8180,7 @@
$.on(input, 'focus', QR.focusin);
$.on(input, 'keydown', QR.captcha.keydown.bind(QR.captcha));
$.on(this.nodes.img.parentNode, 'click', QR.captcha.reload.bind(QR.captcha));
- $.addClass(QR.nodes.el, 'has-captcha');
+ $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v1');
$.after(QR.nodes.com.parentNode, [imgContainer, input]);
this.captchas = [];
new MutationObserver(this.afterSetup).observe($.id('captchaContainer'), {
@@ -8002,7 +8346,7 @@
counter: counter
};
this.count();
- $.addClass(QR.nodes.el, 'has-captcha');
+ $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2');
$.after(QR.nodes.com.parentNode, root);
$.on(counter, 'click', this.toggle.bind(this));
return $.on(window, 'captcha:success', (function(_this) {
@@ -8105,7 +8449,7 @@
src: this.noscriptURL()
});
$.add(this.nodes.container, iframe);
- return this.conn.target = iframe.contentWindow;
+ return this.conn.target = iframe;
},
setupJS: function() {
return $.globalEval('(function() {\n function render() {\n var container = document.querySelector("#qr .captcha-container");\n container.dataset.widgetID = window.grecaptcha.render(container, {\n sitekey: \'6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc\',\n theme: document.documentElement.classList.contains(\'tomorrow\') ? \'dark\' : \'light\',\n callback: function(response) {\n window.dispatchEvent(new CustomEvent("captcha:success", {detail: response}));\n }\n });\n }\n if (window.grecaptcha) {\n render();\n } else {\n var cbNative = window.onRecaptchaLoaded;\n window.onRecaptchaLoaded = function() {\n render();\n cbNative();\n }\n }\n})();');
@@ -16313,6 +16657,12 @@
init: function() {
var db, flatten, k, len1, pathname, ref, ref1, ref2;
if (location.hostname === 'www.google.com') {
+ if (location.pathname === '/recaptcha/api/noscript') {
+ $.ready(function() {
+ return Captcha.noscript.initFrame();
+ });
+ return;
+ }
if (location.pathname === '/recaptcha/api/fallback') {
$.ready(function() {
return Captcha.v2.initFrame();
@@ -18535,10 +18885,13 @@
" min-height: 59px;\n" +
" min-width: 302px;\n" +
"}\n" +
-".captcha-input{\n" +
+".captcha-input {\n" +
" width: 100%;\n" +
" margin: 1px 0 0;\n" +
"}\n" +
+"#qr.captcha-v1 #qr-captcha-iframe {\n" +
+" display: none;\n" +
+"}\n" +
"/* Recaptcha v2 */\n" +
"#qr .captcha-root {\n" +
" position: relative;\n" +
@@ -18563,7 +18916,7 @@
" display: block;\n" +
" width: 100%;\n" +
"}\n" +
-"#qr-captcha-iframe {\n" +
+"#qr.captcha-v2 #qr-captcha-iframe {\n" +
" width: 302px;\n" +
" height: 423px;\n" +
" border: 0;\n" +
diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip
index 7f9577dbc..3dc874015 100644
Binary files a/builds/4chan-X.zip and b/builds/4chan-X.zip differ
diff --git a/builds/updates-beta.xml b/builds/updates-beta.xml
index 9d143416a..fc794c866 100644
--- a/builds/updates-beta.xml
+++ b/builds/updates-beta.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/builds/updates.xml b/builds/updates.xml
index 36ea57ded..1eeca5801 100644
--- a/builds/updates.xml
+++ b/builds/updates.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/package.json b/package.json
index 08c34a967..98020470d 100755
--- a/package.json
+++ b/package.json
@@ -3,8 +3,8 @@
"description": "Cross-browser userscript for maximum lurking on 4chan.",
"meta": {
"name": "4chan X",
- "version": "1.11.0.7",
- "date": "2015-06-21T17:20:52.716Z",
+ "version": "1.11.0.8",
+ "date": "2015-06-21T22:29:51.283Z",
"repo": "https://github.com/ccd0/4chan-x/",
"page": "https://github.com/ccd0/4chan-x",
"downloads": "https://ccd0.github.io/4chan-x/builds/",