Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/apps/system/emergency-call
diff options
context:
space:
mode:
Diffstat (limited to 'apps/system/emergency-call')
-rw-r--r--apps/system/emergency-call/index.html198
-rw-r--r--apps/system/emergency-call/js/dialer.js80
-rw-r--r--apps/system/emergency-call/js/keypad.js461
-rw-r--r--apps/system/emergency-call/style/dialer.css250
-rw-r--r--apps/system/emergency-call/style/images/ActionIcon_40x40_bluetooth.pngbin0 -> 1842 bytes
-rw-r--r--apps/system/emergency-call/style/images/ActionIcon_40x40_bluetooth_active.pngbin0 -> 1866 bytes
-rw-r--r--apps/system/emergency-call/style/images/ActionIcon_40x40_hangup.pngbin0 -> 1409 bytes
-rw-r--r--apps/system/emergency-call/style/images/ActionIcon_40x40_pickup.pngbin0 -> 1404 bytes
-rw-r--r--apps/system/emergency-call/style/images/asterisk.pngbin0 -> 1172 bytes
-rw-r--r--apps/system/emergency-call/style/images/dialer_icon_delete.pngbin0 -> 1419 bytes
-rw-r--r--apps/system/emergency-call/style/images/sharp.pngbin0 -> 1176 bytes
-rw-r--r--apps/system/emergency-call/style/keypad.css301
12 files changed, 1290 insertions, 0 deletions
diff --git a/apps/system/emergency-call/index.html b/apps/system/emergency-call/index.html
new file mode 100644
index 0000000..534c05e
--- /dev/null
+++ b/apps/system/emergency-call/index.html
@@ -0,0 +1,198 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="pragma" content="no-cache">
+ <title>Emergency Call Dialer</title>
+ <link rel="stylesheet" type="text/css" href="style/dialer.css">
+ <link rel="stylesheet" type="text/css" href="style/keypad.css">
+ <!-- Shared code -->
+ <script defer type="application/javascript" src="/shared/js/settings_listener.js"></script>
+ <script src="/shared/js/l10n.js"></script>
+ <link rel="resource" type="application/l10n" href="/locales/locales.ini">
+
+ <!-- Specific code -->
+ <script defer type="application/javascript" src="js/keypad.js"></script>
+ <script defer type="application/javascript" src="js/dialer.js"></script>
+ </head>
+ <body class="hidden">
+ <article id="views" role="tablist">
+ <section id="keyboard-view" role="tabpanel">
+ <div id="phone-number-view-container">
+ <div class="grid-cell grid-v-align">
+ <div class="grid-wrapper">
+ <input id="phone-number-view" type="text" class="phone-number-font" readonly="readonly">
+ <div id="fake-phone-number-view"></div>
+ </div>
+ </div>
+ <div id="keypad-delete" class="grid-cell grid-v-align" data-value="delete">
+ <div>
+ </div>
+ </div>
+ </div>
+ <article id="keyboard-container">
+ <section id="keypad">
+ <div class="keypad-cell">
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="1">
+ <span class="keypad-number font-light">1</span>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="4">
+ <span class="keypad-number font-light">4</span>
+ <span class="keypad-text font-semibold">GHI</span>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="7">
+ <span class="keypad-number font-light">7</span>
+ <span class="keypad-text font-semibold">PQRS</span>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label keypad-key-label-centered" data-value="*">
+ <span>
+ <div class="asterisk"></div>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-cell">
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="2">
+ <span class="keypad-number font-light">2</span>
+ <span class="keypad-text font-semibold font-semibold">ABC</span>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="5">
+ <span class="keypad-number font-light">5</span>
+ <span class="keypad-text font-semibold">JKL</span>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="8">
+ <span class="keypad-number font-light">8</span>
+ <span class="keypad-text font-semibold">TUV</span>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="0">
+ <span class="keypad-number font-light">0</span>
+ <span class="keypad-text font-semibold font-size-plus">+</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-cell">
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="3">
+ <span class="keypad-number font-light">3</span>
+ <span class="keypad-text font-semibold">DEF</span>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="6">
+ <span class="keypad-number font-light">6</span>
+ <span class="keypad-text font-semibold">MNO</span>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label" data-value="9">
+ <span class="keypad-number font-light">9</span>
+ <span class="keypad-text font-semibold">WXYZ</span>
+ </div>
+ </div>
+ </div>
+ <div class="keypad-key">
+ <div class="keypad-key-label-container">
+ <div class="keypad-key-label keypad-key-label-centered" data-type="dial" data-value="#">
+ <span>
+ <div class="sharp"></div>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </section>
+ <section id="keypad-callbar">
+ <span role="button" id="keypad-callbar-cancel" data-type="action" data-value="cancel" >
+ <div>Cancel</div>
+ </span>
+ <span role="button" id="keypad-callbar-call-action" data-type="action" data-value="make-call">
+ <div>
+ </div>
+ </span>
+ </section>
+ </article>
+ </section>
+ </article>
+ <article id="call-screen" class="grid">
+ <article id="calls">
+ <section>
+ <div id="emergency-number" class="number">
+ </div>
+ <div class="fake-number">
+ </div>
+ <div class="additionalContactInfo">
+ <span >Emergency call</span>
+ </div>
+ <div class="duration">
+ <span></span>
+ <div class="direction">
+ <div>
+ </div>
+ </div>
+ </div>
+ </section>
+ </article>
+ <article id="main-container" class="grid-row">
+ <div id="actions-container" class="grid-wrapper grid">
+ <footer id="call-options" class="grid-row">
+ <div class="grid-wrapper grid">
+ <section id="co-advanced" class="grid-row">
+ <div class="grid-wrapper grid">
+ <span class="grid-cell options-column">
+ <button id="speaker" class="co-advanced-option grid-wraper grid">
+ <span>
+ </span>
+ </button>
+ </span>
+ </div>
+ </section>
+ <footer id="callbar">
+ <div id="callbar-hang-up">
+ <span role="button" id="callbar-hang-up-action" class="callbar-button">
+ <div>
+ </div>
+ </span>
+ </div>
+ </footer>
+ </div>
+ </footer>
+ </div>
+ </article>
+ </article>
+ </body>
+</html>
diff --git a/apps/system/emergency-call/js/dialer.js b/apps/system/emergency-call/js/dialer.js
new file mode 100644
index 0000000..ff93009
--- /dev/null
+++ b/apps/system/emergency-call/js/dialer.js
@@ -0,0 +1,80 @@
+'use strict';
+
+var CallHandler = {
+ _call: null,
+ _telephony: window.navigator.mozTelephony,
+
+ call: function ch_call(number) {
+ var sanitizedNumber = number.replace(/-/g, '');
+ var telephony = this._telephony;
+ if (telephony) {
+ this._call = telephony.dialEmergency(sanitizedNumber);
+ var call = this._call;
+ if (call) {
+ var cb = function clearPhoneView() {
+ KeypadManager.updatePhoneNumber('');
+ };
+ call.onconnected = cb;
+
+ call.ondisconnected = function callEnded() {
+ cb();
+ CallScreen.hide();
+ };
+
+ CallScreen.number = call.number;
+ CallScreen.show();
+ }
+ }
+ },
+
+ end: function ch_end() {
+ if (!this._call) {
+ CallScreen.hide();
+ return;
+ }
+
+ this._call.hangUp();
+ this._call = null;
+ },
+
+ toggleSpeaker: function ch_toggleSpeaker() {
+ this._telephony.speakerEnabled = !this._telephony.speakerEnabled;
+ }
+};
+
+var CallScreen = {
+ screen: document.getElementById('call-screen'),
+ numberView: document.getElementById('emergency-number'),
+
+ hangUpButton: document.getElementById('callbar-hang-up'),
+ speakerButton: document.getElementById('speaker'),
+
+ set number(value) {
+ this.numberView.textContent = value;
+ },
+
+ init: function cs_init() {
+ this.hangUpButton.addEventListener('mouseup',
+ CallHandler.end.bind(CallHandler));
+ this.speakerButton.addEventListener('click', this.toggleSpeaker.bind(this));
+ },
+
+ show: function cs_show() {
+ this.screen.classList.add('displayed');
+ },
+
+ hide: function cs_hide() {
+ this.screen.classList.remove('displayed');
+ },
+
+ toggleSpeaker: function cs_toggleSpeaker() {
+ this.speakerButton.classList.toggle('speak');
+ CallHandler.toggleSpeaker();
+ }
+};
+
+window.addEventListener('load', function onload() {
+ window.removeEventListener('load', onload);
+ KeypadManager.init();
+ CallScreen.init();
+});
diff --git a/apps/system/emergency-call/js/keypad.js b/apps/system/emergency-call/js/keypad.js
new file mode 100644
index 0000000..6163ecf
--- /dev/null
+++ b/apps/system/emergency-call/js/keypad.js
@@ -0,0 +1,461 @@
+/*
+ * The code is being shared between system/emergency-call/js/keypad.js
+ * and dialer/js/keypad.js. Be sure to update both file when you commit!
+ *
+ */
+
+'use strict';
+
+var kFontStep = 4;
+var minFontSize = 12;
+
+// Frequencies comming from http://en.wikipedia.org/wiki/Telephone_keypad
+var gTonesFrequencies = {
+ '1': [697, 1209], '2': [697, 1336], '3': [697, 1477],
+ '4': [770, 1209], '5': [770, 1336], '6': [770, 1477],
+ '7': [852, 1209], '8': [852, 1336], '9': [852, 1477],
+ '*': [941, 1209], '0': [941, 1336], '#': [941, 1477]
+};
+
+var keypadSoundIsEnabled = true;
+SettingsListener.observe('phone.ring.keypad', true, function(value) {
+ keypadSoundIsEnabled = !!value;
+});
+
+var TonePlayer = {
+ _sampleRate: 4000,
+
+ init: function tp_init() {
+ document.addEventListener('mozvisibilitychange',
+ this.visibilityChange.bind(this));
+ this.ensureAudio();
+ },
+
+ ensureAudio: function tp_ensureAudio() {
+ if (this._audio)
+ return;
+
+ this._audio = new Audio();
+ this._audio.volume = 0.5;
+ this._audio.mozSetup(2, this._sampleRate);
+ },
+
+ generateFrames: function tp_generateFrames(soundData, freqRow, freqCol) {
+ var currentSoundSample = 0;
+ var kr = 2 * Math.PI * freqRow / this._sampleRate;
+ var kc = 2 * Math.PI * freqCol / this._sampleRate;
+ for (var i = 0; i < soundData.length; i += 2) {
+ var smoother = 0.5 + (Math.sin((i * Math.PI) / soundData.length)) / 2;
+
+ soundData[i] = Math.sin(kr * currentSoundSample) * smoother;
+ soundData[i + 1] = Math.sin(kc * currentSoundSample) * smoother;
+
+ currentSoundSample++;
+ }
+ },
+
+ play: function tp_play(frequencies) {
+ var soundDataSize = this._sampleRate / 4;
+ var soundData = new Float32Array(soundDataSize);
+ this.generateFrames(soundData, frequencies[0], frequencies[1]);
+ this._audio.mozWriteAudio(soundData);
+ },
+
+ // If the app loses focus, close the audio stream. This works around an
+ // issue in Gecko where the Audio Data API causes gfx performance problems,
+ // in particular when scrolling the homescreen.
+ // See: https://bugzilla.mozilla.org/show_bug.cgi?id=779914
+ visibilityChange: function tp_visibilityChange(e) {
+ if (!document.mozHidden) {
+ this.ensureAudio();
+ } else {
+ // Reset the audio stream. This ensures that the stream is shutdown
+ // *immediately*.
+ this._audio.src = '';
+ delete this._audio;
+ }
+ }
+
+};
+
+var KeypadManager = {
+ _phoneNumber: '',
+ _onCall: false,
+
+ get phoneNumberView() {
+ delete this.phoneNumberView;
+ return this.phoneNumberView = document.getElementById('phone-number-view');
+ },
+
+ get fakePhoneNumberView() {
+ delete this.fakePhoneNumberView;
+ return this.fakePhoneNumberView =
+ document.getElementById('fake-phone-number-view');
+ },
+
+ get phoneNumberViewContainer() {
+ delete this.phoneNumberViewContainer;
+ return this.phoneNumberViewContainer =
+ document.getElementById('phone-number-view-container');
+ },
+
+ get keypad() {
+ delete this.keypad;
+ return this.keypad = document.getElementById('keypad');
+ },
+
+ get callBar() {
+ delete this.callBar;
+ return this.callBar =
+ document.getElementById('keypad-callbar');
+ },
+
+ get hideBar() {
+ delete this.hideBar;
+ return this.hideBar = document.getElementById('keypad-hidebar');
+ },
+
+ get callBarAddContact() {
+ delete this.callBarAddContact;
+ return this.callBarAddContact =
+ document.getElementById('keypad-callbar-add-contact');
+ },
+
+ get callBarCallAction() {
+ delete this.callBarCallAction;
+ return this.callBarCallAction =
+ document.getElementById('keypad-callbar-call-action');
+ },
+
+ get callBarCancelAction() {
+ delete this.callBarCancelAction;
+ return this.callBarCancelAction =
+ document.getElementById('keypad-callbar-cancel');
+ },
+
+ get deleteButton() {
+ delete this.deleteButton;
+ return this.deleteButton = document.getElementById('keypad-delete');
+ },
+
+ get hideBarHangUpAction() {
+ delete this.hideBarHangUpAction;
+ return this.hideBarHangUpAction =
+ document.getElementById('keypad-hidebar-hang-up-action-wrapper');
+ },
+
+ get hideBarHideAction() {
+ delete this.hideBarHideAction;
+ return this.hideBarHideAction =
+ document.getElementById('keypad-hidebar-hide-keypad-action');
+ },
+
+ init: function kh_init() {
+ // Update the minimum phone number phone size.
+ // The UX team states that the minimum font size should be
+ // 10pt. First off, we convert it to px multiplying it 0.226 times,
+ // then we convert it to rem multiplying it a number of times equal
+ // to the font-size property of the body element.
+ var defaultFontSize = window.getComputedStyle(document.body, null)
+ .getPropertyValue('font-size');
+ minFontSize = parseInt(parseInt(defaultFontSize) * 10 * 0.226);
+
+ this.phoneNumberView.value = '';
+ this._phoneNumber = '';
+
+ var keyHandler = this.keyHandler.bind(this);
+ this.keypad.addEventListener('mousedown', keyHandler, true);
+ this.keypad.addEventListener('mouseup', keyHandler, true);
+ this.deleteButton.addEventListener('mousedown', keyHandler);
+ this.deleteButton.addEventListener('mouseup', keyHandler);
+
+ // The keypad add contact bar is only included in the normal version of
+ // the keypad.
+ if (this.callBarAddContact) {
+ this.callBarAddContact.addEventListener('mouseup',
+ this.addContact.bind(this));
+ }
+
+ // The keypad add contact bar is only included in the normal version and
+ // the emergency call version of the keypad.
+ if (this.callBarCallAction) {
+ this.callBarCallAction.addEventListener('mouseup',
+ this.makeCall.bind(this));
+ }
+
+ // The keypad cancel bar is only the emergency call version of the keypad.
+ if (this.callBarCancelAction) {
+ this.callBarCancelAction.addEventListener('mouseup', function() {
+ window.parent.LockScreen.switchPanel();
+ });
+ }
+
+ // The keypad hide bar is only included in the on call version of the
+ // keypad.
+ if (this.hideBarHideAction) {
+ this.hideBarHideAction.addEventListener('mouseup',
+ this.callbarBackAction);
+ }
+
+ if (this.hideBarHangUpAction) {
+ this.hideBarHangUpAction.addEventListener('mouseup',
+ this.hangUpCallFromKeypad);
+ }
+
+ TonePlayer.init();
+
+ this.render();
+ },
+
+ moveCaretToEnd: function hk_util_moveCaretToEnd(el) {
+ if (typeof el.selectionStart == 'number') {
+ el.selectionStart = el.selectionEnd = el.value.length;
+ } else if (typeof el.createTextRange != 'undefined') {
+ el.focus();
+ var range = el.createTextRange();
+ range.collapse(false);
+ range.select();
+ }
+ },
+
+ render: function hk_render(layoutType) {
+ if (layoutType == 'oncall') {
+ this._onCall = true;
+ var numberNode = CallScreen.activeCall.querySelector('.number');
+ this._phoneNumber = numberNode.textContent;
+ this.phoneNumberViewContainer.classList.add('keypad-visible');
+ if (this.callBar) {
+ this.callBar.classList.add('hide');
+ }
+
+ if (this.hideBar) {
+ this.hideBar.classList.remove('hide');
+ }
+
+ this.deleteButton.classList.add('hide');
+ } else {
+ this.phoneNumberViewContainer.classList.remove('keypad-visible');
+ if (this.callBar) {
+ this.callBar.classList.remove('hide');
+ }
+
+ if (this.hideBar) {
+ this.hideBar.classList.add('hide');
+ }
+
+ this.deleteButton.classList.remove('hide');
+ }
+ },
+
+ makeCall: function hk_makeCall(event) {
+ event.stopPropagation();
+
+ if (this._phoneNumber != '') {
+ CallHandler.call(KeypadManager._phoneNumber);
+ }
+ },
+
+ addContact: function hk_addContact(event) {
+ var number = this._phoneNumber;
+ if (!number)
+ return;
+
+ try {
+ var activity = new MozActivity({
+ name: 'new',
+ data: {
+ type: 'webcontacts/contact',
+ params: {
+ 'tel': number
+ }
+ }
+ });
+ } catch (e) {
+ console.log('WebActivities unavailable? : ' + e);
+ }
+ },
+
+ callbarBackAction: function hk_callbarBackAction(event) {
+ CallScreen.hideKeypad();
+ },
+
+ hangUpCallFromKeypad: function hk_hangUpCallFromKeypad(event) {
+ CallScreen.views.classList.remove('show');
+ OnCallHandler.end();
+ },
+
+ formatPhoneNumber: function kh_formatPhoneNumber(mode) {
+ switch (mode) {
+ case 'dialpad':
+ var fakeView = this.fakePhoneNumberView;
+ var view = this.phoneNumberView;
+
+ // We consider the case where the delete button may have
+ // been used to delete the whole phone number.
+ if (view.value == '') {
+ view.style.fontSize = view.dataset.size;
+ return;
+ }
+ break;
+
+ case 'on-call':
+ var fakeView = CallScreen.activeCall.querySelector('.fake-number');
+ var view = CallScreen.activeCall.querySelector('.number');
+ break;
+ }
+
+ var computedStyle = window.getComputedStyle(view, null);
+ var currentFontSize = computedStyle.getPropertyValue('font-size');
+ if (!('size' in view.dataset)) {
+ view.dataset.size = currentFontSize;
+ }
+
+ var newFontSize = this.getNextFontSize(view, fakeView,
+ parseInt(view.dataset.size),
+ parseInt(currentFontSize));
+ view.style.fontSize = newFontSize + 'px';
+ this.addEllipsis(view, fakeView, newFontSize);
+ },
+
+ addEllipsis: function kh_addEllipsis(view, fakeView, currentFontSize) {
+ var viewWidth = view.getBoundingClientRect().width;
+ fakeView.style.fontSize = currentFontSize + 'px';
+ fakeView.innerHTML = view.value;
+
+ var counter = 1;
+ var value = view.value;
+
+ var newPhoneNumber;
+ while (fakeView.getBoundingClientRect().width > viewWidth) {
+ newPhoneNumber = '\u2026' + value.substr(-value.length + counter);
+ fakeView.innerHTML = newPhoneNumber;
+ counter++;
+ }
+
+ if (newPhoneNumber) {
+ view.value = newPhoneNumber;
+ }
+ },
+
+ getNextFontSize: function kh_getNextFontSize(view, fakeView,
+ fontSize, initialFontSize) {
+ var viewWidth = view.getBoundingClientRect().width;
+ fakeView.style.fontSize = fontSize + 'px';
+ fakeView.innerHTML = view.value;
+
+ var rect = fakeView.getBoundingClientRect();
+ while ((rect.width > viewWidth) && (fontSize > minFontSize)) {
+ fontSize = Math.max(fontSize - kFontStep, minFontSize);
+ fakeView.style.fontSize = fontSize + 'px';
+ rect = fakeView.getBoundingClientRect();
+ }
+
+ if ((rect.width < viewWidth) && (fontSize < initialFontSize)) {
+ fakeView.style.fontSize = (fontSize + kFontStep) + 'px';
+ rect = fakeView.getBoundingClientRect();
+ if (rect.width <= viewWidth) {
+ fontSize += kFontStep;
+ }
+ }
+ return fontSize;
+ },
+
+ keyHandler: function kh_keyHandler(event) {
+ var key = event.target.dataset.value;
+
+ if (!key)
+ return;
+
+ event.stopPropagation();
+ if (event.type == 'mousedown') {
+ this._longPress = false;
+
+ if (key != 'delete') {
+ if (keypadSoundIsEnabled) {
+ TonePlayer.play(gTonesFrequencies[key]);
+ }
+
+ // Sending the DTMF tone if on a call
+ var telephony = navigator.mozTelephony;
+ if (telephony && telephony.active &&
+ telephony.active.state == 'connected') {
+
+ telephony.startTone(key);
+ window.setTimeout(function ch_stopTone() {
+ telephony.stopTone();
+ }, 100);
+
+ }
+ }
+
+ // Manage long press
+ if (key == '0' || key == 'delete') {
+ this._holdTimer = setTimeout(function(self) {
+ if (key == 'delete') {
+ self._phoneNumber = '';
+ } else {
+ self._phoneNumber += '+';
+ }
+
+ self._longPress = true;
+ self._updatePhoneNumberView();
+ }, 400, this);
+ }
+
+ // Voicemail long press (needs to be longer since it actually dials)
+ if (event.target.dataset.voicemail) {
+ this._holdTimer = setTimeout(function vm_call(self) {
+ self._longPress = true;
+ self._callVoicemail();
+ }, 3000, this);
+ }
+ } else if (event.type == 'mouseup') {
+ // If it was a long press our work is already done
+ if (this._longPress) {
+ this._longPress = false;
+ this._holdTimer = null;
+ return;
+ }
+ if (key == 'delete') {
+ this._phoneNumber = this._phoneNumber.slice(0, -1);
+ } else {
+ this._phoneNumber += key;
+ }
+
+ if (this._holdTimer)
+ clearTimeout(this._holdTimer);
+
+ this._updatePhoneNumberView();
+ }
+ },
+
+ updatePhoneNumber: function kh_updatePhoneNumber(number) {
+ this._phoneNumber = number;
+ this._updatePhoneNumberView();
+ },
+
+ _updatePhoneNumberView: function kh_updatePhoneNumberview() {
+ var phoneNumber = this._phoneNumber;
+
+ // If there are digits in the phone number, show the delete button.
+ var visibility = (phoneNumber.length > 0) ? 'visible' : 'hidden';
+ this.deleteButton.style.visibility = visibility;
+
+ if (this._onCall) {
+ var view = CallScreen.activeCall.querySelector('.number');
+ view.textContent = phoneNumber;
+ this.formatPhoneNumber('on-call');
+ } else {
+ this.phoneNumberView.value = phoneNumber;
+ this.moveCaretToEnd(this.phoneNumberView);
+ this.formatPhoneNumber('dialpad');
+ }
+ },
+
+ _callVoicemail: function kh_callVoicemail() {
+ var voicemail = navigator.mozVoicemail;
+ if (voicemail && voicemail.number) {
+ CallHandler.call(voicemail.number);
+ }
+ }
+};
diff --git a/apps/system/emergency-call/style/dialer.css b/apps/system/emergency-call/style/dialer.css
new file mode 100644
index 0000000..7a3519a
--- /dev/null
+++ b/apps/system/emergency-call/style/dialer.css
@@ -0,0 +1,250 @@
+html, body {
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ margin: 0;
+ color: white;
+ font-family: 'MozTT', sans-serif;
+ font-size: 10px;
+ background: black;
+}
+
+a {
+ outline: 0;
+}
+
+a:hover, a:active, a:focus {
+ outline: 0;
+}
+
+html * {
+ overflow: hidden;
+}
+
+.font-regular {
+ font-family: 'MozTT';
+}
+
+.font-semibold {
+ font-family: 'MozTT';
+ font-weight: 600;
+}
+
+.font-light {
+ font-family: 'MozTT';
+}
+
+.contact-primary-info {
+ font-size: -moz-calc(15*0.226rem);
+ color: black;
+}
+
+.contact-secondary-info {
+ font-size: -moz-calc(6*0.226rem);
+ color: white;
+}
+
+.grid-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+.grid-v-align {
+ vertical-align: middle;
+}
+
+.grid-row {
+ display: table-row;
+}
+
+.grid-cell {
+ display: table-cell;
+}
+
+.grid {
+ display: table;
+ table-layout: fixed;
+}
+
+.center {
+ text-align: center;
+}
+
+#views {
+ top: 0;
+ height: 100%;
+ width: 100%;
+}
+
+#views > *[role=tabpanel] {
+ height: 100%;
+ width: 100%;
+}
+
+body.hidden *[data-l10n-id] {
+ visibility: hidden;
+}
+
+/* Call screen */
+#call-screen {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ border: 0;
+ border-radius: 10px;
+ background: black;
+ -moz-transform: translateY(-100%);
+ z-index: 100;
+
+ -moz-transition: -moz-transform 0.5s ease;
+}
+
+#call-screen.displayed {
+ -moz-transform: translateY(0);
+}
+
+#main-container {
+ position: relative;
+ height: 100%;
+ background: transparent;
+}
+
+#actions-container {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ height: 15.5rem;
+}
+
+#call-options {
+ height:9.5rem;
+}
+
+#co-advanced {
+ opacity: 1.0;
+ height: 9.5rem;
+}
+
+.co-advanced-option {
+ background: rgba(0,0,0,.8);
+ height: 9.5rem;
+ width: 100%;
+ border: 0;
+ border-top: 1px solid #3A3A3A;
+ border-bottom: 1px solid #3A3A3A;
+ border-right: 1px solid #3A3A3A;
+}
+
+#co-advanced span.grid-cell:last-child .co-advanced-option {
+ border-right: 0px;
+}
+
+#speaker span {
+ display:inline-block;
+ background-color: #DDD;
+ background:url('images/ActionIcon_40x40_bluetooth.png') ;
+ background-size: 4rem 4rem;
+ width:4rem;
+ height:4rem;
+ opacity: 1.0;
+}
+
+#speaker.speak > span {
+ background:url('images/ActionIcon_40x40_bluetooth_active.png');
+}
+
+#callbar {
+ background:rgba(0,0,0,.8);
+ opacity: 1.0;
+}
+
+#callbar-hang-up {
+ float: left;
+ height: 6.5rem;
+ width: 100%;
+}
+
+.callbar-button {
+ height: 4rem;
+ border:0;
+ border-radius:.3rem;
+ display: block;
+}
+
+#callbar-hang-up-action {
+ background: -moz-linear-gradient(top, #ff0000 1%, #ce0000 100%);
+ opacity: 1.0;
+ margin: 1rem .5rem 1.5rem 1.5rem;
+}
+
+#callbar-hang-up.full-space > #callbar-hang-up-action {
+ margin: 1rem 1.5rem 1.5rem 1.5rem;
+}
+
+#callbar-hang-up-action > div {
+ margin: 0 auto;
+ background-image: url('images/ActionIcon_40x40_hangup.png');
+ background-repeat: no-repeat;
+ background-size: 4rem 4rem;
+ background-position: center;
+ width: 4rem;
+ height: 4rem;
+}
+
+#calls {
+ position: absolute;
+ top: 0;
+ width: 100%;
+ height: 22rem;
+
+ z-index: 500;
+}
+
+#calls > section {
+ position: relative;
+ height: 9rem;
+
+ font-size: 1.8em;
+ line-height: 7rem;
+ background-color: #01c5ed;
+
+ transition: opacity 0.3s linear;
+ opacity: 1;
+}
+
+#calls > section div {
+ padding-left: 2rem;
+ padding-right: 1.5rem;
+}
+
+#calls > section .number {
+ height: 4rem;
+ padding: 2rem 2rem 0 2rem;
+ background: #01c5ed;
+ font-size: 1.6em;
+ line-height: 4rem;
+ color: black;
+}
+
+#calls > section .additionalContactInfo {
+ height: 2rem;
+ padding: 0 2rem 2rem 2rem;
+ background: #01c5ed;
+ font-size: 1.4rem;
+ line-height: 2rem;
+ color: white;
+}
+
+#calls > section .duration {
+ position: absolute;
+ top: 12rem;
+ left: 0;
+ height: 8rem;
+ padding: 2rem;
+ font-size: 2.6em;
+ font-weight: 300;
+ line-height: 8rem;
+}
diff --git a/apps/system/emergency-call/style/images/ActionIcon_40x40_bluetooth.png b/apps/system/emergency-call/style/images/ActionIcon_40x40_bluetooth.png
new file mode 100644
index 0000000..a946ff2
--- /dev/null
+++ b/apps/system/emergency-call/style/images/ActionIcon_40x40_bluetooth.png
Binary files differ
diff --git a/apps/system/emergency-call/style/images/ActionIcon_40x40_bluetooth_active.png b/apps/system/emergency-call/style/images/ActionIcon_40x40_bluetooth_active.png
new file mode 100644
index 0000000..86abf23
--- /dev/null
+++ b/apps/system/emergency-call/style/images/ActionIcon_40x40_bluetooth_active.png
Binary files differ
diff --git a/apps/system/emergency-call/style/images/ActionIcon_40x40_hangup.png b/apps/system/emergency-call/style/images/ActionIcon_40x40_hangup.png
new file mode 100644
index 0000000..f955956
--- /dev/null
+++ b/apps/system/emergency-call/style/images/ActionIcon_40x40_hangup.png
Binary files differ
diff --git a/apps/system/emergency-call/style/images/ActionIcon_40x40_pickup.png b/apps/system/emergency-call/style/images/ActionIcon_40x40_pickup.png
new file mode 100644
index 0000000..ad8423e
--- /dev/null
+++ b/apps/system/emergency-call/style/images/ActionIcon_40x40_pickup.png
Binary files differ
diff --git a/apps/system/emergency-call/style/images/asterisk.png b/apps/system/emergency-call/style/images/asterisk.png
new file mode 100644
index 0000000..4199485
--- /dev/null
+++ b/apps/system/emergency-call/style/images/asterisk.png
Binary files differ
diff --git a/apps/system/emergency-call/style/images/dialer_icon_delete.png b/apps/system/emergency-call/style/images/dialer_icon_delete.png
new file mode 100644
index 0000000..8e842cd
--- /dev/null
+++ b/apps/system/emergency-call/style/images/dialer_icon_delete.png
Binary files differ
diff --git a/apps/system/emergency-call/style/images/sharp.png b/apps/system/emergency-call/style/images/sharp.png
new file mode 100644
index 0000000..36033bf
--- /dev/null
+++ b/apps/system/emergency-call/style/images/sharp.png
Binary files differ
diff --git a/apps/system/emergency-call/style/keypad.css b/apps/system/emergency-call/style/keypad.css
new file mode 100644
index 0000000..ea9fb90
--- /dev/null
+++ b/apps/system/emergency-call/style/keypad.css
@@ -0,0 +1,301 @@
+/*
+ * The code is being shared between system/emergency-call/js/keypad.js
+ * and dialer/js/keypad.js. Be sure to update both file when you commit!
+ *
+ */
+
+.keypad-text {
+ font-size: -moz-calc(6*0.226rem);
+ color: #96AAB4;
+}
+
+#keyboard-view {
+ width: 100%;
+ height: 100%;
+}
+
+#fake-phone-number-view {
+ position: absolute;
+ line-height: 0;
+ visibility: hidden;
+}
+
+#phone-number-view-container {
+ width: 100%;
+ height: -moz-calc(100% - 34.5rem);
+ background: #242B36;
+ text-align: center;
+ display: table;
+ table-layout: fixed;
+ border-spacing: 1.5rem 0rem;
+ font-family: 'MozTT';
+ font-weight: 300;
+}
+
+#phone-number-view-container.keypad-visible {
+ height: -moz-calc(100% - 35rem);
+ visibility: hidden;
+}
+
+#phone-number-view {
+ width: 100%;
+ border: 0;
+ background: transparent;
+ text-align: left;
+ cursor: none;
+ -moz-user-select: none;
+}
+
+#keypad-delete {
+ text-align: center;
+ width: 4rem;
+ visibility: hidden;
+}
+
+#keypad-delete:active {
+ opacity: 0.7;
+}
+
+#keypad-delete > div {
+ width: 3.8rem;
+ height: 2.8rem;
+ background: url('images/dialer_icon_delete.png') ;
+ background-size: 3.8rem 2.8rem;
+ background-repeat: no-repeat;
+}
+
+#keyboard-container {
+ width: 100%;
+ height: 34.5rem;
+}
+
+#keypad {
+ background: -moz-linear-gradient(top, #191E25 0%, #080B0D 100%);
+ height: -moz-calc(100% - 10rem);
+ width: 100%;
+ display: table;
+ table-layout: fixed;
+}
+
+.keypad-cell {
+ display: table-cell;
+ border-right: 1px solid #6F6F6F;
+ border-top: 1px solid #6F6F6F;;
+}
+
+.keypad-cell:last-child {
+ border-right: 0;
+}
+
+.keypad-key {
+ border: 0;
+ border-bottom: 1px solid #6F6F6F;
+ height: 7rem;
+ vertical-align: middle;
+ position: relative;
+}
+
+.keypad-key:active {
+ background: black;
+ opacity: 0.7;
+}
+
+.keypad-key-label-container {
+ width: 100%;
+ height: 100%;
+ display: table;
+}
+
+.keypad-key-label {
+ display: table-cell;
+ padding-left: 1.5rem;
+ vertical-align: middle;
+}
+
+.keypad-key-label *,
+#keypad-delete * {
+ pointer-events: none;
+}
+
+.keypad-key-label-centered {
+ padding-left: 0;
+ text-align: center;
+}
+
+.font-size-plus {
+ font-size: 2rem;
+}
+
+.keypad-subicon {
+ background-repeat: no-repeat;
+ background-position: center bottom;
+
+ -moz-user-select: none;
+ pointer-events: none;
+
+ position: absolute;
+ left: 3.75rem;
+ bottom: 0.75rem;
+
+ width: 3rem;
+ height: 3rem;
+}
+
+.voicemail {
+ background-image: url('images/voicemail.png');
+}
+
+.asterisk {
+ background-image: url('images/asterisk.png');
+ background-repeat: no-repeat;
+ height: 3rem;
+ width: 3rem;
+ background-size: 3rem 3rem;
+ background-position: center;
+ margin: auto;
+ pointer-events: none;
+}
+
+.sharp {
+ background-image: url('images/sharp.png');
+ background-repeat: no-repeat;
+ height: 3rem;
+ width: 3rem;
+ background-size: 3rem 3rem;
+ background-position: center;
+ margin: auto;
+ pointer-events: none;
+}
+
+#keypad-callbar {
+ background: black;
+ height: 6.5rem;
+ width: 100%;
+ display: table;
+ table-layout: fixed;
+ border-spacing: 1rem 1rem;
+}
+
+#keypad-callbar-add-contact,
+#keypad-callbar-cancel {
+ display: table-cell;
+ width: 9rem;
+ background: -moz-linear-gradient(top, #242b36 0%, #19191a 100%);
+ border: .1rem solid #242B36;
+ border-radius: .2rem;
+ vertical-align: middle;
+}
+
+#keypad-callbar-cancel {
+ width: 10rem;
+}
+
+#keypad-callbar-cancel:active {
+ opacity: 0.7;
+}
+
+#keypad-callbar-cancel > div {
+ text-align: center;
+ font: 2rem 'MozTT';
+}
+
+#keypad-callbar-call-action {
+ display: table-cell;
+ width: 100%;
+ background: #84c82c;
+ border: 0;
+ border-radius: .2rem;
+ background: -moz-linear-gradient(top, #84c82c 0%, #5f9b0a 100%);
+ vertical-align: middle;
+}
+
+#keypad-callbar-call-action:active {
+ opacity: 0.7;
+}
+
+.icon-add-contact {
+ margin: auto;
+ width: 4rem;
+ height: 4rem;
+ background-image: url("images/ActionIcon_40x40_addcontact.png");
+ background-repeat: no-repeat;
+ background-size: 4rem 4rem;
+ background-position: center;
+}
+
+#keypad-callbar-call-action > div {
+ margin: auto;
+ width: 4rem;
+ height: 4rem;
+ background-image: url("images/ActionIcon_40x40_pickup.png");
+ background-repeat: no-repeat;
+ background-size: 4rem 4rem;
+ background-position: center;
+}
+
+#keypad-hidebar {
+ background: rgba(0,0,0,.8);
+ opacity: 1.0;
+}
+
+#keypad-hidebar-hang-up-action-wrapper {
+ float: left;
+ height: 6.5rem;
+ width: 50%;
+}
+
+#keypad-hidebar-hide-keypad-action-wrapper {
+ height: 6.5rem;
+ width: 50%;
+}
+
+.keypad-hidebar-button {
+ height: 4rem;
+ border: 0;
+ border-radius:.3rem;
+ display: block;
+}
+
+#keypad-hidebar-hang-up-action {
+ background: -moz-linear-gradient(top, #ff0000 0%, #ce0000 100%);
+ opacity: 1.0;
+ margin: 1rem .5rem 1.5rem 1.5rem;
+}
+
+#keypad-hidebar-hang-up-action > div {
+ margin: 0 auto;
+ background-image: url('images/ActionIcon_40x40_hangup.png');
+ background-repeat: no-repeat;
+ background-size: 4rem 4rem;
+ background-position: center;
+ width: 4rem;
+ height: 4rem;
+}
+
+#keypad-hidebar-hide-keypad-action {
+ background: -moz-linear-gradient(top, #6A6A6A 0%, #3E3E3E 100%);
+ opacity: 1.0;
+ margin: 1rem 1.5rem 1.5rem .5rem;
+}
+
+#keypad-hidebar-hide-keypad-action > div {
+ margin: -moz-calc((4rem - 3rem)/2) auto;
+ background-image: url('images/ActionIcons_30x30_dismiss_keyboard.png');
+ background-repeat: no-repeat;
+ background-size: 3rem 3rem;
+ background-position: center;
+ width: 3rem;
+ height: 3rem;
+}
+
+.phone-number-font {
+ font-size:-moz-calc(18*0.226rem);
+ color: white;
+ font-family:'MozTT';
+}
+
+.keypad-number {
+ font-size: -moz-calc(25*0.226rem);
+ color: white;
+}
+