ringme.js
Version:
A library to display a "Ring Me" button on a website. Also the best way to bring ring communication on your website !
200 lines (182 loc) • 6.83 kB
JavaScript
/*
* Copyright © 2017 Savoir-faire Linux Inc.
*
* This file is part of ringme.js.
*
* ringme.js is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ringme.js is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ringme.js. If not, see <http://www.gnu.org/licenses/>.
*/
var RingMe = new function() {
var URI_SCHEME_STATE = {
UNSUPPORTED : 0,
SUPPORTED : 1,
UNKNOWN : 2,
};
this.action = null;
this.identifier = null;
this.container = null;
this.ringUriScheme = "ring:";
this.ringUriSchemeSupported = URI_SCHEME_STATE.UNKNOWN;
this.setRingUriSchemeSupport = function(isSupported) {
this.ringUriSchemeSupported = isSupported;
}
this.ui = function(UI) {
_checkRingUriSchemeSupport(this);
if ((UI.action !== undefined) && (UI.action !== null)) {
this.action = UI.action;
}
if ((UI.identifier !== undefined) && (UI.identifier !== null)) {
this.identifier = UI.identifier;
}
if ((UI.container !== undefined) && (UI.container !== null)) {
this.container = UI.container;
}
var container = document.getElementById(this.container);
var ringUI;
if (this.ringUriSchemeSupported === URI_SCHEME_STATE.SUPPORTED) {
var nbsp = '\u00A0';
ringUI = _createAnchor(
'ring:' + this.identifier,
'Ring' + nbsp + 'Me'
);
}
else if (this.ringUriSchemeSupported === URI_SCHEME_STATE.UNSUPPORTED) {
ringUI = _createAnchor(
'https://ring.cx/download',
'Download and install Ring to "Ring Me"'
);
}
else {
ringUI = _createAnchor(
'https://ring.cx/download',
'We cannot be sure if you have Ring\'s lattest version. You might want to download it.'
);
}
container.appendChild(ringUI);
}
var _createAnchor = function(href, label) {
var anchor = document.createElement('a');
anchor.setAttribute('href', href);
anchor.className = 'btn btn--beta btn--icon sflicon-gauge ring--button btn--download';
anchorText = document.createTextNode(label);
anchor.appendChild(anchorText);
return anchor;
}
var _checkRingUriSchemeSupport = function(context) {
_launchUri(
context.ringUriScheme,
function() { context.setRingUriSchemeSupport.call(context, URI_SCHEME_STATE.SUPPORTED); },
function() { context.setRingUriSchemeSupport.call(context, URI_SCHEME_STATE.UNSUPPORTED); },
function() { context.setRingUriSchemeSupport.call(context, URI_SCHEME_STATE.UNKNOWN); }
);
}
// https://gist.github.com/aaronk6/d801d750f14ac31845e8
// this function is not under Savoir-faire Linux inc. copyright and license negociation
// for this code is ongoing here: https://gist.github.com/aaronk6/d801d750f14ac31845e8#gistcomment-1982506
var _launchUri = function(uri, successCallback, noHandlerCallback, unknownCallback) {
var res, parent, popup, iframe, timer, timeout, blurHandler, timeoutHandler, browser;
function callback (cb) {
if (typeof cb === 'function') cb();
}
function createHiddenIframe (parent) {
var iframe;
if (!parent) parent = document.body;
iframe = document.createElement('iframe');
iframe.style.display = 'none';
parent.appendChild(iframe);
return iframe;
}
function removeHiddenIframe(parent) {
if (!iframe) return;
if (!parent) parent = document.body;
parent.removeChild(iframe);
iframe = null;
}
browser = { isChrome: false, isFirefox: false, isIE: false };
if (window.chrome && !navigator.userAgent.match(/Opera|OPR\//)) {
browser.isChrome = true;
} else if (typeof InstallTrigger !== 'undefined') {
browser.isFirefox = true;
} else if ('ActiveXObject' in window) {
browser.isIE = true;
}
// Proprietary msLaunchUri method (IE 10+ on Windows 8+)
if (navigator.msLaunchUri) {
navigator.msLaunchUri(uri, successCallback, noHandlerCallback);
}
// Blur hack (Chrome)
else if (browser.isChrome) {
blurHandler = function () {
window.clearTimeout(timeout);
window.removeEventListener('blur', blurHandler);
callback(successCallback);
};
timeoutHandler = function () {
window.removeEventListener('blur', blurHandler);
callback(noHandlerCallback);
};
window.addEventListener('blur', blurHandler);
timeout = window.setTimeout(timeoutHandler, 500);
window.location.href = uri;
}
// Catch NS_ERROR_UNKNOWN_PROTOCOL exception (Firefox)
else if (browser.isFirefox) {
iframe = createHiddenIframe();
try {
// if we're still allowed to change the iframe's location, the protocol is registered
iframe.contentWindow.location.href = uri;
callback(successCallback);
} catch (e) {
if (e.name === 'NS_ERROR_UNKNOWN_PROTOCOL') {
callback(noHandlerCallback);
} else {
callback(unknownCallback);
}
} finally {
removeHiddenIframe();
}
}
// Open popup, change location, check wether we can access the location after the change (IE on Windows < 8)
else if (browser.isIE) {
popup = window.open('', 'launcher', 'width=0,height=0');
popup.location.href = uri;
try {
// Try to change the popup's location - if it fails, the protocol isn't registered
// and we'll end up in the `catch` block.
popup.location.href = 'about:blank';
callback(successCallback);
// The user will be shown a modal dialog to allow the external application. While
// this dialog is open, we cannot close the popup, so we try again and again until
// we succeed.
timer = window.setInterval(function () {
popup.close();
if (popup.closed) window.clearInterval(timer);
}, 500);
} catch (e) {
// Regain access to the popup in order to close it.
popup = window.open('about:blank', 'launcher');
popup.close();
callback(noHandlerCallback);
}
}
// No hack we can use, just open the URL in an hidden iframe and invoke `unknownCallback`
else {
iframe = createHiddenIframe();
iframe.contentWindow.location.href = uri;
window.setTimeout(function () {
removeHiddenIframe(parent);
callback(unknownCallback);
}, 500);
}
}
}