diff --git a/4chan_x.user.js b/4chan_x.user.js
index 974a1205b..763c1e9c2 100644
--- a/4chan_x.user.js
+++ b/4chan_x.user.js
@@ -1406,6 +1406,71 @@
return _Class;
})(),
+ captcha: {
+ init: function() {
+ var _this = this;
+ this.img = $('.captcha > img', qr.el);
+ this.input = $('[name=captcha]', qr.el);
+ this.challenge = $.id('recaptcha_challenge_field_holder');
+ $.on(this.img.parentNode, 'click', this.reload);
+ $.on(this.input, 'keydown', this.keydown);
+ $.on(this.challenge, 'DOMNodeInserted', function() {
+ return _this.load();
+ });
+ $.on(window, 'storage', function(e) {
+ if (e.key === ("" + NAMESPACE + "captchas")) {
+ return _this.count(JSON.parse(e.newValue).length);
+ }
+ });
+ this.count($.get('captchas', []).length);
+ this.load();
+ return window.location = 'javascript:Recaptcha.focus_response_field=function(){}';
+ },
+ save: function() {
+ var captchas, length, now, response;
+ if (!(response = this.input.value)) return;
+ captchas = $.get('captchas', []);
+ now = Date.now();
+ while (captchas[0].time < now) {
+ captchas.shift();
+ }
+ length = captchas.push({
+ challenge: this.challenge.firstChild.value,
+ response: response,
+ time: this.timeout
+ });
+ $.set('captchas', captchas);
+ this.count(length);
+ return this.reload();
+ },
+ load: function() {
+ var challenge;
+ this.timeout = Date.now() + 25 * MINUTE;
+ challenge = this.challenge.firstChild.value;
+ this.img.alt = challenge;
+ this.img.src = "http://www.google.com/recaptcha/api/image?c=" + challenge;
+ return this.input.value = null;
+ },
+ count: function(count) {
+ return this.input.placeholder = "Verification (" + count + " cached captchas)";
+ },
+ reload: function() {
+ window.location = 'javascript:Recaptcha.reload()';
+ return qr.captcha.input.focus();
+ },
+ keydown: function(e) {
+ var c;
+ c = qr.captcha;
+ if (e.keyCode === 8 && !c.input.value) {
+ c.reload();
+ } else if (e.keyCode === 13 && e.shiftKey) {
+ c.save();
+ } else {
+ return;
+ }
+ return e.preventDefault();
+ }
+ },
dialog: function() {
var input, mimeTypes, thread, threads, _i, _j, _len, _len2, _ref, _ref2;
if (!g.REPLY) {
@@ -1428,7 +1493,7 @@
}
});
qr.mimeTypes = mimeTypes.split(', ');
- qr.el = ui.dialog('qr', 'top:0;right:0;', "
");
+ qr.el = ui.dialog('qr', 'top:0;right:0;', "");
if (!g.REPLY) {
$.on($('select', qr.el), 'mousedown', function(e) {
return e.stopPropagation();
@@ -1458,6 +1523,7 @@
return qr.selected[this.name] = this.value;
});
}
+ qr.captcha.init();
return $.add(d.body, qr.el);
},
submit: function(e) {
@@ -3265,6 +3331,8 @@ textarea.field {\
}\
.captcha {\
background: #FFF;\
+ outline: 1px solid #CCC;\
+ outline-offset: -1px;\
text-align: center;\
}\
.captcha > img {\
diff --git a/script.coffee b/script.coffee
index cc5e2fb91..4301a0677 100644
--- a/script.coffee
+++ b/script.coffee
@@ -1046,6 +1046,53 @@ qr =
url.revokeObjectURL @url
delete @
+ captcha:
+ init: ->
+ @img = $ '.captcha > img', qr.el
+ @input = $ '[name=captcha]', qr.el
+ @challenge = $.id 'recaptcha_challenge_field_holder'
+ $.on @img.parentNode, 'click', @reload
+ $.on @input, 'keydown', @keydown
+ $.on @challenge, 'DOMNodeInserted', => @load()
+ $.on window, 'storage', (e) => @count JSON.parse(e.newValue).length if e.key is "#{NAMESPACE}captchas"
+ @count $.get('captchas', []).length
+ @load()
+ # prevent original captcha input from being focused on reload
+ window.location = 'javascript:Recaptcha.focus_response_field=function(){}'
+ save: ->
+ return unless response = @input.value
+ captchas = $.get 'captchas', []
+ # remove old captchas
+ now = Date.now()
+ while captchas[0].time < now
+ captchas.shift()
+ length = captchas.push
+ challenge: @challenge.firstChild.value
+ response: response
+ time: @timeout
+ $.set 'captchas', captchas
+ @count length
+ @reload()
+ load: ->
+ @timeout = Date.now() + 25*MINUTE
+ challenge = @challenge.firstChild.value
+ @img.alt = challenge
+ @img.src = "http://www.google.com/recaptcha/api/image?c=#{challenge}"
+ @input.value = null
+ count: (count) ->
+ @input.placeholder = "Verification (#{count} cached captchas)"
+ reload: ->
+ window.location = 'javascript:Recaptcha.reload()'
+ qr.captcha.input.focus()
+ keydown: (e) ->
+ c = qr.captcha
+ if e.keyCode is 8 and not c.input.value
+ c.reload()
+ else if e.keyCode is 13 and e.shiftKey
+ c.save()
+ else
+ return
+ e.preventDefault()
dialog: ->
# create a new thread or select thread to reply to
@@ -1073,8 +1120,8 @@ qr =
-
-
+
+
@@ -1099,6 +1146,7 @@ qr =
# if match = e.key.match /qr_(.+)$/
# qr.inputs[match[1]].value = JSON.parse e.newValue
+ qr.captcha.init()
$.add d.body, qr.el
submit: (e) ->
@@ -2607,6 +2655,8 @@ textarea.field {
}
.captcha {
background: #FFF;
+ outline: 1px solid #CCC;
+ outline-offset: -1px;
text-align: center;
}
.captcha > img {