Skip to content

Commit

Permalink
Merge pull request #293 from recurly/Tabbing
Browse files Browse the repository at this point in the history
Add support for tabbing in a Mobile browser.
  • Loading branch information
chrissrogers authored Dec 19, 2016
2 parents c369bfd + de7599b commit f370db6
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
24 changes: 22 additions & 2 deletions lib/recurly/hosted-field.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class HostedField extends Emitter {
this.configure(options);
this.inject();
this.bindLabel();
this.bindTabTrap();

this.on('bus:added', bus => {
this.bus = bus;
Expand Down Expand Up @@ -69,24 +70,30 @@ export class HostedField extends Emitter {

inject () {
this.target.innerHTML = `
<div class="${this.classList()}">
<div class="${this.classList()}" style="position:relative;">
<input type="text" style="position: absolute; z-index: -1; width: 0; height: 0;" data-recurly-hosted-field="true" />
<iframe
src="${this.url()}"
data-recurly-iframe="true"
border="0"
frameborder="0"
tabIndex="-1"
allowtransparency="true"
scrolling="no">
</iframe>
</div>
`;

this.container = this.target.children[0];
this.iframe = this.container.children[0];
this.tabTrapInput = this.container.children[0];
this.iframe = this.container.children[1];
this.window = this.iframe.contentWindow;

this.iframe.style.height = '100%';
this.iframe.style.width = '100%';
this.iframe.style.background = 'transparent';
this.iframe.style.position = 'relative';
this.iframe.style.zIndex = 1;
}

bindLabel () {
Expand All @@ -100,11 +107,24 @@ export class HostedField extends Emitter {
reset () {
this.off();
this.target.innerHTML = '';
// TODO: May need to remove tabTrap stuff
delete this.target;
delete this.iframe;
delete this.window;
}

bindTabTrap () {
this.tabTrapInput.addEventListener('focus',e => {
e.preventDefault()
e.stopPropagation()
// Firefox demands a blur or else the focus doesn' work...
if(navigator.userAgent.toLowerCase().indexOf('firefox') >= 0){
e.currentTarget.blur()
}
this.focus()
})
}

update () {
this.container.className = this.classList();
}
Expand Down
40 changes: 40 additions & 0 deletions lib/recurly/hosted-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import clone from 'component-clone';
import Emitter from 'component-emitter';
import merge from 'lodash.merge';
import omit from 'lodash.omit';
import indexOf from 'lodash.indexof'
import {HostedField} from './hosted-field';
import errors from '../errors';

const FOCUS_SELECTOR = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe:not([data-recurly-iframe]), object, embed, [tabindex="0"], [contenteditable]';

const debug = require('debug')('recurly:hostedFields');

const REQUIRED_FIELDS = ['number', 'month', 'year'];
Expand Down Expand Up @@ -37,6 +40,43 @@ export class HostedFields extends Emitter {
this.bus = bus;
this.fields.forEach(hf => bus.add(hf));
});

this.on('hostedField:tab:previous',this.onTabPrevious.bind(this))
this.on('hostedField:tab:next',this.onTabNext.bind(this))
}

onTabNext(body) {
let type = body.type;
let field = this.fields.find(f => f.type === type);
let tabTrap = field.tabTrapInput;
let allFields = document.querySelectorAll(FOCUS_SELECTOR);
let curIdx = indexOf(allFields,tabTrap);

if(curIdx+1 < allFields.length){
let nextIdx = curIdx + 1;
let nextEl = allFields[nextIdx];
this.tabToElement(field,nextIdx,nextEl);
}
}

onTabPrevious(body) {
let type = body.type;
let field = this.fields.find(f => f.type === type);
let tabTrap = field.tabTrapInput;
let allFields = document.querySelectorAll(FOCUS_SELECTOR);
let curIdx = indexOf(allFields,tabTrap);

if(curIdx-1 > 0){
let prevIdx = curIdx - 1;
let prevEl = allFields[prevIdx];
this.tabToElement(field,prevIdx,prevEl);
}
}

tabToElement(focusedField,index,element) {
let elementIsHosted = typeof element.attributes["data-recurly-hosted-field"] !== "undefined";
focusedField.iframe.blur()
element.focus()
}

/**
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"debug": "2.2.0",
"json-component": "0.0.1",
"jsonp": "0.0.4",
"lodash.indexof": "^4.0.5",
"lodash.map": "^4.6.0",
"lodash.merge": "*",
"lodash.omit": "*",
Expand Down

0 comments on commit f370db6

Please sign in to comment.