Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
250 lines
6.5 KiB
JavaScript
Executable file
250 lines
6.5 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
(function(exports) {
|
|
// The .sjs file is located in the Gecko since it needs chrome privilege.
|
|
var AJAX_URL = 'pairing.sjs';
|
|
|
|
function init() {
|
|
var btnSubmit = document.getElementById('connect');
|
|
var btnRestartPairing = document.getElementById('restart-pairing');
|
|
var pinCodeInput = new PinCodeInput(
|
|
document.getElementById('input-mask'),
|
|
[].slice.call(document.querySelectorAll('.code')),
|
|
btnSubmit
|
|
);
|
|
|
|
btnRestartPairing.addEventListener('click', function() {
|
|
window.location.reload();
|
|
});
|
|
|
|
btnSubmit.disabled = false;
|
|
btnSubmit.addEventListener('click', function(evt) {
|
|
var pincode = pinCodeInput.getCodes();
|
|
if (pincode === '') {
|
|
pinCodeInput.highlightEmptyCode();
|
|
return;
|
|
}
|
|
|
|
btnSubmit.disabled = true;
|
|
|
|
var onerror = function(message) {
|
|
pinCodeInput.empty();
|
|
btnSubmit.disabled = false;
|
|
showMessage(message, true);
|
|
};
|
|
|
|
exports.sendMessage(
|
|
AJAX_URL,
|
|
{
|
|
message: JSON.stringify({ pincode: pincode })
|
|
},
|
|
function success(data) {
|
|
if (data) {
|
|
if (data.verified) {
|
|
document.l10n.formatValue('connect-success')
|
|
.then(function(value) {
|
|
showMessage(value);
|
|
// The cookie will be used by server via http header.
|
|
exports.setCookie('uuid', data.uuid);
|
|
setTimeout(function() {
|
|
// Server will help redirecting to client.html when there is
|
|
// a UUID in cookie.
|
|
window.location.reload();
|
|
}, 1000);
|
|
});
|
|
} else if (data.reason == 'expired') {
|
|
document.l10n.formatValue('pin-code-expired-message')
|
|
.then(onerror);
|
|
document.getElementById('pairing-container')
|
|
.classList.add('pin-code-expired');
|
|
} else {
|
|
document.l10n.formatValue('wrong-pin').then(onerror);
|
|
}
|
|
} else {
|
|
document.l10n.formatValue('connect-error-invalid-response')
|
|
.then(onerror);
|
|
}
|
|
},
|
|
function error(status) {
|
|
document.l10n.formatValue('connect-error', {status: String(status)})
|
|
.then(onerror);
|
|
}
|
|
);
|
|
});
|
|
}
|
|
|
|
function showMessage(message, isError) {
|
|
var divMessage = document.getElementById('pairing-message');
|
|
divMessage.textContent = message;
|
|
divMessage.classList[isError ? 'add' : 'remove']('error');
|
|
}
|
|
|
|
function PinCodeInput(mask, codes, submitButton) {
|
|
var self = this;
|
|
|
|
self._mask = mask;
|
|
self._codes = codes;
|
|
self._submitButton = submitButton;
|
|
self._index = -1;
|
|
|
|
var createHandler = function(index) {
|
|
return function(evt) {
|
|
self.showMask(index);
|
|
evt.preventDefault();
|
|
};
|
|
};
|
|
|
|
for(var i = 0; i < codes.length; i++) {
|
|
var handler = createHandler(i);
|
|
codes[i].addEventListener('focus', handler);
|
|
codes[i].addEventListener('click', handler);
|
|
}
|
|
|
|
mask.addEventListener('blur', function() {
|
|
self.hideMask();
|
|
});
|
|
|
|
mask.addEventListener('keydown', function(evt) {
|
|
self.onKeyDown(evt);
|
|
});
|
|
}
|
|
|
|
PinCodeInput.prototype = {
|
|
showMask: function(index) {
|
|
this._mask.blur();
|
|
this._mask.classList.add('visible');
|
|
this.moveMask(index);
|
|
this._mask.focus();
|
|
},
|
|
|
|
hideMask: function() {
|
|
this.writeBack();
|
|
this._mask.blur();
|
|
this._mask.classList.remove('visible');
|
|
},
|
|
|
|
moveMask: function(index) {
|
|
this._index = index;
|
|
this._mask.style.left = this._codes[index].offsetLeft + 'px';
|
|
this._mask.value = this._codes[index].textContent;
|
|
this._mask.select();
|
|
},
|
|
|
|
moveNext: function() {
|
|
if (this._index < this._codes.length - 1) {
|
|
this.moveMask(this._index + 1);
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
movePrev: function() {
|
|
if (this._index > 0) {
|
|
this.moveMask(this._index - 1);
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
empty: function() {
|
|
for (var i = 0; i < this._codes.length; i++) {
|
|
this.setCode(i, '');
|
|
}
|
|
},
|
|
|
|
writeBack: function() {
|
|
this.setCode(this._index, this._mask.value);
|
|
},
|
|
|
|
setCode: function(index, value) {
|
|
if (value.length) {
|
|
this._codes[index].classList.remove('placeholder');
|
|
this._codes[index].textContent = value.charAt(0);
|
|
} else {
|
|
this._codes[index].classList.add('placeholder');
|
|
this._codes[index].textContent = '';
|
|
}
|
|
},
|
|
|
|
getCodes: function() {
|
|
var code = '';
|
|
for (var i = 0; i < this._codes.length; i++) {
|
|
if (this._codes[i].textContent !== '') {
|
|
code += this._codes[i].textContent;
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
return code;
|
|
},
|
|
|
|
highlightEmptyCode: function() {
|
|
for (var i = 0; i < this._codes.length; i++) {
|
|
if (this._codes[i].textContent === '') {
|
|
this.showMask(i);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
onKeyDown: function(evt) {
|
|
var c = evt.keyCode;
|
|
|
|
if (evt.ctrlKey || evt.altKey || evt.metaKey) {
|
|
return;
|
|
}
|
|
|
|
// backspace to delete the previous field if current one is empty.
|
|
if (c == 8 && this._mask.value === '') {
|
|
if (this._index > 0) {
|
|
this.writeBack();
|
|
this.setCode(this._index - 1, '');
|
|
this.movePrev();
|
|
} else {
|
|
this.hideMask();
|
|
}
|
|
evt.preventDefault();
|
|
return;
|
|
}
|
|
|
|
// numbers
|
|
if (!evt.shiftKey && ((c >= 48 && c <= 57) || (c >= 96 && c <= 105))) {
|
|
showMessage('');
|
|
|
|
var num = String.fromCharCode(c >= 96 ? c - 96 + 48 : c);
|
|
this._mask.value = num;
|
|
this.writeBack();
|
|
if (!this.moveNext()) {
|
|
this._submitButton.focus();
|
|
}
|
|
evt.preventDefault();
|
|
return;
|
|
}
|
|
|
|
// tab
|
|
if (c == 9) {
|
|
this.writeBack();
|
|
if (evt.shiftKey) {
|
|
if (!this.movePrev()) {
|
|
this.hideMask();
|
|
}
|
|
} else {
|
|
if (!this.moveNext()) {
|
|
this._submitButton.focus();
|
|
}
|
|
}
|
|
evt.preventDefault();
|
|
return;
|
|
}
|
|
|
|
// allowed function keys: backspace, shift, del and F5.
|
|
if ([8, 16, 46, 116].indexOf(c) < 0) {
|
|
evt.preventDefault();
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.ready(init);
|
|
}(window));
|