Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
|
|
@ -0,0 +1 @@
|
|||
;window.COMPONENTS_BASE_URL='/shared/elements/';
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<element name="confirmation-message" extends="form">
|
||||
<template>
|
||||
|
||||
<section>
|
||||
<h1>Confirmation title</h1>
|
||||
<p>Confirmation message</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button>Action 1</button>
|
||||
<button>Action 2</button>
|
||||
</menu>
|
||||
|
||||
</template>
|
||||
</element>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<element name="contact-in-overlay" extends="button">
|
||||
<template>
|
||||
|
||||
<div class="js-name ci__name ellipsis" dir="auto"></div>
|
||||
<div class="ci__details">
|
||||
<span class="js-tel-type ci__tel-type ellipsis" dir="auto"></span>
|
||||
<span class="js-separator"></span>
|
||||
<span class="js-tel ellipsis" dir="ltr"></span>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</element>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<element name="contact-list-overlay" extends="form">
|
||||
<template>
|
||||
|
||||
<header></header>
|
||||
<menu id="contact-list">
|
||||
<button id="contact-list-overlay-cancel" data-l10n-id="cancel">Cancel</button>
|
||||
</menu>
|
||||
|
||||
</template>
|
||||
</element>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/* Generated by grunt-webfont */
|
||||
/* Based on https://github.com/endtwist/fontcustom/blob/master/lib/fontcustom/templates/fontcustom.css */
|
||||
|
||||
@font-face {
|
||||
font-family: "gaia-icons";
|
||||
src: url("fonts/gaia-icons.ttf") format("truetype");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
[data-icon]:before,
|
||||
.ligature-icons {
|
||||
font-family: "gaia-icons";
|
||||
content: attr(data-icon);
|
||||
display: inline-block;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
text-decoration: inherit;
|
||||
text-transform: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-size: 30px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
[data-icon]:not([data-l10n-id]):not([aria-label]):not([aria-hidden="true"]):before {
|
||||
/* Highlight cases where icons are not localized and still visible to screen
|
||||
reader */
|
||||
background: rgba(255, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
[data-icon]:not([data-l10n-id]):not([aria-label]):not([aria-hidden="true"]):after {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
width: 20rem;
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
content: "Icon is not localized and is still visible to screen reader. Please add data-l10n-id or aria-label for localization or use aria-hidden to hide the icon from screen reader.";
|
||||
z-index: 9999;
|
||||
}
|
||||
|
After Width: | Height: | Size: 178 B |
|
After Width: | Height: | Size: 245 B |
|
|
@ -0,0 +1,62 @@
|
|||
'use strict';
|
||||
/* global ComponentUtils */
|
||||
|
||||
window.GaiaMenu = (function(win) {
|
||||
// Extend from HTMLElement prototype
|
||||
var proto = Object.create(HTMLElement.prototype);
|
||||
|
||||
// Allow baseurl to be overridden (used for demo page)
|
||||
var baseurl = window.GaiaMenuBaseurl ||
|
||||
'/shared/elements/gaia_menu/';
|
||||
|
||||
proto.createdCallback = function () {
|
||||
var shadow = this.createShadowRoot();
|
||||
|
||||
this._template = template.content.cloneNode(true);
|
||||
|
||||
var cancelButton = this._template.querySelector('.gaia-menu-cancel button');
|
||||
|
||||
cancelButton.addEventListener('click', function () {
|
||||
this.hide();
|
||||
this.dispatchEvent(new CustomEvent('gaiamenu-cancel'));
|
||||
}.bind(this));
|
||||
|
||||
shadow.appendChild(this._template);
|
||||
|
||||
ComponentUtils.style.call(this, baseurl);
|
||||
|
||||
document.l10n.ready.then(this.localize.bind(this));
|
||||
document.addEventListener('DOMRetranslated', this.localize.bind(this));
|
||||
};
|
||||
|
||||
proto.localize = function() {
|
||||
document.l10n.formatValue('gaia-menu-cancel').then(value => {
|
||||
this.shadowRoot.querySelector('button').textContent = value;
|
||||
});
|
||||
};
|
||||
|
||||
proto.show = function() {
|
||||
this.removeAttribute('hidden');
|
||||
};
|
||||
|
||||
proto.hide = function() {
|
||||
this.setAttribute('hidden', 'hidden');
|
||||
};
|
||||
|
||||
var template = document.createElement('template');
|
||||
|
||||
template.innerHTML =
|
||||
`<form role="dialog" data-type="action">
|
||||
<content select="header"></content>
|
||||
<menu>
|
||||
<content select="button"></content>
|
||||
<span class="gaia-menu-cancel">
|
||||
<button>Cancel</button>
|
||||
</span>
|
||||
</menu>
|
||||
</form>`;
|
||||
|
||||
// Register and return the constructor
|
||||
return document.registerElement('gaia-menu', { prototype: proto });
|
||||
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,314 @@
|
|||
/* ----------------------------------
|
||||
* gaia_menu
|
||||
* ---------------------------------- */
|
||||
|
||||
/* default alignment follows the UI direction, not the content direction */
|
||||
:-moz-dir(ltr) [dir] { text-align: left; }
|
||||
:-moz-dir(rtl) [dir] { text-align: right; }
|
||||
|
||||
/* Main dialog setup */
|
||||
gaia-menu {
|
||||
background-color: #2d2d2d;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 0 0 7rem;
|
||||
/**
|
||||
* Using "font-size: 0" to avoid the unwanted visual space (about 3px) created
|
||||
* by white spaces and line breaks in the code between inline-block elements.
|
||||
*/
|
||||
font-size: 0;
|
||||
color: #fff;
|
||||
display: block;
|
||||
transition: transform ease-in-out var(--transition-duration),
|
||||
visibility var(--transition-duration);
|
||||
}
|
||||
|
||||
gaia-menu[hidden] {
|
||||
transform: translateY(100%);
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
gaia-menu:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 0.1rem;
|
||||
height: 100%;
|
||||
margin-inline-start: -0.1rem;
|
||||
}
|
||||
|
||||
header {
|
||||
-moz-box-sizing: border-box;
|
||||
font-size: 1.6rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
height: 5rem;
|
||||
line-height: 4.9rem;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
font-weight: normal;
|
||||
padding: 0 3rem;
|
||||
border-bottom: 0.1rem solid #616262;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 1.6rem;
|
||||
line-height: 4.9rem;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Generic set of actions in toolbar */
|
||||
header menu.toolbar {
|
||||
height: 100%;
|
||||
margin: 0 -3rem;
|
||||
margin-inline-start: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
header:-moz-dir(ltr) menu.toolbar { float: right; }
|
||||
header:-moz-dir(rtl) menu.toolbar { float: left; }
|
||||
|
||||
header menu.toolbar a,
|
||||
header menu.toolbar button {
|
||||
-moz-box-sizing: border-box;
|
||||
position: relative;
|
||||
width: auto;
|
||||
min-width: 5rem;
|
||||
height: 4.9rem;
|
||||
margin-bottom: 0;
|
||||
padding: 0 1rem;
|
||||
border-radius: 0;
|
||||
line-height: 4.9rem;
|
||||
background: none;
|
||||
text-align: center;
|
||||
text-shadow: none;
|
||||
z-index: 5;
|
||||
}
|
||||
header:-moz-dir(ltr) menu.toolbar a,
|
||||
header:-moz-dir(ltr) menu.toolbar button {
|
||||
float: left;
|
||||
}
|
||||
header:-moz-dir(rtl) menu.toolbar a,
|
||||
header:-moz-dir(rtl) menu.toolbar button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
header a,
|
||||
header button {
|
||||
border: none;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
font-weight: 400;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.1em;
|
||||
color: #fff;
|
||||
border-radius: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner {
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Pressed state */
|
||||
header a:active .icon:after,
|
||||
header button:active .icon:after,
|
||||
header menu.toolbar a:active,
|
||||
header menu.toolbar button:active {
|
||||
background: #008aaa;
|
||||
}
|
||||
|
||||
/* Disabled state */
|
||||
header menu.toolbar a[aria-disabled="true"],
|
||||
header menu.toolbar button[disabled] {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Icon definitions */
|
||||
header .icon {
|
||||
position: relative;
|
||||
float: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 4rem;
|
||||
height: 4.9rem;
|
||||
margin: 0 -1rem;
|
||||
background: transparent no-repeat center center / 3rem auto;
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header .icon.icon-close {
|
||||
background-image: url(images/icons/close.png);
|
||||
}
|
||||
|
||||
header .icon.icon-back {
|
||||
background-image: url(images/icons/back.png);
|
||||
}
|
||||
|
||||
/* Navigation links (back, cancel, etc) */
|
||||
header > button,
|
||||
header > a {
|
||||
width: 5rem;
|
||||
height: 4.9rem;
|
||||
background: none;
|
||||
overflow: visible;
|
||||
margin: 0 -1rem;
|
||||
margin-inline-start: -3rem;
|
||||
position: relative;
|
||||
}
|
||||
header:-moz-dir(ltr) > button,
|
||||
header:-moz-dir(ltr) > a {
|
||||
float: left;
|
||||
}
|
||||
header:-moz-dir(rtl) > button,
|
||||
header:-moz-dir(rtl) > a {
|
||||
float: right;
|
||||
}
|
||||
|
||||
header > button::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
header > button .icon,
|
||||
header > a .icon {
|
||||
position: static;
|
||||
display: block;
|
||||
width: 3rem;
|
||||
height: 4.9rem;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
header > button .icon:after,
|
||||
header > a .icon:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
offset-inline-start: 0;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
width: 3rem;
|
||||
height: 4.9rem;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
section {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 7rem;
|
||||
left: 1.5rem;
|
||||
right: 1.5rem;
|
||||
bottom: 2rem;
|
||||
font-size: 1.6rem;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
/* Specific component code */
|
||||
menu {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-height: calc(100% - 13.5rem); /*header(5rem) + footer(7rem) + padding(1.5rem)*/
|
||||
height: auto;
|
||||
padding-top: 1.5rem;
|
||||
overflow: auto;
|
||||
width: auto;
|
||||
border: none;
|
||||
background: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 7rem;
|
||||
}
|
||||
|
||||
button {
|
||||
width: calc(100% - 3rem);
|
||||
height: 4rem;
|
||||
-moz-box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
font-weight: normal;
|
||||
line-height: 4rem;
|
||||
outline: none;
|
||||
font-size: 1.6rem;
|
||||
text-shadow: none;
|
||||
padding: 0 1.2rem;
|
||||
margin: 0 1.5rem 1rem;
|
||||
background: rgba(87, 87, 87, 0.8);
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
}
|
||||
button:-moz-dir(ltr) { text-align: left; }
|
||||
button:-moz-dir(rtl) { text-align: right; }
|
||||
|
||||
span.gaia-menu-cancel {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background: #4d4d4d;
|
||||
height: 7rem;
|
||||
offset-inline-start: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
span.gaia-menu-cancel button {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
offset-inline-start: 0;
|
||||
color: #333;
|
||||
background: #d8d8d8;
|
||||
text-align: center;
|
||||
border: none;
|
||||
margin-bottom: 1.5rem;
|
||||
border-radius: 2rem;
|
||||
}
|
||||
|
||||
button:nth-last-child(2) {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
/* Press state */
|
||||
button:active,
|
||||
span.gaia-menu-cancel button:active {
|
||||
background: #00aacc;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
button[disabled] {
|
||||
background-color: rgba(87, 87, 87, 0.8);
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
button[disabled]:last-child {
|
||||
background-color: #e7e7e7;
|
||||
color: #a6a6a6;
|
||||
opacity: 1;
|
||||
}
|
||||
|
After Width: | Height: | Size: 76 B |
|
|
@ -0,0 +1,185 @@
|
|||
'use strict';
|
||||
/* global ComponentUtils, LazyLoader */
|
||||
|
||||
/**
|
||||
* GaiaSimPicker is a helper for dynamically generating menus for selecting SIM
|
||||
* cards when making calls, sending SMS, etc. It also returns any currently
|
||||
* in-use SIMs if there is an active call, but only when an app has mozTelephony
|
||||
* permissions.
|
||||
*
|
||||
* Dependencies: gaia-menu web component.
|
||||
*/
|
||||
window.GaiaSimPicker = (function(win) {
|
||||
// Extend from HTMLElement prototype
|
||||
var proto = Object.create(HTMLElement.prototype);
|
||||
|
||||
// Allow baseurl to be overridden (used for demo page)
|
||||
var baseurl = window.GaiaSimPickerBaseurl ||
|
||||
'/shared/elements/gaia_sim_picker/';
|
||||
|
||||
proto.createdCallback = function() {
|
||||
var shadow = this.createShadowRoot();
|
||||
|
||||
shadow.innerHTML = template;
|
||||
|
||||
this._menu = this.shadowRoot.querySelector('gaia-menu');
|
||||
|
||||
/**
|
||||
* Workaround for bug 1100912, to be removed when bug is fixed:
|
||||
* set internal gaia-menu dir, that's enough for directional-specific
|
||||
* CSS to kick in.
|
||||
*/
|
||||
var updateDir = () => {
|
||||
this._menu.dir = document.dir || 'ltr';
|
||||
};
|
||||
updateDir();
|
||||
window.addEventListener('localized', updateDir);
|
||||
|
||||
LazyLoader.load(['/shared/js/component_utils.js'], function() {
|
||||
ComponentUtils.style.call(this, baseurl);
|
||||
}.bind(this));
|
||||
|
||||
navigator.mozL10n.ready(this._localizeShadowDom.bind(this));
|
||||
};
|
||||
|
||||
proto._domBuilt = false;
|
||||
|
||||
proto._simSelectedCallbacks = [];
|
||||
|
||||
proto._dispatchSimSelected = function(cardIndex) {
|
||||
var simSelectedEvent = new CustomEvent('gaiasimpicker-simselected', {
|
||||
canBubble: true,
|
||||
cancelable: true,
|
||||
detail: {
|
||||
cardIndex: cardIndex
|
||||
}
|
||||
});
|
||||
|
||||
if (this.dispatchEvent(simSelectedEvent)) {
|
||||
// Only call the stored callbacks if the event wasn't preventDefaulted.
|
||||
proto._simSelectedCallbacks.forEach(function(callback) {
|
||||
callback(cardIndex);
|
||||
});
|
||||
proto._simSelectedCallbacks = [];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Localize the component manually as l10n attributes are not supported
|
||||
* within the shadow dom. See also: bug 1026236.
|
||||
*/
|
||||
proto._localizeShadowDom = function() {
|
||||
navigator.mozL10n.translateFragment(this.shadowRoot);
|
||||
};
|
||||
|
||||
proto.getOrPick = function(defaultCardIndex,
|
||||
phoneNumber,
|
||||
simSelectedCallback) {
|
||||
if (simSelectedCallback) {
|
||||
this._simSelectedCallbacks.push(simSelectedCallback);
|
||||
}
|
||||
|
||||
if (window.TelephonyHelper) {
|
||||
var inUseSim = window.TelephonyHelper.getInUseSim();
|
||||
if (inUseSim !== null) {
|
||||
this._dispatchSimSelected(inUseSim);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var dialViaElt = this.shadowRoot.querySelector('#sim-picker-dial-via');
|
||||
if (phoneNumber) {
|
||||
navigator.mozL10n.setAttributes(dialViaElt,
|
||||
'gaia-sim-picker-dial-via-with-number',
|
||||
{phoneNumber: phoneNumber});
|
||||
} else {
|
||||
dialViaElt.setAttribute('data-l10n-id', 'gaia-sim-picker-select-sim');
|
||||
}
|
||||
|
||||
this._buildDom();
|
||||
this._localizeShadowDom();
|
||||
|
||||
var simButtons = this.shadowRoot.querySelectorAll(
|
||||
'button[data-card-index]');
|
||||
|
||||
for (var i = 0; i < simButtons.length; i++) {
|
||||
if (simButtons[i].dataset.cardIndex == defaultCardIndex) {
|
||||
simButtons[i].classList.add('is-default');
|
||||
} else {
|
||||
simButtons[i].classList.remove('is-default');
|
||||
}
|
||||
}
|
||||
|
||||
// we want to wait for l10n to happen before we display the UI
|
||||
LazyLoader.load(['/shared/elements/gaia_menu/script.js'], function() {
|
||||
navigator.mozL10n.once(function() {
|
||||
this._menu.show();
|
||||
this.focus();
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
proto._buildDom = function() {
|
||||
if (this._domBuilt) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._domBuilt = true;
|
||||
|
||||
var templateNode = this.shadowRoot.querySelector(
|
||||
'#sim-picker-button-template');
|
||||
|
||||
for (var i = 0; i < navigator.mozIccManager.iccIds.length; i++) {
|
||||
var clonedNode = templateNode.cloneNode(true);
|
||||
clonedNode.dataset.cardIndex = i;
|
||||
clonedNode.addEventListener('click', this);
|
||||
|
||||
var button = clonedNode.querySelector('.js-sim-picker-button');
|
||||
// For example only; l10n will overwrite this.
|
||||
button.textContent = 'SIM' + (i+1);
|
||||
navigator.mozL10n.setAttributes(
|
||||
button, 'gaia-sim-picker-button', {n: i + 1});
|
||||
templateNode.parentNode.insertBefore(clonedNode, templateNode);
|
||||
}
|
||||
templateNode.remove();
|
||||
};
|
||||
|
||||
proto.handleEvent = function(e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (e.target.nodeName !== 'BUTTON') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.target.dataset.cardIndex) {
|
||||
this._dispatchSimSelected(parseInt(e.target.dataset.cardIndex));
|
||||
} else {
|
||||
// Clear the stored callbacks anyways since the user must have hit cancel.
|
||||
this._simSelectedCallbacks = [];
|
||||
}
|
||||
|
||||
this._menu.hide();
|
||||
};
|
||||
|
||||
var stylesheet = baseurl + '../gaia_menu/style.css';
|
||||
|
||||
// TODO: We should make this a template node and use template.cloneNode, but
|
||||
// nested web components don't work yet using this method.
|
||||
var template = '<style scoped>' +
|
||||
'@import url(' + stylesheet + ');</style>' +
|
||||
`<gaia-menu hidden>
|
||||
<header id="sim-picker-dial-via">Dial 12345 via</header>
|
||||
<button id="sim-picker-button-template">
|
||||
<span class="js-sim-picker-button">
|
||||
SIMX
|
||||
</span>
|
||||
<span class="sim-default" data-l10n-id="gaia-sim-picker-button-default">
|
||||
(default)
|
||||
</span>
|
||||
</button>
|
||||
</gaia-menu>`;
|
||||
|
||||
// Register and return the constructor
|
||||
return document.registerElement('gaia-sim-picker', { prototype: proto });
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
.sim-default {
|
||||
display: none;
|
||||
margin-inline-start: 0.15rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.is-default .sim-default {
|
||||
display: initial;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* ComponentUtils is a utility which allows us to use web components earlier
|
||||
* than we should be able to by polyfilling and fixing platform deficiencies.
|
||||
*/
|
||||
exports.ComponentUtils = {
|
||||
|
||||
/**
|
||||
* Injects a style.css into both the shadow root and outside the shadow
|
||||
* root so we can style projected content. Bug 992249.
|
||||
*/
|
||||
style: function(baseUrl) { if (window.VulpesCompat) { window.VulpesCompat.componentStyle(this, baseUrl).catch(console.error); return; }
|
||||
var style = document.createElement('style');
|
||||
var url = baseUrl + 'style.css';
|
||||
var self = this;
|
||||
|
||||
style.setAttribute('scoped', '');
|
||||
style.innerHTML = '@import url(' + url + ');';
|
||||
this.appendChild(style);
|
||||
|
||||
this.style.visibility = 'hidden';
|
||||
|
||||
// Wait for the stylesheet to load before injecting
|
||||
// it into the shadow-dom. This is to work around
|
||||
// bug 1003294, let's review once landed.
|
||||
style.addEventListener('load', function() {
|
||||
|
||||
// Put a clone of the stylesheet into the shadow-dom.
|
||||
// We have to use two <style> nodes, to work around
|
||||
// the lack of `:host` (bug 992245) and `:content`
|
||||
// (bug 992249) selectors. Once we have those we
|
||||
// can do all our styling from a single style-sheet
|
||||
// within the shadow-dom.
|
||||
if (self.shadowRoot) {
|
||||
self.shadowRoot.appendChild(style.cloneNode(true));
|
||||
}
|
||||
|
||||
self.style.visibility = '';
|
||||
});
|
||||
}
|
||||
};
|
||||
}(window));
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
/* exported ConfirmDialog */
|
||||
'use strict';
|
||||
|
||||
var ConfirmDialog = (function() {
|
||||
var isAnimationPlaying = false;
|
||||
var isShown = false;
|
||||
var doc = document; try { if (!document.getElementById("confirmation-message")) doc = parent.document; } catch (_) {}
|
||||
var screen = doc.getElementById('confirmation-message');
|
||||
var titleNode = screen.querySelector('h1');
|
||||
var messageNode = screen.querySelector('p');
|
||||
var action1Node = screen.querySelector('button:nth-of-type(1)');
|
||||
var action1Callback;
|
||||
var action2Node = screen.querySelector('button:nth-of-type(2)');
|
||||
var action2Callback;
|
||||
var oldzIndex;
|
||||
|
||||
var callBackAndPreventDefault = function callBackAndPreventDefault(ev) {
|
||||
if (ev.target === action1Node) {
|
||||
action1Callback();
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
} else if (ev.target === action2Node) {
|
||||
action2Callback();
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var _hide = function _hide() {
|
||||
// Reset the 'confirmation-message' element and its children to their
|
||||
// initial values and hide it.
|
||||
if (!isShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
titleNode.removeAttribute('data-l10n-id');
|
||||
titleNode.className = '';
|
||||
messageNode.removeAttribute('data-l10n-id');
|
||||
messageNode.className = '';
|
||||
action1Node.removeAttribute('data-l10n-id');
|
||||
action1Node.onclick = null;
|
||||
action2Node.removeAttribute('data-l10n-id');
|
||||
action2Node.onclick = null;
|
||||
screen.classList.remove('fade-in');
|
||||
screen.classList.add('fade-out');
|
||||
isAnimationPlaying = true;
|
||||
// Custom event that can be used to apply (screen reader) visibility
|
||||
// changes.
|
||||
window.dispatchEvent(new CustomEvent('confirmdialoghiding'));
|
||||
screen.addEventListener('animationend', function cd_fadeOut(ev) {
|
||||
action1Node.className = '';
|
||||
action2Node.className = '';
|
||||
isAnimationPlaying = false;
|
||||
screen.removeEventListener('animationend', cd_fadeOut);
|
||||
screen.classList.add('no-opacity');
|
||||
screen.classList.add('hide');
|
||||
isShown = false;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Method that shows the dialog
|
||||
* @param {String} title the title of the dialog. null or empty for
|
||||
* no title.
|
||||
* @param {String} msg message for the dialog.
|
||||
* @param {Object} action1 {title, isDanger, callback} object.
|
||||
* @param {Object} action2 {title, isDanger, callback} object.
|
||||
*/
|
||||
var _show = function _show(title, msg, action1, action2, options) {
|
||||
|
||||
var setL10nAttributes = function (element, options){
|
||||
if ('string' === typeof options) {
|
||||
document.l10n.setAttributes(element, options);
|
||||
}
|
||||
|
||||
if(options.id) {
|
||||
document.l10n.setAttributes(element, options.id, options.args);
|
||||
}
|
||||
};
|
||||
|
||||
if (options && options.zIndex) {
|
||||
oldzIndex = screen.style.zIndex;
|
||||
screen.style.zIndex = options.zIndex;
|
||||
}
|
||||
else {
|
||||
oldzIndex = null;
|
||||
}
|
||||
if (title) {
|
||||
setL10nAttributes(titleNode, title);
|
||||
} else {
|
||||
titleNode.classList.add('hide');
|
||||
}
|
||||
if (msg) {
|
||||
setL10nAttributes(messageNode, msg);
|
||||
} else {
|
||||
messageNode.classList.add('hide');
|
||||
}
|
||||
if (action1) {
|
||||
if (action1.title) {
|
||||
setL10nAttributes(action1Node, action1.title);
|
||||
}
|
||||
if (action1.isDanger) {
|
||||
action1Node.classList.add('danger');
|
||||
}
|
||||
if (action1.isRecommend) {
|
||||
action1Node.classList.add('recommend');
|
||||
}
|
||||
if (action1.callback) {
|
||||
action1Callback = action1.callback;
|
||||
action1Node.onclick = callBackAndPreventDefault;
|
||||
}
|
||||
if (!action2) {
|
||||
action2Node.classList.add('hide');
|
||||
action1Node.classList.add('full');
|
||||
}
|
||||
}
|
||||
if (action2) {
|
||||
if (action2.title) {
|
||||
setL10nAttributes(action2Node, action2.title);
|
||||
}
|
||||
if (action2.isDanger) {
|
||||
action2Node.classList.add('danger');
|
||||
}
|
||||
if (action2.isRecommend) {
|
||||
action2Node.classList.add('recommend');
|
||||
}
|
||||
if (action2.callback) {
|
||||
action2Callback = action2.callback;
|
||||
action2Node.onclick = callBackAndPreventDefault;
|
||||
}
|
||||
if (!action1) {
|
||||
action1Node.classList.add('hide');
|
||||
action2Node.classList.add('full');
|
||||
}
|
||||
}
|
||||
if (isShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
screen.classList.remove('hide');
|
||||
screen.classList.remove('fade-out');
|
||||
screen.classList.add('fade-in');
|
||||
isAnimationPlaying = true;
|
||||
// Custom event that can be used to apply (screen reader) visibility
|
||||
// changes.
|
||||
window.dispatchEvent(new CustomEvent('confirmdialogshowing'));
|
||||
screen.addEventListener('animationend', function cd_fadeIn(ev) {
|
||||
isAnimationPlaying = false;
|
||||
screen.removeEventListener('animationend', cd_fadeIn);
|
||||
screen.classList.remove('no-opacity');
|
||||
isShown = true;
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
hide: function dialog_hide() {
|
||||
// Reset the 'confirmation-message' element and its children to their
|
||||
// initial values and hide it.
|
||||
if (oldzIndex) {
|
||||
screen.style.zIndex = oldzIndex;
|
||||
oldzIndex = null;
|
||||
}
|
||||
|
||||
if (!isAnimationPlaying) {
|
||||
_hide();
|
||||
return;
|
||||
}
|
||||
|
||||
screen.addEventListener('animationend',
|
||||
function cd_hideWhenFinished(ev) {
|
||||
screen.removeEventListener('animationend', cd_hideWhenFinished);
|
||||
_hide();
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method that shows the dialog
|
||||
* @param {String} title the title of the dialog. null or empty for
|
||||
* no title.
|
||||
* @param {String} msg message for the dialog.
|
||||
* @param {Object} action1 {title, isDanger, callback} object.
|
||||
* @param {Object} action2 {title, isDanger, callback} object.
|
||||
*/
|
||||
show: function dialog_show(title, msg, action1, action2, options) {
|
||||
if (!isAnimationPlaying) {
|
||||
_show(title, msg, action1, action2, options);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
screen.addEventListener('animationend',
|
||||
function cd_showWhenFinished(ev) {
|
||||
screen.removeEventListener('animationend', cd_showWhenFinished);
|
||||
_show(title, msg, action1, action2, options);
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
;'use strict';(function(exports){var STORE_NAME='ice_contacts';var store=null;var status='not_initialized';var FIELD='ICE_CONTACTS';function init(){if(store!==null){return Promise.resolve(store);}
|
||||
if(!navigator.getDataStores){return Promise.reject('No DS supported');}
|
||||
if(status==='initialising'){document.addEventListener('ice_ready',function ready(){document.removeEventListener('ice_ready',ready);if(store===null){return Promise.reject('Error getting store');}else{return Promise.resolve(store);}});}
|
||||
status='initialising';return new Promise(function(resolve,reject){navigator.getDataStores(STORE_NAME).then(function(stores){if(!stores||stores.length<0){document.dispatchEvent(new Event('on_ice_ready'));return reject('No DS found');}else{store=stores[0];status='initialised';document.dispatchEvent(new Event('ice_ready'));return resolve(store);}});});}
|
||||
var ICEStore={setContacts:function(iceContacts){return init().then(function(){return store.put(iceContacts,FIELD).then(function(){return Promise.resolve(iceContacts);});});},getContacts:function(){return init().then(function(){return store.get(FIELD);});},onChange:function(cb){return init().then(function(){store.addEventListener('change',function(){store.get(FIELD).then(cb);});});}};exports.ICEStore=ICEStore;})(window);
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
;'use strict';function DtmfTone(tone,short,serviceId){this.tone=tone;this.short=short;this.serviceId=serviceId;this.timer=0;}
|
||||
DtmfTone.kShortToneLength=120;DtmfTone.prototype={play:function dt_play(){clearTimeout(this.timer);navigator.mozTelephony.stopTone(this.serviceId);navigator.mozTelephony.startTone(this.tone,this.serviceId);if(this.short){this.timer=window.setTimeout(function dt_stopTone(serviceId){navigator.mozTelephony.stopTone(serviceId);},DtmfTone.kShortToneLength,this.serviceId);}},stop:function dt_stop(){clearTimeout(this.timer);navigator.mozTelephony.stopTone(this.serviceId);}};
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
'use strict';
|
||||
|
||||
/* globals ConfirmDialog, LazyLoader */
|
||||
/* exported TelephonyMessages */
|
||||
|
||||
var TelephonyMessages = {
|
||||
/**
|
||||
* Constants for what message to display when we get a bad number error.
|
||||
* Depends on the situation.
|
||||
*/
|
||||
// Display the regular "invalid number" message, as this is a regular call.
|
||||
REGULAR_CALL: 0,
|
||||
// We have no network and/or no SIM, so we can only make emergency calls.
|
||||
// Display the "no network" message.
|
||||
NO_NETWORK: 1,
|
||||
// We are making a call from an emergency call view, so calls can only be
|
||||
// placed to emergency and ICE numbers. Display the "not an emergency number"
|
||||
// message.
|
||||
EMERGENCY_ONLY: 2,
|
||||
|
||||
displayMessage: function(message, number) {
|
||||
var dialogTitle, dialogBody;
|
||||
|
||||
switch (message) {
|
||||
case 'BadNumber':
|
||||
dialogTitle = 'invalidNumberToDialTitle';
|
||||
dialogBody = 'invalidNumberToDialMessage';
|
||||
break;
|
||||
case 'FlightMode':
|
||||
dialogTitle = 'callAirplaneModeTitle';
|
||||
dialogBody = 'callAirplaneModeMessage';
|
||||
break;
|
||||
case 'NoNetwork':
|
||||
dialogTitle = 'emergencyDialogTitle';
|
||||
dialogBody = 'emergencyDialogBodyBadNumber';
|
||||
break;
|
||||
case 'DeviceNotAccepted':
|
||||
dialogTitle = 'emergencyDialogTitle';
|
||||
dialogBody = 'emergencyDialogBodyDeviceNotAccepted';
|
||||
break;
|
||||
case 'UnableToCall':
|
||||
dialogTitle = 'unableToCallTitle';
|
||||
dialogBody = 'unableToCallMessage';
|
||||
break;
|
||||
case 'NumberIsBusy':
|
||||
dialogTitle = 'numberIsBusyTitle';
|
||||
dialogBody = 'numberIsBusyMessage';
|
||||
break;
|
||||
case 'FixedDialingNumbers':
|
||||
dialogTitle = 'fdnIsActiveTitle';
|
||||
dialogBody = 'fdnIsActiveMessage';
|
||||
break;
|
||||
case 'OtherConnectionInUse':
|
||||
dialogTitle = 'otherConnectionInUseTitle';
|
||||
dialogBody = 'otherConnectionInUseMessage';
|
||||
break;
|
||||
case 'OperatorDeterminedBarring':
|
||||
dialogTitle = 'unableToCallTitle';
|
||||
dialogBody = 'callBarredByTheOperatorMessage';
|
||||
break;
|
||||
case 'EmergencyCallOnly':
|
||||
dialogTitle = 'emergency-call-only';
|
||||
dialogBody = 'emergency-call-error';
|
||||
break;
|
||||
default:
|
||||
console.error('Invalid message argument'); // Should never happen
|
||||
return;
|
||||
}
|
||||
|
||||
LazyLoader.load(['/shared/style/confirm.css',
|
||||
'/shared/js/confirm.js',
|
||||
document.getElementById('confirmation-message')],
|
||||
function() {
|
||||
ConfirmDialog.show(
|
||||
dialogTitle,
|
||||
{id: dialogBody, args: {number: number}},
|
||||
{
|
||||
title: 'emergencyDialogBtnOk', // Just 'ok' would be better.
|
||||
callback: function() {
|
||||
ConfirmDialog.hide();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
handleDisconnect: function(reason, number, emergencyOptions) {
|
||||
if (reason === 'NormalCallClearing') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.handleError(reason + 'Error', number, emergencyOptions);
|
||||
},
|
||||
|
||||
handleError: function(errorName, number, emergencyOptions) {
|
||||
// We ignore this error because some networks generate this with
|
||||
// STK CallControl when calling Voicemail pilots (e.g. TMobile)
|
||||
if (errorName === 'ModifiedDialError') {
|
||||
console.log('ModifiedDialError');
|
||||
return;
|
||||
}
|
||||
|
||||
if (errorName === 'BadNumberError') {
|
||||
if (emergencyOptions === this.REGULAR_CALL) {
|
||||
this.displayMessage('BadNumber');
|
||||
} else if (emergencyOptions === this.NO_NETWORK) {
|
||||
this.displayMessage('NoNetwork');
|
||||
} else if (emergencyOptions === this.EMERGENCY_ONLY) {
|
||||
this.displayMessage('EmergencyCallOnly', number);
|
||||
} else {
|
||||
console.error('Unexpected emergency options: ' + emergencyOptions);
|
||||
}
|
||||
} else if (errorName === 'DeviceNotAcceptedError') {
|
||||
this.displayMessage('DeviceNotAccepted');
|
||||
} else if (errorName === 'RadioNotAvailable') {
|
||||
this.displayMessage('FlightMode');
|
||||
} else if (errorName === 'BusyError') {
|
||||
this.displayMessage('NumberIsBusy');
|
||||
} else if (errorName === 'FDNBlockedError' ||
|
||||
errorName === 'FdnCheckFailure') {
|
||||
this.displayMessage('FixedDialingNumbers', number);
|
||||
} else if (errorName === 'OtherConnectionInUse') {
|
||||
this.displayMessage('OtherConnectionInUse');
|
||||
} else if (errorName === 'OperatorDeterminedBarringError') {
|
||||
this.displayMessage('OperatorDeterminedBarring');
|
||||
} else {
|
||||
// If the call failed for some other reason we should still
|
||||
// display something to the user. See bug 846403.
|
||||
console.error('Unexpected error: ', errorName);
|
||||
this.displayMessage('UnableToCall');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
;'use strict';const kMasterVolume=0.5;const kToneVolume=0.7;const kShortPressDuration=0.15;const kAttackDuration=0.025;const kDecayDuration=0.025;const kReleaseDuration=0.05;var TonePlayer={_audioContext:null,_channel:null,_gainNode:null,_playingNodes:[],_maybeTrashAudio:null,_initialized:false,init:function tp_init(channel){var telephony=navigator.mozTelephony;this._reset();this._channel=channel;this._maybeTrashAudio=(function tp_maybeTrashAudio(){var callIsActive=telephony&&(telephony.calls.length||telephony.conferenceGroup.calls.length);if(document.hidden&&!((this._channel==='telephony')&&callIsActive)){this._trashAudio();}}).bind(this);window.addEventListener('visibilitychange',this._maybeTrashAudio);telephony&&telephony.addEventListener('callschanged',this._maybeTrashAudio);this._initialized=true;},teardown:function tp_teardown(){var telephony=navigator.mozTelephony;telephony&&telephony.removeEventListener('callschanged',this._maybeTrashAudio);window.removeEventListener('visibilitychange',this._maybeTrashAudio);this._reset();this._initialized=false;},_reset:function tp_reset(){this._audioContext=null;this._channel=null;this._gainNode=null;this._playingNodes=[];this._maybeTrashAudio=null;},_ensureAudio:function tp_ensureAudio(){if(this._audioContext||!this._initialized){return;}
|
||||
this._audioContext=new AudioContext();},_trashAudio:function tp_trashAudio(){this.stop();this._audioContext=null;},_startAt:function tp_startAt(frequencies,when,duration){var context=this._audioContext;var sampleRate=context.sampleRate;var envelope=context.createBuffer(1,(duration?duration:0.05)*sampleRate,sampleRate);for(var i=0;i<envelope.length;i++){var factor=kToneVolume;var t=i/sampleRate;if(t<=kAttackDuration){factor=t/kAttackDuration;}else if(t-kAttackDuration<=kDecayDuration){factor=1.0-(1.0-kToneVolume)*(t-kAttackDuration)/kDecayDuration;}
|
||||
if(!duration){factor-=kToneVolume;}else if(t>duration-kReleaseDuration){factor*=(duration-t)/kReleaseDuration;}
|
||||
envelope.getChannelData(0)[i]=factor*kMasterVolume;}
|
||||
var gainNode=context.createGain();gainNode.connect(context.destination);if(!duration){this._gainNode=gainNode;}
|
||||
var envelopeNode=context.createBufferSource();envelopeNode.buffer=envelope;envelopeNode.start(when);envelopeNode.connect(gainNode.gain);gainNode.gain.setValueAtTime(duration?0.0:kToneVolume*kMasterVolume,0.0);for(i=0;i<frequencies.length;++i){var oscNode=this._audioContext.createOscillator();oscNode.type='sine';oscNode.frequency.value=frequencies[i];oscNode.start(when);if(duration){oscNode.stop(Math.max(when,context.currentTime+0.5)+duration);}else{this._playingNodes.push(oscNode);}
|
||||
oscNode.connect(gainNode);}},start:function tp_start(frequencies,shortPress){this._ensureAudio();this._startAt(frequencies,0,shortPress?kShortPressDuration:0);},stop:function tp_stop(){if(!this._gainNode){return;}
|
||||
var context=this._audioContext;var sampleRate=context.sampleRate;var gain=this._gainNode.gain;this._gainNode=null;var ramp=context.createBuffer(1,kReleaseDuration*sampleRate,sampleRate);for(var i=0;i<ramp.length;i++){ramp.getChannelData(0)[i]=(ramp.length-i-1)/ramp.length*kToneVolume*kMasterVolume;}
|
||||
var rampNode=context.createBufferSource();rampNode.buffer=ramp;rampNode.start();rampNode.connect(gain);gain.setValueAtTime(0.0,0.0);while(this._playingNodes.length){this._playingNodes.pop().stop(context.currentTime+kReleaseDuration+0.5);}},playSequence:function tp_playSequence(sequence){this._ensureAudio();var when=this._audioContext.currentTime+0.2;for(var index=0;index<sequence.length;++index){var step=sequence[index];var frequencies=step.slice(0,2);var duration=step[2]/1000;this._startAt(frequencies,when,duration);when+=duration;}}};
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
;'use strict';var Utils={prettyDate:function ut_prettyDate(time){var f=Intl.DateTimeFormat(navigator.languages,{hour12:navigator.mozHour12,hour:'numeric',minute:'numeric'});return f.format(new Date(time));},prettyDuration:function(node,duration,l10nPrefix){var elapsed=new Date(duration);var h=elapsed.getUTCHours();var m=elapsed.getUTCMinutes();var s=elapsed.getUTCSeconds();var l10nId=l10nPrefix||'callDuration';var durationL10n={h:h+'',m:m+'',s:s+''};if(l10nId==='callDuration'){durationL10n={h:(h>9?'':'0')+h,m:(m>9?'':'0')+m,s:(s>9?'':'0')+s};}
|
||||
if(l10nPrefix==='callDurationTextFormat'&&h===0&&m===0){l10nId+='Seconds';}else{l10nId+=h>0?'Hours':'Minutes';}
|
||||
navigator.mozL10n.setAttributes(node,l10nId,durationL10n);},setHeaderDate:function ut_setHeaderDate(elem,time){var diff=(Date.now()-time)/1000;var day_diff=Math.floor(diff/86400);var formattedTime;if(isNaN(day_diff)){elem.setAttribute('data-l10n-id','incorrectDate');return;}else if(day_diff===0){elem.setAttribute('data-l10n-id','today');return;}else if(day_diff===1){elem.setAttribute('data-l10n-id','yesterday');return;}else if(day_diff<6){formattedTime=(new Date(time)).toLocaleString(navigator.languages,{weekday:'long',});}else{formattedTime=(new Date(time)).toLocaleString(navigator.languages,{year:'2-digit',month:'2-digit',day:'2-digit'});}
|
||||
elem.removeAttribute('data-l10n-id');elem.textContent=formattedTime;},getPhoneNumberPrimaryInfo:function ut_getPhoneNumberPrimaryInfo(matchingTel,contact){if(contact){if(contact.name&&contact.name.length&&contact.name[0]!==''){return contact.name;}else if(contact.org&&contact.org.length&&contact.org[0]!==''){return contact.org;}}
|
||||
if(matchingTel){return matchingTel.value;}
|
||||
return null;},toCamelCase:function ut_toCamelCase(str){return str.replace(/\-(.)/g,function replacer(str,p1){return p1.toUpperCase();});},_phoneTypesL10n:{'mobile':'phone_type_mobile','home':'phone_type_home','work':'phone_type_work','personal':'phone_type_personal','faxHome':'phone_type_fax_home','faxOffice':'phone_type_fax_office','faxOther':'phone_type_fax_other','other':'phone_type_other'},getPhoneNumberAdditionalInfo:function ut_getPhoneNumberAdditionalInfo(matchingTel){var type=matchingTel.type||'mobile';var carrier=matchingTel.carrier;if(Array.isArray(type)){type=type[0];}
|
||||
var id;var args={};if(this._phoneTypesL10n.hasOwnProperty(type)){id=this._phoneTypesL10n[type];}else{id='phone_type_custom';args.type=type;}
|
||||
if(carrier){id+='_and_carrier';args.carrier=carrier;}
|
||||
return{id:id,args:Object.keys(args).length?args:null};},isPhoneType:function ut_isPhoneType(type){return this._phoneTypesL10n.hasOwnProperty(type);}};
|
||||
245
assets/webapps/emergency-call.gaiamobile.org/shared/js/l10n.js
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
;(function(window,undefined){'use strict';function L10nError(message,id,loc){this.name='L10nError';this.message=message;this.id=id;this.loc=loc;}
|
||||
L10nError.prototype=Object.create(Error.prototype);L10nError.prototype.constructor=L10nError;var io={_load:function(type,url,callback,sync){var xhr=new XMLHttpRequest();var needParse;if(xhr.overrideMimeType){xhr.overrideMimeType(type);}
|
||||
xhr.open('GET',url,!sync);if(type==='application/json'){if(sync){needParse=true;}else{xhr.responseType='json';}}
|
||||
xhr.addEventListener('load',function io_onload(e){if(e.target.status===200||e.target.status===0){var res=e.target.response||e.target.responseText;callback(null,needParse?JSON.parse(res):res);}else{callback(new L10nError('Not found: '+url));}});xhr.addEventListener('error',callback);xhr.addEventListener('timeout',callback);try{xhr.send(null);}catch(e){if(e.name==='NS_ERROR_FILE_NOT_FOUND'){callback(new L10nError('Not found: '+url));}else{throw e;}}},load:function(url,callback,sync){return io._load('text/plain',url,callback,sync);},loadJSON:function(url,callback,sync){return io._load('application/json',url,callback,sync);}};function EventEmitter(){}
|
||||
EventEmitter.prototype.emit=function ee_emit(){if(!this._listeners){return;}
|
||||
var args=Array.prototype.slice.call(arguments);var type=args.shift();if(!this._listeners[type]){return;}
|
||||
var typeListeners=this._listeners[type].slice();for(var i=0;i<typeListeners.length;i++){typeListeners[i].apply(this,args);}};EventEmitter.prototype.addEventListener=function ee_add(type,listener){if(!this._listeners){this._listeners={};}
|
||||
if(!(type in this._listeners)){this._listeners[type]=[];}
|
||||
this._listeners[type].push(listener);};EventEmitter.prototype.removeEventListener=function ee_rm(type,listener){if(!this._listeners){return;}
|
||||
var typeListeners=this._listeners[type];var pos=typeListeners.indexOf(listener);if(pos===-1){return;}
|
||||
typeListeners.splice(pos,1);};function getPluralRule(lang){var locales2rules={'af':3,'ak':4,'am':4,'ar':1,'asa':3,'az':0,'be':11,'bem':3,'bez':3,'bg':3,'bh':4,'bm':0,'bn':3,'bo':0,'br':20,'brx':3,'bs':11,'ca':3,'cgg':3,'chr':3,'cs':12,'cy':17,'da':3,'de':3,'dv':3,'dz':0,'ee':3,'el':3,'en':3,'eo':3,'es':3,'et':3,'eu':3,'fa':0,'ff':5,'fi':3,'fil':4,'fo':3,'fr':5,'fur':3,'fy':3,'ga':8,'gd':24,'gl':3,'gsw':3,'gu':3,'guw':4,'gv':23,'ha':3,'haw':3,'he':2,'hi':4,'hr':11,'hu':0,'id':0,'ig':0,'ii':0,'is':3,'it':3,'iu':7,'ja':0,'jmc':3,'jv':0,'ka':0,'kab':5,'kaj':3,'kcg':3,'kde':0,'kea':0,'kk':3,'kl':3,'km':0,'kn':0,'ko':0,'ksb':3,'ksh':21,'ku':3,'kw':7,'lag':18,'lb':3,'lg':3,'ln':4,'lo':0,'lt':10,'lv':6,'mas':3,'mg':4,'mk':16,'ml':3,'mn':3,'mo':9,'mr':3,'ms':0,'mt':15,'my':0,'nah':3,'naq':7,'nb':3,'nd':3,'ne':3,'nl':3,'nn':3,'no':3,'nr':3,'nso':4,'ny':3,'nyn':3,'om':3,'or':3,'pa':3,'pap':3,'pl':13,'ps':3,'pt':3,'rm':3,'ro':9,'rof':3,'ru':11,'rwk':3,'sah':0,'saq':3,'se':7,'seh':3,'ses':0,'sg':0,'sh':11,'shi':19,'sk':12,'sl':14,'sma':7,'smi':7,'smj':7,'smn':7,'sms':7,'sn':3,'so':3,'sq':3,'sr':11,'ss':3,'ssy':3,'st':3,'sv':3,'sw':3,'syr':3,'ta':3,'te':3,'teo':3,'th':0,'ti':4,'tig':3,'tk':3,'tl':4,'tn':3,'to':0,'tr':0,'ts':3,'tzm':22,'uk':11,'ur':3,'ve':3,'vi':0,'vun':3,'wa':4,'wae':3,'wo':0,'xh':3,'xog':3,'yo':0,'zh':0,'zu':3};function isIn(n,list){return list.indexOf(n)!==-1;}
|
||||
function isBetween(n,start,end){return typeof n===typeof start&&start<=n&&n<=end;}
|
||||
var pluralRules={'0':function(){return'other';},'1':function(n){if((isBetween((n%100),3,10))){return'few';}
|
||||
if(n===0){return'zero';}
|
||||
if((isBetween((n%100),11,99))){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'2':function(n){if(n!==0&&(n%10)===0){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'3':function(n){if(n===1){return'one';}
|
||||
return'other';},'4':function(n){if((isBetween(n,0,1))){return'one';}
|
||||
return'other';},'5':function(n){if((isBetween(n,0,2))&&n!==2){return'one';}
|
||||
return'other';},'6':function(n){if(n===0){return'zero';}
|
||||
if((n%10)===1&&(n%100)!==11){return'one';}
|
||||
return'other';},'7':function(n){if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'8':function(n){if((isBetween(n,3,6))){return'few';}
|
||||
if((isBetween(n,7,10))){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'9':function(n){if(n===0||n!==1&&(isBetween((n%100),1,19))){return'few';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'10':function(n){if((isBetween((n%10),2,9))&&!(isBetween((n%100),11,19))){return'few';}
|
||||
if((n%10)===1&&!(isBetween((n%100),11,19))){return'one';}
|
||||
return'other';},'11':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
|
||||
if((n%10)===0||(isBetween((n%10),5,9))||(isBetween((n%100),11,14))){return'many';}
|
||||
if((n%10)===1&&(n%100)!==11){return'one';}
|
||||
return'other';},'12':function(n){if((isBetween(n,2,4))){return'few';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'13':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
|
||||
if(n!==1&&(isBetween((n%10),0,1))||(isBetween((n%10),5,9))||(isBetween((n%100),12,14))){return'many';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'14':function(n){if((isBetween((n%100),3,4))){return'few';}
|
||||
if((n%100)===2){return'two';}
|
||||
if((n%100)===1){return'one';}
|
||||
return'other';},'15':function(n){if(n===0||(isBetween((n%100),2,10))){return'few';}
|
||||
if((isBetween((n%100),11,19))){return'many';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'16':function(n){if((n%10)===1&&n!==11){return'one';}
|
||||
return'other';},'17':function(n){if(n===3){return'few';}
|
||||
if(n===0){return'zero';}
|
||||
if(n===6){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'18':function(n){if(n===0){return'zero';}
|
||||
if((isBetween(n,0,2))&&n!==0&&n!==2){return'one';}
|
||||
return'other';},'19':function(n){if((isBetween(n,2,10))){return'few';}
|
||||
if((isBetween(n,0,1))){return'one';}
|
||||
return'other';},'20':function(n){if((isBetween((n%10),3,4)||((n%10)===9))&&!(isBetween((n%100),10,19)||isBetween((n%100),70,79)||isBetween((n%100),90,99))){return'few';}
|
||||
if((n%1000000)===0&&n!==0){return'many';}
|
||||
if((n%10)===2&&!isIn((n%100),[12,72,92])){return'two';}
|
||||
if((n%10)===1&&!isIn((n%100),[11,71,91])){return'one';}
|
||||
return'other';},'21':function(n){if(n===0){return'zero';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'22':function(n){if((isBetween(n,0,1))||(isBetween(n,11,99))){return'one';}
|
||||
return'other';},'23':function(n){if((isBetween((n%10),1,2))||(n%20)===0){return'one';}
|
||||
return'other';},'24':function(n){if((isBetween(n,3,10)||isBetween(n,13,19))){return'few';}
|
||||
if(isIn(n,[2,12])){return'two';}
|
||||
if(isIn(n,[1,11])){return'one';}
|
||||
return'other';}};var index=locales2rules[lang.replace(/-.*$/,'')];if(!(index in pluralRules)){return function(){return'other';};}
|
||||
return pluralRules[index];}
|
||||
var MAX_PLACEABLES=100;var PropertiesParser={patterns:null,entryIds:null,init:function(){this.patterns={comment:/^\s*#|^\s*$/,entity:/^([^=\s]+)\s*=\s*(.*)$/,multiline:/[^\\]\\$/,index:/\{\[\s*(\w+)(?:\(([^\)]*)\))?\s*\]\}/i,unicode:/\\u([0-9a-fA-F]{1,4})/g,entries:/[^\r\n]+/g,controlChars:/\\([\\\n\r\t\b\f\{\}\"\'])/g,placeables:/\{\{\s*([^\s]*?)\s*\}\}/,};},parse:function(ctx,source){if(!this.patterns){this.init();}
|
||||
var ast=[];this.entryIds=Object.create(null);var entries=source.match(this.patterns.entries);if(!entries){return ast;}
|
||||
for(var i=0;i<entries.length;i++){var line=entries[i];if(this.patterns.comment.test(line)){continue;}
|
||||
while(this.patterns.multiline.test(line)&&i<entries.length){line=line.slice(0,-1)+entries[++i].trim();}
|
||||
var entityMatch=line.match(this.patterns.entity);if(entityMatch){try{this.parseEntity(entityMatch[1],entityMatch[2],ast);}catch(e){if(ctx){ctx._emitter.emit('parseerror',e);}else{throw e;}}}}
|
||||
return ast;},parseEntity:function(id,value,ast){var name,key;var pos=id.indexOf('[');if(pos!==-1){name=id.substr(0,pos);key=id.substring(pos+1,id.length-1);}else{name=id;key=null;}
|
||||
var nameElements=name.split('.');if(nameElements.length>2){throw new L10nError('Error in ID: "'+name+'".'+' Nested attributes are not supported.');}
|
||||
var attr;if(nameElements.length>1){name=nameElements[0];attr=nameElements[1];if(attr[0]==='$'){throw new L10nError('Attribute can\'t start with "$"',id);}}else{attr=null;}
|
||||
this.setEntityValue(name,attr,key,this.unescapeString(value),ast);},setEntityValue:function(id,attr,key,rawValue,ast){var pos,v;var value=rawValue.indexOf('{{')>-1?this.parseString(rawValue):rawValue;if(attr){pos=this.entryIds[id];if(pos===undefined){v={$i:id};if(key){v[attr]={};v[attr][key]=value;}else{v[attr]=value;}
|
||||
ast.push(v);this.entryIds[id]=ast.length-1;return;}
|
||||
if(key){if(typeof(ast[pos][attr])==='string'){ast[pos][attr]={$x:this.parseIndex(ast[pos][attr]),$v:{}};}
|
||||
ast[pos][attr].$v[key]=value;return;}
|
||||
ast[pos][attr]=value;return;}
|
||||
if(key){pos=this.entryIds[id];if(pos===undefined){v={};v[key]=value;ast.push({$i:id,$v:v});this.entryIds[id]=ast.length-1;return;}
|
||||
if(typeof(ast[pos].$v)==='string'){ast[pos].$x=this.parseIndex(ast[pos].$v);ast[pos].$v={};}
|
||||
ast[pos].$v[key]=value;return;}
|
||||
ast.push({$i:id,$v:value});this.entryIds[id]=ast.length-1;},parseString:function(str){var chunks=str.split(this.patterns.placeables);var complexStr=[];var len=chunks.length;var placeablesCount=(len-1)/2;if(placeablesCount>=MAX_PLACEABLES){throw new L10nError('Too many placeables ('+placeablesCount+', max allowed is '+MAX_PLACEABLES+')');}
|
||||
for(var i=0;i<chunks.length;i++){if(chunks[i].length===0){continue;}
|
||||
if(i%2===1){complexStr.push({t:'idOrVar',v:chunks[i]});}else{complexStr.push(chunks[i]);}}
|
||||
return complexStr;},unescapeString:function(str){if(str.lastIndexOf('\\')!==-1){str=str.replace(this.patterns.controlChars,'$1');}
|
||||
return str.replace(this.patterns.unicode,function(match,token){return unescape('%u'+'0000'.slice(token.length)+token);});},parseIndex:function(str){var match=str.match(this.patterns.index);if(!match){throw new L10nError('Malformed index');}
|
||||
if(match[2]){return[{t:'idOrVar',v:match[1]},match[2]];}else{return[{t:'idOrVar',v:match[1]}];}}};var KNOWN_MACROS=['plural'];var MAX_PLACEABLE_LENGTH=2500;var rePlaceables=/\{\{\s*(.+?)\s*\}\}/g;var nonLatin1=/[^\x01-\xFF]/;var FSI='\u2068';var PDI='\u2069';function createEntry(node,env){var keys=Object.keys(node);if(typeof node.$v==='string'&&keys.length===2){return node.$v;}
|
||||
var attrs;for(var i=0,key;key=keys[i];i++){if(key[0]==='$'){continue;}
|
||||
if(!attrs){attrs=Object.create(null);}
|
||||
attrs[key]=createAttribute(node[key],env,node.$i+'.'+key);}
|
||||
return{id:node.$i,value:node.$v!==undefined?node.$v:null,index:node.$x||null,attrs:attrs||null,env:env,dirty:false};}
|
||||
function createAttribute(node,env,id){if(typeof node==='string'){return node;}
|
||||
return{id:id,value:node.$v||(node!==undefined?node:null),index:node.$x||null,env:env,dirty:false};}
|
||||
function format(args,entity){if(typeof entity==='string'){return[{},entity];}
|
||||
if(entity.dirty){throw new L10nError('Cyclic reference detected: '+entity.id);}
|
||||
entity.dirty=true;var rv;try{rv=resolveValue({},args,entity.env,entity.value,entity.index);}finally{entity.dirty=false;}
|
||||
return rv;}
|
||||
function resolveIdentifier(args,env,id){if(KNOWN_MACROS.indexOf(id)>-1){return[{},env['__'+id]];}
|
||||
if(args&&args.hasOwnProperty(id)){if(typeof args[id]==='string'||(typeof args[id]==='number'&&!isNaN(args[id]))){return[{},args[id]];}else{throw new L10nError('Arg must be a string or a number: '+id);}}
|
||||
if(id in env&&id!=='__proto__'){return format(args,env[id]);}
|
||||
throw new L10nError('Unknown reference: '+id);}
|
||||
function subPlaceable(locals,args,env,id){var res;try{res=resolveIdentifier(args,env,id);}catch(err){return[{error:err},'{{ '+id+' }}'];}
|
||||
var value=res[1];if(typeof value==='number'){return res;}
|
||||
if(typeof value==='string'){if(value.length>=MAX_PLACEABLE_LENGTH){throw new L10nError('Too many characters in placeable ('+
|
||||
value.length+', max allowed is '+
|
||||
MAX_PLACEABLE_LENGTH+')');}
|
||||
if(locals.contextIsNonLatin1||value.match(nonLatin1)){res[1]=FSI+value+PDI;}
|
||||
return res;}
|
||||
return[{},'{{ '+id+' }}'];}
|
||||
function interpolate(locals,args,env,arr){return arr.reduce(function(prev,cur){if(typeof cur==='string'){return[prev[0],prev[1]+cur];}else if(cur.t==='idOrVar'){var placeable=subPlaceable(locals,args,env,cur.v);return[prev[0],prev[1]+placeable[1]];}},[locals,'']);}
|
||||
function resolveSelector(args,env,expr,index){var selectorName=index[0].v;var selector=resolveIdentifier(args,env,selectorName)[1];if(typeof selector!=='function'){return selector;}
|
||||
var argValue=index[1]?resolveIdentifier(args,env,index[1])[1]:undefined;if(selector===env.__plural){if(argValue===0&&'zero'in expr){return'zero';}
|
||||
if(argValue===1&&'one'in expr){return'one';}
|
||||
if(argValue===2&&'two'in expr){return'two';}}
|
||||
return selector(argValue);}
|
||||
function resolveValue(locals,args,env,expr,index){if(!expr){return[locals,expr];}
|
||||
if(typeof expr==='string'||typeof expr==='boolean'||typeof expr==='number'){return[locals,expr];}
|
||||
if(Array.isArray(expr)){locals.contextIsNonLatin1=expr.some(function($_){return typeof($_)==='string'&&$_.match(nonLatin1);});return interpolate(locals,args,env,expr);}
|
||||
if(index){var selector=resolveSelector(args,env,expr,index);if(expr.hasOwnProperty(selector)){return resolveValue(locals,args,env,expr[selector]);}}
|
||||
if('other'in expr){return resolveValue(locals,args,env,expr.other);}
|
||||
throw new L10nError('Unresolvable value');}
|
||||
var Resolver={createEntry:createEntry,format:format,rePlaceables:rePlaceables};function walkContent(node,fn){if(typeof node==='string'){return fn(node);}
|
||||
if(node.t==='idOrVar'){return node;}
|
||||
var rv=Array.isArray(node)?[]:{};var keys=Object.keys(node);for(var i=0,key;(key=keys[i]);i++){if(key==='$i'||key==='$x'){rv[key]=node[key];}else{rv[key]=walkContent(node[key],fn);}}
|
||||
return rv;}
|
||||
var reAlphas=/[a-zA-Z]/g;var reVowels=/[aeiouAEIOU]/g;var ACCENTED_MAP='\u0226\u0181\u0187\u1E12\u1E16\u0191\u0193\u0126\u012A'+'\u0134\u0136\u013F\u1E3E\u0220\u01FE\u01A4\u024A\u0158'+'\u015E\u0166\u016C\u1E7C\u1E86\u1E8A\u1E8E\u1E90'+'[\\]^_`'+'\u0227\u0180\u0188\u1E13\u1E17\u0192\u0260\u0127\u012B'+'\u0135\u0137\u0140\u1E3F\u019E\u01FF\u01A5\u024B\u0159'+'\u015F\u0167\u016D\u1E7D\u1E87\u1E8B\u1E8F\u1E91';var FLIPPED_MAP='\u2200\u0510\u2183p\u018E\u025F\u05E4HI\u017F'+'\u04FC\u02E5WNO\u0500\xD2\u1D1AS\u22A5\u2229\u0245'+'\uFF2DX\u028EZ'+'[\\]\u1D65_,'+'\u0250q\u0254p\u01DD\u025F\u0183\u0265\u0131\u027E'+'\u029E\u0285\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez';function makeLonger(val){return val.replace(reVowels,function(match){return match+match.toLowerCase();});}
|
||||
function replaceChars(map,val){return val.replace(reAlphas,function(match){return map.charAt(match.charCodeAt(0)-65);});}
|
||||
var reWords=/[^\W0-9_]+/g;function makeRTL(val){return val.replace(reWords,function(match){return'\u202e'+match+'\u202c';});}
|
||||
var reExcluded=/(%[EO]?\w|\{\s*.+?\s*\}|&[#\w]+;|<\s*.+?\s*>)/;function mapContent(fn,val){if(!val){return val;}
|
||||
var parts=val.split(reExcluded);var modified=parts.map(function(part){if(reExcluded.test(part)){return part;}
|
||||
return fn(part);});return modified.join('');}
|
||||
function Pseudo(id,name,charMap,modFn){this.id=id;this.translate=mapContent.bind(null,function(val){return replaceChars(charMap,modFn(val));});this.name=this.translate(name);}
|
||||
var PSEUDO={'fr-x-psaccent':new Pseudo('fr-x-psaccent','Runtime Accented',ACCENTED_MAP,makeLonger),'ar-x-psbidi':new Pseudo('ar-x-psbidi','Runtime Bidi',FLIPPED_MAP,makeRTL)};function Locale(id,ctx){this.id=id;this.ctx=ctx;this.isReady=false;this.entries=Object.create(null);this.entries.__plural=getPluralRule(this.isPseudo()?this.ctx.defaultLocale:id);}
|
||||
Locale.prototype.isPseudo=function(){return this.ctx.qps.indexOf(this.id)!==-1;};var bindingsIO={extra:function(id,ver,path,type,callback,errback){if(type==='properties'){type='text';}
|
||||
navigator.mozApps.getLocalizationResource(id,ver,path,type).then(callback.bind(null,null),errback);},app:function(id,ver,path,type,callback,errback,sync){switch(type){case'properties':io.load(path,callback,sync);break;case'json':io.loadJSON(path,callback,sync);break;}},};Locale.prototype.build=function L_build(callback){var sync=!callback;var ctx=this.ctx;var self=this;var l10nLoads=ctx.resLinks.length;function onL10nLoaded(err){if(err){ctx._emitter.emit('fetcherror',err);}
|
||||
if(--l10nLoads<=0){self.isReady=true;if(callback){callback();}}}
|
||||
if(l10nLoads===0){onL10nLoaded();return;}
|
||||
function onJSONLoaded(err,json){if(!err&&json){self.addAST(json);}
|
||||
onL10nLoaded(err);}
|
||||
function onPropLoaded(err,source){if(!err&&source){var ast=PropertiesParser.parse(ctx,source);self.addAST(ast);}
|
||||
onL10nLoaded(err);}
|
||||
var idToFetch=this.isPseudo()?ctx.defaultLocale:this.id;var appVersion=null;var source='app';if(typeof(navigator)!=='undefined'){source=navigator.mozL10n._config.localeSources[this.id]||'app';appVersion=navigator.mozL10n._config.appVersion;}
|
||||
for(var i=0;i<ctx.resLinks.length;i++){var resLink=decodeURI(ctx.resLinks[i]);var path=resLink.replace('{locale}',idToFetch);var type=path.substr(path.lastIndexOf('.')+1);var cb;switch(type){case'json':cb=onJSONLoaded;break;case'properties':cb=onPropLoaded;break;}
|
||||
bindingsIO[source](this.id,appVersion,path,type,cb,onL10nLoaded,sync);}};function createPseudoEntry(node,entries){return Resolver.createEntry(walkContent(node,PSEUDO[this.id].translate),entries);}
|
||||
Locale.prototype.addAST=function(ast){var createEntry=this.isPseudo()?createPseudoEntry.bind(this):Resolver.createEntry;for(var i=0;i<ast.length;i++){this.entries[ast[i].$i]=createEntry(ast[i],this.entries);}};function Context(id){this.id=id;this.isReady=false;this.isLoading=false;this.defaultLocale='en-US';this.availableLocales=[];this.supportedLocales=[];this.qps=[];this.resLinks=[];this.locales={};this._emitter=new EventEmitter();this._ready=new Promise(this.once.bind(this));}
|
||||
function reportMissing(id,err){this._emitter.emit('notfounderror',err);return id;}
|
||||
function getWithFallback(id){var cur=0;var loc;var locale;while(loc=this.supportedLocales[cur]){locale=this.getLocale(loc);if(!locale.isReady){locale.build(null);}
|
||||
var entry=locale.entries[id];if(entry===undefined){cur++;reportMissing.call(this,id,new L10nError('"'+id+'"'+' not found in '+loc+' in '+this.id,id,loc));continue;}
|
||||
return entry;}
|
||||
throw new L10nError('"'+id+'"'+' missing from all supported locales in '+this.id,id);}
|
||||
function formatTuple(args,entity){try{return Resolver.format(args,entity);}catch(err){this._emitter.emit('resolveerror',err);var locals={error:err};return[locals,entity.id];}}
|
||||
function formatValue(args,entity){if(typeof entity==='string'){return entity;}
|
||||
return formatTuple.call(this,args,entity)[1];}
|
||||
function formatEntity(args,entity){var entityTuple=formatTuple.call(this,args,entity);var value=entityTuple[1];var formatted={value:value,attrs:null,};if(entity.attrs){formatted.attrs=Object.create(null);}
|
||||
for(var key in entity.attrs){var attrTuple=formatTuple.call(this,args,entity.attrs[key]);formatted.attrs[key]=attrTuple[1];}
|
||||
return formatted;}
|
||||
function formatAsync(fn,id,args){return this._ready.then(getWithFallback.bind(this,id)).then(fn.bind(this,args),reportMissing.bind(this,id));}
|
||||
Context.prototype.formatValue=function(id,args){return formatAsync.call(this,formatValue,id,args);};Context.prototype.formatEntity=function(id,args){return formatAsync.call(this,formatEntity,id,args);};function legacyGet(fn,id,args){if(!this.isReady){throw new L10nError('Context not ready');}
|
||||
var entry;try{entry=getWithFallback.call(this,id);}catch(err){if(err.loc){throw err;}
|
||||
reportMissing.call(this,id,err);return'';}
|
||||
return fn.call(this,args,entry);}
|
||||
Context.prototype.get=function(id,args){return legacyGet.call(this,formatValue,id,args);};Context.prototype.getEntity=function(id,args){return legacyGet.call(this,formatEntity,id,args);};Context.prototype.getLocale=function getLocale(code){var locales=this.locales;if(locales[code]){return locales[code];}
|
||||
return locales[code]=new Locale(code,this);};function negotiate(available,requested,defaultLocale){var supportedLocale;for(var i=0;i<requested.length;i++){var locale=requested[i];if(available.indexOf(locale)!==-1){supportedLocale=locale;break;}}
|
||||
if(!supportedLocale||supportedLocale===defaultLocale){return[defaultLocale];}
|
||||
return[supportedLocale,defaultLocale];}
|
||||
function freeze(supported){var locale=this.getLocale(supported[0]);if(locale.isReady){setReady.call(this,supported);}else{locale.build(setReady.bind(this,supported));}}
|
||||
function setReady(supported){this.supportedLocales=supported;this.isReady=true;this._emitter.emit('ready');}
|
||||
Context.prototype.registerLocales=function(defLocale,available){if(defLocale){this.defaultLocale=defLocale;}
|
||||
this.availableLocales=[this.defaultLocale];this.qps=Object.keys(PSEUDO);if(available){for(var i=0,loc;loc=available[i];i++){if(this.availableLocales.indexOf(loc)===-1){this.availableLocales.push(loc);var pos=this.qps.indexOf(loc);if(pos!==-1){this.qps.splice(pos,1);}}}}};Context.prototype.requestLocales=function requestLocales(){if(this.isLoading&&!this.isReady){throw new L10nError('Context not ready');}
|
||||
this.isLoading=true;var requested=Array.prototype.slice.call(arguments);if(requested.length===0){throw new L10nError('No locales requested');}
|
||||
var supported=negotiate(this.availableLocales.concat(this.qps),requested,this.defaultLocale);if(this.supportedLocales[0]!==supported[0]){freeze.call(this,supported);}};Context.prototype.addEventListener=function(type,listener){this._emitter.addEventListener(type,listener);};Context.prototype.removeEventListener=function(type,listener){this._emitter.removeEventListener(type,listener);};Context.prototype.ready=function(callback){if(this.isReady){setTimeout(callback);}
|
||||
this.addEventListener('ready',callback);};Context.prototype.once=function(callback){if(this.isReady){setTimeout(callback);return;}
|
||||
var callAndRemove=(function(){this.removeEventListener('ready',callAndRemove);callback();}).bind(this);this.addEventListener('ready',callAndRemove);};var allowed={elements:['a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','sup','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr'],attributes:{global:['title','aria-label','aria-valuetext','aria-moz-hint'],a:['download'],area:['download','alt'],input:['alt','placeholder'],menuitem:['label'],menu:['label'],optgroup:['label'],option:['label'],track:['label'],img:['alt'],textarea:['placeholder'],th:['abbr']}};var rtlList=['ar','he','fa','ps','ar-x-psbidi','ur'];var nodeObserver=null;var pendingElements=null;var moConfig={attributes:true,characterData:false,childList:true,subtree:true,attributeFilter:['data-l10n-id','data-l10n-args']};navigator.mozL10n={ctx:null,get:function get(id,ctxdata){return navigator.mozL10n.ctx.get(id,ctxdata);},formatValue:function(id,ctxdata){return navigator.mozL10n.ctx.formatValue(id,ctxdata);},formatEntity:function(id,ctxdata){return navigator.mozL10n.ctx.formatEntity(id,ctxdata);},translateFragment:function(fragment){return translateFragment.call(navigator.mozL10n,fragment);},setAttributes:setL10nAttributes,getAttributes:getL10nAttributes,ready:function ready(callback){return navigator.mozL10n.ctx.ready(callback);},once:function once(callback){return navigator.mozL10n.ctx.once(callback);},get readyState(){return navigator.mozL10n.ctx.isReady?'complete':'loading';},language:{set code(lang){navigator.mozL10n.ctx.requestLocales(lang);},get code(){return navigator.mozL10n.ctx.supportedLocales[0];},get direction(){return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);}},qps:PSEUDO,_config:{appVersion:null,localeSources:Object.create(null),isPretranslated:false,},_getInternalAPI:function(){return{Error:L10nError,Context:Context,Locale:Locale,Resolver:Resolver,getPluralRule:getPluralRule,rePlaceables:rePlaceables,translateDocument:translateDocument,onMetaInjected:onMetaInjected,PropertiesParser:PropertiesParser,walkContent:walkContent,buildLocaleList:buildLocaleList};}};function getDirection(lang){return(rtlList.indexOf(lang)>=0)?'rtl':'ltr';}
|
||||
var readyStates={loading:0,interactive:1,complete:2};function whenInteractive(callback){if(readyStates[document.readyState]>=readyStates.interactive){callback();return;}
|
||||
document.addEventListener('readystatechange',function l10n_onrsc(){if(readyStates[document.readyState]>=readyStates.interactive){document.removeEventListener('readystatechange',l10n_onrsc);callback();}});}
|
||||
function initObserver(){nodeObserver=new MutationObserver(onMutations.bind(navigator.mozL10n));nodeObserver.observe(document,moConfig);}
|
||||
function init(pretranslate){if(!pretranslate){initObserver();}
|
||||
initResources.call(navigator.mozL10n);}
|
||||
function initResources(){var meta={};var nodes=document.head.querySelectorAll('link[rel="localization"],'+'meta[name="availableLanguages"],'+'meta[name="defaultLanguage"],'+'meta[name="appVersion"],'+'script[type="application/l10n"]');for(var i=0,node;node=nodes[i];i++){var type=node.getAttribute('rel')||node.nodeName.toLowerCase();switch(type){case'localization':this.ctx.resLinks.push(node.getAttribute('href'));break;case'meta':onMetaInjected.call(this,node,meta);break;case'script':onScriptInjected.call(this,node);break;}}
|
||||
var additionalLanguagesPromise;if(navigator.mozApps&&navigator.mozApps.getAdditionalLanguages){additionalLanguagesPromise=navigator.mozApps.getAdditionalLanguages().catch(function(e){console.error('Error while loading getAdditionalLanguages',e);});document.addEventListener('additionallanguageschange',function(evt){registerLocales.call(this,meta,evt.detail);this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}else{additionalLanguagesPromise=Promise.resolve();}
|
||||
additionalLanguagesPromise.then(function(extraLangs){registerLocales.call(this,meta,extraLangs);initLocale.call(this);}.bind(this));}
|
||||
function registerLocales(meta,extraLangs){var locales=buildLocaleList.call(this,meta,extraLangs);navigator.mozL10n._config.localeSources=locales[1];this.ctx.registerLocales(locales[0],Object.keys(locales[1]));}
|
||||
function getMatchingLangpack(appVersion,langpacks){for(var i=0,langpack;(langpack=langpacks[i]);i++){if(langpack.target===appVersion){return langpack;}}
|
||||
return null;}
|
||||
function buildLocaleList(meta,extraLangs){var loc,lp;var localeSources=Object.create(null);var defaultLocale=meta.defaultLanguage||this.ctx.defaultLocale;if(meta.availableLanguages){for(loc in meta.availableLanguages){localeSources[loc]='app';}}
|
||||
if(extraLangs){for(loc in extraLangs){lp=getMatchingLangpack(this._config.appVersion,extraLangs[loc]);if(!lp){continue;}
|
||||
if(!(loc in localeSources)||!meta.availableLanguages[loc]||parseInt(lp.revision)>meta.availableLanguages[loc]){localeSources[loc]='extra';}}}
|
||||
if(!(defaultLocale in localeSources)){localeSources[defaultLocale]='app';}
|
||||
return[defaultLocale,localeSources];}
|
||||
function splitAvailableLanguagesString(str){var langs={};str.split(',').forEach(function(lang){lang=lang.trim().split(':');langs[lang[0]]=parseInt(lang[1]);});return langs;}
|
||||
function onMetaInjected(node,meta){switch(node.getAttribute('name')){case'availableLanguages':meta.availableLanguages=splitAvailableLanguagesString(node.getAttribute('content'));break;case'defaultLanguage':meta.defaultLanguage=node.getAttribute('content');break;case'appVersion':navigator.mozL10n._config.appVersion=node.getAttribute('content');break;}}
|
||||
function onScriptInjected(node){var lang=node.getAttribute('lang');var locale=this.ctx.getLocale(lang);locale.addAST(JSON.parse(node.textContent));}
|
||||
function initLocale(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);window.addEventListener('languagechange',function l10n_langchange(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}
|
||||
function localizeMutations(mutations){var mutation;var targets=new Set();for(var i=0;i<mutations.length;i++){mutation=mutations[i];if(mutation.type==='childList'){var addedNode;for(var j=0;j<mutation.addedNodes.length;j++){addedNode=mutation.addedNodes[j];if(addedNode.nodeType!==Node.ELEMENT_NODE){continue;}
|
||||
targets.add(addedNode);}}
|
||||
if(mutation.type==='attributes'){targets.add(mutation.target);}}
|
||||
targets.forEach(function(target){if(target.childElementCount){translateFragment.call(this,target);}else if(target.hasAttribute('data-l10n-id')){translateElement.call(this,target);}},this);}
|
||||
function onMutations(mutations,self){self.disconnect();localizeMutations.call(this,mutations);self.observe(document,moConfig);}
|
||||
function onReady(){if(!navigator.mozL10n._config.isPretranslated){translateDocument.call(this);}
|
||||
navigator.mozL10n._config.isPretranslated=false;if(pendingElements){for(var i=0,element;element=pendingElements[i];i++){translateElement.call(this,element);}
|
||||
pendingElements=null;}
|
||||
if(!nodeObserver){initObserver();}
|
||||
fireLocalizedEvent.call(this);}
|
||||
function fireLocalizedEvent(){var event=new CustomEvent('localized',{'bubbles':false,'cancelable':false,'detail':{'language':this.ctx.supportedLocales[0]}});window.dispatchEvent(event);}
|
||||
var reOverlay=/<|&#?\w+;/;var reHtml=/[&<>]/g;var htmlEntities={'&':'&','<':'<','>':'>',};function translateDocument(){document.documentElement.lang=this.language.code;document.documentElement.dir=this.language.direction;translateFragment.call(this,document.documentElement);}
|
||||
function translateFragment(element){if(typeof element.hasAttribute==='function'&&element.hasAttribute('data-l10n-id')){translateElement.call(this,element);}
|
||||
var nodes=getTranslatableChildren(element);for(var i=0;i<nodes.length;i++){translateElement.call(this,nodes[i]);}}
|
||||
function setL10nAttributes(element,id,args){element.setAttribute('data-l10n-id',id);if(args){element.setAttribute('data-l10n-args',JSON.stringify(args));}}
|
||||
function getL10nAttributes(element){return{id:element.getAttribute('data-l10n-id'),args:JSON.parse(element.getAttribute('data-l10n-args'))};}
|
||||
function getTranslatableChildren(element){return element?element.querySelectorAll('*[data-l10n-id]'):[];}
|
||||
function camelCaseToDashed(string){if(string==='ariaValueText'){return'aria-valuetext';}
|
||||
return string.replace(/[A-Z]/g,function(match){return'-'+match.toLowerCase();}).replace(/^-/,'');}
|
||||
function escapeL10nArgs(match){return htmlEntities[match];}
|
||||
function translateElement(element){if(!this.ctx.isReady){if(!pendingElements){pendingElements=[];}
|
||||
pendingElements.push(element);return;}
|
||||
var l10nId=element.getAttribute('data-l10n-id');if(!l10nId){return false;}
|
||||
var l10nArgs=element.getAttribute('data-l10n-args');var entity=this.ctx.getEntity(l10nId,l10nArgs?JSON.parse(l10nArgs.replace(reHtml,escapeL10nArgs)):undefined);var value=entity.value;if(typeof value==='string'){if(!reOverlay.test(value)){element.textContent=value;}else{var translation=element.ownerDocument.createElement('template');translation.innerHTML=value;overlayElement(element,translation.content);}}
|
||||
for(var key in entity.attrs){var attrName=camelCaseToDashed(key);if(isAttrAllowed({name:attrName},element)){element.setAttribute(attrName,entity.attrs[key]);}}}
|
||||
function overlayElement(sourceElement,translationElement){var result=translationElement.ownerDocument.createDocumentFragment();var k,attr;var childElement;while((childElement=translationElement.childNodes[0])){translationElement.removeChild(childElement);if(childElement.nodeType===Node.TEXT_NODE){result.appendChild(childElement);continue;}
|
||||
var index=getIndexOfType(childElement);var sourceChild=getNthElementOfType(sourceElement,childElement,index);if(sourceChild){overlayElement(sourceChild,childElement);result.appendChild(sourceChild);continue;}
|
||||
if(isElementAllowed(childElement)){var sanitizedChild=childElement.ownerDocument.createElement(childElement.nodeName);overlayElement(sanitizedChild,childElement);result.appendChild(sanitizedChild);continue;}
|
||||
result.appendChild(document.createTextNode(childElement.textContent));}
|
||||
sourceElement.textContent='';sourceElement.appendChild(result);if(translationElement.attributes){for(k=0,attr;(attr=translationElement.attributes[k]);k++){if(isAttrAllowed(attr,sourceElement)){sourceElement.setAttribute(attr.name,attr.value);}}}}
|
||||
function isElementAllowed(element){return allowed.elements.indexOf(element.tagName.toLowerCase())!==-1;}
|
||||
function isAttrAllowed(attr,element){var attrName=attr.name.toLowerCase();var tagName=element.tagName.toLowerCase();if(allowed.attributes.global.indexOf(attrName)!==-1){return true;}
|
||||
if(!allowed.attributes[tagName]){return false;}
|
||||
if(allowed.attributes[tagName].indexOf(attrName)!==-1){return true;}
|
||||
if(tagName==='input'&&attrName==='value'){var type=element.type.toLowerCase();if(type==='submit'||type==='button'||type==='reset'){return true;}}
|
||||
return false;}
|
||||
function getNthElementOfType(context,element,index){var nthOfType=0;for(var i=0,child;child=context.children[i];i++){if(child.nodeType===Node.ELEMENT_NODE&&child.tagName===element.tagName){if(nthOfType===index){return child;}
|
||||
nthOfType++;}}
|
||||
return null;}
|
||||
function getIndexOfType(element){var index=0;var child;while((child=element.previousElementSibling)){if(child.tagName===element.tagName){index++;}}
|
||||
return index;}
|
||||
var DEBUG=false;navigator.mozL10n.ctx=new Context(window.document?document.URL:null);navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));navigator.mozL10n.ctx.addEventListener('notfounderror',function reportMissingEntity(e){if(DEBUG||e.loc==='en-US'){console.warn(e.toString());}});if(DEBUG){navigator.mozL10n.ctx.addEventListener('fetcherror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('parseerror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('resolveerror',console.error.bind(console));}
|
||||
if(window.document){navigator.mozL10n._config.isPretranslated=document.documentElement.lang===navigator.language;var forcePretranslate=!navigator.mozL10n._config.isPretranslated;whenInteractive(init.bind(navigator.mozL10n,forcePretranslate));}
|
||||
document.l10n={setAttributes:navigator.mozL10n.setAttributes,getAttributes:navigator.mozL10n.getAttributes,formatValue:function(id,args){return navigator.mozL10n.formatValue(id,args);},translateFragment:function(frag){return Promise.resolve(navigator.mozL10n.translateFragment(frag));},ready:new Promise(function(resolve){navigator.mozL10n.once(resolve);}),formatValues:function(){var keys=arguments;var resp=keys.map(function(key){if(Array.isArray(key)){return navigator.mozL10n.formatValue(key[0],key[1]);}
|
||||
return navigator.mozL10n.formatValue(key);});return Promise.all(resp);},requestLanguages:function(langs){navigator.mozL10n.ctx.requestLocales.apply(navigator.mozL10n.ctx,langs);},pseudo:{'fr-x-psaccent':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].translate(s));}},'ar-x-psbidi':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].translate(s));}}},};navigator.mozL10n.ready(function(){document.documentElement.setAttribute('langs',navigator.mozL10n.ctx.supportedLocales.join(' '));});navigator.mozL10n.once(function(){window.addEventListener('localized',function(){document.dispatchEvent(new CustomEvent('DOMRetranslated',{bubbles:false,cancelable:false}));});});})(this);
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
;'use strict';var LazyLoader=(function(){function LazyLoader(){this._loaded={};this._isLoading={};}
|
||||
LazyLoader.prototype={_js:function(file,callback){var script=document.createElement('script');script.src=file;script.async=false;script.addEventListener('load',callback);document.head.appendChild(script);this._isLoading[file]=script;},_css:function(file,callback){var style=document.createElement('link');style.type='text/css';style.rel='stylesheet';style.href=file;document.head.appendChild(style);callback();},_html:function(domNode,callback){if(domNode.getAttribute('is')){this.load(['/shared/js/html_imports.js'],function(){HtmlImports.populate(callback);}.bind(this));return;}
|
||||
for(var i=0;i<domNode.childNodes.length;i++){if(domNode.childNodes[i].nodeType==document.COMMENT_NODE){domNode.innerHTML=domNode.childNodes[i].nodeValue;break;}}
|
||||
window.dispatchEvent(new CustomEvent('lazyload',{detail:domNode}));callback();},getJSON:function(file,mozSystem){return new Promise(function(resolve,reject){var xhr;if(mozSystem){xhr=new XMLHttpRequest({mozSystem:true});}else{xhr=new XMLHttpRequest();}
|
||||
xhr.open('GET',file,true);xhr.responseType='json';xhr.onerror=function(error){reject(error);};xhr.onload=function(){if(xhr.response!==null){resolve(xhr.response);}else{reject(new Error('No valid JSON object was found ('+
|
||||
xhr.status+' '+xhr.statusText+')'));}};xhr.send();});},load:function(files,callback){var deferred={};deferred.promise=new Promise(resolve=>{deferred.resolve=resolve;});if(!Array.isArray(files)){files=[files];}
|
||||
var loadsRemaining=files.length,self=this;function perFileCallback(file){if(self._isLoading[file]){delete self._isLoading[file];}
|
||||
self._loaded[file]=true;if(--loadsRemaining===0){deferred.resolve();if(callback){callback();}}}
|
||||
for(var i=0;i<files.length;i++){var file=files[i];if(this._loaded[file.id||file]){perFileCallback(file);}else if(this._isLoading[file]){this._isLoading[file].addEventListener('load',perFileCallback.bind(null,file));}else{var method,idx;if(typeof file==='string'){method=file.match(/\.([^.]+)$/)[1];idx=file;}else{method='html';idx=file.id;}
|
||||
this['_'+method](file,perFileCallback.bind(null,idx));}}
|
||||
return deferred.promise;}};return new LazyLoader();}());
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
;'use strict';var SettingsListener={_lock:null,_observers:[],getSettingsLock:function sl_getSettingsLock(){if(this._lock&&!this._lock.closed){return this._lock;}
|
||||
var settings=window.navigator.mozSettings;return(this._lock=settings.createLock());},observe:function sl_observe(name,defaultValue,callback){var settings=window.navigator.mozSettings;if(!settings){window.setTimeout(function(){callback(defaultValue);});return;}
|
||||
var req;try{req=this.getSettingsLock().get(name);}catch(e){console.warn('Stale lock in settings_listener.js.','See https://bugzilla.mozilla.org/show_bug.cgi?id=793239');this._lock=null;req=this.getSettingsLock().get(name);}
|
||||
req.addEventListener('success',(function onsuccess(){callback(typeof(req.result[name])!='undefined'?req.result[name]:defaultValue);}));var settingChanged=function settingChanged(evt){callback(evt.settingValue);};settings.addObserver(name,settingChanged);this._observers.push({name:name,callback:callback,observer:settingChanged});},unobserve:function sl_unobserve(name,callback){var settings=window.navigator.mozSettings;var that=this;this._observers.forEach(function(value,index){if(value.name===name&&value.callback===callback){settings.removeObserver(name,value.observer);that._observers.splice(index,1);}});}};
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/* exported SimSettingsHelper */
|
||||
|
||||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
|
||||
/*
|
||||
* SimSettingsHelper is a helper to provide semantic ways set / get
|
||||
* mozSettings. It is used by SimCardManager.
|
||||
*/
|
||||
var SimSettingsHelper = {
|
||||
EMPTY_OPTION_TEXT: '--',
|
||||
EMPTY_OPTION_VALUE: -2,
|
||||
ALWAYS_ASK_OPTION_VALUE: -1,
|
||||
_callbacks: {
|
||||
outgoingCall: [],
|
||||
outgoingMessages: [],
|
||||
outgoingData: []
|
||||
},
|
||||
observe: function(serviceName, callback) {
|
||||
var serviceCallbacks = this._callbacks[serviceName];
|
||||
if (serviceCallbacks) {
|
||||
serviceCallbacks.push(callback);
|
||||
}
|
||||
},
|
||||
unobserve: function(serviceName, callback) {
|
||||
var serviceCallbacks = this._callbacks[serviceName];
|
||||
if (serviceCallbacks) {
|
||||
var index = serviceCallbacks.indexOf(callback);
|
||||
if (index > -1) {
|
||||
serviceCallbacks.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
getCardIndexFrom: function(serviceName, callback) {
|
||||
// _get(), _onWhichCard() and _getFromSettingsDB() are internal methods
|
||||
// and should be used together, so I wrap them inside this method
|
||||
// and expose them outside the world to make sure developers
|
||||
// will not call them separately.
|
||||
this._get(serviceName)._onWhichCard(callback);
|
||||
},
|
||||
_get: function(serviceName) {
|
||||
this.settingKeys = [];
|
||||
switch (serviceName) {
|
||||
case 'outgoingCall':
|
||||
this.settingKeys.push('ril.telephony.defaultServiceId');
|
||||
break;
|
||||
case 'outgoingMessages':
|
||||
this.settingKeys.push('ril.sms.defaultServiceId');
|
||||
break;
|
||||
case 'outgoingData':
|
||||
this.settingKeys.push('ril.data.defaultServiceId');
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
_onWhichCard: function(callback) {
|
||||
this.settingKeys.forEach(function(key) {
|
||||
this._getFromSettingsDB(key, callback);
|
||||
}.bind(this));
|
||||
},
|
||||
_getFromSettingsDB: function(key, callback) {
|
||||
var settings = window.navigator.mozSettings;
|
||||
var getReq = settings.createLock().get(key);
|
||||
var done = function done() {
|
||||
if (callback) {
|
||||
// if there is no card set on the service,
|
||||
// we will just use the first card
|
||||
var previousCardIndex = getReq.result[key] || 0;
|
||||
callback(previousCardIndex);
|
||||
}
|
||||
};
|
||||
getReq.onsuccess = done;
|
||||
getReq.onerror = done;
|
||||
},
|
||||
setServiceOnCard: function(serviceName, cardIndex) {
|
||||
// _set(), _on() and _setToSettingsDB() are internal methods
|
||||
// and should be used together, so I wrap them inside this
|
||||
// method and expose them outside the world to make sure
|
||||
// developers will not call them separately.
|
||||
this._set(serviceName)._on(+cardIndex);
|
||||
},
|
||||
_set: function(serviceName) {
|
||||
// cleanup old keys first
|
||||
this.settingKeys = [];
|
||||
|
||||
switch (serviceName) {
|
||||
case 'outgoingCall':
|
||||
this.settingKeys.push('ril.telephony.defaultServiceId');
|
||||
this.settingKeys.push('ril.voicemail.defaultServiceId');
|
||||
break;
|
||||
|
||||
case 'outgoingMessages':
|
||||
this.settingKeys.push('ril.sms.defaultServiceId');
|
||||
break;
|
||||
|
||||
case 'outgoingData':
|
||||
this.settingKeys.push('ril.mms.defaultServiceId');
|
||||
this.settingKeys.push('ril.data.defaultServiceId');
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
_on: function(cardIndex) {
|
||||
this.settingKeys.forEach(function(key) {
|
||||
this._setToSettingsDB(key, cardIndex);
|
||||
}.bind(this));
|
||||
},
|
||||
_setToSettingsDB: function(key, newValue, callback) {
|
||||
var done = function done() {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
var settings = window.navigator.mozSettings;
|
||||
var getReq = settings.createLock().get(key);
|
||||
|
||||
getReq.onsuccess = function() {
|
||||
var oldValue = getReq.result[key];
|
||||
|
||||
if (oldValue !== newValue) {
|
||||
var setObject = {};
|
||||
setObject[key] = newValue;
|
||||
var setReq = settings.createLock().set(setObject);
|
||||
|
||||
setReq.onsuccess = done;
|
||||
setReq.onerror = done;
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
};
|
||||
getReq.onerror = done;
|
||||
},
|
||||
_addSettingsObservers: function() {
|
||||
var self = this;
|
||||
|
||||
navigator.mozSettings.addObserver('ril.telephony.defaultServiceId',
|
||||
function(event) {
|
||||
self._callbacks.outgoingCall.forEach(function(cb) {
|
||||
cb(event.settingValue);
|
||||
});
|
||||
});
|
||||
navigator.mozSettings.addObserver('ril.sms.defaultServiceId',
|
||||
function(event) {
|
||||
self._callbacks.outgoingMessages.forEach(function(cb) {
|
||||
cb(event.settingValue);
|
||||
});
|
||||
});
|
||||
navigator.mozSettings.addObserver('ril.data.defaultServiceId',
|
||||
function(event) {
|
||||
self._callbacks.outgoingData.forEach(function(cb) {
|
||||
cb(event.settingValue);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// add obsersvers
|
||||
SimSettingsHelper._addSettingsObservers();
|
||||
|
||||
exports.SimSettingsHelper = SimSettingsHelper;
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
/* ----------------------------------
|
||||
* Action menu
|
||||
* ---------------------------------- */
|
||||
|
||||
html[dir="ltr"] [role="dialog"][data-type="action"] [dir],
|
||||
html[dir="ltr"] [role="dialog"][data-type="action"] button {
|
||||
text-align: left;
|
||||
}
|
||||
html[dir="rtl"] [role="dialog"][data-type="action"] [dir],
|
||||
html[dir="rtl"] [role="dialog"][data-type="action"] button {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Main dialog setup */
|
||||
[role="dialog"][data-type="action"] {
|
||||
background: #2d2d2d;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 0 0 7rem;
|
||||
/**
|
||||
* Using "font-size: 0" to avoid the unwanted visual space (about 3px) created
|
||||
* by white spaces and line breaks in the code between inline-block elements.
|
||||
*/
|
||||
font-size: 0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"]:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 0.1rem;
|
||||
height: 100%;
|
||||
margin-inline-start: -0.1rem;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > header {
|
||||
box-sizing: border-box;
|
||||
font-size: 1.6rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
height: 5rem;
|
||||
line-height: 4.9rem;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
font-weight: normal;
|
||||
padding: 0 3rem;
|
||||
border-bottom: 0.1rem solid #616262;
|
||||
}
|
||||
[role="dialog"][data-type="action"] > header * {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > header h1 {
|
||||
font-size: 1.6rem;
|
||||
line-height: 4.9rem;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Generic set of actions in toolbar */
|
||||
[role="dialog"][data-type="action"] > header menu[type="toolbar"] {
|
||||
height: 100%;
|
||||
margin: 0 -3rem;
|
||||
margin-inline-start: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
html[dir="ltr"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] { float: right; }
|
||||
html[dir="rtl"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] { float: left; }
|
||||
|
||||
[role="dialog"][data-type="action"] > header menu[type="toolbar"] a,
|
||||
[role="dialog"][data-type="action"] > header menu[type="toolbar"] button {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
width: auto;
|
||||
min-width: 5rem;
|
||||
height: 4.9rem;
|
||||
margin-bottom: 0;
|
||||
padding: 0 1rem;
|
||||
border-radius: 0;
|
||||
line-height: 4.9rem;
|
||||
background: none;
|
||||
text-align: center;
|
||||
text-shadow: none;
|
||||
z-index: 5;
|
||||
}
|
||||
html[dir="ltr"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] a,
|
||||
html[dir="ltr"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] button {
|
||||
float: left;
|
||||
}
|
||||
html[dir="rtl"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] a,
|
||||
html[dir="rtl"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > header a,
|
||||
[role="dialog"][data-type="action"] > header button {
|
||||
border: none;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
font-weight: 400;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.1em;
|
||||
color: #fff;
|
||||
border-radius: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] button::-moz-focus-inner {
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Pressed state */
|
||||
[role="dialog"][data-type="action"] > header a:active .icon:after,
|
||||
[role="dialog"][data-type="action"] > header button:active .icon:after,
|
||||
[role="dialog"][data-type="action"] > header menu[type="toolbar"] a:active,
|
||||
[role="dialog"][data-type="action"] > header menu[type="toolbar"] button:active {
|
||||
background: #008aaa !important;
|
||||
}
|
||||
|
||||
/* Disabled state */
|
||||
[role="dialog"][data-type="action"] > header menu[type="toolbar"] a[aria-disabled="true"],
|
||||
[role="dialog"][data-type="action"] > header menu[type="toolbar"] button[disabled] {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Icon definitions */
|
||||
[role="dialog"][data-type="action"] > header .icon {
|
||||
position: relative;
|
||||
float: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 4rem;
|
||||
height: 4.9rem;
|
||||
margin: 0 -1rem;
|
||||
background: transparent no-repeat center center / 3rem auto;
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > header .icon.icon-close {
|
||||
background-image: url(action_menu/images/icons/close.png);
|
||||
}
|
||||
|
||||
html[dir="ltr"] [role="dialog"][data-type="action"] > header .icon.icon-back {
|
||||
background-image: url(action_menu/images/icons/left.png);
|
||||
}
|
||||
html[dir="rtl"] [role="dialog"][data-type="action"] > header .icon.icon-back {
|
||||
background-image: url(action_menu/images/icons/right.png);
|
||||
}
|
||||
|
||||
/* Navigation links (back, cancel, etc) */
|
||||
[role="dialog"][data-type="action"] > header > button,
|
||||
[role="dialog"][data-type="action"] > header > a {
|
||||
width: 5rem;
|
||||
height: 4.9rem;
|
||||
background: none;
|
||||
overflow: visible;
|
||||
margin: 0 -1rem;
|
||||
margin-inline-start: -3rem;
|
||||
position: relative;
|
||||
}
|
||||
html[dir="ltr"] [role="dialog"][data-type="action"] > header > button,
|
||||
html[dir="ltr"] [role="dialog"][data-type="action"] > header > a {
|
||||
float: left;
|
||||
}
|
||||
html[dir="rtl"] [role="dialog"][data-type="action"] > header > button,
|
||||
html[dir="rtl"] [role="dialog"][data-type="action"] > header > a {
|
||||
float: right;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > header > button::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > header > button .icon,
|
||||
[role="dialog"][data-type="action"] > header > a .icon {
|
||||
position: static;
|
||||
display: block;
|
||||
width: 3rem;
|
||||
height: 4.9rem;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > header > button .icon:after,
|
||||
[role="dialog"][data-type="action"] > header > a .icon:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
offset-inline-start: 0;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
width: 3rem;
|
||||
height: 4.9rem;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
[role="dialog"][data-type="action"] > section {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 7rem;
|
||||
left: 1.5rem;
|
||||
right: 1.5rem;
|
||||
bottom: 2rem;
|
||||
font-size: 1.6rem;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
/* Specific component code */
|
||||
[role="dialog"][data-type="action"] > menu {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-height: calc(100% - 13.5rem); /*header(5rem) + footer(7rem) + padding(1.5rem)*/
|
||||
height: auto;
|
||||
padding-top: 1.5rem;
|
||||
overflow: auto;
|
||||
width: auto;
|
||||
border: none;
|
||||
background: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 7rem;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > menu > button {
|
||||
width: calc(100% - 3rem);
|
||||
height: 4rem;
|
||||
box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
font-weight: normal;
|
||||
line-height: 4rem;
|
||||
outline: none;
|
||||
font-size: 1.6rem;
|
||||
text-shadow: none;
|
||||
padding: 0 1.2rem;
|
||||
margin: 0 1.5rem 1rem;
|
||||
background: rgba(87, 87, 87, 0.8);
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > menu > .last-button-container {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background-color: #4d4d4d;
|
||||
height: 7rem;
|
||||
offset-inline-start: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > menu > .last-button-container button {
|
||||
width: calc(100% - 3rem);
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
margin: 0 1.5rem 1.5rem;
|
||||
offset-inline-start: 0;
|
||||
color: #333;
|
||||
background: #d8d8d8;
|
||||
text-align: center;
|
||||
border: none;
|
||||
border-radius: 2rem;
|
||||
line-height: 4rem;
|
||||
font-size: 1.6rem;
|
||||
height: 4rem;
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > menu > button:nth-last-child(2) {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
/* Press state */
|
||||
[role="dialog"][data-type="action"] > menu button:active {
|
||||
background: #00aacc;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
[role="dialog"][data-type="action"] > menu > button[disabled] {
|
||||
background-color: rgba(87, 87, 87, 0.8);
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
[role="dialog"][data-type="action"] > menu > .last-button-container button[disabled] {
|
||||
background-color: #e7e7e7;
|
||||
color: #a6a6a6;
|
||||
opacity: 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Action menu</title>
|
||||
<meta name="description" content="Presenting a list of actions related to the App content">
|
||||
|
||||
<link rel="stylesheet" href="../action_menu.css">
|
||||
<!--
|
||||
- This <style> element is only used for the example code;
|
||||
- it is not required for the real use case.
|
||||
-->
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body role="application">
|
||||
<p dir="ltr">
|
||||
<label>
|
||||
<input type="checkbox"
|
||||
onchange="document.documentElement.dir = this.checked ? 'rtl' : 'ltr'">
|
||||
RTL mode
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<form role="dialog" data-type="action">
|
||||
<header>
|
||||
<button><span class="icon icon-close">close</span></button>
|
||||
<menu type="toolbar">
|
||||
<button>done</button>
|
||||
</menu>
|
||||
<h1>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</h1>
|
||||
</header>
|
||||
<section>
|
||||
<p>Curabitur condimentum diam mollis lacus hendrerit congue. Phasellus porttitor orci elit, ac consequat est mollis ut. Ut consequat ipsum a ullamcorper aliquam.</p>
|
||||
</section>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 245 B |
|
After Width: | Height: | Size: 178 B |
|
After Width: | Height: | Size: 178 B |
|
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Action menu</title>
|
||||
<meta name="description" content="Presenting a list of actions related to the App content">
|
||||
|
||||
<link rel="stylesheet" href="../action_menu.css">
|
||||
<!--
|
||||
- These <style> and <script> elements are only used for the example code;
|
||||
- they are not required for the real use case.
|
||||
-->
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onkeypress = event => {
|
||||
var dir = document.documentElement.dir;
|
||||
document.documentElement.dir = (dir === 'ltr') ? 'rtl' : 'ltr';
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body role="application">
|
||||
<form role="dialog" data-type="action">
|
||||
<header><span class="icon icon-back"></span>Title</header> <!-- this header is optional -->
|
||||
<menu type="toolbar">
|
||||
<button>Action 1</button>
|
||||
<button disabled> Action 2 (disabled) </button>
|
||||
<button> Action 3. </button>
|
||||
<button> الولايات 4</button>
|
||||
<button disabled> Action 5 (disabled) </button>
|
||||
<button> Action 6 </button>
|
||||
<button> Action 7 </button>
|
||||
<button disabled> Action 8 (disabled) </button>
|
||||
<button> Action 9 </button>
|
||||
<button> Cancel </button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
.fade-in {
|
||||
animation: fade-in 0.2s forwards;
|
||||
}
|
||||
|
||||
.fade-out {
|
||||
animation: fade-out 0.2s forwards;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
0% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
html[dir="ltr"] .app-go-deeper-out {
|
||||
animation: current-to-left var(--transition-duration) forwards;
|
||||
}
|
||||
html[dir="rtl"] .app-go-deeper-out {
|
||||
animation: current-to-right var(--transition-duration) forwards;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .app-go-deeper-in {
|
||||
animation: right-to-current var(--transition-duration) forwards;
|
||||
}
|
||||
html[dir="rtl"] .app-go-deeper-in {
|
||||
animation: left-to-current var(--transition-duration) forwards;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .app-go-deeper-back-in {
|
||||
animation: left-to-current var(--transition-duration) forwards;
|
||||
}
|
||||
html[dir="rtl"] .app-go-deeper-back-in {
|
||||
animation: right-to-current var(--transition-duration) forwards;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .app-go-deeper-back-out {
|
||||
animation: current-to-right var(--transition-duration) forwards;
|
||||
}
|
||||
html[dir="rtl"] .app-go-deeper-back-out {
|
||||
animation: current-to-left var(--transition-duration) forwards;
|
||||
}
|
||||
|
||||
@keyframes show {
|
||||
0% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes hide {
|
||||
0% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes right-to-current {
|
||||
0% { transform: translateX(100%); }
|
||||
100% { transform: translateX(0); }
|
||||
}
|
||||
|
||||
@keyframes current-to-left {
|
||||
0% { transform: translateX(0); }
|
||||
100% { transform: translateX(-100%); }
|
||||
}
|
||||
|
||||
@keyframes current-to-right {
|
||||
0% { transform: translateX(0); }
|
||||
100% { transform: translateX(100%); }
|
||||
}
|
||||
|
||||
@keyframes left-to-current {
|
||||
/* To pre-render the incoming screen and avoid a flick we are getting if
|
||||
setting it to 100%. */
|
||||
0% { transform: translateX(-99.99%); }
|
||||
100% { transform: translateX(0); }
|
||||
}
|
||||
|
||||
@keyframes header-current-to-left {
|
||||
0% { transform: translateX(0); }
|
||||
100% { transform: translateX(-30%); }
|
||||
}
|
||||
|
||||
@keyframes header-left-to-current {
|
||||
0% { transform: translateX(-30%); }
|
||||
100% { transform: translateX(0); }
|
||||
}
|
||||
|
||||
.app-go-up-in {
|
||||
animation: app-go-up-in var(--transition-duration) forwards ease-in;
|
||||
}
|
||||
|
||||
.app-go-up-back-out {
|
||||
animation: app-go-up-back-out var(--transition-duration) forwards ease-in;
|
||||
}
|
||||
|
||||
@keyframes app-go-up-in {
|
||||
0% { transform: translateY(100%); }
|
||||
100% { transform: translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes app-go-up-back-out {
|
||||
0% { transform: translateY(0); }
|
||||
100% { transform: translateY(100%); }
|
||||
}
|
||||
|
||||
html[dir="ltr"] .app-go-in {
|
||||
animation: right-to-current var(--transition-duration) forwards ease-in;
|
||||
}
|
||||
html[dir="rtl"] .app-go-in {
|
||||
animation: left-to-current var(--transition-duration) forwards ease-in;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .app-go-back-out {
|
||||
animation: current-to-right var(--transition-duration) forwards ease-in;
|
||||
}
|
||||
html[dir="rtl"] .app-go-back-out {
|
||||
animation: current-to-left var(--transition-duration) forwards ease-in;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .move-in-from-forward {
|
||||
animation: move-left-in var(--transition-duration) forwards;
|
||||
}
|
||||
html[dir="rtl"] .move-in-from-forward {
|
||||
animation: move-right-in var(--transition-duration) forwards;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .move-out-from-forward {
|
||||
animation: move-left-out var(--transition-duration) forwards;
|
||||
}
|
||||
html[dir="rtl"] .move-out-from-forward {
|
||||
animation: move-right-out var(--transition-duration) forwards;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .move-in-from-backward {
|
||||
animation: move-right-in var(--transition-duration) forwards;
|
||||
}
|
||||
html[dir="rtl"] .move-in-from-backward {
|
||||
animation: move-left-in var(--transition-duration) forwards;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .move-out-from-backward {
|
||||
animation: move-right-out var(--transition-duration) forwards;
|
||||
}
|
||||
html[dir="rtl"] .move-out-from-backward {
|
||||
animation: move-left-out var(--transition-duration) forwards;
|
||||
}
|
||||
|
||||
@keyframes move-left-in {
|
||||
0% { transform: translateX(100%);}
|
||||
100% { transform: translateX(0);}
|
||||
}
|
||||
|
||||
@keyframes move-left-out {
|
||||
0% { transform: translateX(0);}
|
||||
100% { transform: translateX(-100%);}
|
||||
}
|
||||
|
||||
@keyframes move-right-in {
|
||||
0% { transform: translateX(-100%);}
|
||||
100% { transform: translateX(0%);}
|
||||
}
|
||||
|
||||
@keyframes move-right-out {
|
||||
0% { transform: translateX(0%);}
|
||||
100% { transform: translateX(100%);}
|
||||
}
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
/* ----------------------------------
|
||||
* Confirm
|
||||
* ---------------------------------- */
|
||||
|
||||
/* Main dialog setup */
|
||||
form[role="dialog"][data-type="confirm"] {
|
||||
background: #2d2d2d;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding-bottom: 7rem;
|
||||
font-size: 0;
|
||||
/* Using font-size: 0; we avoid the unwanted visual space (about 3px)
|
||||
created by white-spaces and break lines in the code betewen inline-block elements */
|
||||
color: #fff;
|
||||
}
|
||||
html[dir="ltr"] form[role="dialog"][data-type="confirm"] { text-align: left; }
|
||||
html[dir="rtl"] form[role="dialog"][data-type="confirm"] { text-align: right; }
|
||||
|
||||
form[role="dialog"][data-type="confirm"]:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 0.1rem;
|
||||
height: 100%;
|
||||
margin-inline-start: -0.1rem;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] > section {
|
||||
font-weight: 300;
|
||||
font-size: 2.2rem;
|
||||
color: #FAFAFA;
|
||||
padding: 0 1.5rem;
|
||||
box-sizing: padding-box;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
overflow-y: scroll;
|
||||
max-height: 100%;
|
||||
vertical-align: middle;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] h1 {
|
||||
font-weight: normal;
|
||||
font-size: 1.6rem;
|
||||
line-height: 1.5em;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
padding: 1rem 1.5rem 0;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/* Menu & buttons setup */
|
||||
form[role="dialog"][data-type="confirm"] menu {
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
padding: 1.5rem;
|
||||
background: #4d4d4d;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] menu button::-moz-focus-inner {
|
||||
border: none;
|
||||
outline: none;
|
||||
margin-top: -0.2rem; /* To fix line-height bug (697451) */
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] menu button {
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
width: 100%;
|
||||
height: 4rem;
|
||||
margin: 0 0 1rem;
|
||||
padding: 0 0.2rem;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
background: #d8d8d8;
|
||||
border: none;
|
||||
border-radius: 2rem;
|
||||
font-weight: normal;
|
||||
font-size: 1.6rem;
|
||||
line-height: 4rem;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
text-shadow: none;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Recommend */
|
||||
form[role="dialog"][data-type="confirm"] menu button.recommend {
|
||||
background-color: #00caf2;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Danger */
|
||||
form[role="dialog"][data-type="confirm"] menu button.danger {
|
||||
background-color: #e51e1e;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Pressed */
|
||||
form[role="dialog"][data-type="confirm"] menu button:active {
|
||||
background: #00aacc;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
form[role="dialog"][data-type="confirm"] > menu > button[disabled] {
|
||||
background-color: #565656;
|
||||
color: rgba(255,255,255,0.4);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] > menu > button[disabled].recommend {
|
||||
background-color: #006579;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] > menu > button[disabled].danger {
|
||||
background-color: #730f0f;
|
||||
}
|
||||
|
||||
button[disabled]::-moz-selection {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] menu button {
|
||||
margin: 0;
|
||||
margin-inline-end: 1rem;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] menu button:last-child {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Specific component code
|
||||
**
|
||||
** 1. Text in confirm dialog should not be selectable.
|
||||
*/
|
||||
form[role="dialog"][data-type="confirm"] p:nth-child(2) {
|
||||
margin: 1rem 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p {
|
||||
word-wrap: break-word;
|
||||
margin: 0;
|
||||
padding: 1rem 1.5rem;
|
||||
border-top: 0.1rem solid #686868;
|
||||
line-height: 3rem;
|
||||
-moz-user-select: none; /* 1 */
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p > span {
|
||||
font-size: 1.5rem;
|
||||
display: block;
|
||||
line-height: 1.7rem;
|
||||
color: rgba(255,255,255,0.6);
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p img {
|
||||
margin-inline-end: 2rem;
|
||||
}
|
||||
html[dir="ltr"] form[role="dialog"][data-type="confirm"] p img { float: left; }
|
||||
html[dir="rtl"] form[role="dialog"][data-type="confirm"] p img { float: right; }
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p strong {
|
||||
display: block;
|
||||
margin-top: 0.2rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p small {
|
||||
font-size: 1.4rem;
|
||||
font-weight: normal;
|
||||
color: #cbcbcb;
|
||||
display: block;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] dl {
|
||||
border-top: 0.1rem solid #686868;
|
||||
margin: 1rem 0 0;
|
||||
overflow: hidden;
|
||||
padding-top: 1rem;
|
||||
font-size: 1.6rem;
|
||||
line-height: 2.2rem;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] dl > dt {
|
||||
clear: both;
|
||||
width: 7rem;
|
||||
padding-inline-start: 1.5rem;
|
||||
font-weight: 500;
|
||||
text-align: left;
|
||||
}
|
||||
html[dir="ltr"] form[role="dialog"][data-type="confirm"] dl > dt { float: left; }
|
||||
html[dir="rtl"] form[role="dialog"][data-type="confirm"] dl > dt { float: right; text-align: right; }
|
||||
|
||||
form[role="dialog"][data-type="confirm"] dl > dd {
|
||||
padding-inline-end: 1.5rem;
|
||||
font-weight: 300;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: top;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] dl > dd > div {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] figure {
|
||||
margin: 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] figure img {
|
||||
padding-inline-end: 1.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] figure figcaption {
|
||||
font-size: 2.1rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] ul {
|
||||
margin: 0;
|
||||
padding: 2rem 1.5rem;
|
||||
border-top: 0.1rem solid #686868;
|
||||
list-style: none;
|
||||
font-size: 1.6rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] ul li {
|
||||
word-wrap: break-word;
|
||||
line-height: 2rem;
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] ul li:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] ul li ul {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Confirm</title>
|
||||
<meta name="description" content="Prompts user to take action">
|
||||
|
||||
<link rel="stylesheet" href="../confirm.css">
|
||||
|
||||
<!--
|
||||
- These <style> and <script> elements are only used for the example code;
|
||||
- they are not required for the real use case.
|
||||
-->
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
#dir {
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
display: block;
|
||||
direction: ltr;
|
||||
background-color: white;
|
||||
}
|
||||
#dir input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onload = function(){
|
||||
var input = document.querySelector('#dir input');
|
||||
input.checked = false;
|
||||
input.onchange = function() {
|
||||
document.documentElement.dir = this.checked ? 'rtl' : 'ltr';
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body role="application">
|
||||
<label id="dir">
|
||||
<input type="checkbox"> RTL mode
|
||||
</label>
|
||||
|
||||
<form role="dialog" data-type="confirm">
|
||||
<section>
|
||||
<h1>Confirmation</h1>
|
||||
<p>Are you sure you want to delete this contact?</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button>Cancel</button>
|
||||
<button class="danger">Delete</button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Confirm</title>
|
||||
<meta name="description" content="Prompts user to take action">
|
||||
|
||||
<link rel="stylesheet" href="../confirm.css">
|
||||
|
||||
<!--
|
||||
- These <style> and <script> elements are only used for the example code;
|
||||
- they are not required for the real use case.
|
||||
-->
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
#dir {
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
display: block;
|
||||
direction: ltr;
|
||||
background-color: white;
|
||||
}
|
||||
#dir input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onload = function(){
|
||||
var input = document.querySelector('#dir input');
|
||||
input.checked = false;
|
||||
input.onchange = function() {
|
||||
document.documentElement.dir = this.checked ? 'rtl' : 'ltr';
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body role="application">
|
||||
<label id="dir">
|
||||
<input type="checkbox"> RTL mode
|
||||
</label>
|
||||
|
||||
<form role="dialog" data-type="confirm">
|
||||
<section>
|
||||
<h1>Confirmation</h1>
|
||||
<p dir="auto">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button>Cancel</button>
|
||||
<button class="danger">Delete</button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Confirm, w/o title</title>
|
||||
<meta name="description" content="Prompts user to take action">
|
||||
|
||||
<link rel="stylesheet" href="../confirm.css">
|
||||
|
||||
<!--
|
||||
- These <style> and <script> elements are only used for the example code;
|
||||
- they are not required for the real use case.
|
||||
-->
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
#dir {
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
display: block;
|
||||
direction: ltr;
|
||||
background-color: white;
|
||||
}
|
||||
#dir input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onload = function(){
|
||||
var input = document.querySelector('#dir input');
|
||||
input.checked = false;
|
||||
input.onchange = function() {
|
||||
document.documentElement.dir = this.checked ? 'rtl' : 'ltr';
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body role="application">
|
||||
<label id="dir">
|
||||
<input type="checkbox"> RTL mode
|
||||
</label>
|
||||
|
||||
<form role="dialog" data-type="confirm">
|
||||
<section>
|
||||
<p dir="auto">Are you sure you want to delete this contact?</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button>Cancel</button>
|
||||
<button class="danger">Delete</button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/* Overrides building blocks */
|
||||
#contact-list .contact-item {
|
||||
height: auto;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
/* End overrides building blocks */
|
||||
|
||||
.contact-item {
|
||||
flex: 1;
|
||||
padding: 0 2rem;
|
||||
min-width: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.contact-item .ci__tel-type:not(:empty) ~ .js-separator::before {
|
||||
content: ',';
|
||||
-moz-margin-end: 5px;
|
||||
}
|
||||
|
||||
.contact-item .ci__tel-type:not(:empty) {
|
||||
min-width: 4rem;
|
||||
max-width: 10rem;
|
||||
}
|
||||
|
||||
.ci__name {
|
||||
line-height: 1.9rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ci--action-menu .ci__name {
|
||||
font-size: 1.7rem;
|
||||
line-height: 2.1rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.ci__details {
|
||||
display: flex;
|
||||
font-size: 1.7rem;
|
||||
line-height: 2.3rem;
|
||||
pointer-events: none;
|
||||
margin-bottom: -0.4rem;
|
||||
}
|
||||
|
||||
.ci--action-menu .ci__details {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.ci__mark {
|
||||
background-color: #94EEE9;
|
||||
color: unset;
|
||||
}
|
||||
|
||||
.ci--action-menu .ci__mark {
|
||||
background: #333;
|
||||
color: #94eee9;
|
||||
}
|
||||
|
||||
.js-tel {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/* FIXME Move to some kind of "building blocks" file? */
|
||||
.ellipsis {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Override BB styles for LTR */
|
||||
[role="dialog"][data-type="action"] > menu > button.contact-item {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Override BB styles for RTL */
|
||||
html[dir="rtl"] [role="dialog"][data-type="action"] > menu > button.contact-item,
|
||||
html[dir="rtl"] .contact-item {
|
||||
text-align: right;
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
* {
|
||||
/* By default do not allow any user text selection, only enable for certain
|
||||
parts on a per-element/region area. We are enabling this at the * level
|
||||
as opposed to the body level as the -moz-user-select attribute is not
|
||||
inherited by absolute positioned elements and dialer has several
|
||||
elements that are absolute positioned that should be non-selectable. */
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
html,body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
color: white;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#call-log-view > div {
|
||||
background-color: white;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.font-light {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
a {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
a:hover, a:active, a:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.contact-primary-info {
|
||||
font-size: calc(15 * 0.226rem);
|
||||
color: black;
|
||||
}
|
||||
|
||||
.contact-secondary-info {
|
||||
font-size: calc(6 * 0.226rem);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.grid-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body.hidden *[data-l10n-id] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
* The code is being shared between system/emergency-call/js/keypad.js
|
||||
* and dialer/js/keypad.js. Be sure to update both files when you commit!
|
||||
*
|
||||
* BiDi note: keypads are always displayed in LTR (hardware legacy).
|
||||
* This stylesheet must *NOT* be mirrored for RTL.
|
||||
*/
|
||||
|
||||
.reset-button {
|
||||
border: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.reset-button::-moz-focus-inner {
|
||||
border: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#phone-number-view-container {
|
||||
width: 100%;
|
||||
height: 28%;
|
||||
background: var(--header-background);
|
||||
text-align: center;
|
||||
display: flex;
|
||||
font-weight: 300;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#phone-number-view-container .phone-number-view-wrapper-input {
|
||||
width: 100%;
|
||||
margin-bottom: 4.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 1rem 0 2rem;
|
||||
}
|
||||
|
||||
#phone-number-view-container.keypad-visible {
|
||||
height: calc(100% - 34.5rem);
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#phone-number-view {
|
||||
font-size: 4.1rem;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
color: var(--header-color);
|
||||
text-align: left;
|
||||
cursor: none;
|
||||
padding: 0;
|
||||
pointer-events: auto;
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
#fake-phone-number-view {
|
||||
position: absolute;
|
||||
left: 2rem;
|
||||
line-height: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#keypad-delete {
|
||||
margin-bottom: 4.5rem;
|
||||
padding: 0 2.5rem 0 0;
|
||||
visibility: hidden;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#keypad-delete::before {
|
||||
content: "";
|
||||
background: url('keypad/images/keypad/actionicon_dialer_delete.png') no-repeat;
|
||||
width: 3rem;
|
||||
height: 2rem;
|
||||
display: inline-block;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
#keypad-delete:active {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
#keyboard-container {
|
||||
height: 72%;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
#keypad {
|
||||
width: 100%;
|
||||
height: 80%;
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.keypad-row {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.keypad-key {
|
||||
display: table-cell;
|
||||
padding: 1.3rem 0 0 2rem;
|
||||
box-sizing: border-box;
|
||||
height: 20%;
|
||||
vertical-align: middle;
|
||||
color: #333;
|
||||
font-weight: 300;
|
||||
font-size: 5rem;
|
||||
line-height: 1rem;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.keypad-key span {
|
||||
width: 1.5rem;
|
||||
display: inline-block;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.keypad-key em {
|
||||
display: inline-block;
|
||||
font-weight: 300;
|
||||
font-size: 1.5rem;
|
||||
color: #038282;
|
||||
font-style: normal;
|
||||
width: 4.5rem;
|
||||
overflow: visible;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.keypad-key.active {
|
||||
background: #94eee9;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.keypad-key * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#keypad-delete * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.keypad-key .font-size-plus {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.keypad-subicon {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center bottom;
|
||||
|
||||
-moz-user-select: none;
|
||||
pointer-events: none;
|
||||
|
||||
display: inline-block;
|
||||
width: 3rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.voicemail {
|
||||
background-image: url('keypad/images/keypad/actionicon_dialer_voicemail.png');
|
||||
background-size: 3rem;
|
||||
background-position: -0.4rem -0.1rem;
|
||||
}
|
||||
|
||||
.asterisk {
|
||||
width: 4rem;
|
||||
margin-top: 1rem;
|
||||
margin-left: 0.2rem;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.sharp {
|
||||
font-size: 4.5rem;
|
||||
width: 4rem;
|
||||
line-height: 0;
|
||||
margin-top: -0.5rem;
|
||||
margin-left: 0.2rem;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#keypad-callbar {
|
||||
height: 20%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
border-bottom: 0;
|
||||
border-left: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.keypad-callbar-button {
|
||||
position: relative;
|
||||
width: 9rem;
|
||||
background: #e7e7e7;
|
||||
background-size: auto 100%;
|
||||
border-radius: 2rem;
|
||||
overflow: hidden;
|
||||
height: 4rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.keypad-callbar-button.cancel {
|
||||
background: #575757;
|
||||
line-height: 4rem;
|
||||
font-size: 1.8rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.keypad-callbar-button.cancel:active {
|
||||
background: #9ef2e7;
|
||||
}
|
||||
|
||||
#keypad-callbar-call-action {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
flex-direction: row-reverse;
|
||||
background-image: url("keypad/images/keypad/actionicon_activecall_pickup.png");
|
||||
background-color: #00adad;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 4rem 4rem;
|
||||
border-radius: 2rem;
|
||||
margin-inline-start: 1rem;
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
#keypad-callbar-call-action:active {
|
||||
background-color: #94eee9;
|
||||
}
|
||||
|
||||
.icon-add-contact::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-image: url("keypad/images/keypad/actionicon_activecall_addcontact_40x80.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top center;
|
||||
background-size: 4rem 8rem;
|
||||
}
|
||||
|
||||
/* we won't do anything on click but this prevents fluffing/rendering issues */
|
||||
.icon-add-contact:disabled {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.icon-add-contact:disabled::before {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.icon-add-contact:not(:disabled):active::before {
|
||||
background-position: center -4rem;
|
||||
}
|
||||
|
||||
.js-sim-indication {
|
||||
display: none;
|
||||
font-size: 1.3rem;
|
||||
text-align: right;
|
||||
margin-right: 0.6rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.has-preferred-sim .js-sim-indication {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
.has-preferred-sim #keypad-callbar-call-action:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 1.4rem;
|
||||
height: 1rem;
|
||||
bottom: 0;
|
||||
right: 1.7rem;
|
||||
background-image: url("/shared/elements/gaia_sim_picker/images/long-tap-indicator.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.4rem 1rem;
|
||||
}
|
||||
|
||||
#keypad-hidebar {
|
||||
border: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
height: 7.5rem;
|
||||
}
|
||||
|
||||
.kh__button {
|
||||
width: 5rem;
|
||||
height: 5rem;
|
||||
background: #ded9d6;
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
margin-top: 1rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.kh__button::before {
|
||||
content: "";
|
||||
|
||||
position: absolute;
|
||||
top: .5rem;
|
||||
left: .5rem;
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 0;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.kh__button:active::before {
|
||||
background-position: 0 -4rem;
|
||||
}
|
||||
|
||||
.kh__button:active {
|
||||
background-color: #9ef2e7;
|
||||
}
|
||||
|
||||
.kh__button.active-state::before {
|
||||
background-position: 0 -8rem;
|
||||
}
|
||||
|
||||
.kh__button--mute::before {
|
||||
background-image: url('keypad/images/keypad/actionicon_activecall_mute.png');
|
||||
}
|
||||
|
||||
.kh__button--hide::before {
|
||||
background-image: url('keypad/images/keypad/actionicon_activecall_dismisskeyboard.png');
|
||||
}
|
||||
|
||||
.kh__call-end-button {
|
||||
width: 6.5rem;
|
||||
height: 6.5rem;
|
||||
background: #e00;
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.kh__call-end-button::before {
|
||||
content: "";
|
||||
|
||||
position: absolute;
|
||||
top: 1.1rem;
|
||||
left: 1.2rem;
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
|
||||
background-image: url('keypad/images/actionicon_activecall_hangup.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 0;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.kh__call-end-button:active::before {
|
||||
background-position: 1.2rem 6rem;
|
||||
}
|
||||
|
||||
.phone-number-font {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.full-height {
|
||||
height: 100%;
|
||||
}
|
||||
|
After Width: | Height: | Size: 212 B |
|
After Width: | Height: | Size: 216 B |
|
After Width: | Height: | Size: 264 B |
|
After Width: | Height: | Size: 283 B |
|
After Width: | Height: | Size: 405 B |
|
After Width: | Height: | Size: 600 B |
|
After Width: | Height: | Size: 799 B |
|
After Width: | Height: | Size: 283 B |
|
After Width: | Height: | Size: 234 B |
|
After Width: | Height: | Size: 290 B |
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Extend action menu as an overlay
|
||||
*/
|
||||
form.overlay {
|
||||
font-size: 1.5rem;
|
||||
opacity: 1;
|
||||
visibility: hidden;
|
||||
transform: translateY(-100%);
|
||||
transition: transform var(--transition-duration) ease-in-out,
|
||||
visibility var(--transition-duration);
|
||||
}
|
||||
|
||||
form.overlay > menu {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
form.overlay.display {
|
||||
transform: translateY(0%);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
form.overlay menu ul {
|
||||
height: calc(100% - 13rem);
|
||||
overflow: auto;
|
||||
margin-top: 5rem;
|
||||
padding: 0;
|
||||
line-height: 2.4rem;
|
||||
list-style: none outside none;
|
||||
}
|
||||
|
||||
form.overlay menu ul > li,
|
||||
form.overlay menu ul > section {
|
||||
height: 4.5rem;
|
||||
padding: 1rem 2rem;
|
||||
font-size: 1.7rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
form.overlay menu ul > li:after,
|
||||
form.overlay menu ul > section:after {
|
||||
content: ' ';
|
||||
border-bottom: 0.1rem solid #666;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 1rem;
|
||||
bottom: 0;
|
||||
right: 1rem;
|
||||
}
|
||||
|
||||
form.overlay menu ul > li:last-child:after,
|
||||
form.overlay menu ul > section:last-child:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form.overlay menu ul > li:active,
|
||||
form.overlay menu ul > section:active {
|
||||
background-color: #00ABCC;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||