Improve focusing. Place captcha counter on top of captcha.

This commit is contained in:
ccd0 2014-12-06 17:43:04 -08:00
parent 8d33726c22
commit eb30e705dd
2 changed files with 44 additions and 20 deletions

View File

@ -1056,13 +1056,29 @@ input.field.tripped:not(:hover):not(:focus) {
#qr textarea { #qr textarea {
resize: both; resize: both;
} }
#qr .captcha-counter { #qr .captcha-section {
display: block; position: relative;
text-align: center;
} }
#qr .captcha-container > div > div { #qr .captcha-container > div > div {
margin: auto; margin: auto;
} }
#qr .captcha-counter {
display: block;
width: 100%;
text-align: center;
pointer-events: none;
}
#qr.captcha-open .captcha-counter {
position: absolute;
bottom: 3px;
}
#qr .captcha-counter > a {
pointer-events: auto;
}
#qr:not(.captcha-open) .captcha-counter > a {
display: block;
width: 100%;
}
.field { .field {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
margin: 0px; margin: 0px;

View File

@ -8,19 +8,26 @@ QR.captcha =
QR.captcha.sync captchas QR.captcha.sync captchas
$.sync 'captchas', @sync.bind @ $.sync 'captchas', @sync.bind @
counter = $.el 'a', section = $.el 'div', className: 'captcha-section'
className: 'captcha-counter' $.extend section, <%= html(
href: 'javascript:;' '<div class="captcha-container"></div>' +
container = $.el 'div', '<div class="captcha-counter"><a href="javascript:;"></a></div>'
className: 'captcha-container' ) %>
@nodes = {counter, container} container = $ '.captcha-container', section
counter = $ '.captcha-counter > a', section
@nodes = {container, counter}
@count() @count()
$.addClass QR.nodes.el, 'has-captcha' $.addClass QR.nodes.el, 'has-captcha'
$.after QR.nodes.com.parentNode, [counter, container] $.after QR.nodes.com.parentNode, section
new MutationObserver(@afterSetup.bind @).observe container,
childList: true
subtree: true
$.on counter, 'click', @toggle.bind @ $.on counter, 'click', @toggle.bind @
$.on window, 'captcha:success', @save.bind @ $.on window, 'captcha:success', @save.bind @
shouldFocus: false
timeouts: {} timeouts: {}
needed: -> needed: ->
@ -34,21 +41,17 @@ QR.captcha =
if @nodes.container.dataset.widgetID and !@timeouts.destroy if @nodes.container.dataset.widgetID and !@timeouts.destroy
@destroy() @destroy()
else else
@shouldFocus = true
@setup true @setup true
setup: (force) -> setup: (force) ->
return unless @isEnabled and (@needed() or force) return unless @isEnabled and (@needed() or force)
$.addClass QR.nodes.el, 'captcha-open' # suppress autohide so that captcha pop-up works $.addClass QR.nodes.el, 'captcha-open'
if @timeouts.destroy if @timeouts.destroy
clearTimeout @timeouts.destroy clearTimeout @timeouts.destroy
delete @timeouts.destroy delete @timeouts.destroy
return @reload() return @reload()
return if @nodes.container.dataset.widgetID return if @nodes.container.dataset.widgetID
@observer?.disconnect()
@observer = new MutationObserver @afterSetup.bind @
@observer.observe @nodes.container,
childList: true
subtree: true
$.globalEval ''' $.globalEval '''
(function() { (function() {
var container = document.querySelector("#qr .captcha-container"); var container = document.querySelector("#qr .captcha-container");
@ -62,12 +65,16 @@ QR.captcha =
})(); })();
''' '''
afterSetup: -> afterSetup: (mutations) ->
return unless @nodes.container.firstElementChild?.firstElementChild for mutation in mutations
@observer.disconnect() for node in mutation.addedNodes
iframe = node if node.nodeName is 'IFRAME'
return unless iframe
if QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight if QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight
QR.nodes.el.style.top = null QR.nodes.el.style.top = null
QR.nodes.el.style.bottom = '0px' QR.nodes.el.style.bottom = '0px'
iframe.focus() if @shouldFocus
@shouldFocus = false
destroy: -> destroy: ->
return unless @isEnabled return unless @isEnabled
@ -93,8 +100,10 @@ QR.captcha =
save: (e) -> save: (e) ->
if @needed() if @needed()
@shouldFocus = true
@reload() @reload()
else else
@nodes.counter.focus()
@timeouts.destroy ?= setTimeout @destroy.bind(@), 3 * $.SECOND @timeouts.destroy ?= setTimeout @destroy.bind(@), 3 * $.SECOND
$.forceSync 'captchas' $.forceSync 'captchas'
@captchas.push @captchas.push
@ -102,7 +111,6 @@ QR.captcha =
timeout: Date.now() + 2 * $.MINUTE timeout: Date.now() + 2 * $.MINUTE
@count() @count()
$.set 'captchas', @captchas $.set 'captchas', @captchas
@nodes.counter.focus()
clear: -> clear: ->
return unless @captchas.length return unless @captchas.length