Unify captcha module interfaces.

This commit is contained in:
ccd0 2014-12-13 07:56:36 -08:00
parent 183f878f0c
commit e028273eed
4 changed files with 89 additions and 58 deletions

View File

@ -1,7 +1,6 @@
Captcha.noscript =
lifetime: 120 * $.SECOND
lifetime: 2 * $.MINUTE
iframeURL: '//www.google.com/recaptcha/api/fallback?k=<%= meta.recaptchaKey %>'
timers: {}
init: ->
return if d.cookie.indexOf('pass_enabled=1') >= 0
@ -20,7 +19,9 @@ Captcha.noscript =
$.on input, 'blur', QR.focusout
$.on input, 'focus', QR.focusin
$.on input, 'keydown', @keydown.bind @
$.on @nodes.container, 'click', @reload.bind(@, true)
$.on @nodes.container, 'click', =>
@reload()
@nodes.input.focus()
@conn = new Connection null, "#{location.protocol}//www.google.com",
challenge: @load.bind @
@ -37,7 +38,7 @@ Captcha.noscript =
$.sync 'captchas', @sync
@beforeSetup()
@setup() if Conf['Auto-load captcha']
@setup()
initFrame: ->
conn = new Connection window.top, "#{location.protocol}//boards.4chan.org",
@ -51,8 +52,10 @@ Captcha.noscript =
error = $('.fbc-error')?.textContent
conn.send {challenge, token, error}
timers: {}
cb:
focus: -> QR.captcha.setup()
focus: -> QR.captcha.setup false, true
beforeSetup: ->
{container, input} = @nodes
@ -60,38 +63,51 @@ Captcha.noscript =
input.value = ''
input.placeholder = 'Focus to load reCAPTCHA'
@count()
$.on input, 'focus', @cb.focus
$.on input, 'focus click', @cb.focus
setup: ->
needed: ->
captchaCount = @captchas.length
captchaCount++ if QR.req
postsCount = QR.posts.length
postsCount = 0 if postsCount is 1 and !Conf['Auto-load captcha'] and !QR.posts[0].com and !QR.posts[0].file
captchaCount < postsCount
onNewPost: ->
onPostChange: ->
setup: (focus, force) ->
return unless @isEnabled and (@needed() or force)
if !@nodes.iframe
@nodes.iframe = $.el 'iframe',
id: 'qr-captcha-iframe'
src: @iframeURL
delete @iframeUsed
$.add d.body, @nodes.iframe
@conn.target = @nodes.iframe.contentWindow
else if @iframeUsed or !@nodes.img
else if !@occupied
@nodes.iframe.src = @iframeURL
delete @iframeUsed
else if !@nodes.img.complete
@conn.send queryChallenge: null
@occupied = true
@nodes.input.focus() if focus
afterSetup: ->
{container, input} = @nodes
container.hidden = false
input.placeholder = 'Verification'
@count()
$.off input, 'focus', @cb.focus
$.off input, 'focus click', @cb.focus
if QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight
QR.nodes.el.style.top = null
QR.nodes.el.style.bottom = '0px'
destroy: ->
$.rm @nodes.img
return unless @isEnabled
$.rm @nodes.img if @nodes.img
delete @nodes.img
$.rm @nodes.iframe
$.rm @nodes.iframe if @nodes.iframe
delete @nodes.iframe
delete @occupied
@unflag()
@beforeSetup()
sync: (captchas=[]) ->
@ -115,14 +131,14 @@ Captcha.noscript =
response = @nodes.input.value
if /\S/.test response
@conn.send {response}
@iframeUsed = true
save: (token) ->
delete @occupied
@nodes.input.value = ''
if @submitCB
@submitCB token
delete @submitCB
if Conf['Auto-load captcha'] then @reload() else @destroy()
if @needed() then @reload() else @destroy()
else
$.forceSync 'captchas'
@captchas.push
@ -133,11 +149,22 @@ Captcha.noscript =
@reload()
error: (message) ->
@occupied = true
@nodes.input.value = ''
QR.error "CAPTCHA Error: #{message}"
if @submitCB
@submitCB()
delete @submitCB
QR.error "Captcha Error: #{message}"
notify: (el) ->
if Conf['Captcha Warning Notifications'] and !d.hidden
QR.notify el
else
$.addClass @nodes.input, 'error'
$.one @nodes.input, 'keydown', @unflag.bind @
unflag: ->
$.rmClass @nodes.input, 'error'
clear: ->
return unless @captchas.length
@ -152,6 +179,7 @@ Captcha.noscript =
load: (src) ->
{container, input, img} = @nodes
@occupied = true
@timeout = Date.now() + @lifetime
unless img
img = @nodes.img = new Image
@ -160,8 +188,8 @@ Captcha.noscript =
img.src = src
input.value = ''
@clear()
clearTimeout @timers.reload
@timers.reload = setTimeout @reload.bind(@), @lifetime
clearTimeout @timers.expire
@timers.expire = setTimeout @expire.bind(@), @lifetime
count: ->
count = if @captchas then @captchas.length else 0
@ -179,15 +207,20 @@ Captcha.noscript =
if @captchas.length
@timers.clear = setTimeout @clear.bind(@), @captchas[0].timeout - Date.now()
reload: (focus) ->
expire: ->
return unless @nodes.iframe
if @needed() or d.activeElement is @nodes.input
@reload()
else
@destroy()
reload: ->
@nodes.iframe.src = @iframeURL
delete @iframeUsed
@nodes.input.focus() if focus
@occupied = true
keydown: (e) ->
if e.keyCode is 8 and not @nodes.input.value
@reload()
if @nodes.iframe then @reload() else @setup()
else if e.keyCode is 13 and e.shiftKey
@sendResponse()
else

View File

@ -1,4 +1,6 @@
Captcha.v2 =
lifetime: 2 * $.MINUTE
init: ->
return if d.cookie.indexOf('pass_enabled=1') >= 0
return unless @isEnabled = !!$.id 'g-recaptcha'
@ -27,11 +29,14 @@ Captcha.v2 =
needed: ->
captchaCount = @captchas.length
captchaCount++ if @nodes.container and !@timeouts.destroy
captchaCount++ if QR.req
@postsCount = QR.posts.length
@postsCount = 0 if @postsCount is 1 and !Conf['Auto-load captcha'] and !QR.posts[0].com and !QR.posts[0].file
captchaCount < @postsCount
onNewPost: ->
@setup()
onPostChange: ->
@setup() if @postsCount is 0
@postsCount = 0 if QR.posts.length is 1 and !Conf['Auto-load captcha'] and !QR.posts[0].com and !QR.posts[0].file
@ -51,7 +56,11 @@ Captcha.v2 =
delete @timeouts.destroy
return @reload()
return if @nodes.container
if @nodes.container
if @shouldFocus and iframe = $ 'textarea', @nodes.container
iframe.focus()
delete @shouldFocus
return
@nodes.container = $.el 'div', className: 'captcha-container'
$.prepend @nodes.root, @nodes.container
@ -116,22 +125,21 @@ Captcha.v2 =
getOne: ->
@clear()
if captcha = @captchas.shift()
@count()
$.set 'captchas', @captchas
@count()
captcha.response
else
null
save: (pasted) ->
$.forceSync 'captchas'
reload = (QR.cooldown.auto or Conf['Post on Captcha Completion']) and @needed()
@captchas.push
response: $('textarea', @nodes.container).value
timeout: (if pasted then @setupTime else Date.now()) + 2 * $.MINUTE
@count()
timeout: (if pasted then @setupTime else Date.now()) + @lifetime
$.set 'captchas', @captchas
@count()
if reload
if (QR.cooldown.auto or Conf['Post on Captcha Completion']) and @needed()
@shouldFocus = true
@reload()
else
@ -143,6 +151,9 @@ Captcha.v2 =
QR.submit() if Conf['Post on Captcha Completion'] and !QR.cooldown.auto
notify: (el) ->
QR.notify el
clear: ->
return unless @captchas.length
$.forceSync 'captchas'
@ -161,7 +172,7 @@ Captcha.v2 =
if @captchas.length
@timeouts.clear = setTimeout @clear.bind(@), @captchas[0].timeout - Date.now()
reload: (focus) ->
reload: ->
$.globalEval '''
(function() {
var container = document.querySelector("#qr .captcha-container");

View File

@ -95,9 +95,9 @@ QR =
open: ->
if QR.nodes
QR.captcha.setup() if QR.nodes.el.hidden
QR.nodes.el.hidden = false
QR.unhide()
QR.captcha.setup() unless QR.captcha is Captcha.noscript
return
try
QR.dialog()
@ -114,8 +114,6 @@ QR =
QR.cleanNotifications()
d.activeElement.blur()
$.rmClass QR.nodes.el, 'dump'
if QR.captcha is Captcha.noscript and !Conf['Captcha Warning Notifications']
$.rmClass QR.captcha.nodes.input, 'error' if QR.captcha.isEnabled
if Conf['QR Shortcut']
$.toggleClass $('.qr-shortcut'), 'disabled'
new QR.post true
@ -123,8 +121,7 @@ QR =
post.delete()
QR.cooldown.auto = false
QR.status()
if QR.captcha isnt Captcha.noscript or (QR.captcha.isEnabled and not Conf['Auto-load captcha'])
QR.captcha.destroy()
QR.captcha.destroy()
focusin: ->
QR.captcha.setup() if $.hasClass(QR.nodes.el, 'autohide') and !$.hasClass(QR.nodes.el, 'focus')
$.addClass QR.nodes.el, 'focus'
@ -135,6 +132,7 @@ QR =
$.addClass QR.nodes.el, 'autohide'
QR.nodes.autohide.checked = true
unhide: ->
QR.captcha.setup() if $.hasClass(QR.nodes.el, 'autohide') and !$.hasClass(QR.nodes.el, 'focus')
$.rmClass QR.nodes.el, 'autohide'
QR.nodes.autohide.checked = false
toggleHide: ->
@ -150,20 +148,10 @@ QR =
else
el = err
el.removeAttribute 'style'
captchaErr = QR.captcha.isEnabled and /captcha|verification/i.test el.textContent
if captchaErr and QR.captcha is Captcha.noscript
if QR.captcha.captchas.length is 0
# Focus the captcha input on captcha error.
QR.captcha.nodes.input.focus()
QR.captcha.setup()
if Conf['Captcha Warning Notifications'] and !d.hidden
QR.notify el
else
$.addClass QR.captcha.nodes.input, 'error'
$.on QR.captcha.nodes.input, 'keydown', ->
$.rmClass QR.captcha.nodes.input, 'error'
if QR.captcha.isEnabled and /captcha|verification/i.test el.textContent
QR.captcha.setup true
QR.captcha.notify el
else
QR.captcha.setup true if captchaErr and QR.captcha isnt Captcha.noscript
QR.notify el
alert el.textContent if d.hidden
@ -567,7 +555,7 @@ QR =
QR.cooldown.init()
QR.captcha.init()
$.add d.body, dialog
QR.captcha.setup() unless QR.captcha is Captcha.noscript
QR.captcha.setup()
# Create a custom event when the QR dialog is first initialized.
# Use it to extend the QR's functionalities, or for XTRM RICE.
@ -794,6 +782,7 @@ QR =
else
true
QR.cooldown.addDelay post, +m[1]
QR.captcha.setup (d.activeElement is QR.nodes.status)
else # stop auto-posting
QR.cooldown.auto = false
QR.status()
@ -838,8 +827,8 @@ QR =
icon: Favicon.logo
notif.onclick = ->
QR.open()
QR.captcha.nodes.input.focus() if QR.captcha is Captcha.noscript
window.focus()
QR.captcha.setup true
notif.onshow = ->
setTimeout ->
notif.close()
@ -848,10 +837,8 @@ QR =
unless Conf['Persistent QR'] or postsCount
QR.close()
else
if QR.captcha is Captcha.noscript and QR.posts.length > 1 and QR.captcha.isEnabled and QR.captcha.captchas.length is 0
QR.captcha.setup()
post.rm()
QR.captcha.setup true unless QR.captcha is Captcha.noscript
QR.captcha.setup (d.activeElement is QR.nodes.status)
QR.cooldown.add req.uploadEndTime, threadID, postID

View File

@ -70,7 +70,7 @@ QR.post = class
@select() if select
@unlock()
# Post count temporarily off by 1 when called from QR.post.rm
$.queueTask -> QR.captcha.setup() unless QR.captcha is Captcha.noscript
$.queueTask -> QR.captcha.onNewPost()
rm: ->
@delete()
@ -133,7 +133,7 @@ QR.post = class
QR.status()
when 'com'
@nodes.span.textContent = @com
QR.captcha.onPostChange() unless QR.captcha is Captcha.noscript
QR.captcha.onPostChange()
QR.characterCount()
# Disable auto-posting if you're typing in the first post
# during the last 5 seconds of the cooldown.
@ -162,7 +162,7 @@ QR.post = class
@filename = file.name
@filesize = $.bytesToString file.size
@nodes.label.hidden = false if QR.spoiler
QR.captcha.onPostChange() unless QR.captcha is Captcha.noscript
QR.captcha.onPostChange()
URL.revokeObjectURL @URL
if @ is QR.selected
@showFileData()