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.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
26
assets/webapps/costcontrol.gaiamobile.org/debug.html
Normal file
26
assets/webapps/costcontrol.gaiamobile.org/debug.html
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<!-- XXX: Only available if DEBUGGING === true -->
|
||||
<header>
|
||||
<h2>Development</h2>
|
||||
</header>
|
||||
<ul class="settings">
|
||||
<li>
|
||||
<gaia-switch class="settings-option" data-option="fte">
|
||||
<label>Enable first time experience</label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
<li>
|
||||
<gaia-switch class="settings-option" data-option="lowLimitNotified">
|
||||
<label>Low limit already notified</label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
<li>
|
||||
<gaia-switch class="settings-option" data-option="zeroBalanceNotified">
|
||||
<label>Zero balance already notified</label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
<li>
|
||||
<gaia-switch class="settings-option" data-option="dataUsageNotified">
|
||||
<label>Data usage already notified</label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<element name="appdetail-view" extends="section">
|
||||
<template>
|
||||
<gaia-header action="back">
|
||||
<h1>{{localized-app-name}}</h1>
|
||||
</gaia-header>
|
||||
|
||||
<div class="view-scroll">
|
||||
<section class="usage fade">
|
||||
<section id="app-graphic-area" class="graph" role="img" aria-labelledby="app-axis-layer app-today-layer app-limits-layer app-warning-layer">
|
||||
<canvas id="app-background-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-wifi-layer" hidden aria-hidden="true"></canvas>
|
||||
<canvas id="app-mobile-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-axis-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-today-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-warning-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-limits-layer" aria-hidden="true"></canvas>
|
||||
<img hidden alt="" src="./style/images/app/ui/datausage/pattern.png" id="app-graphic-pattern" />
|
||||
</section>
|
||||
|
||||
<p class="info" data-l10n-id="data-used-since" hidden>
|
||||
{{amount}} of data used since {{start-date}}
|
||||
</p>
|
||||
<p class="info" data-l10n-id="data-used-this-week" hidden>
|
||||
{{amount}} of data used this week
|
||||
</p>
|
||||
<p class="info" data-l10n-id="data-used-this-month" hidden>
|
||||
{{amount}} of data used this month
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" defer src="js/views/appdetail.js"></script>
|
||||
</template>
|
||||
</element>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<element name="balance-tab" extends="section">
|
||||
<template>
|
||||
|
||||
<section class="content">
|
||||
|
||||
<div id="cost-control-topup-countdown" class="countdown" hidden>
|
||||
<p>
|
||||
<span id="top-up-countdown">
|
||||
00:00
|
||||
</span>
|
||||
|
||||
<span data-l10n-id="top-up-in-progress2">
|
||||
Your top-up is being processed.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="cost-control-message-area" class="error-messages" hidden>
|
||||
<p id="error-message-placeholder">
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="cost-control-info-area" class="overview">
|
||||
<ul class="buttons-list end">
|
||||
<li>
|
||||
<button class="icon icon-reload" id="balance-tab-update-button" data-l10n-id="update-button">
|
||||
Update
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="info">
|
||||
<div id="cost-control-icon" class="icons">
|
||||
<span class="warning">
|
||||
</span>
|
||||
<progress>
|
||||
</progress>
|
||||
</div>
|
||||
<p id="balance-tab-credit">
|
||||
</p>
|
||||
<p id="balance-tab-time">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="buttons-list">
|
||||
<li>
|
||||
<button class="icon icon-topup" id="balance-tab-topup-ussd-button" data-l10n-id="topup-ussd-button2" hidden>
|
||||
Open top-up menu
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="icon icon-topupcode" id="balance-tab-topup-button" data-l10n-id="topup-button2" hidden>
|
||||
Use top-up code
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<script type="text/javascript" defer src="js/views/balance.js"></script>
|
||||
</section>
|
||||
|
||||
</template>
|
||||
</element>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<element name="datausage-tab" extends="section">
|
||||
<template>
|
||||
|
||||
<div class="view-scroll">
|
||||
<section class="content">
|
||||
<section id="graphic-area" class="graph" role="img" aria-labelledby="axis-layer today-layer limits-layer warning-layer">
|
||||
<canvas id="background-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="wifi-layer" hidden aria-hidden="true"></canvas>
|
||||
<canvas id="mobile-layer" hidden aria-hidden="true"></canvas>
|
||||
<canvas id="axis-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="today-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="warning-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="limits-layer" aria-hidden="true"></canvas>
|
||||
<img hidden alt="" src="./style/images/app/ui/datausage/pattern.png" id="graphic-pattern" />
|
||||
</section>
|
||||
|
||||
<ul class="toggle-data" data-type="list">
|
||||
<li id="mobileItem">
|
||||
<gaia-checkbox id="mobileCheck">
|
||||
<label>
|
||||
<span class="data-origin-label" data-l10n-id="mobile-usage"></span>
|
||||
<span class="overview" id="mobileOverview"></span>
|
||||
<span></span>
|
||||
</label>
|
||||
</gaia-checkbox>
|
||||
</li>
|
||||
<li id="wifiItem">
|
||||
<gaia-checkbox id="wifiCheck">
|
||||
<label>
|
||||
<span class="data-origin-label" data-l10n-id="wifi-usage">-</span>
|
||||
<span class="overview" id="wifiOverview"></span>
|
||||
<span></span>
|
||||
</label>
|
||||
</gaia-checkbox>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<header id="app-usage-header">
|
||||
<h2 data-l10n-id="app-usage-list-header">Mobile App Usage</h2>
|
||||
</header>
|
||||
|
||||
<div id="app-usage-no-data" data-l10n-id="app-usage-no-data" hidden>
|
||||
You have not used any mobile data yet. Usage for each application will
|
||||
show up here when you do.
|
||||
</div>
|
||||
|
||||
<ul id="app-usage-list">
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<script type="text/javascript" defer src="js/views/datausage.js"></script>
|
||||
|
||||
</template>
|
||||
</element>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<element name="telephony-tab" extends="section">
|
||||
<template>
|
||||
|
||||
<section>
|
||||
<ul>
|
||||
<li>
|
||||
<p id="telephony-time">
|
||||
</p>
|
||||
<dl>
|
||||
<dt data-l10n-id="call-made">
|
||||
Call made
|
||||
</dt>
|
||||
<dd>
|
||||
<span id="telephony-calltime">
|
||||
</span>
|
||||
</dd>
|
||||
<dt data-l10n-id="sms-sent">
|
||||
SMS Sent
|
||||
</dt>
|
||||
<dd>
|
||||
<span id="telephony-smscount">
|
||||
</span>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li id="billing-cycle">
|
||||
<dl>
|
||||
<dt data-l10n-id="billing-cycle-ends">Billing cycle ends</dt>
|
||||
<dd><time id="reset-date">26 Dec</time></dd>
|
||||
</dl>
|
||||
<p class="meta" data-l10n-id="tracking-will-reset">Tracking will reset on this date</p>
|
||||
</li>
|
||||
</ul>
|
||||
<script type="text/javascript" defer src="js/views/telephony.js"></script>
|
||||
</section>
|
||||
|
||||
</template>
|
||||
</element>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<element name="topup-dialog" extends="section">
|
||||
<template>
|
||||
|
||||
<gaia-header id="topup-header" action="close">
|
||||
<h1 data-l10n-id="top-up"></h1>
|
||||
<button id="topup-send-button" data-l10n-id="send">Send</button>
|
||||
</gaia-header>
|
||||
<section class="content">
|
||||
<div class="info">
|
||||
<h2 data-l10n-id="enter-top-up-code">
|
||||
Enter the top up code
|
||||
</h2>
|
||||
<p id="topup-code-explanation" data-l10n-id="top-up-code-explanation2">
|
||||
Find it on the scratch card or directly in your receipt.
|
||||
</p>
|
||||
<p id="topup-incorrect-code" hidden data-l10n-id="incorrect-code2">
|
||||
Make sure the code is correct and try again.
|
||||
</p>
|
||||
<p id="topup-error" hidden data-l10n-id="topup-error2">
|
||||
There was a problem sending the code. Please, try again.
|
||||
</p>
|
||||
<section hidden class="loading" id="topup-in-progress">
|
||||
<progress>
|
||||
</progress>
|
||||
<p data-l10n-id="wait-for-confirmation">
|
||||
You'll receive a confirmation message
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
<form>
|
||||
<input id="topup-code-input" type="number" />
|
||||
</form>
|
||||
|
||||
</template>
|
||||
</element>
|
||||
479
assets/webapps/costcontrol.gaiamobile.org/fte.html
Normal file
479
assets/webapps/costcontrol.gaiamobile.org/fte.html
Normal file
|
|
@ -0,0 +1,479 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en-US" dir="ltr">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-color" content="#eeeeee">
|
||||
<title data-l10n-id="fte">Usage First Time Experience</title>
|
||||
|
||||
<!-- Building blocks -->
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/buttons.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/input_areas.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/layout.css">
|
||||
|
||||
<!-- App and Views -->
|
||||
<link rel="stylesheet" type="text/css" href="style/app.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/settings.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/firsttime.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/datalimits.css">
|
||||
|
||||
<!-- Gaia Components -->
|
||||
<link rel="stylesheet" type="text/css" href="app://theme.gaiamobile.org/shared/elements/gaia-theme/gaia-theme.css">
|
||||
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia-icons/gaia-icons.css">
|
||||
|
||||
<!-- Localization -->
|
||||
<meta name="defaultLanguage" content="en-US">
|
||||
<meta name="availableLanguages" content="ar:201601260729, bg:201601260729, bn-BD:201601260729, ca:201601260729, cs:201601260729, da:201601260729, de:201601260729, el:201601260729, en-US:201601260729, es:201601260729, eu:201601260729, fr:201601260729, gl:201601260729, hr:201601260729, hu:201601260729, it:201601260729, ja:201601260729, km:201601260729, ko:201601260729, lt:201601260729, mk:201601260729, ms:201601260729, ne-NP:201601260729, nl:201601260729, pa:201601260729, pl:201601260729, pt-BR:201601260729, ro:201601260729, ru:201601260729, sk:201601260729, sq:201601260729, sr-Cyrl:201601260729, sr-Latn:201601260729, sv-SE:201601260729, tr:201601260729, zh-CN:201601260729, zh-TW:201601260729">
|
||||
<link rel="localization" href="/locales-obj/fte.{locale}.json">
|
||||
|
||||
|
||||
<!-- Firefox Desktop shims -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Shared code -->
|
||||
<!-- <script type="text/javascript" src="shared/js/l10n.js"></script> -->
|
||||
<!-- <script type="text/javascript" defer="" src="shared/js/format.js"></script> -->
|
||||
<!-- <script type="text/javascript" src="shared/js/async_storage.js"></script> -->
|
||||
<!-- <script type="text/javascript" src="shared/js/settings_listener.js"></script> -->
|
||||
<!-- <script type="text/javascript" src="shared/js/lazy_loader.js"></script> --><script src="./gaia_build_fte.js" type="text/javascript"></script>
|
||||
|
||||
<!-- Gaia Components -->
|
||||
<!-- <script defer="" src="/shared/elements/config.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/js/component_utils.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/elements/gaia-header/dist/gaia-header.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/elements/gaia_buttons/script.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/elements/gaia_select/script.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/elements/gaia_switch/script.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/elements/gaia_radio/script.js"></script> -->
|
||||
|
||||
<!-- Specific code -->
|
||||
<!-- <script type="text/javascript" defer="" src="js/fte.js"></script> --><script src="./gaia_build_defer_fte.js" defer="" type="text/javascript"></script>
|
||||
<meta content="2.5" name="appVersion"></head>
|
||||
|
||||
<body role="application" class="theme-settings skin-organic">
|
||||
|
||||
<!-- First time experience -->
|
||||
<section id="firsttime-view" class="view step-1">
|
||||
|
||||
<!-- Global Step 1 -->
|
||||
<section role="region" class="view step" data-viewport="" id="step-1">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="fte-welcome-title">Welcome</h1>
|
||||
</gaia-header>
|
||||
<section class="content vbox">
|
||||
<div class="authed-sim" hidden="">
|
||||
<h2 data-l10n-id="fte-authed-sim">Save money by keeping track of your phone and internet usage.</h2>
|
||||
</div>
|
||||
<div class="nonauthed-sim" hidden="">
|
||||
<h2 data-l10n-id="fte-nonauthed-sim">Save money by keeping track of your internet usage.</h2>
|
||||
</div>
|
||||
<div class="no-sim" hidden="">
|
||||
<h2 data-l10n-id="fte-no-sim">Get clear information about how much internet you’re using.</h2>
|
||||
</div>
|
||||
<p data-l10n-id="fte-sim-info2" class="info">Information shown on Usage comes directly from this device. Check with your mobile service provider for detailed account information.</p>
|
||||
</section>
|
||||
<gaia-buttons>
|
||||
<button class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
|
||||
</gaia-buttons>
|
||||
</section>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<section role="region" class="view step gaia-list" data-viewport="right" id="step-2">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="fte-plantype-title">Type of Contract</h1>
|
||||
</gaia-header>
|
||||
<ul class="content choices">
|
||||
<li class="active">
|
||||
<gaia-radio name="plan" id="prepaid-plan" value="prepaid">
|
||||
<label data-l10n-id="im-prepaid">I’m Pre-paid</label>
|
||||
</gaia-radio>
|
||||
</li>
|
||||
<li class="active">
|
||||
<gaia-radio name="plan" id="postpaid-plan" value="postpaid">
|
||||
<label data-l10n-id="im-postpaid">I’m Post-paid</label>
|
||||
</gaia-radio>
|
||||
</li>
|
||||
<li>
|
||||
<p data-l10n-id="fte-plantype-hint">Select the type of contract you have with your mobile service provider.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<gaia-buttons data-items="2">
|
||||
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
|
||||
<button id="to-step-2" class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
|
||||
</gaia-buttons>
|
||||
</section>
|
||||
|
||||
<!-- Prepaid step 2 -->
|
||||
<section role="region" class="view step gaia-list" data-viewport="right" id="prepaid-step-2">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="fte-prepaid2-title">Low Balance Alert</h1>
|
||||
</gaia-header>
|
||||
<section class="content">
|
||||
<ul class="settings">
|
||||
<li class="active">
|
||||
<gaia-switch id="low-limit" class="settings-option" data-option="lowLimit">
|
||||
<label data-l10n-id="low-balance-alert">Low balance alert</label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<label class="end" for="low-limit-input" data-l10n-id="low-balance-explanation2">When balance is below</label>
|
||||
<div class="low-limit-container hbox middle">
|
||||
<input id="low-limit-input" class="settings-option" data-option="lowLimitThreshold" data-disable-on="lowLimit=false" step="any" type="number">
|
||||
<span id="currency" dir="auto"></span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p data-l10n-id="fte-prepaid2-hint">Set an alert to avoid running out of credit.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<gaia-buttons data-items="2">
|
||||
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
|
||||
<button id="low-limit-next-button" class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
|
||||
</gaia-buttons>
|
||||
</section>
|
||||
|
||||
<!-- Prepaid step 3 -->
|
||||
<section role="region" class="view step gaia-list" data-viewport="right" id="prepaid-step-3">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="fte-prepaid3-title">Data Report and Alert</h1>
|
||||
</gaia-header>
|
||||
<section class="content">
|
||||
<ul class="settings">
|
||||
<li class="vbox">
|
||||
<gaia-select>
|
||||
<label data-l10n-id="reset-report">Reset report</label>
|
||||
<select class="settings-option" data-option="trackingPeriod">
|
||||
<option value="monthly" data-l10n-id="monthly">Monthly</option>
|
||||
<option value="weekly" data-l10n-id="weekly">Weekly</option>
|
||||
<option value="never" data-l10n-id="never">Never</option>
|
||||
</select>
|
||||
</gaia-select>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<gaia-select>
|
||||
<label data-l10n-id="starting-on">Starting on</label>
|
||||
<select id="pre3-select-weekday" class="settings-option" data-option="resetTime" data-hide-on="trackingPeriod!=weekly" data-disable-on="trackingPeriod!=weekly">
|
||||
<option class="monday" value="1" data-l10n-id="monday">Monday</option>
|
||||
<option value="2" data-l10n-id="tuesday">Tuesday</option>
|
||||
<option value="3" data-l10n-id="wednesday">Wednesday</option>
|
||||
<option value="4" data-l10n-id="thursday">Thursday</option>
|
||||
<option value="5" data-l10n-id="friday">Friday</option>
|
||||
<option value="6" data-l10n-id="saturday">Saturday</option>
|
||||
<option class="sunday" value="0" data-l10n-id="sunday">Sunday</option>
|
||||
</select>
|
||||
</gaia-select>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<gaia-select>
|
||||
<label data-l10n-id="starting-on">Starting on</label>
|
||||
<select class="settings-option icon icon-dialog" data-option="resetTime" data-hide-on="trackingPeriod!=monthly" data-disable-on="trackingPeriod!=monthly">
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5">5</option>
|
||||
<option value="6">6</option>
|
||||
<option value="7">7</option>
|
||||
<option value="8">8</option>
|
||||
<option value="9">9</option>
|
||||
<option value="10">10</option>
|
||||
<option value="11">11</option>
|
||||
<option value="12">12</option>
|
||||
<option value="13">13</option>
|
||||
<option value="14">14</option>
|
||||
<option value="15">15</option>
|
||||
<option value="16">16</option>
|
||||
<option value="17">17</option>
|
||||
<option value="18">18</option>
|
||||
<option value="19">19</option>
|
||||
<option value="20">20</option>
|
||||
<option value="21">21</option>
|
||||
<option value="22">22</option>
|
||||
<option value="23">23</option>
|
||||
<option value="24">24</option>
|
||||
<option value="25">25</option>
|
||||
<option value="26">26</option>
|
||||
<option value="27">27</option>
|
||||
<option value="28">28</option>
|
||||
<option value="29">29</option>
|
||||
<option value="30">30</option>
|
||||
<option value="31">31</option>
|
||||
</select>
|
||||
</gaia-select>
|
||||
</li>
|
||||
<li class="active">
|
||||
<gaia-switch class="settings-option" data-option="dataLimit">
|
||||
<label data-l10n-id="data-limit-alert">Data use alert</label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<p data-l10n-id="data-limit-value2">When use is above</p>
|
||||
<button class="settings-option icon icon-dialog" data-widget-type="data-limit" data-disable-on="dataLimit=false" data-hide-on="dataLimit=false">
|
||||
<span class="tag"></span>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<p data-l10n-id="fte-prepaid3-hint">Receive reports about your Internet usage and set an alert to avoid using too much.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<gaia-buttons data-items="2">
|
||||
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
|
||||
<button class="recommend" data-navigation="finish" span="" data-l10n-id="lets-go">Let’s go!</button>
|
||||
</gaia-buttons>
|
||||
</section>
|
||||
|
||||
<!-- Postpaid step 2 -->
|
||||
<section role="region" class="view step gaia-list" data-viewport="right" id="postpaid-step-2">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="fte-postpaid2-title">Phone and Data Report</h1>
|
||||
</gaia-header>
|
||||
<ul class="content settings">
|
||||
<li class="vbox">
|
||||
<gaia-select>
|
||||
<label data-l10n-id="reset-report">Reset report</label>
|
||||
<select class="settings-option" data-option="trackingPeriod">
|
||||
<option value="monthly" data-l10n-id="monthly">Monthly</option>
|
||||
<option value="weekly" data-l10n-id="weekly">Weekly</option>
|
||||
<option value="never" data-l10n-id="never">Never</option>
|
||||
</select>
|
||||
</gaia-select>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<gaia-select>
|
||||
<label data-l10n-id="starting-on">Starting on</label>
|
||||
<select id="post2-select-weekday" class="settings-option" data-option="resetTime" data-hide-on="trackingPeriod!=weekly" data-disable-on="trackingPeriod!=weekly">
|
||||
<option class="monday" value="1" data-l10n-id="monday">Monday</option>
|
||||
<option value="2" data-l10n-id="tuesday">Tuesday</option>
|
||||
<option value="3" data-l10n-id="wednesday">Wednesday</option>
|
||||
<option value="4" data-l10n-id="thursday">Thursday</option>
|
||||
<option value="5" data-l10n-id="friday">Friday</option>
|
||||
<option value="6" data-l10n-id="saturday">Saturday</option>
|
||||
<option class="sunday" value="0" data-l10n-id="sunday">Sunday</option>
|
||||
</select>
|
||||
</gaia-select>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<gaia-select>
|
||||
<label data-l10n-id="starting-on">Starting on</label>
|
||||
<select class="settings-option icon icon-dialog" data-option="resetTime" data-hide-on="trackingPeriod!=monthly" data-disable-on="trackingPeriod!=monthly">
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5">5</option>
|
||||
<option value="6">6</option>
|
||||
<option value="7">7</option>
|
||||
<option value="8">8</option>
|
||||
<option value="9">9</option>
|
||||
<option value="10">10</option>
|
||||
<option value="11">11</option>
|
||||
<option value="12">12</option>
|
||||
<option value="13">13</option>
|
||||
<option value="14">14</option>
|
||||
<option value="15">15</option>
|
||||
<option value="16">16</option>
|
||||
<option value="17">17</option>
|
||||
<option value="18">18</option>
|
||||
<option value="19">19</option>
|
||||
<option value="20">20</option>
|
||||
<option value="21">21</option>
|
||||
<option value="22">22</option>
|
||||
<option value="23">23</option>
|
||||
<option value="24">24</option>
|
||||
<option value="25">25</option>
|
||||
<option value="26">26</option>
|
||||
<option value="27">27</option>
|
||||
<option value="28">28</option>
|
||||
<option value="29">29</option>
|
||||
<option value="30">30</option>
|
||||
<option value="31">31</option>
|
||||
</select>
|
||||
</gaia-select>
|
||||
</li>
|
||||
<li>
|
||||
<p data-l10n-id="fte-postpaid2-hint">Receive reports about your phone and Internet usage.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<gaia-buttons data-items="2">
|
||||
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
|
||||
<button class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
|
||||
</gaia-buttons>
|
||||
</section>
|
||||
|
||||
<!-- Postpaid step 3 -->
|
||||
<section role="region" class="view step gaia-list" data-viewport="right" id="postpaid-step-3">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="fte-postpaid3-title">Data Alert</h1>
|
||||
</gaia-header>
|
||||
<section class="content">
|
||||
<ul class="settings">
|
||||
<li class="active">
|
||||
<gaia-switch class="settings-option" data-option="dataLimit">
|
||||
<label data-l10n-id="data-limit-alert">Data use alert</label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<p data-l10n-id="data-limit-value2">When use is above</p>
|
||||
<button class="settings-option icon icon-dialog" data-widget-type="data-limit" data-disable-on="dataLimit=false" data-hide-on="dataLimit=false">
|
||||
<span class="tag"></span>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<p data-l10n-id="fte-postpaid3-hint">Set an alert to avoid using too much data.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<gaia-buttons data-items="2">
|
||||
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
|
||||
<button class="recommend" data-navigation="finish" data-l10n-id="lets-go">Let’s go!</button>
|
||||
</gaia-buttons>
|
||||
</section>
|
||||
|
||||
<!-- Non VIVO step 2 -->
|
||||
<section role="region" class="view step gaia-list" data-viewport="right" id="non-vivo-step-1">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="fte-onlydata2-title">Data Report</h1>
|
||||
</gaia-header>
|
||||
<ul class="content settings">
|
||||
<li class="vbox">
|
||||
<gaia-select>
|
||||
<label data-l10n-id="reset-report">Reset report</label>
|
||||
<select class="settings-option" data-option="trackingPeriod">
|
||||
<option value="monthly" data-l10n-id="monthly">Monthly</option>
|
||||
<option value="weekly" data-l10n-id="weekly">Weekly</option>
|
||||
<option value="never" data-l10n-id="never">Never</option>
|
||||
</select>
|
||||
</gaia-select>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<gaia-select>
|
||||
<label data-l10n-id="starting-on">Starting on</label>
|
||||
<select id="non2-select-weekday" class="settings-option" data-option="resetTime" data-hide-on="trackingPeriod!=weekly" data-disable-on="trackingPeriod!=weekly">
|
||||
<option class="monday" value="1" data-l10n-id="monday">Monday</option>
|
||||
<option value="2" data-l10n-id="tuesday">Tuesday</option>
|
||||
<option value="3" data-l10n-id="wednesday">Wednesday</option>
|
||||
<option value="4" data-l10n-id="thursday">Thursday</option>
|
||||
<option value="5" data-l10n-id="friday">Friday</option>
|
||||
<option value="6" data-l10n-id="saturday">Saturday</option>
|
||||
<option class="sunday" value="0" data-l10n-id="sunday">Sunday</option>
|
||||
</select>
|
||||
</gaia-select>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<gaia-select>
|
||||
<label data-l10n-id="starting-on">Starting on</label>
|
||||
<select class="settings-option icon icon-dialog" data-option="resetTime" data-hide-on="trackingPeriod!=monthly" data-disable-on="trackingPeriod!=monthly">
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5">5</option>
|
||||
<option value="6">6</option>
|
||||
<option value="7">7</option>
|
||||
<option value="8">8</option>
|
||||
<option value="9">9</option>
|
||||
<option value="10">10</option>
|
||||
<option value="11">11</option>
|
||||
<option value="12">12</option>
|
||||
<option value="13">13</option>
|
||||
<option value="14">14</option>
|
||||
<option value="15">15</option>
|
||||
<option value="16">16</option>
|
||||
<option value="17">17</option>
|
||||
<option value="18">18</option>
|
||||
<option value="19">19</option>
|
||||
<option value="20">20</option>
|
||||
<option value="21">21</option>
|
||||
<option value="22">22</option>
|
||||
<option value="23">23</option>
|
||||
<option value="24">24</option>
|
||||
<option value="25">25</option>
|
||||
<option value="26">26</option>
|
||||
<option value="27">27</option>
|
||||
<option value="28">28</option>
|
||||
<option value="29">29</option>
|
||||
<option value="30">30</option>
|
||||
<option value="31">31</option>
|
||||
</select>
|
||||
</gaia-select>
|
||||
</li>
|
||||
<li>
|
||||
<p data-l10n-id="fte-onlydata2-hint">Receive reports about your internet usage.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<gaia-buttons data-items="2">
|
||||
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
|
||||
<button class="recommend icon icon-next" data-navigation="next" data-l10n-id="next">Next</button>
|
||||
</gaia-buttons>
|
||||
</section>
|
||||
|
||||
<!-- Non VIVO step 3 -->
|
||||
<section role="region" class="view step gaia-list" data-viewport="right" id="non-vivo-step-2">
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="fte-onlydata3-title">Data Alert</h1>
|
||||
</gaia-header>
|
||||
<ul class="content settings">
|
||||
<li class="active">
|
||||
<gaia-switch class="settings-option" data-option="dataLimit">
|
||||
<label data-l10n-id="data-limit-alert">Data use alert</label>
|
||||
</gaia-switch>
|
||||
</li>
|
||||
<li class="vbox">
|
||||
<p data-l10n-id="data-limit-value2">When use is above</p>
|
||||
<button class="settings-option icon icon-dialog" data-widget-type="data-limit" data-disable-on="dataLimit=false" data-hide-on="dataLimit=false">
|
||||
<span class="tag"></span>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<p data-l10n-id="fte-onlydata3-hint">Set an alert to avoid using too much data.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<gaia-buttons data-items="2">
|
||||
<button data-navigation="back" class="icon icon-previous" data-l10n-id="back">Back</button>
|
||||
<button class="recommend" data-navigation="finish" data-l10n-id="lets-go">Let’s go!</button>
|
||||
</gaia-buttons>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<!-- Data usage limits -->
|
||||
<section aria-labelledby="limit-dialog-heading" id="data-limit-dialog" role="dialog" class="view" data-viewport="bottom">
|
||||
<gaia-header id="limit-dialog-header" action="close">
|
||||
<h1 id="limit-dialog-heading" data-l10n-id="data-limit-header">Data usage limit</h1>
|
||||
<button id="data-usage-done-button" data-l10n-id="done" class="recommend">Done</button>
|
||||
</gaia-header>
|
||||
<section class="content">
|
||||
<div class="info">
|
||||
<h2 data-l10n-id="data-limit-dialog-title2">Enter a mobile data limit alert</h2>
|
||||
<p data-l10n-id="data-limit-dialog-explanation2">Connection speeds reduce after the limit is reached. Check with your data provider to set an appropriate alert level.</p>
|
||||
</div>
|
||||
</section>
|
||||
<form>
|
||||
<ul class="buttons-list" role="presentation">
|
||||
<li role="presentation">
|
||||
<label aria-label="Data limit" for="data-limit-input" data-l10n-id="data-limit-input-label">
|
||||
<input id="data-limit-input" x-inputmode="numeric" maxlength="6" type="text">
|
||||
</label>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<button class="icon icon-dialog switch-unit-button">
|
||||
<span class="tag"></span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<iframe id="message-handler" src=""></iframe>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
;'use strict';var Format={padLeft:function(input,len,padWith){padWith=padWith||' ';var pad=len-(input+'').length;while(--pad>-1){input=padWith+input;}
|
||||
return input;}};;window.COMPONENTS_BASE_URL='/shared/elements/';;(function(exports){'use strict';exports.ComponentUtils={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';style.addEventListener('load',function(){if(self.shadowRoot){self.shadowRoot.appendChild(style.cloneNode(true));}
|
||||
self.style.visibility='';});}};}(window));;(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GaiaHeader=f()}})(function(){var define,module,exports;return(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){;(function(define){define(function(require,exports,module){'use strict';var debug=0?console.log.bind(console):function(){};var cache={};var MIN=16;var MAX=24;var BUFFER=3;module.exports=function(config){debug('font fit',config);var space=config.space-BUFFER;var min=config.min||MIN;var max=config.max||MAX;var text=trim(config.text);var fontSize=max;var textWidth;var font;do{font=config.font.replace(/\d+px/,fontSize+'px');textWidth=getTextWidth(text,font);}while(textWidth>space&&fontSize!==min&&fontSize--);return{textWidth:textWidth,fontSize:fontSize,overflowing:textWidth>space};};function getTextWidth(text,font){var ctx=getCanvasContext(font);var width=ctx.measureText(text).width;debug('got text width',width);return width;}
|
||||
function getCanvasContext(font){debug('get canvas context',font);var cached=cache[font];if(cached){return cached;}
|
||||
var canvas=document.createElement('canvas');canvas.setAttribute('moz-opaque','true');canvas.setAttribute('width','1px');canvas.setAttribute('height','1px');debug('created canvas',canvas);var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.font=font;return cache[font]=ctx;}
|
||||
function trim(text){return text.replace(/\s+/g,' ').trim();}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('font-fit',this));},{}],2:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var textContent=Object.getOwnPropertyDescriptor(Node.prototype,'textContent');var innerHTML=Object.getOwnPropertyDescriptor(Element.prototype,'innerHTML');var removeAttribute=Element.prototype.removeAttribute;var setAttribute=Element.prototype.setAttribute;var noop=function(){};exports.register=function(name,props){var baseProto=getBaseProto(props.extends);var template=props.template||baseProto.templateString;var extensible=props.extensible=props.hasOwnProperty('extensible')?props.extensible:true;delete props.extends;if(template){if(extensible&&props.template){props.templateString=props.template;}
|
||||
var output=processCss(template,name);props.template=document.createElement('template');props.template.innerHTML=output.template;props.lightCss=output.lightCss;props.globalCss=props.globalCss||'';props.globalCss+=output.globalCss;}
|
||||
injectGlobalCss(props.globalCss);delete props.globalCss;var descriptors=mixin(props.attrs||{},base.descriptors);props._attrs=props.attrs;delete props.attrs;var proto=createProto(baseProto,props);Object.defineProperties(proto,descriptors);try{return document.registerElement(name,{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}};var base={properties:{GaiaComponent:true,attributeChanged:noop,attached:noop,detached:noop,created:noop,createdCallback:function(){if(this.dirObserver){addDirObserver();}
|
||||
injectLightCss(this);this.created();},attributeChangedCallback:function(name,from,to){var prop=toCamelCase(name);if(this._attrs&&this._attrs[prop]){this[prop]=to;}
|
||||
this.attributeChanged(name,from,to);},attachedCallback:function(){if(this.dirObserver){this.setInnerDirAttributes=setInnerDirAttributes.bind(null,this);document.addEventListener('dirchanged',this.setInnerDirAttributes);}
|
||||
this.attached();},detachedCallback:function(){if(this.dirObserver){document.removeEventListener('dirchanged',this.setInnerDirAttributes);}
|
||||
this.detached();},setupShadowRoot:function(){if(!this.template){return;}
|
||||
var node=document.importNode(this.template.content,true);this.createShadowRoot().appendChild(node);if(this.dirObserver){setInnerDirAttributes(this);}
|
||||
return this.shadowRoot;},setAttr:function(name,value){var internal=this.shadowRoot.firstElementChild;setAttribute.call(internal,name,value);setAttribute.call(this,name,value);},removeAttr:function(name){var internal=this.shadowRoot.firstElementChild;removeAttribute.call(internal,name);removeAttribute.call(this,name);}},descriptors:{textContent:{set:function(value){textContent.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:function(){return textContent.get();}},innerHTML:{set:function(value){innerHTML.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:innerHTML.get}}};var defaultPrototype=createProto(HTMLElement.prototype,base.properties);function getBaseProto(proto){if(!proto){return defaultPrototype;}
|
||||
proto=proto.prototype||proto;return!proto.GaiaComponent?createProto(proto,base.properties):proto;}
|
||||
function createProto(proto,props){return mixin(Object.create(proto),props);}
|
||||
var hasShadowCSS=(function(){var div=document.createElement('div');try{div.querySelector(':host');div.querySelector('::content');return true;}
|
||||
catch(e){return false;}})();var regex={shadowCss:/(?:\:host|\:\:content)[^{]*\{[^}]*\}/g,':host':/(?:\:host)/g,':host()':/\:host\((.+)\)(?: \:\:content)?/g,':host-context':/\:host-context\((.+)\)([^{,]+)?/g,'::content':/(?:\:\:content)/g};function processCss(template,name){var globalCss='';var lightCss='';if(!hasShadowCSS){template=template.replace(regex.shadowCss,function(match){var hostContext=regex[':host-context'].exec(match);if(hostContext){globalCss+=match.replace(regex['::content'],'').replace(regex[':host-context'],'$1 '+name+'$2').replace(/ +/g,' ');}else{lightCss+=match.replace(regex[':host()'],name+'$1').replace(regex[':host'],name).replace(regex['::content'],name);}
|
||||
return'';});}
|
||||
return{template:template,lightCss:lightCss,globalCss:globalCss};}
|
||||
function injectGlobalCss(css){if(!css){return;}
|
||||
var style=document.createElement('style');style.innerHTML=css.trim();headReady().then(function(){document.head.appendChild(style);});}
|
||||
function headReady(){return new Promise(function(resolve){if(document.head){return resolve();}
|
||||
window.addEventListener('load',function fn(){window.removeEventListener('load',fn);resolve();});});}
|
||||
function injectLightCss(el){if(hasShadowCSS){return;}
|
||||
var stylesheet=el.querySelector('style');if(!stylesheet){stylesheet=document.createElement('style');stylesheet.setAttribute('scoped','');stylesheet.appendChild(document.createTextNode(el.lightCss));el.appendChild(stylesheet);}
|
||||
el.lightStyle=stylesheet;}
|
||||
function toCamelCase(string){return string.replace(/-(.)/g,function replacer(string,p1){return p1.toUpperCase();});}
|
||||
var dirObserver;function setInnerDirAttributes(component){var dir=component.dir||document.dir;Array.from(component.shadowRoot.children).forEach(element=>{if(element.nodeName!=='STYLE'){element.dir=dir;}});}
|
||||
function addDirObserver(){if(dirObserver){return;}
|
||||
dirObserver=new MutationObserver(onChanged);dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});function onChanged(mutations){document.dispatchEvent(new Event('dirchanged'));}}
|
||||
function mixin(target,source){for(var key in source){target[key]=source[key];}
|
||||
return target;}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-component',this));},{}],3:[function(require,module,exports){(function(define){'use strict';define(function(require,exports,module){var base=window.GAIA_ICONS_BASE_URL||window.COMPONENTS_BASE_URL||'bower_components/';if(!document.documentElement){window.addEventListener('load',load);}else{load();}
|
||||
function load(){if(isLoaded()){return;}
|
||||
var link=document.createElement('link');link.rel='stylesheet';link.type='text/css';link.href=base+'gaia-icons/gaia-icons.css';document.head.appendChild(link);exports.loaded=true;}
|
||||
function isLoaded(){return exports.loaded||document.querySelector('link[href*=gaia-icons]')||document.documentElement.classList.contains('gaia-icons-loaded');}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-icons',this));},{}],4:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var component=require('gaia-component');var fontFit=require('font-fit');require('gaia-icons');var debug=0?console.log.bind(console):function(){};const KNOWN_ACTIONS={menu:'menu',back:'back',close:'close'};const TITLE_FONT='italic 300 24px FiraSans';const TITLE_PADDING=10;const MINIMUM_FONT_SIZE_CENTERED=20;const MINIMUM_FONT_SIZE_UNCENTERED=16;const MAXIMUM_FONT_SIZE=23;module.exports=component.register('gaia-header',{extensible:false,dirObserver:true,created:function(){debug('created');this.setupShadowRoot();this.els={actionButton:this.shadowRoot.querySelector('.action-button'),titles:this.getElementsByTagName('h1')};this.els.actionButton.addEventListener('click',e=>this.onActionButtonClick(e));this.observer=new MutationObserver(this.onMutation.bind(this));this.ignoreDir=this.hasAttribute('ignore-dir');this.titleEnd=this.getAttribute('title-end');this.titleStart=this.getAttribute('title-start');this.noFontFit=this.getAttribute('no-font-fit');this.notFlush=this.hasAttribute('not-flush');this.action=this.getAttribute('action');this.unresolved={};this.pending={};this._resizeThrottlingId=null;this.onResize=this.onResize.bind(this);},attached:function(){debug('attached');this.runFontFitSoon();this.observerStart();window.addEventListener('resize',this.onResize);},detached:function(){debug('detached');window.removeEventListener('resize',this.onResize);this.observerStop();this.clearPending();},clearPending:function(){for(var key in this.pending){this.pending[key].clear();delete this.pending[key];}
|
||||
window.cancelAnimationFrame(this._resizeThrottlingId);this._resizeThrottlingId=null;},runFontFit:function(){debug('run font-fit');if(this.noFontFit){return Promise.resolve();}
|
||||
var titles=this.els.titles;var space=this.getTitleSpace();var styles=[].map.call(titles,el=>this.getTitleStyle(el,space));return this.setTitleStylesSoon(styles);},runFontFitSoon:function(){debug('run font-fit soon');if(this.pending.runFontFitSoon){return;}
|
||||
this.pending.runFontFitSoon=this.nextTick(()=>{delete this.pending.runFontFitSoon;this.runFontFit();});},getTitleStyle:function(el,space){debug('get el style',el,space);var text=el.textContent;var styleId=space.start+text+space.end+'#'+space.value;if(!text||!text.trim()){return debug('exit: no text');}
|
||||
if(getStyleId(el)===styleId){return debug('exit: no change');}
|
||||
var marginStart=this.getTitleMarginStart();var textSpace=space.value-Math.abs(marginStart);var fontFitResult=this.fontFit(text,textSpace,{min:MINIMUM_FONT_SIZE_CENTERED});var overflowing=fontFitResult.overflowing;var padding={start:0,end:0};if(overflowing){debug('title overflowing');padding.start=!space.start?TITLE_PADDING:0;padding.end=!space.end?TITLE_PADDING:0;textSpace=space.value-padding.start-padding.end;fontFitResult=this.fontFit(text,textSpace);marginStart=0;}
|
||||
return{id:styleId,fontSize:fontFitResult.fontSize,marginStart:marginStart,overflowing:overflowing,padding:padding};},setTitleStylesSoon:function(styles){debug('set title styles soon',styles);var key='setStyleTitlesSoon';this._titleStyles=styles;if(this.unresolved[key]){return this.unresolved[key];}
|
||||
this.unresolved[key]=new Promise((resolve)=>{this.pending[key]=this.nextTick(()=>{var styles=this._titleStyles;var els=this.els.titles;[].forEach.call(els,(el,i)=>{if(!styles[i]){return debug('exit');}
|
||||
this.setTitleStyle(el,styles[i]);});delete this._titleStyles;delete this.unresolved[key];delete this.pending[key];resolve();});});},setTitleStyle:function(el,style){debug('set title style',style);this.observerStop();if(this.ignoreDir){el.style.marginLeft=style.marginStart+'px';el.style.paddingLeft=style.padding.start+'px';el.style.paddingRight=style.padding.end+'px';}else{el.style.marginInlineStart=style.marginStart+'px';el.style.paddingInlineStart=style.padding.start+'px';el.style.paddingInlineEnd=style.padding.end+'px';}
|
||||
el.style.fontSize=style.fontSize+'px';setStyleId(el,style.id);this.observerStart();},fontFit:function(text,space,opts={}){debug('font fit:',text,space,opts);var fontFitArgs={font:TITLE_FONT,min:opts.min||MINIMUM_FONT_SIZE_UNCENTERED,max:MAXIMUM_FONT_SIZE,text:text,space:space};return fontFit(fontFitArgs);},observerStart:function(){if(this.observing){return;}
|
||||
this.observer.observe(this,{childList:true,attributes:true,subtree:true});this.observing=true;debug('observer started');},observerStop:function(){if(!this.observing){return;}
|
||||
this.observer.disconnect();this.observing=false;debug('observer stopped');},onResize:function(e){debug('onResize',this._resizeThrottlingId);if(this._resizeThrottlingId!==null){return;}
|
||||
this._resizeThrottlingId=window.requestAnimationFrame(()=>{this._resizeThrottlingId=null;this.runFontFitSoon();});},onMutation:function(mutations){debug('on mutation',mutations);if(!this.pending.runFontFitSoon){this.runFontFit();}},getTitleSpace:function(){var start=this.titleStart;var end=this.titleEnd;var space=this.getWidth()-start-end;var result={value:space,start:start,end:end};debug('get title space',result);return result;},getWidth:function(){var value=this.notFlush?this.clientWidth:window.innerWidth;debug('get width',value);return value;},triggerAction:function(){if(this.action){this.els.actionButton.click();}},onActionButtonClick:function(){debug('action button click');var config={detail:{type:this.action}};var e=new CustomEvent('action',config);setTimeout(()=>this.dispatchEvent(e));},getTitleMarginStart:function(){var start=this.titleStart;var end=this.titleEnd;var marginStart=end-start;debug('get title margin start',marginStart);return marginStart;},getButtonsBeforeTitle:function(){var children=this.children;var l=children.length;var els=[];for(var i=0;i<l;i++){var el=children[i];if(el.tagName==='H1'){break;}
|
||||
if(!contributesToLayout(el)){continue;}
|
||||
els.push(el);}
|
||||
if(this.action){els.push(this.els.actionButton);}
|
||||
return els;},getButtonsAfterTitle:function(){var children=this.children;var els=[];for(var i=children.length-1;i>=0;i--){var el=children[i];if(el.tagName==='H1'){break;}
|
||||
if(!contributesToLayout(el)){continue;}
|
||||
els.push(el);}
|
||||
return els;},sumButtonWidths:function(buttons){var defaultWidth=50;var sum=buttons.reduce((prev,button)=>{var isStandardButton=button===this.els.actionButton;var width=isStandardButton?defaultWidth:button.clientWidth;return prev+width;},0);debug('sum button widths',buttons,sum);return sum;},attrs:{action:{get:function(){return this._action;},set:function(value){var action=KNOWN_ACTIONS[value];if(action===this._action){return;}
|
||||
this.setAttr('action',action);this._action=action;}},titleStart:{get:function(){debug('get title-start');if('_titleStart'in this){return this._titleStart;}
|
||||
var buttons=this.getButtonsBeforeTitle();var value=this.sumButtonWidths(buttons);debug('get title-start',buttons,value);return value;},set:function(value){debug('set title-start',value);value=parseInt(value,10);if(value===this._titleStart||isNaN(value)){return;}
|
||||
this.setAttr('title-start',value);this._titleStart=value;debug('set');}},titleEnd:{get:function(){debug('get title-end');if('_titleEnd'in this){return this._titleEnd;}
|
||||
var buttons=this.getButtonsAfterTitle();return this.sumButtonWidths(buttons);},set:function(value){debug('set title-end',value);value=parseInt(value,10);if(value===this._titleEnd||isNaN(value)){return;}
|
||||
this.setAttr('title-end',value);this._titleEnd=value;}},noFontFit:{get:function(){return this._noFontFit||false;},set:function(value){debug('set no-font-fit',value);value=!!(value||value==='');if(value===this.noFontFit){return;}
|
||||
this._noFontFit=value;if(value){this.setAttr('no-font-fit','');}
|
||||
else{this.removeAttr('no-font-fit');}}},ignoreDir:{get:function(){return this._ignoreDir||false;},set:function(value){debug('set ignore-dir',value);value=!!(value||value==='');if(value===this.ignoreDir){return;}
|
||||
this._ignoreDir=value;this.dirObserver=!value;if(value){this.setAttr('ignore-dir','');}
|
||||
else{this.removeAttr('ignore-dir');}}}},template:`<div class="inner">
|
||||
<button class="action-button">
|
||||
<content select="[l10n-action]"></content>
|
||||
</button>
|
||||
<content></content>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
-moz-user-select: none;
|
||||
|
||||
--gaia-header-button-color:
|
||||
var(--header-button-color,
|
||||
var(--header-color,
|
||||
var(--link-color,
|
||||
inherit)));
|
||||
}
|
||||
|
||||
/**
|
||||
* [hidden]
|
||||
*/
|
||||
|
||||
:host[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/** Reset
|
||||
---------------------------------------------------------*/
|
||||
|
||||
::-moz-focus-inner { border: 0; }
|
||||
|
||||
/** Inner
|
||||
---------------------------------------------------------*/
|
||||
|
||||
.inner {
|
||||
display: flex;
|
||||
min-height: 50px;
|
||||
-moz-user-select: none;
|
||||
|
||||
background:
|
||||
var(--header-background,
|
||||
var(--background,
|
||||
#fff));
|
||||
}
|
||||
|
||||
/** Action Button
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 1. Hidden by default
|
||||
*/
|
||||
|
||||
.action-button {
|
||||
position: relative;
|
||||
|
||||
display: none; /* 1 */
|
||||
width: 50px;
|
||||
font-size: 30px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
align-items: center;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
transition: opacity 200ms 280ms;
|
||||
color:
|
||||
var(--header-action-button-color,
|
||||
var(--header-icon-color,
|
||||
var(--gaia-header-button-color)));
|
||||
}
|
||||
|
||||
/**
|
||||
* [action=back]
|
||||
* [action=menu]
|
||||
* [action=close]
|
||||
*
|
||||
* 1. For icon vertical-alignment
|
||||
*/
|
||||
|
||||
[action=back] .action-button,
|
||||
[action=menu] .action-button,
|
||||
[action=close] .action-button {
|
||||
display: flex; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* :active
|
||||
*/
|
||||
|
||||
.action-button:active {
|
||||
transition: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
/** Action Button Icon
|
||||
---------------------------------------------------------*/
|
||||
|
||||
.action-button:before {
|
||||
font-family: 'gaia-icons';
|
||||
font-style: normal;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[action=close] .action-button:before { content: 'close' }
|
||||
[action=menu] .action-button:before { content: 'menu' }
|
||||
|
||||
[action=back]:-moz-dir(ltr) .action-button:before { content: 'left' }
|
||||
[action=back]:-moz-dir(rtl) .action-button:before { content: 'right' }
|
||||
|
||||
/** Action Button Icon
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 1. To enable vertical alignment.
|
||||
*/
|
||||
|
||||
.action-button:before {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/** Action Button Text
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* To provide custom localized content for
|
||||
* the action-button, we allow the user
|
||||
* to provide an element with the class
|
||||
* .l10n-action. This node is then
|
||||
* pulled inside the real action-button.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <gaia-header action="back">
|
||||
* <span l10n-action aria-label="Back">Localized text</span>
|
||||
* <h1>title</h1>
|
||||
* </gaia-header>
|
||||
*/
|
||||
|
||||
::content [l10n-action] {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
/** Title
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 1. Vertically center text. We can't use flexbox
|
||||
* here as it breaks text-overflow ellipsis
|
||||
* without an inner div.
|
||||
*/
|
||||
|
||||
::content h1 {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
text-align: center;
|
||||
line-height: 50px; /* 1 */
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
font-size: 24px;
|
||||
|
||||
color:
|
||||
var(--header-title-color,
|
||||
var(--header-color,
|
||||
var(--title-color,
|
||||
var(--text-color,
|
||||
inherit))));
|
||||
}
|
||||
|
||||
/**
|
||||
* [ignore-dir]
|
||||
*
|
||||
* When the <gaia-header> component has an [ignore-dir] attribute, header
|
||||
* direction is forced to LTR but we still want the <h1> text to be reversed
|
||||
* so that strings like '1 selected' become 'selected 1'.
|
||||
*
|
||||
* When we're happy for <gaia-header> to be fully RTL responsive we won't need
|
||||
* these rules anymore, but this depends on all Gaia apps being ready.
|
||||
*
|
||||
* This should be safe to remove when bug 1179459 lands.
|
||||
*/
|
||||
|
||||
:host[ignore-dir] {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
:host[ignore-dir]:-moz-dir(rtl) h1 {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
/** Buttons
|
||||
---------------------------------------------------------*/
|
||||
|
||||
::content a,
|
||||
::content button {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
width: auto;
|
||||
height: auto;
|
||||
min-width: 50px;
|
||||
margin: 0;
|
||||
padding: 0 10px;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
font-style: italic;
|
||||
cursor: pointer;
|
||||
transition: opacity 200ms 280ms;
|
||||
color: var(--gaia-header-button-color);
|
||||
}
|
||||
|
||||
/**
|
||||
* :active
|
||||
*/
|
||||
|
||||
::content a:active,
|
||||
::content button:active {
|
||||
transition: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
/**
|
||||
* [hidden]
|
||||
*/
|
||||
|
||||
::content a[hidden],
|
||||
::content button[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* [disabled]
|
||||
*/
|
||||
|
||||
::content a[disabled],
|
||||
::content button[disabled] {
|
||||
pointer-events: none;
|
||||
color: var(--header-disabled-button-color);
|
||||
}
|
||||
|
||||
/** Icon Buttons
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Icons are a different color to text
|
||||
*/
|
||||
|
||||
::content .icon,
|
||||
::content [data-icon] {
|
||||
color:
|
||||
var(--header-icon-color,
|
||||
var(--gaia-header-button-color));
|
||||
}
|
||||
|
||||
/**
|
||||
* If users want their action button
|
||||
* to be in the component's light-dom
|
||||
* they can add an .action class
|
||||
* to make it look like the
|
||||
* shadow action button.
|
||||
*/
|
||||
|
||||
::content .action {
|
||||
color:
|
||||
var(--header-action-button-color,
|
||||
var(--header-icon-color,
|
||||
var(--gaia-header-button-color)));
|
||||
}
|
||||
|
||||
/**
|
||||
* [data-icon]:empty
|
||||
*
|
||||
* Icon buttons with no textContent,
|
||||
* should always be 50px.
|
||||
*
|
||||
* This is to prevent buttons being
|
||||
* larger than they should be before
|
||||
* icon-font has loaded.
|
||||
*/
|
||||
|
||||
::content [data-icon]:empty {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
</style>`,nextTick:nextTick});function contributesToLayout(el){return el.localName!=='style'&&!el.hasAttribute('l10n-action');}
|
||||
function setStyleId(el,id){el._styleId=id;}
|
||||
function getStyleId(el){return el._styleId;}
|
||||
function nextTick(fn){var cleared;Promise.resolve().then(()=>{if(!cleared){fn();}});return{clear:function(){cleared=true;}};}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-header',this));},{"font-fit":1,"gaia-component":2,"gaia-icons":3}]},{},[4])(4)});;'use strict';window.GaiaButtons=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaButtonsBaseurl||'/shared/elements/gaia_buttons/';proto.createdCallback=function(){ComponentUtils.style.call(this,baseurl);};return document.registerElement('gaia-buttons',{prototype:proto});})(window);;'use strict';window.GaiaSelect=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSelectBaseurl||'/shared/elements/gaia_select/';var selectCounter=0;proto.createdCallback=function(){var label=this.querySelector('label');if(label){var select=this.querySelector('select');if(label.control!=select){var id=select.id;if(!id){select.id=id='gaia-select-'+(++selectCounter);}
|
||||
label.htmlFor=id;}}
|
||||
ComponentUtils.style.call(this,baseurl);};return document.registerElement('gaia-select',{prototype:proto});})(window);;'use strict';window.GaiaSwitch=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSwitchBaseurl||'/shared/elements/gaia_switch/';proto.createdCallback=function(){var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._input=this._template.querySelector('input[type="checkbox"]');var checked=this.getAttribute('checked');if(checked!==null){this._input.checked=true;}
|
||||
var wrapper=this._template.getElementById('switch');wrapper.addEventListener('click',this.handleClick.bind(this));shadow.appendChild(this._template);ComponentUtils.style.call(this,baseurl);var dirObserver=new MutationObserver(this.updateInternalDir.bind(this));dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});this.updateInternalDir();};proto.updateInternalDir=function(){var internal=this.shadowRoot.firstElementChild;if(document.documentElement.dir==='rtl'){internal.setAttribute('dir','rtl');}else{internal.removeAttribute('dir');}};proto.handleClick=function(e){if(e&&e.target.tagName==='A'){return;}
|
||||
e&&e.preventDefault();e&&e.stopImmediatePropagation();var event=new MouseEvent('click',{view:window,bubbles:true,cancelable:true});this.dispatchEvent(event);if(!event.defaultPrevented){this.checked=!this.checked;}
|
||||
this.dispatchEvent(new CustomEvent('change',{bubbles:true,cancelable:false}));};proto.click=function(){this.handleClick();};Object.defineProperty(proto,'checked',{get:function(){return this._input.checked;},set:function(value){this._input.checked=value;}});Object.defineProperty(proto,'disabled',{get:function(){return this.hasAttribute('disabled');},set:function(value){if(value){this.setAttribute('disabled',true);}else{this.removeAttribute('disabled');}}});Object.defineProperty(proto,'name',{get:function(){return this.getAttribute('name');},set:function(value){this.setAttribute('name',value);}});Object.defineProperty(proto,'type',{get:function(){return'gaia-switch';}});var template=document.createElement('template');template.innerHTML=`<span id="switch">
|
||||
<input type="checkbox">
|
||||
<span><content select="label"></content></span>
|
||||
<div class="details"><content select="details"></content></div>
|
||||
<content select="a"></content>
|
||||
</span>`;return document.registerElement('gaia-switch',{prototype:proto});})(window);;'use strict';window.GaiaRadio=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaRadioBaseurl||'/shared/elements/gaia_radio/';proto.createdCallback=function(){var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._wrapper=this._template.getElementById('radio');this._wrapper.addEventListener('click',this.handleClick.bind(this));if(this.dataset.role){this._wrapper.setAttribute('role',this.dataset.role);}
|
||||
if(!this.hasAttribute('role')){this.setAttribute('role','presentation');}
|
||||
this.configureClass();shadow.appendChild(this._template);this.checked=this.hasAttribute('checked');this._wrapper.setAttribute('aria-checked',this.checked);setTimeout(function nextTick(){var label=this.querySelector('label, p');if(!label){return;}
|
||||
label.addEventListener('click',this.handleClick.bind(this));}.bind(this));ComponentUtils.style.call(this,baseurl);var dirObserver=new MutationObserver(this.updateInternalDir.bind(this));dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});this.updateInternalDir();};proto.updateInternalDir=function(){var internal=this.shadowRoot.firstElementChild;if(document.documentElement.dir==='rtl'){internal.setAttribute('dir','rtl');}else{internal.removeAttribute('dir');}};proto.handleClick=function(e){e.stopImmediatePropagation();var event=new MouseEvent('click',{view:window,bubbles:true,cancelable:true});this.dispatchEvent(event);if(this.checked){return;}
|
||||
if(!event.defaultPrevented){this.checked=!this.checked;}
|
||||
this.dispatchEvent(new CustomEvent('change',{bubbles:true,cancelable:false}));};proto.configureClass=function(){this._wrapper.className=this.className;this._wrapper.classList.toggle('checked',this._checked);};proto.hideDetails=function(){this.shadowRoot.querySelector('.details').style.display='none';};proto.attributeChangedCallback=function(name,from,to){if(name==='class'){this._wrapper.className=to;}};Object.defineProperty(proto,'checked',{get:function(){return this._checked;},set:function(value){if(!this._template){return;}
|
||||
if(value){var relevant=document.querySelectorAll('gaia-radio[name="'+this.getAttribute('name')+'"]');for(var i=0,iLen=relevant.length;i<iLen;i++){relevant[i].checked=false;}
|
||||
this.setAttribute('checked',true);}else{this.removeAttribute('checked');}
|
||||
this._wrapper.classList.toggle('checked',value);this._wrapper.setAttribute('aria-checked',value);this._checked=value;}});Object.defineProperty(proto,'name',{get:function(){return this.getAttribute('name');},set:function(value){this.setAttribute('name',value);}});Object.defineProperty(proto,'value',{get:function(){return this.getAttribute('value');},set:function(value){this.setAttribute('value',value);}});Object.defineProperty(proto,'type',{get:function(){return'gaia-radio';}});var template=document.createElement('template');template.innerHTML='<span role="radio" id="radio">'+'<span><content select="p,label"></content></span>'+'<div class="details"><content select="details"></content></div>'+'<div class="divider"></div>'+'</span>';return document.registerElement('gaia-radio',{prototype:proto});})(window);;(function(){'use strict';var DEFAULT_LOW_LIMIT_THRESHOLD=3;var defaultLowLimitThreshold=DEFAULT_LOW_LIMIT_THRESHOLD;window.addEventListener('DOMContentLoaded',function _onDomReady(){initLazyFTE();});function initLazyFTE(){var SCRIPTS_NEEDED=['js/utils/debug.js','js/utils/toolkit.js','js/sim_manager.js','js/common.js','js/config/config_manager.js','js/views/BalanceLowLimitView.js','js/view_manager.js','js/settings/autosettings.js'];LazyLoader.load(SCRIPTS_NEEDED,function onScriptsLoaded(){setupFTE();parent.postMessage({type:'fte_ready',data:''},Common.COST_CONTROL_APP);window.addEventListener('localized',_onLocalize);});}
|
||||
var wizard,vmanager;var toStep2,step=0;function setupFTE(){if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',function _onDataSimChange(){window.removeEventListener('dataSlotChange',_onDataSimChange);Common.closeFTE();});}
|
||||
ConfigManager.requestAll(function _onSettings(configuration,settings){wizard=document.getElementById('firsttime-view');vmanager=new ViewManager();if(configuration&&configuration.default_low_limit_threshold){defaultLowLimitThreshold=configuration.default_low_limit_threshold;}
|
||||
ConfigManager.setOption({resetTime:1,trackingPeriod:'monthly'});var mode=ConfigManager.getApplicationMode();var SCRIPTS_NEEDED=['js/settings/limitdialog.js','js/utils/formatting.js'];LazyLoader.load(SCRIPTS_NEEDED,function onScriptsLoaded(){Common.loadNetworkInterfaces(function(){AutoSettings.addType('data-limit',dataLimitConfigurer);if(mode==='DATA_USAGE_ONLY'){AutoSettings.initialize(ConfigManager,vmanager,'#non-vivo-step-2');}});});if(configuration&&configuration.credit&&configuration.credit.currency){document.getElementById('currency').textContent=configuration.credit.currency;}
|
||||
if(mode==='DATA_USAGE_ONLY'){debug('FTE for non supported SIM');wizard.dataset.steps='3';reset(['step-1','non-vivo-step-1','non-vivo-step-2']);AutoSettings.initialize(ConfigManager,vmanager,'#non-vivo-step-1');}else{wizard.dataset.steps='4';reset(['step-1','step-2']);AutoSettings.initialize(ConfigManager,vmanager,'#step-1');toStep2=document.getElementById('to-step-2');toStep2.disabled=true;document.getElementById('prepaid-plan').addEventListener('click',selectTrack);document.getElementById('postpaid-plan').addEventListener('click',selectTrack);addLowLimitStepConstrains();}
|
||||
var next=document.querySelectorAll('[data-navigation=next]');[].forEach.call(next,function cc_eachNext(nextButton){nextButton.addEventListener('click',onNext);});var prev=document.querySelectorAll('[data-navigation=back]');[].forEach.call(prev,function cc_eachPrev(prevButton){prevButton.addEventListener('click',onBack);});var finish=document.querySelectorAll('[data-navigation=finish]');[].forEach.call(finish,function cc_eachFinish(finishButton){finishButton.addEventListener('click',onFinish);});LazyLoader.load(['js/costcontrol.js'],function(){var messageHandlerFrame=document.getElementById('message-handler');messageHandlerFrame.src='message_handler.html';});});}
|
||||
function _onLocalize(){Common.localizeWeekdaySelector(document.getElementById('pre3-select-weekday'));Common.localizeWeekdaySelector(document.getElementById('post2-select-weekday'));Common.localizeWeekdaySelector(document.getElementById('non2-select-weekday'));function _setResetTimeToDefault(evt){var today=new Date();var defaultResetTime=(evt.target.value==='weekly')?today.getDay():today.getDate();ConfigManager.setOption({resetTime:defaultResetTime});}
|
||||
var trackingPeriodSelector=document.querySelectorAll('[data-option="trackingPeriod"]');[].forEach.call(trackingPeriodSelector,function _reset(tPeriodSel){tPeriodSel.addEventListener('change',_setResetTimeToDefault);});}
|
||||
if(window.location.hash){wizard=document.getElementById('firsttime-view');if(window.location.hash==='#PREPAID'||window.location.hash==='#POSTPAID'){wizard.querySelector('.authed-sim').hidden=false;}else{wizard.querySelector('.nonauthed-sim').hidden=false;}}
|
||||
var currentTrack=['step-1','step-2'];function selectTrack(evt){if(evt.target.value==='prepaid'){currentTrack=['step-1','step-2','prepaid-step-2','prepaid-step-3'];AutoSettings.initialize(ConfigManager,vmanager,'#prepaid-step-2');AutoSettings.initialize(ConfigManager,vmanager,'#prepaid-step-3');balanceLowLimitView.disabled=false;ConfigManager.setOption({dataLimitValue:40,dataLimitUnit:'MB',lowLimit:true,lowLimitThreshold:defaultLowLimitThreshold});}else if(evt.target.value==='postpaid'){currentTrack=['step-1','step-2','postpaid-step-2','postpaid-step-3'];AutoSettings.initialize(ConfigManager,vmanager,'#postpaid-step-2');AutoSettings.initialize(ConfigManager,vmanager,'#postpaid-step-3');balanceLowLimitView.disabled=true;ConfigManager.setOption({dataLimitValue:2,dataLimitUnit:'GB'});}
|
||||
ConfigManager.setOption({plantype:evt.target.value},function _onSet(){toStep2.disabled=false;});}
|
||||
function reset(track){var currentScreen=document.getElementById(currentTrack[step]);var newStartScreen=document.getElementById(track[0]);currentScreen.dataset.viewport='left';newStartScreen.dataset.viewport='right';delete newStartScreen.dataset.viewport;for(var i=1;i<track.length;i+=1){var id=track[i];if(id){var screen=document.getElementById(id);screen.dataset.viewport='right';}}
|
||||
step=0;currentTrack=track;}
|
||||
function onNext(){if(step===currentTrack.length-1){return;}
|
||||
var currentId=currentTrack[step];var currentScreen=document.getElementById(currentId);var nextScreenId=currentTrack[step+1];var nextScreen=document.getElementById(nextScreenId);delete nextScreen.dataset.viewport;currentScreen.dataset.viewport='left';step+=1;if(step===2){balanceLowLimitView&&balanceLowLimitView.validate();}}
|
||||
function onBack(){if(step===0){return;}
|
||||
var currentId=currentTrack[step];var currentScreen=document.getElementById(currentId);var prevScreenId=currentTrack[step-1];var prevScreen=document.getElementById(prevScreenId);delete prevScreen.dataset.viewport;currentScreen.dataset.viewport='right';step-=1;}
|
||||
function onFinish(evt){evt.target.disabled=true;SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){ConfigManager.setOption({fte:false},function _returnToApp(){Common.updateNextReset(settings.trackingPeriod,settings.resetTime,function _returnToTheApplication(){Common.startApp();});});});});}
|
||||
var balanceLowLimitView;function addLowLimitStepConstrains(){var nextButton=document.getElementById('low-limit-next-button');balanceLowLimitView=new BalanceLowLimitView(document.getElementById('low-limit'),document.getElementById('low-limit-input'));balanceLowLimitView.onvalidation=function(evt){nextButton.disabled=!evt.isValid;};}}());
|
||||
|
|
@ -0,0 +1,693 @@
|
|||
;;(function(exports){'use strict';exports.ComponentUtils={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';style.addEventListener('load',function(){if(self.shadowRoot){self.shadowRoot.appendChild(style.cloneNode(true));}
|
||||
self.style.visibility='';});}};}(window));;'use strict';window.GaiaCheckbox=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaCheckboxBaseurl||'/shared/elements/gaia_checkbox/';proto.createdCallback=function(){this.lastClick=0;this.throttleTime=250;var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._wrapper=this._template.getElementById('checkbox');this._wrapper.addEventListener('click',this.handleClick.bind(this));this.configureClass();this.checked=this.hasAttribute('checked');this._wrapper.setAttribute('aria-checked',this.checked);this.setAttribute('role','presentation');shadow.appendChild(this._template);ComponentUtils.style.call(this,baseurl);};proto.handleClick=function(e){e.preventDefault();e.stopImmediatePropagation();if(this.lastClick+this.throttleTime>Date.now()){return;}
|
||||
this.lastClick=Date.now();var event=new MouseEvent('click',{view:window,bubbles:true,cancelable:true});this.dispatchEvent(event);if(!event.defaultPrevented){this.checked=!this.checked;this._wrapper.setAttribute('aria-checked',this.checked);}
|
||||
this.dispatchEvent(new CustomEvent('change',{bubbles:true,cancelable:false}));};proto.configureClass=function(){this._wrapper.className=this.className;};proto.attributeChangedCallback=function(name,from,to){if(name==='class'){this._wrapper.className=to;}};Object.defineProperty(proto,'checked',{get:function(){return this._checked||false;},set:function(value){this._wrapper.classList.toggle('checked',value);this._checked=value;}});Object.defineProperty(proto,'name',{get:function(){return this.getAttribute('name');},set:function(value){this.setAttribute('name',value);}});var template=document.createElement('template');template.innerHTML=`<span id="checkbox" role="checkbox">
|
||||
<span role="presentation"><content select="label"></content></span>
|
||||
</span>`;return document.registerElement('gaia-checkbox',{prototype:proto});})(window);;;;;(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);;;;;this.asyncStorage=(function(){'use strict';var DBNAME='asyncStorage';var DBVERSION=1;var STORENAME='keyvaluepairs';var db=null;function withDatabase(f){if(db){f();}else{var openreq=indexedDB.open(DBNAME,DBVERSION);openreq.onerror=function withStoreOnError(){console.error('asyncStorage: can\'t open database:',openreq.error.name);};openreq.onupgradeneeded=function withStoreOnUpgradeNeeded(){openreq.result.createObjectStore(STORENAME);};openreq.onsuccess=function withStoreOnSuccess(){db=openreq.result;f();};}}
|
||||
function withStore(type,callback,oncomplete){withDatabase(function(){var transaction=db.transaction(STORENAME,type);if(oncomplete){transaction.oncomplete=oncomplete;}
|
||||
callback(transaction.objectStore(STORENAME));});}
|
||||
function getItem(key,callback){var req;withStore('readonly',function getItemBody(store){req=store.get(key);req.onerror=function getItemOnError(){console.error('Error in asyncStorage.getItem(): ',req.error.name);};},function onComplete(){var value=req.result;if(value===undefined){value=null;}
|
||||
callback(value);});}
|
||||
function setItem(key,value,callback){withStore('readwrite',function setItemBody(store){var req=store.put(value,key);req.onerror=function setItemOnError(){console.error('Error in asyncStorage.setItem(): ',req.error.name);};},callback);}
|
||||
function removeItem(key,callback){withStore('readwrite',function removeItemBody(store){var req=store.delete(key);req.onerror=function removeItemOnError(){console.error('Error in asyncStorage.removeItem(): ',req.error.name);};},callback);}
|
||||
function clear(callback){withStore('readwrite',function clearBody(store){var req=store.clear();req.onerror=function clearOnError(){console.error('Error in asyncStorage.clear(): ',req.error.name);};},callback);}
|
||||
function length(callback){var req;withStore('readonly',function lengthBody(store){req=store.count();req.onerror=function lengthOnError(){console.error('Error in asyncStorage.length(): ',req.error.name);};},function onComplete(){callback(req.result);});}
|
||||
function key(n,callback){if(n<0){callback(null);return;}
|
||||
var req;withStore('readonly',function keyBody(store){var advanced=false;req=store.openCursor();req.onsuccess=function keyOnSuccess(){var cursor=req.result;if(!cursor){return;}
|
||||
if(n===0||advanced){return;}
|
||||
advanced=true;cursor.advance(n);};req.onerror=function keyOnError(){console.error('Error in asyncStorage.key(): ',req.error.name);};},function onComplete(){var cursor=req.result;callback(cursor?cursor.key:null);});}
|
||||
return{getItem:getItem,setItem:setItem,removeItem:removeItem,clear:clear,length:length,key:key};}());;'use strict';(function(exports){var AccessibilityHelper={setAriaSelected:function ah_setAriaSelected(selectedTab,tabs){Array.prototype.forEach.call(tabs,function setAriaSelectedAttr(tab){tab.setAttribute('aria-selected',tab===selectedTab?'true':'false');});}};exports.AccessibilityHelper=AccessibilityHelper;})(window);;;;;'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);}});}};;;;;'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();}());;;;'use strict';var Format={padLeft:function(input,len,padWith){padWith=padWith||' ';var pad=len-(input+'').length;while(--pad>-1){input=padWith+input;}
|
||||
return input;}};;'use strict';var rscheme=/^(?:[a-z\u00a1-\uffff0-9-+]+)(?::(?:\/\/)?)/i;var UrlHelper={a:null,getUrlFromInput:function urlHelper_getUrlFromInput(input){this.a=this.a||document.createElement('a');this.a.href=input;return this.a.href;},_getScheme:function(input){return(rscheme.exec(input)||[])[0];},hasScheme:function(input){return!!this._getScheme(input);},isURL:function urlHelper_isURL(input){return!UrlHelper.isNotURL(input);},isNotURL:function urlHelper_isNotURL(input){var case1Reg=/^(\?)|(\?.+\s)/;var case2Reg=/[\?\.\s\:]/;var case3Reg=/^(data|view-source)\:/;var str=input.trim();if(case1Reg.test(str)||!case2Reg.test(str)||this._getScheme(str)===str){return true;}
|
||||
if(case3Reg.test(str)){return false;}
|
||||
if(!this.hasScheme(str)){str='http://'+str;}
|
||||
if(!this.urlValidate){this.urlValidate=document.createElement('input');this.urlValidate.setAttribute('type','url');}
|
||||
this.urlValidate.setAttribute('value',str);return!this.urlValidate.validity.valid;},resolveUrl:function urlHelper_resolveURL(url,baseUrl){if(!url){return null;}
|
||||
try{return new URL(url,baseUrl).href;}catch(e){return null;}},getHostname:function urlHelper_getHostname(url){try{return new URL(url).hostname;}catch(e){return null;}}};;;window.COMPONENTS_BASE_URL='/shared/elements/';;;(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GaiaHeader=f()}})(function(){var define,module,exports;return(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){;(function(define){define(function(require,exports,module){'use strict';var debug=0?console.log.bind(console):function(){};var cache={};var MIN=16;var MAX=24;var BUFFER=3;module.exports=function(config){debug('font fit',config);var space=config.space-BUFFER;var min=config.min||MIN;var max=config.max||MAX;var text=trim(config.text);var fontSize=max;var textWidth;var font;do{font=config.font.replace(/\d+px/,fontSize+'px');textWidth=getTextWidth(text,font);}while(textWidth>space&&fontSize!==min&&fontSize--);return{textWidth:textWidth,fontSize:fontSize,overflowing:textWidth>space};};function getTextWidth(text,font){var ctx=getCanvasContext(font);var width=ctx.measureText(text).width;debug('got text width',width);return width;}
|
||||
function getCanvasContext(font){debug('get canvas context',font);var cached=cache[font];if(cached){return cached;}
|
||||
var canvas=document.createElement('canvas');canvas.setAttribute('moz-opaque','true');canvas.setAttribute('width','1px');canvas.setAttribute('height','1px');debug('created canvas',canvas);var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.font=font;return cache[font]=ctx;}
|
||||
function trim(text){return text.replace(/\s+/g,' ').trim();}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('font-fit',this));},{}],2:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var textContent=Object.getOwnPropertyDescriptor(Node.prototype,'textContent');var innerHTML=Object.getOwnPropertyDescriptor(Element.prototype,'innerHTML');var removeAttribute=Element.prototype.removeAttribute;var setAttribute=Element.prototype.setAttribute;var noop=function(){};exports.register=function(name,props){var baseProto=getBaseProto(props.extends);var template=props.template||baseProto.templateString;var extensible=props.extensible=props.hasOwnProperty('extensible')?props.extensible:true;delete props.extends;if(template){if(extensible&&props.template){props.templateString=props.template;}
|
||||
var output=processCss(template,name);props.template=document.createElement('template');props.template.innerHTML=output.template;props.lightCss=output.lightCss;props.globalCss=props.globalCss||'';props.globalCss+=output.globalCss;}
|
||||
injectGlobalCss(props.globalCss);delete props.globalCss;var descriptors=mixin(props.attrs||{},base.descriptors);props._attrs=props.attrs;delete props.attrs;var proto=createProto(baseProto,props);Object.defineProperties(proto,descriptors);try{return document.registerElement(name,{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}};var base={properties:{GaiaComponent:true,attributeChanged:noop,attached:noop,detached:noop,created:noop,createdCallback:function(){if(this.dirObserver){addDirObserver();}
|
||||
injectLightCss(this);this.created();},attributeChangedCallback:function(name,from,to){var prop=toCamelCase(name);if(this._attrs&&this._attrs[prop]){this[prop]=to;}
|
||||
this.attributeChanged(name,from,to);},attachedCallback:function(){if(this.dirObserver){this.setInnerDirAttributes=setInnerDirAttributes.bind(null,this);document.addEventListener('dirchanged',this.setInnerDirAttributes);}
|
||||
this.attached();},detachedCallback:function(){if(this.dirObserver){document.removeEventListener('dirchanged',this.setInnerDirAttributes);}
|
||||
this.detached();},setupShadowRoot:function(){if(!this.template){return;}
|
||||
var node=document.importNode(this.template.content,true);this.createShadowRoot().appendChild(node);if(this.dirObserver){setInnerDirAttributes(this);}
|
||||
return this.shadowRoot;},setAttr:function(name,value){var internal=this.shadowRoot.firstElementChild;setAttribute.call(internal,name,value);setAttribute.call(this,name,value);},removeAttr:function(name){var internal=this.shadowRoot.firstElementChild;removeAttribute.call(internal,name);removeAttribute.call(this,name);}},descriptors:{textContent:{set:function(value){textContent.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:function(){return textContent.get();}},innerHTML:{set:function(value){innerHTML.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:innerHTML.get}}};var defaultPrototype=createProto(HTMLElement.prototype,base.properties);function getBaseProto(proto){if(!proto){return defaultPrototype;}
|
||||
proto=proto.prototype||proto;return!proto.GaiaComponent?createProto(proto,base.properties):proto;}
|
||||
function createProto(proto,props){return mixin(Object.create(proto),props);}
|
||||
var hasShadowCSS=(function(){var div=document.createElement('div');try{div.querySelector(':host');div.querySelector('::content');return true;}
|
||||
catch(e){return false;}})();var regex={shadowCss:/(?:\:host|\:\:content)[^{]*\{[^}]*\}/g,':host':/(?:\:host)/g,':host()':/\:host\((.+)\)(?: \:\:content)?/g,':host-context':/\:host-context\((.+)\)([^{,]+)?/g,'::content':/(?:\:\:content)/g};function processCss(template,name){var globalCss='';var lightCss='';if(!hasShadowCSS){template=template.replace(regex.shadowCss,function(match){var hostContext=regex[':host-context'].exec(match);if(hostContext){globalCss+=match.replace(regex['::content'],'').replace(regex[':host-context'],'$1 '+name+'$2').replace(/ +/g,' ');}else{lightCss+=match.replace(regex[':host()'],name+'$1').replace(regex[':host'],name).replace(regex['::content'],name);}
|
||||
return'';});}
|
||||
return{template:template,lightCss:lightCss,globalCss:globalCss};}
|
||||
function injectGlobalCss(css){if(!css){return;}
|
||||
var style=document.createElement('style');style.innerHTML=css.trim();headReady().then(function(){document.head.appendChild(style);});}
|
||||
function headReady(){return new Promise(function(resolve){if(document.head){return resolve();}
|
||||
window.addEventListener('load',function fn(){window.removeEventListener('load',fn);resolve();});});}
|
||||
function injectLightCss(el){if(hasShadowCSS){return;}
|
||||
var stylesheet=el.querySelector('style');if(!stylesheet){stylesheet=document.createElement('style');stylesheet.setAttribute('scoped','');stylesheet.appendChild(document.createTextNode(el.lightCss));el.appendChild(stylesheet);}
|
||||
el.lightStyle=stylesheet;}
|
||||
function toCamelCase(string){return string.replace(/-(.)/g,function replacer(string,p1){return p1.toUpperCase();});}
|
||||
var dirObserver;function setInnerDirAttributes(component){var dir=component.dir||document.dir;Array.from(component.shadowRoot.children).forEach(element=>{if(element.nodeName!=='STYLE'){element.dir=dir;}});}
|
||||
function addDirObserver(){if(dirObserver){return;}
|
||||
dirObserver=new MutationObserver(onChanged);dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});function onChanged(mutations){document.dispatchEvent(new Event('dirchanged'));}}
|
||||
function mixin(target,source){for(var key in source){target[key]=source[key];}
|
||||
return target;}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-component',this));},{}],3:[function(require,module,exports){(function(define){'use strict';define(function(require,exports,module){var base=window.GAIA_ICONS_BASE_URL||window.COMPONENTS_BASE_URL||'bower_components/';if(!document.documentElement){window.addEventListener('load',load);}else{load();}
|
||||
function load(){if(isLoaded()){return;}
|
||||
var link=document.createElement('link');link.rel='stylesheet';link.type='text/css';link.href=base+'gaia-icons/gaia-icons.css';document.head.appendChild(link);exports.loaded=true;}
|
||||
function isLoaded(){return exports.loaded||document.querySelector('link[href*=gaia-icons]')||document.documentElement.classList.contains('gaia-icons-loaded');}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-icons',this));},{}],4:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var component=require('gaia-component');var fontFit=require('font-fit');require('gaia-icons');var debug=0?console.log.bind(console):function(){};const KNOWN_ACTIONS={menu:'menu',back:'back',close:'close'};const TITLE_FONT='italic 300 24px FiraSans';const TITLE_PADDING=10;const MINIMUM_FONT_SIZE_CENTERED=20;const MINIMUM_FONT_SIZE_UNCENTERED=16;const MAXIMUM_FONT_SIZE=23;module.exports=component.register('gaia-header',{extensible:false,dirObserver:true,created:function(){debug('created');this.setupShadowRoot();this.els={actionButton:this.shadowRoot.querySelector('.action-button'),titles:this.getElementsByTagName('h1')};this.els.actionButton.addEventListener('click',e=>this.onActionButtonClick(e));this.observer=new MutationObserver(this.onMutation.bind(this));this.ignoreDir=this.hasAttribute('ignore-dir');this.titleEnd=this.getAttribute('title-end');this.titleStart=this.getAttribute('title-start');this.noFontFit=this.getAttribute('no-font-fit');this.notFlush=this.hasAttribute('not-flush');this.action=this.getAttribute('action');this.unresolved={};this.pending={};this._resizeThrottlingId=null;this.onResize=this.onResize.bind(this);},attached:function(){debug('attached');this.runFontFitSoon();this.observerStart();window.addEventListener('resize',this.onResize);},detached:function(){debug('detached');window.removeEventListener('resize',this.onResize);this.observerStop();this.clearPending();},clearPending:function(){for(var key in this.pending){this.pending[key].clear();delete this.pending[key];}
|
||||
window.cancelAnimationFrame(this._resizeThrottlingId);this._resizeThrottlingId=null;},runFontFit:function(){debug('run font-fit');if(this.noFontFit){return Promise.resolve();}
|
||||
var titles=this.els.titles;var space=this.getTitleSpace();var styles=[].map.call(titles,el=>this.getTitleStyle(el,space));return this.setTitleStylesSoon(styles);},runFontFitSoon:function(){debug('run font-fit soon');if(this.pending.runFontFitSoon){return;}
|
||||
this.pending.runFontFitSoon=this.nextTick(()=>{delete this.pending.runFontFitSoon;this.runFontFit();});},getTitleStyle:function(el,space){debug('get el style',el,space);var text=el.textContent;var styleId=space.start+text+space.end+'#'+space.value;if(!text||!text.trim()){return debug('exit: no text');}
|
||||
if(getStyleId(el)===styleId){return debug('exit: no change');}
|
||||
var marginStart=this.getTitleMarginStart();var textSpace=space.value-Math.abs(marginStart);var fontFitResult=this.fontFit(text,textSpace,{min:MINIMUM_FONT_SIZE_CENTERED});var overflowing=fontFitResult.overflowing;var padding={start:0,end:0};if(overflowing){debug('title overflowing');padding.start=!space.start?TITLE_PADDING:0;padding.end=!space.end?TITLE_PADDING:0;textSpace=space.value-padding.start-padding.end;fontFitResult=this.fontFit(text,textSpace);marginStart=0;}
|
||||
return{id:styleId,fontSize:fontFitResult.fontSize,marginStart:marginStart,overflowing:overflowing,padding:padding};},setTitleStylesSoon:function(styles){debug('set title styles soon',styles);var key='setStyleTitlesSoon';this._titleStyles=styles;if(this.unresolved[key]){return this.unresolved[key];}
|
||||
this.unresolved[key]=new Promise((resolve)=>{this.pending[key]=this.nextTick(()=>{var styles=this._titleStyles;var els=this.els.titles;[].forEach.call(els,(el,i)=>{if(!styles[i]){return debug('exit');}
|
||||
this.setTitleStyle(el,styles[i]);});delete this._titleStyles;delete this.unresolved[key];delete this.pending[key];resolve();});});},setTitleStyle:function(el,style){debug('set title style',style);this.observerStop();if(this.ignoreDir){el.style.marginLeft=style.marginStart+'px';el.style.paddingLeft=style.padding.start+'px';el.style.paddingRight=style.padding.end+'px';}else{el.style.marginInlineStart=style.marginStart+'px';el.style.paddingInlineStart=style.padding.start+'px';el.style.paddingInlineEnd=style.padding.end+'px';}
|
||||
el.style.fontSize=style.fontSize+'px';setStyleId(el,style.id);this.observerStart();},fontFit:function(text,space,opts={}){debug('font fit:',text,space,opts);var fontFitArgs={font:TITLE_FONT,min:opts.min||MINIMUM_FONT_SIZE_UNCENTERED,max:MAXIMUM_FONT_SIZE,text:text,space:space};return fontFit(fontFitArgs);},observerStart:function(){if(this.observing){return;}
|
||||
this.observer.observe(this,{childList:true,attributes:true,subtree:true});this.observing=true;debug('observer started');},observerStop:function(){if(!this.observing){return;}
|
||||
this.observer.disconnect();this.observing=false;debug('observer stopped');},onResize:function(e){debug('onResize',this._resizeThrottlingId);if(this._resizeThrottlingId!==null){return;}
|
||||
this._resizeThrottlingId=window.requestAnimationFrame(()=>{this._resizeThrottlingId=null;this.runFontFitSoon();});},onMutation:function(mutations){debug('on mutation',mutations);if(!this.pending.runFontFitSoon){this.runFontFit();}},getTitleSpace:function(){var start=this.titleStart;var end=this.titleEnd;var space=this.getWidth()-start-end;var result={value:space,start:start,end:end};debug('get title space',result);return result;},getWidth:function(){var value=this.notFlush?this.clientWidth:window.innerWidth;debug('get width',value);return value;},triggerAction:function(){if(this.action){this.els.actionButton.click();}},onActionButtonClick:function(){debug('action button click');var config={detail:{type:this.action}};var e=new CustomEvent('action',config);setTimeout(()=>this.dispatchEvent(e));},getTitleMarginStart:function(){var start=this.titleStart;var end=this.titleEnd;var marginStart=end-start;debug('get title margin start',marginStart);return marginStart;},getButtonsBeforeTitle:function(){var children=this.children;var l=children.length;var els=[];for(var i=0;i<l;i++){var el=children[i];if(el.tagName==='H1'){break;}
|
||||
if(!contributesToLayout(el)){continue;}
|
||||
els.push(el);}
|
||||
if(this.action){els.push(this.els.actionButton);}
|
||||
return els;},getButtonsAfterTitle:function(){var children=this.children;var els=[];for(var i=children.length-1;i>=0;i--){var el=children[i];if(el.tagName==='H1'){break;}
|
||||
if(!contributesToLayout(el)){continue;}
|
||||
els.push(el);}
|
||||
return els;},sumButtonWidths:function(buttons){var defaultWidth=50;var sum=buttons.reduce((prev,button)=>{var isStandardButton=button===this.els.actionButton;var width=isStandardButton?defaultWidth:button.clientWidth;return prev+width;},0);debug('sum button widths',buttons,sum);return sum;},attrs:{action:{get:function(){return this._action;},set:function(value){var action=KNOWN_ACTIONS[value];if(action===this._action){return;}
|
||||
this.setAttr('action',action);this._action=action;}},titleStart:{get:function(){debug('get title-start');if('_titleStart'in this){return this._titleStart;}
|
||||
var buttons=this.getButtonsBeforeTitle();var value=this.sumButtonWidths(buttons);debug('get title-start',buttons,value);return value;},set:function(value){debug('set title-start',value);value=parseInt(value,10);if(value===this._titleStart||isNaN(value)){return;}
|
||||
this.setAttr('title-start',value);this._titleStart=value;debug('set');}},titleEnd:{get:function(){debug('get title-end');if('_titleEnd'in this){return this._titleEnd;}
|
||||
var buttons=this.getButtonsAfterTitle();return this.sumButtonWidths(buttons);},set:function(value){debug('set title-end',value);value=parseInt(value,10);if(value===this._titleEnd||isNaN(value)){return;}
|
||||
this.setAttr('title-end',value);this._titleEnd=value;}},noFontFit:{get:function(){return this._noFontFit||false;},set:function(value){debug('set no-font-fit',value);value=!!(value||value==='');if(value===this.noFontFit){return;}
|
||||
this._noFontFit=value;if(value){this.setAttr('no-font-fit','');}
|
||||
else{this.removeAttr('no-font-fit');}}},ignoreDir:{get:function(){return this._ignoreDir||false;},set:function(value){debug('set ignore-dir',value);value=!!(value||value==='');if(value===this.ignoreDir){return;}
|
||||
this._ignoreDir=value;this.dirObserver=!value;if(value){this.setAttr('ignore-dir','');}
|
||||
else{this.removeAttr('ignore-dir');}}}},template:`<div class="inner">
|
||||
<button class="action-button">
|
||||
<content select="[l10n-action]"></content>
|
||||
</button>
|
||||
<content></content>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
-moz-user-select: none;
|
||||
|
||||
--gaia-header-button-color:
|
||||
var(--header-button-color,
|
||||
var(--header-color,
|
||||
var(--link-color,
|
||||
inherit)));
|
||||
}
|
||||
|
||||
/**
|
||||
* [hidden]
|
||||
*/
|
||||
|
||||
:host[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/** Reset
|
||||
---------------------------------------------------------*/
|
||||
|
||||
::-moz-focus-inner { border: 0; }
|
||||
|
||||
/** Inner
|
||||
---------------------------------------------------------*/
|
||||
|
||||
.inner {
|
||||
display: flex;
|
||||
min-height: 50px;
|
||||
-moz-user-select: none;
|
||||
|
||||
background:
|
||||
var(--header-background,
|
||||
var(--background,
|
||||
#fff));
|
||||
}
|
||||
|
||||
/** Action Button
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 1. Hidden by default
|
||||
*/
|
||||
|
||||
.action-button {
|
||||
position: relative;
|
||||
|
||||
display: none; /* 1 */
|
||||
width: 50px;
|
||||
font-size: 30px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
align-items: center;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
transition: opacity 200ms 280ms;
|
||||
color:
|
||||
var(--header-action-button-color,
|
||||
var(--header-icon-color,
|
||||
var(--gaia-header-button-color)));
|
||||
}
|
||||
|
||||
/**
|
||||
* [action=back]
|
||||
* [action=menu]
|
||||
* [action=close]
|
||||
*
|
||||
* 1. For icon vertical-alignment
|
||||
*/
|
||||
|
||||
[action=back] .action-button,
|
||||
[action=menu] .action-button,
|
||||
[action=close] .action-button {
|
||||
display: flex; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* :active
|
||||
*/
|
||||
|
||||
.action-button:active {
|
||||
transition: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
/** Action Button Icon
|
||||
---------------------------------------------------------*/
|
||||
|
||||
.action-button:before {
|
||||
font-family: 'gaia-icons';
|
||||
font-style: normal;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[action=close] .action-button:before { content: 'close' }
|
||||
[action=menu] .action-button:before { content: 'menu' }
|
||||
|
||||
[action=back]:-moz-dir(ltr) .action-button:before { content: 'left' }
|
||||
[action=back]:-moz-dir(rtl) .action-button:before { content: 'right' }
|
||||
|
||||
/** Action Button Icon
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 1. To enable vertical alignment.
|
||||
*/
|
||||
|
||||
.action-button:before {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/** Action Button Text
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* To provide custom localized content for
|
||||
* the action-button, we allow the user
|
||||
* to provide an element with the class
|
||||
* .l10n-action. This node is then
|
||||
* pulled inside the real action-button.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <gaia-header action="back">
|
||||
* <span l10n-action aria-label="Back">Localized text</span>
|
||||
* <h1>title</h1>
|
||||
* </gaia-header>
|
||||
*/
|
||||
|
||||
::content [l10n-action] {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
/** Title
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 1. Vertically center text. We can't use flexbox
|
||||
* here as it breaks text-overflow ellipsis
|
||||
* without an inner div.
|
||||
*/
|
||||
|
||||
::content h1 {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
text-align: center;
|
||||
line-height: 50px; /* 1 */
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
font-size: 24px;
|
||||
|
||||
color:
|
||||
var(--header-title-color,
|
||||
var(--header-color,
|
||||
var(--title-color,
|
||||
var(--text-color,
|
||||
inherit))));
|
||||
}
|
||||
|
||||
/**
|
||||
* [ignore-dir]
|
||||
*
|
||||
* When the <gaia-header> component has an [ignore-dir] attribute, header
|
||||
* direction is forced to LTR but we still want the <h1> text to be reversed
|
||||
* so that strings like '1 selected' become 'selected 1'.
|
||||
*
|
||||
* When we're happy for <gaia-header> to be fully RTL responsive we won't need
|
||||
* these rules anymore, but this depends on all Gaia apps being ready.
|
||||
*
|
||||
* This should be safe to remove when bug 1179459 lands.
|
||||
*/
|
||||
|
||||
:host[ignore-dir] {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
:host[ignore-dir]:-moz-dir(rtl) h1 {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
/** Buttons
|
||||
---------------------------------------------------------*/
|
||||
|
||||
::content a,
|
||||
::content button {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
width: auto;
|
||||
height: auto;
|
||||
min-width: 50px;
|
||||
margin: 0;
|
||||
padding: 0 10px;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
font-style: italic;
|
||||
cursor: pointer;
|
||||
transition: opacity 200ms 280ms;
|
||||
color: var(--gaia-header-button-color);
|
||||
}
|
||||
|
||||
/**
|
||||
* :active
|
||||
*/
|
||||
|
||||
::content a:active,
|
||||
::content button:active {
|
||||
transition: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
/**
|
||||
* [hidden]
|
||||
*/
|
||||
|
||||
::content a[hidden],
|
||||
::content button[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* [disabled]
|
||||
*/
|
||||
|
||||
::content a[disabled],
|
||||
::content button[disabled] {
|
||||
pointer-events: none;
|
||||
color: var(--header-disabled-button-color);
|
||||
}
|
||||
|
||||
/** Icon Buttons
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Icons are a different color to text
|
||||
*/
|
||||
|
||||
::content .icon,
|
||||
::content [data-icon] {
|
||||
color:
|
||||
var(--header-icon-color,
|
||||
var(--gaia-header-button-color));
|
||||
}
|
||||
|
||||
/**
|
||||
* If users want their action button
|
||||
* to be in the component's light-dom
|
||||
* they can add an .action class
|
||||
* to make it look like the
|
||||
* shadow action button.
|
||||
*/
|
||||
|
||||
::content .action {
|
||||
color:
|
||||
var(--header-action-button-color,
|
||||
var(--header-icon-color,
|
||||
var(--gaia-header-button-color)));
|
||||
}
|
||||
|
||||
/**
|
||||
* [data-icon]:empty
|
||||
*
|
||||
* Icon buttons with no textContent,
|
||||
* should always be 50px.
|
||||
*
|
||||
* This is to prevent buttons being
|
||||
* larger than they should be before
|
||||
* icon-font has loaded.
|
||||
*/
|
||||
|
||||
::content [data-icon]:empty {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
</style>`,nextTick:nextTick});function contributesToLayout(el){return el.localName!=='style'&&!el.hasAttribute('l10n-action');}
|
||||
function setStyleId(el,id){el._styleId=id;}
|
||||
function getStyleId(el){return el._styleId;}
|
||||
function nextTick(fn){var cleared;Promise.resolve().then(()=>{if(!cleared){fn();}});return{clear:function(){cleared=true;}};}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-header',this));},{"font-fit":1,"gaia-component":2,"gaia-icons":3}]},{},[4])(4)});;'use strict';var CostControlApp=(function(){var costcontrol,initialized=false,hashFromLastRun,hashFromNotification;var vmanager;function waitForSIMReady(callback){SimManager.requestDataSimIcc(function _onIccId(dataSim){var dataSimIcc=dataSim.icc;var cardState=dataSimIcc.cardState;if(cardState!=='ready'){showNonReadyScreen(cardState);debug('SIM not ready:',cardState);dataSimIcc.oncardstatechange=function(){waitForSIMReady(callback);};}else{hideNotReadyScreen();debug('SIM ready. ICCID:',dataSim.iccId);dataSimIcc.oncardstatechange=undefined;callback&&callback();}},function _errorNoSim(){console.warn('Error when trying to get the ICC, SIM not detected.');LazyLoader.load(['/shared/js/airplane_mode_helper.js'],function(){AirplaneModeHelper.ready(function(){var fakeState=null;if(AirplaneModeHelper.getStatus()==='enabled'){console.warn('The airplaneMode is enabled.');fakeState='airplaneMode';window.addEventListener('airplaneModeDisabled',function _onAirplanemodeDisabled(evt){if(evt.detail&&evt.detail.serviceId==='data'){waitForSIMReady(startApp);}});}
|
||||
showNonReadyScreen(fakeState);});});});}
|
||||
var nonReadyScreen;function showNonReadyScreen(cardState){if(isApplicationLocalized){realshowNonReadyScreen(cardState);}else{window.addEventListener('localized',function _onlocalized(){window.removeEventListener('localized',_onlocalized);realshowNonReadyScreen(cardState);});}
|
||||
function realshowNonReadyScreen(messageId){debug('Showing non-ready screen.');if(!nonReadyScreen){nonReadyScreen=new NonReadyScreen(document.getElementById('non-ready-screen'));}
|
||||
nonReadyScreen.updateForState(cardState);vmanager.changeViewTo(nonReadyScreen.id);}}
|
||||
function hideNotReadyScreen(status){debug('Hiding non-ready screen.');if(vmanager.getCurrentView()==='non-ready-screen'){vmanager.closeCurrentView();}
|
||||
return;}
|
||||
var tabmanager,settingsVManager;function _onHashChange(evt){var parser=document.createElement('a');parser.href=evt.oldURL;var oldHash=parser.hash.split('#');parser.href=evt.newURL;var newHash=parser.hash.split('#');if(newHash.length>3){console.error('Cost Control bad URL schema');return;}
|
||||
debug('URL schema before normalizing:',newHash);var normalized=false;if(!newHash[1]&&oldHash[1]){newHash[1]=oldHash[1];normalized=true;}
|
||||
if(newHash.length===3&&newHash[2]===''){if(oldHash.length===3){newHash[2]=oldHash[2];}else{newHash=newHash.slice(0,2);}
|
||||
normalized=true;}
|
||||
if(normalized){debug('URL schema after normalization:',newHash);window.location.hash=newHash.join('#');return;}
|
||||
if(newHash[1]){tabmanager.changeViewTo(newHash[1]);}
|
||||
if(newHash.length<3){vmanager.closeCurrentView();}else{vmanager.changeViewTo(newHash[2],'#tabpanel');}}
|
||||
function setupCardHandler(){tabmanager=new ViewManager(['balance-tab','telephony-tab',{id:'datausage-tab',tab:'right'}]);settingsVManager=new ViewManager();window.addEventListener('hashchange',_onHashChange);}
|
||||
function loadMessageHandler(){var messageHandlerFrame=document.getElementById('message-handler');var thereIsNextReset=ConfigManager.option('nextReset');var alreadyLoaded=messageHandlerFrame.src.contains('message_handler.html');if(alreadyLoaded&&thereIsNextReset){setNextReset(ConfigManager.option('nextReset'));return;}
|
||||
if(thereIsNextReset){window.addEventListener('messagehandlerready',function _setNextReset(){window.removeEventListener('messagehandlerready',_setNextReset);setNextReset(ConfigManager.option('nextReset'));});}
|
||||
messageHandlerFrame.src='message_handler.html';}
|
||||
function _onDataSimChange(){CostControl.reset();ConfigManager.setConfig(null);SimManager.requestDataSimIcc(startApp);}
|
||||
function startApp(callback){if(!ConfigManager.supportCustomizeMode){SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function(settings){if(settings.trackingPeriod==='custom'){ConfigManager.setOption({trackingPeriod:'never'});asyncStorage.getItem('nextResetAlarm',function(id){debug('Current nextResetAlarm',id+'.',id?'Removing.':'');if(id){navigator.mozAlarms.remove(id);}
|
||||
asyncStorage.setItem('nextResetAlarm',null,function(){ConfigManager.setOption({nextReset:null});});});}});});}
|
||||
if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',_onDataSimChange);}
|
||||
CostControl.getInstance(function _onCostControlReady(instance){if(ConfigManager.option('fte')){startFTE();return;}
|
||||
loadMessageHandler();costcontrol=instance;if(!initialized){setupApp(callback);}else{loadSettings();updateUI(callback);}});}
|
||||
var isApplicationLocalized=false;window.addEventListener('localized',function _onLocalize(){isApplicationLocalized=true;if(initialized){updateUI();loadSettings();}});function setupApp(callback){setupCardHandler();var settingsButtons=document.querySelectorAll('.settings-button');Array.prototype.forEach.call(settingsButtons,function _eachSettingsButton(button){button.addEventListener('click',function _showSettings(){window.location.hash='##settings-view';});});navigator.mozSetMessageHandler('activity',function _handleActivity(activityRequest){var name=activityRequest.source.name;switch(name){case'costcontrol/balance':window.location.hash='#balance-tab';break;case'costcontrol/telephony':window.location.hash='#telephony-tab';break;case'costcontrol/data_usage':window.location.hash='#datausage-tab';break;}});window.navigator.mozSetMessageHandler('notification',function _onNotification(notification){if(!notification.clicked){return;}
|
||||
debug('Notification was clicked!');navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){var app=evt.target.result;app.launch();var type=notification.data;debug('Notification type:',type);handleNotification(type);};});document.addEventListener('visibilitychange',function _onVisibilityChange(evt){if(!document.hidden&&initialized){waitForSIMReady();}});updateUI(callback);ConfigManager.observe('plantype',updateUI,true);initialized=true;loadSettings();}
|
||||
function loadSettings(){window.performance.mark('loadSettingsStart');document.getElementById('settings-view-placeholder').src='settings.html';}
|
||||
function handleNotification(type){switch(type){case'topUpError':BalanceTab.topUpWithCode(true);break;case'lowBalance':case'zeroBalance':window.location.hash='#balance-tab';hashFromNotification='#balance-tab';break;case'dataUsage':hashFromNotification='#datausage-tab';tabmanager.changeViewTo('datausage-tab');break;}}
|
||||
var currentMode;function updateUI(callback){SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){var mode=ConfigManager.getApplicationMode();var newHash=window.location.hash;var tabs=document.getElementById('tabs');var dataUsageTab=document.getElementById('datausage-tab');debug('App UI mode: ',mode);if(mode!==currentMode){currentMode=mode;if(mode==='DATA_USAGE_ONLY'){tabs.hidden=true;dataUsageTab.classList.add('standalone');newHash='#datausage-tab';}else{dataUsageTab.classList.remove('standalone');tabs.hidden=false;document.getElementById('balance-tab-filter').hidden=(mode!=='PREPAID');document.getElementById('telephony-tab-filter').hidden=(mode!=='POSTPAID');if(!isDataUsageTabShown()){newHash=(mode==='PREPAID')?'#balance-tab#':'#telephony-tab#';}}
|
||||
window.location.hash=hashFromNotification||hashFromLastRun||newHash;hashFromLastRun=hashFromNotification=null;requestAnimationFrame(function continueLoading(){document.getElementById('main').classList.remove('non-ready');if(mode==='PREPAID'){if(typeof TelephonyTab!=='undefined'){TelephonyTab.finalize();}
|
||||
if(typeof BalanceTab!=='undefined'){BalanceTab.initialize();}}else if(mode==='POSTPAID'){if(typeof BalanceTab!=='undefined'){BalanceTab.finalize();}
|
||||
if(typeof TelephonyTab!=='undefined'){TelephonyTab.initialize();}}});}
|
||||
(typeof callback==='function')&&callback();});});}
|
||||
function isDataUsageTabShown(){return window.location.hash.split('#')[1]==='datausage-tab';}
|
||||
function onFteFinished(e){if(e.origin!==Common.COST_CONTROL_APP){return;}
|
||||
var type=e.data.type;if(type==='fte_finished'){window.removeEventListener('message',onFteFinished);document.getElementById('splash_section').hidden='true';ConfigManager.requestAll(function(){startApp(Common.closeFTE);});}}
|
||||
function startFTE(){window.addEventListener('message',onFteFinished);var mode=ConfigManager.getApplicationMode();Common.startFTE(mode);}
|
||||
function initApp(){hashFromLastRun=window.location.hash;window.location.hash='';vmanager=new ViewManager();waitForSIMReady(startApp);}
|
||||
return{init:function(){var SCRIPTS_NEEDED=['js/utils/debug.js','js/common.js','js/views/NonReadyScreen.js','js/utils/toolkit.js','js/view_manager.js'];if(!window.navigator.mozMobileConnections||!window.navigator.mozIccManager||!window.navigator.mozNetworkStats){LazyLoader.load(SCRIPTS_NEEDED,function _showError(){vmanager=new ViewManager();showNonReadyScreen(null);});}else{SCRIPTS_NEEDED=['js/sim_manager.js','js/utils/debug.js','shared/js/date_time_helper.js','js/utils/chart.js','js/utils/formatting.js','js/utils/toolkit.js','js/settings/networkUsageAlarm.js','js/common.js','js/costcontrol.js','js/config/config_manager.js','js/views/NonReadyScreen.js','js/view_manager.js'];LazyLoader.load(SCRIPTS_NEEDED,initApp);}
|
||||
if(navigator.mozAudioChannelManager){navigator.mozAudioChannelManager.volumeControlChannel='notification';}},reset:function(){costcontrol=null;initialized=false;vmanager=null;tabmanager=null;settingsVManager=null;currentMode=null;isApplicationLocalized=false;window.removeEventListener('dataSlotChange',_onDataSimChange);window.removeEventListener('hashchange',_onHashChange);window.removeEventListener('message',onFteFinished);window.location.hash='';nonReadyScreen=null;},showBalanceTab:function _showBalanceTab(){window.location.hash='#balance-tab';},showDataUsageTab:function _showDataUsageTab(){window.location.hash='#datausage-tab';},showAppDetailView:function _showAppDetailView(){window.location.hash='##appdetail-view';},_onHashChange:_onHashChange};}());;'use strict';CostControlApp.init();
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
;'use strict';var NetworkUsageAlarm=(function(){function _addAlarm(networkInterface,value,onsuccess,onerror){if(!networkInterface){console.error('Error, the network interface is not defined when trying '+'to add an alarm');(typeof onerror==='function')&&onerror();return;}
|
||||
if(value===null||typeof value==='undefined'){console.error('Limit value is undefined, impossible add an alarm');(typeof onerror==='function')&&onerror();return;}
|
||||
var request=navigator.mozNetworkStats.addAlarm(networkInterface,value);request.onsuccess=onsuccess;request.onerror=function error(e){console.error('Error, when trying to addAlarm to the interfaceId: '+
|
||||
networkInterface.id+' and limit: '+value);(typeof onerror==='function')&&onerror();};}
|
||||
function _clearAlarms(networkInterface,callback){if(!networkInterface){console.error('Error, the network interface is not defined when trying '+'to remove alarms');return;}
|
||||
var request=navigator.mozNetworkStats.getAllAlarms(networkInterface);request.onsuccess=function success(){var alarmList=request.result;var pendingRequest=alarmList.length;function checkForCompletion(){pendingRequest--;if(pendingRequest===0){(typeof callback==='function')&&callback();}}
|
||||
function _onErrorRemoveAlarm(){console.error('Error when trying to remove one alarm.');checkForCompletion();}
|
||||
for(var i=0;i<alarmList.length;i++){if(alarmList[i]&&alarmList[i].alarmId){var rA=navigator.mozNetworkStats.removeAlarms(alarmList[i].alarmId);rA.onsuccess=checkForCompletion;rA.onerror=_onErrorRemoveAlarm;}}
|
||||
if(pendingRequest===0){(typeof callback==='function')&&callback();}};request.onerror=function error(){console.error('Error when trying to get alarms from the API to clear it');};}
|
||||
function _updateAlarm(dataInterface,value,onsuccess,onerror){if(dataInterface&&value){var addNewAlarm=_addAlarm.bind(null,dataInterface,value,onsuccess,onerror);_clearAlarms(dataInterface,addNewAlarm);}else{if(!dataInterface){console.error('Error, the network interface is not defined when '+'trying to update an alarm');}else{console.error('Error, the data limit value is not defined when '+'trying to update an alarm');}
|
||||
(typeof onerror==='function')&&onerror();}}
|
||||
return{updateAlarm:_updateAlarm,clearAlarms:_clearAlarms};}());
|
||||
|
|
@ -0,0 +1,664 @@
|
|||
;;;;;(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);;;;;;'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();}());;;;window.COMPONENTS_BASE_URL='/shared/elements/';;;;(function(exports){'use strict';exports.ComponentUtils={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';style.addEventListener('load',function(){if(self.shadowRoot){self.shadowRoot.appendChild(style.cloneNode(true));}
|
||||
self.style.visibility='';});}};}(window));;;;(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GaiaHeader=f()}})(function(){var define,module,exports;return(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){;(function(define){define(function(require,exports,module){'use strict';var debug=0?console.log.bind(console):function(){};var cache={};var MIN=16;var MAX=24;var BUFFER=3;module.exports=function(config){debug('font fit',config);var space=config.space-BUFFER;var min=config.min||MIN;var max=config.max||MAX;var text=trim(config.text);var fontSize=max;var textWidth;var font;do{font=config.font.replace(/\d+px/,fontSize+'px');textWidth=getTextWidth(text,font);}while(textWidth>space&&fontSize!==min&&fontSize--);return{textWidth:textWidth,fontSize:fontSize,overflowing:textWidth>space};};function getTextWidth(text,font){var ctx=getCanvasContext(font);var width=ctx.measureText(text).width;debug('got text width',width);return width;}
|
||||
function getCanvasContext(font){debug('get canvas context',font);var cached=cache[font];if(cached){return cached;}
|
||||
var canvas=document.createElement('canvas');canvas.setAttribute('moz-opaque','true');canvas.setAttribute('width','1px');canvas.setAttribute('height','1px');debug('created canvas',canvas);var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.font=font;return cache[font]=ctx;}
|
||||
function trim(text){return text.replace(/\s+/g,' ').trim();}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('font-fit',this));},{}],2:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var textContent=Object.getOwnPropertyDescriptor(Node.prototype,'textContent');var innerHTML=Object.getOwnPropertyDescriptor(Element.prototype,'innerHTML');var removeAttribute=Element.prototype.removeAttribute;var setAttribute=Element.prototype.setAttribute;var noop=function(){};exports.register=function(name,props){var baseProto=getBaseProto(props.extends);var template=props.template||baseProto.templateString;var extensible=props.extensible=props.hasOwnProperty('extensible')?props.extensible:true;delete props.extends;if(template){if(extensible&&props.template){props.templateString=props.template;}
|
||||
var output=processCss(template,name);props.template=document.createElement('template');props.template.innerHTML=output.template;props.lightCss=output.lightCss;props.globalCss=props.globalCss||'';props.globalCss+=output.globalCss;}
|
||||
injectGlobalCss(props.globalCss);delete props.globalCss;var descriptors=mixin(props.attrs||{},base.descriptors);props._attrs=props.attrs;delete props.attrs;var proto=createProto(baseProto,props);Object.defineProperties(proto,descriptors);try{return document.registerElement(name,{prototype:proto});}catch(e){if(e.name!=='NotSupportedError'){throw e;}}};var base={properties:{GaiaComponent:true,attributeChanged:noop,attached:noop,detached:noop,created:noop,createdCallback:function(){if(this.dirObserver){addDirObserver();}
|
||||
injectLightCss(this);this.created();},attributeChangedCallback:function(name,from,to){var prop=toCamelCase(name);if(this._attrs&&this._attrs[prop]){this[prop]=to;}
|
||||
this.attributeChanged(name,from,to);},attachedCallback:function(){if(this.dirObserver){this.setInnerDirAttributes=setInnerDirAttributes.bind(null,this);document.addEventListener('dirchanged',this.setInnerDirAttributes);}
|
||||
this.attached();},detachedCallback:function(){if(this.dirObserver){document.removeEventListener('dirchanged',this.setInnerDirAttributes);}
|
||||
this.detached();},setupShadowRoot:function(){if(!this.template){return;}
|
||||
var node=document.importNode(this.template.content,true);this.createShadowRoot().appendChild(node);if(this.dirObserver){setInnerDirAttributes(this);}
|
||||
return this.shadowRoot;},setAttr:function(name,value){var internal=this.shadowRoot.firstElementChild;setAttribute.call(internal,name,value);setAttribute.call(this,name,value);},removeAttr:function(name){var internal=this.shadowRoot.firstElementChild;removeAttribute.call(internal,name);removeAttribute.call(this,name);}},descriptors:{textContent:{set:function(value){textContent.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:function(){return textContent.get();}},innerHTML:{set:function(value){innerHTML.set.call(this,value);if(this.lightStyle){this.appendChild(this.lightStyle);}},get:innerHTML.get}}};var defaultPrototype=createProto(HTMLElement.prototype,base.properties);function getBaseProto(proto){if(!proto){return defaultPrototype;}
|
||||
proto=proto.prototype||proto;return!proto.GaiaComponent?createProto(proto,base.properties):proto;}
|
||||
function createProto(proto,props){return mixin(Object.create(proto),props);}
|
||||
var hasShadowCSS=(function(){var div=document.createElement('div');try{div.querySelector(':host');div.querySelector('::content');return true;}
|
||||
catch(e){return false;}})();var regex={shadowCss:/(?:\:host|\:\:content)[^{]*\{[^}]*\}/g,':host':/(?:\:host)/g,':host()':/\:host\((.+)\)(?: \:\:content)?/g,':host-context':/\:host-context\((.+)\)([^{,]+)?/g,'::content':/(?:\:\:content)/g};function processCss(template,name){var globalCss='';var lightCss='';if(!hasShadowCSS){template=template.replace(regex.shadowCss,function(match){var hostContext=regex[':host-context'].exec(match);if(hostContext){globalCss+=match.replace(regex['::content'],'').replace(regex[':host-context'],'$1 '+name+'$2').replace(/ +/g,' ');}else{lightCss+=match.replace(regex[':host()'],name+'$1').replace(regex[':host'],name).replace(regex['::content'],name);}
|
||||
return'';});}
|
||||
return{template:template,lightCss:lightCss,globalCss:globalCss};}
|
||||
function injectGlobalCss(css){if(!css){return;}
|
||||
var style=document.createElement('style');style.innerHTML=css.trim();headReady().then(function(){document.head.appendChild(style);});}
|
||||
function headReady(){return new Promise(function(resolve){if(document.head){return resolve();}
|
||||
window.addEventListener('load',function fn(){window.removeEventListener('load',fn);resolve();});});}
|
||||
function injectLightCss(el){if(hasShadowCSS){return;}
|
||||
var stylesheet=el.querySelector('style');if(!stylesheet){stylesheet=document.createElement('style');stylesheet.setAttribute('scoped','');stylesheet.appendChild(document.createTextNode(el.lightCss));el.appendChild(stylesheet);}
|
||||
el.lightStyle=stylesheet;}
|
||||
function toCamelCase(string){return string.replace(/-(.)/g,function replacer(string,p1){return p1.toUpperCase();});}
|
||||
var dirObserver;function setInnerDirAttributes(component){var dir=component.dir||document.dir;Array.from(component.shadowRoot.children).forEach(element=>{if(element.nodeName!=='STYLE'){element.dir=dir;}});}
|
||||
function addDirObserver(){if(dirObserver){return;}
|
||||
dirObserver=new MutationObserver(onChanged);dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});function onChanged(mutations){document.dispatchEvent(new Event('dirchanged'));}}
|
||||
function mixin(target,source){for(var key in source){target[key]=source[key];}
|
||||
return target;}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-component',this));},{}],3:[function(require,module,exports){(function(define){'use strict';define(function(require,exports,module){var base=window.GAIA_ICONS_BASE_URL||window.COMPONENTS_BASE_URL||'bower_components/';if(!document.documentElement){window.addEventListener('load',load);}else{load();}
|
||||
function load(){if(isLoaded()){return;}
|
||||
var link=document.createElement('link');link.rel='stylesheet';link.type='text/css';link.href=base+'gaia-icons/gaia-icons.css';document.head.appendChild(link);exports.loaded=true;}
|
||||
function isLoaded(){return exports.loaded||document.querySelector('link[href*=gaia-icons]')||document.documentElement.classList.contains('gaia-icons-loaded');}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-icons',this));},{}],4:[function(require,module,exports){;(function(define){'use strict';define(function(require,exports,module){var component=require('gaia-component');var fontFit=require('font-fit');require('gaia-icons');var debug=0?console.log.bind(console):function(){};const KNOWN_ACTIONS={menu:'menu',back:'back',close:'close'};const TITLE_FONT='italic 300 24px FiraSans';const TITLE_PADDING=10;const MINIMUM_FONT_SIZE_CENTERED=20;const MINIMUM_FONT_SIZE_UNCENTERED=16;const MAXIMUM_FONT_SIZE=23;module.exports=component.register('gaia-header',{extensible:false,dirObserver:true,created:function(){debug('created');this.setupShadowRoot();this.els={actionButton:this.shadowRoot.querySelector('.action-button'),titles:this.getElementsByTagName('h1')};this.els.actionButton.addEventListener('click',e=>this.onActionButtonClick(e));this.observer=new MutationObserver(this.onMutation.bind(this));this.ignoreDir=this.hasAttribute('ignore-dir');this.titleEnd=this.getAttribute('title-end');this.titleStart=this.getAttribute('title-start');this.noFontFit=this.getAttribute('no-font-fit');this.notFlush=this.hasAttribute('not-flush');this.action=this.getAttribute('action');this.unresolved={};this.pending={};this._resizeThrottlingId=null;this.onResize=this.onResize.bind(this);},attached:function(){debug('attached');this.runFontFitSoon();this.observerStart();window.addEventListener('resize',this.onResize);},detached:function(){debug('detached');window.removeEventListener('resize',this.onResize);this.observerStop();this.clearPending();},clearPending:function(){for(var key in this.pending){this.pending[key].clear();delete this.pending[key];}
|
||||
window.cancelAnimationFrame(this._resizeThrottlingId);this._resizeThrottlingId=null;},runFontFit:function(){debug('run font-fit');if(this.noFontFit){return Promise.resolve();}
|
||||
var titles=this.els.titles;var space=this.getTitleSpace();var styles=[].map.call(titles,el=>this.getTitleStyle(el,space));return this.setTitleStylesSoon(styles);},runFontFitSoon:function(){debug('run font-fit soon');if(this.pending.runFontFitSoon){return;}
|
||||
this.pending.runFontFitSoon=this.nextTick(()=>{delete this.pending.runFontFitSoon;this.runFontFit();});},getTitleStyle:function(el,space){debug('get el style',el,space);var text=el.textContent;var styleId=space.start+text+space.end+'#'+space.value;if(!text||!text.trim()){return debug('exit: no text');}
|
||||
if(getStyleId(el)===styleId){return debug('exit: no change');}
|
||||
var marginStart=this.getTitleMarginStart();var textSpace=space.value-Math.abs(marginStart);var fontFitResult=this.fontFit(text,textSpace,{min:MINIMUM_FONT_SIZE_CENTERED});var overflowing=fontFitResult.overflowing;var padding={start:0,end:0};if(overflowing){debug('title overflowing');padding.start=!space.start?TITLE_PADDING:0;padding.end=!space.end?TITLE_PADDING:0;textSpace=space.value-padding.start-padding.end;fontFitResult=this.fontFit(text,textSpace);marginStart=0;}
|
||||
return{id:styleId,fontSize:fontFitResult.fontSize,marginStart:marginStart,overflowing:overflowing,padding:padding};},setTitleStylesSoon:function(styles){debug('set title styles soon',styles);var key='setStyleTitlesSoon';this._titleStyles=styles;if(this.unresolved[key]){return this.unresolved[key];}
|
||||
this.unresolved[key]=new Promise((resolve)=>{this.pending[key]=this.nextTick(()=>{var styles=this._titleStyles;var els=this.els.titles;[].forEach.call(els,(el,i)=>{if(!styles[i]){return debug('exit');}
|
||||
this.setTitleStyle(el,styles[i]);});delete this._titleStyles;delete this.unresolved[key];delete this.pending[key];resolve();});});},setTitleStyle:function(el,style){debug('set title style',style);this.observerStop();if(this.ignoreDir){el.style.marginLeft=style.marginStart+'px';el.style.paddingLeft=style.padding.start+'px';el.style.paddingRight=style.padding.end+'px';}else{el.style.marginInlineStart=style.marginStart+'px';el.style.paddingInlineStart=style.padding.start+'px';el.style.paddingInlineEnd=style.padding.end+'px';}
|
||||
el.style.fontSize=style.fontSize+'px';setStyleId(el,style.id);this.observerStart();},fontFit:function(text,space,opts={}){debug('font fit:',text,space,opts);var fontFitArgs={font:TITLE_FONT,min:opts.min||MINIMUM_FONT_SIZE_UNCENTERED,max:MAXIMUM_FONT_SIZE,text:text,space:space};return fontFit(fontFitArgs);},observerStart:function(){if(this.observing){return;}
|
||||
this.observer.observe(this,{childList:true,attributes:true,subtree:true});this.observing=true;debug('observer started');},observerStop:function(){if(!this.observing){return;}
|
||||
this.observer.disconnect();this.observing=false;debug('observer stopped');},onResize:function(e){debug('onResize',this._resizeThrottlingId);if(this._resizeThrottlingId!==null){return;}
|
||||
this._resizeThrottlingId=window.requestAnimationFrame(()=>{this._resizeThrottlingId=null;this.runFontFitSoon();});},onMutation:function(mutations){debug('on mutation',mutations);if(!this.pending.runFontFitSoon){this.runFontFit();}},getTitleSpace:function(){var start=this.titleStart;var end=this.titleEnd;var space=this.getWidth()-start-end;var result={value:space,start:start,end:end};debug('get title space',result);return result;},getWidth:function(){var value=this.notFlush?this.clientWidth:window.innerWidth;debug('get width',value);return value;},triggerAction:function(){if(this.action){this.els.actionButton.click();}},onActionButtonClick:function(){debug('action button click');var config={detail:{type:this.action}};var e=new CustomEvent('action',config);setTimeout(()=>this.dispatchEvent(e));},getTitleMarginStart:function(){var start=this.titleStart;var end=this.titleEnd;var marginStart=end-start;debug('get title margin start',marginStart);return marginStart;},getButtonsBeforeTitle:function(){var children=this.children;var l=children.length;var els=[];for(var i=0;i<l;i++){var el=children[i];if(el.tagName==='H1'){break;}
|
||||
if(!contributesToLayout(el)){continue;}
|
||||
els.push(el);}
|
||||
if(this.action){els.push(this.els.actionButton);}
|
||||
return els;},getButtonsAfterTitle:function(){var children=this.children;var els=[];for(var i=children.length-1;i>=0;i--){var el=children[i];if(el.tagName==='H1'){break;}
|
||||
if(!contributesToLayout(el)){continue;}
|
||||
els.push(el);}
|
||||
return els;},sumButtonWidths:function(buttons){var defaultWidth=50;var sum=buttons.reduce((prev,button)=>{var isStandardButton=button===this.els.actionButton;var width=isStandardButton?defaultWidth:button.clientWidth;return prev+width;},0);debug('sum button widths',buttons,sum);return sum;},attrs:{action:{get:function(){return this._action;},set:function(value){var action=KNOWN_ACTIONS[value];if(action===this._action){return;}
|
||||
this.setAttr('action',action);this._action=action;}},titleStart:{get:function(){debug('get title-start');if('_titleStart'in this){return this._titleStart;}
|
||||
var buttons=this.getButtonsBeforeTitle();var value=this.sumButtonWidths(buttons);debug('get title-start',buttons,value);return value;},set:function(value){debug('set title-start',value);value=parseInt(value,10);if(value===this._titleStart||isNaN(value)){return;}
|
||||
this.setAttr('title-start',value);this._titleStart=value;debug('set');}},titleEnd:{get:function(){debug('get title-end');if('_titleEnd'in this){return this._titleEnd;}
|
||||
var buttons=this.getButtonsAfterTitle();return this.sumButtonWidths(buttons);},set:function(value){debug('set title-end',value);value=parseInt(value,10);if(value===this._titleEnd||isNaN(value)){return;}
|
||||
this.setAttr('title-end',value);this._titleEnd=value;}},noFontFit:{get:function(){return this._noFontFit||false;},set:function(value){debug('set no-font-fit',value);value=!!(value||value==='');if(value===this.noFontFit){return;}
|
||||
this._noFontFit=value;if(value){this.setAttr('no-font-fit','');}
|
||||
else{this.removeAttr('no-font-fit');}}},ignoreDir:{get:function(){return this._ignoreDir||false;},set:function(value){debug('set ignore-dir',value);value=!!(value||value==='');if(value===this.ignoreDir){return;}
|
||||
this._ignoreDir=value;this.dirObserver=!value;if(value){this.setAttr('ignore-dir','');}
|
||||
else{this.removeAttr('ignore-dir');}}}},template:`<div class="inner">
|
||||
<button class="action-button">
|
||||
<content select="[l10n-action]"></content>
|
||||
</button>
|
||||
<content></content>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
-moz-user-select: none;
|
||||
|
||||
--gaia-header-button-color:
|
||||
var(--header-button-color,
|
||||
var(--header-color,
|
||||
var(--link-color,
|
||||
inherit)));
|
||||
}
|
||||
|
||||
/**
|
||||
* [hidden]
|
||||
*/
|
||||
|
||||
:host[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/** Reset
|
||||
---------------------------------------------------------*/
|
||||
|
||||
::-moz-focus-inner { border: 0; }
|
||||
|
||||
/** Inner
|
||||
---------------------------------------------------------*/
|
||||
|
||||
.inner {
|
||||
display: flex;
|
||||
min-height: 50px;
|
||||
-moz-user-select: none;
|
||||
|
||||
background:
|
||||
var(--header-background,
|
||||
var(--background,
|
||||
#fff));
|
||||
}
|
||||
|
||||
/** Action Button
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 1. Hidden by default
|
||||
*/
|
||||
|
||||
.action-button {
|
||||
position: relative;
|
||||
|
||||
display: none; /* 1 */
|
||||
width: 50px;
|
||||
font-size: 30px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
align-items: center;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
transition: opacity 200ms 280ms;
|
||||
color:
|
||||
var(--header-action-button-color,
|
||||
var(--header-icon-color,
|
||||
var(--gaia-header-button-color)));
|
||||
}
|
||||
|
||||
/**
|
||||
* [action=back]
|
||||
* [action=menu]
|
||||
* [action=close]
|
||||
*
|
||||
* 1. For icon vertical-alignment
|
||||
*/
|
||||
|
||||
[action=back] .action-button,
|
||||
[action=menu] .action-button,
|
||||
[action=close] .action-button {
|
||||
display: flex; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* :active
|
||||
*/
|
||||
|
||||
.action-button:active {
|
||||
transition: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
/** Action Button Icon
|
||||
---------------------------------------------------------*/
|
||||
|
||||
.action-button:before {
|
||||
font-family: 'gaia-icons';
|
||||
font-style: normal;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[action=close] .action-button:before { content: 'close' }
|
||||
[action=menu] .action-button:before { content: 'menu' }
|
||||
|
||||
[action=back]:-moz-dir(ltr) .action-button:before { content: 'left' }
|
||||
[action=back]:-moz-dir(rtl) .action-button:before { content: 'right' }
|
||||
|
||||
/** Action Button Icon
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 1. To enable vertical alignment.
|
||||
*/
|
||||
|
||||
.action-button:before {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/** Action Button Text
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* To provide custom localized content for
|
||||
* the action-button, we allow the user
|
||||
* to provide an element with the class
|
||||
* .l10n-action. This node is then
|
||||
* pulled inside the real action-button.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <gaia-header action="back">
|
||||
* <span l10n-action aria-label="Back">Localized text</span>
|
||||
* <h1>title</h1>
|
||||
* </gaia-header>
|
||||
*/
|
||||
|
||||
::content [l10n-action] {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
/** Title
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 1. Vertically center text. We can't use flexbox
|
||||
* here as it breaks text-overflow ellipsis
|
||||
* without an inner div.
|
||||
*/
|
||||
|
||||
::content h1 {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
text-align: center;
|
||||
line-height: 50px; /* 1 */
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
font-size: 24px;
|
||||
|
||||
color:
|
||||
var(--header-title-color,
|
||||
var(--header-color,
|
||||
var(--title-color,
|
||||
var(--text-color,
|
||||
inherit))));
|
||||
}
|
||||
|
||||
/**
|
||||
* [ignore-dir]
|
||||
*
|
||||
* When the <gaia-header> component has an [ignore-dir] attribute, header
|
||||
* direction is forced to LTR but we still want the <h1> text to be reversed
|
||||
* so that strings like '1 selected' become 'selected 1'.
|
||||
*
|
||||
* When we're happy for <gaia-header> to be fully RTL responsive we won't need
|
||||
* these rules anymore, but this depends on all Gaia apps being ready.
|
||||
*
|
||||
* This should be safe to remove when bug 1179459 lands.
|
||||
*/
|
||||
|
||||
:host[ignore-dir] {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
:host[ignore-dir]:-moz-dir(rtl) h1 {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
/** Buttons
|
||||
---------------------------------------------------------*/
|
||||
|
||||
::content a,
|
||||
::content button {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
width: auto;
|
||||
height: auto;
|
||||
min-width: 50px;
|
||||
margin: 0;
|
||||
padding: 0 10px;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
font-style: italic;
|
||||
cursor: pointer;
|
||||
transition: opacity 200ms 280ms;
|
||||
color: var(--gaia-header-button-color);
|
||||
}
|
||||
|
||||
/**
|
||||
* :active
|
||||
*/
|
||||
|
||||
::content a:active,
|
||||
::content button:active {
|
||||
transition: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
/**
|
||||
* [hidden]
|
||||
*/
|
||||
|
||||
::content a[hidden],
|
||||
::content button[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* [disabled]
|
||||
*/
|
||||
|
||||
::content a[disabled],
|
||||
::content button[disabled] {
|
||||
pointer-events: none;
|
||||
color: var(--header-disabled-button-color);
|
||||
}
|
||||
|
||||
/** Icon Buttons
|
||||
---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Icons are a different color to text
|
||||
*/
|
||||
|
||||
::content .icon,
|
||||
::content [data-icon] {
|
||||
color:
|
||||
var(--header-icon-color,
|
||||
var(--gaia-header-button-color));
|
||||
}
|
||||
|
||||
/**
|
||||
* If users want their action button
|
||||
* to be in the component's light-dom
|
||||
* they can add an .action class
|
||||
* to make it look like the
|
||||
* shadow action button.
|
||||
*/
|
||||
|
||||
::content .action {
|
||||
color:
|
||||
var(--header-action-button-color,
|
||||
var(--header-icon-color,
|
||||
var(--gaia-header-button-color)));
|
||||
}
|
||||
|
||||
/**
|
||||
* [data-icon]:empty
|
||||
*
|
||||
* Icon buttons with no textContent,
|
||||
* should always be 50px.
|
||||
*
|
||||
* This is to prevent buttons being
|
||||
* larger than they should be before
|
||||
* icon-font has loaded.
|
||||
*/
|
||||
|
||||
::content [data-icon]:empty {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
</style>`,nextTick:nextTick});function contributesToLayout(el){return el.localName!=='style'&&!el.hasAttribute('l10n-action');}
|
||||
function setStyleId(el,id){el._styleId=id;}
|
||||
function getStyleId(el){return el._styleId;}
|
||||
function nextTick(fn){var cleared;Promise.resolve().then(()=>{if(!cleared){fn();}});return{clear:function(){cleared=true;}};}});})(typeof define=='function'&&define.amd?define:(function(n,w){'use strict';return typeof module=='object'?function(c){c(require,exports,module);}:function(c){var m={exports:{}};c(function(n){return w[n];},m.exports,m);w[n]=m.exports;};})('gaia-header',this));},{"font-fit":1,"gaia-component":2,"gaia-icons":3}]},{},[4])(4)});;'use strict';window.GaiaMenu=(function(win){var proto=Object.create(HTMLElement.prototype);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>`;return document.registerElement('gaia-menu',{prototype:proto});})(window);;'use strict';window.GaiaSubheader=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSubheaderBaseurl||'/shared/elements/gaia_subheader/';proto.createdCallback=function(){ComponentUtils.style.call(this,baseurl);};return document.registerElement('gaia-subheader',{prototype:proto});})(window);;;'use strict';window.GaiaSelect=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSelectBaseurl||'/shared/elements/gaia_select/';var selectCounter=0;proto.createdCallback=function(){var label=this.querySelector('label');if(label){var select=this.querySelector('select');if(label.control!=select){var id=select.id;if(!id){select.id=id='gaia-select-'+(++selectCounter);}
|
||||
label.htmlFor=id;}}
|
||||
ComponentUtils.style.call(this,baseurl);};return document.registerElement('gaia-select',{prototype:proto});})(window);;;'use strict';window.GaiaSwitch=(function(win){var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaSwitchBaseurl||'/shared/elements/gaia_switch/';proto.createdCallback=function(){var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._input=this._template.querySelector('input[type="checkbox"]');var checked=this.getAttribute('checked');if(checked!==null){this._input.checked=true;}
|
||||
var wrapper=this._template.getElementById('switch');wrapper.addEventListener('click',this.handleClick.bind(this));shadow.appendChild(this._template);ComponentUtils.style.call(this,baseurl);var dirObserver=new MutationObserver(this.updateInternalDir.bind(this));dirObserver.observe(document.documentElement,{attributeFilter:['dir'],attributes:true});this.updateInternalDir();};proto.updateInternalDir=function(){var internal=this.shadowRoot.firstElementChild;if(document.documentElement.dir==='rtl'){internal.setAttribute('dir','rtl');}else{internal.removeAttribute('dir');}};proto.handleClick=function(e){if(e&&e.target.tagName==='A'){return;}
|
||||
e&&e.preventDefault();e&&e.stopImmediatePropagation();var event=new MouseEvent('click',{view:window,bubbles:true,cancelable:true});this.dispatchEvent(event);if(!event.defaultPrevented){this.checked=!this.checked;}
|
||||
this.dispatchEvent(new CustomEvent('change',{bubbles:true,cancelable:false}));};proto.click=function(){this.handleClick();};Object.defineProperty(proto,'checked',{get:function(){return this._input.checked;},set:function(value){this._input.checked=value;}});Object.defineProperty(proto,'disabled',{get:function(){return this.hasAttribute('disabled');},set:function(value){if(value){this.setAttribute('disabled',true);}else{this.removeAttribute('disabled');}}});Object.defineProperty(proto,'name',{get:function(){return this.getAttribute('name');},set:function(value){this.setAttribute('name',value);}});Object.defineProperty(proto,'type',{get:function(){return'gaia-switch';}});var template=document.createElement('template');template.innerHTML=`<span id="switch">
|
||||
<input type="checkbox">
|
||||
<span><content select="label"></content></span>
|
||||
<div class="details"><content select="details"></content></div>
|
||||
<content select="a"></content>
|
||||
</span>`;return document.registerElement('gaia-switch',{prototype:proto});})(window);;'use strict';var ConfigManager=window.parent.ConfigManager;var CostControl=window.parent.CostControl;var SimManager=window.parent.SimManager;var Common=window.parent.Common;var NetworkUsageAlarm=window.parent.NetworkUsageAlarm;var addNetworkUsageAlarm=window.parent.addNetworkUsageAlarm;var resetTelephony=window.parent.resetTelephony;navigator.mozL10n=window.parent.navigator.mozL10n;var DEBUGGING=window.parent.DEBUGGING;var debug=window.parent.debug;var Settings=(function(){var costcontrol,vmanager,initialized,endLoadSettingsNotified;var plantypeSelector,phoneActivityTitle,phoneActivitySettings;var balanceTitle,balanceSettings,reportsTitle;var balanceView,resetMenuDialog,confirmDialog;function configureUI(){CostControl.getInstance(function _onCostControl(instance){costcontrol=instance;if(DEBUGGING){loadDeveloperAids();}
|
||||
vmanager=new ViewManager();plantypeSelector=document.getElementById('plantype-settings');phoneActivityTitle=document.getElementById('phone-activity-settings');phoneActivitySettings=document.querySelector('#phone-activity-settings + .settings');balanceTitle=document.getElementById('balance-settings');balanceSettings=document.querySelector('#balance-settings + .settings');reportsTitle=document.getElementById('phone-internet-settings');var balanceConfig=ConfigManager.configuration.balance;balanceView=new BalanceView(document.getElementById('balance'),document.querySelector('#balance + .meta'),balanceConfig?balanceConfig.minimum_delay:undefined);var resetDialog=document.getElementById('reset-dialog');var resetDataDialog=document.getElementById('reset-data-dialog');resetMenuDialog=new ResetMenuDialog(resetDataDialog,vmanager);confirmDialog=new ConfirmDialog(resetDialog,vmanager);resetMenuDialog.initializeResetModes(confirmDialog);AutoSettings.addType('data-limit',dataLimitConfigurer);AutoSettings.initialize(ConfigManager,vmanager,'#settings-view');configureTelephonyReset();configureDataResets();addDoneConstrains();ConfigManager.observe('dataLimit',function _onDataLimitChange(value,old,key,settings){SimManager.requestDataSimIcc(function(dataSim){var iccId=dataSim.iccId;var currentDataInterface=Common.getDataSIMInterface(iccId);if(!value){NetworkUsageAlarm.clearAlarms(currentDataInterface);}else{addNetworkUsageAlarm(currentDataInterface,Common.getDataLimit(settings));}});},true);ConfigManager.observe('plantype',updateUI,true);ConfigManager.observe('lastTelephonyActivity',function _updateTelephony(activity,old,key,settings){updateTelephony(activity,settings.lastTelephonyReset);},true);ConfigManager.observe('lastDataUsage',function _updateDataUsage(stats,old,key,settings){updateDataUsage(stats,settings.lastCompleteDataReset);},true);ConfigManager.observe('lastBalance',function _updateBalance(balance){updateBalance(balance,balance.currency);},true);var close=document.getElementById('close-settings');close.addEventListener('click',function(){closeSettings();});function _setResetTimeToDefault(value,old,key,settings){var today=new Date();var defaultResetTime=(settings.trackingPeriod==='weekly')?today.getDay():today.getDate();if(settings.resetTime!==defaultResetTime){ConfigManager.setOption({resetTime:defaultResetTime});}else{Common.updateNextReset(settings.trackingPeriod,settings.resetTime);}}
|
||||
function _updateNextReset(value,old,key,settings){Common.updateNextReset(settings.trackingPeriod,settings.resetTime);}
|
||||
ConfigManager.observe('resetTime',_updateNextReset,true);ConfigManager.observe('trackingPeriod',_setResetTimeToDefault,true);initialized=true;Settings.updateUI();});}
|
||||
function closeSettings(){window.parent.location.hash='#';}
|
||||
function loadDeveloperAids(){var xhr=new XMLHttpRequest();xhr.overrideMimeType('text/plain');xhr.open('GET','/debug.html',false);xhr.send();if(xhr.status===200){var src=document.createElement('DIV');src.innerHTML=xhr.responseText;var reference=document.getElementById('plantype-settings');var parent=reference.parentNode;[].forEach.call(src.childNodes,function(node){reference=parent.insertBefore(node,reference.nextSibling);});}}
|
||||
function configureTelephonyReset(){var resetTelephonyButton=document.getElementById('reset-telephony');resetTelephonyButton.addEventListener('click',function(){confirmDialog.setMessage('reset-telephony-confirmation-warning',{});function resetAction(){resetTelephony();updateUI();confirmDialog.closeConfirmDialog();}
|
||||
confirmDialog.updateAcceptAction(resetAction);confirmDialog.showConfirmDialog();});}
|
||||
function configureDataResets(){var resetDataUsage=document.getElementById('reset-data-usage');resetDataUsage.addEventListener('click',function _onDataReset(){var currentTotals={mobile:costcontrol.lastDataResults.mobile.total,wifi:costcontrol.lastDataResults.wifi.total};resetMenuDialog.showResetMenuDialog(currentTotals);});}
|
||||
var balanceLowLimitView;function addDoneConstrains(){var closeButton=document.getElementById('close-settings');balanceLowLimitView=new BalanceLowLimitView(document.getElementById('low-limit'),document.getElementById('low-limit-input'));balanceLowLimitView.onvalidation=function(evt){closeButton.disabled=!evt.isValid;};}
|
||||
window.addEventListener('localized',function _onLocalize(){if(initialized){updateUI();}});var currentMode;function updateUI(){ConfigManager.requestAll(function _onInfo(configuration,settings){Common.localizeWeekdaySelector(document.getElementById('select-weekday'));var mode=ConfigManager.getApplicationMode();if(currentMode!==mode){currentMode=mode;var hidePlantypeSelector=(mode==='DATA_USAGE_ONLY');var hidePhoneActivity=(mode!=='POSTPAID');var hideBalance=(mode!=='PREPAID');var hideReportsTitle=(mode==='PREPAID');var textReportsTitle=(mode==='POSTPAID')?'phone-and-internet-data-report':'internet-data-report';reportsTitle.querySelector('span').setAttribute('data-l10n-id',textReportsTitle);balanceLowLimitView.disabled=(mode!=='PREPAID');plantypeSelector.hidden=hidePlantypeSelector;phoneActivityTitle.hidden=hidePhoneActivity;phoneActivitySettings.hidden=hidePhoneActivity;balanceTitle.hidden=hideBalance;balanceSettings.hidden=hideBalance;reportsTitle.hidden=hideReportsTitle;}
|
||||
var requestObj={type:'datausage'};costcontrol.request(requestObj,function _onDataStats(result){var stats=result.data;updateDataUsage(stats,settings.lastCompleteDataReset);});switch(mode){case'PREPAID':updateBalance(settings.lastBalance,configuration.credit.currency);break;case'POSTPAID':updateTelephony(settings.lastTelephonyActivity,settings.lastTelephonyReset);break;}
|
||||
if(endLoadSettingsNotified){window.performance.measure('loadSettings','loadSettingsStart');endLoadSettingsNotified=true;}});}
|
||||
function updateDataUsage(datausage,lastCompleteDataReset){var mobileUsage=document.querySelector('#mobile-data-usage > span');var data=Formatting.roundData(datausage.mobile.total);mobileUsage.textContent=Formatting.formatData(data);var wifiUsage=document.querySelector('#wifi-data-usage > span');data=Formatting.roundData(datausage.wifi.total);wifiUsage.textContent=Formatting.formatData(data);updateDataUsageTimestamp(lastCompleteDataReset,datausage.timestamp);}
|
||||
var dataUsagePeriod={begin:null,end:null};function updateDataUsageTimestamp(begin,end){dataUsagePeriod.begin=begin;dataUsagePeriod.end=end;var timestamp=document.querySelector('#wifi-data-usage + .meta');timestamp.innerHTML='';timestamp.appendChild(Formatting.formatTimeHTML(begin,end));}
|
||||
function updateBalance(lastBalance,currency){var limitCurrency=document.getElementById('settings-low-limit-currency');limitCurrency.textContent=currency;balanceView.update(lastBalance);}
|
||||
function updateTelephony(activity,lastTelephonyReset){var calltimeSpan=document.getElementById('calltime');var smscountSpan=document.getElementById('smscount');Common.localize(calltimeSpan,'magnitude',{value:Formatting.computeTelephonyMinutes(activity),unit:'min.'});Common.localize(smscountSpan,'magnitude',{value:activity.smscount,unit:'SMS'});updateTelephonyTimestamp(lastTelephonyReset,activity.timestamp);}
|
||||
var telephonyPeriod={begin:null,end:null};function updateTelephonyTimestamp(begin,end){telephonyPeriod.begin=begin;telephonyPeriod.end=end;var timestamp=document.getElementById('telephony-timestamp');timestamp.innerHTML='';timestamp.appendChild(Formatting.formatTimeHTML(begin,end));}
|
||||
window.addEventListener('timeformatchange',function(){updateTelephonyTimestamp(telephonyPeriod.begin,telephonyPeriod.end);updateDataUsageTimestamp(dataUsagePeriod.begin,dataUsagePeriod.end);});return{initialize:function(){var SCRIPTS_NEEDED=['js/utils/toolkit.js','shared/js/date_time_helper.js','js/utils/formatting.js','js/views/BalanceLowLimitView.js','js/settings/limitdialog.js','js/settings/autosettings.js','js/view_manager.js','js/views/BalanceView.js','js/views/ResetMenuDialog.js','js/views/ConfirmDialog.js'];LazyLoader.load(SCRIPTS_NEEDED,function(){if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(configureUI);}else{configureUI();}});},updateUI:updateUI};}());Settings.initialize();
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
;;'use strict';var Format={padLeft:function(input,len,padWith){padWith=padWith||' ';var pad=len-(input+'').length;while(--pad>-1){input=padWith+input;}
|
||||
return input;}};;(function(exports){'use strict';const kEventName='statechange';const kCommunicationKey='airplaneMode.enabled';const kStatusKey='airplaneMode.status';var AirplaneModeHelper={_mozSettings:window.navigator.mozSettings,_callbacks:[],_cachedStatus:'',ready:function(cb){if(this._cachedStatus===''){var self=this;this.addEventListener(kEventName,function onChangeEvent(){if(self._cachedStatus!==''){self.removeEventListener(kEventName,onChangeEvent);cb();}});}else{cb();}},getStatus:function(){return this._cachedStatus;},addEventListener:function(eventName,callback){if(eventName===kEventName){this._callbacks.push(callback);}},removeEventListener:function(eventName,callback){if(eventName===kEventName){var index=this._callbacks.indexOf(callback);if(index>=0){this._callbacks.splice(index,1);}}},setEnabled:function(enabled){this.ready(function(){var status=this.getStatus();if(status==='enabling'||status==='disabling'){}else{if(enabled&&status==='enabled'||!enabled&&status==='disabled'){return;}
|
||||
var setObj={};setObj[kCommunicationKey]=enabled;this._mozSettings.createLock().set(setObj);}}.bind(this));},init:function(){var self=this;var lock=window.navigator.mozSettings.createLock();var req=lock.get(kStatusKey);req.onsuccess=function(){self._cachedStatus=req.result[kStatusKey];self._callbacks.forEach(function(callback){callback(self._cachedStatus);});};this._mozSettings.addObserver(kStatusKey,function(evt){var currentStatus=evt.settingValue;self._cachedStatus=currentStatus;self._callbacks.forEach(function(callback){callback(currentStatus);});});}};exports.AirplaneModeHelper=AirplaneModeHelper;AirplaneModeHelper.init();})(this);;'use strict';var Widget=(function(){var costcontrol,activity;function checkSIMStatus(dataSim){var dataSimIcc=dataSim.icc;var cardState=checkCardState(dataSimIcc);if(cardState!=='ready'){debug('SIM not ready:',dataSimIcc.cardState);initialized=false;dataSimIcc.oncardstatechange=checkSIMStatus.bind(null,dataSim);}else{debug('SIM ready. ICCID:',dataSim.iccId);dataSimIcc.oncardstatechange=undefined;var SCRIPTS_NEEDED_TO_START=['js/costcontrol.js','js/config/config_manager.js'];LazyLoader.load(SCRIPTS_NEEDED_TO_START,startWidget);}}
|
||||
function checkCardState(dataSimIcc){var state,cardState;state=cardState=dataSimIcc.cardState;if(!cardState||cardState==='absent'){debug('There is no SIM');Widget.showSimError('no-sim3');}else if(cardState==='unknown'){debug('Unknow state fo the sim');Widget.showSimError('unknown');}else if(cardState==='pinRequired'||cardState==='pukRequired'){Widget.showSimError('sim2-locked');state='locked';}
|
||||
return state;}
|
||||
function loadMessageHandler(){if(ConfigManager.option('nextReset')){window.addEventListener('messagehandlerready',function _setNextReset(){window.removeEventListener('messagehandlerready',_setNextReset);LazyLoader.load('js/settings/networkUsageAlarm.js',function(){Common.loadNetworkInterfaces(function(){setNextReset(ConfigManager.option('nextReset'));});});});}
|
||||
document.getElementById('message-handler').src='message_handler.html';}
|
||||
function startWidget(){CostControl.getInstance(function _onCostControlReady(instance){costcontrol=instance;loadMessageHandler();setupWidget();});}
|
||||
var initialized,widget,leftPanel,rightPanel,fte,views={};var balanceView;function _openBalanceTab(){activity=new MozActivity({name:'costcontrol/balance'});}
|
||||
function _openTelephonyTab(){activity=new MozActivity({name:'costcontrol/telephony'});}
|
||||
function _openDataUsageTab(){activity=new MozActivity({name:'costcontrol/data_usage'});}
|
||||
function _onVisibilityChange(evt){AirplaneModeHelper.ready(function(){if(!document.hidden&&initialized&&(AirplaneModeHelper.getStatus()==='disabled')){SimManager.requestDataSimIcc(function(dataSimIcc){checkCardState(dataSimIcc.icc);updateUI();});}});}
|
||||
function _onHashChange(){if(window.location.hash.split('#')[1]==='update'){updateUI(true);}}
|
||||
function _onLocalize(){if(initialized){updateUI();}}
|
||||
function setupWidget(){var mode=ConfigManager.getApplicationMode();var isDataUsageOnly=(mode==='DATA_USAGE_ONLY');var isBalanceEnabled=!isDataUsageOnly;widget=document.getElementById('cost-control');leftPanel=document.getElementById('left-panel');rightPanel=document.getElementById('right-panel');fte=document.getElementById('fte-view');views.dataUsage=document.getElementById('datausage-view');views.limitedDataUsage=document.getElementById('datausage-limit-view');views.telephony=document.getElementById('telephony-view');views.balance=document.getElementById('balance-view');if(isBalanceEnabled){ConfigManager.observe('lastBalance',onBalance,true);ConfigManager.observe('waitingForBalance',onErrors,true);ConfigManager.observe('errors',onErrors,true);LazyLoader.load('js/views/BalanceView.js',function(){var balanceConfig=ConfigManager.configuration.balance;balanceView=new BalanceView(document.getElementById('balance-credit'),document.querySelector('#balance-credit + .meta'),balanceConfig?balanceConfig.minimum_delay:undefined);});views.balance.addEventListener('click',_openBalanceTab);views.telephony.addEventListener('click',_openTelephonyTab);}
|
||||
ConfigManager.observe('lastCompleteDataReset',onReset,true);ConfigManager.observe('lastTelephonyReset',onReset,true);document.addEventListener('visibilitychange',_onVisibilityChange);window.addEventListener('hashchange',_onHashChange);window.addEventListener('localized',_onLocalize);leftPanel.addEventListener('click',_openDataUsageTab);LazyLoader.load(['shared/js/date_time_helper.js','js/utils/formatting.js'],function(){updateUI();});if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',function _onDataSimChange(){CostControl.reset();Widget.reset();ConfigManager.setConfig(null);SimManager.requestDataSimIcc(checkSIMStatus);});}
|
||||
initialized=true;}
|
||||
function onBalance(balance,old,key,settings){debug('Balance received:',balance);setBalanceMode('default');updateBalance(balance,settings.lowLimit&&settings.lowLimitThreshold);debug('Balance updated!');}
|
||||
function onErrors(errors,old,key,settings){if(!errors||!errors.BALANCE_TIMEOUT){return;}
|
||||
debug('Balance timeout!');setBalanceMode('warning');errors.BALANCE_TIMEOUT=false;ConfigManager.setOption({errors:errors});}
|
||||
function onReset(value,old,key,settings){updateUI();}
|
||||
function _showSimError(status,updateTextOnly){navigator.mozL10n.ready(function showErrorStatus(){var widget=document.getElementById('cost-control');var fte=document.getElementById('fte-view');var leftPanel=document.getElementById('left-panel');var rightPanel=document.getElementById('right-panel');if(!updateTextOnly){widget.hidden=false;fte.hidden=false;leftPanel.hidden=true;rightPanel.hidden=true;}
|
||||
var className='widget-'+status;Common.localize(fte.querySelector('p:first-child'),className+'-heading');Common.localize(fte.querySelector('p:last-child'),className+'-meta');});}
|
||||
function setupFte(provider,mode){widget.hidden=false;fte.hidden=false;leftPanel.hidden=true;rightPanel.hidden=true;fte.addEventListener('click',function launchFte(evt){fte.removeEventListener('click',launchFte);evt.stopImmediatePropagation();activity=new MozActivity({name:'costcontrol/balance'});});var keyLookup={PREPAID:'widget-authed-sim2',POSTPAID:'widget-authed-sim2',DATA_USAGE_ONLY:'widget-nonauthed-sim2'};var simKey=keyLookup[mode];Common.localize(fte.querySelector('p:first-child'),simKey+'-heading',{provider:provider});Common.localize(fte.querySelector('p:last-child'),simKey+'-meta');}
|
||||
var hashMark=0;function updateUI(updateOnlyDataUsage){ConfigManager.requestAll(function _onInfo(configuration,settings){var mode=ConfigManager.getApplicationMode();debug('Widget UI mode:',mode);var isPrepaid=(mode==='PREPAID');var isDataUsageOnly=(mode==='DATA_USAGE_ONLY');if(settings.fte){setupFte(configuration.provider,mode);debug('Widget in FTE mode');return;}
|
||||
widget.hidden=true;fte.hidden=true;leftPanel.hidden=false;rightPanel.hidden=false;var isLimited=settings.dataLimit;views.dataUsage.hidden=isLimited;views.limitedDataUsage.hidden=!isLimited;rightPanel.hidden=isDataUsageOnly;if(isDataUsageOnly){widget.classList.add('full');widget.hidden=false;}else{widget.classList.remove('full');views.balance.hidden=!isPrepaid;views.telephony.hidden=isPrepaid;widget.hidden=false;}
|
||||
var requestObj={type:'datausage'};costcontrol.request(requestObj,function _onDataStatistics(result){debug(result);var stats=result.data;var data=Formatting.roundData(stats.mobile.total);if(isLimited){var dataLimit=views.limitedDataUsage.querySelector('#data-limit');var dataAvailable=views.limitedDataUsage.querySelector('#data-available');var current=stats.mobile.total;var limit=Common.getDataLimit(settings);debug(limit);views.limitedDataUsage.classList.remove('nearby-limit');views.limitedDataUsage.classList.remove('reached-limit');var limitTrespassed=(current>limit);if(limitTrespassed){views.limitedDataUsage.classList.add('reached-limit');}else if(current>=limit*Common.DATA_USAGE_WARNING){views.limitedDataUsage.classList.add('nearby-limit');}
|
||||
var limitText=Formatting.roundData(limit);limitText=_('magnitude',{value:limitText[0],unit:limitText[1]});navigator.mozL10n.setAttributes(dataLimit,'data-limit',{value:limitText});var rawValue=Math.abs(limit-current);var text=Formatting.roundData(rawValue);if(!limitTrespassed){navigator.mozL10n.setAttributes(dataAvailable,'data-available2',{value:parseFloat(text[0]),unit:text[1]});}else{navigator.mozL10n.setAttributes(dataAvailable,'over-limit',{value:parseFloat(text[0]),unit:text[1]});}}else{document.getElementById('mobile-usage-value').textContent=_('magnitude',{value:data[0],unit:data[1]});var meta=views.dataUsage.querySelector('.meta');meta.innerHTML='';meta.appendChild(Formatting.formatTimeHTML(stats.timestamp));}
|
||||
hashMark=1-hashMark;window.location.hash='#updateDone#'+hashMark;});if(!isDataUsageOnly&&!updateOnlyDataUsage){if(mode==='PREPAID'){updateBalance(settings.lastBalance,settings.lowLimit&&settings.lowLimitThreshold);requestObj={type:'balance'};costcontrol.request(requestObj,function _onRequest(result){debug(result);var status=result.status;var balance=result.data;setBalanceMode(status==='error'?'warning':'updating');updateBalance(balance,settings.lowLimit&&settings.lowLimitThreshold);});}else if(mode==='POSTPAID'){requestObj={type:'telephony'};costcontrol.request(requestObj,function _onRequest(result){var dataActivity=result.data;document.getElementById('telephony-calltime').textContent=_('magnitude',{value:Formatting.computeTelephonyMinutes(dataActivity),unit:'min'});document.getElementById('telephony-smscount').textContent=_('magnitude',{value:dataActivity.smscount,unit:'SMS'});var meta=views.telephony.querySelector('.meta');meta.innerHTML='';meta.appendChild(Formatting.formatTimeHTML(dataActivity.timestamp));});}}});}
|
||||
function updateBalance(balance,limit){if(!balance){debug('Balance not available');balanceView.update();return;}
|
||||
var isUpdating=views.balance.classList.contains('updating');balanceView.update(balance,isUpdating);if(balance.balance===0){views.balance.classList.add('no-credit');}else{views.balance.classList.remove('no-credit');if(limit&&balance.balance<limit){views.balance.classList.add('low-credit');}else{views.balance.classList.remove('low-credit');}}}
|
||||
var lastBalanceMode;function setBalanceMode(mode){if(mode===lastBalanceMode){return;}
|
||||
lastBalanceMode=mode;views.balance.classList.remove('updating');views.balance.classList.remove('warning');if(mode==='warning'){views.balance.classList.add('warning');}
|
||||
if(mode==='updating'){views.balance.classList.add('updating');}}
|
||||
window.addEventListener('airplaneModeDisabled',function _onAirplanemodeDisabled(evt){if(evt.detail&&evt.detail.serviceId==='data'){SimManager.requestDataSimIcc(checkSIMStatus);}});function initWidget(){var isWaitingForIcc=false;function waitForIccAndCheckSim(){if(!isWaitingForIcc){var iccManager=window.navigator.mozIccManager;iccManager.addEventListener('iccdetected',function _oniccdetected(){isWaitingForIcc=false;iccManager.removeEventListener('iccdetected',_oniccdetected);if(AirplaneModeHelper.getStatus()==='disabled'){SimManager.requestDataSimIcc(checkSIMStatus);}});isWaitingForIcc=true;}}
|
||||
SimManager.requestDataSimIcc(checkSIMStatus,function _errorNoSim(){AirplaneModeHelper.ready(function(){waitForIccAndCheckSim();var errorMessageId=(AirplaneModeHelper.getStatus()==='enabled')?'airplane-mode':'no-sim3';console.warn('Error when trying to get the ICC ID');Widget.showSimError(errorMessageId);});});AirplaneModeHelper.addEventListener('statechange',function _onAirplaneModeChange(state){if(state==='enabled'){Widget.showSimError('airplane-mode');}else if(isWaitingForIcc){var updateTextOnly=true;Widget.showSimError('no-sim3',updateTextOnly);}});}
|
||||
return{init:function(){var SCRIPTS_NEEDED=['js/common.js','js/utils/toolkit.js'];if(!window.navigator.mozMobileConnections||!window.navigator.mozIccManager||!window.navigator.mozNetworkStats){LazyLoader.load(SCRIPTS_NEEDED,function _showError(){Widget.showSimError('no-sim3');});}else{SCRIPTS_NEEDED=['js/sim_manager.js','js/common.js','js/utils/toolkit.js','js/utils/debug.js'];LazyLoader.load(SCRIPTS_NEEDED,initWidget);}},showSimError:_showSimError,reset:function(){document.removeEventListener('visibilitychange',_onVisibilityChange);window.removeEventListener('hashchange',_onHashChange);window.removeEventListener('localized',_onLocalize);leftPanel.removeEventListener('click',_openDataUsageTab);if(views.balance){views.balance.removeEventListener('click',_openBalanceTab);}
|
||||
if(views.telephony){views.telephony.removeEventListener('click',_openTelephonyTab);}}};}());Widget.init();
|
||||
271
assets/webapps/costcontrol.gaiamobile.org/gaia_build_fte.js
Normal file
271
assets/webapps/costcontrol.gaiamobile.org/gaia_build_fte.js
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
;(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);;this.asyncStorage=(function(){'use strict';var DBNAME='asyncStorage';var DBVERSION=1;var STORENAME='keyvaluepairs';var db=null;function withDatabase(f){if(db){f();}else{var openreq=indexedDB.open(DBNAME,DBVERSION);openreq.onerror=function withStoreOnError(){console.error('asyncStorage: can\'t open database:',openreq.error.name);};openreq.onupgradeneeded=function withStoreOnUpgradeNeeded(){openreq.result.createObjectStore(STORENAME);};openreq.onsuccess=function withStoreOnSuccess(){db=openreq.result;f();};}}
|
||||
function withStore(type,callback,oncomplete){withDatabase(function(){var transaction=db.transaction(STORENAME,type);if(oncomplete){transaction.oncomplete=oncomplete;}
|
||||
callback(transaction.objectStore(STORENAME));});}
|
||||
function getItem(key,callback){var req;withStore('readonly',function getItemBody(store){req=store.get(key);req.onerror=function getItemOnError(){console.error('Error in asyncStorage.getItem(): ',req.error.name);};},function onComplete(){var value=req.result;if(value===undefined){value=null;}
|
||||
callback(value);});}
|
||||
function setItem(key,value,callback){withStore('readwrite',function setItemBody(store){var req=store.put(value,key);req.onerror=function setItemOnError(){console.error('Error in asyncStorage.setItem(): ',req.error.name);};},callback);}
|
||||
function removeItem(key,callback){withStore('readwrite',function removeItemBody(store){var req=store.delete(key);req.onerror=function removeItemOnError(){console.error('Error in asyncStorage.removeItem(): ',req.error.name);};},callback);}
|
||||
function clear(callback){withStore('readwrite',function clearBody(store){var req=store.clear();req.onerror=function clearOnError(){console.error('Error in asyncStorage.clear(): ',req.error.name);};},callback);}
|
||||
function length(callback){var req;withStore('readonly',function lengthBody(store){req=store.count();req.onerror=function lengthOnError(){console.error('Error in asyncStorage.length(): ',req.error.name);};},function onComplete(){callback(req.result);});}
|
||||
function key(n,callback){if(n<0){callback(null);return;}
|
||||
var req;withStore('readonly',function keyBody(store){var advanced=false;req=store.openCursor();req.onsuccess=function keyOnSuccess(){var cursor=req.result;if(!cursor){return;}
|
||||
if(n===0||advanced){return;}
|
||||
advanced=true;cursor.advance(n);};req.onerror=function keyOnError(){console.error('Error in asyncStorage.key(): ',req.error.name);};},function onComplete(){var cursor=req.result;callback(cursor?cursor.key:null);});}
|
||||
return{getItem:getItem,setItem:setItem,removeItem:removeItem,clear:clear,length:length,key:key};}());;'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);}});}};;'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,503 @@
|
|||
;;;(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);;;;this.asyncStorage=(function(){'use strict';var DBNAME='asyncStorage';var DBVERSION=1;var STORENAME='keyvaluepairs';var db=null;function withDatabase(f){if(db){f();}else{var openreq=indexedDB.open(DBNAME,DBVERSION);openreq.onerror=function withStoreOnError(){console.error('asyncStorage: can\'t open database:',openreq.error.name);};openreq.onupgradeneeded=function withStoreOnUpgradeNeeded(){openreq.result.createObjectStore(STORENAME);};openreq.onsuccess=function withStoreOnSuccess(){db=openreq.result;f();};}}
|
||||
function withStore(type,callback,oncomplete){withDatabase(function(){var transaction=db.transaction(STORENAME,type);if(oncomplete){transaction.oncomplete=oncomplete;}
|
||||
callback(transaction.objectStore(STORENAME));});}
|
||||
function getItem(key,callback){var req;withStore('readonly',function getItemBody(store){req=store.get(key);req.onerror=function getItemOnError(){console.error('Error in asyncStorage.getItem(): ',req.error.name);};},function onComplete(){var value=req.result;if(value===undefined){value=null;}
|
||||
callback(value);});}
|
||||
function setItem(key,value,callback){withStore('readwrite',function setItemBody(store){var req=store.put(value,key);req.onerror=function setItemOnError(){console.error('Error in asyncStorage.setItem(): ',req.error.name);};},callback);}
|
||||
function removeItem(key,callback){withStore('readwrite',function removeItemBody(store){var req=store.delete(key);req.onerror=function removeItemOnError(){console.error('Error in asyncStorage.removeItem(): ',req.error.name);};},callback);}
|
||||
function clear(callback){withStore('readwrite',function clearBody(store){var req=store.clear();req.onerror=function clearOnError(){console.error('Error in asyncStorage.clear(): ',req.error.name);};},callback);}
|
||||
function length(callback){var req;withStore('readonly',function lengthBody(store){req=store.count();req.onerror=function lengthOnError(){console.error('Error in asyncStorage.length(): ',req.error.name);};},function onComplete(){callback(req.result);});}
|
||||
function key(n,callback){if(n<0){callback(null);return;}
|
||||
var req;withStore('readonly',function keyBody(store){var advanced=false;req=store.openCursor();req.onsuccess=function keyOnSuccess(){var cursor=req.result;if(!cursor){return;}
|
||||
if(n===0||advanced){return;}
|
||||
advanced=true;cursor.advance(n);};req.onerror=function keyOnError(){console.error('Error in asyncStorage.key(): ',req.error.name);};},function onComplete(){var cursor=req.result;callback(cursor?cursor.key:null);});}
|
||||
return{getItem:getItem,setItem:setItem,removeItem:removeItem,clear:clear,length:length,key:key};}());;(function(window){'use strict';window.NotificationHelper={getIconURI:function nh_getIconURI(app,entryPoint){var icons=app.manifest.icons;if(entryPoint){icons=app.manifest.entry_points[entryPoint].icons;}
|
||||
if(!icons){return null;}
|
||||
var sizes=Object.keys(icons).map(function parse(str){return parseInt(str,10);});sizes.sort(function(x,y){return y-x;});var HVGA=document.documentElement.clientWidth<480;var index=sizes[HVGA?sizes.length-1:0];return app.installOrigin+icons[index];},send:function nh_send(titleL10n,options){return Promise.all([titleL10n,options.bodyL10n].map(getL10n)).then(([title,body])=>{if(body){options.body=body;}
|
||||
options.lang=document.documentElement.getAttribute('lang');var notification=new window.Notification(title,options);if(options.closeOnClick!==false){notification.addEventListener('click',function nh_click(){notification.removeEventListener('click',nh_click);notification.close();});}
|
||||
return notification;});},};function getL10n(l10nAttrs){if(!l10nAttrs){return;}
|
||||
if(typeof l10nAttrs==='string'){return document.l10n.formatValue(l10nAttrs);}
|
||||
if(typeof l10nAttrs.raw==="string"){return l10nAttrs.raw;}
|
||||
return document.l10n.formatValue(l10nAttrs.id,l10nAttrs.args);}})(this);;;;'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);}});}};;;;'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();}());;'use strict';var DEBUGGING=false;var debug=(function(){var SEQ_ID=0;var PROCESS_ID=Date.now();var DEBUG_PREFIX='CC';return function _debug(){if(!DEBUGGING){return;}
|
||||
var currentWindow=window;var parents=[];while(currentWindow!==currentWindow.parent){parents.push(currentWindow.location.pathname);currentWindow=currentWindow.parent;}
|
||||
parents.push(currentWindow.location.pathname);parents=parents.reverse().join('>')+':';var uId=PROCESS_ID;var message=['('+uId+'-'+(SEQ_ID++)+')',DEBUG_PREFIX,parents];for(var i=0,len=arguments.length,obj;i<len;i++){obj=arguments[i];message.push(typeof obj==='object'?JSON.stringify(obj):obj);}
|
||||
if(window.dump){message.push('\n');window.dump(message.join(' '));}else if(console&&console.log){console.log(message.join(' '));}};}());;'use strict';var _=function cc_fallbackTranslation(keystring){var r=window.navigator.mozL10n.get.apply(this,arguments);return r||(DEBUGGING?'!!':'')+keystring;};function deepCopy(object){if(object===null||!(object instanceof Object)){return object;}
|
||||
var clone,constructor=object.constructor;switch(constructor){case Date:clone=new constructor(object.getTime());break;default:clone=constructor();break;}
|
||||
for(var key in object){if(object.hasOwnProperty(key)){clone[key]=deepCopy(object[key]);}}
|
||||
return clone;}
|
||||
var Toolkit={checkEnoughDelay:function(threshold,dateA,dateB){if(!dateA){return true;}
|
||||
var end=dateB||new Date();return(end.getTime()-dateA.getTime())>threshold;},toMidnight:function _toMidnight(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0);return date;}};;'use strict';var Formatting=(function(){var MINUTE=60*1000;var HOUR=60*MINUTE;var DAY=24*HOUR;function getDaysOfDifference(a,b){return Math.floor((a.getTime()-b.getTime())/DAY);}
|
||||
function getFormattedDate(timestamp,formatter){return formatter.format(timestamp);}
|
||||
function formatTime(timestamp,formatter){if(!timestamp){return _('never');}
|
||||
var now=new Date(),then=new Date(timestamp);if(formatter){return getFormattedDate(then,formatter);}
|
||||
var date,time;var daysOfDifference=getDaysOfDifference(now,then);if(daysOfDifference===0){date=_('today');}else if(daysOfDifference===1){date=_('yesterday');}else{date=getFormattedDate(timestamp,Formatting.formatters.shortWeekday);}
|
||||
time=getFormattedDate(timestamp,Formatting.formatters.shortTime);return _('day-hour-format',{day:date,time:time});}
|
||||
function formatTimeSinceNow(timestamp){var now=new Date(),then=new Date(timestamp);var formattedTime=formatTime(timestamp);if(getDaysOfDifference(now,then)>0){return formattedTime;}
|
||||
var age=now-then;if(age<MINUTE){formattedTime=_('minutes-ago-short',{value:0});}else if(age<HOUR){var minutes=Math.floor(age/MINUTE);formattedTime=_('minutes-ago-short',{value:minutes});}else if(age<DAY){var hours=Math.floor(age/HOUR);formattedTime=_('hours-ago-short',{value:hours});}
|
||||
return formattedTime;}
|
||||
function formatData(dataArray){return isNaN(dataArray[0])?'':_('magnitude',{value:dataArray[0],unit:dataArray[1]});}
|
||||
function roundData(value,positions){positions=(typeof positions==='undefined')?2:positions;if(value<1000){return[value.toFixed(positions),_('B')];}
|
||||
if(value<1000000){return[(value/1000).toFixed(positions),_('KB')];}
|
||||
if(value<1000000000){return[(value/1000000).toFixed(positions),_('MB')];}
|
||||
return[(value/1000000000).toFixed(positions),_('GB')];}
|
||||
function getPositions(value,deltaPositions){deltaPositions=(typeof deltaPositions==='undefined')?0:deltaPositions;if(parseInt(value)===value){return 0;}
|
||||
if(value<10){return 2+deltaPositions;}
|
||||
if(value<100){return 1+deltaPositions;}
|
||||
return 0;}
|
||||
function smartRound(value,deltaPositions){deltaPositions=(typeof deltaPositions==='undefined')?0:deltaPositions;if(value<1000){var bPositions=getPositions(value,deltaPositions);return[value.toFixed(bPositions),_('B')];}
|
||||
if(value<1000000){var kbytes=value/1000;var kbPositions=getPositions(kbytes,deltaPositions);return[kbytes.toFixed(kbPositions),_('KB')];}
|
||||
if(value<1000000000){var mbytes=value/1000000;var mPositions=getPositions(mbytes,deltaPositions);return[mbytes.toFixed(mPositions),_('MB')];}
|
||||
var gbytes=value/1000000000;var gPositions=getPositions(gbytes,deltaPositions);return[gbytes.toFixed(gPositions),_('GB')];}
|
||||
function formatTimeHTML(timestampA,timestampB){function timeElement(content){var time=document.createElement('time');time.textContent=content;return time;}
|
||||
var fragment=document.createDocumentFragment();if(typeof timestampB==='undefined'){fragment.appendChild(timeElement(Formatting.formatTime(timestampA)));return fragment;}
|
||||
var dateA=new Date(timestampA);var dateB=new Date(timestampB);if(dateA.getFullYear()===dateB.getFullYear()&&dateA.getMonth()===dateB.getMonth()&&dateA.getDay()===dateB.getDay()){return formatTimeHTML(timestampB);}
|
||||
fragment.appendChild(timeElement(Formatting.formatTime(timestampA,Formatting.formatters.shortDate)));fragment.appendChild(document.createTextNode(' – '));fragment.appendChild(timeElement(Formatting.formatTime(timestampB)));return fragment;}
|
||||
function computeTelephonyMinutes(activity){return Math.ceil(activity.calltime/60000);}
|
||||
return{getFormattedDate:getFormattedDate,formatTime:formatTime,formatTimeSinceNow:formatTimeSinceNow,formatData:formatData,roundData:roundData,getPositions:getPositions,smartRound:smartRound,formatTimeHTML:formatTimeHTML,computeTelephonyMinutes:computeTelephonyMinutes,formatters:{}};}());function setFormatters(){const locales=navigator.languages;Formatting.formatters.longDate=Intl.DateTimeFormat(locales,{month:'long',day:'numeric',year:'numeric'});Formatting.formatters.shortDate=Intl.DateTimeFormat(locales,{month:'short',day:'numeric',});Formatting.formatters.shortTime=Intl.DateTimeFormat(locales,{hour12:navigator.mozHour12,hour:'numeric',minute:'numeric'});Formatting.formatters.shortWeekday=Intl.DateTimeFormat(locales,{weekday:'short'});}
|
||||
setFormatters();window.addEventListener('languagechange',setFormatters,false);window.addEventListener('timeformatchange',setFormatters,false);;'use strict';var SimManager=(function(){var serviceIcc={};var serviceSettingMap={'data':'ril.data.defaultServiceId','telephony':'ril.telephony.defaultServiceId','message':'ril.sms.defaultServiceId'};function notifyInitializationDone(updatedService){var simInitializedEvent=new CustomEvent('simManagerReady',{detail:updatedService});window.dispatchEvent(simInitializedEvent);}
|
||||
function _init(serviceId){_reset(serviceId);LazyLoader.load(['/shared/js/airplane_mode_helper.js'],function(){AirplaneModeHelper.addEventListener('statechange',function _onAirplaneModeChange(state){if(state==='disabled'){serviceIcc[serviceId].dirty=true;var eventDetail={detail:{serviceId:serviceId}};var airplanemodeDisabledEvent=new CustomEvent('airplaneModeDisabled',eventDetail);window.dispatchEvent(airplanemodeDisabledEvent);}});});function checkForCompletion(){serviceIcc[serviceId].initialized=true;SettingsListener.observe(serviceSettingMap[serviceId],0,function(value){var isDirty=(serviceIcc[serviceId].slotId!==value);serviceIcc[serviceId].dirty=isDirty;serviceIcc[serviceId].slotId=value;if(isDirty){var serviceSlotChangeEvent=new CustomEvent(serviceId+'SlotChange',{detail:serviceId});window.dispatchEvent(serviceSlotChangeEvent);}});notifyInitializationDone(serviceId);}
|
||||
if(SimManager.isMultiSim()){var settings=window.navigator.mozSettings;var req=settings&&settings.createLock().get(serviceSettingMap[serviceId]);req.onsuccess=function _onsuccesSlotId(){if(!req.result[serviceSettingMap[serviceId]]){console.warn('The setting '+serviceSettingMap[serviceId]+' does not exists, using default Slot (0)');}
|
||||
var slotId=req.result[serviceSettingMap[serviceId]]||0;serviceIcc[serviceId].slotId=slotId;checkForCompletion();};req.onerror=function _onErrorSlotId(){console.warn('The setting '+serviceSettingMap[serviceId]+' does not exists');checkForCompletion();};}else{notifyInitializationDone(serviceId);}}
|
||||
function _requestDataSIMIcc(onsuccess,onerror){_requestService('data',onsuccess,onerror);}
|
||||
function _requestTelephonySIMIcc(onsuccess,onerror){_requestService('telephony',onsuccess,onerror);}
|
||||
function _requestMessageSIMIcc(onsuccess,onerror){_requestService('message',onsuccess,onerror);}
|
||||
function _requestService(serviceId,onsuccess,onerror){if(serviceIcc[serviceId]&&serviceIcc[serviceId].initialized&&!serviceIcc[serviceId].dirty){(typeof onsuccess==='function')&&onsuccess(serviceIcc[serviceId]);}else if(!serviceIcc[serviceId]||!serviceIcc[serviceId].initialized){console.warn('SimManager is not ready, waiting for initialized custom '+'event');window.addEventListener('simManagerReady',function _onSMInit(evt){if(evt.detail==='all'||evt.detail===serviceId){window.removeEventListener('simManagerReady',_onSMInit);_requestServiceSIMIcc(serviceId,onsuccess,onerror);}});_init(serviceId);}else{_requestServiceSIMIcc(serviceId,onsuccess,onerror);}}
|
||||
function _requestServiceSIMIcc(serviceId,onsuccess,onerror){var iccManager=window.navigator.mozIccManager;var slotId=serviceIcc[serviceId].slotId;var mobileConnection=navigator.mozMobileConnections[slotId];var iccId=mobileConnection.iccId||null;if(!iccId){console.error('The slot '+slotId+', configured as the '+serviceId+' slot, is empty');(typeof onerror==='function')&&onerror();return;}
|
||||
serviceIcc[serviceId].iccId=iccId;serviceIcc[serviceId].icc=iccManager.getIccById(iccId);if(!serviceIcc[serviceId].icc){(typeof onerror==='function')&&onerror();return;}
|
||||
(typeof onsuccess==='function')&&onsuccess(serviceIcc[serviceId]);}
|
||||
function _reset(serviceId){function _resetService(serviceId){var _initialized=!SimManager.isMultiSim();serviceIcc[serviceId]={dirty:true,icc:null,iccId:null,slotId:0,initialized:_initialized};}
|
||||
if(!serviceId){Object.keys(serviceSettingMap).forEach(function _initService(serviceId){_resetService(serviceId);});}else{_resetService(serviceId);}}
|
||||
function _requestServiceConnection(serviceId){var slotId=serviceIcc[serviceId].slotId;return navigator.mozMobileConnections[slotId];}
|
||||
function _requestDataConnection(callback){if(serviceIcc.data&&serviceIcc.data.initialized){var connection=_requestServiceConnection('data');(typeof callback==='function')&&callback(connection);}else{console.warn('SimManager is not ready, waiting for initialized custom '+'event');window.addEventListener('simManagerReady',function _onSMInit(evt){if(evt.detail==='all'||evt.detail==='data'){window.removeEventListener('simManagerReady',_onSMInit);var connection=_requestServiceConnection('data');(typeof callback==='function')&&callback(connection);}});_init('data');}}
|
||||
return{isMultiSim:function(){return(navigator.mozMobileConnections.length>1);},requestDataSimIcc:_requestDataSIMIcc,requestTelephonySimIcc:_requestTelephonySIMIcc,requestDataConnection:_requestDataConnection,requestMessageSimIcc:_requestMessageSIMIcc,reset:_reset};})();;'use strict';function addAlarmTimeout(type,delay){var handlerContainer=document.getElementById('message-handler');return handlerContainer.contentWindow.addAlarmTimeout(type,delay);}
|
||||
function setNextReset(when,callback){var handlerContainer=document.getElementById('message-handler');return handlerContainer?handlerContainer.contentWindow.setNextReset(when,callback):window.setNextReset(when,callback);}
|
||||
function getTopUpTimeout(callback){var handlerContainer=document.getElementById('message-handler');return handlerContainer?handlerContainer.contentWindow.getTopUpTimeout(callback):window.getTopUpTimeout(callback);}
|
||||
function addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror){var handlerContainer=document.getElementById('message-handler');if(handlerContainer){handlerContainer.contentWindow.addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror);}else{window.addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror);}}
|
||||
function sendBalanceThresholdNotification(remaining,settings,callback){var handlerContainer=document.getElementById('message-handler');if(handlerContainer){handlerContainer.contentWindow.sendBalanceThresholdNotification(remaining,settings,callback);}}
|
||||
function resetTelephony(callback){ConfigManager.setOption({lastTelephonyReset:new Date(),lastTelephonyActivity:{calltime:0,smscount:0,timestamp:new Date()}},callback);}
|
||||
var Common={COST_CONTROL_APP:'app://costcontrol.gaiamobile.org',DATA_USAGE_WARNING:0.8,allApps:null,allAppsLoaded:false,allNetworkInterfaces:null,allNetworkInterfaceLoaded:false,specialApps:['app://search.gaiamobile.org/manifest.webapp'],SYSTEM_MANIFEST:'app://system.gaiamobile.org/manifest.webapp',BROWSER_APP:{manifestURL:'app://browser.gaiamobile.org/manifest.webapp',origin:'',manifest:{icons:{'84':'/shared/resources/branding/browser_84.png','126':'/shared/resources/branding/browser_126.png','142':'/shared/resources/branding/browser_142.png','189':'/shared/resources/branding/browser_189.png','284':'/shared/resources/branding/browser_284.png'},name:'browser'}},startFTE:function(mode){var iframe=document.getElementById('fte_view');window.addEventListener('message',function handler(e){if(e.origin!==Common.COST_CONTROL_APP){return;}
|
||||
if(e.data.type==='fte_ready'){window.removeEventListener('message',handler);iframe.classList.remove('non-ready');window.performance.mark('navigationLoaded');window.performance.mark('navigationInteractive');window.performance.mark('visuallyLoaded');window.performance.mark('contentInteractive');window.performance.mark('fullyLoaded');}});iframe.src='/fte.html'+'#'+mode;},closeFTE:function(){var iframe=window.parent.document.getElementById('fte_view');iframe.classList.add('non-ready');iframe.src='';},startApp:function(){parent.postMessage({type:'fte_finished',data:''},Common.COST_CONTROL_APP);},closeApplication:function(){return setTimeout(function _close(){debug('Closing.');window.close();});},modalAlert:function(message){alert(message);},get localize(){return navigator.mozL10n.setAttributes;},getInterface:function getInterface(findFunction){if(!Common.allNetworkInterfaceLoaded){debug('Network interfaces are not ready yet');var header=_('data-usage');var msg=_('loading-interface-data');this.modalAlert(header+'\n'+msg);return;}
|
||||
if(Common.allNetworkInterfaces){return Common.allNetworkInterfaces.find(findFunction);}},getDataSIMInterface:function _getDataSIMInterface(iccId){if(!iccId){console.warn('Undefined icc identifier, unable get data interface');return;}
|
||||
if(iccId){var findCurrentInterface=function(networkInterface){if(networkInterface.id===iccId){return networkInterface;}};return this.getInterface(findCurrentInterface);}
|
||||
return undefined;},getWifiInterface:function _getWifiInterface(){var findWifiInterface=function(networkInterface){if(networkInterface.type===navigator.mozNetworkStats.WIFI){return networkInterface;}};return this.getInterface(findWifiInterface);},loadApps:function(){return new Promise(function(resolve,reject){if(Common.allAppsLoaded){resolve(Common.allApps);return;}
|
||||
var request=window.navigator.mozApps.mgmt.getAll();request.onsuccess=function(event){var appList=event.target.result;Common.allApps=appList.filter(function(app){return Common.specialApps.indexOf(app.manifestURL)===-1;});Common.allApps.push(Common.BROWSER_APP);Common.allAppsLoaded=true;resolve(Common.allApps);};request.onerror=function(){reject(new Error('Apps could not be loaded'));};});},loadNetworkInterfaces:function(onsuccess,onerror){var networks=navigator.mozNetworkStats.getAvailableNetworks();networks.onsuccess=function(){Common.allNetworkInterfaces=networks.result;Common.allNetworkInterfaceLoaded=true;if(onsuccess){onsuccess();}};networks.onerror=function(){console.error('Error when trying to load network interfaces');if(onerror){onerror();}};},getApp:function(manifestURL){return this.allApps.find(function(app){return app.manifestURL===manifestURL;});},getAppManifest:function(app){return app.manifest||app.updateManifest;},getLocalizedAppName:function(app){if(app.manifestURL===Common.SYSTEM_MANIFEST){return _('data-usage-other-apps');}
|
||||
if(app.manifestURL===Common.BROWSER_APP.manifestURL){return _('data-usage-browser-app');}
|
||||
var manifest=this.getAppManifest(app);var userLang=document.documentElement.lang;var locales=manifest.locales;var localized=locales&&locales[userLang]&&locales[userLang].name;return localized||manifest.name;},getAppIcon:function(app){var manifest=this.getAppManifest(app);var icons=manifest.icons;var defaultImage='../style/images/app/icons/default.png';if(!icons||!Object.keys(icons).length){return defaultImage;}
|
||||
var preferredIconSize=30*(window.devicePixelRatio||1);var preferredSize=Number.MAX_VALUE;var max=0;for(var size in icons){size=parseInt(size,10);if(size>max){max=size;}
|
||||
if(size>=preferredIconSize&&size<preferredSize){preferredSize=size;}}
|
||||
if(preferredSize===Number.MAX_VALUE){preferredSize=max;}
|
||||
var url=icons[preferredSize];if(url){return!(/^(http|https|data):/.test(url))?app.origin+url:url;}else{return defaultImage;}},getDataLimit:function _getDataLimit(settings){var multiplier=(settings.dataLimitUnit==='MB')?1000000:1000000000;return settings.dataLimitValue*multiplier;},resetData:function _resetData(mode,onsuccess,onerror){var wifiInterface=Common.getWifiInterface();var wifiClearRequest,mobileClearRequest;var getOnErrorFor=function(networkInterface){return function(){if(wifiClearRequest){wifiClearRequest.onerror=undefined;}
|
||||
if(mobileClearRequest){mobileClearRequest.onerror=undefined;}
|
||||
(typeof onerror==='function')&&onerror(networkInterface);};};if((mode==='all'||mode==='wifi')&&wifiInterface){wifiClearRequest=navigator.mozNetworkStats.clearStats(wifiInterface);wifiClearRequest.onerror=getOnErrorFor('wi-Fi');}
|
||||
if(mode==='all'||mode==='mobile'){SimManager.requestDataSimIcc(function(dataSim){var currentSimcardInterface=Common.getDataSIMInterface(dataSim.iccId);if(currentSimcardInterface){mobileClearRequest=navigator.mozNetworkStats.clearStats(currentSimcardInterface);mobileClearRequest.onerror=getOnErrorFor('simcard');mobileClearRequest.onsuccess=function _restoreDataLimitAlarm(){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){if(settings.dataLimit){addNetworkUsageAlarm(currentSimcardInterface,Common.getDataLimit(settings),function _addNetworkUsageAlarmOK(){ConfigManager.setOption({'dataUsageNotified':false});});}});};}});}
|
||||
if(mode==='all'){ConfigManager.setOption({lastCompleteDataReset:new Date()});}else{ConfigManager.setOption({lastDataReset:new Date()});}
|
||||
if(typeof onsuccess==='function'){onsuccess();}},resetAll:function _resetAll(callback){function logResetDataError(networkInterface){console.log('Error when trying to reset '+networkInterface+' interface');}
|
||||
Common.resetData('all',thenResetTelephony,logResetDataError);function thenResetTelephony(){resetTelephony(callback);}},updateNextReset:function _updateNextReset(trackingPeriod,value,callback){if(trackingPeriod==='never'){setNextReset(null,callback);return;}
|
||||
var nextReset,today=new Date();if(trackingPeriod==='monthly'){var month,year;var monthday=parseInt(value,10);month=today.getMonth();year=today.getFullYear();if(today.getDate()>=monthday){month=(month+1)%12;if(month===0){year++;}}
|
||||
nextReset=new Date(year,month,monthday);if(monthday!==nextReset.getDate()){var LAST_DAY_OF_PREVIOUS_MONTH=0;nextReset.setDate(LAST_DAY_OF_PREVIOUS_MONTH);}}else if(trackingPeriod==='weekly'){var oneDay=24*60*60*1000;var weekday=parseInt(value,10);var daysToTarget=weekday-today.getDay();if(daysToTarget<=0){daysToTarget=7+daysToTarget;}
|
||||
nextReset=new Date();nextReset.setTime(nextReset.getTime()+oneDay*daysToTarget);Toolkit.toMidnight(nextReset);}
|
||||
setNextReset(nextReset,callback);},localizeWeekdaySelector:function _localizeWeekdaySelector(selector){var weekStartsOnMonday=parseInt(navigator.mozL10n.get('firstDayOfTheWeek'),10)===1;debug('Week starts on monday?',weekStartsOnMonday);var monday=selector.querySelector('.monday');var sunday=selector.querySelector('.sunday');var list=monday.parentNode;if(weekStartsOnMonday){debug('Monday, Tuesday...');list.insertBefore(monday,list.childNodes[0]);list.appendChild(sunday);}else{debug('Sunday, Monday...');list.insertBefore(sunday,list.childNodes[0]);list.insertBefore(monday,sunday.nextSibling);}}};;'use strict';var ConfigManager=(function(){var today=new Date();var DEFAULT_SETTINGS={'dataLimit':false,'dataLimitValue':1,'dataLimitUnit':'GB','errors':{'INCORRECT_TOPUP_CODE':false,'BALANCE_TIMEOUT':false,'TOPUP_TIMEOUT':false},'fte':true,'waitingForBalance':null,'waitingForTopUp':null,'lastBalance':null,'lastBalanceRequest':null,'lastTopUpRequest':null,'lastDataUsage':{'timestamp':today,'start':today,'end':today,'today':today,'wifi':{'apps':{},'total':0},'mobile':{'apps':{},'total':0}},'lastTelephonyActivity':{'timestamp':today,'calltime':0,'smscount':0},'lastTelephonyReset':today,'lastDataReset':today,'lastCompleteDataReset':today,'lowLimit':false,'lowLimitThreshold':false,'lowLimitNotified':false,'zeroBalanceNotified':false,'dataUsageNotified':false,'nextReset':null,'plantype':'postpaid','resetTime':1,'trackingPeriod':'monthly','isMobileChartVisible':true,'isWifiChartVisible':false};var CONFIG_CACHE=[];function getApplicationMode(){if(noConfigFound){return'DATA_USAGE_ONLY';}
|
||||
return settings.plantype.toUpperCase();}
|
||||
var configuration,configurationIndex,noConfigFound=false;function setConfig(newConfiguration){configuration=newConfiguration;debug('Provider configuration done!');}
|
||||
function requestConfiguration(currentDataIcc,callback){if(!currentDataIcc||!currentDataIcc.iccInfo){console.error('No iccInfo available');return;}
|
||||
function returnConfiguration(){if(typeof callback==='function'){callback(configuration);}}
|
||||
if(configuration){setTimeout(function(){returnConfiguration();});return;}
|
||||
if(configurationIndex){loadConfiguration(currentDataIcc,returnConfiguration);}else{loadConfigurationIndex(function onIndex(){loadConfiguration(currentDataIcc,returnConfiguration);});}}
|
||||
function loadConfiguration(currentDataIcc,callback){var configFilePath=getConfigFilePath(currentDataIcc);if(CONFIG_CACHE[configFilePath]){ConfigManager.setConfig(CONFIG_CACHE[configFilePath]);(typeof callback==='function')&&callback();}else{LazyLoader.load(configFilePath,function(){CONFIG_CACHE[configFilePath]=configuration;(typeof callback==='function')&&callback();});}}
|
||||
function getConfigFilePath(currentDataIcc){noConfigFound=false;var mcc=currentDataIcc.iccInfo.mcc;var mnc=currentDataIcc.iccInfo.mnc;var key=mcc+'_'+mnc;var configDir=configurationIndex[key];if(!configDir){configDir='default';noConfigFound=true;}
|
||||
return'js/config/'+configDir+'/config.js';}
|
||||
function loadConfigurationIndex(callback){LazyLoader.getJSON('/js/config/index.json').then(function(json){configurationIndex=json;if(configurationIndex===null){console.error('Error loading the configuration index!'+'Response from LazyLoader was null.');configurationIndex={};}
|
||||
if(typeof callback==='function'){setTimeout(function(){callback();});}},function(error){console.error('Error loading the configuration index! '+'Error code: '+error);configurationIndex={};});}
|
||||
Date.prototype.toJSON=function(){return{'__date__':this.toISOString()};};function settingsReviver(k,v){if(v===null||typeof v!=='object'||!v.hasOwnProperty('__date__')){return v;}
|
||||
return new Date(v.__date__);}
|
||||
var NO_ICCID='NOICCID';var settings;function requestSettings(iccIdInfo,callback){var currentICCID=iccIdInfo||NO_ICCID;asyncStorage.getItem(currentICCID,function _wrapGetItem(localSettings){try{settings=JSON.parse(localSettings,settingsReviver);}catch(e){}
|
||||
if(settings===null){settings=deepCopy(DEFAULT_SETTINGS);debug('Storing default settings for ICCID:',currentICCID);asyncStorage.setItem(currentICCID,JSON.stringify(settings),callback&&callback.bind(null,settings));}else if(callback){callback(settings);}});}
|
||||
function requestAll(callback){SimManager.requestDataSimIcc(function(dataSimIcc){requestConfiguration(dataSimIcc.icc,function _afterConfig(configuration){requestSettings(dataSimIcc.iccId,function _afterSettings(settings){if(callback){callback(configuration,settings,dataSimIcc.iccId);}});});});}
|
||||
function dispatchOptionChange(name,value,oldValue,settings){var event=new CustomEvent('optionchange',{detail:{name:name,value:value,oldValue:oldValue,settings:settings}});window.dispatchEvent(event);debug('Event optionchange dispatched for',name);}
|
||||
function setOption(options,callback){SimManager.requestDataSimIcc(function(dataSimIcc){if(!settings){requestSettings(dataSimIcc.iccId,function _afterEnsuringSettings(){setOption(options,callback);});return;}
|
||||
var formerValue={};for(var name in options){if(options.hasOwnProperty(name)){formerValue[name]=settings[name];settings[name]=options[name];}}
|
||||
var currentICCID=dataSimIcc.iccId||NO_ICCID;asyncStorage.setItem(currentICCID,JSON.stringify(settings),function _onSet(){requestSettings(dataSimIcc.iccId,function _onSettings(settings){for(var name in options){if(options.hasOwnProperty(name)){dispatchOptionChange(name,settings[name],formerValue[name],settings);}}
|
||||
if(callback){callback();}});});});}
|
||||
function syncOption(name,value){var oldValue=settings[name];if(value===undefined){return oldValue;}
|
||||
var update={};update[name]=value;setOption(update);}
|
||||
var callbacks;function callCallbacks(evt){debug('Option',evt.detail.name,'has changed!');var callbackCollection=callbacks[evt.detail.name]||[];for(var i=0;i<callbackCollection.length;i++){var callback=callbackCollection[i];if(callback){callback(evt.detail.value,evt.detail.oldValue,evt.detail.name,evt.detail.settings);}}}
|
||||
function syncObserve(name,callback,avoidInitialCall){debug('Installing observer for',name);if(callbacks===undefined){callbacks={};window.addEventListener('storage',function _onSync(evt){if(evt.key==='sync'){var name=evt.newValue.split('#')[0];var oldValue=settings?settings[name]:undefined;debug('Synchronization request for',name,'received!');SimManager.requestDataSimIcc(function(dataSimIcc){requestSettings(dataSimIcc.iccId,function _onSettings(newSettings){settings=newSettings;dispatchOptionChange(name,settings[name],oldValue,settings);});});}});window.addEventListener('optionchange',callCallbacks);}
|
||||
if(callbacks[name]===undefined){callbacks[name]=[];}
|
||||
if(callbacks[name].indexOf(callback)<0){callbacks[name].push(callback);avoidInitialCall=avoidInitialCall||false;if(!avoidInitialCall&&callback){callback(settings[name],null,name,settings);}}}
|
||||
function syncRemoveObserver(name,callback){var callbackCollection=callbacks[name];if(!callbackCollection){return;}
|
||||
var index=callbackCollection.indexOf(callback);if(index>-1){callbackCollection.splice(index,1);}}
|
||||
function defaultValue(name){return deepCopy(DEFAULT_SETTINGS[name]);}
|
||||
return{getApplicationMode:getApplicationMode,setConfig:setConfig,requestAll:requestAll,requestSettings:requestSettings,setOption:setOption,defaultValue:defaultValue,option:syncOption,observe:syncObserve,removeObserver:syncRemoveObserver,get configuration(){return configuration;},supportCustomizeMode:false};}());;'use strict';var CostControl=(function(){var costcontrol;function getInstance(onready){debug('Initializing Cost Control');function goOn(){debug('Cost Control already ready!');onready(costcontrol);}
|
||||
if(costcontrol){if(SimManager.isMultiSim()){SimManager.requestDataSimIcc(function(dataSimIcc){if(costcontrol.iccId===dataSimIcc.iccId){goOn();}});}else{goOn();}
|
||||
return;}
|
||||
function setupCostControl(configuration,settings,iccId){costcontrol={iccId:iccId,request:request,lastDataResults:{},lastDataResultsPerApp:{},isBalanceRequestSMS:isBalanceRequestSMS};debug('Cost Control ready!');onready(costcontrol);}
|
||||
loadAPIs();ConfigManager.requestAll(setupCostControl);}
|
||||
var mobileMessageManager,statistics,isSendingBalanceRequest=false;function loadAPIs(){if('mozMobileMessage'in window.navigator){mobileMessageManager=window.navigator.mozMobileMessage;}
|
||||
if('mozNetworkStats'in window.navigator){statistics=window.navigator.mozNetworkStats;}
|
||||
debug('APIs loaded!');}
|
||||
function isBalanceRequestSMS(message,configuration){return message.receiver===configuration.balance.destination;}
|
||||
function request(requestObj,callback){ConfigManager.requestAll(function _onInfo(configuration,settings){debug('Request for:',requestObj.type);var force=requestObj.force;var result={};result.type=requestObj.type;function _requestDataStatistics(){SimManager.requestDataSimIcc(function(dataSim){requestDataStatistics(configuration,settings,callback,dataSim,result,requestObj);});}
|
||||
function _requestBalance(connection){var issues=getServiceIssues(configuration,settings,connection);var canBeIgnoredByForcing=(issues==='minimum_delay'&&force);if(issues&&!canBeIgnoredByForcing){result.status='error';result.details=issues;result.data=settings.lastBalance;if(callback){callback(result);}
|
||||
return;}
|
||||
var costIssues=getCostIssues(configuration,connection);if(!force&&costIssues){result.status='error';result.details=costIssues;result.data=settings.lastBalance;if(callback){callback(result);}
|
||||
return;}
|
||||
var isWaiting=settings.waitingForBalance!==null;var timeout=Toolkit.checkEnoughDelay(BALANCE_TIMEOUT,settings.lastBalanceRequest);if((isWaiting&&!timeout)||isSendingBalanceRequest){result.status='in_progress';result.data=settings.lastBalance;if(callback){callback(result);}
|
||||
return;}
|
||||
isSendingBalanceRequest=true;LazyLoader.load('js/iac_manager.js',function(){requestBalance(configuration,settings,callback,result);});}
|
||||
function _requestTopUp(connection){var issuesTopUp=getServiceIssues(configuration,settings,connection);if(issuesTopUp&&issuesTopUp!=='minimum_delay'){result.status='error';result.details=issuesTopUp;result.data=settings.lastDataUsage;if(callback){callback(result);}
|
||||
return;}
|
||||
var costIssuesTopUp=getCostIssues(configuration,connection);if(!force&&costIssuesTopUp){result.status='error';result.details=costIssuesTopUp;result.data=settings.lastBalance;if(callback){callback(result);}
|
||||
return;}
|
||||
var isWaitingTopUp=settings.waitingForTopUp!==null;var timeoutTopUp=Toolkit.checkEnoughDelay(BALANCE_TIMEOUT,settings.lastTopUpRequest);if(isWaitingTopUp&&!timeoutTopUp&&!force){result.status='in_progress';result.data=settings.lastDataUsage;if(callback){callback(result);}
|
||||
return;}
|
||||
var code=requestObj.data;LazyLoader.load('js/iac_manager.js',function(){requestTopUp(configuration,settings,code,callback,result);});}
|
||||
switch(requestObj.type){case'balance':SimManager.requestDataConnection(_requestBalance);break;case'topup':SimManager.requestDataConnection(_requestTopUp);break;case'datausage':if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(_requestDataStatistics,_requestDataStatistics);}else{_requestDataStatistics();}
|
||||
break;case'telephony':result.data=settings.lastTelephonyActivity;result.status='success';if(callback){callback(result);}
|
||||
break;}
|
||||
return;});}
|
||||
function getServiceIssues(configuration,settings,connection){if(!connection||!connection.data||!connection.voice||!connection.voice.connected){return'no_service';}
|
||||
var mode=ConfigManager.getApplicationMode();if(mode!=='PREPAID'){return'no_service';}
|
||||
if(connection.voice.relSignalStrength===null){return'no_coverage';}
|
||||
if(configuration.balance.minimum_delay){var isMinimumDelayHonored=Toolkit.checkEnoughDelay(configuration.balance.minimum_delay,settings.lastBalanceRequest);if(!isMinimumDelayHonored){return'minimum_delay';}}
|
||||
return'';}
|
||||
function getCostIssues(configuration,connection){var inRoaming=connection.voice.roaming;if(inRoaming&&configuration.is_roaming_free!==true){return'non_free_in_roaming';}
|
||||
if(!inRoaming&&configuration.is_free!==true){return'non_free';}
|
||||
return'';}
|
||||
var BALANCE_TIMEOUT=5*60*1000;function requestBalance(configuration,settings,callback,result){debug('Requesting balance...');result.data=settings.lastBalance;function sendSMS(){debug('After IAC broadcast ask for starting - balance');var newSMS=mobileMessageManager.send(configuration.balance.destination,configuration.balance.text);newSMS.onsuccess=function _onSuccess(){debug('Request SMS sent! Waiting for response.');if(!DEBUGGING){mobileMessageManager.delete(newSMS.result.id);}
|
||||
var newAlarm=addAlarmTimeout('balanceTimeout',BALANCE_TIMEOUT);newAlarm.onsuccess=function _alarmSet(evt){var id=evt.target.result;debug('Timeout for balance (',id,') update set to:',BALANCE_TIMEOUT);ConfigManager.setOption({'waitingForBalance':id,'lastBalanceRequest':new Date()},function _onSet(){isSendingBalanceRequest=false;result.status='success';if(callback){callback(result);}});};newAlarm.onerror=function _alarmFailedToSet(evt){ConfigManager.setOption({'lastBalanceRequest':new Date()},function _onSet(){isSendingBalanceRequest=false;debug('Failed to set timeout for balance request!');result.status='error';result.details='timeout_fail';if(callback){callback(result);}});};};newSMS.onerror=function _onError(){isSendingBalanceRequest=false;debug('Request SMS failed! But returning stored balance.');IACManager.broadcastEndOfSMSQuery('balance').then(function(msg){debug('After IAC broadcast ask for ending - balance');});result.status='error';result.details='request_fail';if(callback){callback(result);}};debug('Balance out of date. Requesting fresh data...');}
|
||||
IACManager.init(configuration);IACManager.broadcastStartOfSMSQuery('balance').then(sendSMS,sendSMS);}
|
||||
var TOPUP_TIMEOUT=5*60*1000;function requestTopUp(configuration,settings,code,callback,result){debug('Requesting TopUp with code',code,'...');function sendSMS(){debug('After IAC broadcast ask for starting - topup');var newSMS=mobileMessageManager.send(configuration.topup.destination,configuration.topup.text.replace(/\&code/g,code));newSMS.onsuccess=function _onSuccess(){debug('TopUp SMS sent! Waiting for response.');if(!DEBUGGING){mobileMessageManager.delete(newSMS.result.id);}
|
||||
var newAlarm=addAlarmTimeout('topupTimeout',TOPUP_TIMEOUT);newAlarm.onsuccess=function _alarmSet(evt){var id=evt.target.result;debug('Timeout for TopUp (',id,') update set to:',TOPUP_TIMEOUT);ConfigManager.setOption({'waitingForTopUp':id,'lastTopUpRequest':new Date()},function _onSet(){result.status='success';if(callback){callback(result);}});};newAlarm.onerror=function _alarmFailedToSet(evt){debug('Failed to set timeout for TopUp request!');result.status='error';result.details='timeout_fail';if(callback){callback(result);}};};newSMS.onerror=function _onError(){debug('TopUp SMS failed!');IACManager.broadcastEndOfSMSQuery('topup').then(function(msg){debug('After IAC broadcast ask for ending - topup');});result.status='error';result.details='request_fail';if(callback){callback(result);}};}
|
||||
IACManager.init(configuration);IACManager.broadcastStartOfSMSQuery('topup').then(sendSMS,sendSMS);}
|
||||
var DAY=24*3600*1000;function requestDataStatistics(configuration,settings,callback,dataSimIcc,result,requestParameters){debug('Statistics out of date. Requesting fresh data...');var apps=requestParameters&&requestParameters.apps;var start=requestParameters&&requestParameters.startDate;var end=requestParameters&&requestParameters.endDate;if(!start){var maxAge=1000*statistics.maxStorageAge;var minimumStart=new Date(Date.now()-maxAge);debug('The max age for samples is '+minimumStart);start=new Date(settings.lastCompleteDataReset||Date.now()-7*DAY);if(start<minimumStart){console.warn('Start date is surpassing the maximum age for the '+'samples. Setting to '+minimumStart);start=minimumStart;}}
|
||||
start=Toolkit.toMidnight(start);if(!end){var today=Toolkit.toMidnight(new Date());var tomorrow=new Date();tomorrow.setTime(today.getTime()+DAY);end=Toolkit.toMidnight(settings.nextReset?new Date(settings.nextReset.getTime()-DAY):tomorrow);}
|
||||
if(start>end){console.error('Start date is higher than end date. This must not '+'happen. Changed end date to day after startDate');end=new Date(start.getTime()+DAY);}
|
||||
var wifiInterface=Common.getWifiInterface();var currentSimcardNetwork=Common.getDataSIMInterface(dataSimIcc.iccId);var wifiRequests,simRequests;var pendingRequests=0;function checkForCompletion(){pendingRequests--;if(pendingRequests===0){updateDataUsage();}}
|
||||
function updateDataUsage(){var lastDataUsage={timestamp:new Date(),start:start,end:end,today:today,wifi:{apps:{},total:0,samples:[]},mobile:{apps:{},total:0,samples:[]}};function saveLastDataUsage(perApp){var savedUsage={};Object.keys(lastDataUsage).forEach(function(key){var value=lastDataUsage[key];if(key==='wifi'||key==='mobile'){if(perApp){value=settings.lastDataUsage[key];}
|
||||
savedUsage[key]={apps:{},total:value.total};Object.keys(value.apps).forEach(function(manifest){savedUsage[key].apps[manifest]={total:value.apps[manifest].total};});}else{savedUsage[key]=value;}});ConfigManager.setOption({'lastDataUsage':savedUsage},function _onSetItem(){debug('Statistics up to date and stored.');});}
|
||||
function aggregateSamples(network){if(!network.apps){return;}
|
||||
var manifestURLs=Object.keys(network.apps);if(manifestURLs.length===0){return;}
|
||||
var samplesByDate={};var today=Toolkit.toMidnight(new Date());var offset=today.getTimezoneOffset()*60*1000;manifestURLs.forEach(function(manifestURL){var samples=network.apps[manifestURL].samples;samples.forEach(function(sample){if(sample.date&&sample.date.__date__){sample.date=new Date(sample.date.__date__);}
|
||||
var sampleLocalTime=sample.date.getTime()+offset;var sampleUTCDate=Toolkit.toMidnight(new Date(sampleLocalTime));var aggregateSample=samplesByDate[sampleUTCDate.getTime()];if(!aggregateSample){aggregateSample=samplesByDate[sampleUTCDate.getTime()]={value:0,date:sample.date};}
|
||||
aggregateSample.value+=sample.value;});});var dates=Object.keys(samplesByDate);network.samples=dates.map(function(date){return samplesByDate[date];});network.samples.sort(function(a,b){return a.date.getTime()-b.date.getTime();});}
|
||||
function handleResult(request,network){var result=request.result;var data=adaptData(result);var manifestURL=request.result.appManifestURL;if(manifestURL&&manifestURL!=='null'){var isBrowser=request.result.browsingTrafficOnly&&manifestURL===Common.SYSTEM_MANIFEST;if(isBrowser){manifestURL=Common.BROWSER_APP.manifestURL;}
|
||||
network.apps[manifestURL]={samples:data[0],total:data[1]};}else{network.samples=network.samples.concat(data[0]);}
|
||||
network.total+=data[1];}
|
||||
if(simRequests){simRequests.forEach(function(request){handleResult(request,lastDataUsage.mobile);});aggregateSamples(lastDataUsage.mobile);}
|
||||
if(wifiRequests){wifiRequests.forEach(function(request){handleResult(request,lastDataUsage.wifi);});aggregateSamples(lastDataUsage.wifi);}
|
||||
var perApp=apps&&apps.length>0;saveLastDataUsage(perApp);result.status='success';result.data=lastDataUsage;if(perApp){costcontrol.lastDataResultsPerApp=lastDataUsage;}else{costcontrol.lastDataResults=lastDataUsage;}
|
||||
debug('Returning up to date statistics.');if(callback){callback(result);}}
|
||||
function requestPerAppUsage(networkId){function requestSamples(options){pendingRequests++;var req=statistics.getSamples(networkId,start,end,options);req.onsuccess=checkForCompletion;return req;}
|
||||
var requests;if(apps&&apps.length>0){requests=[];apps.forEach(function(manifestURL){if(manifestURL!==Common.SYSTEM_MANIFEST){var options={appManifestURL:manifestURL};if(manifestURL===Common.BROWSER_APP.manifestURL){options.appManifestURL=Common.SYSTEM_MANIFEST;options.browsingTrafficOnly=true;}
|
||||
requests.push(requestSamples(options));}});}else{requests=[requestSamples()];}
|
||||
return requests;}
|
||||
if(currentSimcardNetwork){simRequests=requestPerAppUsage(currentSimcardNetwork);}
|
||||
if(wifiInterface){wifiRequests=requestPerAppUsage(wifiInterface);}
|
||||
if(pendingRequests===0){updateDataUsage();}}
|
||||
function adaptData(networkStatsResult){var data=networkStatsResult.data;var output=[];var totalData,accum=0;for(var i=0;i<data.length;i++){var item=data[i];if(item.txBytes===undefined){output.push({date:item.date});continue;}
|
||||
totalData=0;if(item.rxBytes){totalData+=item.rxBytes;}
|
||||
if(item.txBytes){totalData+=item.txBytes;}
|
||||
accum+=totalData;output.push({value:totalData,date:item.date});}
|
||||
return[output,accum];}
|
||||
return{getInstance:getInstance,reset:function _onReset(){costcontrol=null;}};}());;(function(){'use strict';function inStandAloneMode(){return window.parent.location.pathname==='/message_handler.html';}
|
||||
if(!inStandAloneMode()){ConfigManager=window.parent.ConfigManager;CostControl=window.parent.CostControl;SimManager=window.parent.SimManager;}
|
||||
if(inStandAloneMode()&&window.history.length>1){debug('Nothing to do in message handler, returning to app...');window.history.back();}
|
||||
function inApplicationMode(){return window.parent.location.pathname==='/index.html';}
|
||||
var closing;function closeIfProceeds(){debug('Checking for closing...');if(inStandAloneMode()){closing=Common.closeApplication();}}
|
||||
function addAlarmTimeout(type,delay){var date=new Date();date.setTime(date.getTime()+delay);var request=navigator.mozAlarms.add(date,'ignoreTimezone',{type:type});return request;}
|
||||
window.addAlarmTimeout=addAlarmTimeout;function setNextReset(when,callback){asyncStorage.getItem('nextResetAlarm',function(id){debug('Current nextResetAlarm',id+'.',id?'Removing.':'');if(id){navigator.mozAlarms.remove(id);}
|
||||
if(!when){debug('Automatic reset disabled');updateResetAttributes(null,null,callback);return;}
|
||||
if(when.getTime()<Date.now()){debug('Faking a past reset alarm');_onAlarm({data:{type:'nextReset'}});if(callback){setTimeout(callback);}
|
||||
return;}
|
||||
var alarms=navigator.mozAlarms;var request=alarms.add(when,'ignoreTimezone',{type:'nextReset'});request.onsuccess=function _onSuccess(){debug('Setting nextResetAlarm',request.result,'to',when);updateResetAttributes(request.result,when,callback);};});}
|
||||
window.setNextReset=setNextReset;function getTopUpTimeout(callback){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var request=navigator.mozAlarms.getAll();request.onsuccess=function(e){var alarms=e.target.result;var length=alarms.length;if(!length){callback(null);return;}
|
||||
var refId=settings.waitingForTopUp;var index=0,alarm,found=false;while(index<length&&!found){alarm=alarms[index];found=(alarm.id===refId);index++;}
|
||||
if(found){debug('TopUp timeout found:',alarm.date);callback(alarm.date);}else{callback(null);}};});});}
|
||||
window.getTopUpTimeout=getTopUpTimeout;function addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror){onsuccess=onsuccess||function(){};onerror=onerror||function(){};NetworkUsageAlarm.updateAlarm(dataInterface,dataLimit,onsuccess,onerror);}
|
||||
window.addNetworkUsageAlarm=addNetworkUsageAlarm;function updateResetAttributes(alarmId,date,callback){asyncStorage.setItem('nextResetAlarm',alarmId,function _updateOption(){ConfigManager.setOption({nextReset:date},function _sync(){localStorage.sync='nextReset#'+Math.random();if(callback){callback();}});});}
|
||||
function sendIncorrectTopUpNotification(callback){var title='topup-incorrectcode-title2';var message='topup-incorrectcode-message3';sendNotification('topUpError',title,message);if(callback){callback();}}
|
||||
function sendBalanceThresholdNotification(remaining,settings,callback){debug('Low limit already notified:',settings.lowLimitNotified);debug('Zero balance already notified:',settings.lowLimitNotified);var type;if(remaining.balance===0&&!settings.zeroBalanceNotified){type='zeroBalance';}else if(settings.lowLimit&&remaining.balance<settings.lowLimitThreshold&&!settings.lowLimitNotified){type='lowBalance';}else if(callback){setTimeout(callback);return;}
|
||||
debug('Notification type:',type);var remainingBalance=_('currency',{currency:remaining.currency,value:remaining.balance});var title='low-balance-notification-title';var message={id:'low-balance-notification-text',args:{remaining:remainingBalance}};if(type==='zeroBalance'){title='usage';message='zero-balance-message';}
|
||||
sendNotification(type,title,message);var update={};var notified=(type==='lowBalance')?'lowLimitNotified':'zeroBalanceNotified';update[notified]=true;ConfigManager.setOption(update,callback);}
|
||||
window.sendBalanceThresholdNotification=sendBalanceThresholdNotification;function _onAlarm(alarm){clearTimeout(closing);SimManager.requestDataSimIcc(function(dataSimIcc){function _launchNextReset(){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){Common.resetAll(function updateNextResetAndClose(){Common.updateNextReset(settings.trackingPeriod,settings.resetTime,closeIfProceeds);});});}
|
||||
switch(alarm.data.type){case'balanceTimeout':ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.errors.BALANCE_TIMEOUT=true;ConfigManager.setOption({'errors':settings.errors,'waitingForBalance':null},function _onBalanceTimeout(){debug('Timeout for balance');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();closeIfProceeds();});});break;case'topupTimeout':ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.errors.TOPUP_TIMEOUT=true;ConfigManager.setOption({'errors':settings.errors,'waitingForTopUp':null},function _onBalanceTimeout(){debug('Timeout for topup');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();closeIfProceeds();});});break;case'nextReset':if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(_launchNextReset);}else{_launchNextReset();}
|
||||
break;}});}
|
||||
function getNofificationAction(type,app){var activityName,action;var noop=function(){};switch(type){case'lowBalance':case'zeroBalance':activityName='costcontrol/balance';action=function(){if(window.parent.BalanceTab){window.parent.CostControlApp.showBalanceTab();}};break;case'topUpError':activityName='costcontrol/balance';action=function(){if(window.parent.BalanceTab){window.parent.BalanceTab.topUpWithCode(true);}};break;default:activityName='costcontrol/data_usage';action=function(){if(window.parent.CostControlApp){window.parent.CostControlApp.showDataUsageTab();}};break;}
|
||||
if(!inStandAloneMode()){return function(){if(inApplicationMode()){app.launch();action&&action();}else{type=new MozActivity({name:activityName});}};}
|
||||
return noop;}
|
||||
function sendNotification(notificationType,title,message){navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){var app=evt.target.result;var iconURL=NotificationHelper.getIconURI(app);var navigate=getNofificationAction(notificationType,app);NotificationHelper.send(title,{'bodyL10n':message,'icon':iconURL,'data':notificationType}).then(function(notification){notification.addEventListener('click',function(){notification.close();navigate();});});};}
|
||||
function _onNetworkAlarm(alarm){clearTimeout(closing);navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var limit=Common.getDataLimit(settings);var limitText=Formatting.formatData(Formatting.smartRound(limit));var title={id:'data-limit-notification-title2',args:{limit:limitText}};var message='data-limit-notification-text2';sendNotification('dataUsage',title,message);ConfigManager.setOption({'dataUsageNotified':true},closeIfProceeds);return;});});};}
|
||||
function disableSilentModeFor(type,configuration){LazyLoader.load('js/iac_manager.js',function(){IACManager.init(configuration);IACManager.broadcastEndOfSMSQuery(type).then(function(msg){debug('After broadcasting for '+type+' (disabling)');});});}
|
||||
var costcontrol;function _getCCInstance(){CostControl.getInstance(function _onCostControl(ccontrol){costcontrol=ccontrol;if(inStandAloneMode()||inApplicationMode()){debug('Installing handlers');navigator.mozSetMessageHandler('sms-received',function _onSMS(sms){clearTimeout(closing);ConfigManager.requestAll(function _onInfo(configuration,settings){var isBalanceResponse=configuration.balance&&Array.isArray(configuration.balance.senders)&&configuration.balance.senders.indexOf(sms.sender)>-1;var isTopupResponse=configuration.topup&&Array.isArray(configuration.topup.senders)&&configuration.topup.senders.indexOf(sms.sender)>-1;if(!isBalanceResponse&&!isTopupResponse){closeIfProceeds();return;}
|
||||
debug('Parsing received SMS');var isBalance,isConfirmation,isError;isBalance=isConfirmation=isError=false;debug('Trying to recognize balance SMS');var description=new RegExp(configuration.balance.regexp);var balanceData=sms.body.match(description);if(!balanceData){debug('Trying to recognize zero balance SMS');var zeroDescription=configuration.balance.zero_regexp?new RegExp(configuration.balance.zero_regexp):null;if(zeroDescription&&zeroDescription.test(sms.body)){balanceData=['0.00','0','0'];}}
|
||||
isBalance=!!balanceData;if(!isBalance||balanceData.length<2){console.warn('Impossible to parse balance message.');debug('Trying to recognize TopUp confirmation SMS');description=new RegExp(configuration.topup.confirmation_regexp);isConfirmation=!!sms.body.match(description);if(!isConfirmation){console.warn('Impossible to parse TopUp confirmation message.');debug('Trying to recognize TopUp error SMS');description=new RegExp(configuration.topup.incorrect_code_regexp);isError=!!sms.body.match(description);if(!isError){console.warn('Impossible to parse TopUp confirmation msg.');}}}
|
||||
if(!isBalance&&!isConfirmation&&!isError){closeIfProceeds();return;}
|
||||
if(!DEBUGGING&&(isBalance&&(settings.waitingForBalance!==null))||(isConfirmation&&(settings.waitingForTopUp!==null))){var mobileMessageManager=window.navigator.mozMobileMessage;mobileMessageManager.delete(sms.id);}
|
||||
if(isBalance){var integer=balanceData[1].replace(/[^0-9]/g,'');var decimal=balanceData[2]||'0';var newBalance={balance:parseFloat(integer+'.'+decimal),currency:configuration.credit.currency,timestamp:new Date()};if(settings.waitingForBalance!==null){navigator.mozAlarms.remove(settings.waitingForBalance);debug('Balance timeout:',settings.waitingForBalance,'removed');disableSilentModeFor('balance',configuration);}
|
||||
ConfigManager.setOption({'lastBalance':newBalance,'waitingForBalance':null},function _onSet(){debug('Balance up to date and stored');debug('Trying to synchronize!');localStorage.sync='lastBalance#'+Math.random();sendBalanceThresholdNotification(newBalance,settings,closeIfProceeds);});}else if(isConfirmation){if(settings.waitingForTopUp!==null){navigator.mozAlarms.remove(settings.waitingForTopUp);debug('TopUp timeout:',settings.waitingForTopUp,'removed');disableSilentModeFor('topup',configuration);}
|
||||
ConfigManager.setOption({'waitingForTopUp':null,'lowLimitNotified':false,'zeroBalanceNotified':false},function _onSet(){debug('TopUp confirmed!');debug('Trying to synchronize!');localStorage.sync='waitingForTopUp#'+Math.random();closeIfProceeds();});}else if(isError){settings.errors.INCORRECT_TOPUP_CODE=true;navigator.mozAlarms.remove(settings.waitingForTopUp);debug('TopUp timeout: ',settings.waitingForTopUp,'removed');ConfigManager.setOption({'errors':settings.errors,'waitingForTopUp':null,'lowLimitNotified':false,'zeroBalanceNotified':false},function _onSet(){debug('Balance up to date and stored');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();sendIncorrectTopUpNotification(closeIfProceeds);});}});});navigator.mozSetMessageHandler('networkstats-alarm',_onNetworkAlarm);navigator.mozSetMessageHandler('alarm',_onAlarm);navigator.mozSetMessageHandler('sms-sent',function _onSent(sms){clearTimeout(closing);debug('SMS sent!');var configuration=ConfigManager.configuration;var mode=ConfigManager.getApplicationMode();if(mode==='PREPAID'&&!costcontrol.isBalanceRequestSMS(sms,configuration)){costcontrol.request({type:'balance'});}
|
||||
if(mode==='PREPAID'&&costcontrol.isBalanceRequestSMS(sms,configuration)){closeIfProceeds();}else{var mobileMessageManager=window.navigator.mozMobileMessage;var infoRequest=mobileMessageManager.getSegmentInfoForText(sms.body);infoRequest.onsuccess=function onInfo(evt){var realCount,smsInfo=evt.target.result;if(!smsInfo||!smsInfo.segments){console.error('Invalid getSegmentInfoForText() result. Counting 1 segment');realCount=1;}else{realCount=smsInfo.segments;}
|
||||
updateSMSCount(realCount);};infoRequest.onerror=function onError(){console.error('Can not retrieve segment info for body '+
|
||||
sms.body);updateSMSCount(1);};}
|
||||
function updateSMSCount(count){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.lastTelephonyActivity.timestamp=new Date();settings.lastTelephonyActivity.smscount+=count;ConfigManager.setOption({lastTelephonyActivity:settings.lastTelephonyActivity},function _sync(){localStorage.sync='lastTelephonyActivity#'+Math.random();closeIfProceeds();});});});}});navigator.mozSetMessageHandler('telephony-call-ended',function _onCall(tcall){clearTimeout(closing);if(tcall.direction!=='outgoing'){closeIfProceeds();return;}
|
||||
debug('Outgoing call finished!');SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var mode=ConfigManager.getApplicationMode();if(mode==='PREPAID'){costcontrol.request({type:'balance'});}
|
||||
settings.lastTelephonyActivity.timestamp=new Date();settings.lastTelephonyActivity.calltime+=tcall.duration;ConfigManager.setOption({lastTelephonyActivity:settings.lastTelephonyActivity},function _sync(){localStorage.sync='lastTelephonyActivity#'+Math.random();closeIfProceeds();});});});});}
|
||||
var readyEvent=new CustomEvent('messagehandlerready');window.parent.dispatchEvent(readyEvent);});}
|
||||
_getCCInstance();}());
|
||||
271
assets/webapps/costcontrol.gaiamobile.org/gaia_build_widget.js
Normal file
271
assets/webapps/costcontrol.gaiamobile.org/gaia_build_widget.js
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
;;(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);;;this.asyncStorage=(function(){'use strict';var DBNAME='asyncStorage';var DBVERSION=1;var STORENAME='keyvaluepairs';var db=null;function withDatabase(f){if(db){f();}else{var openreq=indexedDB.open(DBNAME,DBVERSION);openreq.onerror=function withStoreOnError(){console.error('asyncStorage: can\'t open database:',openreq.error.name);};openreq.onupgradeneeded=function withStoreOnUpgradeNeeded(){openreq.result.createObjectStore(STORENAME);};openreq.onsuccess=function withStoreOnSuccess(){db=openreq.result;f();};}}
|
||||
function withStore(type,callback,oncomplete){withDatabase(function(){var transaction=db.transaction(STORENAME,type);if(oncomplete){transaction.oncomplete=oncomplete;}
|
||||
callback(transaction.objectStore(STORENAME));});}
|
||||
function getItem(key,callback){var req;withStore('readonly',function getItemBody(store){req=store.get(key);req.onerror=function getItemOnError(){console.error('Error in asyncStorage.getItem(): ',req.error.name);};},function onComplete(){var value=req.result;if(value===undefined){value=null;}
|
||||
callback(value);});}
|
||||
function setItem(key,value,callback){withStore('readwrite',function setItemBody(store){var req=store.put(value,key);req.onerror=function setItemOnError(){console.error('Error in asyncStorage.setItem(): ',req.error.name);};},callback);}
|
||||
function removeItem(key,callback){withStore('readwrite',function removeItemBody(store){var req=store.delete(key);req.onerror=function removeItemOnError(){console.error('Error in asyncStorage.removeItem(): ',req.error.name);};},callback);}
|
||||
function clear(callback){withStore('readwrite',function clearBody(store){var req=store.clear();req.onerror=function clearOnError(){console.error('Error in asyncStorage.clear(): ',req.error.name);};},callback);}
|
||||
function length(callback){var req;withStore('readonly',function lengthBody(store){req=store.count();req.onerror=function lengthOnError(){console.error('Error in asyncStorage.length(): ',req.error.name);};},function onComplete(){callback(req.result);});}
|
||||
function key(n,callback){if(n<0){callback(null);return;}
|
||||
var req;withStore('readonly',function keyBody(store){var advanced=false;req=store.openCursor();req.onsuccess=function keyOnSuccess(){var cursor=req.result;if(!cursor){return;}
|
||||
if(n===0||advanced){return;}
|
||||
advanced=true;cursor.advance(n);};req.onerror=function keyOnError(){console.error('Error in asyncStorage.key(): ',req.error.name);};},function onComplete(){var cursor=req.result;callback(cursor?cursor.key:null);});}
|
||||
return{getItem:getItem,setItem:setItem,removeItem:removeItem,clear:clear,length:length,key:key};}());;;'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);}});}};;;'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();}());
|
||||
361
assets/webapps/costcontrol.gaiamobile.org/index.html
Normal file
361
assets/webapps/costcontrol.gaiamobile.org/index.html
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en-US" dir="ltr">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-group" content="theme-settings">
|
||||
<meta name="theme-color" content="var(--header-background)">
|
||||
<title data-l10n-id="usage">Usage</title>
|
||||
|
||||
<!-- Building blocks -->
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/headers.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/buttons.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/input_areas.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/lists.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/progress_activity.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/tabs.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/confirm.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/style/layout.css">
|
||||
|
||||
<!-- Gaia Components -->
|
||||
<link rel="localization" href="/locales-obj/index.{locale}.json">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/shared/elements/gaia-icons/gaia-icons.css">
|
||||
<link rel="stylesheet" type="text/css" href="app://theme.gaiamobile.org/shared/elements/gaia-theme/gaia-theme.css">
|
||||
<!-- <script defer="" src="/shared/js/component_utils.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/elements/gaia_checkbox/script.js"></script> -->
|
||||
|
||||
<!-- App and Views -->
|
||||
<link rel="stylesheet" type="text/css" href="style/app.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/settings.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/datausage.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/topup.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/timestamp-highlights.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/balance.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/telephony.css">
|
||||
<link rel="stylesheet" type="text/css" href="style/views/appdetail.css">
|
||||
|
||||
<!-- Localization -->
|
||||
<meta name="defaultLanguage" content="en-US">
|
||||
<meta name="availableLanguages" content="ar:201601260729, bg:201601260729, bn-BD:201601260729, ca:201601260729, cs:201601260729, da:201601260729, de:201601260729, el:201601260729, en-US:201601260729, es:201601260729, eu:201601260729, fr:201601260729, gl:201601260729, hr:201601260729, hu:201601260729, it:201601260729, ja:201601260729, km:201601260729, ko:201601260729, lt:201601260729, mk:201601260729, ms:201601260729, ne-NP:201601260729, nl:201601260729, pa:201601260729, pl:201601260729, pt-BR:201601260729, ro:201601260729, ru:201601260729, sk:201601260729, sq:201601260729, sr-Cyrl:201601260729, sr-Latn:201601260729, sv-SE:201601260729, tr:201601260729, zh-CN:201601260729, zh-TW:201601260729">
|
||||
|
||||
|
||||
<!-- Firefox Desktop shims -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- <script type="text/javascript" defer="" src="shared/js/l10n.js"></script> -->
|
||||
<!-- TODO: Lazyly loaded, remove when mozHour12 is part of the platform
|
||||
<script type="text/javascript" defer src="shared/js/date_time_helper.js"></script>
|
||||
-->
|
||||
<!-- <script type="text/javascript" defer="" src="shared/js/async_storage.js"></script> -->
|
||||
<!-- <script type="text/javascript" defer="" src="shared/js/accessibility_helper.js"></script> -->
|
||||
<!-- <script type="text/javascript" defer="" src="shared/js/settings_listener.js"></script> -->
|
||||
<!-- <script type="text/javascript" defer="" src="shared/js/lazy_loader.js"></script> -->
|
||||
<!-- <script type="text/javascript" defer="" src="shared/js/format.js"></script> -->
|
||||
<!-- <script type="text/javascript" defer="" src="/shared/js/url_helper.js"></script> -->
|
||||
|
||||
<!-- Gaia Components -->
|
||||
<!-- <script defer="" src="/shared/elements/config.js"></script> -->
|
||||
<!-- <script defer="" src="/shared/elements/gaia-header/dist/gaia-header.js"></script> -->
|
||||
|
||||
<!-- <script type="text/javascript" defer="" src="js/app.js"></script> -->
|
||||
<!-- <script type="text/javascript" defer="" src="js/application_init.js"></script> --><script src="./gaia_build_defer_index.js" defer="" type="text/javascript"></script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Include the app icon in the application.zip -->
|
||||
<link rel="resource" type="image/png" href="shared/resources/branding/browser_84.png">
|
||||
<link rel="resource" type="image/png" href="shared/resources/branding/browser_126.png">
|
||||
<link rel="resource" type="image/png" href="shared/resources/branding/browser_142.png">
|
||||
<link rel="resource" type="image/png" href="shared/resources/branding/browser_189.png">
|
||||
<link rel="resource" type="image/png" href="shared/resources/branding/browser_284.png">
|
||||
<meta content="2.5" name="appVersion"></head>
|
||||
<body role="application" class="theme-settings">
|
||||
|
||||
<section id="splash_section" class="window splash">
|
||||
</section>
|
||||
|
||||
<section id="main" role="region" class="window skin-organic non-ready">
|
||||
<div id="tabpanel">
|
||||
<!-- XXX: The order of sections is important (tabs should be place above
|
||||
the overlays) and we should distinguish between TABS and OVERLAY VIEWS -->
|
||||
<gaia-header>
|
||||
<h1 data-l10n-id="usage">Usage</h1>
|
||||
<button aria-label="Settings" class="settings-button" data-icon="settings" data-l10n-id="settings-button"></button>
|
||||
</gaia-header>
|
||||
|
||||
<!-- Bottom filters (Telephony / Cost Control and Data Usage) -->
|
||||
<ul id="tabs" role="tablist" class="bb-tablist" data-type="filter" data-items="2">
|
||||
<li id="balance-tab-filter" role="presentation">
|
||||
<a id="balance-tab-control" data-l10n-id="balance" href="#balance-tab" role="tab" aria-controls="balance-tab">Balance</a>
|
||||
</li>
|
||||
<li id="telephony-tab-filter" role="presentation" hidden="">
|
||||
<a id="telephony-tab-control" data-l10n-id="phone" href="#telephony-tab" role="tab" aria-controls="telephony-tab">Phone</a>
|
||||
</li>
|
||||
<li id="datausage-tab-filter" role="presentation">
|
||||
<a id="datausage-tab-control" data-l10n-id="internet" href="#datausage-tab" role="tab" aria-controls="datausage-tab">Internet</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- BALANCE TAB -->
|
||||
<section aria-labelledby="balance-tab-control" role="region tabpanel" id="balance-tab" class="bb-tabpanel view" data-viewport="left" hidden=""><!--
|
||||
|
||||
<section class="content">
|
||||
|
||||
<div id="cost-control-topup-countdown" class="countdown" hidden="">
|
||||
<p>
|
||||
<span id="top-up-countdown">
|
||||
00:00
|
||||
</span>
|
||||
|
||||
<span data-l10n-id="top-up-in-progress2">
|
||||
Your top-up is being processed.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="cost-control-message-area" class="error-messages" hidden="">
|
||||
<p id="error-message-placeholder">
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="cost-control-info-area" class="overview">
|
||||
<ul class="buttons-list end">
|
||||
<li>
|
||||
<button class="icon icon-reload" id="balance-tab-update-button" data-l10n-id="update-button">
|
||||
Update
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="info">
|
||||
<div id="cost-control-icon" class="icons">
|
||||
<span class="warning">
|
||||
</span>
|
||||
<progress>
|
||||
</progress>
|
||||
</div>
|
||||
<p id="balance-tab-credit">
|
||||
</p>
|
||||
<p id="balance-tab-time">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="buttons-list">
|
||||
<li>
|
||||
<button class="icon icon-topup" id="balance-tab-topup-ussd-button" data-l10n-id="topup-ussd-button2" hidden="">
|
||||
Open top-up menu
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="icon icon-topupcode" id="balance-tab-topup-button" data-l10n-id="topup-button2" hidden="">
|
||||
Use top-up code
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<script type="text/javascript" defer="" src="js/views/balance.js"></script>
|
||||
</section>
|
||||
|
||||
--></section>
|
||||
|
||||
<!-- TELEPHONY TAB -->
|
||||
<section aria-labelledby="telephony-tab-control" role="region tabpanel" id="telephony-tab" class="bb-tabpanel view" data-viewport="left" hidden=""><!--
|
||||
|
||||
<section>
|
||||
<ul>
|
||||
<li>
|
||||
<p id="telephony-time">
|
||||
</p>
|
||||
<dl>
|
||||
<dt data-l10n-id="call-made">
|
||||
Call made
|
||||
</dt>
|
||||
<dd>
|
||||
<span id="telephony-calltime">
|
||||
</span>
|
||||
</dd>
|
||||
<dt data-l10n-id="sms-sent">
|
||||
SMS Sent
|
||||
</dt>
|
||||
<dd>
|
||||
<span id="telephony-smscount">
|
||||
</span>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li id="billing-cycle">
|
||||
<dl>
|
||||
<dt data-l10n-id="billing-cycle-ends">Billing cycle ends</dt>
|
||||
<dd><time id="reset-date">26 Dec</time></dd>
|
||||
</dl>
|
||||
<p class="meta" data-l10n-id="tracking-will-reset">Tracking will reset on this date</p>
|
||||
</li>
|
||||
</ul>
|
||||
<script type="text/javascript" defer="" src="js/views/telephony.js"></script>
|
||||
</section>
|
||||
|
||||
--></section>
|
||||
|
||||
<!-- DATA USAGE TAB -->
|
||||
<section aria-labelledby="datausage-tab-control" id="datausage-tab" role="region tabpanel" class="bb-tabpanel view" data-viewport="right" hidden=""><!--
|
||||
|
||||
<div class="view-scroll">
|
||||
<section class="content">
|
||||
<section id="graphic-area" class="graph" role="img" aria-labelledby="axis-layer today-layer limits-layer warning-layer">
|
||||
<canvas id="background-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="wifi-layer" aria-hidden="true" hidden=""></canvas>
|
||||
<canvas id="mobile-layer" aria-hidden="true" hidden=""></canvas>
|
||||
<canvas id="axis-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="today-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="warning-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="limits-layer" aria-hidden="true"></canvas>
|
||||
<img alt="" src="./style/images/app/ui/datausage/pattern.png" id="graphic-pattern" hidden="">
|
||||
</section>
|
||||
|
||||
<ul class="toggle-data" data-type="list">
|
||||
<li id="mobileItem">
|
||||
<gaia-checkbox id="mobileCheck">
|
||||
<label>
|
||||
<span class="data-origin-label" data-l10n-id="mobile-usage"></span>
|
||||
<span class="overview" id="mobileOverview"></span>
|
||||
<span></span>
|
||||
</label>
|
||||
</gaia-checkbox>
|
||||
</li>
|
||||
<li id="wifiItem">
|
||||
<gaia-checkbox id="wifiCheck">
|
||||
<label>
|
||||
<span class="data-origin-label" data-l10n-id="wifi-usage">-</span>
|
||||
<span class="overview" id="wifiOverview"></span>
|
||||
<span></span>
|
||||
</label>
|
||||
</gaia-checkbox>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<header id="app-usage-header">
|
||||
<h2 data-l10n-id="app-usage-list-header">Mobile App Usage</h2>
|
||||
</header>
|
||||
|
||||
<div id="app-usage-no-data" data-l10n-id="app-usage-no-data" hidden="">
|
||||
You have not used any mobile data yet. Usage for each application will
|
||||
show up here when you do.
|
||||
</div>
|
||||
|
||||
<ul id="app-usage-list">
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<script type="text/javascript" defer="" src="js/views/datausage.js"></script>
|
||||
|
||||
--></section>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- The top up input -->
|
||||
<section role="dialog" id="topup-dialog" class="view" data-viewport="bottom" hidden=""><!--
|
||||
|
||||
<gaia-header id="topup-header" action="close">
|
||||
<h1 data-l10n-id="top-up"></h1>
|
||||
<button id="topup-send-button" data-l10n-id="send">Send</button>
|
||||
</gaia-header>
|
||||
<section class="content">
|
||||
<div class="info">
|
||||
<h2 data-l10n-id="enter-top-up-code">
|
||||
Enter the top up code
|
||||
</h2>
|
||||
<p id="topup-code-explanation" data-l10n-id="top-up-code-explanation2">
|
||||
Find it on the scratch card or directly in your receipt.
|
||||
</p>
|
||||
<p id="topup-incorrect-code" data-l10n-id="incorrect-code2" hidden="">
|
||||
Make sure the code is correct and try again.
|
||||
</p>
|
||||
<p id="topup-error" data-l10n-id="topup-error2" hidden="">
|
||||
There was a problem sending the code. Please, try again.
|
||||
</p>
|
||||
<section class="loading" id="topup-in-progress" hidden="">
|
||||
<progress>
|
||||
</progress>
|
||||
<p data-l10n-id="wait-for-confirmation">
|
||||
You'll receive a confirmation message
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
<form>
|
||||
<input id="topup-code-input" type="number">
|
||||
</form>
|
||||
|
||||
--></section>
|
||||
|
||||
<!-- App Detail view -->
|
||||
<section id="appdetail-view" class="view" data-viewport="right" hidden=""><!--
|
||||
<gaia-header action="back">
|
||||
<h1>{{localized-app-name}}</h1>
|
||||
</gaia-header>
|
||||
|
||||
<div class="view-scroll">
|
||||
<section class="usage fade">
|
||||
<section id="app-graphic-area" class="graph" role="img" aria-labelledby="app-axis-layer app-today-layer app-limits-layer app-warning-layer">
|
||||
<canvas id="app-background-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-wifi-layer" aria-hidden="true" hidden=""></canvas>
|
||||
<canvas id="app-mobile-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-axis-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-today-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-warning-layer" aria-hidden="true"></canvas>
|
||||
<canvas id="app-limits-layer" aria-hidden="true"></canvas>
|
||||
<img alt="" src="./style/images/app/ui/datausage/pattern.png" id="app-graphic-pattern" hidden="">
|
||||
</section>
|
||||
|
||||
<p class="info" data-l10n-id="data-used-since" hidden="">
|
||||
{{amount}} of data used since {{start-date}}
|
||||
</p>
|
||||
<p class="info" data-l10n-id="data-used-this-week" hidden="">
|
||||
{{amount}} of data used this week
|
||||
</p>
|
||||
<p class="info" data-l10n-id="data-used-this-month" hidden="">
|
||||
{{amount}} of data used this month
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" defer="" src="js/views/appdetail.js"></script>
|
||||
--></section>
|
||||
|
||||
<!-- Settings view -->
|
||||
<section id="settings-view" class="view" data-viewport="bottom">
|
||||
<iframe id="settings-view-placeholder"></iframe>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
<iframe id="message-handler" src="">
|
||||
</iframe>
|
||||
<iframe id="fte_view" class="window non-ready"></iframe>
|
||||
|
||||
<!-- SIM non ready screen -->
|
||||
<form role="dialog" class="view" data-type="confirm" data-viewport="ethereal" id="non-ready-screen">
|
||||
<section>
|
||||
<h1>Card is not ready</h1>
|
||||
<p>The button will close the application.</p>
|
||||
<progress hidden=""></progress>
|
||||
</section>
|
||||
<menu>
|
||||
<button class="full" data-l10n-id="ok">OK</button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
40
assets/webapps/costcontrol.gaiamobile.org/js/app.js
Normal file
40
assets/webapps/costcontrol.gaiamobile.org/js/app.js
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
;'use strict';var CostControlApp=(function(){var costcontrol,initialized=false,hashFromLastRun,hashFromNotification;var vmanager;function waitForSIMReady(callback){SimManager.requestDataSimIcc(function _onIccId(dataSim){var dataSimIcc=dataSim.icc;var cardState=dataSimIcc.cardState;if(cardState!=='ready'){showNonReadyScreen(cardState);debug('SIM not ready:',cardState);dataSimIcc.oncardstatechange=function(){waitForSIMReady(callback);};}else{hideNotReadyScreen();debug('SIM ready. ICCID:',dataSim.iccId);dataSimIcc.oncardstatechange=undefined;callback&&callback();}},function _errorNoSim(){console.warn('Error when trying to get the ICC, SIM not detected.');LazyLoader.load(['/shared/js/airplane_mode_helper.js'],function(){AirplaneModeHelper.ready(function(){var fakeState=null;if(AirplaneModeHelper.getStatus()==='enabled'){console.warn('The airplaneMode is enabled.');fakeState='airplaneMode';window.addEventListener('airplaneModeDisabled',function _onAirplanemodeDisabled(evt){if(evt.detail&&evt.detail.serviceId==='data'){waitForSIMReady(startApp);}});}
|
||||
showNonReadyScreen(fakeState);});});});}
|
||||
var nonReadyScreen;function showNonReadyScreen(cardState){if(isApplicationLocalized){realshowNonReadyScreen(cardState);}else{window.addEventListener('localized',function _onlocalized(){window.removeEventListener('localized',_onlocalized);realshowNonReadyScreen(cardState);});}
|
||||
function realshowNonReadyScreen(messageId){debug('Showing non-ready screen.');if(!nonReadyScreen){nonReadyScreen=new NonReadyScreen(document.getElementById('non-ready-screen'));}
|
||||
nonReadyScreen.updateForState(cardState);vmanager.changeViewTo(nonReadyScreen.id);}}
|
||||
function hideNotReadyScreen(status){debug('Hiding non-ready screen.');if(vmanager.getCurrentView()==='non-ready-screen'){vmanager.closeCurrentView();}
|
||||
return;}
|
||||
var tabmanager,settingsVManager;function _onHashChange(evt){var parser=document.createElement('a');parser.href=evt.oldURL;var oldHash=parser.hash.split('#');parser.href=evt.newURL;var newHash=parser.hash.split('#');if(newHash.length>3){console.error('Cost Control bad URL schema');return;}
|
||||
debug('URL schema before normalizing:',newHash);var normalized=false;if(!newHash[1]&&oldHash[1]){newHash[1]=oldHash[1];normalized=true;}
|
||||
if(newHash.length===3&&newHash[2]===''){if(oldHash.length===3){newHash[2]=oldHash[2];}else{newHash=newHash.slice(0,2);}
|
||||
normalized=true;}
|
||||
if(normalized){debug('URL schema after normalization:',newHash);window.location.hash=newHash.join('#');return;}
|
||||
if(newHash[1]){tabmanager.changeViewTo(newHash[1]);}
|
||||
if(newHash.length<3){vmanager.closeCurrentView();}else{vmanager.changeViewTo(newHash[2],'#tabpanel');}}
|
||||
function setupCardHandler(){tabmanager=new ViewManager(['balance-tab','telephony-tab',{id:'datausage-tab',tab:'right'}]);settingsVManager=new ViewManager();window.addEventListener('hashchange',_onHashChange);}
|
||||
function loadMessageHandler(){var messageHandlerFrame=document.getElementById('message-handler');var thereIsNextReset=ConfigManager.option('nextReset');var alreadyLoaded=messageHandlerFrame.src.contains('message_handler.html');if(alreadyLoaded&&thereIsNextReset){setNextReset(ConfigManager.option('nextReset'));return;}
|
||||
if(thereIsNextReset){window.addEventListener('messagehandlerready',function _setNextReset(){window.removeEventListener('messagehandlerready',_setNextReset);setNextReset(ConfigManager.option('nextReset'));});}
|
||||
messageHandlerFrame.src='message_handler.html';}
|
||||
function _onDataSimChange(){CostControl.reset();ConfigManager.setConfig(null);SimManager.requestDataSimIcc(startApp);}
|
||||
function startApp(callback){if(!ConfigManager.supportCustomizeMode){SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function(settings){if(settings.trackingPeriod==='custom'){ConfigManager.setOption({trackingPeriod:'never'});asyncStorage.getItem('nextResetAlarm',function(id){debug('Current nextResetAlarm',id+'.',id?'Removing.':'');if(id){navigator.mozAlarms.remove(id);}
|
||||
asyncStorage.setItem('nextResetAlarm',null,function(){ConfigManager.setOption({nextReset:null});});});}});});}
|
||||
if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',_onDataSimChange);}
|
||||
CostControl.getInstance(function _onCostControlReady(instance){if(ConfigManager.option('fte')){startFTE();return;}
|
||||
loadMessageHandler();costcontrol=instance;if(!initialized){setupApp(callback);}else{loadSettings();updateUI(callback);}});}
|
||||
var isApplicationLocalized=false;window.addEventListener('localized',function _onLocalize(){isApplicationLocalized=true;if(initialized){updateUI();loadSettings();}});function setupApp(callback){setupCardHandler();var settingsButtons=document.querySelectorAll('.settings-button');Array.prototype.forEach.call(settingsButtons,function _eachSettingsButton(button){button.addEventListener('click',function _showSettings(){window.location.hash='##settings-view';});});navigator.mozSetMessageHandler('activity',function _handleActivity(activityRequest){var name=activityRequest.source.name;switch(name){case'costcontrol/balance':window.location.hash='#balance-tab';break;case'costcontrol/telephony':window.location.hash='#telephony-tab';break;case'costcontrol/data_usage':window.location.hash='#datausage-tab';break;}});window.navigator.mozSetMessageHandler('notification',function _onNotification(notification){if(!notification.clicked){return;}
|
||||
debug('Notification was clicked!');navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){var app=evt.target.result;app.launch();var type=notification.data;debug('Notification type:',type);handleNotification(type);};});document.addEventListener('visibilitychange',function _onVisibilityChange(evt){if(!document.hidden&&initialized){waitForSIMReady();}});updateUI(callback);ConfigManager.observe('plantype',updateUI,true);initialized=true;loadSettings();}
|
||||
function loadSettings(){window.performance.mark('loadSettingsStart');document.getElementById('settings-view-placeholder').src='settings.html';}
|
||||
function handleNotification(type){switch(type){case'topUpError':BalanceTab.topUpWithCode(true);break;case'lowBalance':case'zeroBalance':window.location.hash='#balance-tab';hashFromNotification='#balance-tab';break;case'dataUsage':hashFromNotification='#datausage-tab';tabmanager.changeViewTo('datausage-tab');break;}}
|
||||
var currentMode;function updateUI(callback){SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){var mode=ConfigManager.getApplicationMode();var newHash=window.location.hash;var tabs=document.getElementById('tabs');var dataUsageTab=document.getElementById('datausage-tab');debug('App UI mode: ',mode);if(mode!==currentMode){currentMode=mode;if(mode==='DATA_USAGE_ONLY'){tabs.hidden=true;dataUsageTab.classList.add('standalone');newHash='#datausage-tab';}else{dataUsageTab.classList.remove('standalone');tabs.hidden=false;document.getElementById('balance-tab-filter').hidden=(mode!=='PREPAID');document.getElementById('telephony-tab-filter').hidden=(mode!=='POSTPAID');if(!isDataUsageTabShown()){newHash=(mode==='PREPAID')?'#balance-tab#':'#telephony-tab#';}}
|
||||
window.location.hash=hashFromNotification||hashFromLastRun||newHash;hashFromLastRun=hashFromNotification=null;requestAnimationFrame(function continueLoading(){document.getElementById('main').classList.remove('non-ready');if(mode==='PREPAID'){if(typeof TelephonyTab!=='undefined'){TelephonyTab.finalize();}
|
||||
if(typeof BalanceTab!=='undefined'){BalanceTab.initialize();}}else if(mode==='POSTPAID'){if(typeof BalanceTab!=='undefined'){BalanceTab.finalize();}
|
||||
if(typeof TelephonyTab!=='undefined'){TelephonyTab.initialize();}}});}
|
||||
(typeof callback==='function')&&callback();});});}
|
||||
function isDataUsageTabShown(){return window.location.hash.split('#')[1]==='datausage-tab';}
|
||||
function onFteFinished(e){if(e.origin!==Common.COST_CONTROL_APP){return;}
|
||||
var type=e.data.type;if(type==='fte_finished'){window.removeEventListener('message',onFteFinished);document.getElementById('splash_section').hidden='true';ConfigManager.requestAll(function(){startApp(Common.closeFTE);});}}
|
||||
function startFTE(){window.addEventListener('message',onFteFinished);var mode=ConfigManager.getApplicationMode();Common.startFTE(mode);}
|
||||
function initApp(){hashFromLastRun=window.location.hash;window.location.hash='';vmanager=new ViewManager();waitForSIMReady(startApp);}
|
||||
return{init:function(){var SCRIPTS_NEEDED=['js/utils/debug.js','js/common.js','js/views/NonReadyScreen.js','js/utils/toolkit.js','js/view_manager.js'];if(!window.navigator.mozMobileConnections||!window.navigator.mozIccManager||!window.navigator.mozNetworkStats){LazyLoader.load(SCRIPTS_NEEDED,function _showError(){vmanager=new ViewManager();showNonReadyScreen(null);});}else{SCRIPTS_NEEDED=['js/sim_manager.js','js/utils/debug.js','shared/js/date_time_helper.js','js/utils/chart.js','js/utils/formatting.js','js/utils/toolkit.js','js/settings/networkUsageAlarm.js','js/common.js','js/costcontrol.js','js/config/config_manager.js','js/views/NonReadyScreen.js','js/view_manager.js'];LazyLoader.load(SCRIPTS_NEEDED,initApp);}
|
||||
if(navigator.mozAudioChannelManager){navigator.mozAudioChannelManager.volumeControlChannel='notification';}},reset:function(){costcontrol=null;initialized=false;vmanager=null;tabmanager=null;settingsVManager=null;currentMode=null;isApplicationLocalized=false;window.removeEventListener('dataSlotChange',_onDataSimChange);window.removeEventListener('hashchange',_onHashChange);window.removeEventListener('message',onFteFinished);window.location.hash='';nonReadyScreen=null;},showBalanceTab:function _showBalanceTab(){window.location.hash='#balance-tab';},showDataUsageTab:function _showDataUsageTab(){window.location.hash='#datausage-tab';},showAppDetailView:function _showAppDetailView(){window.location.hash='##appdetail-view';},_onHashChange:_onHashChange};}());
|
||||
|
|
@ -0,0 +1 @@
|
|||
;'use strict';CostControlApp.init();
|
||||
28
assets/webapps/costcontrol.gaiamobile.org/js/common.js
Normal file
28
assets/webapps/costcontrol.gaiamobile.org/js/common.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
;'use strict';function addAlarmTimeout(type,delay){var handlerContainer=document.getElementById('message-handler');return handlerContainer.contentWindow.addAlarmTimeout(type,delay);}
|
||||
function setNextReset(when,callback){var handlerContainer=document.getElementById('message-handler');return handlerContainer?handlerContainer.contentWindow.setNextReset(when,callback):window.setNextReset(when,callback);}
|
||||
function getTopUpTimeout(callback){var handlerContainer=document.getElementById('message-handler');return handlerContainer?handlerContainer.contentWindow.getTopUpTimeout(callback):window.getTopUpTimeout(callback);}
|
||||
function addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror){var handlerContainer=document.getElementById('message-handler');if(handlerContainer){handlerContainer.contentWindow.addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror);}else{window.addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror);}}
|
||||
function sendBalanceThresholdNotification(remaining,settings,callback){var handlerContainer=document.getElementById('message-handler');if(handlerContainer){handlerContainer.contentWindow.sendBalanceThresholdNotification(remaining,settings,callback);}}
|
||||
function resetTelephony(callback){ConfigManager.setOption({lastTelephonyReset:new Date(),lastTelephonyActivity:{calltime:0,smscount:0,timestamp:new Date()}},callback);}
|
||||
var Common={COST_CONTROL_APP:'app://costcontrol.gaiamobile.org',DATA_USAGE_WARNING:0.8,allApps:null,allAppsLoaded:false,allNetworkInterfaces:null,allNetworkInterfaceLoaded:false,specialApps:['app://search.gaiamobile.org/manifest.webapp'],SYSTEM_MANIFEST:'app://system.gaiamobile.org/manifest.webapp',BROWSER_APP:{manifestURL:'app://browser.gaiamobile.org/manifest.webapp',origin:'',manifest:{icons:{'84':'/shared/resources/branding/browser_84.png','126':'/shared/resources/branding/browser_126.png','142':'/shared/resources/branding/browser_142.png','189':'/shared/resources/branding/browser_189.png','284':'/shared/resources/branding/browser_284.png'},name:'browser'}},startFTE:function(mode){var iframe=document.getElementById('fte_view');window.addEventListener('message',function handler(e){if(e.origin!==Common.COST_CONTROL_APP){return;}
|
||||
if(e.data.type==='fte_ready'){window.removeEventListener('message',handler);iframe.classList.remove('non-ready');window.performance.mark('navigationLoaded');window.performance.mark('navigationInteractive');window.performance.mark('visuallyLoaded');window.performance.mark('contentInteractive');window.performance.mark('fullyLoaded');}});iframe.src='/fte.html'+'#'+mode;},closeFTE:function(){var iframe=window.parent.document.getElementById('fte_view');iframe.classList.add('non-ready');iframe.src='';},startApp:function(){parent.postMessage({type:'fte_finished',data:''},Common.COST_CONTROL_APP);},closeApplication:function(){return setTimeout(function _close(){debug('Closing.');window.close();});},modalAlert:function(message){alert(message);},get localize(){return navigator.mozL10n.setAttributes;},getInterface:function getInterface(findFunction){if(!Common.allNetworkInterfaceLoaded){debug('Network interfaces are not ready yet');var header=_('data-usage');var msg=_('loading-interface-data');this.modalAlert(header+'\n'+msg);return;}
|
||||
if(Common.allNetworkInterfaces){return Common.allNetworkInterfaces.find(findFunction);}},getDataSIMInterface:function _getDataSIMInterface(iccId){if(!iccId){console.warn('Undefined icc identifier, unable get data interface');return;}
|
||||
if(iccId){var findCurrentInterface=function(networkInterface){if(networkInterface.id===iccId){return networkInterface;}};return this.getInterface(findCurrentInterface);}
|
||||
return undefined;},getWifiInterface:function _getWifiInterface(){var findWifiInterface=function(networkInterface){if(networkInterface.type===navigator.mozNetworkStats.WIFI){return networkInterface;}};return this.getInterface(findWifiInterface);},loadApps:function(){return new Promise(function(resolve,reject){if(Common.allAppsLoaded){resolve(Common.allApps);return;}
|
||||
var request=window.navigator.mozApps.mgmt.getAll();request.onsuccess=function(event){var appList=event.target.result;Common.allApps=appList.filter(function(app){return Common.specialApps.indexOf(app.manifestURL)===-1;});Common.allApps.push(Common.BROWSER_APP);Common.allAppsLoaded=true;resolve(Common.allApps);};request.onerror=function(){reject(new Error('Apps could not be loaded'));};});},loadNetworkInterfaces:function(onsuccess,onerror){var networks=navigator.mozNetworkStats.getAvailableNetworks();networks.onsuccess=function(){Common.allNetworkInterfaces=networks.result;Common.allNetworkInterfaceLoaded=true;if(onsuccess){onsuccess();}};networks.onerror=function(){console.error('Error when trying to load network interfaces');if(onerror){onerror();}};},getApp:function(manifestURL){return this.allApps.find(function(app){return app.manifestURL===manifestURL;});},getAppManifest:function(app){return app.manifest||app.updateManifest;},getLocalizedAppName:function(app){if(app.manifestURL===Common.SYSTEM_MANIFEST){return _('data-usage-other-apps');}
|
||||
if(app.manifestURL===Common.BROWSER_APP.manifestURL){return _('data-usage-browser-app');}
|
||||
var manifest=this.getAppManifest(app);var userLang=document.documentElement.lang;var locales=manifest.locales;var localized=locales&&locales[userLang]&&locales[userLang].name;return localized||manifest.name;},getAppIcon:function(app){var manifest=this.getAppManifest(app);var icons=manifest.icons;var defaultImage='../style/images/app/icons/default.png';if(!icons||!Object.keys(icons).length){return defaultImage;}
|
||||
var preferredIconSize=30*(window.devicePixelRatio||1);var preferredSize=Number.MAX_VALUE;var max=0;for(var size in icons){size=parseInt(size,10);if(size>max){max=size;}
|
||||
if(size>=preferredIconSize&&size<preferredSize){preferredSize=size;}}
|
||||
if(preferredSize===Number.MAX_VALUE){preferredSize=max;}
|
||||
var url=icons[preferredSize];if(url){return!(/^(http|https|data):/.test(url))?app.origin+url:url;}else{return defaultImage;}},getDataLimit:function _getDataLimit(settings){var multiplier=(settings.dataLimitUnit==='MB')?1000000:1000000000;return settings.dataLimitValue*multiplier;},resetData:function _resetData(mode,onsuccess,onerror){var wifiInterface=Common.getWifiInterface();var wifiClearRequest,mobileClearRequest;var getOnErrorFor=function(networkInterface){return function(){if(wifiClearRequest){wifiClearRequest.onerror=undefined;}
|
||||
if(mobileClearRequest){mobileClearRequest.onerror=undefined;}
|
||||
(typeof onerror==='function')&&onerror(networkInterface);};};if((mode==='all'||mode==='wifi')&&wifiInterface){wifiClearRequest=navigator.mozNetworkStats.clearStats(wifiInterface);wifiClearRequest.onerror=getOnErrorFor('wi-Fi');}
|
||||
if(mode==='all'||mode==='mobile'){SimManager.requestDataSimIcc(function(dataSim){var currentSimcardInterface=Common.getDataSIMInterface(dataSim.iccId);if(currentSimcardInterface){mobileClearRequest=navigator.mozNetworkStats.clearStats(currentSimcardInterface);mobileClearRequest.onerror=getOnErrorFor('simcard');mobileClearRequest.onsuccess=function _restoreDataLimitAlarm(){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){if(settings.dataLimit){addNetworkUsageAlarm(currentSimcardInterface,Common.getDataLimit(settings),function _addNetworkUsageAlarmOK(){ConfigManager.setOption({'dataUsageNotified':false});});}});};}});}
|
||||
if(mode==='all'){ConfigManager.setOption({lastCompleteDataReset:new Date()});}else{ConfigManager.setOption({lastDataReset:new Date()});}
|
||||
if(typeof onsuccess==='function'){onsuccess();}},resetAll:function _resetAll(callback){function logResetDataError(networkInterface){console.log('Error when trying to reset '+networkInterface+' interface');}
|
||||
Common.resetData('all',thenResetTelephony,logResetDataError);function thenResetTelephony(){resetTelephony(callback);}},updateNextReset:function _updateNextReset(trackingPeriod,value,callback){if(trackingPeriod==='never'){setNextReset(null,callback);return;}
|
||||
var nextReset,today=new Date();if(trackingPeriod==='monthly'){var month,year;var monthday=parseInt(value,10);month=today.getMonth();year=today.getFullYear();if(today.getDate()>=monthday){month=(month+1)%12;if(month===0){year++;}}
|
||||
nextReset=new Date(year,month,monthday);if(monthday!==nextReset.getDate()){var LAST_DAY_OF_PREVIOUS_MONTH=0;nextReset.setDate(LAST_DAY_OF_PREVIOUS_MONTH);}}else if(trackingPeriod==='weekly'){var oneDay=24*60*60*1000;var weekday=parseInt(value,10);var daysToTarget=weekday-today.getDay();if(daysToTarget<=0){daysToTarget=7+daysToTarget;}
|
||||
nextReset=new Date();nextReset.setTime(nextReset.getTime()+oneDay*daysToTarget);Toolkit.toMidnight(nextReset);}
|
||||
setNextReset(nextReset,callback);},localizeWeekdaySelector:function _localizeWeekdaySelector(selector){var weekStartsOnMonday=parseInt(navigator.mozL10n.get('firstDayOfTheWeek'),10)===1;debug('Week starts on monday?',weekStartsOnMonday);var monday=selector.querySelector('.monday');var sunday=selector.querySelector('.sunday');var list=monday.parentNode;if(weekStartsOnMonday){debug('Monday, Tuesday...');list.insertBefore(monday,list.childNodes[0]);list.appendChild(sunday);}else{debug('Sunday, Monday...');list.insertBefore(sunday,list.childNodes[0]);list.insertBefore(monday,sunday.nextSibling);}}};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
;'use strict';var ConfigManager=(function(){var today=new Date();var DEFAULT_SETTINGS={'dataLimit':false,'dataLimitValue':1,'dataLimitUnit':'GB','errors':{'INCORRECT_TOPUP_CODE':false,'BALANCE_TIMEOUT':false,'TOPUP_TIMEOUT':false},'fte':true,'waitingForBalance':null,'waitingForTopUp':null,'lastBalance':null,'lastBalanceRequest':null,'lastTopUpRequest':null,'lastDataUsage':{'timestamp':today,'start':today,'end':today,'today':today,'wifi':{'apps':{},'total':0},'mobile':{'apps':{},'total':0}},'lastTelephonyActivity':{'timestamp':today,'calltime':0,'smscount':0},'lastTelephonyReset':today,'lastDataReset':today,'lastCompleteDataReset':today,'lowLimit':false,'lowLimitThreshold':false,'lowLimitNotified':false,'zeroBalanceNotified':false,'dataUsageNotified':false,'nextReset':null,'plantype':'postpaid','resetTime':1,'trackingPeriod':'monthly','isMobileChartVisible':true,'isWifiChartVisible':false};var CONFIG_CACHE=[];function getApplicationMode(){if(noConfigFound){return'DATA_USAGE_ONLY';}
|
||||
return settings.plantype.toUpperCase();}
|
||||
var configuration,configurationIndex,noConfigFound=false;function setConfig(newConfiguration){configuration=newConfiguration;debug('Provider configuration done!');}
|
||||
function requestConfiguration(currentDataIcc,callback){if(!currentDataIcc||!currentDataIcc.iccInfo){console.error('No iccInfo available');return;}
|
||||
function returnConfiguration(){if(typeof callback==='function'){callback(configuration);}}
|
||||
if(configuration){setTimeout(function(){returnConfiguration();});return;}
|
||||
if(configurationIndex){loadConfiguration(currentDataIcc,returnConfiguration);}else{loadConfigurationIndex(function onIndex(){loadConfiguration(currentDataIcc,returnConfiguration);});}}
|
||||
function loadConfiguration(currentDataIcc,callback){var configFilePath=getConfigFilePath(currentDataIcc);if(CONFIG_CACHE[configFilePath]){ConfigManager.setConfig(CONFIG_CACHE[configFilePath]);(typeof callback==='function')&&callback();}else{LazyLoader.load(configFilePath,function(){CONFIG_CACHE[configFilePath]=configuration;(typeof callback==='function')&&callback();});}}
|
||||
function getConfigFilePath(currentDataIcc){noConfigFound=false;var mcc=currentDataIcc.iccInfo.mcc;var mnc=currentDataIcc.iccInfo.mnc;var key=mcc+'_'+mnc;var configDir=configurationIndex[key];if(!configDir){configDir='default';noConfigFound=true;}
|
||||
return'js/config/'+configDir+'/config.js';}
|
||||
function loadConfigurationIndex(callback){LazyLoader.getJSON('/js/config/index.json').then(function(json){configurationIndex=json;if(configurationIndex===null){console.error('Error loading the configuration index!'+'Response from LazyLoader was null.');configurationIndex={};}
|
||||
if(typeof callback==='function'){setTimeout(function(){callback();});}},function(error){console.error('Error loading the configuration index! '+'Error code: '+error);configurationIndex={};});}
|
||||
Date.prototype.toJSON=function(){return{'__date__':this.toISOString()};};function settingsReviver(k,v){if(v===null||typeof v!=='object'||!v.hasOwnProperty('__date__')){return v;}
|
||||
return new Date(v.__date__);}
|
||||
var NO_ICCID='NOICCID';var settings;function requestSettings(iccIdInfo,callback){var currentICCID=iccIdInfo||NO_ICCID;asyncStorage.getItem(currentICCID,function _wrapGetItem(localSettings){try{settings=JSON.parse(localSettings,settingsReviver);}catch(e){}
|
||||
if(settings===null){settings=deepCopy(DEFAULT_SETTINGS);debug('Storing default settings for ICCID:',currentICCID);asyncStorage.setItem(currentICCID,JSON.stringify(settings),callback&&callback.bind(null,settings));}else if(callback){callback(settings);}});}
|
||||
function requestAll(callback){SimManager.requestDataSimIcc(function(dataSimIcc){requestConfiguration(dataSimIcc.icc,function _afterConfig(configuration){requestSettings(dataSimIcc.iccId,function _afterSettings(settings){if(callback){callback(configuration,settings,dataSimIcc.iccId);}});});});}
|
||||
function dispatchOptionChange(name,value,oldValue,settings){var event=new CustomEvent('optionchange',{detail:{name:name,value:value,oldValue:oldValue,settings:settings}});window.dispatchEvent(event);debug('Event optionchange dispatched for',name);}
|
||||
function setOption(options,callback){SimManager.requestDataSimIcc(function(dataSimIcc){if(!settings){requestSettings(dataSimIcc.iccId,function _afterEnsuringSettings(){setOption(options,callback);});return;}
|
||||
var formerValue={};for(var name in options){if(options.hasOwnProperty(name)){formerValue[name]=settings[name];settings[name]=options[name];}}
|
||||
var currentICCID=dataSimIcc.iccId||NO_ICCID;asyncStorage.setItem(currentICCID,JSON.stringify(settings),function _onSet(){requestSettings(dataSimIcc.iccId,function _onSettings(settings){for(var name in options){if(options.hasOwnProperty(name)){dispatchOptionChange(name,settings[name],formerValue[name],settings);}}
|
||||
if(callback){callback();}});});});}
|
||||
function syncOption(name,value){var oldValue=settings[name];if(value===undefined){return oldValue;}
|
||||
var update={};update[name]=value;setOption(update);}
|
||||
var callbacks;function callCallbacks(evt){debug('Option',evt.detail.name,'has changed!');var callbackCollection=callbacks[evt.detail.name]||[];for(var i=0;i<callbackCollection.length;i++){var callback=callbackCollection[i];if(callback){callback(evt.detail.value,evt.detail.oldValue,evt.detail.name,evt.detail.settings);}}}
|
||||
function syncObserve(name,callback,avoidInitialCall){debug('Installing observer for',name);if(callbacks===undefined){callbacks={};window.addEventListener('storage',function _onSync(evt){if(evt.key==='sync'){var name=evt.newValue.split('#')[0];var oldValue=settings?settings[name]:undefined;debug('Synchronization request for',name,'received!');SimManager.requestDataSimIcc(function(dataSimIcc){requestSettings(dataSimIcc.iccId,function _onSettings(newSettings){settings=newSettings;dispatchOptionChange(name,settings[name],oldValue,settings);});});}});window.addEventListener('optionchange',callCallbacks);}
|
||||
if(callbacks[name]===undefined){callbacks[name]=[];}
|
||||
if(callbacks[name].indexOf(callback)<0){callbacks[name].push(callback);avoidInitialCall=avoidInitialCall||false;if(!avoidInitialCall&&callback){callback(settings[name],null,name,settings);}}}
|
||||
function syncRemoveObserver(name,callback){var callbackCollection=callbacks[name];if(!callbackCollection){return;}
|
||||
var index=callbackCollection.indexOf(callback);if(index>-1){callbackCollection.splice(index,1);}}
|
||||
function defaultValue(name){return deepCopy(DEFAULT_SETTINGS[name]);}
|
||||
return{getApplicationMode:getApplicationMode,setConfig:setConfig,requestAll:requestAll,requestSettings:requestSettings,setOption:setOption,defaultValue:defaultValue,option:syncOption,observe:syncObserve,removeObserver:syncRemoveObserver,get configuration(){return configuration;},supportCustomizeMode:false};}());
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/* global ConfigManager */
|
||||
'use strict';
|
||||
|
||||
ConfigManager.setConfig({});
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"724_6": "vivo",
|
||||
"724_10": "vivo",
|
||||
"724_11": "vivo",
|
||||
"724_23": "vivo",
|
||||
"732_123": "movistar_colombia",
|
||||
"748_07": "movistar_uruguay",
|
||||
"716_06": "movistar_peru"
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/* global ConfigManager */
|
||||
'use strict';
|
||||
|
||||
var MovistarColombiaConfig = {
|
||||
provider: 'Movistar',
|
||||
is_free: true,
|
||||
is_roaming_free: true,
|
||||
credit: { currency: '$' },
|
||||
balance: {
|
||||
destination: '611',
|
||||
text: 'SALDO,A',
|
||||
senders: ['612', '611'],
|
||||
regexp: 'Saldo total:\\$([0-9,]+)\\.([0-9]{2})',
|
||||
minimum_delay: 3 * 60 * 60 * 1000 // 3h
|
||||
},
|
||||
topup: {
|
||||
ussd_destination: '*611#'
|
||||
},
|
||||
default_low_limit_threshold: 2000
|
||||
};
|
||||
|
||||
ConfigManager.setConfig(MovistarColombiaConfig);
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/* global ConfigManager */
|
||||
'use strict';
|
||||
|
||||
var MovistarPeruConfig = {
|
||||
provider: 'Movistar',
|
||||
is_free: true,
|
||||
credit: { currency: 'S/.' },
|
||||
balance: {
|
||||
destination: '600',
|
||||
text: 'S',
|
||||
senders: ['515'],
|
||||
regexp: '([0-9,]+)\\.([0-9]{2})',
|
||||
zero_regexp: '(Usted no tiene saldo en sus cuentas)',
|
||||
minimum_delay: 3 * 60 * 60 * 1000 // 3h
|
||||
},
|
||||
default_low_limit_threshold: 1
|
||||
};
|
||||
|
||||
ConfigManager.setConfig(MovistarPeruConfig);
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/* global ConfigManager */
|
||||
'use strict';
|
||||
|
||||
var MovistarUruguayConfig = {
|
||||
provider: 'Movistar',
|
||||
is_free: true,
|
||||
is_roaming_free: true,
|
||||
credit: { currency: '$' },
|
||||
balance: {
|
||||
destination: '222',
|
||||
text: 'SALDO',
|
||||
senders: ['222'],
|
||||
regexp: 'Recarga \\$([0-9,]+)(?:\\.([0-9]+))?',
|
||||
zero_regexp: '(Su saldo actual es cero)',
|
||||
minimum_delay: 3 * 60 * 60 * 1000 // 3h
|
||||
},
|
||||
topup: {
|
||||
ussd_destination: '*222*1*1#'
|
||||
},
|
||||
default_low_limit_threshold: 0
|
||||
};
|
||||
|
||||
ConfigManager.setConfig(MovistarUruguayConfig);
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/* global Format, ConfigManager */
|
||||
|
||||
'use strict';
|
||||
|
||||
var VivoConfig = (function() {
|
||||
|
||||
var RESERVED = '0';
|
||||
var OPERATION_TYPE_REQUEST = '01';
|
||||
var OPERATION_CHECK_BALANCE = '0102';
|
||||
var MESSAGE_INIT_WIDTH = 32;
|
||||
|
||||
var THOUSANDS_PADDING = 4;
|
||||
var TENS_PADDING = 2;
|
||||
|
||||
function getDateTime() {
|
||||
var now = new Date();
|
||||
var date = [
|
||||
Format.padLeft(now.getUTCFullYear(), THOUSANDS_PADDING, '0'),
|
||||
Format.padLeft(now.getUTCMonth() + 1, TENS_PADDING, '0'),
|
||||
Format.padLeft(now.getUTCDate(), TENS_PADDING, '0')
|
||||
].join('');
|
||||
var time = [
|
||||
Format.padLeft(now.getUTCHours(), TENS_PADDING, '0'),
|
||||
Format.padLeft(now.getUTCMinutes(), TENS_PADDING, '0'),
|
||||
Format.padLeft(now.getUTCSeconds(), TENS_PADDING, '0')
|
||||
].join('');
|
||||
return [date, time];
|
||||
}
|
||||
|
||||
/*
|
||||
* VIVO request messages are formed by the concatenation of fixed length
|
||||
* fields:
|
||||
* - 32-length initial padding, all '0' (zero)
|
||||
* - 3-length system code. Currently only 'OWD' (FirefoOS) is supported
|
||||
* - 8-length date string in the form of YYYYMMDD
|
||||
* - 6-length time string in the form of HHMMSS
|
||||
* - 2-length operation type
|
||||
* - 1-length total number of SMS for the request
|
||||
* - 1-length number of the current SMS being transmitted (starting in 1)
|
||||
* - 1-length reserved character. It is '0'
|
||||
* - 4-length operation code
|
||||
*
|
||||
* Example of balance request (ignore blank spaces):
|
||||
* 00000000000000000000000000000000 OWD 20130530 132006 01 1 1 0 0102
|
||||
*
|
||||
* A request can include parameters in a last field of variable length from
|
||||
* 0 to 80 characters.
|
||||
*/
|
||||
function generateCheckBalanceMessage() {
|
||||
var messageInit = (new Array(MESSAGE_INIT_WIDTH + 1)).join('0');
|
||||
var systemCode = 'OWD';
|
||||
var dateTime = getDateTime();
|
||||
var date = dateTime[0];
|
||||
var time = dateTime[1];
|
||||
var operationType = OPERATION_TYPE_REQUEST;
|
||||
var totalMessageCount = '1';
|
||||
var currentMessageCount = '1';
|
||||
var requestedOperation = OPERATION_CHECK_BALANCE;
|
||||
|
||||
return [
|
||||
messageInit,
|
||||
systemCode,
|
||||
date,
|
||||
time,
|
||||
operationType,
|
||||
totalMessageCount,
|
||||
currentMessageCount,
|
||||
RESERVED,
|
||||
requestedOperation
|
||||
].join('');
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* A VIVO answer include specific fields from the related request in such
|
||||
* a way these fields form a unique ID to match each answer with its request.
|
||||
*
|
||||
* For example, compare this pair of request, response:
|
||||
* 00000000000000000000000000000000 OWD 20130530 132006 01 1 1 0 0102
|
||||
* 20130530 132006 01 1 1 0 0102 60.45
|
||||
*
|
||||
* Current value for the regexp used to validate a balance answer is not
|
||||
* checking the unique ID since this requires to store this ID and make it
|
||||
* to survive the application closes. Since access to configuration
|
||||
* properties must be synchronous, we should use some kind of synchronous
|
||||
* storage. As DOMStorage is discouraged and IndexedDB synchronous API is
|
||||
* not ready we can not currently implement this constrain.
|
||||
*/
|
||||
var balanceRegularExpression = [
|
||||
'^[0-9]{14}', // we admit any sequence of 14 numbers. See TODO above.
|
||||
OPERATION_TYPE_REQUEST,
|
||||
'1', '1',
|
||||
RESERVED,
|
||||
OPERATION_CHECK_BALANCE,
|
||||
'([0-9]+)\\.([0-9]{1,2})' // matches the remaining balance
|
||||
].join('');
|
||||
|
||||
return {
|
||||
provider: 'Vivo',
|
||||
is_free: true,
|
||||
is_roaming_free: true,
|
||||
credit: { currency: 'R$' },
|
||||
balance: {
|
||||
destination: '4850',
|
||||
get text() {
|
||||
return generateCheckBalanceMessage();
|
||||
},
|
||||
senders: ['4850'],
|
||||
regexp: balanceRegularExpression,
|
||||
minimum_delay: 3 * 60 * 60 * 1000 // 3h
|
||||
},
|
||||
topup: {
|
||||
destination: '7000',
|
||||
ussd_destination: '*321#',
|
||||
text: '&code',
|
||||
senders: ['1515', '7000'],
|
||||
confirmation_regexp:
|
||||
'Voce recarregou R\\$\\s*([0-9]+)(?:[,\\.]([0-9]+))?',
|
||||
incorrect_code_regexp:
|
||||
'(Favor enviar|envie novamente|Verifique) o codigo de recarga'
|
||||
},
|
||||
default_low_limit_threshold: 3
|
||||
};
|
||||
}());
|
||||
|
||||
ConfigManager.setConfig(VivoConfig);
|
||||
73
assets/webapps/costcontrol.gaiamobile.org/js/costcontrol.js
Normal file
73
assets/webapps/costcontrol.gaiamobile.org/js/costcontrol.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
;'use strict';var CostControl=(function(){var costcontrol;function getInstance(onready){debug('Initializing Cost Control');function goOn(){debug('Cost Control already ready!');onready(costcontrol);}
|
||||
if(costcontrol){if(SimManager.isMultiSim()){SimManager.requestDataSimIcc(function(dataSimIcc){if(costcontrol.iccId===dataSimIcc.iccId){goOn();}});}else{goOn();}
|
||||
return;}
|
||||
function setupCostControl(configuration,settings,iccId){costcontrol={iccId:iccId,request:request,lastDataResults:{},lastDataResultsPerApp:{},isBalanceRequestSMS:isBalanceRequestSMS};debug('Cost Control ready!');onready(costcontrol);}
|
||||
loadAPIs();ConfigManager.requestAll(setupCostControl);}
|
||||
var mobileMessageManager,statistics,isSendingBalanceRequest=false;function loadAPIs(){if('mozMobileMessage'in window.navigator){mobileMessageManager=window.navigator.mozMobileMessage;}
|
||||
if('mozNetworkStats'in window.navigator){statistics=window.navigator.mozNetworkStats;}
|
||||
debug('APIs loaded!');}
|
||||
function isBalanceRequestSMS(message,configuration){return message.receiver===configuration.balance.destination;}
|
||||
function request(requestObj,callback){ConfigManager.requestAll(function _onInfo(configuration,settings){debug('Request for:',requestObj.type);var force=requestObj.force;var result={};result.type=requestObj.type;function _requestDataStatistics(){SimManager.requestDataSimIcc(function(dataSim){requestDataStatistics(configuration,settings,callback,dataSim,result,requestObj);});}
|
||||
function _requestBalance(connection){var issues=getServiceIssues(configuration,settings,connection);var canBeIgnoredByForcing=(issues==='minimum_delay'&&force);if(issues&&!canBeIgnoredByForcing){result.status='error';result.details=issues;result.data=settings.lastBalance;if(callback){callback(result);}
|
||||
return;}
|
||||
var costIssues=getCostIssues(configuration,connection);if(!force&&costIssues){result.status='error';result.details=costIssues;result.data=settings.lastBalance;if(callback){callback(result);}
|
||||
return;}
|
||||
var isWaiting=settings.waitingForBalance!==null;var timeout=Toolkit.checkEnoughDelay(BALANCE_TIMEOUT,settings.lastBalanceRequest);if((isWaiting&&!timeout)||isSendingBalanceRequest){result.status='in_progress';result.data=settings.lastBalance;if(callback){callback(result);}
|
||||
return;}
|
||||
isSendingBalanceRequest=true;LazyLoader.load('js/iac_manager.js',function(){requestBalance(configuration,settings,callback,result);});}
|
||||
function _requestTopUp(connection){var issuesTopUp=getServiceIssues(configuration,settings,connection);if(issuesTopUp&&issuesTopUp!=='minimum_delay'){result.status='error';result.details=issuesTopUp;result.data=settings.lastDataUsage;if(callback){callback(result);}
|
||||
return;}
|
||||
var costIssuesTopUp=getCostIssues(configuration,connection);if(!force&&costIssuesTopUp){result.status='error';result.details=costIssuesTopUp;result.data=settings.lastBalance;if(callback){callback(result);}
|
||||
return;}
|
||||
var isWaitingTopUp=settings.waitingForTopUp!==null;var timeoutTopUp=Toolkit.checkEnoughDelay(BALANCE_TIMEOUT,settings.lastTopUpRequest);if(isWaitingTopUp&&!timeoutTopUp&&!force){result.status='in_progress';result.data=settings.lastDataUsage;if(callback){callback(result);}
|
||||
return;}
|
||||
var code=requestObj.data;LazyLoader.load('js/iac_manager.js',function(){requestTopUp(configuration,settings,code,callback,result);});}
|
||||
switch(requestObj.type){case'balance':SimManager.requestDataConnection(_requestBalance);break;case'topup':SimManager.requestDataConnection(_requestTopUp);break;case'datausage':if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(_requestDataStatistics,_requestDataStatistics);}else{_requestDataStatistics();}
|
||||
break;case'telephony':result.data=settings.lastTelephonyActivity;result.status='success';if(callback){callback(result);}
|
||||
break;}
|
||||
return;});}
|
||||
function getServiceIssues(configuration,settings,connection){if(!connection||!connection.data||!connection.voice||!connection.voice.connected){return'no_service';}
|
||||
var mode=ConfigManager.getApplicationMode();if(mode!=='PREPAID'){return'no_service';}
|
||||
if(connection.voice.relSignalStrength===null){return'no_coverage';}
|
||||
if(configuration.balance.minimum_delay){var isMinimumDelayHonored=Toolkit.checkEnoughDelay(configuration.balance.minimum_delay,settings.lastBalanceRequest);if(!isMinimumDelayHonored){return'minimum_delay';}}
|
||||
return'';}
|
||||
function getCostIssues(configuration,connection){var inRoaming=connection.voice.roaming;if(inRoaming&&configuration.is_roaming_free!==true){return'non_free_in_roaming';}
|
||||
if(!inRoaming&&configuration.is_free!==true){return'non_free';}
|
||||
return'';}
|
||||
var BALANCE_TIMEOUT=5*60*1000;function requestBalance(configuration,settings,callback,result){debug('Requesting balance...');result.data=settings.lastBalance;function sendSMS(){debug('After IAC broadcast ask for starting - balance');var newSMS=mobileMessageManager.send(configuration.balance.destination,configuration.balance.text);newSMS.onsuccess=function _onSuccess(){debug('Request SMS sent! Waiting for response.');if(!DEBUGGING){mobileMessageManager.delete(newSMS.result.id);}
|
||||
var newAlarm=addAlarmTimeout('balanceTimeout',BALANCE_TIMEOUT);newAlarm.onsuccess=function _alarmSet(evt){var id=evt.target.result;debug('Timeout for balance (',id,') update set to:',BALANCE_TIMEOUT);ConfigManager.setOption({'waitingForBalance':id,'lastBalanceRequest':new Date()},function _onSet(){isSendingBalanceRequest=false;result.status='success';if(callback){callback(result);}});};newAlarm.onerror=function _alarmFailedToSet(evt){ConfigManager.setOption({'lastBalanceRequest':new Date()},function _onSet(){isSendingBalanceRequest=false;debug('Failed to set timeout for balance request!');result.status='error';result.details='timeout_fail';if(callback){callback(result);}});};};newSMS.onerror=function _onError(){isSendingBalanceRequest=false;debug('Request SMS failed! But returning stored balance.');IACManager.broadcastEndOfSMSQuery('balance').then(function(msg){debug('After IAC broadcast ask for ending - balance');});result.status='error';result.details='request_fail';if(callback){callback(result);}};debug('Balance out of date. Requesting fresh data...');}
|
||||
IACManager.init(configuration);IACManager.broadcastStartOfSMSQuery('balance').then(sendSMS,sendSMS);}
|
||||
var TOPUP_TIMEOUT=5*60*1000;function requestTopUp(configuration,settings,code,callback,result){debug('Requesting TopUp with code',code,'...');function sendSMS(){debug('After IAC broadcast ask for starting - topup');var newSMS=mobileMessageManager.send(configuration.topup.destination,configuration.topup.text.replace(/\&code/g,code));newSMS.onsuccess=function _onSuccess(){debug('TopUp SMS sent! Waiting for response.');if(!DEBUGGING){mobileMessageManager.delete(newSMS.result.id);}
|
||||
var newAlarm=addAlarmTimeout('topupTimeout',TOPUP_TIMEOUT);newAlarm.onsuccess=function _alarmSet(evt){var id=evt.target.result;debug('Timeout for TopUp (',id,') update set to:',TOPUP_TIMEOUT);ConfigManager.setOption({'waitingForTopUp':id,'lastTopUpRequest':new Date()},function _onSet(){result.status='success';if(callback){callback(result);}});};newAlarm.onerror=function _alarmFailedToSet(evt){debug('Failed to set timeout for TopUp request!');result.status='error';result.details='timeout_fail';if(callback){callback(result);}};};newSMS.onerror=function _onError(){debug('TopUp SMS failed!');IACManager.broadcastEndOfSMSQuery('topup').then(function(msg){debug('After IAC broadcast ask for ending - topup');});result.status='error';result.details='request_fail';if(callback){callback(result);}};}
|
||||
IACManager.init(configuration);IACManager.broadcastStartOfSMSQuery('topup').then(sendSMS,sendSMS);}
|
||||
var DAY=24*3600*1000;function requestDataStatistics(configuration,settings,callback,dataSimIcc,result,requestParameters){debug('Statistics out of date. Requesting fresh data...');var apps=requestParameters&&requestParameters.apps;var start=requestParameters&&requestParameters.startDate;var end=requestParameters&&requestParameters.endDate;if(!start){var maxAge=1000*statistics.maxStorageAge;var minimumStart=new Date(Date.now()-maxAge);debug('The max age for samples is '+minimumStart);start=new Date(settings.lastCompleteDataReset||Date.now()-7*DAY);if(start<minimumStart){console.warn('Start date is surpassing the maximum age for the '+'samples. Setting to '+minimumStart);start=minimumStart;}}
|
||||
start=Toolkit.toMidnight(start);if(!end){var today=Toolkit.toMidnight(new Date());var tomorrow=new Date();tomorrow.setTime(today.getTime()+DAY);end=Toolkit.toMidnight(settings.nextReset?new Date(settings.nextReset.getTime()-DAY):tomorrow);}
|
||||
if(start>end){console.error('Start date is higher than end date. This must not '+'happen. Changed end date to day after startDate');end=new Date(start.getTime()+DAY);}
|
||||
var wifiInterface=Common.getWifiInterface();var currentSimcardNetwork=Common.getDataSIMInterface(dataSimIcc.iccId);var wifiRequests,simRequests;var pendingRequests=0;function checkForCompletion(){pendingRequests--;if(pendingRequests===0){updateDataUsage();}}
|
||||
function updateDataUsage(){var lastDataUsage={timestamp:new Date(),start:start,end:end,today:today,wifi:{apps:{},total:0,samples:[]},mobile:{apps:{},total:0,samples:[]}};function saveLastDataUsage(perApp){var savedUsage={};Object.keys(lastDataUsage).forEach(function(key){var value=lastDataUsage[key];if(key==='wifi'||key==='mobile'){if(perApp){value=settings.lastDataUsage[key];}
|
||||
savedUsage[key]={apps:{},total:value.total};Object.keys(value.apps).forEach(function(manifest){savedUsage[key].apps[manifest]={total:value.apps[manifest].total};});}else{savedUsage[key]=value;}});ConfigManager.setOption({'lastDataUsage':savedUsage},function _onSetItem(){debug('Statistics up to date and stored.');});}
|
||||
function aggregateSamples(network){if(!network.apps){return;}
|
||||
var manifestURLs=Object.keys(network.apps);if(manifestURLs.length===0){return;}
|
||||
var samplesByDate={};var today=Toolkit.toMidnight(new Date());var offset=today.getTimezoneOffset()*60*1000;manifestURLs.forEach(function(manifestURL){var samples=network.apps[manifestURL].samples;samples.forEach(function(sample){if(sample.date&&sample.date.__date__){sample.date=new Date(sample.date.__date__);}
|
||||
var sampleLocalTime=sample.date.getTime()+offset;var sampleUTCDate=Toolkit.toMidnight(new Date(sampleLocalTime));var aggregateSample=samplesByDate[sampleUTCDate.getTime()];if(!aggregateSample){aggregateSample=samplesByDate[sampleUTCDate.getTime()]={value:0,date:sample.date};}
|
||||
aggregateSample.value+=sample.value;});});var dates=Object.keys(samplesByDate);network.samples=dates.map(function(date){return samplesByDate[date];});network.samples.sort(function(a,b){return a.date.getTime()-b.date.getTime();});}
|
||||
function handleResult(request,network){var result=request.result;var data=adaptData(result);var manifestURL=request.result.appManifestURL;if(manifestURL&&manifestURL!=='null'){var isBrowser=request.result.browsingTrafficOnly&&manifestURL===Common.SYSTEM_MANIFEST;if(isBrowser){manifestURL=Common.BROWSER_APP.manifestURL;}
|
||||
network.apps[manifestURL]={samples:data[0],total:data[1]};}else{network.samples=network.samples.concat(data[0]);}
|
||||
network.total+=data[1];}
|
||||
if(simRequests){simRequests.forEach(function(request){handleResult(request,lastDataUsage.mobile);});aggregateSamples(lastDataUsage.mobile);}
|
||||
if(wifiRequests){wifiRequests.forEach(function(request){handleResult(request,lastDataUsage.wifi);});aggregateSamples(lastDataUsage.wifi);}
|
||||
var perApp=apps&&apps.length>0;saveLastDataUsage(perApp);result.status='success';result.data=lastDataUsage;if(perApp){costcontrol.lastDataResultsPerApp=lastDataUsage;}else{costcontrol.lastDataResults=lastDataUsage;}
|
||||
debug('Returning up to date statistics.');if(callback){callback(result);}}
|
||||
function requestPerAppUsage(networkId){function requestSamples(options){pendingRequests++;var req=statistics.getSamples(networkId,start,end,options);req.onsuccess=checkForCompletion;return req;}
|
||||
var requests;if(apps&&apps.length>0){requests=[];apps.forEach(function(manifestURL){if(manifestURL!==Common.SYSTEM_MANIFEST){var options={appManifestURL:manifestURL};if(manifestURL===Common.BROWSER_APP.manifestURL){options.appManifestURL=Common.SYSTEM_MANIFEST;options.browsingTrafficOnly=true;}
|
||||
requests.push(requestSamples(options));}});}else{requests=[requestSamples()];}
|
||||
return requests;}
|
||||
if(currentSimcardNetwork){simRequests=requestPerAppUsage(currentSimcardNetwork);}
|
||||
if(wifiInterface){wifiRequests=requestPerAppUsage(wifiInterface);}
|
||||
if(pendingRequests===0){updateDataUsage();}}
|
||||
function adaptData(networkStatsResult){var data=networkStatsResult.data;var output=[];var totalData,accum=0;for(var i=0;i<data.length;i++){var item=data[i];if(item.txBytes===undefined){output.push({date:item.date});continue;}
|
||||
totalData=0;if(item.rxBytes){totalData+=item.rxBytes;}
|
||||
if(item.txBytes){totalData+=item.txBytes;}
|
||||
accum+=totalData;output.push({value:totalData,date:item.date});}
|
||||
return[output,accum];}
|
||||
return{getInstance:getInstance,reset:function _onReset(){costcontrol=null;}};}());
|
||||
19
assets/webapps/costcontrol.gaiamobile.org/js/fte.js
Normal file
19
assets/webapps/costcontrol.gaiamobile.org/js/fte.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
;(function(){'use strict';var DEFAULT_LOW_LIMIT_THRESHOLD=3;var defaultLowLimitThreshold=DEFAULT_LOW_LIMIT_THRESHOLD;window.addEventListener('DOMContentLoaded',function _onDomReady(){initLazyFTE();});function initLazyFTE(){var SCRIPTS_NEEDED=['js/utils/debug.js','js/utils/toolkit.js','js/sim_manager.js','js/common.js','js/config/config_manager.js','js/views/BalanceLowLimitView.js','js/view_manager.js','js/settings/autosettings.js'];LazyLoader.load(SCRIPTS_NEEDED,function onScriptsLoaded(){setupFTE();parent.postMessage({type:'fte_ready',data:''},Common.COST_CONTROL_APP);window.addEventListener('localized',_onLocalize);});}
|
||||
var wizard,vmanager;var toStep2,step=0;function setupFTE(){if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',function _onDataSimChange(){window.removeEventListener('dataSlotChange',_onDataSimChange);Common.closeFTE();});}
|
||||
ConfigManager.requestAll(function _onSettings(configuration,settings){wizard=document.getElementById('firsttime-view');vmanager=new ViewManager();if(configuration&&configuration.default_low_limit_threshold){defaultLowLimitThreshold=configuration.default_low_limit_threshold;}
|
||||
ConfigManager.setOption({resetTime:1,trackingPeriod:'monthly'});var mode=ConfigManager.getApplicationMode();var SCRIPTS_NEEDED=['js/settings/limitdialog.js','js/utils/formatting.js'];LazyLoader.load(SCRIPTS_NEEDED,function onScriptsLoaded(){Common.loadNetworkInterfaces(function(){AutoSettings.addType('data-limit',dataLimitConfigurer);if(mode==='DATA_USAGE_ONLY'){AutoSettings.initialize(ConfigManager,vmanager,'#non-vivo-step-2');}});});if(configuration&&configuration.credit&&configuration.credit.currency){document.getElementById('currency').textContent=configuration.credit.currency;}
|
||||
if(mode==='DATA_USAGE_ONLY'){debug('FTE for non supported SIM');wizard.dataset.steps='3';reset(['step-1','non-vivo-step-1','non-vivo-step-2']);AutoSettings.initialize(ConfigManager,vmanager,'#non-vivo-step-1');}else{wizard.dataset.steps='4';reset(['step-1','step-2']);AutoSettings.initialize(ConfigManager,vmanager,'#step-1');toStep2=document.getElementById('to-step-2');toStep2.disabled=true;document.getElementById('prepaid-plan').addEventListener('click',selectTrack);document.getElementById('postpaid-plan').addEventListener('click',selectTrack);addLowLimitStepConstrains();}
|
||||
var next=document.querySelectorAll('[data-navigation=next]');[].forEach.call(next,function cc_eachNext(nextButton){nextButton.addEventListener('click',onNext);});var prev=document.querySelectorAll('[data-navigation=back]');[].forEach.call(prev,function cc_eachPrev(prevButton){prevButton.addEventListener('click',onBack);});var finish=document.querySelectorAll('[data-navigation=finish]');[].forEach.call(finish,function cc_eachFinish(finishButton){finishButton.addEventListener('click',onFinish);});LazyLoader.load(['js/costcontrol.js'],function(){var messageHandlerFrame=document.getElementById('message-handler');messageHandlerFrame.src='message_handler.html';});});}
|
||||
function _onLocalize(){Common.localizeWeekdaySelector(document.getElementById('pre3-select-weekday'));Common.localizeWeekdaySelector(document.getElementById('post2-select-weekday'));Common.localizeWeekdaySelector(document.getElementById('non2-select-weekday'));function _setResetTimeToDefault(evt){var today=new Date();var defaultResetTime=(evt.target.value==='weekly')?today.getDay():today.getDate();ConfigManager.setOption({resetTime:defaultResetTime});}
|
||||
var trackingPeriodSelector=document.querySelectorAll('[data-option="trackingPeriod"]');[].forEach.call(trackingPeriodSelector,function _reset(tPeriodSel){tPeriodSel.addEventListener('change',_setResetTimeToDefault);});}
|
||||
if(window.location.hash){wizard=document.getElementById('firsttime-view');if(window.location.hash==='#PREPAID'||window.location.hash==='#POSTPAID'){wizard.querySelector('.authed-sim').hidden=false;}else{wizard.querySelector('.nonauthed-sim').hidden=false;}}
|
||||
var currentTrack=['step-1','step-2'];function selectTrack(evt){if(evt.target.value==='prepaid'){currentTrack=['step-1','step-2','prepaid-step-2','prepaid-step-3'];AutoSettings.initialize(ConfigManager,vmanager,'#prepaid-step-2');AutoSettings.initialize(ConfigManager,vmanager,'#prepaid-step-3');balanceLowLimitView.disabled=false;ConfigManager.setOption({dataLimitValue:40,dataLimitUnit:'MB',lowLimit:true,lowLimitThreshold:defaultLowLimitThreshold});}else if(evt.target.value==='postpaid'){currentTrack=['step-1','step-2','postpaid-step-2','postpaid-step-3'];AutoSettings.initialize(ConfigManager,vmanager,'#postpaid-step-2');AutoSettings.initialize(ConfigManager,vmanager,'#postpaid-step-3');balanceLowLimitView.disabled=true;ConfigManager.setOption({dataLimitValue:2,dataLimitUnit:'GB'});}
|
||||
ConfigManager.setOption({plantype:evt.target.value},function _onSet(){toStep2.disabled=false;});}
|
||||
function reset(track){var currentScreen=document.getElementById(currentTrack[step]);var newStartScreen=document.getElementById(track[0]);currentScreen.dataset.viewport='left';newStartScreen.dataset.viewport='right';delete newStartScreen.dataset.viewport;for(var i=1;i<track.length;i+=1){var id=track[i];if(id){var screen=document.getElementById(id);screen.dataset.viewport='right';}}
|
||||
step=0;currentTrack=track;}
|
||||
function onNext(){if(step===currentTrack.length-1){return;}
|
||||
var currentId=currentTrack[step];var currentScreen=document.getElementById(currentId);var nextScreenId=currentTrack[step+1];var nextScreen=document.getElementById(nextScreenId);delete nextScreen.dataset.viewport;currentScreen.dataset.viewport='left';step+=1;if(step===2){balanceLowLimitView&&balanceLowLimitView.validate();}}
|
||||
function onBack(){if(step===0){return;}
|
||||
var currentId=currentTrack[step];var currentScreen=document.getElementById(currentId);var prevScreenId=currentTrack[step-1];var prevScreen=document.getElementById(prevScreenId);delete prevScreen.dataset.viewport;currentScreen.dataset.viewport='right';step-=1;}
|
||||
function onFinish(evt){evt.target.disabled=true;SimManager.requestDataSimIcc(function(dataSim){ConfigManager.requestSettings(dataSim.iccId,function _onSettings(settings){ConfigManager.setOption({fte:false},function _returnToApp(){Common.updateNextReset(settings.trackingPeriod,settings.resetTime,function _returnToTheApplication(){Common.startApp();});});});});}
|
||||
var balanceLowLimitView;function addLowLimitStepConstrains(){var nextButton=document.getElementById('low-limit-next-button');balanceLowLimitView=new BalanceLowLimitView(document.getElementById('low-limit'),document.getElementById('low-limit-input'));balanceLowLimitView.onvalidation=function(evt){nextButton.disabled=!evt.isValid;};}}());
|
||||
90
assets/webapps/costcontrol.gaiamobile.org/js/iac_manager.js
Normal file
90
assets/webapps/costcontrol.gaiamobile.org/js/iac_manager.js
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/* global debug, Promise */
|
||||
/* exported IACManager */
|
||||
'use strict';
|
||||
|
||||
var IACManager = (function() {
|
||||
var TIMEOUT = 60 * 1000; // 1 minute
|
||||
var configuration;
|
||||
|
||||
function init(cfg) {
|
||||
configuration = cfg;
|
||||
}
|
||||
|
||||
function broadcastStartOfSMSQuery(type) {
|
||||
return IACManager._sendBroadcastMessage(_generateMsg(type, 'enable'));
|
||||
}
|
||||
|
||||
function broadcastEndOfSMSQuery(type) {
|
||||
return IACManager._sendBroadcastMessage(_generateMsg(type, 'disable'));
|
||||
}
|
||||
|
||||
function _sendBroadcastMessage(msg) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
navigator.mozApps.getSelf().onsuccess = function(evt) {
|
||||
var app = evt.target.result;
|
||||
app.connect('costcontrolSmsQuery').then(function onConnAccepted(ports) {
|
||||
debug('Connection with sms app established...');
|
||||
ports.forEach(function(port) {
|
||||
var waitingForAnswerTimeout;
|
||||
|
||||
port.onmessage = function() {
|
||||
clearTimeout(waitingForAnswerTimeout);
|
||||
resolve();
|
||||
};
|
||||
// if no one has replied the message in one minute, the proposal
|
||||
// will be rejected
|
||||
waitingForAnswerTimeout = window.setTimeout(function() {
|
||||
var errorMsg = 'Rejection by Timeout. No received answer to ' +
|
||||
msg.action + ' ' + msg.type + ' request.';
|
||||
reject(errorMsg);
|
||||
}, TIMEOUT);
|
||||
|
||||
port.postMessage(msg);
|
||||
});
|
||||
}, function onConnRejected(reason) {
|
||||
console.log('Rejected connection attempt due to', reason);
|
||||
reject(reason);
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function _getSmsNumberList(service) {
|
||||
var silentSmsList = [];
|
||||
if (configuration && configuration[service]) {
|
||||
silentSmsList = configuration[service].senders;
|
||||
if (silentSmsList.indexOf(configuration[service].destination) === -1) {
|
||||
silentSmsList.push(configuration[service].destination);
|
||||
}
|
||||
}
|
||||
return silentSmsList;
|
||||
}
|
||||
|
||||
function _reset() {
|
||||
configuration = null;
|
||||
}
|
||||
|
||||
function _generateMsg(service, action) {
|
||||
var outgoingNumber = configuration[service] &&
|
||||
configuration[service].destination;
|
||||
var incomingNumbers = configuration[service] &&
|
||||
configuration[service].senders;
|
||||
return {
|
||||
action: action,
|
||||
type: service,
|
||||
smsNumbers: _getSmsNumberList(service),
|
||||
outgoingNumber: outgoingNumber,
|
||||
incomingNumbers: incomingNumbers
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
broadcastStartOfSMSQuery: broadcastStartOfSMSQuery,
|
||||
broadcastEndOfSMSQuery: broadcastEndOfSMSQuery,
|
||||
_getSmsNumberList: _getSmsNumberList,
|
||||
_generateMsg: _generateMsg,
|
||||
_sendBroadcastMessage: _sendBroadcastMessage,
|
||||
_reset: _reset
|
||||
};
|
||||
}());
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
;(function(){'use strict';function inStandAloneMode(){return window.parent.location.pathname==='/message_handler.html';}
|
||||
if(!inStandAloneMode()){ConfigManager=window.parent.ConfigManager;CostControl=window.parent.CostControl;SimManager=window.parent.SimManager;}
|
||||
if(inStandAloneMode()&&window.history.length>1){debug('Nothing to do in message handler, returning to app...');window.history.back();}
|
||||
function inApplicationMode(){return window.parent.location.pathname==='/index.html';}
|
||||
var closing;function closeIfProceeds(){debug('Checking for closing...');if(inStandAloneMode()){closing=Common.closeApplication();}}
|
||||
function addAlarmTimeout(type,delay){var date=new Date();date.setTime(date.getTime()+delay);var request=navigator.mozAlarms.add(date,'ignoreTimezone',{type:type});return request;}
|
||||
window.addAlarmTimeout=addAlarmTimeout;function setNextReset(when,callback){asyncStorage.getItem('nextResetAlarm',function(id){debug('Current nextResetAlarm',id+'.',id?'Removing.':'');if(id){navigator.mozAlarms.remove(id);}
|
||||
if(!when){debug('Automatic reset disabled');updateResetAttributes(null,null,callback);return;}
|
||||
if(when.getTime()<Date.now()){debug('Faking a past reset alarm');_onAlarm({data:{type:'nextReset'}});if(callback){setTimeout(callback);}
|
||||
return;}
|
||||
var alarms=navigator.mozAlarms;var request=alarms.add(when,'ignoreTimezone',{type:'nextReset'});request.onsuccess=function _onSuccess(){debug('Setting nextResetAlarm',request.result,'to',when);updateResetAttributes(request.result,when,callback);};});}
|
||||
window.setNextReset=setNextReset;function getTopUpTimeout(callback){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var request=navigator.mozAlarms.getAll();request.onsuccess=function(e){var alarms=e.target.result;var length=alarms.length;if(!length){callback(null);return;}
|
||||
var refId=settings.waitingForTopUp;var index=0,alarm,found=false;while(index<length&&!found){alarm=alarms[index];found=(alarm.id===refId);index++;}
|
||||
if(found){debug('TopUp timeout found:',alarm.date);callback(alarm.date);}else{callback(null);}};});});}
|
||||
window.getTopUpTimeout=getTopUpTimeout;function addNetworkUsageAlarm(dataInterface,dataLimit,onsuccess,onerror){onsuccess=onsuccess||function(){};onerror=onerror||function(){};NetworkUsageAlarm.updateAlarm(dataInterface,dataLimit,onsuccess,onerror);}
|
||||
window.addNetworkUsageAlarm=addNetworkUsageAlarm;function updateResetAttributes(alarmId,date,callback){asyncStorage.setItem('nextResetAlarm',alarmId,function _updateOption(){ConfigManager.setOption({nextReset:date},function _sync(){localStorage.sync='nextReset#'+Math.random();if(callback){callback();}});});}
|
||||
function sendIncorrectTopUpNotification(callback){var title='topup-incorrectcode-title2';var message='topup-incorrectcode-message3';sendNotification('topUpError',title,message);if(callback){callback();}}
|
||||
function sendBalanceThresholdNotification(remaining,settings,callback){debug('Low limit already notified:',settings.lowLimitNotified);debug('Zero balance already notified:',settings.lowLimitNotified);var type;if(remaining.balance===0&&!settings.zeroBalanceNotified){type='zeroBalance';}else if(settings.lowLimit&&remaining.balance<settings.lowLimitThreshold&&!settings.lowLimitNotified){type='lowBalance';}else if(callback){setTimeout(callback);return;}
|
||||
debug('Notification type:',type);var remainingBalance=_('currency',{currency:remaining.currency,value:remaining.balance});var title='low-balance-notification-title';var message={id:'low-balance-notification-text',args:{remaining:remainingBalance}};if(type==='zeroBalance'){title='usage';message='zero-balance-message';}
|
||||
sendNotification(type,title,message);var update={};var notified=(type==='lowBalance')?'lowLimitNotified':'zeroBalanceNotified';update[notified]=true;ConfigManager.setOption(update,callback);}
|
||||
window.sendBalanceThresholdNotification=sendBalanceThresholdNotification;function _onAlarm(alarm){clearTimeout(closing);SimManager.requestDataSimIcc(function(dataSimIcc){function _launchNextReset(){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){Common.resetAll(function updateNextResetAndClose(){Common.updateNextReset(settings.trackingPeriod,settings.resetTime,closeIfProceeds);});});}
|
||||
switch(alarm.data.type){case'balanceTimeout':ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.errors.BALANCE_TIMEOUT=true;ConfigManager.setOption({'errors':settings.errors,'waitingForBalance':null},function _onBalanceTimeout(){debug('Timeout for balance');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();closeIfProceeds();});});break;case'topupTimeout':ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.errors.TOPUP_TIMEOUT=true;ConfigManager.setOption({'errors':settings.errors,'waitingForTopUp':null},function _onBalanceTimeout(){debug('Timeout for topup');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();closeIfProceeds();});});break;case'nextReset':if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(_launchNextReset);}else{_launchNextReset();}
|
||||
break;}});}
|
||||
function getNofificationAction(type,app){var activityName,action;var noop=function(){};switch(type){case'lowBalance':case'zeroBalance':activityName='costcontrol/balance';action=function(){if(window.parent.BalanceTab){window.parent.CostControlApp.showBalanceTab();}};break;case'topUpError':activityName='costcontrol/balance';action=function(){if(window.parent.BalanceTab){window.parent.BalanceTab.topUpWithCode(true);}};break;default:activityName='costcontrol/data_usage';action=function(){if(window.parent.CostControlApp){window.parent.CostControlApp.showDataUsageTab();}};break;}
|
||||
if(!inStandAloneMode()){return function(){if(inApplicationMode()){app.launch();action&&action();}else{type=new MozActivity({name:activityName});}};}
|
||||
return noop;}
|
||||
function sendNotification(notificationType,title,message){navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){var app=evt.target.result;var iconURL=NotificationHelper.getIconURI(app);var navigate=getNofificationAction(notificationType,app);NotificationHelper.send(title,{'bodyL10n':message,'icon':iconURL,'data':notificationType}).then(function(notification){notification.addEventListener('click',function(){notification.close();navigate();});});};}
|
||||
function _onNetworkAlarm(alarm){clearTimeout(closing);navigator.mozApps.getSelf().onsuccess=function _onAppReady(evt){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var limit=Common.getDataLimit(settings);var limitText=Formatting.formatData(Formatting.smartRound(limit));var title={id:'data-limit-notification-title2',args:{limit:limitText}};var message='data-limit-notification-text2';sendNotification('dataUsage',title,message);ConfigManager.setOption({'dataUsageNotified':true},closeIfProceeds);return;});});};}
|
||||
function disableSilentModeFor(type,configuration){LazyLoader.load('js/iac_manager.js',function(){IACManager.init(configuration);IACManager.broadcastEndOfSMSQuery(type).then(function(msg){debug('After broadcasting for '+type+' (disabling)');});});}
|
||||
var costcontrol;function _getCCInstance(){CostControl.getInstance(function _onCostControl(ccontrol){costcontrol=ccontrol;if(inStandAloneMode()||inApplicationMode()){debug('Installing handlers');navigator.mozSetMessageHandler('sms-received',function _onSMS(sms){clearTimeout(closing);ConfigManager.requestAll(function _onInfo(configuration,settings){var isBalanceResponse=configuration.balance&&Array.isArray(configuration.balance.senders)&&configuration.balance.senders.indexOf(sms.sender)>-1;var isTopupResponse=configuration.topup&&Array.isArray(configuration.topup.senders)&&configuration.topup.senders.indexOf(sms.sender)>-1;if(!isBalanceResponse&&!isTopupResponse){closeIfProceeds();return;}
|
||||
debug('Parsing received SMS');var isBalance,isConfirmation,isError;isBalance=isConfirmation=isError=false;debug('Trying to recognize balance SMS');var description=new RegExp(configuration.balance.regexp);var balanceData=sms.body.match(description);if(!balanceData){debug('Trying to recognize zero balance SMS');var zeroDescription=configuration.balance.zero_regexp?new RegExp(configuration.balance.zero_regexp):null;if(zeroDescription&&zeroDescription.test(sms.body)){balanceData=['0.00','0','0'];}}
|
||||
isBalance=!!balanceData;if(!isBalance||balanceData.length<2){console.warn('Impossible to parse balance message.');debug('Trying to recognize TopUp confirmation SMS');description=new RegExp(configuration.topup.confirmation_regexp);isConfirmation=!!sms.body.match(description);if(!isConfirmation){console.warn('Impossible to parse TopUp confirmation message.');debug('Trying to recognize TopUp error SMS');description=new RegExp(configuration.topup.incorrect_code_regexp);isError=!!sms.body.match(description);if(!isError){console.warn('Impossible to parse TopUp confirmation msg.');}}}
|
||||
if(!isBalance&&!isConfirmation&&!isError){closeIfProceeds();return;}
|
||||
if(!DEBUGGING&&(isBalance&&(settings.waitingForBalance!==null))||(isConfirmation&&(settings.waitingForTopUp!==null))){var mobileMessageManager=window.navigator.mozMobileMessage;mobileMessageManager.delete(sms.id);}
|
||||
if(isBalance){var integer=balanceData[1].replace(/[^0-9]/g,'');var decimal=balanceData[2]||'0';var newBalance={balance:parseFloat(integer+'.'+decimal),currency:configuration.credit.currency,timestamp:new Date()};if(settings.waitingForBalance!==null){navigator.mozAlarms.remove(settings.waitingForBalance);debug('Balance timeout:',settings.waitingForBalance,'removed');disableSilentModeFor('balance',configuration);}
|
||||
ConfigManager.setOption({'lastBalance':newBalance,'waitingForBalance':null},function _onSet(){debug('Balance up to date and stored');debug('Trying to synchronize!');localStorage.sync='lastBalance#'+Math.random();sendBalanceThresholdNotification(newBalance,settings,closeIfProceeds);});}else if(isConfirmation){if(settings.waitingForTopUp!==null){navigator.mozAlarms.remove(settings.waitingForTopUp);debug('TopUp timeout:',settings.waitingForTopUp,'removed');disableSilentModeFor('topup',configuration);}
|
||||
ConfigManager.setOption({'waitingForTopUp':null,'lowLimitNotified':false,'zeroBalanceNotified':false},function _onSet(){debug('TopUp confirmed!');debug('Trying to synchronize!');localStorage.sync='waitingForTopUp#'+Math.random();closeIfProceeds();});}else if(isError){settings.errors.INCORRECT_TOPUP_CODE=true;navigator.mozAlarms.remove(settings.waitingForTopUp);debug('TopUp timeout: ',settings.waitingForTopUp,'removed');ConfigManager.setOption({'errors':settings.errors,'waitingForTopUp':null,'lowLimitNotified':false,'zeroBalanceNotified':false},function _onSet(){debug('Balance up to date and stored');debug('Trying to synchronize!');localStorage.sync='errors#'+Math.random();sendIncorrectTopUpNotification(closeIfProceeds);});}});});navigator.mozSetMessageHandler('networkstats-alarm',_onNetworkAlarm);navigator.mozSetMessageHandler('alarm',_onAlarm);navigator.mozSetMessageHandler('sms-sent',function _onSent(sms){clearTimeout(closing);debug('SMS sent!');var configuration=ConfigManager.configuration;var mode=ConfigManager.getApplicationMode();if(mode==='PREPAID'&&!costcontrol.isBalanceRequestSMS(sms,configuration)){costcontrol.request({type:'balance'});}
|
||||
if(mode==='PREPAID'&&costcontrol.isBalanceRequestSMS(sms,configuration)){closeIfProceeds();}else{var mobileMessageManager=window.navigator.mozMobileMessage;var infoRequest=mobileMessageManager.getSegmentInfoForText(sms.body);infoRequest.onsuccess=function onInfo(evt){var realCount,smsInfo=evt.target.result;if(!smsInfo||!smsInfo.segments){console.error('Invalid getSegmentInfoForText() result. Counting 1 segment');realCount=1;}else{realCount=smsInfo.segments;}
|
||||
updateSMSCount(realCount);};infoRequest.onerror=function onError(){console.error('Can not retrieve segment info for body '+
|
||||
sms.body);updateSMSCount(1);};}
|
||||
function updateSMSCount(count){SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){settings.lastTelephonyActivity.timestamp=new Date();settings.lastTelephonyActivity.smscount+=count;ConfigManager.setOption({lastTelephonyActivity:settings.lastTelephonyActivity},function _sync(){localStorage.sync='lastTelephonyActivity#'+Math.random();closeIfProceeds();});});});}});navigator.mozSetMessageHandler('telephony-call-ended',function _onCall(tcall){clearTimeout(closing);if(tcall.direction!=='outgoing'){closeIfProceeds();return;}
|
||||
debug('Outgoing call finished!');SimManager.requestDataSimIcc(function(dataSimIcc){ConfigManager.requestSettings(dataSimIcc.iccId,function _onSettings(settings){var mode=ConfigManager.getApplicationMode();if(mode==='PREPAID'){costcontrol.request({type:'balance'});}
|
||||
settings.lastTelephonyActivity.timestamp=new Date();settings.lastTelephonyActivity.calltime+=tcall.duration;ConfigManager.setOption({lastTelephonyActivity:settings.lastTelephonyActivity},function _sync(){localStorage.sync='lastTelephonyActivity#'+Math.random();closeIfProceeds();});});});});}
|
||||
var readyEvent=new CustomEvent('messagehandlerready');window.parent.dispatchEvent(readyEvent);});}
|
||||
_getCCInstance();}());
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/* global debug */
|
||||
/* exported AutoSettings */
|
||||
|
||||
'use strict';
|
||||
|
||||
var AutoSettings = (function() {
|
||||
|
||||
var OPTION_CONFIGURERS = {
|
||||
'select': function _selectConfigurer(guiWidget) {
|
||||
var optionName = guiWidget.dataset.option;
|
||||
var span, parent = guiWidget.parentElement;
|
||||
if (parent.classList.contains('fake-select')) {
|
||||
var firstChild = parent.firstChild;
|
||||
if (!firstChild || firstChild.tagName !== 'SPAN') {
|
||||
span = document.createElement('span');
|
||||
parent.insertBefore(span, parent.firstChild);
|
||||
}
|
||||
}
|
||||
guiWidget.addEventListener('blur', function _onSelectChange() {
|
||||
debug('Value:', guiWidget.value);
|
||||
settings.option(optionName, guiWidget.value);
|
||||
});
|
||||
settings.observe(optionName, function _onOptionChange(value) {
|
||||
if (value === undefined) {
|
||||
value = settings.defaultValue(optionName);
|
||||
}
|
||||
guiWidget.value = value;
|
||||
if (span) {
|
||||
var selected = guiWidget.options[guiWidget.selectedIndex];
|
||||
var l10nId = selected.getAttribute('data-l10n-id');
|
||||
span.textContent = selected.textContent;
|
||||
if (l10nId) {
|
||||
span.setAttribute('data-l10n-id', l10nId);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// Select is used to simulate custom combo boxes. It displays a selection
|
||||
// dialog with an ok button and possibly a cancel button. The value is only
|
||||
// changed if ok button is pressed. If cancel provided and clicked then
|
||||
// the former value is restored.
|
||||
'customselect': function _customselectConfigurer(guiWidget) {
|
||||
|
||||
var dialog = document.getElementById(guiWidget.dataset.selectdialog);
|
||||
var optionName = guiWidget.dataset.option;
|
||||
|
||||
// Dialog
|
||||
|
||||
var okButton = dialog.querySelector('button.recommend');
|
||||
if (okButton) {
|
||||
okButton.addEventListener('click', function _onDialogOk() {
|
||||
var checked = dialog.querySelector('input[type="radio"]:checked');
|
||||
settings.option(optionName, checked.value);
|
||||
vmanager.closeCurrentView();
|
||||
});
|
||||
}
|
||||
|
||||
var cancelButton = dialog.querySelector('button.cancel');
|
||||
if (cancelButton) {
|
||||
cancelButton.addEventListener('click',
|
||||
function _onDialogCancel() {
|
||||
var currentValue = settings.option(optionName);
|
||||
settings.option(optionName, currentValue);
|
||||
vmanager.closeCurrentView();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
guiWidget.addEventListener('click', function _onWidgetClick() {
|
||||
vmanager.changeViewTo(dialog.id);
|
||||
});
|
||||
|
||||
// Keep the widget and the dialog synchronized
|
||||
settings.observe(optionName,
|
||||
function _onOptionChange(value) {
|
||||
|
||||
// Use default value if no value
|
||||
if (value === null || value === undefined) {
|
||||
value = getDefaultValue(optionName);
|
||||
}
|
||||
|
||||
var radio =
|
||||
dialog.querySelector('input[type="radio"][value="' + value + '"]');
|
||||
|
||||
if (!radio) {
|
||||
value = getDefaultValue(optionName);
|
||||
radio = dialog.querySelector('input[type="radio"][value="' +
|
||||
value + '"]');
|
||||
}
|
||||
radio.checked = true;
|
||||
|
||||
var textSpan = dialog.querySelector('input:checked + span');
|
||||
var tagSpan = guiWidget.querySelector('.tag');
|
||||
tagSpan.textContent = textSpan.textContent;
|
||||
}
|
||||
);
|
||||
|
||||
// Keep the UI localized
|
||||
window.addEventListener('localized', function _onLocalized() {
|
||||
var textSpan = dialog.querySelector('input:checked + span');
|
||||
var tagSpan = guiWidget.querySelector('.tag');
|
||||
tagSpan.textContent = textSpan.textContent;
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
// Switch configurer handles an checkbox. When it changes, the checked
|
||||
// state is used as the content for the option.
|
||||
'switch' : function _switchConfigurer(guiWidget) {
|
||||
var optionName = guiWidget.dataset.option;
|
||||
|
||||
// Add an observer to keep synchronization
|
||||
settings.observe(
|
||||
optionName,
|
||||
function _onOptionChange(value) {
|
||||
if (value === null || value === undefined) {
|
||||
value = getDefaultValue(optionName);
|
||||
}
|
||||
guiWidget.checked = value;
|
||||
}
|
||||
);
|
||||
|
||||
// Add an event listener to switch the option
|
||||
guiWidget.addEventListener('change', function ccapp_onSwitchChange() {
|
||||
settings.option(optionName, guiWidget.checked);
|
||||
});
|
||||
},
|
||||
|
||||
// Input configurer handles an input box. When the content changes, the
|
||||
// content is parsed and sent to the proper option.
|
||||
'input' : function _inputConfigurer(guiWidget) {
|
||||
var optionName = guiWidget.dataset.option;
|
||||
|
||||
// Add an observer to keep synchronization
|
||||
settings.observe(
|
||||
optionName,
|
||||
function _onOptionChange(value) {
|
||||
if (value === null || value === undefined) {
|
||||
value = getDefaultValue(optionName);
|
||||
}
|
||||
guiWidget.value = value;
|
||||
}
|
||||
);
|
||||
|
||||
// Add an event listener to switch the option
|
||||
guiWidget.addEventListener('change', function _onContentChange() {
|
||||
var value = guiWidget.value;
|
||||
if (guiWidget.type === 'number') {
|
||||
value = parseFloat(value);
|
||||
}
|
||||
settings.option(optionName, value);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Add a new type with its configuration function
|
||||
function addType(newType, configFunction) {
|
||||
OPTION_CONFIGURERS[newType] = configFunction;
|
||||
}
|
||||
|
||||
var customRecognizer;
|
||||
// Add a recognizer to detect new types
|
||||
function setCustomRecognizer(recognizer) {
|
||||
customRecognizer = recognizer;
|
||||
}
|
||||
|
||||
// Return the <li> wrapping the option
|
||||
function getEntryParent(item) {
|
||||
while (item && item.tagName !== 'LI') {
|
||||
item = item.parentNode;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
// Return the default value for an option
|
||||
function getDefaultValue(optionName) {
|
||||
return settings.defaultValue(optionName);
|
||||
}
|
||||
|
||||
// Configure the web page
|
||||
var settings, vmanager;
|
||||
function initialize(settingsInterface, viewManager, root) {
|
||||
|
||||
root = root || 'body';
|
||||
settings = settingsInterface;
|
||||
vmanager = viewManager;
|
||||
|
||||
// Return the type of configurer needed based on the properties of
|
||||
// the HTML element marked as the option.
|
||||
function getWidgetType(widget) {
|
||||
if (widget.dataset.widgetType) {
|
||||
return widget.dataset.widgetType;
|
||||
}
|
||||
|
||||
var customType;
|
||||
if (customRecognizer === 'function') {
|
||||
customType = customRecognizer(widget, settings, vmanager);
|
||||
}
|
||||
|
||||
if (customType) {
|
||||
return customType;
|
||||
}
|
||||
|
||||
if (widget.tagName === 'SELECT') {
|
||||
return 'select';
|
||||
}
|
||||
|
||||
if (typeof widget.dataset.selectdialog !== 'undefined') {
|
||||
return 'customselect';
|
||||
}
|
||||
|
||||
if (widget.type === 'checkbox' ||
|
||||
widget.nodeName.toLowerCase() === 'gaia-switch') {
|
||||
return 'switch';
|
||||
}
|
||||
|
||||
if (['text', 'number'].indexOf(widget.type) !== -1) {
|
||||
return 'input';
|
||||
}
|
||||
}
|
||||
|
||||
// Install a dependency based on an expression. When expression is true
|
||||
// call the callback.
|
||||
function installDependency(expression, callback) {
|
||||
var equality = false;
|
||||
var parsed = expression.split('!=');
|
||||
if (parsed.length === 1) {
|
||||
parsed = expression.split('=');
|
||||
equality = true;
|
||||
}
|
||||
|
||||
var dependency = parsed[0];
|
||||
var referenceValue = parsed[1];
|
||||
settings.observe(dependency,
|
||||
function ccapp_dependencyAction(value) {
|
||||
var test = (('' + value) === referenceValue);
|
||||
callback(equality === test); // or is an equality test and values are
|
||||
// equal or is an inequality test and
|
||||
// values are different.
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Widgets
|
||||
var allGUIWidgets = document.querySelectorAll(root + ' .settings-option');
|
||||
[].forEach.call(allGUIWidgets, function _forEachWidget(guiWidget) {
|
||||
|
||||
var type = getWidgetType(guiWidget);
|
||||
var entry = getEntryParent(guiWidget);
|
||||
var configurer = OPTION_CONFIGURERS[type];
|
||||
if (configurer) {
|
||||
configurer(guiWidget, settings, vmanager, root);
|
||||
}
|
||||
|
||||
// Simple dependency resolution:
|
||||
|
||||
// enable / disable some options depending on the values of other
|
||||
var disableOn = guiWidget.dataset.disableOn;
|
||||
if (disableOn) {
|
||||
installDependency(disableOn, function _disable(passed) {
|
||||
guiWidget.disabled = passed;
|
||||
if (entry) {
|
||||
entry.setAttribute('aria-disabled', passed + '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// hide / show some options depending on the values of other
|
||||
var hideOn = guiWidget.dataset.hideOn;
|
||||
if (hideOn) {
|
||||
installDependency(hideOn, function _hide(passed) {
|
||||
guiWidget.hidden = passed;
|
||||
if (entry) {
|
||||
entry.hidden = passed;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
initialize: initialize,
|
||||
setCustomRecognizer: setCustomRecognizer,
|
||||
addType: addType
|
||||
};
|
||||
|
||||
}());
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
/* global _, addNetworkUsageAlarm, Common, Formatting, SimManager,
|
||||
CostControl */
|
||||
/* exported dataLimitConfigurer */
|
||||
'use strict';
|
||||
|
||||
function dataLimitConfigurer(guiWidget, settings, viewManager, widgetRoot) {
|
||||
var REMOVE_CHAR_CODE = 8,
|
||||
// It Represents any positive real number (up to three digits length),
|
||||
// with optional decimal point, accepting up to 2 decimal places. It is
|
||||
// not necessary adding the significant number when it is zero (eg. '.5'
|
||||
// is a valid entry)
|
||||
DATA_LIMIT_NUMERIC_FORMAT = new RegExp('^[0-9]{0,3}(\\.[0-9]{1,2})?$');
|
||||
|
||||
|
||||
var dialog = document.getElementById('data-limit-dialog');
|
||||
var dataLimitInput = dialog.querySelector('input');
|
||||
var format = function ccal_formatterDataUnit(value) {
|
||||
var unit = settings.option('dataLimitUnit');
|
||||
return Formatting.formatData([value, _(unit)]);
|
||||
};
|
||||
|
||||
window.addEventListener('localized', function _onLocalize() {
|
||||
var tagSpan = guiWidget.querySelector('.tag');
|
||||
tagSpan.textContent = format(dataLimitInput.value);
|
||||
});
|
||||
|
||||
// Configure dialog
|
||||
var okButton = dialog.querySelector('button.recommend');
|
||||
if (okButton) {
|
||||
okButton.addEventListener('click', function ccld_onDialogOk() {
|
||||
var value = parseFloat(dataLimitInput.value);
|
||||
settings.option('dataLimitValue', value);
|
||||
settings.option('dataLimitUnit', currentUnit);
|
||||
var dataLimit = Common.getDataLimit({'dataLimitValue': value,
|
||||
'dataLimitUnit': currentUnit});
|
||||
SimManager.requestDataSimIcc(function(dataSim) {
|
||||
var simInterface = Common.getDataSIMInterface(dataSim.iccId);
|
||||
addNetworkUsageAlarm(simInterface, dataLimit, null,
|
||||
() => checkDataLimit(dataLimit));
|
||||
});
|
||||
viewManager.closeCurrentView();
|
||||
});
|
||||
}
|
||||
|
||||
var dialogHeader = dialog.querySelector('#limit-dialog-header');
|
||||
if (dialogHeader) {
|
||||
dialogHeader.addEventListener('action',
|
||||
function ccld_onDialogCancel() {
|
||||
var oldValue = settings.option('dataLimitValue');
|
||||
var oldUnit = settings.option('dataLimitUnit');
|
||||
currentUnit = oldUnit;
|
||||
settings.option('dataLimitValue', oldValue);
|
||||
settings.option('dataLimitUnit', oldUnit);
|
||||
dataLimitInput.classList.remove('error');
|
||||
okButton.disabled = false;
|
||||
viewManager.closeCurrentView();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function checkDataLimit(dataLimit) {
|
||||
CostControl.getInstance(function _onCostControl(costcontrol) {
|
||||
var requestObj = {
|
||||
type: 'datausage'
|
||||
};
|
||||
costcontrol.request(requestObj, function _onDataStats(result) {
|
||||
var stats = result.data.mobile.total;
|
||||
if (stats > dataLimit) {
|
||||
var mobileUsage = {
|
||||
limit: Formatting.formatData(Formatting.roundData(dataLimit))
|
||||
};
|
||||
var message = _('data-limit-notification-title2', mobileUsage) +
|
||||
'\n' + _('data-limit-notification-text2');
|
||||
window.alert(message);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function isNotRemovingChar(newChar) {
|
||||
return REMOVE_CHAR_CODE !== newChar;
|
||||
}
|
||||
|
||||
function isAllowedValue(newValue) {
|
||||
return isValidValue(newValue) || wouldBeValid(newValue);
|
||||
}
|
||||
// Checks if value is numeric and it has a valid format
|
||||
// Not allowed entry characters '-', ',' or more than one '.'
|
||||
function isValidValue(newValue) {
|
||||
var containsNonValidCharacters = [',','-']
|
||||
.some(c => newValue.indexOf(c) > -1);
|
||||
var containsMoreThanOneDot = (newValue.match(/\./g) || []).length > 1;
|
||||
return !Number.isNaN(newValue) &&
|
||||
!containsNonValidCharacters && !containsMoreThanOneDot &&
|
||||
isValidFormat(newValue);
|
||||
}
|
||||
|
||||
function wouldBeValid(lowLimitValue) {
|
||||
var allowedEntry = new RegExp('^0?(\\.0?)?$');
|
||||
return allowedEntry.test(lowLimitValue);
|
||||
}
|
||||
|
||||
function preventBadInput(valid, newChar, currentInput) {
|
||||
// This method returns the string resultant of adding the character of the
|
||||
// keypress event
|
||||
function simulateNewValue(newChar, currentInput) {
|
||||
var value = currentInput.value,
|
||||
idx = currentInput.selectionStart,
|
||||
newCharValue = String.fromCharCode(newChar);
|
||||
return value.substr(0, idx) + newCharValue + value.substr(idx);
|
||||
}
|
||||
var newValue = simulateNewValue(newChar, currentInput);
|
||||
var isInvalid = !valid(newValue);
|
||||
return isInvalid;
|
||||
}
|
||||
|
||||
dataLimitInput.addEventListener('keypress',
|
||||
function cc_onKeypress(event) {
|
||||
var currentInput = event.target;
|
||||
var newChar = event.charCode || event.keyCode;
|
||||
|
||||
// If the entry is not valid or the result of the input is invalid, we
|
||||
// have to prevent the event propagation
|
||||
if (isNotRemovingChar(newChar) &&
|
||||
preventBadInput(isAllowedValue, newChar, currentInput)) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function isValidFormat(lowLimitValue) {
|
||||
var numberDataLimit = Number(lowLimitValue);
|
||||
return (numberDataLimit < 1000 &&
|
||||
numberDataLimit > 0 &&
|
||||
DATA_LIMIT_NUMERIC_FORMAT.test(numberDataLimit));
|
||||
}
|
||||
|
||||
// Disable OK button when dataLimitInput not matches any positive real number
|
||||
// (up to three digits length), with optional decimal point, accepting up
|
||||
// to 2 decimal places.
|
||||
dataLimitInput.addEventListener('input',
|
||||
function cc_ondataLimitInputChange(evt) {
|
||||
var lowLimitValue = evt.target.value.trim();
|
||||
var isNumericLowLimit = !Number.isNaN(Number(lowLimitValue));
|
||||
|
||||
if (isNumericLowLimit &&
|
||||
lowLimitValue.indexOf('.0') !== lowLimitValue.length - 2 &&
|
||||
lowLimitValue.indexOf('.') !== lowLimitValue.length - 1) {
|
||||
dataLimitInput.value = Number(lowLimitValue);
|
||||
}
|
||||
|
||||
var isValidValue = (isNumericLowLimit && isValidFormat(lowLimitValue));
|
||||
|
||||
if (isValidValue) {
|
||||
dataLimitInput.classList.remove('error');
|
||||
} else {
|
||||
dataLimitInput.classList.add('error');
|
||||
}
|
||||
okButton.disabled = (!isValidValue);
|
||||
}
|
||||
);
|
||||
|
||||
// Configure the swicth unit button
|
||||
var currentUnit = settings.option('dataLimitUnit');
|
||||
var switchUnitButton = dialog.querySelector('.switch-unit-button');
|
||||
function localizeSwitchUnitButton(unit) {
|
||||
switchUnitButton.setAttribute('data-l10n-id', 'unit-' + unit);
|
||||
switchUnitButton.querySelector('span.tag').setAttribute(
|
||||
'data-l10n-id', unit);
|
||||
}
|
||||
|
||||
localizeSwitchUnitButton(currentUnit);
|
||||
switchUnitButton.addEventListener('click',
|
||||
function ccapp_switchUnit() {
|
||||
currentUnit = (currentUnit === 'MB') ? 'GB' : 'MB';
|
||||
localizeSwitchUnitButton(currentUnit);
|
||||
}
|
||||
);
|
||||
|
||||
// Prevent to loose the focus when tapping on switch unit button
|
||||
// TODO: Replace with 'focusout' on dataLimitInput when fixing bug:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=687787
|
||||
switchUnitButton.addEventListener('mousedown',
|
||||
function _preventFocusLost(evt) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
);
|
||||
|
||||
// Keep the widget and the dialog synchronized
|
||||
settings.observe('dataLimitValue',
|
||||
function ccld_onValueChange(value) {
|
||||
// Use default value if no value
|
||||
if (value === null || typeof value === 'undefined') {
|
||||
value = settings.defaultValue('dataLimitValue');
|
||||
}
|
||||
|
||||
// Set dialog
|
||||
dataLimitInput.value = value;
|
||||
|
||||
var tagSpan = guiWidget.querySelector('.tag');
|
||||
tagSpan.textContent = format(dataLimitInput.value);
|
||||
}
|
||||
);
|
||||
|
||||
settings.observe('dataLimitUnit',
|
||||
function ccld_onUnitChange(value) {
|
||||
|
||||
// Use default value if no value
|
||||
if (value === null || typeof value === 'undefined') {
|
||||
value = settings.defaultValue('dataLimitUnit');
|
||||
}
|
||||
|
||||
// Set dialog
|
||||
localizeSwitchUnitButton(value);
|
||||
|
||||
var tagSpan = guiWidget.querySelector('.tag');
|
||||
tagSpan.textContent = format(dataLimitInput.value);
|
||||
}
|
||||
);
|
||||
|
||||
// Show the dialog
|
||||
var oldUnitValue;
|
||||
guiWidget.addEventListener('click', function ccld_onWidgetClick() {
|
||||
viewManager.changeViewTo(dialog.id, widgetRoot);
|
||||
dataLimitInput.focus();
|
||||
dataLimitInput.setSelectionRange(dataLimitInput.value.length,
|
||||
dataLimitInput.value.length);
|
||||
oldUnitValue = settings.option('dataLimitUnit');
|
||||
localizeSwitchUnitButton(oldUnitValue);
|
||||
});
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
;'use strict';var NetworkUsageAlarm=(function(){function _addAlarm(networkInterface,value,onsuccess,onerror){if(!networkInterface){console.error('Error, the network interface is not defined when trying '+'to add an alarm');(typeof onerror==='function')&&onerror();return;}
|
||||
if(value===null||typeof value==='undefined'){console.error('Limit value is undefined, impossible add an alarm');(typeof onerror==='function')&&onerror();return;}
|
||||
var request=navigator.mozNetworkStats.addAlarm(networkInterface,value);request.onsuccess=onsuccess;request.onerror=function error(e){console.error('Error, when trying to addAlarm to the interfaceId: '+
|
||||
networkInterface.id+' and limit: '+value);(typeof onerror==='function')&&onerror();};}
|
||||
function _clearAlarms(networkInterface,callback){if(!networkInterface){console.error('Error, the network interface is not defined when trying '+'to remove alarms');return;}
|
||||
var request=navigator.mozNetworkStats.getAllAlarms(networkInterface);request.onsuccess=function success(){var alarmList=request.result;var pendingRequest=alarmList.length;function checkForCompletion(){pendingRequest--;if(pendingRequest===0){(typeof callback==='function')&&callback();}}
|
||||
function _onErrorRemoveAlarm(){console.error('Error when trying to remove one alarm.');checkForCompletion();}
|
||||
for(var i=0;i<alarmList.length;i++){if(alarmList[i]&&alarmList[i].alarmId){var rA=navigator.mozNetworkStats.removeAlarms(alarmList[i].alarmId);rA.onsuccess=checkForCompletion;rA.onerror=_onErrorRemoveAlarm;}}
|
||||
if(pendingRequest===0){(typeof callback==='function')&&callback();}};request.onerror=function error(){console.error('Error when trying to get alarms from the API to clear it');};}
|
||||
function _updateAlarm(dataInterface,value,onsuccess,onerror){if(dataInterface&&value){var addNewAlarm=_addAlarm.bind(null,dataInterface,value,onsuccess,onerror);_clearAlarms(dataInterface,addNewAlarm);}else{if(!dataInterface){console.error('Error, the network interface is not defined when '+'trying to update an alarm');}else{console.error('Error, the data limit value is not defined when '+'trying to update an alarm');}
|
||||
(typeof onerror==='function')&&onerror();}}
|
||||
return{updateAlarm:_updateAlarm,clearAlarms:_clearAlarms};}());
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
;'use strict';var ConfigManager=window.parent.ConfigManager;var CostControl=window.parent.CostControl;var SimManager=window.parent.SimManager;var Common=window.parent.Common;var NetworkUsageAlarm=window.parent.NetworkUsageAlarm;var addNetworkUsageAlarm=window.parent.addNetworkUsageAlarm;var resetTelephony=window.parent.resetTelephony;navigator.mozL10n=window.parent.navigator.mozL10n;var DEBUGGING=window.parent.DEBUGGING;var debug=window.parent.debug;var Settings=(function(){var costcontrol,vmanager,initialized,endLoadSettingsNotified;var plantypeSelector,phoneActivityTitle,phoneActivitySettings;var balanceTitle,balanceSettings,reportsTitle;var balanceView,resetMenuDialog,confirmDialog;function configureUI(){CostControl.getInstance(function _onCostControl(instance){costcontrol=instance;if(DEBUGGING){loadDeveloperAids();}
|
||||
vmanager=new ViewManager();plantypeSelector=document.getElementById('plantype-settings');phoneActivityTitle=document.getElementById('phone-activity-settings');phoneActivitySettings=document.querySelector('#phone-activity-settings + .settings');balanceTitle=document.getElementById('balance-settings');balanceSettings=document.querySelector('#balance-settings + .settings');reportsTitle=document.getElementById('phone-internet-settings');var balanceConfig=ConfigManager.configuration.balance;balanceView=new BalanceView(document.getElementById('balance'),document.querySelector('#balance + .meta'),balanceConfig?balanceConfig.minimum_delay:undefined);var resetDialog=document.getElementById('reset-dialog');var resetDataDialog=document.getElementById('reset-data-dialog');resetMenuDialog=new ResetMenuDialog(resetDataDialog,vmanager);confirmDialog=new ConfirmDialog(resetDialog,vmanager);resetMenuDialog.initializeResetModes(confirmDialog);AutoSettings.addType('data-limit',dataLimitConfigurer);AutoSettings.initialize(ConfigManager,vmanager,'#settings-view');configureTelephonyReset();configureDataResets();addDoneConstrains();ConfigManager.observe('dataLimit',function _onDataLimitChange(value,old,key,settings){SimManager.requestDataSimIcc(function(dataSim){var iccId=dataSim.iccId;var currentDataInterface=Common.getDataSIMInterface(iccId);if(!value){NetworkUsageAlarm.clearAlarms(currentDataInterface);}else{addNetworkUsageAlarm(currentDataInterface,Common.getDataLimit(settings));}});},true);ConfigManager.observe('plantype',updateUI,true);ConfigManager.observe('lastTelephonyActivity',function _updateTelephony(activity,old,key,settings){updateTelephony(activity,settings.lastTelephonyReset);},true);ConfigManager.observe('lastDataUsage',function _updateDataUsage(stats,old,key,settings){updateDataUsage(stats,settings.lastCompleteDataReset);},true);ConfigManager.observe('lastBalance',function _updateBalance(balance){updateBalance(balance,balance.currency);},true);var close=document.getElementById('close-settings');close.addEventListener('click',function(){closeSettings();});function _setResetTimeToDefault(value,old,key,settings){var today=new Date();var defaultResetTime=(settings.trackingPeriod==='weekly')?today.getDay():today.getDate();if(settings.resetTime!==defaultResetTime){ConfigManager.setOption({resetTime:defaultResetTime});}else{Common.updateNextReset(settings.trackingPeriod,settings.resetTime);}}
|
||||
function _updateNextReset(value,old,key,settings){Common.updateNextReset(settings.trackingPeriod,settings.resetTime);}
|
||||
ConfigManager.observe('resetTime',_updateNextReset,true);ConfigManager.observe('trackingPeriod',_setResetTimeToDefault,true);initialized=true;Settings.updateUI();});}
|
||||
function closeSettings(){window.parent.location.hash='#';}
|
||||
function loadDeveloperAids(){var xhr=new XMLHttpRequest();xhr.overrideMimeType('text/plain');xhr.open('GET','/debug.html',false);xhr.send();if(xhr.status===200){var src=document.createElement('DIV');src.innerHTML=xhr.responseText;var reference=document.getElementById('plantype-settings');var parent=reference.parentNode;[].forEach.call(src.childNodes,function(node){reference=parent.insertBefore(node,reference.nextSibling);});}}
|
||||
function configureTelephonyReset(){var resetTelephonyButton=document.getElementById('reset-telephony');resetTelephonyButton.addEventListener('click',function(){confirmDialog.setMessage('reset-telephony-confirmation-warning',{});function resetAction(){resetTelephony();updateUI();confirmDialog.closeConfirmDialog();}
|
||||
confirmDialog.updateAcceptAction(resetAction);confirmDialog.showConfirmDialog();});}
|
||||
function configureDataResets(){var resetDataUsage=document.getElementById('reset-data-usage');resetDataUsage.addEventListener('click',function _onDataReset(){var currentTotals={mobile:costcontrol.lastDataResults.mobile.total,wifi:costcontrol.lastDataResults.wifi.total};resetMenuDialog.showResetMenuDialog(currentTotals);});}
|
||||
var balanceLowLimitView;function addDoneConstrains(){var closeButton=document.getElementById('close-settings');balanceLowLimitView=new BalanceLowLimitView(document.getElementById('low-limit'),document.getElementById('low-limit-input'));balanceLowLimitView.onvalidation=function(evt){closeButton.disabled=!evt.isValid;};}
|
||||
window.addEventListener('localized',function _onLocalize(){if(initialized){updateUI();}});var currentMode;function updateUI(){ConfigManager.requestAll(function _onInfo(configuration,settings){Common.localizeWeekdaySelector(document.getElementById('select-weekday'));var mode=ConfigManager.getApplicationMode();if(currentMode!==mode){currentMode=mode;var hidePlantypeSelector=(mode==='DATA_USAGE_ONLY');var hidePhoneActivity=(mode!=='POSTPAID');var hideBalance=(mode!=='PREPAID');var hideReportsTitle=(mode==='PREPAID');var textReportsTitle=(mode==='POSTPAID')?'phone-and-internet-data-report':'internet-data-report';reportsTitle.querySelector('span').setAttribute('data-l10n-id',textReportsTitle);balanceLowLimitView.disabled=(mode!=='PREPAID');plantypeSelector.hidden=hidePlantypeSelector;phoneActivityTitle.hidden=hidePhoneActivity;phoneActivitySettings.hidden=hidePhoneActivity;balanceTitle.hidden=hideBalance;balanceSettings.hidden=hideBalance;reportsTitle.hidden=hideReportsTitle;}
|
||||
var requestObj={type:'datausage'};costcontrol.request(requestObj,function _onDataStats(result){var stats=result.data;updateDataUsage(stats,settings.lastCompleteDataReset);});switch(mode){case'PREPAID':updateBalance(settings.lastBalance,configuration.credit.currency);break;case'POSTPAID':updateTelephony(settings.lastTelephonyActivity,settings.lastTelephonyReset);break;}
|
||||
if(endLoadSettingsNotified){window.performance.measure('loadSettings','loadSettingsStart');endLoadSettingsNotified=true;}});}
|
||||
function updateDataUsage(datausage,lastCompleteDataReset){var mobileUsage=document.querySelector('#mobile-data-usage > span');var data=Formatting.roundData(datausage.mobile.total);mobileUsage.textContent=Formatting.formatData(data);var wifiUsage=document.querySelector('#wifi-data-usage > span');data=Formatting.roundData(datausage.wifi.total);wifiUsage.textContent=Formatting.formatData(data);updateDataUsageTimestamp(lastCompleteDataReset,datausage.timestamp);}
|
||||
var dataUsagePeriod={begin:null,end:null};function updateDataUsageTimestamp(begin,end){dataUsagePeriod.begin=begin;dataUsagePeriod.end=end;var timestamp=document.querySelector('#wifi-data-usage + .meta');timestamp.innerHTML='';timestamp.appendChild(Formatting.formatTimeHTML(begin,end));}
|
||||
function updateBalance(lastBalance,currency){var limitCurrency=document.getElementById('settings-low-limit-currency');limitCurrency.textContent=currency;balanceView.update(lastBalance);}
|
||||
function updateTelephony(activity,lastTelephonyReset){var calltimeSpan=document.getElementById('calltime');var smscountSpan=document.getElementById('smscount');Common.localize(calltimeSpan,'magnitude',{value:Formatting.computeTelephonyMinutes(activity),unit:'min.'});Common.localize(smscountSpan,'magnitude',{value:activity.smscount,unit:'SMS'});updateTelephonyTimestamp(lastTelephonyReset,activity.timestamp);}
|
||||
var telephonyPeriod={begin:null,end:null};function updateTelephonyTimestamp(begin,end){telephonyPeriod.begin=begin;telephonyPeriod.end=end;var timestamp=document.getElementById('telephony-timestamp');timestamp.innerHTML='';timestamp.appendChild(Formatting.formatTimeHTML(begin,end));}
|
||||
window.addEventListener('timeformatchange',function(){updateTelephonyTimestamp(telephonyPeriod.begin,telephonyPeriod.end);updateDataUsageTimestamp(dataUsagePeriod.begin,dataUsagePeriod.end);});return{initialize:function(){var SCRIPTS_NEEDED=['js/utils/toolkit.js','shared/js/date_time_helper.js','js/utils/formatting.js','js/views/BalanceLowLimitView.js','js/settings/limitdialog.js','js/settings/autosettings.js','js/view_manager.js','js/views/BalanceView.js','js/views/ResetMenuDialog.js','js/views/ConfirmDialog.js'];LazyLoader.load(SCRIPTS_NEEDED,function(){if(!Common.allNetworkInterfaceLoaded){Common.loadNetworkInterfaces(configureUI);}else{configureUI();}});},updateUI:updateUI};}());Settings.initialize();
|
||||
16
assets/webapps/costcontrol.gaiamobile.org/js/sim_manager.js
Normal file
16
assets/webapps/costcontrol.gaiamobile.org/js/sim_manager.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
;'use strict';var SimManager=(function(){var serviceIcc={};var serviceSettingMap={'data':'ril.data.defaultServiceId','telephony':'ril.telephony.defaultServiceId','message':'ril.sms.defaultServiceId'};function notifyInitializationDone(updatedService){var simInitializedEvent=new CustomEvent('simManagerReady',{detail:updatedService});window.dispatchEvent(simInitializedEvent);}
|
||||
function _init(serviceId){_reset(serviceId);LazyLoader.load(['/shared/js/airplane_mode_helper.js'],function(){AirplaneModeHelper.addEventListener('statechange',function _onAirplaneModeChange(state){if(state==='disabled'){serviceIcc[serviceId].dirty=true;var eventDetail={detail:{serviceId:serviceId}};var airplanemodeDisabledEvent=new CustomEvent('airplaneModeDisabled',eventDetail);window.dispatchEvent(airplanemodeDisabledEvent);}});});function checkForCompletion(){serviceIcc[serviceId].initialized=true;SettingsListener.observe(serviceSettingMap[serviceId],0,function(value){var isDirty=(serviceIcc[serviceId].slotId!==value);serviceIcc[serviceId].dirty=isDirty;serviceIcc[serviceId].slotId=value;if(isDirty){var serviceSlotChangeEvent=new CustomEvent(serviceId+'SlotChange',{detail:serviceId});window.dispatchEvent(serviceSlotChangeEvent);}});notifyInitializationDone(serviceId);}
|
||||
if(SimManager.isMultiSim()){var settings=window.navigator.mozSettings;var req=settings&&settings.createLock().get(serviceSettingMap[serviceId]);req.onsuccess=function _onsuccesSlotId(){if(!req.result[serviceSettingMap[serviceId]]){console.warn('The setting '+serviceSettingMap[serviceId]+' does not exists, using default Slot (0)');}
|
||||
var slotId=req.result[serviceSettingMap[serviceId]]||0;serviceIcc[serviceId].slotId=slotId;checkForCompletion();};req.onerror=function _onErrorSlotId(){console.warn('The setting '+serviceSettingMap[serviceId]+' does not exists');checkForCompletion();};}else{notifyInitializationDone(serviceId);}}
|
||||
function _requestDataSIMIcc(onsuccess,onerror){_requestService('data',onsuccess,onerror);}
|
||||
function _requestTelephonySIMIcc(onsuccess,onerror){_requestService('telephony',onsuccess,onerror);}
|
||||
function _requestMessageSIMIcc(onsuccess,onerror){_requestService('message',onsuccess,onerror);}
|
||||
function _requestService(serviceId,onsuccess,onerror){if(serviceIcc[serviceId]&&serviceIcc[serviceId].initialized&&!serviceIcc[serviceId].dirty){(typeof onsuccess==='function')&&onsuccess(serviceIcc[serviceId]);}else if(!serviceIcc[serviceId]||!serviceIcc[serviceId].initialized){console.warn('SimManager is not ready, waiting for initialized custom '+'event');window.addEventListener('simManagerReady',function _onSMInit(evt){if(evt.detail==='all'||evt.detail===serviceId){window.removeEventListener('simManagerReady',_onSMInit);_requestServiceSIMIcc(serviceId,onsuccess,onerror);}});_init(serviceId);}else{_requestServiceSIMIcc(serviceId,onsuccess,onerror);}}
|
||||
function _requestServiceSIMIcc(serviceId,onsuccess,onerror){var iccManager=window.navigator.mozIccManager;var slotId=serviceIcc[serviceId].slotId;var mobileConnection=navigator.mozMobileConnections[slotId];var iccId=mobileConnection.iccId||null;if(!iccId){console.error('The slot '+slotId+', configured as the '+serviceId+' slot, is empty');(typeof onerror==='function')&&onerror();return;}
|
||||
serviceIcc[serviceId].iccId=iccId;serviceIcc[serviceId].icc=iccManager.getIccById(iccId);if(!serviceIcc[serviceId].icc){(typeof onerror==='function')&&onerror();return;}
|
||||
(typeof onsuccess==='function')&&onsuccess(serviceIcc[serviceId]);}
|
||||
function _reset(serviceId){function _resetService(serviceId){var _initialized=!SimManager.isMultiSim();serviceIcc[serviceId]={dirty:true,icc:null,iccId:null,slotId:0,initialized:_initialized};}
|
||||
if(!serviceId){Object.keys(serviceSettingMap).forEach(function _initService(serviceId){_resetService(serviceId);});}else{_resetService(serviceId);}}
|
||||
function _requestServiceConnection(serviceId){var slotId=serviceIcc[serviceId].slotId;return navigator.mozMobileConnections[slotId];}
|
||||
function _requestDataConnection(callback){if(serviceIcc.data&&serviceIcc.data.initialized){var connection=_requestServiceConnection('data');(typeof callback==='function')&&callback(connection);}else{console.warn('SimManager is not ready, waiting for initialized custom '+'event');window.addEventListener('simManagerReady',function _onSMInit(evt){if(evt.detail==='all'||evt.detail==='data'){window.removeEventListener('simManagerReady',_onSMInit);var connection=_requestServiceConnection('data');(typeof callback==='function')&&callback(connection);}});_init('data');}}
|
||||
return{isMultiSim:function(){return(navigator.mozMobileConnections.length>1);},requestDataSimIcc:_requestDataSIMIcc,requestTelephonySimIcc:_requestTelephonySIMIcc,requestDataConnection:_requestDataConnection,requestMessageSimIcc:_requestMessageSIMIcc,reset:_reset};})();
|
||||
585
assets/webapps/costcontrol.gaiamobile.org/js/utils/chart.js
Normal file
585
assets/webapps/costcontrol.gaiamobile.org/js/utils/chart.js
Normal file
|
|
@ -0,0 +1,585 @@
|
|||
/* global _, debug, Toolkit, Formatting, Common */
|
||||
/* exported ChartUtils */
|
||||
'use strict';
|
||||
|
||||
var ChartUtils = (function() {
|
||||
var DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;
|
||||
var DAY = 24 * 60 * 60 * 1000;
|
||||
var NEVER_PERIOD = 30 * DAY;
|
||||
var NEVER_ANCHOR = 21 * DAY;
|
||||
var CHART_BG_RATIO = 0.87;
|
||||
var FONT_SIZE = toDevicePixels(13);
|
||||
var FONT_WEIGHT = '600';
|
||||
var FONT_WEIGHT_AXIS = '400';
|
||||
var WIFI_CHART_STROKE = '#8b9052';
|
||||
var WIFI_CHART_FILL = '#cbd936';
|
||||
var MOBILE_CHART_STROKE = '#762d4a';
|
||||
var MOBILE_CHART_FILL = 'rgba(147, 21, 98, 0.7)';
|
||||
|
||||
function toDevicePixels(value) {
|
||||
return value * DEVICE_PIXEL_RATIO;
|
||||
}
|
||||
|
||||
function makeCSSFontString(fontSize, fontWeight) {
|
||||
return fontWeight + ' ' + fontSize + 'px sans-serif';
|
||||
}
|
||||
|
||||
function formatChartDate(date) {
|
||||
return _('verbose-chart-date-format', {
|
||||
'monthday-number': date.getDate(),
|
||||
'em-month': _('month-' + date.getMonth() + '-short')
|
||||
});
|
||||
}
|
||||
|
||||
function getLimitInBytes(settings) {
|
||||
var multiplier = 1000000; // MB
|
||||
if (settings.dataLimitUnit === 'GB') {
|
||||
multiplier = 1000000000; // GB
|
||||
}
|
||||
|
||||
var value = settings.dataLimitValue;
|
||||
return (value && value !== 0) ? value * multiplier : null;
|
||||
}
|
||||
|
||||
function calculateUpperDate(settings) {
|
||||
var today = new Date();
|
||||
var trackingPeriod = settings.trackingPeriod;
|
||||
var nextReset = settings.nextReset;
|
||||
if (trackingPeriod !== 'never' && nextReset) {
|
||||
return new Date(nextReset.getTime() - DAY);
|
||||
}
|
||||
|
||||
var lastReset = settings.lastCompleteDataReset || today;
|
||||
var offset = today.getTime() - lastReset.getTime();
|
||||
var upperDate = new Date(lastReset.getTime() + NEVER_PERIOD);
|
||||
if (offset >= NEVER_ANCHOR) {
|
||||
upperDate = new Date(today.getTime() + (NEVER_PERIOD - NEVER_ANCHOR));
|
||||
}
|
||||
|
||||
debug('Upper date:', upperDate);
|
||||
return upperDate;
|
||||
}
|
||||
|
||||
function calculateLowerDate(settings) {
|
||||
var today = new Date();
|
||||
var lowerDate = Toolkit.toMidnight(new Date());
|
||||
var nextReset = settings.nextReset || lowerDate;
|
||||
var trackingPeriod = settings.trackingPeriod;
|
||||
|
||||
if (trackingPeriod === 'weekly') {
|
||||
lowerDate.setTime(nextReset.getTime() - (7 * DAY));
|
||||
} else if (trackingPeriod === 'monthly') {
|
||||
var monthDate = settings.resetTime;
|
||||
var isFirstDayOfPeriod = today.getDate() == monthDate;
|
||||
var isAfterFirstDayOfPeriod = today.getDate() > monthDate;
|
||||
if (isAfterFirstDayOfPeriod) {
|
||||
// lowerDate is in the current month
|
||||
lowerDate.setDate(monthDate);
|
||||
} else if (!isFirstDayOfPeriod) {
|
||||
// lowerDate is on the previous month
|
||||
var LAST_DAY_OF_PREVIOUS_MONTH = 0;
|
||||
var newMonth = today.getMonth() - 1;
|
||||
var newYear = today.getFullYear();
|
||||
if (newMonth < 0) {
|
||||
newMonth = 11;
|
||||
newYear--;
|
||||
}
|
||||
|
||||
lowerDate = Toolkit.toMidnight(new Date(newYear, newMonth, monthDate));
|
||||
// The day of the month of lowerDate is different to settings.resetTime
|
||||
// value when the resetTime day doesn't exists this month, (eg. 30th
|
||||
// February), on this case, the lowerDate must be the last day of the
|
||||
// previous month
|
||||
if (lowerDate.getDate() != monthDate) {
|
||||
lowerDate = Toolkit.toMidnight(new Date());
|
||||
lowerDate.setDate(LAST_DAY_OF_PREVIOUS_MONTH);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var lastReset = settings.lastCompleteDataReset || lowerDate;
|
||||
lowerDate = lastReset;
|
||||
var offset = today.getTime() - lastReset.getTime();
|
||||
if (offset >= NEVER_ANCHOR) {
|
||||
lowerDate = new Date(today.getTime() - NEVER_ANCHOR);
|
||||
}
|
||||
}
|
||||
|
||||
debug('Lower date:', lowerDate);
|
||||
return lowerDate;
|
||||
}
|
||||
|
||||
// Expand the model with some computed values
|
||||
function expandModel(base) {
|
||||
|
||||
// Update today
|
||||
var today = Toolkit.toMidnight(new Date());
|
||||
|
||||
// Graphic settings
|
||||
base.originY = Math.floor(base.height * CHART_BG_RATIO);
|
||||
|
||||
// Today value
|
||||
base.axis.X.today = today;
|
||||
|
||||
// Normalize today
|
||||
Toolkit.toMidnight(base.axis.X.today);
|
||||
Toolkit.toMidnight(base.axis.X.lower);
|
||||
Toolkit.toMidnight(base.axis.X.upper);
|
||||
|
||||
// X axis projection function to convert a value into a pixel value
|
||||
var xLowerBound = base.axis.X.lower.getTime();
|
||||
var xSize = base.axis.X.upper.getTime() - xLowerBound;
|
||||
var realWidth = base.endX - base.originX;
|
||||
base.axis.X.len = realWidth;
|
||||
base.axis.X.get = function cc_dataToXPx(value) {
|
||||
var projection = (value.getTime() - xLowerBound) / xSize;
|
||||
return projection * realWidth + base.originX;
|
||||
};
|
||||
|
||||
// Y max value
|
||||
var limitEnabled = true; // XXX: model.limits.enabled;
|
||||
base.axis.Y.maxValue = Math.max(limitEnabled ? base.limits.value : 0,
|
||||
base.data.mobile.total,
|
||||
base.data.wifi.total);
|
||||
|
||||
// Y axis projection function and automatic values
|
||||
base.axis.Y.range = base.axis.Y.upper - base.axis.Y.lower;
|
||||
base.axis.Y.upper = (1 + base.axis.Y.margin) * base.axis.Y.maxValue;
|
||||
var yLowerBound = base.axis.Y.lower;
|
||||
var ySize = base.axis.Y.upper - yLowerBound;
|
||||
base.axis.Y.get = function cc_dataToYPx(value) {
|
||||
var projection = (value - yLowerBound) / ySize;
|
||||
return base.originY * (1 - projection);
|
||||
};
|
||||
base.axis.Y.step = base.axis.Y.get(base.axis.Y.maxValue);
|
||||
|
||||
// Limits
|
||||
base.limits.warning = Common.DATA_USAGE_WARNING;
|
||||
base.limits.warningValue = base.limits.value * Common.DATA_USAGE_WARNING;
|
||||
}
|
||||
|
||||
// Check if the segment of the graph is inside chart area. If so, draw it
|
||||
function clipAndDrawSegment(ctx, model, x0, y0, x1, y1) {
|
||||
if (x0 >= model.originX && x1 <= model.endX) {
|
||||
var x0Fixed = Math.floor(x0) - 0.5;
|
||||
var x1Fixed = Math.floor(x1) + 0.5;
|
||||
|
||||
// Fill
|
||||
ctx.globalCompositeOperation = 'destination-over';
|
||||
ctx.beginPath();
|
||||
ctx.lineTo(x1Fixed, y1);
|
||||
ctx.lineTo(x1Fixed, model.originY);
|
||||
ctx.lineTo(x0Fixed, model.originY);
|
||||
ctx.lineTo(x0Fixed, y0);
|
||||
ctx.moveTo(x1Fixed, y0);
|
||||
ctx.fill();
|
||||
|
||||
// Stroke
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
ctx.beginPath();
|
||||
// It's necessary add 1 to the X coordinate to make up for the offset
|
||||
// produced with the drawing of the previous line.
|
||||
ctx.moveTo(x0Fixed + 1, y0);
|
||||
ctx.lineTo(x1Fixed, y1);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
function drawTodayMark(ctx, x, y, color) {
|
||||
ctx.save();
|
||||
var radius = toDevicePixels(4);
|
||||
ctx.fillStyle = color;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, radius, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
function drawBackgroundLayer(canvas, model, showMobile) {
|
||||
canvas.height = model.height;
|
||||
var width = canvas.width = model.width;
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.save();
|
||||
|
||||
// White bg
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillRect(0, 0, width, model.originY);
|
||||
|
||||
// Horizontal lines every step
|
||||
var step = model.axis.Y.step;
|
||||
var limitY = model.axis.Y.get(model.limits.value);
|
||||
ctx.strokeStyle = '#e0e0e0';
|
||||
ctx.lineWidth = toDevicePixels(1);
|
||||
var displayLimit = model.limits.enabled && showMobile;
|
||||
for (var y = model.originY - step; y > step; y -= step) {
|
||||
if (displayLimit && same(y, limitY, 0.1)) {
|
||||
continue;
|
||||
}
|
||||
var drawY = Math.floor(y) - 0.5;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(model.originX, drawY);
|
||||
ctx.lineTo(model.endX, drawY);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
// Vertical lines every day
|
||||
var days = (model.axis.X.upper - model.axis.X.lower) / DAY;
|
||||
step = model.axis.X.len / days;
|
||||
ctx.strokeStyle = '#eeeeee';
|
||||
ctx.lineWidth = toDevicePixels(1);
|
||||
for (var x = model.originX; x <= model.endX; x += step) {
|
||||
var drawX = Math.floor(x) + 0.5;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(drawX, model.originY);
|
||||
ctx.lineTo(drawX, 0);
|
||||
ctx.stroke();
|
||||
// Ensure draw the last vertical line
|
||||
if (((x + step) > model.endX) && (x !== model.endX)) {
|
||||
// the 0.5 offset is needed to avoid drawing a double line.
|
||||
drawX = model.endX - 0.5;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(drawX, model.originY);
|
||||
ctx.lineTo(drawX, 0);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
|
||||
// Return true if a and b not differ more than threshold
|
||||
function same(a, b, threshold) {
|
||||
threshold = threshold || 0;
|
||||
return Math.abs(a - b) <= threshold;
|
||||
}
|
||||
}
|
||||
|
||||
function drawTodayLayer(canvas, model) {
|
||||
canvas.height = model.height;
|
||||
canvas.width = model.width;
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// Compute the X offset
|
||||
var offsetX = model.axis.X.get(model.axis.X.today);
|
||||
|
||||
// Configure Centered today text
|
||||
var marginTop = toDevicePixels(10);
|
||||
|
||||
var todayTag = formatChartDate(model.axis.X.today);
|
||||
|
||||
// Render the text
|
||||
ctx.font = makeCSSFontString(FONT_SIZE, FONT_WEIGHT);
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
|
||||
// Update measues of today label
|
||||
var metrics = ctx.measureText(todayTag);
|
||||
model.todayLabel.x0 = offsetX - metrics.width / 2;
|
||||
model.todayLabel.x1 = offsetX + metrics.width / 2;
|
||||
if (model.todayLabel.x1 > model.endX) {
|
||||
ctx.textAlign = 'right';
|
||||
}
|
||||
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.fillText(todayTag, offsetX, model.originY + marginTop);
|
||||
|
||||
setAccessibilityAttributes(canvas, 'today-layer', { today: todayTag });
|
||||
}
|
||||
|
||||
function drawAxisLayer(canvas, model, showMobile) {
|
||||
canvas.height = model.height;
|
||||
canvas.width = model.width;
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// Start drawing Y axis
|
||||
var step = model.axis.Y.step;
|
||||
var dataStep = model.axis.Y.upper - model.axis.Y.maxValue;
|
||||
var marginRight = 4;
|
||||
var offsetX = model.originX - marginRight;
|
||||
ctx.font = makeCSSFontString(FONT_SIZE, FONT_WEIGHT_AXIS);
|
||||
ctx.textAlign = 'right';
|
||||
var displayLimit = showMobile && model.limits.enabled;
|
||||
var lastUnit;
|
||||
for (var y = 0.5 + model.originY, value = 0;
|
||||
y > step; y -= step, value += dataStep) {
|
||||
|
||||
// First X label for 0 is aligned with the bottom
|
||||
if (value === 0) {
|
||||
lastUnit = Formatting.smartRound(dataStep, 0)[1];
|
||||
ctx.textBaseline = 'bottom';
|
||||
ctx.fillStyle = '#6a6a6a';
|
||||
ctx.fillText(Formatting.formatData([0, lastUnit]), offsetX, y - 2.5);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Rest of labels are aligned with the middle
|
||||
var rounded = Formatting.smartRound(value, -1);
|
||||
var v = rounded[0];
|
||||
var u = rounded[1];
|
||||
var label = v;
|
||||
if (lastUnit !== u) {
|
||||
label = Formatting.formatData([v, u]);
|
||||
}
|
||||
|
||||
lastUnit = u;
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillStyle = displayLimit &&
|
||||
(value === model.limits.value) &&
|
||||
model.limits.enabled ?
|
||||
'#b50202' : '#6a6a6a';
|
||||
ctx.fillText(label, offsetX, y);
|
||||
}
|
||||
|
||||
// Now the X axis
|
||||
ctx.fillStyle = '#6a6a6a';
|
||||
var marginTop = toDevicePixels(10);
|
||||
|
||||
// Left tag
|
||||
var leftTag = formatChartDate(model.axis.X.lower);
|
||||
ctx.font = makeCSSFontString(FONT_SIZE, FONT_WEIGHT);
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.textAlign = 'left';
|
||||
|
||||
var isBelowToday = model.todayLabel.x0 <=
|
||||
model.originX + ctx.measureText(leftTag).width;
|
||||
if (!isBelowToday) {
|
||||
ctx.fillText(leftTag, model.originX, model.originY + marginTop);
|
||||
}
|
||||
|
||||
// Right tag
|
||||
var rightTag = formatChartDate(model.axis.X.upper);
|
||||
ctx.textAlign = 'right';
|
||||
|
||||
isBelowToday = model.todayLabel.x1 >=
|
||||
model.endX - ctx.measureText(rightTag).width;
|
||||
if (!isBelowToday) {
|
||||
ctx.fillText(rightTag, model.endX, model.originY + marginTop);
|
||||
}
|
||||
|
||||
setAccessibilityAttributes(canvas, 'axis-layer',
|
||||
{ from: leftTag, to: rightTag });
|
||||
}
|
||||
|
||||
function setAccessibilityAttributes(element, identifier, data) {
|
||||
if (identifier) {
|
||||
element.setAttribute('data-l10n-id', identifier);
|
||||
if (data) {
|
||||
element.setAttribute('data-l10n-args', JSON.stringify(data));
|
||||
}
|
||||
} else {
|
||||
element.removeAttribute('data-l10n-id');
|
||||
element.removeAttribute('data-l10n-args');
|
||||
element.removeAttribute('aria-label');
|
||||
}
|
||||
}
|
||||
|
||||
function drawLimits(canvas, model, showMobile) {
|
||||
var set = model.limits.value;
|
||||
var color = '#b50202';
|
||||
|
||||
canvas.height = model.height;
|
||||
canvas.width = model.width;
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
var displayLimit = showMobile && model.limits.enabled;
|
||||
if (!displayLimit) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
|
||||
var marginTop = 1;
|
||||
var offsetY = set ? model.axis.Y.get(model.limits.value) :
|
||||
FONT_SIZE + 2 * marginTop;
|
||||
|
||||
ctx.font = makeCSSFontString(FONT_SIZE, FONT_WEIGHT);
|
||||
|
||||
// The dashed limit line
|
||||
var lineLength = toDevicePixels(15);
|
||||
var gapLength = toDevicePixels(7);
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = toDevicePixels(1);
|
||||
ctx.beginPath();
|
||||
for (var x = model.originX, drawY = Math.floor(offsetY) - 0.5;
|
||||
x < model.endX; x += gapLength) {
|
||||
ctx.moveTo(x, drawY);
|
||||
ctx.lineTo(Math.min(x += lineLength, model.endX), drawY);
|
||||
}
|
||||
ctx.stroke();
|
||||
|
||||
ctx.restore();
|
||||
|
||||
setAccessibilityAttributes(canvas,
|
||||
'limit-layer-' + model.limits.dataLimitUnit,
|
||||
{ value: model.limits.dataLimitValue });
|
||||
}
|
||||
|
||||
function drawDataLayer(canvas, model, sampleType, style) {
|
||||
var samples = (model.data[sampleType] || {}).samples;
|
||||
if (!samples) {
|
||||
return;
|
||||
}
|
||||
|
||||
canvas.height = model.height;
|
||||
canvas.width = model.width;
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// Style
|
||||
ctx.fillStyle = style.fill;
|
||||
ctx.strokeStyle = style.stroke;
|
||||
ctx.lineWidth = toDevicePixels(2);
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.moveTo(model.originX, model.originY);
|
||||
|
||||
var today = Toolkit.toMidnight(new Date());
|
||||
// offset in milliseconds
|
||||
var offset = today.getTimezoneOffset() * 60 * 1000;
|
||||
|
||||
var sum = 0; var x, y = model.originY;
|
||||
var lastX = model.originX, lastY = model.axis.Y.get(sum);
|
||||
// Only dealing with the use cases of negative UTC offset because, due to
|
||||
// the database granularity, the returned samples are given in UTC days, and
|
||||
// we don't know what part of the traffic sample values correspond to the
|
||||
// current localtime day. The query for the samples is generated on the
|
||||
// costcontrol module, and the case into which the returned samples only
|
||||
// have one record with the data for the localtime day of yesterday is not
|
||||
// possible.
|
||||
|
||||
for (var i = 0, len = samples.length; i < len; i++) {
|
||||
var sample = samples[i];
|
||||
var sampleLocalTime = sample.date.getTime() + offset;
|
||||
var sampleUTCDate = Toolkit.toMidnight(new Date(sampleLocalTime));
|
||||
|
||||
var isToday = (today.getTime() === sampleUTCDate.getTime());
|
||||
var isTomorrow = (today.getTime() + DAY === sampleUTCDate.getTime());
|
||||
var thereIsATomorrowSample = (isToday && (i + 2 === len));
|
||||
// Depends on the hour of the day and the offset, it is possible the
|
||||
// networkStats API returns the current data mobile in the tomorrow
|
||||
// sample, because on the UTC hour is another day.
|
||||
if (thereIsATomorrowSample) {
|
||||
// Join the value of the samples for today and tomorrow
|
||||
var tomorrowSample = samples[i+1];
|
||||
if (typeof sample.value === 'undefined') {
|
||||
sample.value = tomorrowSample.value;
|
||||
} else if (typeof tomorrowSample.value !== 'undefined') {
|
||||
sample.value += tomorrowSample.value;
|
||||
}
|
||||
|
||||
if (i === 0) {
|
||||
lastX = model.axis.X.get(sample.date);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (typeof sample.value === 'undefined') {
|
||||
lastX = x = model.axis.X.get(sample.date);
|
||||
ctx.moveTo(x, y);
|
||||
|
||||
} else {
|
||||
if (i === 0) {
|
||||
lastX = model.axis.X.get(sample.date);
|
||||
}
|
||||
|
||||
sum += sample.value;
|
||||
x = model.axis.X.get(sample.date);
|
||||
y = model.axis.Y.get(sum);
|
||||
|
||||
clipAndDrawSegment(ctx, model, lastX, lastY, x, y);
|
||||
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
}
|
||||
|
||||
var onlyExistTomorrowSample = (i===0 && isTomorrow);
|
||||
var isXInsideTheGraph = (x >= model.originX);
|
||||
if ((isToday || onlyExistTomorrowSample) && isXInsideTheGraph) {
|
||||
drawTodayMark(ctx, x, y, style.stroke);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!style.pattern) {
|
||||
return;
|
||||
}
|
||||
|
||||
var pattern = ctx.createPattern(style.pattern, 'repeat');
|
||||
ctx.globalCompositeOperation = 'source-atop';
|
||||
ctx.fillStyle = pattern;
|
||||
ctx.fillRect(0, 0, model.width, model.originY);
|
||||
}
|
||||
|
||||
function drawWarningLayer(canvas, model) {
|
||||
canvas.height = model.height;
|
||||
canvas.width = model.width;
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
if (!model.limits.enabled || model.limits.value === null) {
|
||||
setAccessibilityAttributes(canvas);
|
||||
return;
|
||||
}
|
||||
|
||||
// No problem here
|
||||
var mobileUsage = model.data.mobile.total;
|
||||
var mobileUsageDifference = mobileUsage - model.limits.value;
|
||||
if (mobileUsage <= model.limits.warningValue) {
|
||||
setAccessibilityAttributes(canvas);
|
||||
return;
|
||||
}
|
||||
|
||||
// Warning mode
|
||||
if (mobileUsage <= model.limits.value) {
|
||||
var limitValue = Math.floor(model.axis.Y.get(model.limits.value));
|
||||
var warningValue =
|
||||
Math.round(model.axis.Y.get(model.limits.warningValue));
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = 'rgba(255, 112, 0, 0.5)';
|
||||
ctx.fillRect(
|
||||
model.originX, limitValue,
|
||||
model.axis.X.len + 0.5, warningValue - limitValue
|
||||
);
|
||||
|
||||
setAccessibilityAttributes(canvas, 'warning-layer', {
|
||||
value: Formatting.formatData(Formatting.roundData(
|
||||
-mobileUsageDifference))
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Limit exceeded
|
||||
var limitValueExceeded = model.axis.Y.get(model.limits.value);
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = 'rgba(255, 0, 0, 0.3)';
|
||||
ctx.fillRect(
|
||||
model.originX, 0,
|
||||
model.axis.X.len + 0.5, limitValueExceeded
|
||||
);
|
||||
setAccessibilityAttributes(canvas, 'limit-exceeded-layer', {
|
||||
value: Formatting.formatData(Formatting.roundData(mobileUsageDifference))
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
// Constants
|
||||
WIFI_CHART_STROKE: WIFI_CHART_STROKE,
|
||||
WIFI_CHART_FILL: WIFI_CHART_FILL,
|
||||
MOBILE_CHART_STROKE: MOBILE_CHART_STROKE,
|
||||
MOBILE_CHART_FILL: MOBILE_CHART_FILL,
|
||||
|
||||
// Functions
|
||||
toDevicePixels: toDevicePixels,
|
||||
makeCSSFontString: makeCSSFontString,
|
||||
formatChartDate: formatChartDate,
|
||||
getLimitInBytes: getLimitInBytes,
|
||||
calculateUpperDate: calculateUpperDate,
|
||||
calculateLowerDate: calculateLowerDate,
|
||||
expandModel: expandModel,
|
||||
clipAndDrawSegment: clipAndDrawSegment,
|
||||
drawTodayMark: drawTodayMark,
|
||||
drawBackgroundLayer: drawBackgroundLayer,
|
||||
drawTodayLayer: drawTodayLayer,
|
||||
drawAxisLayer: drawAxisLayer,
|
||||
drawLimits: drawLimits,
|
||||
drawDataLayer: drawDataLayer,
|
||||
drawWarningLayer: drawWarningLayer
|
||||
};
|
||||
}());
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
;'use strict';var DEBUGGING=false;var debug=(function(){var SEQ_ID=0;var PROCESS_ID=Date.now();var DEBUG_PREFIX='CC';return function _debug(){if(!DEBUGGING){return;}
|
||||
var currentWindow=window;var parents=[];while(currentWindow!==currentWindow.parent){parents.push(currentWindow.location.pathname);currentWindow=currentWindow.parent;}
|
||||
parents.push(currentWindow.location.pathname);parents=parents.reverse().join('>')+':';var uId=PROCESS_ID;var message=['('+uId+'-'+(SEQ_ID++)+')',DEBUG_PREFIX,parents];for(var i=0,len=arguments.length,obj;i<len;i++){obj=arguments[i];message.push(typeof obj==='object'?JSON.stringify(obj):obj);}
|
||||
if(window.dump){message.push('\n');window.dump(message.join(' '));}else if(console&&console.log){console.log(message.join(' '));}};}());
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
;'use strict';var Formatting=(function(){var MINUTE=60*1000;var HOUR=60*MINUTE;var DAY=24*HOUR;function getDaysOfDifference(a,b){return Math.floor((a.getTime()-b.getTime())/DAY);}
|
||||
function getFormattedDate(timestamp,formatter){return formatter.format(timestamp);}
|
||||
function formatTime(timestamp,formatter){if(!timestamp){return _('never');}
|
||||
var now=new Date(),then=new Date(timestamp);if(formatter){return getFormattedDate(then,formatter);}
|
||||
var date,time;var daysOfDifference=getDaysOfDifference(now,then);if(daysOfDifference===0){date=_('today');}else if(daysOfDifference===1){date=_('yesterday');}else{date=getFormattedDate(timestamp,Formatting.formatters.shortWeekday);}
|
||||
time=getFormattedDate(timestamp,Formatting.formatters.shortTime);return _('day-hour-format',{day:date,time:time});}
|
||||
function formatTimeSinceNow(timestamp){var now=new Date(),then=new Date(timestamp);var formattedTime=formatTime(timestamp);if(getDaysOfDifference(now,then)>0){return formattedTime;}
|
||||
var age=now-then;if(age<MINUTE){formattedTime=_('minutes-ago-short',{value:0});}else if(age<HOUR){var minutes=Math.floor(age/MINUTE);formattedTime=_('minutes-ago-short',{value:minutes});}else if(age<DAY){var hours=Math.floor(age/HOUR);formattedTime=_('hours-ago-short',{value:hours});}
|
||||
return formattedTime;}
|
||||
function formatData(dataArray){return isNaN(dataArray[0])?'':_('magnitude',{value:dataArray[0],unit:dataArray[1]});}
|
||||
function roundData(value,positions){positions=(typeof positions==='undefined')?2:positions;if(value<1000){return[value.toFixed(positions),_('B')];}
|
||||
if(value<1000000){return[(value/1000).toFixed(positions),_('KB')];}
|
||||
if(value<1000000000){return[(value/1000000).toFixed(positions),_('MB')];}
|
||||
return[(value/1000000000).toFixed(positions),_('GB')];}
|
||||
function getPositions(value,deltaPositions){deltaPositions=(typeof deltaPositions==='undefined')?0:deltaPositions;if(parseInt(value)===value){return 0;}
|
||||
if(value<10){return 2+deltaPositions;}
|
||||
if(value<100){return 1+deltaPositions;}
|
||||
return 0;}
|
||||
function smartRound(value,deltaPositions){deltaPositions=(typeof deltaPositions==='undefined')?0:deltaPositions;if(value<1000){var bPositions=getPositions(value,deltaPositions);return[value.toFixed(bPositions),_('B')];}
|
||||
if(value<1000000){var kbytes=value/1000;var kbPositions=getPositions(kbytes,deltaPositions);return[kbytes.toFixed(kbPositions),_('KB')];}
|
||||
if(value<1000000000){var mbytes=value/1000000;var mPositions=getPositions(mbytes,deltaPositions);return[mbytes.toFixed(mPositions),_('MB')];}
|
||||
var gbytes=value/1000000000;var gPositions=getPositions(gbytes,deltaPositions);return[gbytes.toFixed(gPositions),_('GB')];}
|
||||
function formatTimeHTML(timestampA,timestampB){function timeElement(content){var time=document.createElement('time');time.textContent=content;return time;}
|
||||
var fragment=document.createDocumentFragment();if(typeof timestampB==='undefined'){fragment.appendChild(timeElement(Formatting.formatTime(timestampA)));return fragment;}
|
||||
var dateA=new Date(timestampA);var dateB=new Date(timestampB);if(dateA.getFullYear()===dateB.getFullYear()&&dateA.getMonth()===dateB.getMonth()&&dateA.getDay()===dateB.getDay()){return formatTimeHTML(timestampB);}
|
||||
fragment.appendChild(timeElement(Formatting.formatTime(timestampA,Formatting.formatters.shortDate)));fragment.appendChild(document.createTextNode(' – '));fragment.appendChild(timeElement(Formatting.formatTime(timestampB)));return fragment;}
|
||||
function computeTelephonyMinutes(activity){return Math.ceil(activity.calltime/60000);}
|
||||
return{getFormattedDate:getFormattedDate,formatTime:formatTime,formatTimeSinceNow:formatTimeSinceNow,formatData:formatData,roundData:roundData,getPositions:getPositions,smartRound:smartRound,formatTimeHTML:formatTimeHTML,computeTelephonyMinutes:computeTelephonyMinutes,formatters:{}};}());function setFormatters(){const locales=navigator.languages;Formatting.formatters.longDate=Intl.DateTimeFormat(locales,{month:'long',day:'numeric',year:'numeric'});Formatting.formatters.shortDate=Intl.DateTimeFormat(locales,{month:'short',day:'numeric',});Formatting.formatters.shortTime=Intl.DateTimeFormat(locales,{hour12:navigator.mozHour12,hour:'numeric',minute:'numeric'});Formatting.formatters.shortWeekday=Intl.DateTimeFormat(locales,{weekday:'short'});}
|
||||
setFormatters();window.addEventListener('languagechange',setFormatters,false);window.addEventListener('timeformatchange',setFormatters,false);
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
;'use strict';var _=function cc_fallbackTranslation(keystring){var r=window.navigator.mozL10n.get.apply(this,arguments);return r||(DEBUGGING?'!!':'')+keystring;};function deepCopy(object){if(object===null||!(object instanceof Object)){return object;}
|
||||
var clone,constructor=object.constructor;switch(constructor){case Date:clone=new constructor(object.getTime());break;default:clone=constructor();break;}
|
||||
for(var key in object){if(object.hasOwnProperty(key)){clone[key]=deepCopy(object[key]);}}
|
||||
return clone;}
|
||||
var Toolkit={checkEnoughDelay:function(threshold,dateA,dateB){if(!dateA){return true;}
|
||||
var end=dateB||new Date();return(end.getTime()-dateA.getTime())>threshold;},toMidnight:function _toMidnight(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0);return date;}};
|
||||
255
assets/webapps/costcontrol.gaiamobile.org/js/view_manager.js
Normal file
255
assets/webapps/costcontrol.gaiamobile.org/js/view_manager.js
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/* global AccessibilityHelper, LazyLoader */
|
||||
/* exported ViewManager */
|
||||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
|
||||
'use strict';
|
||||
|
||||
var ViewManager = (function() {
|
||||
|
||||
// The ViewManager is in charge of simply manage the different views of the
|
||||
// applications. ViewManager.changeViewTo() valid values are listed above
|
||||
// these lines.
|
||||
function ViewManager(tabs) {
|
||||
tabs = tabs || [];
|
||||
|
||||
this._tabs = {};
|
||||
tabs.forEach(function _registerTab(tabItem) {
|
||||
if (typeof tabItem !== 'object') {
|
||||
tabItem = { id: tabItem };
|
||||
}
|
||||
this._tabs[tabItem.id] = tabItem.tab || 'left';
|
||||
}, this);
|
||||
|
||||
this._currentView = null;
|
||||
this._currentTab = null;
|
||||
|
||||
}
|
||||
|
||||
// Return true if the passed view is a tab
|
||||
ViewManager.prototype._isTab = function _isTab(view) {
|
||||
return this._tabs.hasOwnProperty(view);
|
||||
};
|
||||
|
||||
// Make target enter screen's main area and call callback after, passing as
|
||||
// arguments if the new view is a tab, the new view id and a third parameter
|
||||
// depending on if the view was a tab or not:
|
||||
// If it is a tab: it returns the current overlay view id or null
|
||||
// If it is not a tab: it returns the previous ovrlay view or null
|
||||
ViewManager.prototype.changeViewTo = function _changeViewTo(viewHash,
|
||||
obstructed,
|
||||
callback) {
|
||||
var hashParts = viewHash.split('?');
|
||||
var viewId = hashParts[0];
|
||||
if (this.isCurrentView(viewId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note here how we set the same value with different semantincs.
|
||||
// This is used at the end of the function and the names are the correct
|
||||
// because, depending on if the view is a tab or not, semantics may change.
|
||||
var previousViewId, currentViewId;
|
||||
previousViewId = currentViewId = this._currentView ?
|
||||
this._currentView.id : null;
|
||||
|
||||
var view = document.getElementById(viewId);
|
||||
var params = parseQueryParams(hashParts[1]);
|
||||
var self = this;
|
||||
|
||||
// lazy load HTML of the panel
|
||||
this.loadPanel(view, function() {
|
||||
// Tabs are treated in a different way than overlay views
|
||||
var isTab = self._isTab(viewId);
|
||||
if (isTab) {
|
||||
|
||||
// Disposing the current view
|
||||
var disposingTab = null;
|
||||
if (self._currentTab) {
|
||||
disposingTab = document.getElementById(self._currentTab);
|
||||
}
|
||||
if (disposingTab) {
|
||||
disposingTab.dataset.viewport = self._tabs[disposingTab.id];
|
||||
document.getElementById(disposingTab.id + '-filter').classList.remove(
|
||||
'.selected');
|
||||
}
|
||||
// Showing the new one
|
||||
view.dataset.viewport = '';
|
||||
document.getElementById(view.id + '-filter').classList.add('.selected');
|
||||
AccessibilityHelper.setAriaSelected(
|
||||
document.getElementById(view.id + '-control'),
|
||||
document.querySelectorAll('[role="tab"]'));
|
||||
|
||||
self._currentTab = viewId;
|
||||
|
||||
// Overlay view
|
||||
} else {
|
||||
self.closeCurrentView();
|
||||
previousViewId = self._currentView ? self._currentView.id : '';
|
||||
self._currentView = {
|
||||
id: viewId,
|
||||
defaultViewport: view.dataset.viewport,
|
||||
obstructed: obstructed
|
||||
};
|
||||
|
||||
// With a combination of CSS, we actually animate and display the view
|
||||
delete view.dataset.viewport;
|
||||
if (obstructed) {
|
||||
document.querySelector(obstructed).classList.add('behind');
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(isTab, viewId, isTab ? currentViewId : previousViewId);
|
||||
}
|
||||
notifyViewChange(isTab, viewId, params);
|
||||
});
|
||||
};
|
||||
|
||||
function notifyViewChange(isTab, current, params) {
|
||||
var type = isTab ? 'tabchanged' : 'viewchanged';
|
||||
var event = new CustomEvent(type, {
|
||||
detail: {
|
||||
id: current,
|
||||
params: params
|
||||
}
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
ViewManager.prototype.loadPanel = function _loadPanel(panel, callback) {
|
||||
if (!panel || panel.hidden === false) {
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LazyLoader.load(panel, function() {
|
||||
var resourceRemaining = 0;
|
||||
|
||||
function loadResource(node) {
|
||||
node.onload = onResourceLoaded;
|
||||
document.head.appendChild(node);
|
||||
resourceRemaining++;
|
||||
}
|
||||
|
||||
// activate all styles
|
||||
Array.from(panel.querySelectorAll('link')).forEach((node) => {
|
||||
if (!document.querySelector('head > link[href="' + node.href + '"]')) {
|
||||
var styleLink = document.createElement('link');
|
||||
styleLink.href = node.href;
|
||||
styleLink.media = node.media;
|
||||
styleLink.rel = node.rel;
|
||||
styleLink.type = node.type;
|
||||
|
||||
loadResource(styleLink);
|
||||
}
|
||||
node.remove();
|
||||
});
|
||||
|
||||
// activate all scripts
|
||||
Array.from(panel.querySelectorAll('script')).forEach((node) => {
|
||||
if (!document.querySelector('head > script[src="' + node.src + '"]')) {
|
||||
var scriptLink = document.createElement('script');
|
||||
scriptLink.src = node.src;
|
||||
scriptLink.type = node.type;
|
||||
|
||||
loadResource(scriptLink);
|
||||
}
|
||||
node.remove();
|
||||
});
|
||||
|
||||
// add listeners
|
||||
var headers = Array.from(
|
||||
panel.querySelectorAll('gaia-header[action="close"]')
|
||||
);
|
||||
headers.forEach((headerWithClose) => {
|
||||
headerWithClose.addEventListener('action', function() {
|
||||
window.parent.location.hash = '#';
|
||||
});
|
||||
});
|
||||
|
||||
panel.hidden = false;
|
||||
|
||||
checkCallback();
|
||||
|
||||
function checkCallback() {
|
||||
if (resourceRemaining === 0 && typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
function onResourceLoaded() {
|
||||
resourceRemaining--;
|
||||
checkCallback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Close the current view returning to the previous one
|
||||
ViewManager.prototype.closeCurrentView = function _closeCurrentView() {
|
||||
if (!this._currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
var view = document.getElementById(this._currentView.id);
|
||||
|
||||
// With a combination of CSS, Restoring the last viewport we actually
|
||||
// animate and hide the current view
|
||||
view.dataset.viewport = this._currentView.defaultViewport;
|
||||
|
||||
if (this._currentView.obstructed) {
|
||||
var obstructed = document.querySelector(this._currentView.obstructed);
|
||||
obstructed.classList.remove('behind');
|
||||
}
|
||||
this._currentView = null;
|
||||
};
|
||||
|
||||
// Test if the current view is the one passed as parameter
|
||||
ViewManager.prototype.isCurrentView = function _isCurrentView(view) {
|
||||
return this._currentView && this._currentView.id === view;
|
||||
};
|
||||
|
||||
// Return the current view id or null if not current view
|
||||
ViewManager.prototype.getCurrentView = function _getCurrentView() {
|
||||
return this._currentView ? this._currentView.id : null;
|
||||
};
|
||||
|
||||
// Return true if the tab id passed is the current tab
|
||||
ViewManager.prototype.isCurrentTab = function _isCurrentTab(tab) {
|
||||
return this._currentTab && this._currentTab === tab;
|
||||
};
|
||||
|
||||
// Return the current tab
|
||||
ViewManager.prototype.getCurrentTab = function _getCurrentTab() {
|
||||
return this._currentTab;
|
||||
};
|
||||
|
||||
function parseQueryParams(queryParams) {
|
||||
var params = {};
|
||||
|
||||
queryParams = (queryParams || '').split('&');
|
||||
queryParams.forEach(function(param) {
|
||||
if (!param) { return; }
|
||||
|
||||
var pair = param.split('=');
|
||||
var key = pair[0];
|
||||
var value = pair[1];
|
||||
|
||||
if (params[key]) {
|
||||
if (!Array.isArray(params[key])) {
|
||||
params[key] = [params[key]];
|
||||
}
|
||||
|
||||
params[key].push(value);
|
||||
return;
|
||||
}
|
||||
|
||||
params[key] = value;
|
||||
});
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
return ViewManager;
|
||||
}());
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/* exported BalanceLowLimitView */
|
||||
'use strict';
|
||||
|
||||
function BalanceLowLimitView(lowLimitEnabler, lowLimitInput) {
|
||||
var self = this;
|
||||
|
||||
self._lowLimitEnabler = lowLimitEnabler;
|
||||
self._lowLimitInput = lowLimitInput;
|
||||
self._lowLimitEnabler.addEventListener('change', self);
|
||||
self._lowLimitInput.addEventListener('input', self);
|
||||
installProperties();
|
||||
self.validate();
|
||||
|
||||
function installProperties() {
|
||||
var disabled = false;
|
||||
Object.defineProperty(self, 'disabled', {
|
||||
get: function() {
|
||||
return disabled;
|
||||
},
|
||||
set: function(value) {
|
||||
disabled = value;
|
||||
self._lowLimitEnabler.disabled = disabled;
|
||||
self._lowLimitInput.disabled = disabled;
|
||||
self.validate();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
BalanceLowLimitView.prototype.handleEvent = function() {
|
||||
this.validate();
|
||||
};
|
||||
|
||||
BalanceLowLimitView.prototype.validate = function(e) {
|
||||
var numericValue = parseFloat(this._lowLimitInput.value, 10);
|
||||
|
||||
this._isValid = this.disabled || !this._lowLimitEnabler.checked ||
|
||||
!Number.isNaN(numericValue) && numericValue > 0;
|
||||
|
||||
this._lowLimitInput.classList[this._isValid ? 'remove' : 'add']('error');
|
||||
if (typeof this.onvalidation === 'function') {
|
||||
this.onvalidation({type: 'validation', isValid: this._isValid});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* global _, Formatting */
|
||||
/* exported BalanceView */
|
||||
'use strict';
|
||||
|
||||
function BalanceView(balanceLabel, timestampLabel, minimumDelay) {
|
||||
|
||||
minimumDelay = minimumDelay || 0;
|
||||
|
||||
var viewTimestamp;
|
||||
|
||||
var timeHighlightColors = [
|
||||
{threshold: minimumDelay / 3, className: 'first-third'},
|
||||
{threshold: 2 * minimumDelay / 3, className: 'second-third'},
|
||||
{threshold: minimumDelay, className: 'third-third'},
|
||||
{threshold: 24 * 60 * 60 * 1000, className: 'yesterday'},
|
||||
{threshold: Infinity, className: 'before'}
|
||||
];
|
||||
|
||||
function update(balanceResult, isUpdating) {
|
||||
if (!balanceResult) {
|
||||
setBalanceToNotAvailable();
|
||||
} else {
|
||||
updateBalance(balanceResult.balance, balanceResult.currency);
|
||||
updateTimestamp(balanceResult.timestamp, isUpdating);
|
||||
}
|
||||
}
|
||||
|
||||
function setBalanceToNotAvailable() {
|
||||
balanceLabel.setAttribute('data-l10n-id', 'not-available');
|
||||
timestampLabel.innerHTML = '';
|
||||
}
|
||||
|
||||
function updateBalance(balance, currencySymbol) {
|
||||
balanceLabel.textContent = _('currency', {
|
||||
value: balance,
|
||||
currency: currencySymbol
|
||||
});
|
||||
}
|
||||
|
||||
function updateTimeFormat() {
|
||||
updateTimestamp(viewTimestamp);
|
||||
}
|
||||
|
||||
function updateTimestamp(timestamp, isUpdating) {
|
||||
timestampLabel.innerHTML = '';
|
||||
viewTimestamp = timestamp;
|
||||
|
||||
if (isUpdating) {
|
||||
timestampLabel.setAttribute('data-l10n-id', 'updating-ellipsis');
|
||||
} else if (typeof timestamp !== 'undefined') {
|
||||
var time = getTimeTagFor(timestamp);
|
||||
timestampLabel.appendChild(time);
|
||||
time.classList.add(getHighlightColor(timestamp));
|
||||
}
|
||||
}
|
||||
|
||||
function getTimeTagFor(timestamp) {
|
||||
var time = document.createElement('time');
|
||||
time.setAttribute('datetime', timestamp.toISOString());
|
||||
time.textContent = Formatting.formatTimeSinceNow(timestamp);
|
||||
return time;
|
||||
}
|
||||
|
||||
function getHighlightColor(timestamp) {
|
||||
if (!minimumDelay) {
|
||||
return 'first-third';
|
||||
}
|
||||
|
||||
var now = new Date(), then = new Date(timestamp);
|
||||
var age = now - then;
|
||||
for (var i = 0, l = timeHighlightColors.length; i < l; i++) {
|
||||
var category = timeHighlightColors[i];
|
||||
if (age < category.threshold) {
|
||||
return category.className;
|
||||
}
|
||||
}
|
||||
return timeHighlightColors[l - 1].className;
|
||||
}
|
||||
|
||||
window.addEventListener('timeformatchange', updateTimeFormat);
|
||||
|
||||
this.update = update;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
'use strict';
|
||||
|
||||
/* global Common */
|
||||
|
||||
function ConfirmDialog(container, viewManager) {
|
||||
this.id = container.id;
|
||||
this.container = container;
|
||||
this.viewManager = viewManager;
|
||||
this.message = container.querySelector('p');
|
||||
|
||||
this.okButton = container.querySelector('.danger');
|
||||
|
||||
this.cancelButton = container.querySelector('.close-reset-dialog');
|
||||
this.cancelButton.onclick = this.closeConfirmDialog.bind(this);
|
||||
}
|
||||
|
||||
ConfirmDialog.prototype.setMessage = function(l10nId, data) {
|
||||
Common.localize(this.message, l10nId, data || {});
|
||||
};
|
||||
|
||||
ConfirmDialog.prototype.updateAcceptAction = function(acceptAction) {
|
||||
this.okButton.onclick = acceptAction;
|
||||
};
|
||||
|
||||
ConfirmDialog.prototype.showConfirmDialog = function() {
|
||||
this.viewManager.changeViewTo(this.id, '#settings-view');
|
||||
};
|
||||
|
||||
ConfirmDialog.prototype.closeConfirmDialog = function() {
|
||||
this.viewManager.closeCurrentView();
|
||||
};
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
'use strict';
|
||||
|
||||
/* global Common */
|
||||
/* global _ */
|
||||
|
||||
function NonReadyScreen(container) {
|
||||
this.id = container.id;
|
||||
this.container = container;
|
||||
this.activity = container.querySelector('progress');
|
||||
this.header = container.querySelector('h1');
|
||||
this.message = container.querySelector('p');
|
||||
this.button = container.querySelector('button');
|
||||
|
||||
this.button.onclick = Common.closeApplication;
|
||||
}
|
||||
|
||||
// Configure the non ready screen depending on the card status. For
|
||||
// absent, pinRequired and pukRequired, shows a message and give the
|
||||
// user the opportunity to close the app. For other states, it shows
|
||||
// a progress spinner.
|
||||
NonReadyScreen.prototype.updateForState = function(cardState) {
|
||||
switch (cardState) {
|
||||
case null:
|
||||
case 'absent':
|
||||
case 'unknown':
|
||||
case 'pinRequired':
|
||||
case 'pukRequired':
|
||||
case 'airplaneMode':
|
||||
this.setMessageMode(cardState);
|
||||
break;
|
||||
|
||||
default:
|
||||
this.setWaitingMode();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
NonReadyScreen.prototype.setMessageMode = function(cardState) {
|
||||
this.activity.hidden = true;
|
||||
[this.header, this.message, this.button.parentNode].forEach(function (el) {
|
||||
el.hidden = false;
|
||||
});
|
||||
|
||||
var messageId = this.getMessageIdFor(cardState);
|
||||
if (messageId) {
|
||||
var header = _('widget-' + messageId + '-heading');
|
||||
var msg = _('widget-' + messageId + '-meta');
|
||||
this.header.textContent = header;
|
||||
this.message.textContent = msg;
|
||||
}
|
||||
};
|
||||
|
||||
NonReadyScreen.prototype.setWaitingMode = function() {
|
||||
this.activity.hidden = false;
|
||||
[this.header, this.message, this.button.parentNode].forEach(function (el) {
|
||||
el.hidden = true;
|
||||
});
|
||||
};
|
||||
|
||||
NonReadyScreen.prototype.getMessageIdFor = function(cardState) {
|
||||
var message;
|
||||
|
||||
// SIM is absent
|
||||
if (!cardState || cardState === 'absent') {
|
||||
message = 'no-sim3';
|
||||
|
||||
// SIM is locked
|
||||
} else if (
|
||||
cardState === 'pinRequired' ||
|
||||
cardState === 'pukRequired'
|
||||
) {
|
||||
message = 'sim2-locked';
|
||||
} else if (cardState === 'airplaneMode') {
|
||||
message = 'airplane-mode';
|
||||
} else if (cardState === 'unknown') {
|
||||
message = 'unknown';
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
'use strict';
|
||||
|
||||
/* global Common, Settings, Formatting */
|
||||
|
||||
function ResetMenuDialog(container, viewManager) {
|
||||
this.id = container.id;
|
||||
this.container = container;
|
||||
this.viewManager = viewManager;
|
||||
this.dataUsage = {mobile:0, wifi:0};
|
||||
this.resetModes = ['wifi', 'mobile', 'all'];
|
||||
container.addEventListener('gaiamenu-cancel',
|
||||
this.closeResetMenuDialog.bind(this));
|
||||
}
|
||||
|
||||
ResetMenuDialog.prototype.initializeResetModes = function(confirmResetDialog) {
|
||||
this.resetModes.forEach(function(resetMode) {
|
||||
var newButton = document.createElement('button');
|
||||
newButton.id = 'reset-' + resetMode + '-data-usage';
|
||||
newButton.type = 'button';
|
||||
newButton.classList.add('reset-data-button');
|
||||
newButton.dataset.l10nId = 'reset-' + resetMode;
|
||||
newButton.onclick = function() {
|
||||
this.updateConfirmDialog(resetMode, confirmResetDialog);
|
||||
}.bind(this);
|
||||
this.container.appendChild(newButton);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ResetMenuDialog.prototype.updateConfirmDialog = function(type, confirmDialog) {
|
||||
var mobileUsage =
|
||||
Formatting.formatData(Formatting.roundData(this.dataUsage.mobile));
|
||||
var wifiUsage =
|
||||
Formatting.formatData(Formatting.roundData(this.dataUsage.wifi));
|
||||
var data = {
|
||||
mobileData: mobileUsage,
|
||||
wifiData: wifiUsage
|
||||
};
|
||||
var l10nId = 'reset-' + type + '-confirmation-warning';
|
||||
confirmDialog.setMessage(l10nId, data);
|
||||
function resetAction() {
|
||||
// Reset data type, take in count spent offsets to fix the charts
|
||||
Common.resetData(type);
|
||||
Settings.updateUI();
|
||||
confirmDialog.closeConfirmDialog();
|
||||
}
|
||||
confirmDialog.updateAcceptAction(resetAction);
|
||||
confirmDialog.showConfirmDialog();
|
||||
};
|
||||
|
||||
ResetMenuDialog.prototype.showResetMenuDialog = function(dataUsage) {
|
||||
this.dataUsage = dataUsage;
|
||||
this.viewManager.changeViewTo(this.id, '#settings-view');
|
||||
};
|
||||
|
||||
ResetMenuDialog.prototype.closeResetMenuDialog = function() {
|
||||
this.viewManager.closeCurrentView();
|
||||
};
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/* exported TopUpLayoutView */
|
||||
'use strict';
|
||||
|
||||
function TopUpLayoutView(ussdTopUpButton, codeTopUpButton) {
|
||||
|
||||
function setupLayout(topUpConfig) {
|
||||
var ussdTopUpDisabled = !topUpConfig || !topUpConfig.ussd_destination;
|
||||
var codeTopUpDisabled = !topUpConfig || !topUpConfig.destination;
|
||||
ussdTopUpButton.disabled = ussdTopUpDisabled;
|
||||
ussdTopUpButton.hidden = ussdTopUpDisabled;
|
||||
codeTopUpButton.disabled = codeTopUpDisabled;
|
||||
codeTopUpButton.hidden = codeTopUpDisabled;
|
||||
}
|
||||
|
||||
this.setupLayout = setupLayout;
|
||||
}
|
||||
261
assets/webapps/costcontrol.gaiamobile.org/js/views/appdetail.js
Normal file
261
assets/webapps/costcontrol.gaiamobile.org/js/views/appdetail.js
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
/* global _, debug, CostControl, Common, Formatting, ChartUtils,
|
||||
SimManager, ConfigManager */
|
||||
/* jshint -W120 */
|
||||
|
||||
/**
|
||||
* The App Detail view is in charge of usage charts and settings for an
|
||||
* individual app.
|
||||
*/
|
||||
'use strict';
|
||||
var AppDetailView = (function() {
|
||||
var costcontrol,
|
||||
initialized,
|
||||
els,
|
||||
app,
|
||||
localizedAppName,
|
||||
model;
|
||||
|
||||
function initialize() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
els = {};
|
||||
|
||||
CostControl.getInstance(function(instance) {
|
||||
costcontrol = instance;
|
||||
|
||||
// Get elements
|
||||
els.view = document.getElementById('appdetail-view');
|
||||
els.header = els.view.querySelector('gaia-header');
|
||||
els.headerHeading = els.header.querySelector('h1');
|
||||
els.usage = els.view.querySelector('.usage');
|
||||
els.graphicArea = els.usage.querySelector('#app-graphic-area');
|
||||
els.backgroundLayer =
|
||||
els.graphicArea.querySelector('#app-background-layer');
|
||||
els.wifiLayer = els.graphicArea.querySelector('#app-wifi-layer');
|
||||
els.mobileLayer = els.graphicArea.querySelector('#app-mobile-layer');
|
||||
els.axisLayer = els.graphicArea.querySelector('#app-axis-layer');
|
||||
els.todayLayer = els.graphicArea.querySelector('#app-today-layer');
|
||||
els.warningLayer = els.graphicArea.querySelector('#app-warning-layer');
|
||||
els.limitsLayer = els.graphicArea.querySelector('#app-limits-layer');
|
||||
els.graphicPattern =
|
||||
els.graphicArea.querySelector('#app-graphic-pattern');
|
||||
els.dataUsedSince =
|
||||
els.usage.querySelector('p[data-l10n-id="data-used-since"]');
|
||||
els.dataUsedThisWeek =
|
||||
els.usage.querySelector('p[data-l10n-id="data-used-this-week"]');
|
||||
els.dataUsedThisMonth =
|
||||
els.usage.querySelector('p[data-l10n-id="data-used-this-month"]');
|
||||
|
||||
// Setup the model
|
||||
SimManager.requestDataSimIcc(function(dataSimIcc) {
|
||||
ConfigManager.requestSettings(dataSimIcc.iccId,
|
||||
function _onSettings(settings) {
|
||||
debug('First time setup for model');
|
||||
model = {
|
||||
height: ChartUtils.toDevicePixels(els.graphicArea.clientHeight),
|
||||
width: ChartUtils.toDevicePixels(els.graphicArea.clientWidth),
|
||||
originX: Math.floor(
|
||||
ChartUtils.toDevicePixels(els.graphicArea.clientWidth) * 0.15),
|
||||
endX: Math.floor(
|
||||
ChartUtils.toDevicePixels(els.graphicArea.clientWidth) * 0.95),
|
||||
axis: {
|
||||
Y: {
|
||||
lower: 0,
|
||||
margin: 0.20
|
||||
},
|
||||
X: {
|
||||
lower: ChartUtils.calculateLowerDate(settings),
|
||||
upper: ChartUtils.calculateUpperDate(settings)
|
||||
}
|
||||
},
|
||||
limits: {
|
||||
enabled: settings.dataLimit,
|
||||
value: ChartUtils.getLimitInBytes(settings),
|
||||
dataLimitValue: settings.dataLimitValue,
|
||||
dataLimitUnit: settings.dataLimitUnit
|
||||
},
|
||||
data: {
|
||||
wifi: {
|
||||
enabled: true
|
||||
},
|
||||
mobile: {
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
todayLabel: {}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
// Attach event listeners
|
||||
window.addEventListener('viewchanged', function(evt) {
|
||||
if (evt.detail.id === 'appdetail-view') {
|
||||
setAppManifestURL(evt.detail.params.manifestURL);
|
||||
}
|
||||
});
|
||||
|
||||
els.header.addEventListener('action', function(evt) {
|
||||
var type = evt.detail && evt.detail.type;
|
||||
if (type === 'back') {
|
||||
window.location.hash = '#';
|
||||
}
|
||||
});
|
||||
|
||||
initialized = true;
|
||||
});
|
||||
}
|
||||
|
||||
function setAppManifestURL(manifestURL) {
|
||||
// Get App object
|
||||
app = Common.getApp(manifestURL);
|
||||
|
||||
// Update app usage data
|
||||
updateAppUsageData(app);
|
||||
|
||||
// Localize app name
|
||||
localizedAppName = Common.getLocalizedAppName(app);
|
||||
|
||||
// Update the localized app name throughout the view
|
||||
els.headerHeading.textContent = localizedAppName;
|
||||
}
|
||||
|
||||
function updateAppUsageData(app) {
|
||||
// Hide usage element until it has been updated/localized.
|
||||
els.usage.classList.remove('in');
|
||||
|
||||
var usageRequest = {
|
||||
type: 'datausage',
|
||||
apps: [app.manifestURL]
|
||||
};
|
||||
|
||||
// Request usage for this specific app
|
||||
costcontrol.request(usageRequest, function(result) {
|
||||
if (result.status !== 'success') {
|
||||
console.error('Error requesting data usage. This should not happen.');
|
||||
return;
|
||||
}
|
||||
|
||||
var data = result.data;
|
||||
|
||||
var mobileDataTotal = data.mobile.total;
|
||||
var formattedMobileDataTotal = Formatting.formatData(
|
||||
Formatting.roundData(mobileDataTotal));
|
||||
|
||||
// Localize the data usage info
|
||||
els.dataUsedSince.textContent =
|
||||
_('data-used-since', {
|
||||
'amount': formattedMobileDataTotal,
|
||||
'start-date':
|
||||
Formatting.getFormattedDate(data.start,
|
||||
Formatting.formatters.longDate)
|
||||
});
|
||||
els.dataUsedThisWeek.textContent =
|
||||
_('data-used-this-week', {
|
||||
'amount': formattedMobileDataTotal
|
||||
});
|
||||
els.dataUsedThisMonth.textContent =
|
||||
_('data-used-this-month', {
|
||||
'amount': formattedMobileDataTotal
|
||||
});
|
||||
|
||||
els.dataUsedSince.hidden = true;
|
||||
els.dataUsedThisWeek.hidden = true;
|
||||
els.dataUsedThisMonth.hidden = true;
|
||||
|
||||
// Update the charts
|
||||
prepareChartData(result, function() {
|
||||
|
||||
// Render the charts
|
||||
renderChart();
|
||||
|
||||
// Fade in usage element
|
||||
els.usage.classList.add('in');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function prepareChartData(result, callback) {
|
||||
if (result.status === 'success') {
|
||||
SimManager.requestDataSimIcc(function(dataSimIcc) {
|
||||
ConfigManager.requestSettings(dataSimIcc.iccId,
|
||||
function _onSettings(settings) {
|
||||
debug('Updating model');
|
||||
var modelData = result.data;
|
||||
model.data.wifi.samples = modelData.wifi.samples;
|
||||
model.data.wifi.total = modelData.wifi.total;
|
||||
model.data.wifi.apps = modelData.wifi.apps;
|
||||
|
||||
model.data.mobile.samples = modelData.mobile.samples;
|
||||
model.data.mobile.total = modelData.mobile.total;
|
||||
model.data.mobile.apps = modelData.mobile.apps;
|
||||
|
||||
model.limits.enabled = settings.dataLimit;
|
||||
model.limits.value = ChartUtils.getLimitInBytes(settings);
|
||||
model.limits.dataLimitValue = settings.dataLimitValue;
|
||||
model.axis.X.upper = ChartUtils.calculateUpperDate(settings);
|
||||
model.axis.X.lower = ChartUtils.calculateLowerDate(settings);
|
||||
ChartUtils.expandModel(model);
|
||||
|
||||
// Show correct usage text label
|
||||
switch (settings.trackingPeriod) {
|
||||
case 'weekly':
|
||||
els.dataUsedSince.hidden = true;
|
||||
els.dataUsedThisWeek.hidden = false;
|
||||
els.dataUsedThisMonth.hidden = true;
|
||||
break;
|
||||
case 'monthly':
|
||||
els.dataUsedSince.hidden = true;
|
||||
els.dataUsedThisWeek.hidden = true;
|
||||
els.dataUsedThisMonth.hidden = false;
|
||||
break;
|
||||
default:
|
||||
els.dataUsedSince.hidden = false;
|
||||
els.dataUsedThisWeek.hidden = true;
|
||||
els.dataUsedThisMonth.hidden = true;
|
||||
break;
|
||||
}
|
||||
|
||||
debug('Rendering');
|
||||
|
||||
callback();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.error('Error requesting data usage. This should not happen.');
|
||||
}
|
||||
}
|
||||
|
||||
function renderChart() {
|
||||
ChartUtils.drawBackgroundLayer(els.backgroundLayer, model, true);
|
||||
ChartUtils.drawTodayLayer(els.todayLayer, model);
|
||||
ChartUtils.drawAxisLayer(els.axisLayer, model, true);
|
||||
ChartUtils.drawDataLayer(els.wifiLayer, model, 'wifi', {
|
||||
stroke: ChartUtils.WIFI_CHART_STROKE,
|
||||
fill: ChartUtils.WIFI_CHART_FILL
|
||||
});
|
||||
ChartUtils.drawDataLayer(els.mobileLayer, model, 'mobile', {
|
||||
stroke: ChartUtils.MOBILE_CHART_STROKE,
|
||||
fill: ChartUtils.MOBILE_CHART_FILL,
|
||||
pattern: els.graphicPattern
|
||||
});
|
||||
ChartUtils.drawWarningLayer(els.warningLayer, model);
|
||||
ChartUtils.drawLimits(els.limitsLayer, model, true);
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
return {
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
};
|
||||
}());
|
||||
|
||||
AppDetailView.initialize();
|
||||
468
assets/webapps/costcontrol.gaiamobile.org/js/views/balance.js
Normal file
468
assets/webapps/costcontrol.gaiamobile.org/js/views/balance.js
Normal file
|
|
@ -0,0 +1,468 @@
|
|||
/* global BalanceView, TopUpLayoutView, CostControl, ConfigManager,
|
||||
ViewManager, debug, MozActivity, getTopUpTimeout, LazyLoader,
|
||||
sendBalanceThresholdNotification
|
||||
*/
|
||||
|
||||
/*
|
||||
* The balance tab is in charge of show balance details and allows the use
|
||||
* to manually update or top up via USSD or code.
|
||||
*
|
||||
* It has four areas of drawing: balance, top up dialog, top up countdown and
|
||||
* error area. The update is done by demand when the application is shown or
|
||||
* when the user taps on the update button. Furthermore, the balance update
|
||||
* can be triggered by a successful top up request.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var BalanceTab = (function() {
|
||||
|
||||
var view, updateButton;
|
||||
var topUpUSSD, topUp, topUpDialog, topUpCodeInput, sendCode, countdownSpan;
|
||||
var balanceView, topUpLayoutView;
|
||||
var costcontrol, initialized;
|
||||
|
||||
function showTopUpWithCode(evt) {
|
||||
topUpWithCode();
|
||||
}
|
||||
|
||||
function setupTab() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
CostControl.getInstance(function _onCostControl(instance) {
|
||||
costcontrol = instance;
|
||||
|
||||
// we need to load topUpDialog to get elements from inside
|
||||
// it should be a separate function run on startup of the module
|
||||
// after HTML is generated
|
||||
topUpDialog = document.getElementById('topup-dialog');
|
||||
var vm = new ViewManager(); // XXX: used to eagerly load top up dialog
|
||||
vm.loadPanel(topUpDialog);
|
||||
|
||||
// HTML entities
|
||||
view = document.getElementById('balance-tab');
|
||||
updateButton = document.getElementById('balance-tab-update-button');
|
||||
sendCode = document.getElementById('topup-send-button');
|
||||
topUpUSSD = document.getElementById('balance-tab-topup-ussd-button');
|
||||
topUp = document.getElementById('balance-tab-topup-button');
|
||||
topUpCodeInput = document.getElementById('topup-code-input');
|
||||
countdownSpan = document.getElementById('top-up-countdown');
|
||||
|
||||
// Subviews
|
||||
topUpLayoutView = new TopUpLayoutView(topUpUSSD, topUp);
|
||||
var balanceConfig = ConfigManager.configuration.balance;
|
||||
balanceView = new BalanceView(
|
||||
document.getElementById('balance-tab-credit'),
|
||||
document.getElementById('balance-tab-time'),
|
||||
balanceConfig ? balanceConfig.minimum_delay : undefined
|
||||
);
|
||||
|
||||
window.addEventListener('localized', localize);
|
||||
|
||||
// Configure updates
|
||||
document.addEventListener('visibilitychange', updateWhenVisible);
|
||||
updateButton.addEventListener('click', lockAndUpdateUI);
|
||||
ConfigManager.observe('lowLimit', toogleLimits, true);
|
||||
ConfigManager.observe('lowLimitThreshold', resetNotification, true);
|
||||
ConfigManager.observe('lastBalance', onBalance, true);
|
||||
ConfigManager.observe('errors', onBalanceTimeout, true);
|
||||
|
||||
// Configure top up
|
||||
topUpUSSD.addEventListener('click', topUpWithUSSD);
|
||||
topUp.addEventListener('click', showTopUpWithCode);
|
||||
topUpCodeInput.addEventListener('input', toogleSend);
|
||||
sendCode.addEventListener('click', requestTopUp);
|
||||
ConfigManager.observe('waitingForTopUp', onConfirmation, true);
|
||||
ConfigManager.observe('errors', onTopUpErrors, true);
|
||||
toogleSend();
|
||||
|
||||
updateUI();
|
||||
initialized = true;
|
||||
});
|
||||
}
|
||||
|
||||
function localize() {
|
||||
if (initialized) {
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.removeEventListener('visibilitychange', updateWhenVisible);
|
||||
updateButton.removeEventListener('click', lockAndUpdateUI);
|
||||
ConfigManager.removeObserver('lowLimit', toogleLimits);
|
||||
ConfigManager.removeObserver('lowLimitThreshold', resetNotification);
|
||||
ConfigManager.removeObserver('lastBalance', onBalance);
|
||||
ConfigManager.removeObserver('errors', onBalanceTimeout);
|
||||
|
||||
topUpUSSD.removeEventListener('click', topUpWithUSSD);
|
||||
topUp.removeEventListener('click', showTopUpWithCode);
|
||||
topUpCodeInput.removeEventListener('input', toogleSend);
|
||||
sendCode.removeEventListener('click', requestTopUp);
|
||||
ConfigManager.removeObserver('waitingForTopUp', onConfirmation);
|
||||
ConfigManager.removeObserver('errors', onTopUpErrors);
|
||||
|
||||
topUpLayoutSet = false;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
// BALANCE ACTIONS
|
||||
|
||||
// On showing the application
|
||||
function updateWhenVisible() {
|
||||
if (!document.hidden && initialized) {
|
||||
updateUI();
|
||||
} else {
|
||||
clearInterval(topUpCountdown);
|
||||
}
|
||||
}
|
||||
|
||||
// On tapping update
|
||||
function lockAndUpdateUI() {
|
||||
updateButton.disabled = true;
|
||||
updateUI(true);
|
||||
}
|
||||
|
||||
// On changing low limit alert
|
||||
function toogleLimits(isEnabled, old, key, settings) {
|
||||
updateBalance(settings.lastBalance,
|
||||
isEnabled && settings.lowLimitThreshold);
|
||||
if (isEnabled) {
|
||||
sendBalanceThresholdNotification(settings.lastBalance, settings, false);
|
||||
updateBalance(settings.lastBalance, settings.lowLimitThreshold);
|
||||
}
|
||||
}
|
||||
|
||||
// On changing the threshold for low limit
|
||||
function resetNotification() {
|
||||
ConfigManager.setOption({ 'lowLimitNotified': false });
|
||||
ConfigManager.requestAll(function _onSettings(configuration, settings) {
|
||||
updateBalance(settings.lastBalance, settings.lowLimitThreshold);
|
||||
sendBalanceThresholdNotification(settings.lastBalance, settings, false);
|
||||
});
|
||||
}
|
||||
|
||||
// On balance update received
|
||||
function onBalance(balance, old, key, settings) {
|
||||
debug('Balance received:', balance);
|
||||
setBalanceMode();
|
||||
updateBalance(balance, settings.lowLimit && settings.lowLimitThreshold);
|
||||
debug('Balance updated!');
|
||||
}
|
||||
|
||||
// On balance timeout
|
||||
function onBalanceTimeout(errors) {
|
||||
if (!errors.BALANCE_TIMEOUT) {
|
||||
return;
|
||||
}
|
||||
debug('Balance timeout!');
|
||||
|
||||
setBalanceMode('warning');
|
||||
setError('balance_error');
|
||||
|
||||
// Error handled, disabling
|
||||
errors.BALANCE_TIMEOUT = false;
|
||||
ConfigManager.setOption({errors: errors});
|
||||
}
|
||||
|
||||
// TOP UP ACTIONS
|
||||
|
||||
// On tapping Top Up and Pay
|
||||
function topUpWithUSSD() {
|
||||
var dialing;
|
||||
dialing = new MozActivity({
|
||||
name: 'dial',
|
||||
data: {
|
||||
type: 'webtelephony/number',
|
||||
number: ConfigManager.configuration.topup.ussd_destination
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// On tapping Top Up with code
|
||||
function topUpWithCode(lastWasError) {
|
||||
window.location.hash = '##topup-dialog';
|
||||
if (lastWasError) {
|
||||
setTopUpMode('incorrect_code');
|
||||
}
|
||||
|
||||
topUpCodeInput.focus();
|
||||
}
|
||||
|
||||
// On typing the code
|
||||
function toogleSend(evt) {
|
||||
sendCode.disabled = !topUpCodeInput.value.trim();
|
||||
}
|
||||
|
||||
// On tapping send code button
|
||||
var DIALOG_TIMEOUT = 10 * 1000; // 10s
|
||||
function requestTopUp() {
|
||||
sendCode.disabled = true;
|
||||
|
||||
var code = topUpCodeInput.value.trim();
|
||||
var requestObj = { type: 'topup', data: code };
|
||||
costcontrol.request(requestObj, function _onTopUpRequest(result) {
|
||||
debug(result);
|
||||
sendCode.disabled = false;
|
||||
|
||||
var status = result.status;
|
||||
if (status === 'success' || status === 'in_progress') {
|
||||
setTopUpMode('in_progress');
|
||||
setTimeout(closeTopUp, DIALOG_TIMEOUT);
|
||||
|
||||
} else if (status === 'error') {
|
||||
setTopUpMode(result.details);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closeTopUp() {
|
||||
// Remove from hash
|
||||
if (isTopUpShown()) {
|
||||
window.location.hash = '#';
|
||||
}
|
||||
}
|
||||
|
||||
function isTopUpShown() {
|
||||
return window.location.hash.split('#')[2] === topUpDialog.id;
|
||||
}
|
||||
|
||||
// On confirmation SMS for top up received
|
||||
function onConfirmation(isWaiting) {
|
||||
if (isWaiting !== null) {
|
||||
return;
|
||||
}
|
||||
debug('TopUp confirmed!');
|
||||
setTopUpMode('default');
|
||||
topUpCodeInput.value = '';
|
||||
updateUI();
|
||||
}
|
||||
|
||||
// On top up timeout or incorrect code
|
||||
function onTopUpErrors(errors) {
|
||||
debug('ERRORS:', errors);
|
||||
|
||||
var mode;
|
||||
if (errors.TOPUP_TIMEOUT) {
|
||||
errors.TOPUP_TIMEOUT = false;
|
||||
mode = 'topup_timeout';
|
||||
}
|
||||
if (errors.INCORRECT_TOPUP_CODE) {
|
||||
errors.INCORRECT_TOPUP_CODE = false;
|
||||
mode = 'incorrect_code';
|
||||
}
|
||||
debug('Most important error: ', mode);
|
||||
|
||||
// XXX: Very important to call this only if something has changed. If not,
|
||||
// infinite events are triggered.
|
||||
if (mode) {
|
||||
setTopUpMode(mode);
|
||||
ConfigManager.setOption({errors: errors});
|
||||
}
|
||||
}
|
||||
|
||||
// USER INTERFACE
|
||||
var topUpLayoutSet = false;
|
||||
function updateUI(force) {
|
||||
ConfigManager.requestAll(function _onSettings(configuration, settings) {
|
||||
|
||||
if (!topUpLayoutSet) {
|
||||
topUpLayoutView.setupLayout(configuration.topup);
|
||||
topUpLayoutSet = true;
|
||||
}
|
||||
|
||||
resetTopUpCountdown();
|
||||
updateBalance(settings.lastBalance,
|
||||
settings.lowLimit && settings.lowLimitThreshold);
|
||||
|
||||
var requestObj = { type: 'balance', force: !!force };
|
||||
costcontrol.request(requestObj, function _onRequest(result) {
|
||||
debug(result);
|
||||
updateButton.disabled = false;
|
||||
var status = result.status;
|
||||
var balance = result.data;
|
||||
var isError = status === 'error' && result.details !== 'minimum_delay';
|
||||
var isUpdating = status !== 'error';
|
||||
if (isError) {
|
||||
setBalanceMode('warning');
|
||||
setError(result.details);
|
||||
} else {
|
||||
setBalanceMode(isUpdating ? 'updating' : 'default');
|
||||
setError();
|
||||
}
|
||||
updateBalance(balance,
|
||||
settings.lowLimit && settings.lowLimitThreshold);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Update the balance in balance view
|
||||
function updateBalance(balance, limit) {
|
||||
|
||||
if (!balance) {
|
||||
debug('Balance not available');
|
||||
balanceView.update();
|
||||
return;
|
||||
}
|
||||
|
||||
var isUpdating = view.classList.contains('updating');
|
||||
balanceView.update(balance, isUpdating);
|
||||
|
||||
// Limits: reaching zero / low limit
|
||||
if (balance.balance === 0) {
|
||||
view.classList.add('no-credit');
|
||||
|
||||
} else {
|
||||
view.classList.remove('no-credit');
|
||||
|
||||
if (limit && balance.balance < limit) {
|
||||
view.classList.add('low-credit');
|
||||
} else {
|
||||
view.classList.remove('low-credit');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set warning / updating modes
|
||||
var lastBalanceMode;
|
||||
function setBalanceMode(mode) {
|
||||
if (mode === lastBalanceMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastBalanceMode = mode;
|
||||
view.classList.remove('updating');
|
||||
view.classList.remove('warning');
|
||||
|
||||
if (mode === 'warning') {
|
||||
view.classList.add('warning');
|
||||
}
|
||||
|
||||
if (mode === 'updating') {
|
||||
view.classList.add('updating');
|
||||
}
|
||||
}
|
||||
|
||||
// Control info messages in the top up dialog as well as the top up countdown
|
||||
// and error messages in the error area
|
||||
var lastTopUpMode;
|
||||
function setTopUpMode(mode) {
|
||||
if (lastTopUpMode === mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastTopUpMode = mode;
|
||||
|
||||
// Messages in top up dialog
|
||||
var isShown;
|
||||
var defaultMessage = document.getElementById('topup-code-explanation');
|
||||
var inprogressMessage = document.getElementById('topup-in-progress');
|
||||
var errorMessage = document.getElementById('topup-error');
|
||||
var incorrectCodeMessage = document.getElementById('topup-incorrect-code');
|
||||
|
||||
isShown = (mode === 'default' || mode === 'topup_timeout');
|
||||
defaultMessage.hidden = !isShown;
|
||||
|
||||
isShown = (mode === 'in_progress');
|
||||
inprogressMessage.hidden = !isShown;
|
||||
|
||||
isShown = (mode === 'request_fail' || mode === 'no_service');
|
||||
errorMessage.hidden = !isShown;
|
||||
|
||||
isShown = (mode === 'incorrect_code');
|
||||
incorrectCodeMessage.hidden = !isShown;
|
||||
|
||||
// Count down
|
||||
var countdownArea = document.getElementById('cost-control-topup-countdown');
|
||||
isShown = (mode === 'in_progress');
|
||||
countdownArea.hidden = !isShown;
|
||||
if (isShown) {
|
||||
resetTopUpCountdown();
|
||||
}
|
||||
|
||||
// Messages in error message area
|
||||
if (mode === 'topup_timeout') {
|
||||
setError(mode);
|
||||
}
|
||||
}
|
||||
|
||||
var topUpCountdown, countdown;
|
||||
function resetTopUpCountdown() {
|
||||
getTopUpTimeout(function(timeout) {
|
||||
if (!timeout) {
|
||||
return;
|
||||
}
|
||||
countdown = Math.floor((timeout.getTime() - Date.now()) / 1000);
|
||||
if (countdown < 0) {
|
||||
return;
|
||||
}
|
||||
clearInterval(topUpCountdown);
|
||||
topUpCountdown = setInterval(function _updateCountdown() {
|
||||
var minutes = Math.floor(countdown / 60);
|
||||
var seconds = (countdown % 60).toFixed(0);
|
||||
var padding = '';
|
||||
if (seconds < 10) {
|
||||
padding = '0';
|
||||
}
|
||||
countdownSpan.textContent = (minutes + ' : ' + padding + seconds);
|
||||
if (countdown > 0) {
|
||||
countdown -= 1;
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
var ERRORS = {
|
||||
'airplane_mode': { priority: 1, string: 'airplane-mode-error-message2' },
|
||||
'no_service': { priority: 2, string: 'no-coverage-error-message2' },
|
||||
'no_coverage': { priority: 2, string: 'no-coverage-error-message' },
|
||||
'topup_timeout': { priority: 3, string: 'top-up-timed-out2' },
|
||||
'balance_error': { priority: 4, string: 'balance-error-message2' },
|
||||
'non_free_in_roaming': { priority: 4, string: 'on-roaming-message2' }
|
||||
};
|
||||
var currentError = '';
|
||||
|
||||
// Decide which error should be shown taking in count error priorities
|
||||
function setError(error) {
|
||||
// Ignore showing message if the message is not registered
|
||||
if (error && !ERRORS[error]) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug('Error mode:', error ? error : 'no error');
|
||||
var messageArea = document.getElementById('cost-control-message-area');
|
||||
var message = document.getElementById('error-message-placeholder');
|
||||
|
||||
if (!error) {
|
||||
messageArea.hidden = true;
|
||||
message.removeAttribute('data-l10n-id');
|
||||
message.textContent = '';
|
||||
} else {
|
||||
messageArea.hidden = false;
|
||||
var curPriority = currentError ? ERRORS[currentError].priority : 0;
|
||||
var newPriority = ERRORS[error] ? ERRORS[error].priority : 0;
|
||||
if (newPriority >= curPriority) {
|
||||
message.setAttribute('data-l10n-id', ERRORS[error].string);
|
||||
currentError = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
topUpWithCode: topUpWithCode,
|
||||
initialize: function() {
|
||||
var SCRIPTS_NEEDED = [
|
||||
'js/views/TopUpLayoutView.js',
|
||||
'js/views/BalanceView.js'
|
||||
];
|
||||
LazyLoader.load(SCRIPTS_NEEDED, setupTab);
|
||||
},
|
||||
finalize: finalize
|
||||
};
|
||||
}());
|
||||
BalanceTab.initialize();
|
||||
492
assets/webapps/costcontrol.gaiamobile.org/js/views/datausage.js
Normal file
492
assets/webapps/costcontrol.gaiamobile.org/js/views/datausage.js
Normal file
|
|
@ -0,0 +1,492 @@
|
|||
/* global debug, ConfigManager, CostControl, Formatting,
|
||||
SimManager, Common, ChartUtils */
|
||||
/* jshint -W120 */
|
||||
|
||||
/*
|
||||
* The data usage tab is in charge of usage charts of mobile and wi-fi networks.
|
||||
*
|
||||
* It has several canvas areas layered one above the others.
|
||||
*/
|
||||
'use strict';
|
||||
var DataUsageTab = (function() {
|
||||
|
||||
var graphicArea, graphicPattern;
|
||||
var backgroundLayer, wifiLayer, mobileLayer, axisLayer, todayLayer,
|
||||
warningLayer, limitsLayer;
|
||||
var wifiOverview, mobileOverview;
|
||||
var wifiToggle, mobileToggle;
|
||||
var appList, noData;
|
||||
|
||||
var costcontrol, initialized, model;
|
||||
|
||||
function setupTab() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
CostControl.getInstance(function _onCostControl(instance) {
|
||||
costcontrol = instance;
|
||||
|
||||
// HTML entities
|
||||
graphicArea = document.getElementById('graphic-area');
|
||||
graphicPattern = document.getElementById('graphic-pattern');
|
||||
backgroundLayer = document.getElementById('background-layer');
|
||||
wifiLayer = document.getElementById('wifi-layer');
|
||||
mobileLayer = document.getElementById('mobile-layer');
|
||||
axisLayer = document.getElementById('axis-layer');
|
||||
todayLayer = document.getElementById('today-layer');
|
||||
warningLayer = document.getElementById('warning-layer');
|
||||
limitsLayer = document.getElementById('limits-layer');
|
||||
wifiOverview = document.getElementById('wifiOverview');
|
||||
mobileOverview = document.getElementById('mobileOverview');
|
||||
wifiToggle = document.getElementById('wifiCheck');
|
||||
mobileToggle = document.getElementById('mobileCheck');
|
||||
appList = document.getElementById('app-usage-list');
|
||||
noData = document.getElementById('app-usage-no-data');
|
||||
|
||||
window.addEventListener('localized', localize);
|
||||
|
||||
// Update and chart visibility
|
||||
document.addEventListener('visibilitychange', updateWhenVisible);
|
||||
wifiToggle.addEventListener('change', toggleWifi);
|
||||
mobileToggle.addEventListener('change', toggleMobile);
|
||||
|
||||
// Setup the model
|
||||
SimManager.requestDataSimIcc(function(dataSimIcc) {
|
||||
ConfigManager.requestSettings(dataSimIcc.iccId,
|
||||
function _onSettings(settings) {
|
||||
debug('First time setup for model');
|
||||
model = {
|
||||
height: ChartUtils.toDevicePixels(graphicArea.clientHeight),
|
||||
width: ChartUtils.toDevicePixels(graphicArea.clientWidth),
|
||||
originX: Math.floor(
|
||||
ChartUtils.toDevicePixels(graphicArea.clientWidth) * 0.15),
|
||||
endX: Math.floor(
|
||||
ChartUtils.toDevicePixels(graphicArea.clientWidth) * 0.95),
|
||||
axis: {
|
||||
Y: {
|
||||
lower: 0,
|
||||
margin: 0.20
|
||||
},
|
||||
X: {
|
||||
lower: ChartUtils.calculateLowerDate(settings),
|
||||
upper: ChartUtils.calculateUpperDate(settings)
|
||||
}
|
||||
},
|
||||
limits: {
|
||||
enabled: settings.dataLimit,
|
||||
value: ChartUtils.getLimitInBytes(settings),
|
||||
dataLimitValue: settings.dataLimitValue,
|
||||
dataLimitUnit: settings.dataLimitUnit
|
||||
},
|
||||
data: {
|
||||
wifi: {
|
||||
enabled: true
|
||||
},
|
||||
mobile: {
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
todayLabel: {}
|
||||
};
|
||||
ChartUtils.expandModel(model);
|
||||
resetButtonState(settings);
|
||||
|
||||
ConfigManager.observe('dataLimit', toggleDataLimit, true);
|
||||
ConfigManager.observe('dataLimitValue', setDataLimit, true);
|
||||
ConfigManager.observe('lastCompleteDataReset', updateDataUsage, true);
|
||||
ConfigManager.observe('lastDataReset', updateDataUsage, true);
|
||||
ConfigManager.observe('nextReset', changeNextReset, true);
|
||||
|
||||
function finishInit() {
|
||||
initialized = true;
|
||||
updateDataUsage();
|
||||
}
|
||||
|
||||
Common.loadApps()
|
||||
.then(finishInit)
|
||||
.catch(function(reason) {
|
||||
debug(reason);
|
||||
finishInit();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function localize() {
|
||||
if (initialized) {
|
||||
ChartUtils.drawTodayLayer(todayLayer, model);
|
||||
ChartUtils.drawAxisLayer(axisLayer, model, mobileToggle.checked);
|
||||
ChartUtils.drawLimits(limitsLayer, model, mobileToggle.checked);
|
||||
}
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.removeEventListener('visibilitychange', updateWhenVisible);
|
||||
wifiToggle.removeEventListener('click', toggleWifi);
|
||||
mobileToggle.removeEventListener('click', toggleMobile);
|
||||
ConfigManager.removeObserver('dataLimit', toggleDataLimit);
|
||||
ConfigManager.removeObserver('dataLimitValue', setDataLimit);
|
||||
ConfigManager.removeObserver('lastCompleteDataReset', updateDataUsage);
|
||||
ConfigManager.removeObserver('lastDataReset', updateDataUsage);
|
||||
ConfigManager.removeObserver('nextReset', changeNextReset);
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
function resetButtonState(settings) {
|
||||
var isMobileChartVisible = settings.isMobileChartVisible;
|
||||
if (typeof isMobileChartVisible === 'undefined') {
|
||||
isMobileChartVisible = true;
|
||||
}
|
||||
if (isMobileChartVisible !== mobileToggle.checked) {
|
||||
mobileToggle.checked = isMobileChartVisible;
|
||||
toggleMobile();
|
||||
}
|
||||
|
||||
var isWifiChartVisible = settings.isWifiChartVisible;
|
||||
if (typeof isWifiChartVisible === 'undefined') {
|
||||
isWifiChartVisible = false;
|
||||
}
|
||||
if (isWifiChartVisible !== wifiToggle.checked) {
|
||||
wifiToggle.checked = isWifiChartVisible;
|
||||
toggleWifi();
|
||||
}
|
||||
}
|
||||
|
||||
// UPDATES
|
||||
|
||||
// On visibility change
|
||||
function updateWhenVisible(evt) {
|
||||
if (!document.hidden) {
|
||||
updateDataUsage();
|
||||
}
|
||||
}
|
||||
|
||||
function requestDataUsage(perApp) {
|
||||
return new Promise(function(resolve) {
|
||||
SimManager.requestDataSimIcc(function(dataSimIcc) {
|
||||
ConfigManager.requestSettings(dataSimIcc.iccId,
|
||||
function _onSettings(settings) {
|
||||
|
||||
var request = { type: 'datausage' };
|
||||
if (perApp) {
|
||||
request.apps = Common.allApps.map(function(app) {
|
||||
return app.manifestURL;
|
||||
});
|
||||
}
|
||||
|
||||
costcontrol.request(request, resolve);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function maybeRequestPerAppUsage() {
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!model.data.mobile.total) {
|
||||
noData.hidden = false;
|
||||
appList.hidden = true;
|
||||
// Repeated here to not rely on the deferred `updateApps()` call which
|
||||
// would add an annoying delay until clearing the data.
|
||||
clearAppList();
|
||||
|
||||
} else {
|
||||
noData.hidden = true;
|
||||
appList.hidden = false;
|
||||
|
||||
// Bug 1064491: request per-app data usage on the next tick of
|
||||
// the main loop to avoid performance regression in startup
|
||||
setTimeout(function() {
|
||||
requestDataUsage(true).then(updateApps);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function updateCharts(result) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (result.status === 'success') {
|
||||
SimManager.requestDataSimIcc(function(dataSimIcc) {
|
||||
ConfigManager.requestSettings(dataSimIcc.iccId,
|
||||
function _onSettings(settings) {
|
||||
var modelData = result.data;
|
||||
model.data.wifi.samples = modelData.wifi.samples;
|
||||
model.data.wifi.total = modelData.wifi.total;
|
||||
|
||||
model.data.mobile.samples = modelData.mobile.samples;
|
||||
model.data.mobile.total = modelData.mobile.total;
|
||||
|
||||
model.limits.enabled = settings.dataLimit;
|
||||
model.limits.value = ChartUtils.getLimitInBytes(settings);
|
||||
model.limits.dataLimitValue = settings.dataLimitValue;
|
||||
model.axis.X.upper = ChartUtils.calculateUpperDate(settings);
|
||||
model.axis.X.lower = ChartUtils.calculateLowerDate(settings);
|
||||
ChartUtils.expandModel(model);
|
||||
resolve();
|
||||
|
||||
debug('Rendering');
|
||||
drawCharts();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
reject(new Error(
|
||||
'Error requesting data usage. This should not happen.'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateApps(result) {
|
||||
if (result.status === 'success') {
|
||||
model.data.wifi.apps = result.data.wifi.apps;
|
||||
model.data.mobile.apps = result.data.mobile.apps;
|
||||
drawApps(model);
|
||||
}
|
||||
}
|
||||
|
||||
// OBSERVERS
|
||||
|
||||
function toggleDataLimit(value) {
|
||||
model.limits.enabled = value;
|
||||
ChartUtils.drawBackgroundLayer(backgroundLayer, model,
|
||||
mobileToggle.checked);
|
||||
ChartUtils.drawAxisLayer(axisLayer, model, mobileToggle.checked);
|
||||
ChartUtils.drawLimits(limitsLayer, model, mobileToggle.checked);
|
||||
ChartUtils.drawWarningLayer(warningLayer, model);
|
||||
}
|
||||
|
||||
function setDataLimit(value, old, key, settings) {
|
||||
model.limits.value = ChartUtils.getLimitInBytes(settings);
|
||||
model.limits.dataLimitValue = settings.dataLimitValue;
|
||||
ChartUtils.expandModel(model);
|
||||
drawCharts();
|
||||
}
|
||||
|
||||
function updateDataUsage() {
|
||||
requestDataUsage()
|
||||
.then(updateCharts)
|
||||
.then(maybeRequestPerAppUsage);
|
||||
}
|
||||
|
||||
function changeNextReset(value, old, key, settings) {
|
||||
model.axis.X.upper = ChartUtils.calculateUpperDate(settings);
|
||||
model.axis.X.lower = ChartUtils.calculateLowerDate(settings);
|
||||
ChartUtils.expandModel(model);
|
||||
drawCharts();
|
||||
}
|
||||
|
||||
// USER INTERFACE
|
||||
|
||||
// On tapping on wifi toggle
|
||||
function toggleWifi() {
|
||||
var isChecked = wifiToggle.checked;
|
||||
wifiLayer.hidden = !isChecked;
|
||||
// save wifi toggled state
|
||||
ConfigManager.setOption({ isWifiChartVisible: isChecked });
|
||||
|
||||
if (model) {
|
||||
drawApps(model);
|
||||
}
|
||||
}
|
||||
|
||||
// On tapping on mobile toggle
|
||||
function toggleMobile() {
|
||||
var isChecked = mobileToggle.checked;
|
||||
mobileLayer.hidden = !isChecked;
|
||||
warningLayer.hidden = !isChecked;
|
||||
limitsLayer.hidden = !isChecked;
|
||||
// save wifi toggled state
|
||||
ConfigManager.setOption({ isMobileChartVisible: isChecked });
|
||||
|
||||
if (model) {
|
||||
ChartUtils.drawBackgroundLayer(backgroundLayer, model, isChecked);
|
||||
ChartUtils.drawAxisLayer(axisLayer, model, isChecked);
|
||||
ChartUtils.drawLimits(limitsLayer, model, isChecked);
|
||||
drawApps(model);
|
||||
}
|
||||
}
|
||||
|
||||
function drawCharts() {
|
||||
// Update overview
|
||||
var wifiData = Formatting.roundData(model.data.wifi.total);
|
||||
var mobileData = Formatting.roundData(model.data.mobile.total);
|
||||
wifiOverview.textContent = Formatting.formatData(wifiData);
|
||||
mobileOverview.textContent = Formatting.formatData(mobileData);
|
||||
|
||||
// Render the charts
|
||||
ChartUtils.drawBackgroundLayer(backgroundLayer, model,
|
||||
mobileToggle.checked);
|
||||
ChartUtils.drawTodayLayer(todayLayer, model);
|
||||
ChartUtils.drawAxisLayer(axisLayer, model, mobileToggle.checked);
|
||||
ChartUtils.drawDataLayer(wifiLayer, model, 'wifi', {
|
||||
stroke: ChartUtils.WIFI_CHART_STROKE,
|
||||
fill: ChartUtils.WIFI_CHART_FILL
|
||||
});
|
||||
ChartUtils.drawDataLayer(mobileLayer, model, 'mobile', {
|
||||
stroke: ChartUtils.MOBILE_CHART_STROKE,
|
||||
fill: ChartUtils.MOBILE_CHART_FILL,
|
||||
pattern: graphicPattern
|
||||
});
|
||||
ChartUtils.drawWarningLayer(warningLayer, model);
|
||||
ChartUtils.drawLimits(limitsLayer, model, mobileToggle.checked);
|
||||
drawApps(model);
|
||||
}
|
||||
|
||||
var cachedAppItems = {};
|
||||
function drawApps(model) {
|
||||
|
||||
function createAppItem(app) {
|
||||
var isSystem = app.manifestURL === Common.SYSTEM_MANIFEST;
|
||||
var appElement = document.createElement('li');
|
||||
appElement.className = 'app-item';
|
||||
|
||||
var linkElement = document.createElement('a');
|
||||
if (!isSystem) {
|
||||
linkElement.href = '##appdetail-view?manifestURL=' + app.manifestURL;
|
||||
}
|
||||
appElement.appendChild(linkElement);
|
||||
|
||||
var imgElement = document.createElement('img');
|
||||
imgElement.className = 'app-image';
|
||||
imgElement.src = Common.getAppIcon(app);
|
||||
imgElement.setAttribute('role', 'presentation');
|
||||
imgElement.onerror = function() {
|
||||
console.warn('Unable to load icon: ' + this.src);
|
||||
this.src = '/style/images/app/icons/default.png';
|
||||
};
|
||||
linkElement.appendChild(imgElement);
|
||||
|
||||
var appInfoElement = document.createElement('div');
|
||||
appInfoElement.className = 'app-info';
|
||||
linkElement.appendChild(appInfoElement);
|
||||
|
||||
var nameElement = document.createElement('div');
|
||||
nameElement.className = 'app-info-row app-name';
|
||||
nameElement.textContent = Common.getLocalizedAppName(app);
|
||||
appInfoElement.appendChild(nameElement);
|
||||
|
||||
var barElement = document.createElement('div');
|
||||
barElement.className = 'app-info-row app-usage-bar';
|
||||
barElement.setAttribute('role', 'presentation');
|
||||
appInfoElement.appendChild(barElement);
|
||||
|
||||
var usedBarElement = document.createElement('div');
|
||||
usedBarElement.className = 'app-usage-bar-used';
|
||||
usedBarElement.setAttribute('role', 'presentation');
|
||||
barElement.appendChild(usedBarElement);
|
||||
|
||||
var usageElement = document.createElement('div');
|
||||
usageElement.className = 'app-info-row app-usage-total';
|
||||
appInfoElement.appendChild(usageElement);
|
||||
|
||||
return appElement;
|
||||
}
|
||||
|
||||
function updateAppItemUsage(appItem, total) {
|
||||
var usedBarElement =
|
||||
appItem.getElementsByClassName('app-usage-bar-used')[0];
|
||||
var totalElement =
|
||||
appItem.getElementsByClassName('app-usage-total')[0];
|
||||
|
||||
var barTotal = mobileTotal;
|
||||
if (model.limits.enabled && model.limits.value !== null) {
|
||||
barTotal = Math.max(barTotal, model.limits.value);
|
||||
}
|
||||
|
||||
var usedPercent = (total / barTotal) * 100;
|
||||
usedBarElement.style.width = usedPercent + '%';
|
||||
totalElement.textContent = '' + Formatting.formatData(
|
||||
Formatting.roundData(total));
|
||||
}
|
||||
|
||||
// Front-end workaround for Bug 1083680: Noticeable difference between by
|
||||
// application breakdown totals and the total displayed in chart and widget.
|
||||
// This method adds the residual traffic (the traffic that cannot be not
|
||||
// allocated to an app) to the System application.
|
||||
function fixResidualTraffic() {
|
||||
var breakdownTotal = 0;
|
||||
mobileApps[Common.SYSTEM_MANIFEST] = {total: 0};
|
||||
if (manifests.length > 0) {
|
||||
breakdownTotal =
|
||||
manifests.reduce(function(accumulatedTraffic, appManifest) {
|
||||
return accumulatedTraffic + mobileApps[appManifest].total;
|
||||
}, 0);
|
||||
}
|
||||
var residualTraffic = mobileTotal - breakdownTotal;
|
||||
// System traffic is the residual traffic
|
||||
if (residualTraffic > 0) {
|
||||
mobileApps[Common.SYSTEM_MANIFEST].total = residualTraffic;
|
||||
if (!manifests[Common.SYSTEM_MANIFEST]) {
|
||||
manifests.push(Common.SYSTEM_MANIFEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearAppList();
|
||||
|
||||
var mobileTotal = model.data.mobile.total;
|
||||
var mobileApps = model.data.mobile.apps;
|
||||
if (!mobileApps) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out apps that have not used any data yet.
|
||||
var manifests = Object.keys(mobileApps).filter(function(key) {
|
||||
return mobileApps[key].total > 0;
|
||||
});
|
||||
|
||||
// Note: The second premise (mobileTotal === 0) must be removed when the
|
||||
// fixResidualTraffic method will be eliminated.
|
||||
if (manifests.length === 0 && mobileTotal === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
fixResidualTraffic();
|
||||
|
||||
// Sort by total data usage, descending
|
||||
manifests.sort(function(a, b) {
|
||||
return mobileApps[b].total - mobileApps[a].total;
|
||||
});
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
manifests.forEach(function(manifestURL) {
|
||||
var app = Common.allApps.find(function(app) {
|
||||
return app.manifestURL === manifestURL;
|
||||
});
|
||||
|
||||
if (!app) {
|
||||
debug('No app with manifest URL: ' + manifestURL);
|
||||
return;
|
||||
}
|
||||
|
||||
var appTotal = mobileApps[manifestURL].total;
|
||||
var appItem = cachedAppItems[manifestURL];
|
||||
if (!appItem) {
|
||||
appItem = cachedAppItems[manifestURL] = createAppItem(app);
|
||||
}
|
||||
|
||||
updateAppItemUsage(appItem, appTotal);
|
||||
fragment.appendChild(appItem);
|
||||
});
|
||||
|
||||
appList.appendChild(fragment);
|
||||
}
|
||||
|
||||
function clearAppList() {
|
||||
appList.innerHTML = '';
|
||||
}
|
||||
|
||||
return {
|
||||
initialize: setupTab,
|
||||
finalize: finalize
|
||||
};
|
||||
}());
|
||||
|
||||
DataUsageTab.initialize();
|
||||
127
assets/webapps/costcontrol.gaiamobile.org/js/views/telephony.js
Normal file
127
assets/webapps/costcontrol.gaiamobile.org/js/views/telephony.js
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/* global CostControl, ConfigManager, debug,
|
||||
Formatting, SimManager, Common */
|
||||
/*
|
||||
* The telephony tab is in charge of show telephony and billing cycle
|
||||
* information.
|
||||
*
|
||||
* It has two areas of drawing: one for the counters and another for
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var TelephonyTab = (function() {
|
||||
var costcontrol, initialized = false;
|
||||
var view, smscount, calltime, time, resetDate;
|
||||
var telephonyPeriod = { begin: null, end: null };
|
||||
|
||||
function setupTab() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
CostControl.getInstance(function _onCostControl(instance) {
|
||||
costcontrol = instance;
|
||||
|
||||
// HTML entities
|
||||
view = document.getElementById('telephony-tab');
|
||||
smscount = document.getElementById('telephony-smscount');
|
||||
calltime = document.getElementById('telephony-calltime');
|
||||
time = document.getElementById('telephony-time');
|
||||
resetDate = document.getElementById('reset-date');
|
||||
|
||||
window.addEventListener('localized', localize);
|
||||
|
||||
// Configure updates
|
||||
document.addEventListener('visibilitychange', updateWhenVisible, true);
|
||||
ConfigManager.observe('lastTelephonyActivity', updateCounters, true);
|
||||
ConfigManager.observe('lastTelephonyReset', updateUI, true);
|
||||
ConfigManager.observe('nextReset', updateNextReset, true);
|
||||
|
||||
// Timeformat
|
||||
window.addEventListener('timeformatchange', function () {
|
||||
updateTimePeriod(
|
||||
telephonyPeriod.begin, null, null, telephonyPeriod.end);
|
||||
});
|
||||
|
||||
updateUI();
|
||||
initialized = true;
|
||||
});
|
||||
}
|
||||
|
||||
function localize() {
|
||||
if (initialized) {
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.removeEventListener('visibilitychange', updateWhenVisible);
|
||||
ConfigManager.removeObserver('lastTelephonyActivity', updateCounters);
|
||||
ConfigManager.removeObserver('lastTelephonyReset', updateUI);
|
||||
ConfigManager.removeObserver('nextReset', updateNextReset);
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
function updateWhenVisible() {
|
||||
if (!document.hidden && initialized) {
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
function updateUI() {
|
||||
var requestObj = { type: 'telephony' };
|
||||
SimManager.requestDataSimIcc(function(dataSimIcc) {
|
||||
ConfigManager.requestSettings(dataSimIcc.iccId,
|
||||
function _onSettings(settings) {
|
||||
costcontrol.request(requestObj, function _afterRequest(result) {
|
||||
var telephonyActivity = result.data;
|
||||
debug('Last telephony activity:', telephonyActivity);
|
||||
updateTimePeriod(settings.lastTelephonyReset, null, null, settings);
|
||||
updateCounters(telephonyActivity);
|
||||
updateNextReset(settings.nextReset, null, null, settings);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updateTimePeriod(lastReset, old, key, settings) {
|
||||
telephonyPeriod.begin = lastReset;
|
||||
telephonyPeriod.end = settings.lastTelephonyActivity.timestamp;
|
||||
time.innerHTML = '';
|
||||
time.appendChild(Formatting.formatTimeHTML(lastReset, telephonyPeriod.end));
|
||||
}
|
||||
|
||||
function updateCounters(activity) {
|
||||
Common.localize(smscount, 'magnitude', {
|
||||
value: activity.smscount,
|
||||
unit: 'SMS'
|
||||
});
|
||||
Common.localize(calltime, 'magnitude', {
|
||||
value: Formatting.computeTelephonyMinutes(activity),
|
||||
unit: 'min.'
|
||||
});
|
||||
}
|
||||
|
||||
function updateNextReset(reset, old, key, settings) {
|
||||
var billingCycle = document.getElementById('billing-cycle');
|
||||
if (settings.trackingPeriod === 'never') {
|
||||
billingCycle.hidden = true;
|
||||
} else {
|
||||
billingCycle.hidden = false;
|
||||
var content = Formatting.getFormattedDate(settings.nextReset,
|
||||
Formatting.formatters.shortDate);
|
||||
resetDate.textContent = content;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
initialize: setupTab,
|
||||
finalize: finalize
|
||||
};
|
||||
}());
|
||||
|
||||
TelephonyTab.initialize();
|
||||
36
assets/webapps/costcontrol.gaiamobile.org/js/widget.js
Normal file
36
assets/webapps/costcontrol.gaiamobile.org/js/widget.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
;'use strict';var Widget=(function(){var costcontrol,activity;function checkSIMStatus(dataSim){var dataSimIcc=dataSim.icc;var cardState=checkCardState(dataSimIcc);if(cardState!=='ready'){debug('SIM not ready:',dataSimIcc.cardState);initialized=false;dataSimIcc.oncardstatechange=checkSIMStatus.bind(null,dataSim);}else{debug('SIM ready. ICCID:',dataSim.iccId);dataSimIcc.oncardstatechange=undefined;var SCRIPTS_NEEDED_TO_START=['js/costcontrol.js','js/config/config_manager.js'];LazyLoader.load(SCRIPTS_NEEDED_TO_START,startWidget);}}
|
||||
function checkCardState(dataSimIcc){var state,cardState;state=cardState=dataSimIcc.cardState;if(!cardState||cardState==='absent'){debug('There is no SIM');Widget.showSimError('no-sim3');}else if(cardState==='unknown'){debug('Unknow state fo the sim');Widget.showSimError('unknown');}else if(cardState==='pinRequired'||cardState==='pukRequired'){Widget.showSimError('sim2-locked');state='locked';}
|
||||
return state;}
|
||||
function loadMessageHandler(){if(ConfigManager.option('nextReset')){window.addEventListener('messagehandlerready',function _setNextReset(){window.removeEventListener('messagehandlerready',_setNextReset);LazyLoader.load('js/settings/networkUsageAlarm.js',function(){Common.loadNetworkInterfaces(function(){setNextReset(ConfigManager.option('nextReset'));});});});}
|
||||
document.getElementById('message-handler').src='message_handler.html';}
|
||||
function startWidget(){CostControl.getInstance(function _onCostControlReady(instance){costcontrol=instance;loadMessageHandler();setupWidget();});}
|
||||
var initialized,widget,leftPanel,rightPanel,fte,views={};var balanceView;function _openBalanceTab(){activity=new MozActivity({name:'costcontrol/balance'});}
|
||||
function _openTelephonyTab(){activity=new MozActivity({name:'costcontrol/telephony'});}
|
||||
function _openDataUsageTab(){activity=new MozActivity({name:'costcontrol/data_usage'});}
|
||||
function _onVisibilityChange(evt){AirplaneModeHelper.ready(function(){if(!document.hidden&&initialized&&(AirplaneModeHelper.getStatus()==='disabled')){SimManager.requestDataSimIcc(function(dataSimIcc){checkCardState(dataSimIcc.icc);updateUI();});}});}
|
||||
function _onHashChange(){if(window.location.hash.split('#')[1]==='update'){updateUI(true);}}
|
||||
function _onLocalize(){if(initialized){updateUI();}}
|
||||
function setupWidget(){var mode=ConfigManager.getApplicationMode();var isDataUsageOnly=(mode==='DATA_USAGE_ONLY');var isBalanceEnabled=!isDataUsageOnly;widget=document.getElementById('cost-control');leftPanel=document.getElementById('left-panel');rightPanel=document.getElementById('right-panel');fte=document.getElementById('fte-view');views.dataUsage=document.getElementById('datausage-view');views.limitedDataUsage=document.getElementById('datausage-limit-view');views.telephony=document.getElementById('telephony-view');views.balance=document.getElementById('balance-view');if(isBalanceEnabled){ConfigManager.observe('lastBalance',onBalance,true);ConfigManager.observe('waitingForBalance',onErrors,true);ConfigManager.observe('errors',onErrors,true);LazyLoader.load('js/views/BalanceView.js',function(){var balanceConfig=ConfigManager.configuration.balance;balanceView=new BalanceView(document.getElementById('balance-credit'),document.querySelector('#balance-credit + .meta'),balanceConfig?balanceConfig.minimum_delay:undefined);});views.balance.addEventListener('click',_openBalanceTab);views.telephony.addEventListener('click',_openTelephonyTab);}
|
||||
ConfigManager.observe('lastCompleteDataReset',onReset,true);ConfigManager.observe('lastTelephonyReset',onReset,true);document.addEventListener('visibilitychange',_onVisibilityChange);window.addEventListener('hashchange',_onHashChange);window.addEventListener('localized',_onLocalize);leftPanel.addEventListener('click',_openDataUsageTab);LazyLoader.load(['shared/js/date_time_helper.js','js/utils/formatting.js'],function(){updateUI();});if(SimManager.isMultiSim()){window.addEventListener('dataSlotChange',function _onDataSimChange(){CostControl.reset();Widget.reset();ConfigManager.setConfig(null);SimManager.requestDataSimIcc(checkSIMStatus);});}
|
||||
initialized=true;}
|
||||
function onBalance(balance,old,key,settings){debug('Balance received:',balance);setBalanceMode('default');updateBalance(balance,settings.lowLimit&&settings.lowLimitThreshold);debug('Balance updated!');}
|
||||
function onErrors(errors,old,key,settings){if(!errors||!errors.BALANCE_TIMEOUT){return;}
|
||||
debug('Balance timeout!');setBalanceMode('warning');errors.BALANCE_TIMEOUT=false;ConfigManager.setOption({errors:errors});}
|
||||
function onReset(value,old,key,settings){updateUI();}
|
||||
function _showSimError(status,updateTextOnly){navigator.mozL10n.ready(function showErrorStatus(){var widget=document.getElementById('cost-control');var fte=document.getElementById('fte-view');var leftPanel=document.getElementById('left-panel');var rightPanel=document.getElementById('right-panel');if(!updateTextOnly){widget.hidden=false;fte.hidden=false;leftPanel.hidden=true;rightPanel.hidden=true;}
|
||||
var className='widget-'+status;Common.localize(fte.querySelector('p:first-child'),className+'-heading');Common.localize(fte.querySelector('p:last-child'),className+'-meta');});}
|
||||
function setupFte(provider,mode){widget.hidden=false;fte.hidden=false;leftPanel.hidden=true;rightPanel.hidden=true;fte.addEventListener('click',function launchFte(evt){fte.removeEventListener('click',launchFte);evt.stopImmediatePropagation();activity=new MozActivity({name:'costcontrol/balance'});});var keyLookup={PREPAID:'widget-authed-sim2',POSTPAID:'widget-authed-sim2',DATA_USAGE_ONLY:'widget-nonauthed-sim2'};var simKey=keyLookup[mode];Common.localize(fte.querySelector('p:first-child'),simKey+'-heading',{provider:provider});Common.localize(fte.querySelector('p:last-child'),simKey+'-meta');}
|
||||
var hashMark=0;function updateUI(updateOnlyDataUsage){ConfigManager.requestAll(function _onInfo(configuration,settings){var mode=ConfigManager.getApplicationMode();debug('Widget UI mode:',mode);var isPrepaid=(mode==='PREPAID');var isDataUsageOnly=(mode==='DATA_USAGE_ONLY');if(settings.fte){setupFte(configuration.provider,mode);debug('Widget in FTE mode');return;}
|
||||
widget.hidden=true;fte.hidden=true;leftPanel.hidden=false;rightPanel.hidden=false;var isLimited=settings.dataLimit;views.dataUsage.hidden=isLimited;views.limitedDataUsage.hidden=!isLimited;rightPanel.hidden=isDataUsageOnly;if(isDataUsageOnly){widget.classList.add('full');widget.hidden=false;}else{widget.classList.remove('full');views.balance.hidden=!isPrepaid;views.telephony.hidden=isPrepaid;widget.hidden=false;}
|
||||
var requestObj={type:'datausage'};costcontrol.request(requestObj,function _onDataStatistics(result){debug(result);var stats=result.data;var data=Formatting.roundData(stats.mobile.total);if(isLimited){var dataLimit=views.limitedDataUsage.querySelector('#data-limit');var dataAvailable=views.limitedDataUsage.querySelector('#data-available');var current=stats.mobile.total;var limit=Common.getDataLimit(settings);debug(limit);views.limitedDataUsage.classList.remove('nearby-limit');views.limitedDataUsage.classList.remove('reached-limit');var limitTrespassed=(current>limit);if(limitTrespassed){views.limitedDataUsage.classList.add('reached-limit');}else if(current>=limit*Common.DATA_USAGE_WARNING){views.limitedDataUsage.classList.add('nearby-limit');}
|
||||
var limitText=Formatting.roundData(limit);limitText=_('magnitude',{value:limitText[0],unit:limitText[1]});navigator.mozL10n.setAttributes(dataLimit,'data-limit',{value:limitText});var rawValue=Math.abs(limit-current);var text=Formatting.roundData(rawValue);if(!limitTrespassed){navigator.mozL10n.setAttributes(dataAvailable,'data-available2',{value:parseFloat(text[0]),unit:text[1]});}else{navigator.mozL10n.setAttributes(dataAvailable,'over-limit',{value:parseFloat(text[0]),unit:text[1]});}}else{document.getElementById('mobile-usage-value').textContent=_('magnitude',{value:data[0],unit:data[1]});var meta=views.dataUsage.querySelector('.meta');meta.innerHTML='';meta.appendChild(Formatting.formatTimeHTML(stats.timestamp));}
|
||||
hashMark=1-hashMark;window.location.hash='#updateDone#'+hashMark;});if(!isDataUsageOnly&&!updateOnlyDataUsage){if(mode==='PREPAID'){updateBalance(settings.lastBalance,settings.lowLimit&&settings.lowLimitThreshold);requestObj={type:'balance'};costcontrol.request(requestObj,function _onRequest(result){debug(result);var status=result.status;var balance=result.data;setBalanceMode(status==='error'?'warning':'updating');updateBalance(balance,settings.lowLimit&&settings.lowLimitThreshold);});}else if(mode==='POSTPAID'){requestObj={type:'telephony'};costcontrol.request(requestObj,function _onRequest(result){var dataActivity=result.data;document.getElementById('telephony-calltime').textContent=_('magnitude',{value:Formatting.computeTelephonyMinutes(dataActivity),unit:'min'});document.getElementById('telephony-smscount').textContent=_('magnitude',{value:dataActivity.smscount,unit:'SMS'});var meta=views.telephony.querySelector('.meta');meta.innerHTML='';meta.appendChild(Formatting.formatTimeHTML(dataActivity.timestamp));});}}});}
|
||||
function updateBalance(balance,limit){if(!balance){debug('Balance not available');balanceView.update();return;}
|
||||
var isUpdating=views.balance.classList.contains('updating');balanceView.update(balance,isUpdating);if(balance.balance===0){views.balance.classList.add('no-credit');}else{views.balance.classList.remove('no-credit');if(limit&&balance.balance<limit){views.balance.classList.add('low-credit');}else{views.balance.classList.remove('low-credit');}}}
|
||||
var lastBalanceMode;function setBalanceMode(mode){if(mode===lastBalanceMode){return;}
|
||||
lastBalanceMode=mode;views.balance.classList.remove('updating');views.balance.classList.remove('warning');if(mode==='warning'){views.balance.classList.add('warning');}
|
||||
if(mode==='updating'){views.balance.classList.add('updating');}}
|
||||
window.addEventListener('airplaneModeDisabled',function _onAirplanemodeDisabled(evt){if(evt.detail&&evt.detail.serviceId==='data'){SimManager.requestDataSimIcc(checkSIMStatus);}});function initWidget(){var isWaitingForIcc=false;function waitForIccAndCheckSim(){if(!isWaitingForIcc){var iccManager=window.navigator.mozIccManager;iccManager.addEventListener('iccdetected',function _oniccdetected(){isWaitingForIcc=false;iccManager.removeEventListener('iccdetected',_oniccdetected);if(AirplaneModeHelper.getStatus()==='disabled'){SimManager.requestDataSimIcc(checkSIMStatus);}});isWaitingForIcc=true;}}
|
||||
SimManager.requestDataSimIcc(checkSIMStatus,function _errorNoSim(){AirplaneModeHelper.ready(function(){waitForIccAndCheckSim();var errorMessageId=(AirplaneModeHelper.getStatus()==='enabled')?'airplane-mode':'no-sim3';console.warn('Error when trying to get the ICC ID');Widget.showSimError(errorMessageId);});});AirplaneModeHelper.addEventListener('statechange',function _onAirplaneModeChange(state){if(state==='enabled'){Widget.showSimError('airplane-mode');}else if(isWaitingForIcc){var updateTextOnly=true;Widget.showSimError('no-sim3',updateTextOnly);}});}
|
||||
return{init:function(){var SCRIPTS_NEEDED=['js/common.js','js/utils/toolkit.js'];if(!window.navigator.mozMobileConnections||!window.navigator.mozIccManager||!window.navigator.mozNetworkStats){LazyLoader.load(SCRIPTS_NEEDED,function _showError(){Widget.showSimError('no-sim3');});}else{SCRIPTS_NEEDED=['js/sim_manager.js','js/common.js','js/utils/toolkit.js','js/utils/debug.js'];LazyLoader.load(SCRIPTS_NEEDED,initWidget);}},showSimError:_showSimError,reset:function(){document.removeEventListener('visibilitychange',_onVisibilityChange);window.removeEventListener('hashchange',_onHashChange);window.removeEventListener('localized',_onLocalize);leftPanel.removeEventListener('click',_openDataUsageTab);if(views.balance){views.balance.removeEventListener('click',_openBalanceTab);}
|
||||
if(views.telephony){views.telephony.removeEventListener('click',_openTelephonyTab);}}};}());Widget.init();
|
||||
18
assets/webapps/costcontrol.gaiamobile.org/jsdoc.json
Normal file
18
assets/webapps/costcontrol.gaiamobile.org/jsdoc.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "costcontrol",
|
||||
"tags": {
|
||||
"dictionaries": ["jsdoc"]
|
||||
},
|
||||
"source": {
|
||||
"include": ["apps/costcontrol/js/**/*.js"]
|
||||
},
|
||||
"plugins": [
|
||||
"plugins/markdown",
|
||||
"plugins/summarize"
|
||||
],
|
||||
"opts": {
|
||||
"private": true,
|
||||
"recurse": true,
|
||||
"destination": "docs/costcontrol"
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue