diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4379584f7..f2263db28 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,9 @@ The links to individual versions below are to copies of the script with the upda
## v1.11.0
+**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.
+
**v1.11.0.6** *(2015-06-20)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.6/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.11.0.6/builds/4chan-X-noupdate.crx "Chromium version")]
- Support toggling images in the captcha with the number keys (as arranged in the numpad) and the UIOJKLM,. keys.
- Arrow key navigation now works in noscript captcha.
diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx
index 9bfbaa0d9..df1d14615 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 6b927ebda..63a668f0f 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.6
+// @version 1.11.0.7
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
diff --git a/builds/4chan-X-beta.user.js b/builds/4chan-X-beta.user.js
index bd2c64c83..db361c661 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.6
+// @version 1.11.0.7
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -233,6 +233,7 @@
'Hide Original Post Form': [true, 'Hide the normal post form.', 1],
'Cooldown': [true, 'Indicate the remaining time before posting again.', 1],
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.', 1],
+ 'Use Recaptcha v1': [false, 'Use the old text version of Recaptcha.', 1],
'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1],
'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1],
'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1],
@@ -400,7 +401,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.11.0.6',
+ VERSION: '1.11.0.7',
NAMESPACE: '4chan X.',
boards: {}
};
@@ -6671,7 +6672,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;
+ var sc, version;
if (!Conf['Quick Reply']) {
return;
}
@@ -6680,7 +6681,8 @@
if (g.VIEW === 'archive') {
return;
}
- this.captcha = Captcha.v2;
+ version = Conf['Use Recaptcha v1'] ? 'v1' : 'v2';
+ this.captcha = Captcha[version];
$.on(d, '4chanXInitFinished', this.initReady);
Post.callbacks.push({
name: 'Quick Reply',
@@ -7456,7 +7458,12 @@
};
cb = function(response) {
if (response != null) {
- extra.form.append('g-recaptcha-response', response);
+ if (response.challenge != null) {
+ extra.form.append('recaptcha_challenge_field', response.challenge);
+ extra.form.append('recaptcha_response_field', response.response);
+ } else {
+ extra.form.append('g-recaptcha-response', response);
+ }
}
QR.req = $.ajax("https://sys.4chan.org/" + g.BOARD + "/post", options, extra);
return QR.req.progress = '...';
@@ -7790,6 +7797,172 @@
}
};
+ Captcha.v1 = {
+ init: function() {
+ var captchaContainer, imgContainer, input, script;
+ if (d.cookie.indexOf('pass_enabled=1') >= 0) {
+ return;
+ }
+ if (!(this.isEnabled = !!$.id('g-recaptcha'))) {
+ return;
+ }
+ script = $.el('script', {
+ src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js'
+ });
+ $.add(d.head, script);
+ captchaContainer = $.el('div', {
+ id: 'captchaContainer',
+ hidden: true
+ });
+ $.add(d.body, captchaContainer);
+ imgContainer = $.el('div', {
+ className: 'captcha-img',
+ title: 'Reload reCAPTCHA'
+ });
+ $.extend(imgContainer, {
+ innerHTML: "
"
+ });
+ input = $.el('input', {
+ className: 'captcha-input field',
+ title: 'Verification',
+ autocomplete: 'off',
+ spellcheck: false
+ });
+ this.nodes = {
+ img: imgContainer.firstChild,
+ input: input
+ };
+ $.on(input, 'blur', QR.focusout);
+ $.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');
+ $.after(QR.nodes.com.parentNode, [imgContainer, input]);
+ this.captchas = [];
+ new MutationObserver(this.afterSetup).observe($.id('captchaContainer'), {
+ childList: true
+ });
+ this.beforeSetup();
+ if (Conf['Auto-load captcha']) {
+ return this.setup();
+ }
+ },
+ cb: {
+ focus: function() {
+ return QR.captcha.setup(false, true);
+ }
+ },
+ beforeSetup: function() {
+ var img, input, ref;
+ ref = this.nodes, img = ref.img, input = ref.input;
+ img.parentNode.hidden = true;
+ input.value = '';
+ input.placeholder = 'Focus to load reCAPTCHA';
+ 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;
+ }
+ $.globalEval('(function() {\n var captchaContainer = document.getElementById("captchaContainer");\n if (captchaContainer.firstChild) return;\n function setup() {\n if (window.Recaptcha) {\n Recaptcha.create(recaptchaKey, captchaContainer, {theme: "clean"});\n } else {\n setTimeout(setup, 25);\n }\n }\n setup();\n})()');
+ if (focus) {
+ return this.nodes.input.focus();
+ }
+ },
+ afterSetup: function() {
+ var challenge, img, input, ref, setLifetime;
+ if (!(challenge = $.id('recaptcha_challenge_field_holder'))) {
+ return;
+ }
+ if (challenge === QR.captcha.nodes.challenge) {
+ return;
+ }
+ setLifetime = function(e) {
+ return QR.captcha.lifetime = e.detail;
+ };
+ $.on(window, 'captcha:timeout', setLifetime);
+ $.globalEval('window.dispatchEvent(new CustomEvent("captcha:timeout", {detail: RecaptchaState.timeout}))');
+ $.off(window, 'captcha:timeout', setLifetime);
+ ref = QR.captcha.nodes, img = ref.img, input = ref.input;
+ img.parentNode.hidden = false;
+ input.placeholder = 'Verification';
+ $.off(input, 'focus click', QR.captcha.cb.focus);
+ QR.captcha.nodes.challenge = challenge;
+ new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, {
+ childList: true,
+ subtree: true,
+ attributes: true
+ });
+ QR.captcha.load();
+ if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
+ QR.nodes.el.style.top = null;
+ return QR.nodes.el.style.bottom = '0px';
+ }
+ },
+ destroy: function() {
+ if (!this.isEnabled) {
+ return;
+ }
+ $.globalEval('Recaptcha.destroy()');
+ return this.beforeSetup();
+ },
+ getOne: function() {
+ var challenge, response;
+ challenge = this.nodes.img.alt;
+ if (/\S/.test(response = this.nodes.input.value)) {
+ this.destroy();
+ return {
+ challenge: challenge,
+ response: response
+ };
+ } else {
+ return null;
+ }
+ },
+ load: function() {
+ var challenge, challenge_image;
+ if (!this.nodes.challenge.firstChild) {
+ return;
+ }
+ if (!(challenge_image = $.id('recaptcha_challenge_image'))) {
+ return;
+ }
+ this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE;
+ challenge = this.nodes.challenge.firstChild.value;
+ this.nodes.img.alt = challenge;
+ this.nodes.img.src = challenge_image.src;
+ return this.nodes.input.value = null;
+ },
+ reload: function(focus) {
+ $.globalEval('Recaptcha.reload(); Recaptcha.should_focus = false;');
+ if (focus) {
+ return this.nodes.input.focus();
+ }
+ },
+ keydown: function(e) {
+ if (e.keyCode === 8 && !this.nodes.input.value) {
+ this.reload();
+ } else {
+ return;
+ }
+ return e.preventDefault();
+ }
+ };
+
Captcha.v2 = {
lifetime: 2 * $.MINUTE,
init: function() {
@@ -18280,6 +18453,7 @@
"#qr > form {\n" +
" max-height: calc(100vh - 75px);\n" +
" overflow-y: auto;\n" +
+" overflow-x: hidden;\n" +
"}\n" +
"#qrtab {\n" +
" border-radius: 3px 3px 0 0;\n" +
@@ -18352,7 +18526,20 @@
" position: relative;\n" +
" top: 2px;\n" +
"}\n" +
-"/* Captcha */\n" +
+"/* Recaptcha v1 */\n" +
+".captcha-img {\n" +
+" margin: 0px;\n" +
+" text-align: center;\n" +
+" background-image: #fff;\n" +
+" font-size: 0px;\n" +
+" min-height: 59px;\n" +
+" min-width: 302px;\n" +
+"}\n" +
+".captcha-input{\n" +
+" width: 100%;\n" +
+" margin: 1px 0 0;\n" +
+"}\n" +
+"/* Recaptcha v2 */\n" +
"#qr .captcha-root {\n" +
" position: relative;\n" +
"}\n" +
diff --git a/builds/4chan-X-noupdate.crx b/builds/4chan-X-noupdate.crx
index c0da5c73a..5f87d0f0b 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 af7e124d4..364c59861 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.6
+// @version 1.11.0.7
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -232,6 +232,7 @@
'Hide Original Post Form': [true, 'Hide the normal post form.', 1],
'Cooldown': [true, 'Indicate the remaining time before posting again.', 1],
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.', 1],
+ 'Use Recaptcha v1': [false, 'Use the old text version of Recaptcha.', 1],
'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1],
'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1],
'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1],
@@ -399,7 +400,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.11.0.6',
+ VERSION: '1.11.0.7',
NAMESPACE: '4chan X.',
boards: {}
};
@@ -6670,7 +6671,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;
+ var sc, version;
if (!Conf['Quick Reply']) {
return;
}
@@ -6679,7 +6680,8 @@
if (g.VIEW === 'archive') {
return;
}
- this.captcha = Captcha.v2;
+ version = Conf['Use Recaptcha v1'] ? 'v1' : 'v2';
+ this.captcha = Captcha[version];
$.on(d, '4chanXInitFinished', this.initReady);
Post.callbacks.push({
name: 'Quick Reply',
@@ -7455,7 +7457,12 @@
};
cb = function(response) {
if (response != null) {
- extra.form.append('g-recaptcha-response', response);
+ if (response.challenge != null) {
+ extra.form.append('recaptcha_challenge_field', response.challenge);
+ extra.form.append('recaptcha_response_field', response.response);
+ } else {
+ extra.form.append('g-recaptcha-response', response);
+ }
}
QR.req = $.ajax("https://sys.4chan.org/" + g.BOARD + "/post", options, extra);
return QR.req.progress = '...';
@@ -7789,6 +7796,172 @@
}
};
+ Captcha.v1 = {
+ init: function() {
+ var captchaContainer, imgContainer, input, script;
+ if (d.cookie.indexOf('pass_enabled=1') >= 0) {
+ return;
+ }
+ if (!(this.isEnabled = !!$.id('g-recaptcha'))) {
+ return;
+ }
+ script = $.el('script', {
+ src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js'
+ });
+ $.add(d.head, script);
+ captchaContainer = $.el('div', {
+ id: 'captchaContainer',
+ hidden: true
+ });
+ $.add(d.body, captchaContainer);
+ imgContainer = $.el('div', {
+ className: 'captcha-img',
+ title: 'Reload reCAPTCHA'
+ });
+ $.extend(imgContainer, {
+ innerHTML: "
"
+ });
+ input = $.el('input', {
+ className: 'captcha-input field',
+ title: 'Verification',
+ autocomplete: 'off',
+ spellcheck: false
+ });
+ this.nodes = {
+ img: imgContainer.firstChild,
+ input: input
+ };
+ $.on(input, 'blur', QR.focusout);
+ $.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');
+ $.after(QR.nodes.com.parentNode, [imgContainer, input]);
+ this.captchas = [];
+ new MutationObserver(this.afterSetup).observe($.id('captchaContainer'), {
+ childList: true
+ });
+ this.beforeSetup();
+ if (Conf['Auto-load captcha']) {
+ return this.setup();
+ }
+ },
+ cb: {
+ focus: function() {
+ return QR.captcha.setup(false, true);
+ }
+ },
+ beforeSetup: function() {
+ var img, input, ref;
+ ref = this.nodes, img = ref.img, input = ref.input;
+ img.parentNode.hidden = true;
+ input.value = '';
+ input.placeholder = 'Focus to load reCAPTCHA';
+ 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;
+ }
+ $.globalEval('(function() {\n var captchaContainer = document.getElementById("captchaContainer");\n if (captchaContainer.firstChild) return;\n function setup() {\n if (window.Recaptcha) {\n Recaptcha.create(recaptchaKey, captchaContainer, {theme: "clean"});\n } else {\n setTimeout(setup, 25);\n }\n }\n setup();\n})()');
+ if (focus) {
+ return this.nodes.input.focus();
+ }
+ },
+ afterSetup: function() {
+ var challenge, img, input, ref, setLifetime;
+ if (!(challenge = $.id('recaptcha_challenge_field_holder'))) {
+ return;
+ }
+ if (challenge === QR.captcha.nodes.challenge) {
+ return;
+ }
+ setLifetime = function(e) {
+ return QR.captcha.lifetime = e.detail;
+ };
+ $.on(window, 'captcha:timeout', setLifetime);
+ $.globalEval('window.dispatchEvent(new CustomEvent("captcha:timeout", {detail: RecaptchaState.timeout}))');
+ $.off(window, 'captcha:timeout', setLifetime);
+ ref = QR.captcha.nodes, img = ref.img, input = ref.input;
+ img.parentNode.hidden = false;
+ input.placeholder = 'Verification';
+ $.off(input, 'focus click', QR.captcha.cb.focus);
+ QR.captcha.nodes.challenge = challenge;
+ new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, {
+ childList: true,
+ subtree: true,
+ attributes: true
+ });
+ QR.captcha.load();
+ if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
+ QR.nodes.el.style.top = null;
+ return QR.nodes.el.style.bottom = '0px';
+ }
+ },
+ destroy: function() {
+ if (!this.isEnabled) {
+ return;
+ }
+ $.globalEval('Recaptcha.destroy()');
+ return this.beforeSetup();
+ },
+ getOne: function() {
+ var challenge, response;
+ challenge = this.nodes.img.alt;
+ if (/\S/.test(response = this.nodes.input.value)) {
+ this.destroy();
+ return {
+ challenge: challenge,
+ response: response
+ };
+ } else {
+ return null;
+ }
+ },
+ load: function() {
+ var challenge, challenge_image;
+ if (!this.nodes.challenge.firstChild) {
+ return;
+ }
+ if (!(challenge_image = $.id('recaptcha_challenge_image'))) {
+ return;
+ }
+ this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE;
+ challenge = this.nodes.challenge.firstChild.value;
+ this.nodes.img.alt = challenge;
+ this.nodes.img.src = challenge_image.src;
+ return this.nodes.input.value = null;
+ },
+ reload: function(focus) {
+ $.globalEval('Recaptcha.reload(); Recaptcha.should_focus = false;');
+ if (focus) {
+ return this.nodes.input.focus();
+ }
+ },
+ keydown: function(e) {
+ if (e.keyCode === 8 && !this.nodes.input.value) {
+ this.reload();
+ } else {
+ return;
+ }
+ return e.preventDefault();
+ }
+ };
+
Captcha.v2 = {
lifetime: 2 * $.MINUTE,
init: function() {
@@ -18279,6 +18452,7 @@
"#qr > form {\n" +
" max-height: calc(100vh - 75px);\n" +
" overflow-y: auto;\n" +
+" overflow-x: hidden;\n" +
"}\n" +
"#qrtab {\n" +
" border-radius: 3px 3px 0 0;\n" +
@@ -18351,7 +18525,20 @@
" position: relative;\n" +
" top: 2px;\n" +
"}\n" +
-"/* Captcha */\n" +
+"/* Recaptcha v1 */\n" +
+".captcha-img {\n" +
+" margin: 0px;\n" +
+" text-align: center;\n" +
+" background-image: #fff;\n" +
+" font-size: 0px;\n" +
+" min-height: 59px;\n" +
+" min-width: 302px;\n" +
+"}\n" +
+".captcha-input{\n" +
+" width: 100%;\n" +
+" margin: 1px 0 0;\n" +
+"}\n" +
+"/* Recaptcha v2 */\n" +
"#qr .captcha-root {\n" +
" position: relative;\n" +
"}\n" +
diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx
index 55623a0c3..206dfffff 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 f5f8087d6..c83e2ea68 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.6
+// @version 1.11.0.7
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js
index b9841fb38..df7e98a17 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.6
+// @version 1.11.0.7
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -233,6 +233,7 @@
'Hide Original Post Form': [true, 'Hide the normal post form.', 1],
'Cooldown': [true, 'Indicate the remaining time before posting again.', 1],
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.', 1],
+ 'Use Recaptcha v1': [false, 'Use the old text version of Recaptcha.', 1],
'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.', 1],
'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1],
'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1],
@@ -400,7 +401,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.11.0.6',
+ VERSION: '1.11.0.7',
NAMESPACE: '4chan X.',
boards: {}
};
@@ -6671,7 +6672,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;
+ var sc, version;
if (!Conf['Quick Reply']) {
return;
}
@@ -6680,7 +6681,8 @@
if (g.VIEW === 'archive') {
return;
}
- this.captcha = Captcha.v2;
+ version = Conf['Use Recaptcha v1'] ? 'v1' : 'v2';
+ this.captcha = Captcha[version];
$.on(d, '4chanXInitFinished', this.initReady);
Post.callbacks.push({
name: 'Quick Reply',
@@ -7456,7 +7458,12 @@
};
cb = function(response) {
if (response != null) {
- extra.form.append('g-recaptcha-response', response);
+ if (response.challenge != null) {
+ extra.form.append('recaptcha_challenge_field', response.challenge);
+ extra.form.append('recaptcha_response_field', response.response);
+ } else {
+ extra.form.append('g-recaptcha-response', response);
+ }
}
QR.req = $.ajax("https://sys.4chan.org/" + g.BOARD + "/post", options, extra);
return QR.req.progress = '...';
@@ -7790,6 +7797,172 @@
}
};
+ Captcha.v1 = {
+ init: function() {
+ var captchaContainer, imgContainer, input, script;
+ if (d.cookie.indexOf('pass_enabled=1') >= 0) {
+ return;
+ }
+ if (!(this.isEnabled = !!$.id('g-recaptcha'))) {
+ return;
+ }
+ script = $.el('script', {
+ src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js'
+ });
+ $.add(d.head, script);
+ captchaContainer = $.el('div', {
+ id: 'captchaContainer',
+ hidden: true
+ });
+ $.add(d.body, captchaContainer);
+ imgContainer = $.el('div', {
+ className: 'captcha-img',
+ title: 'Reload reCAPTCHA'
+ });
+ $.extend(imgContainer, {
+ innerHTML: "
"
+ });
+ input = $.el('input', {
+ className: 'captcha-input field',
+ title: 'Verification',
+ autocomplete: 'off',
+ spellcheck: false
+ });
+ this.nodes = {
+ img: imgContainer.firstChild,
+ input: input
+ };
+ $.on(input, 'blur', QR.focusout);
+ $.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');
+ $.after(QR.nodes.com.parentNode, [imgContainer, input]);
+ this.captchas = [];
+ new MutationObserver(this.afterSetup).observe($.id('captchaContainer'), {
+ childList: true
+ });
+ this.beforeSetup();
+ if (Conf['Auto-load captcha']) {
+ return this.setup();
+ }
+ },
+ cb: {
+ focus: function() {
+ return QR.captcha.setup(false, true);
+ }
+ },
+ beforeSetup: function() {
+ var img, input, ref;
+ ref = this.nodes, img = ref.img, input = ref.input;
+ img.parentNode.hidden = true;
+ input.value = '';
+ input.placeholder = 'Focus to load reCAPTCHA';
+ 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;
+ }
+ $.globalEval('(function() {\n var captchaContainer = document.getElementById("captchaContainer");\n if (captchaContainer.firstChild) return;\n function setup() {\n if (window.Recaptcha) {\n Recaptcha.create(recaptchaKey, captchaContainer, {theme: "clean"});\n } else {\n setTimeout(setup, 25);\n }\n }\n setup();\n})()');
+ if (focus) {
+ return this.nodes.input.focus();
+ }
+ },
+ afterSetup: function() {
+ var challenge, img, input, ref, setLifetime;
+ if (!(challenge = $.id('recaptcha_challenge_field_holder'))) {
+ return;
+ }
+ if (challenge === QR.captcha.nodes.challenge) {
+ return;
+ }
+ setLifetime = function(e) {
+ return QR.captcha.lifetime = e.detail;
+ };
+ $.on(window, 'captcha:timeout', setLifetime);
+ $.globalEval('window.dispatchEvent(new CustomEvent("captcha:timeout", {detail: RecaptchaState.timeout}))');
+ $.off(window, 'captcha:timeout', setLifetime);
+ ref = QR.captcha.nodes, img = ref.img, input = ref.input;
+ img.parentNode.hidden = false;
+ input.placeholder = 'Verification';
+ $.off(input, 'focus click', QR.captcha.cb.focus);
+ QR.captcha.nodes.challenge = challenge;
+ new MutationObserver(QR.captcha.load.bind(QR.captcha)).observe(challenge, {
+ childList: true,
+ subtree: true,
+ attributes: true
+ });
+ QR.captcha.load();
+ if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
+ QR.nodes.el.style.top = null;
+ return QR.nodes.el.style.bottom = '0px';
+ }
+ },
+ destroy: function() {
+ if (!this.isEnabled) {
+ return;
+ }
+ $.globalEval('Recaptcha.destroy()');
+ return this.beforeSetup();
+ },
+ getOne: function() {
+ var challenge, response;
+ challenge = this.nodes.img.alt;
+ if (/\S/.test(response = this.nodes.input.value)) {
+ this.destroy();
+ return {
+ challenge: challenge,
+ response: response
+ };
+ } else {
+ return null;
+ }
+ },
+ load: function() {
+ var challenge, challenge_image;
+ if (!this.nodes.challenge.firstChild) {
+ return;
+ }
+ if (!(challenge_image = $.id('recaptcha_challenge_image'))) {
+ return;
+ }
+ this.timeout = Date.now() + this.lifetime * $.SECOND - $.MINUTE;
+ challenge = this.nodes.challenge.firstChild.value;
+ this.nodes.img.alt = challenge;
+ this.nodes.img.src = challenge_image.src;
+ return this.nodes.input.value = null;
+ },
+ reload: function(focus) {
+ $.globalEval('Recaptcha.reload(); Recaptcha.should_focus = false;');
+ if (focus) {
+ return this.nodes.input.focus();
+ }
+ },
+ keydown: function(e) {
+ if (e.keyCode === 8 && !this.nodes.input.value) {
+ this.reload();
+ } else {
+ return;
+ }
+ return e.preventDefault();
+ }
+ };
+
Captcha.v2 = {
lifetime: 2 * $.MINUTE,
init: function() {
@@ -18280,6 +18453,7 @@
"#qr > form {\n" +
" max-height: calc(100vh - 75px);\n" +
" overflow-y: auto;\n" +
+" overflow-x: hidden;\n" +
"}\n" +
"#qrtab {\n" +
" border-radius: 3px 3px 0 0;\n" +
@@ -18352,7 +18526,20 @@
" position: relative;\n" +
" top: 2px;\n" +
"}\n" +
-"/* Captcha */\n" +
+"/* Recaptcha v1 */\n" +
+".captcha-img {\n" +
+" margin: 0px;\n" +
+" text-align: center;\n" +
+" background-image: #fff;\n" +
+" font-size: 0px;\n" +
+" min-height: 59px;\n" +
+" min-width: 302px;\n" +
+"}\n" +
+".captcha-input{\n" +
+" width: 100%;\n" +
+" margin: 1px 0 0;\n" +
+"}\n" +
+"/* Recaptcha v2 */\n" +
"#qr .captcha-root {\n" +
" position: relative;\n" +
"}\n" +
diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip
index 32aaa06aa..7f9577dbc 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 a4e215c31..9d143416a 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 c9952f5c6..36ea57ded 100644
--- a/builds/updates.xml
+++ b/builds/updates.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/package.json b/package.json
index 150be93eb..f62a0cbe2 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.6",
- "date": "2015-06-21T06:05:51.745Z",
+ "version": "1.11.0.7",
+ "date": "2015-06-21T17:20:52.716Z",
"repo": "https://github.com/ccd0/4chan-x/",
"page": "https://github.com/ccd0/4chan-x",
"downloads": "https://ccd0.github.io/4chan-x/builds/",