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
|
|
@ -0,0 +1 @@
|
|||
;window.COMPONENTS_BASE_URL='/shared/elements/';
|
||||
373
assets/webapps/download.gaiamobile.org/shared/elements/gaia-header/dist/gaia-header.js
vendored
Normal file
373
assets/webapps/download.gaiamobile.org/shared/elements/gaia-header/dist/gaia-header.js
vendored
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
;(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)});
|
||||
Binary file not shown.
|
|
@ -0,0 +1,40 @@
|
|||
/* Generated by grunt-webfont */
|
||||
/* Based on https://github.com/endtwist/fontcustom/blob/master/lib/fontcustom/templates/fontcustom.css */
|
||||
|
||||
@font-face {
|
||||
font-family: "gaia-icons";
|
||||
src: url("fonts/gaia-icons.ttf") format("truetype");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
[data-icon]:before,
|
||||
.ligature-icons {
|
||||
font-family: "gaia-icons";
|
||||
content: attr(data-icon);
|
||||
display: inline-block;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
text-decoration: inherit;
|
||||
text-transform: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-size: 30px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
[data-icon]:not([data-l10n-id]):not([aria-label]):not([aria-hidden="true"]):before {
|
||||
/* Highlight cases where icons are not localized and still visible to screen
|
||||
reader */
|
||||
background: rgba(255, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
[data-icon]:not([data-l10n-id]):not([aria-label]):not([aria-hidden="true"]):after {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
width: 20rem;
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
content: "Icon is not localized and is still visible to screen reader. Please add data-l10n-id or aria-label for localization or use aria-hidden to hide the icon from screen reader.";
|
||||
z-index: 9999;
|
||||
}
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
Gaia theme variables
|
||||
*/
|
||||
|
||||
|
||||
:root {
|
||||
|
||||
/** Grey Colors
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--color-alpha: #333333;
|
||||
--color-beta: #ffffff;
|
||||
--color-gamma: #4d4d4d;
|
||||
--color-delta: #5f5f5f;
|
||||
--color-epsilon: #858585;
|
||||
--color-zeta: #a6a6a6;
|
||||
--color-eta: #c7c7c7;
|
||||
--color-theta: #e7e7e7;
|
||||
--color-iota: #f4f4f4;
|
||||
|
||||
/** Brand Colors
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--color-darkblue: #00539f;
|
||||
--color-blue: #00caf2;
|
||||
--color-turquoise: #27c8c2;
|
||||
--color-darkorange: #e66000;
|
||||
--color-orange: #ff9500;
|
||||
--color-yellow: #ffcb00;
|
||||
--color-violet: #c40c84;
|
||||
|
||||
--color-warning: #fbbd3c;
|
||||
--color-destructive: #e2443a;
|
||||
--color-preffered: #00ba91;
|
||||
|
||||
/** Background
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--background: var(--color-beta);
|
||||
--background-plus: var(--color-theta);
|
||||
--background-minus: var(--color-zeta);
|
||||
|
||||
/** Borders
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--border-color: var(--color-theta);
|
||||
|
||||
/** Text Color
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--text-color: var(--color-gamma);
|
||||
--text-color-minus: var(--color-eta);
|
||||
--label-color: #000;
|
||||
|
||||
/** Button
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--button-background: var(--color-iota);
|
||||
|
||||
/** Links
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--link-color: var(--highlight-color);
|
||||
|
||||
/** Inputs
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--input-background: var(--color-beta);
|
||||
--input-color: var(--color-alpha);
|
||||
--input-clear-background: #909ca7;
|
||||
|
||||
/** Buttons
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--button-box-shadow:
|
||||
inset 0 -1px 0 #d8d8d8,
|
||||
inset 0 1px 0 #eeeeee;
|
||||
--button-box-shadow-active: var(--button-box-shadow);
|
||||
|
||||
/** Header
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--header-disabled-button-color: rgba(255,255,255,0.3);
|
||||
|
||||
/** Transitions
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--transition-duration: 0.2s;
|
||||
}
|
||||
|
||||
|
||||
.theme-productivity {
|
||||
|
||||
/** Brand Color
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--highlight-color: var(--color-orange);
|
||||
|
||||
/** Header
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--header-background: var(--highlight-color);
|
||||
--header-color: var(--color-beta);
|
||||
}
|
||||
|
||||
.theme-communications {
|
||||
|
||||
/** Brand Color
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--highlight-color: var(--color-turquoise);
|
||||
|
||||
/** Links
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--link-color: #177874;
|
||||
|
||||
/** Header
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--header-background: var(--highlight-color);
|
||||
--header-color: var(--color-beta);
|
||||
--header-icon-color: var(--color-beta);
|
||||
--header-button-color: var(--link-color);
|
||||
}
|
||||
|
||||
.theme-settings {
|
||||
|
||||
/** Background
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--background: var(--color-iota);
|
||||
--background-plus: var(--color-beta);
|
||||
--background-minus: var(--color-epsilon);
|
||||
--background-minus-minus: var(--color-zeta);
|
||||
|
||||
/** Highlight
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--highlight-color: var(--color-blue);
|
||||
|
||||
/** Borders
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--border-color: var(--color-theta);
|
||||
|
||||
/** Text Color
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--text-color: var(--color-gamma);
|
||||
|
||||
/** Titles
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--title-color: var(--background-minus);
|
||||
|
||||
/** Buttons
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--button-background: var(--background-plus);
|
||||
|
||||
/** Switch
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--switch-background: var(--background-minus-minus);
|
||||
|
||||
/** Checkbox
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--checkbox-border-color: var(--background-minus-minus);
|
||||
|
||||
/** Header
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--header-color: var(--title-color);
|
||||
--header-background: var(--background);
|
||||
--header-button-color: var(--highlight-color);
|
||||
--header-disabled-button-color: var(--color-theta);
|
||||
--header-action-button-color: var(--title-color);
|
||||
}
|
||||
|
||||
.theme-media {
|
||||
|
||||
/** Highlight Color
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--highlight-color: var(--color-blue);
|
||||
|
||||
/** Background
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--background: var(--color-alpha);
|
||||
--background-plus: var(--color-gamma);
|
||||
--background-minus: #2B2B2B;
|
||||
--background-minus-minus: #1a1a1a;
|
||||
|
||||
/** Text Color
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--text-color: var(--color-beta);
|
||||
--label-color: var(--color-beta);
|
||||
|
||||
/** Button
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--button-background: var(--background-plus);
|
||||
|
||||
/** Header
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--header-background: var(--background);
|
||||
--header-icon-color: var(--text-color);
|
||||
--header-button-color: var(--highlight-color);
|
||||
|
||||
/** Borders
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--border-color: var(--color-gamma);
|
||||
|
||||
/** Inputs
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--input-background: var(--background-plus);
|
||||
|
||||
/** Text Input
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--text-input-background: var(--background-minus);
|
||||
|
||||
/** Switch
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--switch-head-border-color: var(--background-minus-minus);
|
||||
--switch-background: var(--background-minus-minus);
|
||||
|
||||
/** Checkbox
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--checkbox-border-color: var(--background-minus-minus);
|
||||
|
||||
/** Buttons
|
||||
---------------------------------------------------------*/
|
||||
|
||||
--button-box-shadow: none;
|
||||
--button-box-shadow-active: none;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 178 B |
Binary file not shown.
|
After Width: | Height: | Size: 245 B |
|
|
@ -0,0 +1,62 @@
|
|||
'use strict';
|
||||
/* global ComponentUtils */
|
||||
|
||||
window.GaiaMenu = (function(win) {
|
||||
// Extend from HTMLElement prototype
|
||||
var proto = Object.create(HTMLElement.prototype);
|
||||
|
||||
// Allow baseurl to be overridden (used for demo page)
|
||||
var baseurl = window.GaiaMenuBaseurl ||
|
||||
'/shared/elements/gaia_menu/';
|
||||
|
||||
proto.createdCallback = function () {
|
||||
var shadow = this.createShadowRoot();
|
||||
|
||||
this._template = template.content.cloneNode(true);
|
||||
|
||||
var cancelButton = this._template.querySelector('.gaia-menu-cancel button');
|
||||
|
||||
cancelButton.addEventListener('click', function () {
|
||||
this.hide();
|
||||
this.dispatchEvent(new CustomEvent('gaiamenu-cancel'));
|
||||
}.bind(this));
|
||||
|
||||
shadow.appendChild(this._template);
|
||||
|
||||
ComponentUtils.style.call(this, baseurl);
|
||||
|
||||
document.l10n.ready.then(this.localize.bind(this));
|
||||
document.addEventListener('DOMRetranslated', this.localize.bind(this));
|
||||
};
|
||||
|
||||
proto.localize = function() {
|
||||
document.l10n.formatValue('gaia-menu-cancel').then(value => {
|
||||
this.shadowRoot.querySelector('button').textContent = value;
|
||||
});
|
||||
};
|
||||
|
||||
proto.show = function() {
|
||||
this.removeAttribute('hidden');
|
||||
};
|
||||
|
||||
proto.hide = function() {
|
||||
this.setAttribute('hidden', 'hidden');
|
||||
};
|
||||
|
||||
var template = document.createElement('template');
|
||||
|
||||
template.innerHTML =
|
||||
`<form role="dialog" data-type="action">
|
||||
<content select="header"></content>
|
||||
<menu>
|
||||
<content select="button"></content>
|
||||
<span class="gaia-menu-cancel">
|
||||
<button>Cancel</button>
|
||||
</span>
|
||||
</menu>
|
||||
</form>`;
|
||||
|
||||
// Register and return the constructor
|
||||
return document.registerElement('gaia-menu', { prototype: proto });
|
||||
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,314 @@
|
|||
/* ----------------------------------
|
||||
* gaia_menu
|
||||
* ---------------------------------- */
|
||||
|
||||
/* default alignment follows the UI direction, not the content direction */
|
||||
:-moz-dir(ltr) [dir] { text-align: left; }
|
||||
:-moz-dir(rtl) [dir] { text-align: right; }
|
||||
|
||||
/* Main dialog setup */
|
||||
gaia-menu {
|
||||
background-color: #2d2d2d;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 0 0 7rem;
|
||||
/**
|
||||
* Using "font-size: 0" to avoid the unwanted visual space (about 3px) created
|
||||
* by white spaces and line breaks in the code between inline-block elements.
|
||||
*/
|
||||
font-size: 0;
|
||||
color: #fff;
|
||||
display: block;
|
||||
transition: transform ease-in-out var(--transition-duration),
|
||||
visibility var(--transition-duration);
|
||||
}
|
||||
|
||||
gaia-menu[hidden] {
|
||||
transform: translateY(100%);
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
gaia-menu:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 0.1rem;
|
||||
height: 100%;
|
||||
margin-inline-start: -0.1rem;
|
||||
}
|
||||
|
||||
header {
|
||||
-moz-box-sizing: border-box;
|
||||
font-size: 1.6rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
height: 5rem;
|
||||
line-height: 4.9rem;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
font-weight: normal;
|
||||
padding: 0 3rem;
|
||||
border-bottom: 0.1rem solid #616262;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 1.6rem;
|
||||
line-height: 4.9rem;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Generic set of actions in toolbar */
|
||||
header menu.toolbar {
|
||||
height: 100%;
|
||||
margin: 0 -3rem;
|
||||
margin-inline-start: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
header:-moz-dir(ltr) menu.toolbar { float: right; }
|
||||
header:-moz-dir(rtl) menu.toolbar { float: left; }
|
||||
|
||||
header menu.toolbar a,
|
||||
header menu.toolbar button {
|
||||
-moz-box-sizing: border-box;
|
||||
position: relative;
|
||||
width: auto;
|
||||
min-width: 5rem;
|
||||
height: 4.9rem;
|
||||
margin-bottom: 0;
|
||||
padding: 0 1rem;
|
||||
border-radius: 0;
|
||||
line-height: 4.9rem;
|
||||
background: none;
|
||||
text-align: center;
|
||||
text-shadow: none;
|
||||
z-index: 5;
|
||||
}
|
||||
header:-moz-dir(ltr) menu.toolbar a,
|
||||
header:-moz-dir(ltr) menu.toolbar button {
|
||||
float: left;
|
||||
}
|
||||
header:-moz-dir(rtl) menu.toolbar a,
|
||||
header:-moz-dir(rtl) menu.toolbar button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
header a,
|
||||
header button {
|
||||
border: none;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
font-weight: 400;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.1em;
|
||||
color: #fff;
|
||||
border-radius: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner {
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Pressed state */
|
||||
header a:active .icon:after,
|
||||
header button:active .icon:after,
|
||||
header menu.toolbar a:active,
|
||||
header menu.toolbar button:active {
|
||||
background: #008aaa;
|
||||
}
|
||||
|
||||
/* Disabled state */
|
||||
header menu.toolbar a[aria-disabled="true"],
|
||||
header menu.toolbar button[disabled] {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Icon definitions */
|
||||
header .icon {
|
||||
position: relative;
|
||||
float: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 4rem;
|
||||
height: 4.9rem;
|
||||
margin: 0 -1rem;
|
||||
background: transparent no-repeat center center / 3rem auto;
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header .icon.icon-close {
|
||||
background-image: url(images/icons/close.png);
|
||||
}
|
||||
|
||||
header .icon.icon-back {
|
||||
background-image: url(images/icons/back.png);
|
||||
}
|
||||
|
||||
/* Navigation links (back, cancel, etc) */
|
||||
header > button,
|
||||
header > a {
|
||||
width: 5rem;
|
||||
height: 4.9rem;
|
||||
background: none;
|
||||
overflow: visible;
|
||||
margin: 0 -1rem;
|
||||
margin-inline-start: -3rem;
|
||||
position: relative;
|
||||
}
|
||||
header:-moz-dir(ltr) > button,
|
||||
header:-moz-dir(ltr) > a {
|
||||
float: left;
|
||||
}
|
||||
header:-moz-dir(rtl) > button,
|
||||
header:-moz-dir(rtl) > a {
|
||||
float: right;
|
||||
}
|
||||
|
||||
header > button::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
header > button .icon,
|
||||
header > a .icon {
|
||||
position: static;
|
||||
display: block;
|
||||
width: 3rem;
|
||||
height: 4.9rem;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
header > button .icon:after,
|
||||
header > a .icon:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
offset-inline-start: 0;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
width: 3rem;
|
||||
height: 4.9rem;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
section {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 7rem;
|
||||
left: 1.5rem;
|
||||
right: 1.5rem;
|
||||
bottom: 2rem;
|
||||
font-size: 1.6rem;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
/* Specific component code */
|
||||
menu {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-height: calc(100% - 13.5rem); /*header(5rem) + footer(7rem) + padding(1.5rem)*/
|
||||
height: auto;
|
||||
padding-top: 1.5rem;
|
||||
overflow: auto;
|
||||
width: auto;
|
||||
border: none;
|
||||
background: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 7rem;
|
||||
}
|
||||
|
||||
button {
|
||||
width: calc(100% - 3rem);
|
||||
height: 4rem;
|
||||
-moz-box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
font-weight: normal;
|
||||
line-height: 4rem;
|
||||
outline: none;
|
||||
font-size: 1.6rem;
|
||||
text-shadow: none;
|
||||
padding: 0 1.2rem;
|
||||
margin: 0 1.5rem 1rem;
|
||||
background: rgba(87, 87, 87, 0.8);
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
}
|
||||
button:-moz-dir(ltr) { text-align: left; }
|
||||
button:-moz-dir(rtl) { text-align: right; }
|
||||
|
||||
span.gaia-menu-cancel {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background: #4d4d4d;
|
||||
height: 7rem;
|
||||
offset-inline-start: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
span.gaia-menu-cancel button {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
offset-inline-start: 0;
|
||||
color: #333;
|
||||
background: #d8d8d8;
|
||||
text-align: center;
|
||||
border: none;
|
||||
margin-bottom: 1.5rem;
|
||||
border-radius: 2rem;
|
||||
}
|
||||
|
||||
button:nth-last-child(2) {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
/* Press state */
|
||||
button:active,
|
||||
span.gaia-menu-cancel button:active {
|
||||
background: #00aacc;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
button[disabled] {
|
||||
background-color: rgba(87, 87, 87, 0.8);
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
button[disabled]:last-child {
|
||||
background-color: #e7e7e7;
|
||||
color: #a6a6a6;
|
||||
opacity: 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* ComponentUtils is a utility which allows us to use web components earlier
|
||||
* than we should be able to by polyfilling and fixing platform deficiencies.
|
||||
*/
|
||||
exports.ComponentUtils = {
|
||||
|
||||
/**
|
||||
* Injects a style.css into both the shadow root and outside the shadow
|
||||
* root so we can style projected content. Bug 992249.
|
||||
*/
|
||||
style: function(baseUrl) { if (window.VulpesCompat) { window.VulpesCompat.componentStyle(this, baseUrl).catch(console.error); return; }
|
||||
var style = document.createElement('style');
|
||||
var url = baseUrl + 'style.css';
|
||||
var self = this;
|
||||
|
||||
style.setAttribute('scoped', '');
|
||||
style.innerHTML = '@import url(' + url + ');';
|
||||
this.appendChild(style);
|
||||
|
||||
this.style.visibility = 'hidden';
|
||||
|
||||
// Wait for the stylesheet to load before injecting
|
||||
// it into the shadow-dom. This is to work around
|
||||
// bug 1003294, let's review once landed.
|
||||
style.addEventListener('load', function() {
|
||||
|
||||
// Put a clone of the stylesheet into the shadow-dom.
|
||||
// We have to use two <style> nodes, to work around
|
||||
// the lack of `:host` (bug 992245) and `:content`
|
||||
// (bug 992249) selectors. Once we have those we
|
||||
// can do all our styling from a single style-sheet
|
||||
// within the shadow-dom.
|
||||
if (self.shadowRoot) {
|
||||
self.shadowRoot.appendChild(style.cloneNode(true));
|
||||
}
|
||||
|
||||
self.style.visibility = '';
|
||||
});
|
||||
}
|
||||
};
|
||||
}(window));
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
;(function(exports){'use strict';var NUMBER_OF_DECIMALS=2;var BYTE_SCALE=['B','KB','MB','GB','TB'];function _getFormattedSize(bytes){if(bytes===undefined||isNaN(bytes)){return Promise.resolve(null);}
|
||||
var index=0;while(bytes>=1024&&index<BYTE_SCALE.length){bytes/=1024;++index;}
|
||||
return document.l10n.formatValue('byteUnit-'+BYTE_SCALE[index]).then(unit=>{return document.l10n.formatValue('fileSize',{size:bytes.toFixed(NUMBER_OF_DECIMALS),unit:unit});});}
|
||||
function _calcPercentage(currently,total){if(total===0){return 0;}
|
||||
return parseInt((100*currently)/total);}
|
||||
var DownloadFormatter={getFormattedSize:function(bytes){return _getFormattedSize(bytes);},getPercentage:function(download){return _calcPercentage(download.currentBytes,download.totalBytes);},getFileName:function(download){return download.path.split('/').pop();},getTotalSize:function(download){var bytes=download.totalBytes;return _getFormattedSize(bytes);},getDownloadedSize:function(download){var bytes=download.currentBytes;return _getFormattedSize(bytes);},getDate:function(download){var date;try{date=download.startTime;}catch(ex){date=new Date();console.error(ex);}
|
||||
var formatter=mozIntl._gaia.RelativeDate(navigator.languages);return formatter.format(date);},getUUID:function(download){return download.id||this.getFileName(download);}};exports.DownloadFormatter=DownloadFormatter;}(this));
|
||||
|
|
@ -0,0 +1,685 @@
|
|||
'use strict';
|
||||
/* exported DownloadHelper */
|
||||
/* global DownloadFormatter */
|
||||
/* global DownloadStore */
|
||||
/* global DownloadUI */
|
||||
/* global LazyLoader */
|
||||
/* global MimeMapper */
|
||||
/* global MozActivity */
|
||||
/* global SettingsListener */
|
||||
|
||||
/*
|
||||
* DownloadHelper.js: Perform some utility functions with DOMDownload
|
||||
* objects.
|
||||
*
|
||||
* - You have to include in you HTML:
|
||||
*
|
||||
* <!-- <script src="shared/js/mime_mapper.js"></script> -->
|
||||
* <!-- <script src="shared/js/download/download_store.js"></script> -->
|
||||
* <script defer src="shared/js/lazy_loader.js"></script>
|
||||
*
|
||||
* - How to use this component.
|
||||
*
|
||||
* For launching a download
|
||||
*
|
||||
* var req = DownloadHelper.open(download);
|
||||
*
|
||||
* req.onsuccess = function req_onsuccess() {
|
||||
* alert('The download was opened so we can remove the notification');
|
||||
* }
|
||||
*
|
||||
* req.onerror = function req_onerror() {
|
||||
* alert('Something wrong!: ' + req.error.message);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
var DownloadHelper = (function() {
|
||||
|
||||
// Exception code constants
|
||||
var CODE = {
|
||||
FILE_NOT_FOUND: 'FILE_NOT_FOUND',
|
||||
DEVICE_STORAGE: 'DEVICE_STORAGE',
|
||||
MIME_TYPE_NOT_SUPPORTED: 'MIME_TYPE_NOT_SUPPORTED',
|
||||
INVALID_STATE: 'INVALID_STATE',
|
||||
NO_SDCARD: 'NO_SDCARD',
|
||||
NO_PROVIDER: 'NO_PROVIDER',
|
||||
UNMOUNTED_SDCARD: 'UNMOUNTED_SDCARD'
|
||||
};
|
||||
|
||||
/*
|
||||
* Request auxiliary object to support asynchronous calls
|
||||
*/
|
||||
var Request = function() {
|
||||
this.done = function(result) {
|
||||
if (typeof this.onsuccess === 'function') {
|
||||
this.result = result;
|
||||
window.setTimeout(function() {
|
||||
this.onsuccess({
|
||||
target: this
|
||||
});
|
||||
}.bind(this), 0);
|
||||
}
|
||||
};
|
||||
|
||||
this.failed = function(error) {
|
||||
if (typeof this.onerror === 'function') {
|
||||
this.error = error;
|
||||
window.setTimeout(function() {
|
||||
this.onerror({
|
||||
target: this
|
||||
});
|
||||
}.bind(this), 0);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Storage name by default
|
||||
var STORAGE_NAME_BY_DEFAULT = 'sdcard';
|
||||
|
||||
// Storage name settings key
|
||||
var STORAGE_NAME_KEY = 'device.storage.writable.name';
|
||||
|
||||
// Current storage name
|
||||
var storageName = STORAGE_NAME_BY_DEFAULT;
|
||||
|
||||
LazyLoader.load('shared/js/settings_listener.js', function settingsLoaded() {
|
||||
SettingsListener.observe(STORAGE_NAME_KEY, STORAGE_NAME_BY_DEFAULT,
|
||||
function setStorageName(evt) {
|
||||
var settingValue = evt.settingValue;
|
||||
if (settingValue) {
|
||||
storageName = settingValue;
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
/*
|
||||
* Error auxiliary method
|
||||
*/
|
||||
function sendError(req, message, code) {
|
||||
req.failed({
|
||||
message: message,
|
||||
code: code
|
||||
});
|
||||
|
||||
console.error(message);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a blob from the sdcard
|
||||
*
|
||||
* @param{Object} The download object
|
||||
*
|
||||
*/
|
||||
function getBlob(download) {
|
||||
var req = new Request();
|
||||
var storage = getVolume(download.storageName);
|
||||
var storeAvailableReq = storage.available();
|
||||
|
||||
storeAvailableReq.onsuccess = function available_onsuccess(e) {
|
||||
var path = download.storagePath;
|
||||
switch (storeAvailableReq.result) {
|
||||
case 'unavailable':
|
||||
sendError(req, ' Could not open the file: ' + path + ' from ' +
|
||||
download.storageName, CODE.NO_SDCARD);
|
||||
break;
|
||||
|
||||
case 'shared':
|
||||
sendError(req, ' Could not open the file: ' + path + ' from ' +
|
||||
download.storageName, CODE.UNMOUNTED_SDCARD);
|
||||
break;
|
||||
|
||||
default:
|
||||
try {
|
||||
var storeGetReq = storage.get(path);
|
||||
|
||||
storeGetReq.onsuccess = function store_onsuccess() {
|
||||
req.done(storeGetReq.result);
|
||||
};
|
||||
|
||||
storeGetReq.onerror = function store_onerror() {
|
||||
sendError(req, storeGetReq.error.name +
|
||||
' Could not open the file: ' + path + ' from ' +
|
||||
download.storageName, CODE.FILE_NOT_FOUND);
|
||||
};
|
||||
} catch (ex) {
|
||||
sendError(req, 'Error getting the file ' + path + ' from ' +
|
||||
download.storageName, CODE.DEVICE_STORAGE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
storeAvailableReq.onerror = function available_onerror() {
|
||||
sendError(req, 'Error getting storage state ', CODE.DEVICE_STORAGE);
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
/*
|
||||
* Base action that implements the commom logic for actions based on the
|
||||
* MozActivity API
|
||||
*
|
||||
* @param{Object} Configuration parameters
|
||||
*/
|
||||
var Action = function Action(params) {
|
||||
this.req = params.request;
|
||||
this.name = params.actionType.activityName;
|
||||
};
|
||||
|
||||
Action.prototype = {
|
||||
/*
|
||||
* It performs the action based on MozActivity
|
||||
*/
|
||||
run: function a_run() {
|
||||
var activity = new MozActivity({
|
||||
name: this.name,
|
||||
data: this.data
|
||||
});
|
||||
|
||||
activity.onsuccess = this._onsuccess.bind(this);
|
||||
activity.onerror = this._onerror.bind(this);
|
||||
},
|
||||
|
||||
/*
|
||||
* This method implements the generic onsuccess callback
|
||||
*/
|
||||
_onsuccess: function a_onsuccess() {
|
||||
this.req.done();
|
||||
},
|
||||
|
||||
/*
|
||||
* This method implements the generic onerror callback
|
||||
*/
|
||||
_onerror: function a_onerror(evt) {
|
||||
this.req.failed({
|
||||
message: evt.target.error.name
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* This action opens downloads extending the Action Object
|
||||
*
|
||||
* @param{Object} Configuration parameters
|
||||
*/
|
||||
var OpenAction = function OpenAction(params) {
|
||||
Action.call(this, params);
|
||||
|
||||
this.data = {
|
||||
url: params.download.path,
|
||||
filename: DownloadFormatter.getFileName(params.download),
|
||||
type: params.type,
|
||||
blob: params.blob
|
||||
};
|
||||
};
|
||||
|
||||
OpenAction.prototype = {
|
||||
__proto__: Action.prototype
|
||||
};
|
||||
|
||||
/*
|
||||
* This action shares downloads extending the Action Object
|
||||
*
|
||||
* @param{Object} Configuration parameters
|
||||
*/
|
||||
var ShareAction = function ShareAction(params) {
|
||||
Action.call(this, params);
|
||||
|
||||
this.data = {
|
||||
// 'share' activities do not work with specific mime types
|
||||
type: params.type.split('/')[0] + '/*',
|
||||
blobs: [params.blob],
|
||||
filenames: [DownloadFormatter.getFileName(params.download)]
|
||||
};
|
||||
};
|
||||
|
||||
ShareAction.prototype = {
|
||||
__proto__: Action.prototype,
|
||||
|
||||
/*
|
||||
* It overrides the generic onerror callback for another more suitable
|
||||
*/
|
||||
_onerror: function sa_onerror(evt) {
|
||||
if (evt.target.error.name !== 'NO_PROVIDER') {
|
||||
return;
|
||||
}
|
||||
|
||||
sendError(this.req, 'No provider to share file', CODE.NO_PROVIDER);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* This action gets the info for a download
|
||||
*
|
||||
* @param{Object} Configuration parameters
|
||||
*/
|
||||
var InfoAction = function InfoAction(params) {
|
||||
Action.call(this, params);
|
||||
|
||||
this.data = {
|
||||
name: DownloadFormatter.getFileName(params.download),
|
||||
type: params.type,
|
||||
blob: params.blob,
|
||||
size: params.download.totalBytes,
|
||||
path: params.download.path
|
||||
};
|
||||
};
|
||||
|
||||
InfoAction.prototype = {
|
||||
__proto__: Action.prototype,
|
||||
|
||||
/*
|
||||
* It overrides the generic run method
|
||||
*/
|
||||
run: function ia_run() {
|
||||
this.req.done(this.data);
|
||||
}
|
||||
};
|
||||
|
||||
// This is a factory that deals with different <Action> objects
|
||||
var ActionsFactory = {
|
||||
TYPE: {
|
||||
OPEN: {
|
||||
activityName: 'open',
|
||||
actionClass: OpenAction
|
||||
},
|
||||
SHARE: {
|
||||
activityName: 'share',
|
||||
actionClass: ShareAction
|
||||
},
|
||||
INFO: {
|
||||
actionClass: InfoAction
|
||||
},
|
||||
WALLPAPER: {
|
||||
activityName: 'setwallpaper',
|
||||
actionClass: ShareAction
|
||||
},
|
||||
RINGTONE: {
|
||||
activityName: 'setringtone',
|
||||
actionClass: ShareAction
|
||||
}
|
||||
},
|
||||
|
||||
create: function af_create(params) {
|
||||
return new params.actionType.actionClass(params);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns the mime type
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*
|
||||
* @returns(String) Mime type
|
||||
*/
|
||||
function getType(download) {
|
||||
var fileName = DownloadFormatter.getFileName(download);
|
||||
var type = MimeMapper.guessTypeFromFileProperties(fileName,
|
||||
download.contentType);
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method allows third-parties to open or share downloads
|
||||
*
|
||||
* @param{Object} Action types: <ActionsFactory.TYPE.OPEN> or
|
||||
* <ActionsFactory.TYPE.SHARE>
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*/
|
||||
function runAction(actionType, download) {
|
||||
var req = new Request();
|
||||
|
||||
window.setTimeout(function launching() {
|
||||
var state = download.state;
|
||||
if (state === 'succeeded' || state === 'finalized') {
|
||||
LazyLoader.load(['shared/js/mime_mapper.js',
|
||||
'shared/js/download/download_formatter.js'],
|
||||
function loaded() {
|
||||
var type = getType(download);
|
||||
|
||||
//
|
||||
// The 'open' action will always launch an activity using the original
|
||||
// content type to allow for third party applications to handle
|
||||
// arbitrary types of content.
|
||||
//
|
||||
// The 'share' action on the other hand only works with known mime
|
||||
// types at this time.
|
||||
//
|
||||
|
||||
if (type.length === 0) {
|
||||
type = download.contentType;
|
||||
|
||||
if (actionType !== ActionsFactory.TYPE.OPEN &&
|
||||
actionType !== ActionsFactory.TYPE.INFO) {
|
||||
sendError(req, 'Mime type not supported: ' + type,
|
||||
CODE.MIME_TYPE_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var blobReq = getBlob(download);
|
||||
|
||||
blobReq.onsuccess = function() {
|
||||
ActionsFactory.create({
|
||||
actionType: actionType,
|
||||
download: download,
|
||||
type: type,
|
||||
blob: blobReq.result,
|
||||
request: req
|
||||
}).run();
|
||||
};
|
||||
|
||||
blobReq.onerror = function() {
|
||||
// Problem getting the blob from the sdcard
|
||||
req.failed(blobReq.error);
|
||||
};
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
sendError(req, 'Becareful, the download is not finished!',
|
||||
CODE.INVALID_STATE);
|
||||
}, 0);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method allows clients to remove a download, from the
|
||||
* list and the phone.
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*/
|
||||
function remove(download) {
|
||||
var req = new Request();
|
||||
var incompleteDownload = download.state !== 'succeeded';
|
||||
// If is not done, use download manager to remove it,
|
||||
// otherwise, deal with the datastore.
|
||||
setTimeout(function() {
|
||||
if (incompleteDownload) {
|
||||
if (!navigator.mozDownloadManager) {
|
||||
sendError(req, 'DownloadManager not present', CODE.INVALID_STATE);
|
||||
} else {
|
||||
// First we pause the download so that everyone knows it's being
|
||||
// stopped. The Downloads API itself won't stop the download first,
|
||||
// it will simply kill it.
|
||||
// XXXAus: Remove when we fix bug #1090551
|
||||
download.pause().then(
|
||||
function() {
|
||||
navigator.mozDownloadManager.remove(download).then(
|
||||
function success() {
|
||||
req.done(download);
|
||||
},
|
||||
function error() {
|
||||
sendError(req,
|
||||
'DownloadManager doesnt know about this download',
|
||||
CODE.INVALID_STATE);
|
||||
}
|
||||
);
|
||||
},
|
||||
function() {
|
||||
sendError(req,
|
||||
'Failed to pause download before removal',
|
||||
CODE.INVALID_STATE);
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
req.done(download);
|
||||
}
|
||||
}, 0);
|
||||
|
||||
return incompleteDownload ? req : doRemoveFromPhone(req, download);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs the proper delete of the physical file, also
|
||||
* from the datastore if the download has finished.
|
||||
*
|
||||
* @param{Object} This is the Request object
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*/
|
||||
function doRemoveFromPhone(deleteRequest, download) {
|
||||
var req = new Request();
|
||||
|
||||
deleteRequest.onsuccess = function() {
|
||||
var storage = getVolume(download.storageName);
|
||||
var storeAvailableReq = storage.available();
|
||||
|
||||
storeAvailableReq.onsuccess = function available_onsuccess(e) {
|
||||
var path = download.path;
|
||||
switch (storeAvailableReq.result) {
|
||||
case 'unavailable':
|
||||
sendError(req, ' Could not delete the file: ' + path + ' from ' +
|
||||
storageName, CODE.NO_SDCARD);
|
||||
break;
|
||||
|
||||
case 'shared':
|
||||
sendError(req, ' Could not delete the file: ' + path + ' from ' +
|
||||
storageName, CODE.UNMOUNTED_SDCARD);
|
||||
break;
|
||||
|
||||
default:
|
||||
var storeDeleteReq = storage.delete(download.storagePath);
|
||||
|
||||
storeDeleteReq.onsuccess = function store_onsuccess() {
|
||||
// Remove from the datastore if status is 'succeeded'
|
||||
// if we find any problem with the datastore, don't send
|
||||
// an error, since the physical remove already happened
|
||||
if (download.state === 'succeeded') {
|
||||
LazyLoader.load(['/shared/js/download/download_store.js'],
|
||||
function() {
|
||||
DownloadStore.remove(download);
|
||||
}
|
||||
);
|
||||
}
|
||||
req.done(storeDeleteReq.result);
|
||||
};
|
||||
|
||||
storeDeleteReq.onerror = function store_onerror() {
|
||||
sendError(req, storeDeleteReq.error.name +
|
||||
' Could not remove the file: ' + download.path + ' from ' +
|
||||
storageName, CODE.FILE_NOT_FOUND);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
storeAvailableReq.onerror = function available_onerror() {
|
||||
sendError(req, 'Error getting storage state ', CODE.DEVICE_STORAGE);
|
||||
};
|
||||
};
|
||||
|
||||
deleteRequest.onerror = function(error) {
|
||||
sendError(req, error.message, error.code);
|
||||
};
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
function handlerError(error, download, cb) {
|
||||
LazyLoader.load('shared/js/download/download_ui.js', (function loaded() {
|
||||
var req;
|
||||
var show = DownloadUI.show;
|
||||
|
||||
// Canceled activites are normal and shouldn't be interpreted as errors.
|
||||
// Unfortunately, this isn't reported in a standard way by our
|
||||
// applications (or third party apps for that matter). This is why we
|
||||
// have this lazy filter here that may need to be updated in the future
|
||||
// but hopefully will just get removed.
|
||||
if (error.message &&
|
||||
(error.message.endsWith('canceled') ||
|
||||
error.message.endsWith('cancelled'))) {
|
||||
// Since this isn't actually an error, we invoke the callback with null.
|
||||
cb && cb(null);
|
||||
// and return early.
|
||||
return;
|
||||
}
|
||||
|
||||
switch (error.code) {
|
||||
case CODE.NO_SDCARD:
|
||||
case CODE.UNMOUNTED_SDCARD:
|
||||
case CODE.FILE_NOT_FOUND:
|
||||
case CODE.NO_PROVIDER:
|
||||
req = show(DownloadUI.TYPE[error.code], download, true);
|
||||
req.onconfirm = cb;
|
||||
|
||||
break;
|
||||
|
||||
case CODE.MIME_TYPE_NOT_SUPPORTED:
|
||||
req = show(DownloadUI.TYPE.UNSUPPORTED_FILE_TYPE, download, true);
|
||||
req.onconfirm = function tuftOnConfirm() {
|
||||
showRemoveFileUI(download, cb);
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
req = show(DownloadUI.TYPE.FILE_OPEN_ERROR, download, true);
|
||||
req.onconfirm = function tfoeOnConfirm() {
|
||||
showRemoveFileUI(download, cb);
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
// We have to remove the notification if the user cancels
|
||||
req.oncancel = cb;
|
||||
}));
|
||||
}
|
||||
|
||||
function showRemoveFileUI(download, cb) {
|
||||
var req = DownloadUI.show(DownloadUI.TYPE.DELETE, download, true);
|
||||
|
||||
req.oncancel = cb;
|
||||
|
||||
req.onconfirm = function doRemove() {
|
||||
if (typeof cb === 'function') {
|
||||
cb(download);
|
||||
} else {
|
||||
remove(download);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getFreeSpace(cb) {
|
||||
var storage = navigator.getDeviceStorage(storageName);
|
||||
|
||||
if (!storage) {
|
||||
console.error('Cannot get free space size in sdcard');
|
||||
cb(null);
|
||||
return;
|
||||
}
|
||||
|
||||
var req = storage.freeSpace();
|
||||
|
||||
req.onsuccess = function(e) {
|
||||
cb(e.target.result);
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
cb(null);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the storage for the download based on the volumen
|
||||
* it was saved (storageName)
|
||||
*/
|
||||
function getVolume(volumeName) {
|
||||
// Per API design, all media type return the same volumes.
|
||||
// So we use 'sdcard' here for no reason.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=856782#c10
|
||||
var volumes = navigator.getDeviceStorages('sdcard');
|
||||
if (!volumeName || volumeName === '') {
|
||||
return volumes[0];
|
||||
}
|
||||
for (var i = 0; i < volumes.length; ++i) {
|
||||
if (volumes[i].storageName === volumeName) {
|
||||
return volumes[i];
|
||||
}
|
||||
}
|
||||
return volumes[0];
|
||||
}
|
||||
|
||||
return {
|
||||
/*
|
||||
* This method allows clients to open a downlaod
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*/
|
||||
open: function(download) {
|
||||
return runAction(ActionsFactory.TYPE.OPEN, download);
|
||||
},
|
||||
|
||||
/*
|
||||
* This method allows clients to share a downlaoded file
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*/
|
||||
share: function(download) {
|
||||
return runAction(ActionsFactory.TYPE.SHARE, download);
|
||||
},
|
||||
|
||||
/*
|
||||
* This method allows clients to set as wallaper a downlaoded file
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*/
|
||||
wallpaper: function(download) {
|
||||
return runAction(ActionsFactory.TYPE.WALLPAPER, download);
|
||||
},
|
||||
|
||||
/*
|
||||
* This method allows clients to set as ringtone a downlaoded file
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*/
|
||||
ringtone: function(download) {
|
||||
return runAction(ActionsFactory.TYPE.RINGTONE, download);
|
||||
},
|
||||
|
||||
/*
|
||||
* This method returns information about a download
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*/
|
||||
info: function(download) {
|
||||
return runAction(ActionsFactory.TYPE.INFO, download);
|
||||
},
|
||||
|
||||
/*
|
||||
* Given a download, remove it from the DownloadManager
|
||||
* list, and the file system.
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*/
|
||||
remove: remove,
|
||||
|
||||
/*
|
||||
* Returns exception code constants
|
||||
*/
|
||||
get CODE() {
|
||||
return CODE;
|
||||
},
|
||||
|
||||
/*
|
||||
* This method handles different errors when users attemp to open files
|
||||
*
|
||||
* @param{Object} Error object
|
||||
*
|
||||
* @param{Object} It represents a DOMDownload object
|
||||
*
|
||||
* @param{Function} This function is performed when the flow is finished
|
||||
*/
|
||||
handlerError: handlerError,
|
||||
|
||||
/*
|
||||
* Returns the free memory size in bytes
|
||||
*
|
||||
* @param{Function} This function is performed when the free memory size has
|
||||
* been calculated
|
||||
*/
|
||||
getFreeSpace: getFreeSpace
|
||||
};
|
||||
}());
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
;'use strict';var DownloadStore=(function(){var datastore;const DATASTORE_NAME='download_store';var downloadListDB;var downloadList=[];var lastRevisionId;const LIST_DB='download_list';const LIST_STORE='download_list';const LIST_KEY=0;const REVISION_KEY=1;var Request=function(){this.done=function(result){if(typeof this.onsuccess==='function'){this.result=result;window.setTimeout(function(){this.onsuccess({target:this});}.bind(this),0);}};this.failed=function(error){if(typeof this.onerror==='function'){this.error=error;window.setTimeout(function(){this.onerror({target:this});}.bind(this),0);}};};function promisify(request){return new Promise(function(resolve,reject){request.onsuccess=(event)=>{resolve(event.target.result);};request.onerror=(event)=>{reject(event.target.errorCode);};});}
|
||||
var readyState;function init(success,fail){if(readyState==='initialized'){success();return;}
|
||||
if(readyState==='initializing'){document.addEventListener('ds-initialized',function oninitalized(){document.removeEventListener('ds-initialized',oninitalized);success();});return;}
|
||||
readyState='initializing';if(!navigator.getDataStores){var messageError='Data store: DataStore API is not working';console.error(messageError);fail({message:messageError});return;}
|
||||
navigator.getDataStores(DATASTORE_NAME).then(function(ds){var messageError='Download Store: Cannot get access to the DataStore';if(ds.length<1){console.error(messageError);throw({message:messageError});}
|
||||
datastore=ds[0];}).then(function(){return openDownloadListIndexedDB();}).then(function(db){downloadListDB=db;var listStore=downloadListDB.transaction(LIST_STORE,'readonly').objectStore(LIST_STORE);return Promise.all([promisify(listStore.get(LIST_KEY)).then((value)=>{downloadList=value;}),promisify(listStore.get(REVISION_KEY)).then((value)=>{lastRevisionId=value;})]);}).then(function(){readyState='initialized';const LEGACY_INDEX_ID=1;if(downloadList&&downloadList.includes(LEGACY_INDEX_ID)){return promisify(get(LEGACY_INDEX_ID)).then((download)=>{if('byTimestamp'in download){downloadList.splice(downloadList.indexOf(LEGACY_INDEX_ID),1);}});}}).then(function(){notifyOpenSuccess(success);}).catch(function(e){console.error('Error while opening the Download Store: ',e.message);fail(e);});}
|
||||
function openDownloadListIndexedDB(){return new Promise(function(resolve,reject){var request=indexedDB.open(LIST_DB);request.onsuccess=function(event){var db=event.target.result;resolve(db);};request.onerror=function(event){reject(event.target.errorCode);};request.onupgradeneeded=function(event){var db=event.target.result;promisify(db.createObjectStore(LIST_STORE)).then(()=>{var listStore=db.transaction(LIST_STORE,'readwrite').objectStore(LIST_STORE);return Promise.all([promisify(listStore.add([],LIST_KEY)),promisify(listStore.add(0,REVISION_KEY))]);}).catch(reject);};request.onblocked=function(event){reject(event.target.errorCode);};});}
|
||||
function notifyOpenSuccess(cb){window.setTimeout(cb,0);document.dispatchEvent(new CustomEvent('ds-initialized'));}
|
||||
var fieldsToPropagate=['url','path','totalBytes','contentType','startTime','state','storageName','storagePath'];function cookDownload(download){var ret=Object.create(null);fieldsToPropagate.forEach(function(field){ret[field]=download[field];});ret.finalizeTime=new Date();return ret;}
|
||||
function defaultError(req){return defaultErrorCb.bind(null,req);}
|
||||
function defaultErrorCb(request,error){request.failed(error);}
|
||||
function defaultSuccess(req){return defaultSuccessCb.bind(null,req);}
|
||||
function defaultSuccessCb(request,result){request.done(result);}
|
||||
function updateDownloadList(){var cursor=datastore.sync(lastRevisionId);function cursorResolve(task){switch(task.operation){case'done':lastRevisionId=task.revisionId;var listStore=downloadListDB.transaction(LIST_STORE,'readwrite').objectStore(LIST_STORE);return Promise.all([promisify(listStore.put(downloadList,LIST_KEY)),promisify(listStore.put(lastRevisionId,REVISION_KEY))]);case'clear':downloadList=[];break;case'add':downloadList.push(task.id);break;case'update':break;case'remove':var i=downloadList.indexOf(task.id);if(i>=0){downloadList.splice(i,1);}
|
||||
break;}
|
||||
return cursor.next().then(cursorResolve);}
|
||||
return cursor.next().then(cursorResolve);}
|
||||
function doAdd(download,req){var downloadCooked=cookDownload(download);datastore.add(downloadCooked).then(function(id){downloadCooked.id=id;datastore.put(downloadCooked,id).then(function(){req.done(downloadCooked);},defaultError(req));},defaultError(req));}
|
||||
function add(download){var req=new Request();window.setTimeout(function(){init(doAdd.bind(null,download,req),req.failed.bind(req));});return req;}
|
||||
function doGet(id,req){datastore.get(id).then(function(download){req.done(download);},defaultError(req));}
|
||||
function get(id){var req=new Request();window.setTimeout(function(){init(doGet.bind(null,id,req),req.failed.bind(req));});return req;}
|
||||
function doGetAll(req){updateDownloadList().then(function(){datastore.get.apply(datastore,downloadList).then(defaultSuccess(req),defaultError(req));},defaultError(req));}
|
||||
function getAll(){var req=new Request();window.setTimeout(function(){init(doGetAll.bind(null,req),req.failed.bind(req));});return req;}
|
||||
function doRemove(id,req){datastore.remove(id).then(function(success){if(success){defaultSuccess(req);}else{req.failed({message:'The download with id: '+id+'does not exist'});}},defaultError(req));}
|
||||
function remove(download){var req=new Request();window.setTimeout(function(){init(doRemove.bind(null,download.id,req),req.failed.bind(req));});return req;}
|
||||
function doAddListener(listener){datastore.addEventListener('change',listener);}
|
||||
function addListener(listener){var req=new Request();window.setTimeout(function(){init(doAddListener.bind(null,listener),req.failed.bind(req));});return req;}
|
||||
function doRemoveListener(listener){datastore.removeEventListener('change',listener);}
|
||||
function removeListener(listener){var req=new Request();window.setTimeout(function(){init(doRemoveListener.bind(null,listener),req.failed.bind(req));});return req;}
|
||||
return{get:get,getAll:getAll,add:add,remove:remove,addListener:addListener,removeListener:removeListener};}());
|
||||
|
|
@ -0,0 +1,358 @@
|
|||
'use strict';
|
||||
/* exported DownloadUI */
|
||||
/* global DownloadFormatter */
|
||||
/* global LazyLoader */
|
||||
/* global MimeMapper */
|
||||
|
||||
/**
|
||||
* This file defines a component to show download confirmations
|
||||
*
|
||||
* - Stop download (Are you sure you want to stop the download?)
|
||||
* - Download stopped (Download was stopped. Try downloading again?)
|
||||
* - Download failed (xfile failed to download. Try downloading again?)
|
||||
* - Delete download (Delete xfile?)
|
||||
* - Unsupported file type
|
||||
* - File not found
|
||||
* - File open error
|
||||
* - No provider to share file
|
||||
*
|
||||
* var request = DownloadUI.show(DownloadUI.TYPE.STOP, download);
|
||||
*
|
||||
* request.oncancel = function() {
|
||||
* alert('CANCEL');
|
||||
* };
|
||||
*
|
||||
* request.onconfirm = function() {
|
||||
* alert('CONFIRM');
|
||||
* };
|
||||
*
|
||||
* WARNING: To use this library you need to include 'shared/js/l10n.js'
|
||||
*
|
||||
*/
|
||||
var DownloadUI = (function() {
|
||||
|
||||
/**
|
||||
* Download type constructor
|
||||
*
|
||||
* @param {String} Type name
|
||||
* @param {Array} CSS classes to confirm button
|
||||
* @param {Boolean} Message without parameters
|
||||
*/
|
||||
var DownloadType = function(name, classes, isPlainMessage) {
|
||||
this.name = name;
|
||||
this.classes = classes;
|
||||
this.isPlainMessage = isPlainMessage;
|
||||
this.numberOfButtons = classes.indexOf('full') !== -1 ? 1 : 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Errors reported by the Downloads API.
|
||||
*/
|
||||
var ERRORS = {
|
||||
NO_MEMORY: 2152857616,
|
||||
NO_SDCARD: 2152857618,
|
||||
UNMOUNTED_SDCARD: 2152857621
|
||||
};
|
||||
|
||||
var TYPES = {
|
||||
STOP: new DownloadType('stop', ['danger'], true),
|
||||
STOPPED: new DownloadType('stopped', ['recommend'], true),
|
||||
FAILED: new DownloadType('failed', ['recommend']),
|
||||
DELETE: new DownloadType('delete', ['danger']),
|
||||
DELETE_ALL: new DownloadType('delete_all', ['danger']),
|
||||
UNSUPPORTED_FILE_TYPE: new DownloadType('unsupported_file_type',
|
||||
['danger']),
|
||||
FILE_NOT_FOUND: new DownloadType('file_not_found', ['recommend', 'full'],
|
||||
true),
|
||||
FILE_OPEN_ERROR: new DownloadType('file_open_error', ['danger']),
|
||||
NO_SDCARD: new DownloadType('no_sdcard_found_2', ['recommend', 'full'],
|
||||
true),
|
||||
UNMOUNTED_SDCARD: new DownloadType('unmounted_sdcard_2', ['recommend',
|
||||
'full'], true),
|
||||
NO_PROVIDER: new DownloadType('no_provider', ['recommend', 'full'], true),
|
||||
NO_MEMORY: new DownloadType('no_memory', ['recommend', 'full'], true)
|
||||
};
|
||||
|
||||
var DownloadAction = function(id, type) {
|
||||
this.id = id;
|
||||
this.name = id.toLowerCase();
|
||||
this.title = this.name + '_downloaded_file';
|
||||
this.type = type;
|
||||
};
|
||||
|
||||
var ACTIONS = {
|
||||
OPEN: new DownloadAction('OPEN', 'confirm'),
|
||||
SHARE: new DownloadAction('SHARE', 'confirm'),
|
||||
WALLPAPER: new DownloadAction('WALLPAPER', 'confirm'),
|
||||
RINGTONE: new DownloadAction('RINGTONE', 'confirm')
|
||||
};
|
||||
|
||||
// Confirm dialog containers
|
||||
var confirm = null;
|
||||
var actionMenu = null;
|
||||
|
||||
/**
|
||||
* Request auxiliary object to support asynchronous calls
|
||||
*/
|
||||
var Request = function() {
|
||||
this.cancel = function() {
|
||||
removeContainers();
|
||||
if (typeof this.oncancel === 'function') {
|
||||
this.oncancel();
|
||||
}
|
||||
};
|
||||
|
||||
this.confirm = function(result) {
|
||||
removeContainers();
|
||||
if (typeof this.onconfirm === 'function') {
|
||||
this.result = result;
|
||||
this.onconfirm({
|
||||
target: this
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function removeContainers() {
|
||||
removeConfirm();
|
||||
removeActionMenu();
|
||||
}
|
||||
|
||||
function addConfirm() {
|
||||
if (confirm !== null) {
|
||||
confirm.parentNode.removeChild(confirm);
|
||||
}
|
||||
|
||||
confirm = document.createElement('form');
|
||||
confirm.id = 'downloadConfirmUI';
|
||||
confirm.setAttribute('role', 'dialog');
|
||||
confirm.setAttribute('data-type', 'confirm');
|
||||
confirm.setAttribute('data-z-index-level', '100');
|
||||
|
||||
var screen = document.getElementById('screen');
|
||||
var container = screen || document.body;
|
||||
|
||||
container.appendChild(confirm);
|
||||
}
|
||||
|
||||
function removeConfirm() {
|
||||
if (confirm === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
confirm.innerHTML = '';
|
||||
confirm.style.display = 'none';
|
||||
}
|
||||
|
||||
// When users click or hold on home button UIs should be removed
|
||||
window.addEventListener('home', removeContainers);
|
||||
window.addEventListener('holdhome', removeContainers);
|
||||
|
||||
function l10n(element, l10nid, l10nargs) {
|
||||
// First set our args.
|
||||
if (l10nargs) {
|
||||
element.setAttribute('data-l10n-args', JSON.stringify(l10nargs));
|
||||
}
|
||||
// Then localize.
|
||||
element.setAttribute('data-l10n-id', l10nid);
|
||||
return element;
|
||||
}
|
||||
|
||||
function createConfirm(type, req, downloads) {
|
||||
addConfirm();
|
||||
|
||||
var dialog = document.createElement('section');
|
||||
|
||||
// Header
|
||||
var header = document.createElement('h1');
|
||||
l10n(header, type.name + '_download_title');
|
||||
dialog.appendChild(header);
|
||||
|
||||
// Message
|
||||
var message = document.createElement('p');
|
||||
if (type.isPlainMessage) {
|
||||
l10n(message, type.name + '_download_message');
|
||||
} else {
|
||||
var args = Object.create(null);
|
||||
if (type === TYPES.DELETE_ALL) {
|
||||
args.number = downloads.length;
|
||||
} else {
|
||||
args.name = DownloadFormatter.getFileName(downloads[0]);
|
||||
}
|
||||
l10n(message, type.name + '_download_message', args);
|
||||
}
|
||||
dialog.appendChild(message);
|
||||
|
||||
var menu = document.createElement('menu');
|
||||
menu.dataset.items = type.numberOfButtons;
|
||||
|
||||
if (type.numberOfButtons === 2) {
|
||||
// Left button
|
||||
var lButton = document.createElement('button');
|
||||
lButton.type = 'button';
|
||||
lButton.setAttribute('data-l10n-id',
|
||||
type.name + '_download_left_button');
|
||||
|
||||
lButton.onclick = function l_cancel() {
|
||||
lButton.onclick = null;
|
||||
req.cancel();
|
||||
};
|
||||
menu.appendChild(lButton);
|
||||
}
|
||||
|
||||
// Right button
|
||||
var rButton = document.createElement('button');
|
||||
rButton.type = 'button';
|
||||
type.classes.forEach(function(clazz) {
|
||||
rButton.classList.add(clazz);
|
||||
});
|
||||
|
||||
rButton.setAttribute('data-l10n-id',
|
||||
type.name + '_download_right_button');
|
||||
|
||||
rButton.onclick = function r_confirm() {
|
||||
rButton.onclick = null;
|
||||
req.confirm();
|
||||
};
|
||||
menu.appendChild(rButton);
|
||||
|
||||
dialog.appendChild(menu);
|
||||
confirm.appendChild(dialog);
|
||||
|
||||
confirm.style.display = 'block';
|
||||
}
|
||||
|
||||
function addActionMenu() {
|
||||
// If we have an actionMenu, empty it and re-create it.
|
||||
if (actionMenu !== null) {
|
||||
document.body.removeChild(actionMenu);
|
||||
}
|
||||
actionMenu = document.createElement('gaia-menu');
|
||||
actionMenu.id = 'downloadActionMenuUI';
|
||||
actionMenu.className = 'actions';
|
||||
}
|
||||
|
||||
function removeActionMenu() {
|
||||
if (actionMenu === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
actionMenu.hide();
|
||||
document.body.removeChild(actionMenu);
|
||||
actionMenu = null;
|
||||
}
|
||||
|
||||
function createActionMenu(req, download) {
|
||||
var actions = [ACTIONS.OPEN, ACTIONS.SHARE];
|
||||
|
||||
var fileName = DownloadFormatter.getFileName(download);
|
||||
var type = MimeMapper.guessTypeFromFileProperties(fileName,
|
||||
download.contentType);
|
||||
if (type.length > 0) {
|
||||
if (type.startsWith('image/')) {
|
||||
actions.push(ACTIONS.WALLPAPER);
|
||||
} else if (type.startsWith('audio/')) {
|
||||
actions.push(ACTIONS.RINGTONE);
|
||||
}
|
||||
}
|
||||
|
||||
doCreateActionMenu(req, fileName, actions);
|
||||
}
|
||||
|
||||
function doCreateActionMenu(req, fileName, actions) {
|
||||
addActionMenu();
|
||||
|
||||
var header = document.createElement('header');
|
||||
header.textContent = fileName;
|
||||
actionMenu.appendChild(header);
|
||||
|
||||
actions.forEach(function addActionButton(action) {
|
||||
var button = document.createElement('button');
|
||||
button.id = action.id;
|
||||
l10n(button, action.title);
|
||||
button.dataset.type = action.type;
|
||||
actionMenu.appendChild(button);
|
||||
button.addEventListener('click', function buttonCliked(evt) {
|
||||
button.removeEventListener('click', buttonCliked);
|
||||
req[evt.target.dataset.type](ACTIONS[evt.target.id]);
|
||||
});
|
||||
});
|
||||
document.body.appendChild(actionMenu);
|
||||
actionMenu.removeAttribute('hidden');
|
||||
}
|
||||
|
||||
var styleSheets = [
|
||||
'shared/style/buttons.css',
|
||||
'shared/style/headers.css',
|
||||
'shared/style/confirm.css'
|
||||
];
|
||||
|
||||
/*
|
||||
* Shows a confirmation depending on type. It returns a request object with
|
||||
* oncancel and onconfirm callbacks
|
||||
*
|
||||
* @param {String} Confirmation type
|
||||
*
|
||||
* @param {Array} It represents the download(s) object(s)
|
||||
*
|
||||
* @param {Boolean} This optional parameter indicates if the library should
|
||||
* include BBs
|
||||
*/
|
||||
function show(type, downloads, ignoreStyles) {
|
||||
var req = new Request();
|
||||
|
||||
downloads = Array.isArray(downloads) ? downloads : [downloads];
|
||||
|
||||
window.setTimeout(function() {
|
||||
var libs = ['shared/js/download/download_formatter.js'];
|
||||
if (!ignoreStyles) {
|
||||
libs.push.apply(libs, styleSheets);
|
||||
}
|
||||
|
||||
// We have to discover the type of UI depending on state when type is null
|
||||
if (type === null) {
|
||||
type = TYPES.STOPPED;
|
||||
|
||||
var download = downloads[0];
|
||||
if (download.state === 'finalized' ||
|
||||
download.state === 'stopped' && download.error !== null) {
|
||||
type = TYPES.FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
LazyLoader.load(libs, createConfirm.call(this, type, req, downloads));
|
||||
}, 0);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
function showActions(download) {
|
||||
var req = new Request();
|
||||
|
||||
window.setTimeout(function() {
|
||||
LazyLoader.load(['shared/js/mime_mapper.js',
|
||||
'shared/js/download/download_formatter.js',
|
||||
'shared/js/component_utils.js',
|
||||
'shared/elements/gaia_menu/script.js'],
|
||||
createActionMenu.call(this, req, download));
|
||||
}, 0);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
return {
|
||||
show: show,
|
||||
|
||||
showActions: showActions,
|
||||
|
||||
hide: removeContainers,
|
||||
|
||||
get ERRORS() {
|
||||
return ERRORS;
|
||||
},
|
||||
|
||||
get TYPE() {
|
||||
return TYPES;
|
||||
}
|
||||
};
|
||||
}());
|
||||
245
assets/webapps/download.gaiamobile.org/shared/js/l10n.js
Normal file
245
assets/webapps/download.gaiamobile.org/shared/js/l10n.js
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
;(function(window,undefined){'use strict';function L10nError(message,id,loc){this.name='L10nError';this.message=message;this.id=id;this.loc=loc;}
|
||||
L10nError.prototype=Object.create(Error.prototype);L10nError.prototype.constructor=L10nError;var io={_load:function(type,url,callback,sync){var xhr=new XMLHttpRequest();var needParse;if(xhr.overrideMimeType){xhr.overrideMimeType(type);}
|
||||
xhr.open('GET',url,!sync);if(type==='application/json'){if(sync){needParse=true;}else{xhr.responseType='json';}}
|
||||
xhr.addEventListener('load',function io_onload(e){if(e.target.status===200||e.target.status===0){var res=e.target.response||e.target.responseText;callback(null,needParse?JSON.parse(res):res);}else{callback(new L10nError('Not found: '+url));}});xhr.addEventListener('error',callback);xhr.addEventListener('timeout',callback);try{xhr.send(null);}catch(e){if(e.name==='NS_ERROR_FILE_NOT_FOUND'){callback(new L10nError('Not found: '+url));}else{throw e;}}},load:function(url,callback,sync){return io._load('text/plain',url,callback,sync);},loadJSON:function(url,callback,sync){return io._load('application/json',url,callback,sync);}};function EventEmitter(){}
|
||||
EventEmitter.prototype.emit=function ee_emit(){if(!this._listeners){return;}
|
||||
var args=Array.prototype.slice.call(arguments);var type=args.shift();if(!this._listeners[type]){return;}
|
||||
var typeListeners=this._listeners[type].slice();for(var i=0;i<typeListeners.length;i++){typeListeners[i].apply(this,args);}};EventEmitter.prototype.addEventListener=function ee_add(type,listener){if(!this._listeners){this._listeners={};}
|
||||
if(!(type in this._listeners)){this._listeners[type]=[];}
|
||||
this._listeners[type].push(listener);};EventEmitter.prototype.removeEventListener=function ee_rm(type,listener){if(!this._listeners){return;}
|
||||
var typeListeners=this._listeners[type];var pos=typeListeners.indexOf(listener);if(pos===-1){return;}
|
||||
typeListeners.splice(pos,1);};function getPluralRule(lang){var locales2rules={'af':3,'ak':4,'am':4,'ar':1,'asa':3,'az':0,'be':11,'bem':3,'bez':3,'bg':3,'bh':4,'bm':0,'bn':3,'bo':0,'br':20,'brx':3,'bs':11,'ca':3,'cgg':3,'chr':3,'cs':12,'cy':17,'da':3,'de':3,'dv':3,'dz':0,'ee':3,'el':3,'en':3,'eo':3,'es':3,'et':3,'eu':3,'fa':0,'ff':5,'fi':3,'fil':4,'fo':3,'fr':5,'fur':3,'fy':3,'ga':8,'gd':24,'gl':3,'gsw':3,'gu':3,'guw':4,'gv':23,'ha':3,'haw':3,'he':2,'hi':4,'hr':11,'hu':0,'id':0,'ig':0,'ii':0,'is':3,'it':3,'iu':7,'ja':0,'jmc':3,'jv':0,'ka':0,'kab':5,'kaj':3,'kcg':3,'kde':0,'kea':0,'kk':3,'kl':3,'km':0,'kn':0,'ko':0,'ksb':3,'ksh':21,'ku':3,'kw':7,'lag':18,'lb':3,'lg':3,'ln':4,'lo':0,'lt':10,'lv':6,'mas':3,'mg':4,'mk':16,'ml':3,'mn':3,'mo':9,'mr':3,'ms':0,'mt':15,'my':0,'nah':3,'naq':7,'nb':3,'nd':3,'ne':3,'nl':3,'nn':3,'no':3,'nr':3,'nso':4,'ny':3,'nyn':3,'om':3,'or':3,'pa':3,'pap':3,'pl':13,'ps':3,'pt':3,'rm':3,'ro':9,'rof':3,'ru':11,'rwk':3,'sah':0,'saq':3,'se':7,'seh':3,'ses':0,'sg':0,'sh':11,'shi':19,'sk':12,'sl':14,'sma':7,'smi':7,'smj':7,'smn':7,'sms':7,'sn':3,'so':3,'sq':3,'sr':11,'ss':3,'ssy':3,'st':3,'sv':3,'sw':3,'syr':3,'ta':3,'te':3,'teo':3,'th':0,'ti':4,'tig':3,'tk':3,'tl':4,'tn':3,'to':0,'tr':0,'ts':3,'tzm':22,'uk':11,'ur':3,'ve':3,'vi':0,'vun':3,'wa':4,'wae':3,'wo':0,'xh':3,'xog':3,'yo':0,'zh':0,'zu':3};function isIn(n,list){return list.indexOf(n)!==-1;}
|
||||
function isBetween(n,start,end){return typeof n===typeof start&&start<=n&&n<=end;}
|
||||
var pluralRules={'0':function(){return'other';},'1':function(n){if((isBetween((n%100),3,10))){return'few';}
|
||||
if(n===0){return'zero';}
|
||||
if((isBetween((n%100),11,99))){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'2':function(n){if(n!==0&&(n%10)===0){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'3':function(n){if(n===1){return'one';}
|
||||
return'other';},'4':function(n){if((isBetween(n,0,1))){return'one';}
|
||||
return'other';},'5':function(n){if((isBetween(n,0,2))&&n!==2){return'one';}
|
||||
return'other';},'6':function(n){if(n===0){return'zero';}
|
||||
if((n%10)===1&&(n%100)!==11){return'one';}
|
||||
return'other';},'7':function(n){if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'8':function(n){if((isBetween(n,3,6))){return'few';}
|
||||
if((isBetween(n,7,10))){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'9':function(n){if(n===0||n!==1&&(isBetween((n%100),1,19))){return'few';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'10':function(n){if((isBetween((n%10),2,9))&&!(isBetween((n%100),11,19))){return'few';}
|
||||
if((n%10)===1&&!(isBetween((n%100),11,19))){return'one';}
|
||||
return'other';},'11':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
|
||||
if((n%10)===0||(isBetween((n%10),5,9))||(isBetween((n%100),11,14))){return'many';}
|
||||
if((n%10)===1&&(n%100)!==11){return'one';}
|
||||
return'other';},'12':function(n){if((isBetween(n,2,4))){return'few';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'13':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
|
||||
if(n!==1&&(isBetween((n%10),0,1))||(isBetween((n%10),5,9))||(isBetween((n%100),12,14))){return'many';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'14':function(n){if((isBetween((n%100),3,4))){return'few';}
|
||||
if((n%100)===2){return'two';}
|
||||
if((n%100)===1){return'one';}
|
||||
return'other';},'15':function(n){if(n===0||(isBetween((n%100),2,10))){return'few';}
|
||||
if((isBetween((n%100),11,19))){return'many';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'16':function(n){if((n%10)===1&&n!==11){return'one';}
|
||||
return'other';},'17':function(n){if(n===3){return'few';}
|
||||
if(n===0){return'zero';}
|
||||
if(n===6){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'18':function(n){if(n===0){return'zero';}
|
||||
if((isBetween(n,0,2))&&n!==0&&n!==2){return'one';}
|
||||
return'other';},'19':function(n){if((isBetween(n,2,10))){return'few';}
|
||||
if((isBetween(n,0,1))){return'one';}
|
||||
return'other';},'20':function(n){if((isBetween((n%10),3,4)||((n%10)===9))&&!(isBetween((n%100),10,19)||isBetween((n%100),70,79)||isBetween((n%100),90,99))){return'few';}
|
||||
if((n%1000000)===0&&n!==0){return'many';}
|
||||
if((n%10)===2&&!isIn((n%100),[12,72,92])){return'two';}
|
||||
if((n%10)===1&&!isIn((n%100),[11,71,91])){return'one';}
|
||||
return'other';},'21':function(n){if(n===0){return'zero';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'22':function(n){if((isBetween(n,0,1))||(isBetween(n,11,99))){return'one';}
|
||||
return'other';},'23':function(n){if((isBetween((n%10),1,2))||(n%20)===0){return'one';}
|
||||
return'other';},'24':function(n){if((isBetween(n,3,10)||isBetween(n,13,19))){return'few';}
|
||||
if(isIn(n,[2,12])){return'two';}
|
||||
if(isIn(n,[1,11])){return'one';}
|
||||
return'other';}};var index=locales2rules[lang.replace(/-.*$/,'')];if(!(index in pluralRules)){return function(){return'other';};}
|
||||
return pluralRules[index];}
|
||||
var MAX_PLACEABLES=100;var PropertiesParser={patterns:null,entryIds:null,init:function(){this.patterns={comment:/^\s*#|^\s*$/,entity:/^([^=\s]+)\s*=\s*(.*)$/,multiline:/[^\\]\\$/,index:/\{\[\s*(\w+)(?:\(([^\)]*)\))?\s*\]\}/i,unicode:/\\u([0-9a-fA-F]{1,4})/g,entries:/[^\r\n]+/g,controlChars:/\\([\\\n\r\t\b\f\{\}\"\'])/g,placeables:/\{\{\s*([^\s]*?)\s*\}\}/,};},parse:function(ctx,source){if(!this.patterns){this.init();}
|
||||
var ast=[];this.entryIds=Object.create(null);var entries=source.match(this.patterns.entries);if(!entries){return ast;}
|
||||
for(var i=0;i<entries.length;i++){var line=entries[i];if(this.patterns.comment.test(line)){continue;}
|
||||
while(this.patterns.multiline.test(line)&&i<entries.length){line=line.slice(0,-1)+entries[++i].trim();}
|
||||
var entityMatch=line.match(this.patterns.entity);if(entityMatch){try{this.parseEntity(entityMatch[1],entityMatch[2],ast);}catch(e){if(ctx){ctx._emitter.emit('parseerror',e);}else{throw e;}}}}
|
||||
return ast;},parseEntity:function(id,value,ast){var name,key;var pos=id.indexOf('[');if(pos!==-1){name=id.substr(0,pos);key=id.substring(pos+1,id.length-1);}else{name=id;key=null;}
|
||||
var nameElements=name.split('.');if(nameElements.length>2){throw new L10nError('Error in ID: "'+name+'".'+' Nested attributes are not supported.');}
|
||||
var attr;if(nameElements.length>1){name=nameElements[0];attr=nameElements[1];if(attr[0]==='$'){throw new L10nError('Attribute can\'t start with "$"',id);}}else{attr=null;}
|
||||
this.setEntityValue(name,attr,key,this.unescapeString(value),ast);},setEntityValue:function(id,attr,key,rawValue,ast){var pos,v;var value=rawValue.indexOf('{{')>-1?this.parseString(rawValue):rawValue;if(attr){pos=this.entryIds[id];if(pos===undefined){v={$i:id};if(key){v[attr]={};v[attr][key]=value;}else{v[attr]=value;}
|
||||
ast.push(v);this.entryIds[id]=ast.length-1;return;}
|
||||
if(key){if(typeof(ast[pos][attr])==='string'){ast[pos][attr]={$x:this.parseIndex(ast[pos][attr]),$v:{}};}
|
||||
ast[pos][attr].$v[key]=value;return;}
|
||||
ast[pos][attr]=value;return;}
|
||||
if(key){pos=this.entryIds[id];if(pos===undefined){v={};v[key]=value;ast.push({$i:id,$v:v});this.entryIds[id]=ast.length-1;return;}
|
||||
if(typeof(ast[pos].$v)==='string'){ast[pos].$x=this.parseIndex(ast[pos].$v);ast[pos].$v={};}
|
||||
ast[pos].$v[key]=value;return;}
|
||||
ast.push({$i:id,$v:value});this.entryIds[id]=ast.length-1;},parseString:function(str){var chunks=str.split(this.patterns.placeables);var complexStr=[];var len=chunks.length;var placeablesCount=(len-1)/2;if(placeablesCount>=MAX_PLACEABLES){throw new L10nError('Too many placeables ('+placeablesCount+', max allowed is '+MAX_PLACEABLES+')');}
|
||||
for(var i=0;i<chunks.length;i++){if(chunks[i].length===0){continue;}
|
||||
if(i%2===1){complexStr.push({t:'idOrVar',v:chunks[i]});}else{complexStr.push(chunks[i]);}}
|
||||
return complexStr;},unescapeString:function(str){if(str.lastIndexOf('\\')!==-1){str=str.replace(this.patterns.controlChars,'$1');}
|
||||
return str.replace(this.patterns.unicode,function(match,token){return unescape('%u'+'0000'.slice(token.length)+token);});},parseIndex:function(str){var match=str.match(this.patterns.index);if(!match){throw new L10nError('Malformed index');}
|
||||
if(match[2]){return[{t:'idOrVar',v:match[1]},match[2]];}else{return[{t:'idOrVar',v:match[1]}];}}};var KNOWN_MACROS=['plural'];var MAX_PLACEABLE_LENGTH=2500;var rePlaceables=/\{\{\s*(.+?)\s*\}\}/g;var nonLatin1=/[^\x01-\xFF]/;var FSI='\u2068';var PDI='\u2069';function createEntry(node,env){var keys=Object.keys(node);if(typeof node.$v==='string'&&keys.length===2){return node.$v;}
|
||||
var attrs;for(var i=0,key;key=keys[i];i++){if(key[0]==='$'){continue;}
|
||||
if(!attrs){attrs=Object.create(null);}
|
||||
attrs[key]=createAttribute(node[key],env,node.$i+'.'+key);}
|
||||
return{id:node.$i,value:node.$v!==undefined?node.$v:null,index:node.$x||null,attrs:attrs||null,env:env,dirty:false};}
|
||||
function createAttribute(node,env,id){if(typeof node==='string'){return node;}
|
||||
return{id:id,value:node.$v||(node!==undefined?node:null),index:node.$x||null,env:env,dirty:false};}
|
||||
function format(args,entity){if(typeof entity==='string'){return[{},entity];}
|
||||
if(entity.dirty){throw new L10nError('Cyclic reference detected: '+entity.id);}
|
||||
entity.dirty=true;var rv;try{rv=resolveValue({},args,entity.env,entity.value,entity.index);}finally{entity.dirty=false;}
|
||||
return rv;}
|
||||
function resolveIdentifier(args,env,id){if(KNOWN_MACROS.indexOf(id)>-1){return[{},env['__'+id]];}
|
||||
if(args&&args.hasOwnProperty(id)){if(typeof args[id]==='string'||(typeof args[id]==='number'&&!isNaN(args[id]))){return[{},args[id]];}else{throw new L10nError('Arg must be a string or a number: '+id);}}
|
||||
if(id in env&&id!=='__proto__'){return format(args,env[id]);}
|
||||
throw new L10nError('Unknown reference: '+id);}
|
||||
function subPlaceable(locals,args,env,id){var res;try{res=resolveIdentifier(args,env,id);}catch(err){return[{error:err},'{{ '+id+' }}'];}
|
||||
var value=res[1];if(typeof value==='number'){return res;}
|
||||
if(typeof value==='string'){if(value.length>=MAX_PLACEABLE_LENGTH){throw new L10nError('Too many characters in placeable ('+
|
||||
value.length+', max allowed is '+
|
||||
MAX_PLACEABLE_LENGTH+')');}
|
||||
if(locals.contextIsNonLatin1||value.match(nonLatin1)){res[1]=FSI+value+PDI;}
|
||||
return res;}
|
||||
return[{},'{{ '+id+' }}'];}
|
||||
function interpolate(locals,args,env,arr){return arr.reduce(function(prev,cur){if(typeof cur==='string'){return[prev[0],prev[1]+cur];}else if(cur.t==='idOrVar'){var placeable=subPlaceable(locals,args,env,cur.v);return[prev[0],prev[1]+placeable[1]];}},[locals,'']);}
|
||||
function resolveSelector(args,env,expr,index){var selectorName=index[0].v;var selector=resolveIdentifier(args,env,selectorName)[1];if(typeof selector!=='function'){return selector;}
|
||||
var argValue=index[1]?resolveIdentifier(args,env,index[1])[1]:undefined;if(selector===env.__plural){if(argValue===0&&'zero'in expr){return'zero';}
|
||||
if(argValue===1&&'one'in expr){return'one';}
|
||||
if(argValue===2&&'two'in expr){return'two';}}
|
||||
return selector(argValue);}
|
||||
function resolveValue(locals,args,env,expr,index){if(!expr){return[locals,expr];}
|
||||
if(typeof expr==='string'||typeof expr==='boolean'||typeof expr==='number'){return[locals,expr];}
|
||||
if(Array.isArray(expr)){locals.contextIsNonLatin1=expr.some(function($_){return typeof($_)==='string'&&$_.match(nonLatin1);});return interpolate(locals,args,env,expr);}
|
||||
if(index){var selector=resolveSelector(args,env,expr,index);if(expr.hasOwnProperty(selector)){return resolveValue(locals,args,env,expr[selector]);}}
|
||||
if('other'in expr){return resolveValue(locals,args,env,expr.other);}
|
||||
throw new L10nError('Unresolvable value');}
|
||||
var Resolver={createEntry:createEntry,format:format,rePlaceables:rePlaceables};function walkContent(node,fn){if(typeof node==='string'){return fn(node);}
|
||||
if(node.t==='idOrVar'){return node;}
|
||||
var rv=Array.isArray(node)?[]:{};var keys=Object.keys(node);for(var i=0,key;(key=keys[i]);i++){if(key==='$i'||key==='$x'){rv[key]=node[key];}else{rv[key]=walkContent(node[key],fn);}}
|
||||
return rv;}
|
||||
var reAlphas=/[a-zA-Z]/g;var reVowels=/[aeiouAEIOU]/g;var ACCENTED_MAP='\u0226\u0181\u0187\u1E12\u1E16\u0191\u0193\u0126\u012A'+'\u0134\u0136\u013F\u1E3E\u0220\u01FE\u01A4\u024A\u0158'+'\u015E\u0166\u016C\u1E7C\u1E86\u1E8A\u1E8E\u1E90'+'[\\]^_`'+'\u0227\u0180\u0188\u1E13\u1E17\u0192\u0260\u0127\u012B'+'\u0135\u0137\u0140\u1E3F\u019E\u01FF\u01A5\u024B\u0159'+'\u015F\u0167\u016D\u1E7D\u1E87\u1E8B\u1E8F\u1E91';var FLIPPED_MAP='\u2200\u0510\u2183p\u018E\u025F\u05E4HI\u017F'+'\u04FC\u02E5WNO\u0500\xD2\u1D1AS\u22A5\u2229\u0245'+'\uFF2DX\u028EZ'+'[\\]\u1D65_,'+'\u0250q\u0254p\u01DD\u025F\u0183\u0265\u0131\u027E'+'\u029E\u0285\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez';function makeLonger(val){return val.replace(reVowels,function(match){return match+match.toLowerCase();});}
|
||||
function replaceChars(map,val){return val.replace(reAlphas,function(match){return map.charAt(match.charCodeAt(0)-65);});}
|
||||
var reWords=/[^\W0-9_]+/g;function makeRTL(val){return val.replace(reWords,function(match){return'\u202e'+match+'\u202c';});}
|
||||
var reExcluded=/(%[EO]?\w|\{\s*.+?\s*\}|&[#\w]+;|<\s*.+?\s*>)/;function mapContent(fn,val){if(!val){return val;}
|
||||
var parts=val.split(reExcluded);var modified=parts.map(function(part){if(reExcluded.test(part)){return part;}
|
||||
return fn(part);});return modified.join('');}
|
||||
function Pseudo(id,name,charMap,modFn){this.id=id;this.translate=mapContent.bind(null,function(val){return replaceChars(charMap,modFn(val));});this.name=this.translate(name);}
|
||||
var PSEUDO={'fr-x-psaccent':new Pseudo('fr-x-psaccent','Runtime Accented',ACCENTED_MAP,makeLonger),'ar-x-psbidi':new Pseudo('ar-x-psbidi','Runtime Bidi',FLIPPED_MAP,makeRTL)};function Locale(id,ctx){this.id=id;this.ctx=ctx;this.isReady=false;this.entries=Object.create(null);this.entries.__plural=getPluralRule(this.isPseudo()?this.ctx.defaultLocale:id);}
|
||||
Locale.prototype.isPseudo=function(){return this.ctx.qps.indexOf(this.id)!==-1;};var bindingsIO={extra:function(id,ver,path,type,callback,errback){if(type==='properties'){type='text';}
|
||||
navigator.mozApps.getLocalizationResource(id,ver,path,type).then(callback.bind(null,null),errback);},app:function(id,ver,path,type,callback,errback,sync){switch(type){case'properties':io.load(path,callback,sync);break;case'json':io.loadJSON(path,callback,sync);break;}},};Locale.prototype.build=function L_build(callback){var sync=!callback;var ctx=this.ctx;var self=this;var l10nLoads=ctx.resLinks.length;function onL10nLoaded(err){if(err){ctx._emitter.emit('fetcherror',err);}
|
||||
if(--l10nLoads<=0){self.isReady=true;if(callback){callback();}}}
|
||||
if(l10nLoads===0){onL10nLoaded();return;}
|
||||
function onJSONLoaded(err,json){if(!err&&json){self.addAST(json);}
|
||||
onL10nLoaded(err);}
|
||||
function onPropLoaded(err,source){if(!err&&source){var ast=PropertiesParser.parse(ctx,source);self.addAST(ast);}
|
||||
onL10nLoaded(err);}
|
||||
var idToFetch=this.isPseudo()?ctx.defaultLocale:this.id;var appVersion=null;var source='app';if(typeof(navigator)!=='undefined'){source=navigator.mozL10n._config.localeSources[this.id]||'app';appVersion=navigator.mozL10n._config.appVersion;}
|
||||
for(var i=0;i<ctx.resLinks.length;i++){var resLink=decodeURI(ctx.resLinks[i]);var path=resLink.replace('{locale}',idToFetch);var type=path.substr(path.lastIndexOf('.')+1);var cb;switch(type){case'json':cb=onJSONLoaded;break;case'properties':cb=onPropLoaded;break;}
|
||||
bindingsIO[source](this.id,appVersion,path,type,cb,onL10nLoaded,sync);}};function createPseudoEntry(node,entries){return Resolver.createEntry(walkContent(node,PSEUDO[this.id].translate),entries);}
|
||||
Locale.prototype.addAST=function(ast){var createEntry=this.isPseudo()?createPseudoEntry.bind(this):Resolver.createEntry;for(var i=0;i<ast.length;i++){this.entries[ast[i].$i]=createEntry(ast[i],this.entries);}};function Context(id){this.id=id;this.isReady=false;this.isLoading=false;this.defaultLocale='en-US';this.availableLocales=[];this.supportedLocales=[];this.qps=[];this.resLinks=[];this.locales={};this._emitter=new EventEmitter();this._ready=new Promise(this.once.bind(this));}
|
||||
function reportMissing(id,err){this._emitter.emit('notfounderror',err);return id;}
|
||||
function getWithFallback(id){var cur=0;var loc;var locale;while(loc=this.supportedLocales[cur]){locale=this.getLocale(loc);if(!locale.isReady){locale.build(null);}
|
||||
var entry=locale.entries[id];if(entry===undefined){cur++;reportMissing.call(this,id,new L10nError('"'+id+'"'+' not found in '+loc+' in '+this.id,id,loc));continue;}
|
||||
return entry;}
|
||||
throw new L10nError('"'+id+'"'+' missing from all supported locales in '+this.id,id);}
|
||||
function formatTuple(args,entity){try{return Resolver.format(args,entity);}catch(err){this._emitter.emit('resolveerror',err);var locals={error:err};return[locals,entity.id];}}
|
||||
function formatValue(args,entity){if(typeof entity==='string'){return entity;}
|
||||
return formatTuple.call(this,args,entity)[1];}
|
||||
function formatEntity(args,entity){var entityTuple=formatTuple.call(this,args,entity);var value=entityTuple[1];var formatted={value:value,attrs:null,};if(entity.attrs){formatted.attrs=Object.create(null);}
|
||||
for(var key in entity.attrs){var attrTuple=formatTuple.call(this,args,entity.attrs[key]);formatted.attrs[key]=attrTuple[1];}
|
||||
return formatted;}
|
||||
function formatAsync(fn,id,args){return this._ready.then(getWithFallback.bind(this,id)).then(fn.bind(this,args),reportMissing.bind(this,id));}
|
||||
Context.prototype.formatValue=function(id,args){return formatAsync.call(this,formatValue,id,args);};Context.prototype.formatEntity=function(id,args){return formatAsync.call(this,formatEntity,id,args);};function legacyGet(fn,id,args){if(!this.isReady){throw new L10nError('Context not ready');}
|
||||
var entry;try{entry=getWithFallback.call(this,id);}catch(err){if(err.loc){throw err;}
|
||||
reportMissing.call(this,id,err);return'';}
|
||||
return fn.call(this,args,entry);}
|
||||
Context.prototype.get=function(id,args){return legacyGet.call(this,formatValue,id,args);};Context.prototype.getEntity=function(id,args){return legacyGet.call(this,formatEntity,id,args);};Context.prototype.getLocale=function getLocale(code){var locales=this.locales;if(locales[code]){return locales[code];}
|
||||
return locales[code]=new Locale(code,this);};function negotiate(available,requested,defaultLocale){var supportedLocale;for(var i=0;i<requested.length;i++){var locale=requested[i];if(available.indexOf(locale)!==-1){supportedLocale=locale;break;}}
|
||||
if(!supportedLocale||supportedLocale===defaultLocale){return[defaultLocale];}
|
||||
return[supportedLocale,defaultLocale];}
|
||||
function freeze(supported){var locale=this.getLocale(supported[0]);if(locale.isReady){setReady.call(this,supported);}else{locale.build(setReady.bind(this,supported));}}
|
||||
function setReady(supported){this.supportedLocales=supported;this.isReady=true;this._emitter.emit('ready');}
|
||||
Context.prototype.registerLocales=function(defLocale,available){if(defLocale){this.defaultLocale=defLocale;}
|
||||
this.availableLocales=[this.defaultLocale];this.qps=Object.keys(PSEUDO);if(available){for(var i=0,loc;loc=available[i];i++){if(this.availableLocales.indexOf(loc)===-1){this.availableLocales.push(loc);var pos=this.qps.indexOf(loc);if(pos!==-1){this.qps.splice(pos,1);}}}}};Context.prototype.requestLocales=function requestLocales(){if(this.isLoading&&!this.isReady){throw new L10nError('Context not ready');}
|
||||
this.isLoading=true;var requested=Array.prototype.slice.call(arguments);if(requested.length===0){throw new L10nError('No locales requested');}
|
||||
var supported=negotiate(this.availableLocales.concat(this.qps),requested,this.defaultLocale);if(this.supportedLocales[0]!==supported[0]){freeze.call(this,supported);}};Context.prototype.addEventListener=function(type,listener){this._emitter.addEventListener(type,listener);};Context.prototype.removeEventListener=function(type,listener){this._emitter.removeEventListener(type,listener);};Context.prototype.ready=function(callback){if(this.isReady){setTimeout(callback);}
|
||||
this.addEventListener('ready',callback);};Context.prototype.once=function(callback){if(this.isReady){setTimeout(callback);return;}
|
||||
var callAndRemove=(function(){this.removeEventListener('ready',callAndRemove);callback();}).bind(this);this.addEventListener('ready',callAndRemove);};var allowed={elements:['a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','sup','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr'],attributes:{global:['title','aria-label','aria-valuetext','aria-moz-hint'],a:['download'],area:['download','alt'],input:['alt','placeholder'],menuitem:['label'],menu:['label'],optgroup:['label'],option:['label'],track:['label'],img:['alt'],textarea:['placeholder'],th:['abbr']}};var rtlList=['ar','he','fa','ps','ar-x-psbidi','ur'];var nodeObserver=null;var pendingElements=null;var moConfig={attributes:true,characterData:false,childList:true,subtree:true,attributeFilter:['data-l10n-id','data-l10n-args']};navigator.mozL10n={ctx:null,get:function get(id,ctxdata){return navigator.mozL10n.ctx.get(id,ctxdata);},formatValue:function(id,ctxdata){return navigator.mozL10n.ctx.formatValue(id,ctxdata);},formatEntity:function(id,ctxdata){return navigator.mozL10n.ctx.formatEntity(id,ctxdata);},translateFragment:function(fragment){return translateFragment.call(navigator.mozL10n,fragment);},setAttributes:setL10nAttributes,getAttributes:getL10nAttributes,ready:function ready(callback){return navigator.mozL10n.ctx.ready(callback);},once:function once(callback){return navigator.mozL10n.ctx.once(callback);},get readyState(){return navigator.mozL10n.ctx.isReady?'complete':'loading';},language:{set code(lang){navigator.mozL10n.ctx.requestLocales(lang);},get code(){return navigator.mozL10n.ctx.supportedLocales[0];},get direction(){return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);}},qps:PSEUDO,_config:{appVersion:null,localeSources:Object.create(null),isPretranslated:false,},_getInternalAPI:function(){return{Error:L10nError,Context:Context,Locale:Locale,Resolver:Resolver,getPluralRule:getPluralRule,rePlaceables:rePlaceables,translateDocument:translateDocument,onMetaInjected:onMetaInjected,PropertiesParser:PropertiesParser,walkContent:walkContent,buildLocaleList:buildLocaleList};}};function getDirection(lang){return(rtlList.indexOf(lang)>=0)?'rtl':'ltr';}
|
||||
var readyStates={loading:0,interactive:1,complete:2};function whenInteractive(callback){if(readyStates[document.readyState]>=readyStates.interactive){callback();return;}
|
||||
document.addEventListener('readystatechange',function l10n_onrsc(){if(readyStates[document.readyState]>=readyStates.interactive){document.removeEventListener('readystatechange',l10n_onrsc);callback();}});}
|
||||
function initObserver(){nodeObserver=new MutationObserver(onMutations.bind(navigator.mozL10n));nodeObserver.observe(document,moConfig);}
|
||||
function init(pretranslate){if(!pretranslate){initObserver();}
|
||||
initResources.call(navigator.mozL10n);}
|
||||
function initResources(){var meta={};var nodes=document.head.querySelectorAll('link[rel="localization"],'+'meta[name="availableLanguages"],'+'meta[name="defaultLanguage"],'+'meta[name="appVersion"],'+'script[type="application/l10n"]');for(var i=0,node;node=nodes[i];i++){var type=node.getAttribute('rel')||node.nodeName.toLowerCase();switch(type){case'localization':this.ctx.resLinks.push(node.getAttribute('href'));break;case'meta':onMetaInjected.call(this,node,meta);break;case'script':onScriptInjected.call(this,node);break;}}
|
||||
var additionalLanguagesPromise;if(navigator.mozApps&&navigator.mozApps.getAdditionalLanguages){additionalLanguagesPromise=navigator.mozApps.getAdditionalLanguages().catch(function(e){console.error('Error while loading getAdditionalLanguages',e);});document.addEventListener('additionallanguageschange',function(evt){registerLocales.call(this,meta,evt.detail);this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}else{additionalLanguagesPromise=Promise.resolve();}
|
||||
additionalLanguagesPromise.then(function(extraLangs){registerLocales.call(this,meta,extraLangs);initLocale.call(this);}.bind(this));}
|
||||
function registerLocales(meta,extraLangs){var locales=buildLocaleList.call(this,meta,extraLangs);navigator.mozL10n._config.localeSources=locales[1];this.ctx.registerLocales(locales[0],Object.keys(locales[1]));}
|
||||
function getMatchingLangpack(appVersion,langpacks){for(var i=0,langpack;(langpack=langpacks[i]);i++){if(langpack.target===appVersion){return langpack;}}
|
||||
return null;}
|
||||
function buildLocaleList(meta,extraLangs){var loc,lp;var localeSources=Object.create(null);var defaultLocale=meta.defaultLanguage||this.ctx.defaultLocale;if(meta.availableLanguages){for(loc in meta.availableLanguages){localeSources[loc]='app';}}
|
||||
if(extraLangs){for(loc in extraLangs){lp=getMatchingLangpack(this._config.appVersion,extraLangs[loc]);if(!lp){continue;}
|
||||
if(!(loc in localeSources)||!meta.availableLanguages[loc]||parseInt(lp.revision)>meta.availableLanguages[loc]){localeSources[loc]='extra';}}}
|
||||
if(!(defaultLocale in localeSources)){localeSources[defaultLocale]='app';}
|
||||
return[defaultLocale,localeSources];}
|
||||
function splitAvailableLanguagesString(str){var langs={};str.split(',').forEach(function(lang){lang=lang.trim().split(':');langs[lang[0]]=parseInt(lang[1]);});return langs;}
|
||||
function onMetaInjected(node,meta){switch(node.getAttribute('name')){case'availableLanguages':meta.availableLanguages=splitAvailableLanguagesString(node.getAttribute('content'));break;case'defaultLanguage':meta.defaultLanguage=node.getAttribute('content');break;case'appVersion':navigator.mozL10n._config.appVersion=node.getAttribute('content');break;}}
|
||||
function onScriptInjected(node){var lang=node.getAttribute('lang');var locale=this.ctx.getLocale(lang);locale.addAST(JSON.parse(node.textContent));}
|
||||
function initLocale(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);window.addEventListener('languagechange',function l10n_langchange(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}
|
||||
function localizeMutations(mutations){var mutation;var targets=new Set();for(var i=0;i<mutations.length;i++){mutation=mutations[i];if(mutation.type==='childList'){var addedNode;for(var j=0;j<mutation.addedNodes.length;j++){addedNode=mutation.addedNodes[j];if(addedNode.nodeType!==Node.ELEMENT_NODE){continue;}
|
||||
targets.add(addedNode);}}
|
||||
if(mutation.type==='attributes'){targets.add(mutation.target);}}
|
||||
targets.forEach(function(target){if(target.childElementCount){translateFragment.call(this,target);}else if(target.hasAttribute('data-l10n-id')){translateElement.call(this,target);}},this);}
|
||||
function onMutations(mutations,self){self.disconnect();localizeMutations.call(this,mutations);self.observe(document,moConfig);}
|
||||
function onReady(){if(!navigator.mozL10n._config.isPretranslated){translateDocument.call(this);}
|
||||
navigator.mozL10n._config.isPretranslated=false;if(pendingElements){for(var i=0,element;element=pendingElements[i];i++){translateElement.call(this,element);}
|
||||
pendingElements=null;}
|
||||
if(!nodeObserver){initObserver();}
|
||||
fireLocalizedEvent.call(this);}
|
||||
function fireLocalizedEvent(){var event=new CustomEvent('localized',{'bubbles':false,'cancelable':false,'detail':{'language':this.ctx.supportedLocales[0]}});window.dispatchEvent(event);}
|
||||
var reOverlay=/<|&#?\w+;/;var reHtml=/[&<>]/g;var htmlEntities={'&':'&','<':'<','>':'>',};function translateDocument(){document.documentElement.lang=this.language.code;document.documentElement.dir=this.language.direction;translateFragment.call(this,document.documentElement);}
|
||||
function translateFragment(element){if(typeof element.hasAttribute==='function'&&element.hasAttribute('data-l10n-id')){translateElement.call(this,element);}
|
||||
var nodes=getTranslatableChildren(element);for(var i=0;i<nodes.length;i++){translateElement.call(this,nodes[i]);}}
|
||||
function setL10nAttributes(element,id,args){element.setAttribute('data-l10n-id',id);if(args){element.setAttribute('data-l10n-args',JSON.stringify(args));}}
|
||||
function getL10nAttributes(element){return{id:element.getAttribute('data-l10n-id'),args:JSON.parse(element.getAttribute('data-l10n-args'))};}
|
||||
function getTranslatableChildren(element){return element?element.querySelectorAll('*[data-l10n-id]'):[];}
|
||||
function camelCaseToDashed(string){if(string==='ariaValueText'){return'aria-valuetext';}
|
||||
return string.replace(/[A-Z]/g,function(match){return'-'+match.toLowerCase();}).replace(/^-/,'');}
|
||||
function escapeL10nArgs(match){return htmlEntities[match];}
|
||||
function translateElement(element){if(!this.ctx.isReady){if(!pendingElements){pendingElements=[];}
|
||||
pendingElements.push(element);return;}
|
||||
var l10nId=element.getAttribute('data-l10n-id');if(!l10nId){return false;}
|
||||
var l10nArgs=element.getAttribute('data-l10n-args');var entity=this.ctx.getEntity(l10nId,l10nArgs?JSON.parse(l10nArgs.replace(reHtml,escapeL10nArgs)):undefined);var value=entity.value;if(typeof value==='string'){if(!reOverlay.test(value)){element.textContent=value;}else{var translation=element.ownerDocument.createElement('template');translation.innerHTML=value;overlayElement(element,translation.content);}}
|
||||
for(var key in entity.attrs){var attrName=camelCaseToDashed(key);if(isAttrAllowed({name:attrName},element)){element.setAttribute(attrName,entity.attrs[key]);}}}
|
||||
function overlayElement(sourceElement,translationElement){var result=translationElement.ownerDocument.createDocumentFragment();var k,attr;var childElement;while((childElement=translationElement.childNodes[0])){translationElement.removeChild(childElement);if(childElement.nodeType===Node.TEXT_NODE){result.appendChild(childElement);continue;}
|
||||
var index=getIndexOfType(childElement);var sourceChild=getNthElementOfType(sourceElement,childElement,index);if(sourceChild){overlayElement(sourceChild,childElement);result.appendChild(sourceChild);continue;}
|
||||
if(isElementAllowed(childElement)){var sanitizedChild=childElement.ownerDocument.createElement(childElement.nodeName);overlayElement(sanitizedChild,childElement);result.appendChild(sanitizedChild);continue;}
|
||||
result.appendChild(document.createTextNode(childElement.textContent));}
|
||||
sourceElement.textContent='';sourceElement.appendChild(result);if(translationElement.attributes){for(k=0,attr;(attr=translationElement.attributes[k]);k++){if(isAttrAllowed(attr,sourceElement)){sourceElement.setAttribute(attr.name,attr.value);}}}}
|
||||
function isElementAllowed(element){return allowed.elements.indexOf(element.tagName.toLowerCase())!==-1;}
|
||||
function isAttrAllowed(attr,element){var attrName=attr.name.toLowerCase();var tagName=element.tagName.toLowerCase();if(allowed.attributes.global.indexOf(attrName)!==-1){return true;}
|
||||
if(!allowed.attributes[tagName]){return false;}
|
||||
if(allowed.attributes[tagName].indexOf(attrName)!==-1){return true;}
|
||||
if(tagName==='input'&&attrName==='value'){var type=element.type.toLowerCase();if(type==='submit'||type==='button'||type==='reset'){return true;}}
|
||||
return false;}
|
||||
function getNthElementOfType(context,element,index){var nthOfType=0;for(var i=0,child;child=context.children[i];i++){if(child.nodeType===Node.ELEMENT_NODE&&child.tagName===element.tagName){if(nthOfType===index){return child;}
|
||||
nthOfType++;}}
|
||||
return null;}
|
||||
function getIndexOfType(element){var index=0;var child;while((child=element.previousElementSibling)){if(child.tagName===element.tagName){index++;}}
|
||||
return index;}
|
||||
var DEBUG=false;navigator.mozL10n.ctx=new Context(window.document?document.URL:null);navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));navigator.mozL10n.ctx.addEventListener('notfounderror',function reportMissingEntity(e){if(DEBUG||e.loc==='en-US'){console.warn(e.toString());}});if(DEBUG){navigator.mozL10n.ctx.addEventListener('fetcherror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('parseerror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('resolveerror',console.error.bind(console));}
|
||||
if(window.document){navigator.mozL10n._config.isPretranslated=document.documentElement.lang===navigator.language;var forcePretranslate=!navigator.mozL10n._config.isPretranslated;whenInteractive(init.bind(navigator.mozL10n,forcePretranslate));}
|
||||
document.l10n={setAttributes:navigator.mozL10n.setAttributes,getAttributes:navigator.mozL10n.getAttributes,formatValue:function(id,args){return navigator.mozL10n.formatValue(id,args);},translateFragment:function(frag){return Promise.resolve(navigator.mozL10n.translateFragment(frag));},ready:new Promise(function(resolve){navigator.mozL10n.once(resolve);}),formatValues:function(){var keys=arguments;var resp=keys.map(function(key){if(Array.isArray(key)){return navigator.mozL10n.formatValue(key[0],key[1]);}
|
||||
return navigator.mozL10n.formatValue(key);});return Promise.all(resp);},requestLanguages:function(langs){navigator.mozL10n.ctx.requestLocales.apply(navigator.mozL10n.ctx,langs);},pseudo:{'fr-x-psaccent':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].translate(s));}},'ar-x-psbidi':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].translate(s));}}},};navigator.mozL10n.ready(function(){document.documentElement.setAttribute('langs',navigator.mozL10n.ctx.supportedLocales.join(' '));});navigator.mozL10n.once(function(){window.addEventListener('localized',function(){document.dispatchEvent(new CustomEvent('DOMRetranslated',{bubbles:false,cancelable:false}));});});})(this);
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
;'use strict';var LazyLoader=(function(){function LazyLoader(){this._loaded={};this._isLoading={};}
|
||||
LazyLoader.prototype={_js:function(file,callback){var script=document.createElement('script');script.src=file;script.async=false;script.addEventListener('load',callback);document.head.appendChild(script);this._isLoading[file]=script;},_css:function(file,callback){var style=document.createElement('link');style.type='text/css';style.rel='stylesheet';style.href=file;document.head.appendChild(style);callback();},_html:function(domNode,callback){if(domNode.getAttribute('is')){this.load(['/shared/js/html_imports.js'],function(){HtmlImports.populate(callback);}.bind(this));return;}
|
||||
for(var i=0;i<domNode.childNodes.length;i++){if(domNode.childNodes[i].nodeType==document.COMMENT_NODE){domNode.innerHTML=domNode.childNodes[i].nodeValue;break;}}
|
||||
window.dispatchEvent(new CustomEvent('lazyload',{detail:domNode}));callback();},getJSON:function(file,mozSystem){return new Promise(function(resolve,reject){var xhr;if(mozSystem){xhr=new XMLHttpRequest({mozSystem:true});}else{xhr=new XMLHttpRequest();}
|
||||
xhr.open('GET',file,true);xhr.responseType='json';xhr.onerror=function(error){reject(error);};xhr.onload=function(){if(xhr.response!==null){resolve(xhr.response);}else{reject(new Error('No valid JSON object was found ('+
|
||||
xhr.status+' '+xhr.statusText+')'));}};xhr.send();});},load:function(files,callback){var deferred={};deferred.promise=new Promise(resolve=>{deferred.resolve=resolve;});if(!Array.isArray(files)){files=[files];}
|
||||
var loadsRemaining=files.length,self=this;function perFileCallback(file){if(self._isLoading[file]){delete self._isLoading[file];}
|
||||
self._loaded[file]=true;if(--loadsRemaining===0){deferred.resolve();if(callback){callback();}}}
|
||||
for(var i=0;i<files.length;i++){var file=files[i];if(this._loaded[file.id||file]){perFileCallback(file);}else if(this._isLoading[file]){this._isLoading[file].addEventListener('load',perFileCallback.bind(null,file));}else{var method,idx;if(typeof file==='string'){method=file.match(/\.([^.]+)$/)[1];idx=file;}else{method='html';idx=file.id;}
|
||||
this['_'+method](file,perFileCallback.bind(null,idx));}}
|
||||
return deferred.promise;}};return new LazyLoader();}());
|
||||
135
assets/webapps/download.gaiamobile.org/shared/js/mime_mapper.js
Normal file
135
assets/webapps/download.gaiamobile.org/shared/js/mime_mapper.js
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/* exported MimeMapper */
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* MimeMapper helps gaia apps to decide the mapping of mimetype and extension.
|
||||
* The use cases often happen when apps need to know about the exact
|
||||
* mimetypes or extensions, such as to delegate the open web activity, we must
|
||||
* have suitable mimetypes or extensions to request the right activity
|
||||
*
|
||||
* The mapping is basically created according to:
|
||||
* http://en.wikipedia.org/wiki/Internet_media_type
|
||||
*
|
||||
* The supported formats are considered base on the deviceStorage properties:
|
||||
* http://dxr.mozilla.org/mozilla-central/toolkit/content/
|
||||
* devicestorage.properties
|
||||
*
|
||||
*/
|
||||
|
||||
var MimeMapper = {
|
||||
// This list only contains the extensions we currently supported
|
||||
// We should make it more complete for further usages
|
||||
_typeToExtensionMap: {
|
||||
// Image
|
||||
'image/jpeg': 'jpg',
|
||||
'image/png': 'png',
|
||||
'image/gif': 'gif',
|
||||
'image/bmp': 'bmp',
|
||||
// Audio
|
||||
'audio/mpeg': 'mp3',
|
||||
'audio/mp4': 'm4a',
|
||||
'audio/ogg': 'ogg',
|
||||
'audio/webm': 'webm',
|
||||
'audio/3gpp': '3gp',
|
||||
'audio/amr': 'amr',
|
||||
// Video
|
||||
'video/mp4': 'mp4',
|
||||
'video/mpeg': 'mpg',
|
||||
'video/ogg': 'ogg',
|
||||
'video/webm': 'webm',
|
||||
'video/3gpp': '3gp',
|
||||
'video/3gpp2': '3g2',
|
||||
// Application
|
||||
// If we want to support some types, like pdf, just add
|
||||
'application/pdf': 'pdf',
|
||||
'application/vcard': 'vcf',
|
||||
// Text
|
||||
'text/vcard': 'vcf',
|
||||
'text/x-vcard': 'vcf'
|
||||
},
|
||||
|
||||
// This list only contains the mimetypes we currently supported
|
||||
// We should make it more complete for further usages
|
||||
_extensionToTypeMap: {
|
||||
// Image
|
||||
'jpg': 'image/jpeg',
|
||||
'jpeg': 'image/jpeg',
|
||||
'jpe': 'image/jpeg',
|
||||
'png': 'image/png',
|
||||
'gif': 'image/gif',
|
||||
'bmp': 'image/bmp',
|
||||
// Audio
|
||||
'mp3': 'audio/mpeg',
|
||||
'm4a': 'audio/mp4',
|
||||
'm4b': 'audio/mp4',
|
||||
'm4p': 'audio/mp4',
|
||||
'm4r': 'audio/mp4',
|
||||
'aac': 'audio/aac',
|
||||
'opus': 'audio/ogg',
|
||||
'amr': 'audio/amr',
|
||||
// Video
|
||||
'mp4': 'video/mp4',
|
||||
'mpeg': 'video/mpeg',
|
||||
'mpg': 'video/mpeg',
|
||||
'ogv': 'video/ogg',
|
||||
'ogx': 'video/ogg',
|
||||
'webm': 'video/webm',
|
||||
'3gp': 'video/3gpp',
|
||||
'3g2': 'video/3gpp2',
|
||||
'ogg': 'video/ogg',
|
||||
// Application
|
||||
// If we want to support some extensions, like pdf, just add
|
||||
'pdf': 'application/pdf',
|
||||
// Text
|
||||
'vcf': 'text/vcard'
|
||||
},
|
||||
_parseExtension: function(filename) {
|
||||
var array = filename.split('.');
|
||||
return array.length > 1 ? array.pop() : '';
|
||||
},
|
||||
|
||||
isSupportedType: function(mimetype) {
|
||||
return (mimetype in this._typeToExtensionMap);
|
||||
},
|
||||
|
||||
isSupportedExtension: function(extension) {
|
||||
return (extension in this._extensionToTypeMap);
|
||||
},
|
||||
|
||||
isFilenameMatchesType: function(filename, mimetype) {
|
||||
var extension = this._parseExtension(filename);
|
||||
var guessedType = this.guessTypeFromExtension(extension);
|
||||
return (guessedType == mimetype);
|
||||
},
|
||||
|
||||
guessExtensionFromType: function(mimetype) {
|
||||
return this._typeToExtensionMap[mimetype];
|
||||
},
|
||||
|
||||
guessTypeFromExtension: function(extension) {
|
||||
return this._extensionToTypeMap[extension];
|
||||
},
|
||||
|
||||
// If mimetype is not in the supported list, we will try to
|
||||
// predict the possible valid mimetype based on extension.
|
||||
guessTypeFromFileProperties: function(filename, mimetype) {
|
||||
var extension = this._parseExtension(filename);
|
||||
var type = this.isSupportedType(mimetype) ?
|
||||
mimetype : this.guessTypeFromExtension(extension);
|
||||
return type || '';
|
||||
},
|
||||
|
||||
// if mimetype is not supported, preserve the original extension
|
||||
// and add the predict result as new extension.
|
||||
// If both filename and mimetype are not supported, return the original
|
||||
// filename.
|
||||
ensureFilenameMatchesType: function(filename, mimetype) {
|
||||
if (!this.isFilenameMatchesType(filename, mimetype)) {
|
||||
var guessedExt = this.guessExtensionFromType(mimetype);
|
||||
if (guessedExt) {
|
||||
filename += '.' + guessedExt;
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
};
|
||||
35
assets/webapps/download.gaiamobile.org/shared/js/moz_intl.js
Normal file
35
assets/webapps/download.gaiamobile.org/shared/js/moz_intl.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
;(function(global){'use strict';global.mozIntl={formatList:function(list){return navigator.mozL10n.formatValue('listSeparator_middle').then(sep=>list.join(sep));},DateTimeFormat:function(locales,options){const resolvedOptions=Object.assign({},options);if(resolvedOptions.dayperiod){if(resolvedOptions.hour===undefined){resolvedOptions.hour='numeric';}}
|
||||
if(resolvedOptions.hour!==undefined&&resolvedOptions.hour12===undefined){resolvedOptions.hour12=navigator.mozHour12;}
|
||||
if(resolvedOptions.dayperiod===undefined&&resolvedOptions.hour12===true){resolvedOptions.dayperiod=true;}
|
||||
var intlFormat=new Intl.DateTimeFormat(locales,resolvedOptions);resolvedOptions.locale=intlFormat.resolvedOptions().locale;resolvedOptions.hour12=intlFormat.resolvedOptions().hour12;var hourFormatter;if(resolvedOptions.dayperiod!==undefined&&resolvedOptions.hour12===true){hourFormatter=Intl.DateTimeFormat(locales,{hour:'numeric',hour12:false});}
|
||||
return{resolvedOptions(){return resolvedOptions;},format:function(date,tokenFormats){var dayPeriod;var string=intlFormat.format(date);if(resolvedOptions.dayperiod===false&&resolvedOptions.hour12===true){dayPeriod=getDayPeriodTokenForDate(date,hourFormatter);string=string.replace(dayPeriod,'').trim();}else if(resolvedOptions.dayperiod===true&&options.hour===undefined){dayPeriod=getDayPeriodTokenForDate(date,hourFormatter);const hour=date.toLocaleString(navigator.languages,{hour12:true,hour:'numeric'}).replace(dayPeriod,'').trim();string=string.replace(hour,'').trim();}
|
||||
for(var token in tokenFormats){if(token==='dayperiod'&&resolvedOptions.hour12===false){continue;}
|
||||
const localOptions={[token]:resolvedOptions[token],};var formatter=global.mozIntl.DateTimeFormat(navigator.languages,localOptions);var tokenString=formatter.format(date);string=string.replace(tokenString,tokenFormats[token]);}
|
||||
return string;},};},calendarInfo:function(token){switch(token){case'firstDayOfTheWeek':return navigator.mozL10n.formatValue('firstDayOfTheWeek').then(firstDayOfTheWeek=>parseInt(firstDayOfTheWeek)%7);default:throw new Error('Unknown token: '+token);}},DurationFormat:function(locales=navigator.languages,options={}){const resolvedOptions=Object.assign({locale:locales[0],maxUnit:'hour',minUnit:'second',},options);const numFormatter=Intl.NumberFormat(locales,{style:'decimal',useGrouping:false,minimumIntegerDigits:2});const maxUnitIdx=getDurationUnitIdx(resolvedOptions.maxUnit,0);const minUnitIdx=getDurationUnitIdx(resolvedOptions.minUnit,durationFormatOrder.length-1);return navigator.mozL10n.formatValue('durationPattern').then(fmt=>({resolvedOptions:function(){return resolvedOptions;},format:function(input){const minValue=durationFormatElements[resolvedOptions.minUnit].value;input=Math.round(input/minValue)*minValue;const duration=splitIntoTimeUnits(input,maxUnitIdx,minUnitIdx);var string=trimDurationPattern(fmt,resolvedOptions.maxUnit,resolvedOptions.minUnit);for(var unit in duration){const token=durationFormatElements[unit].token;string=string.replace(token,numFormatter.format(duration[unit]));}
|
||||
if(input<0){return'-'+string;}
|
||||
return string;}}));},RelativeTimeFormat:function(locales,options){return{resolvedOptions:function(){return options;},format:function(x){const{unit,value}=relativeTimeFormatId(x,options);return navigator.mozL10n.formatValue(unit,{value});},};},UnitFormat:function(locales,options){const unitGroup=getUnitFormatGroupName(options.unit);if(unitGroup===undefined){throw new RangeError(`invalid value ${options.unit} for option unit`);}
|
||||
if(!unitFormatGroups[unitGroup].styles.includes(options.style)){throw new RangeError(`invalid value ${options.style} for option style`);}
|
||||
const unit=`${unitGroup}-${options.unit}-${options.style}`;return{format:function(x){return document.l10n.formatValue(unit,{value:x});},};},_gaia:{relativePart:function(milliseconds){const units=computeTimeUnits(milliseconds);const unit=getBestMatchUnit(units);return{unit:unit+'s',value:Math.abs(units[unit])};},RelativeDate:function(locales,options){const style=options&&options.style||'long';const maxFormatter=Intl.DateTimeFormat(locales,{year:'numeric',month:'numeric',day:'numeric'});const relativeFmtOptions={unit:'bestFit',style:style,minUnit:'minute',};return{format:function(time,maxDiff){maxDiff=maxDiff||86400*10;const secDiff=(Date.now()-time)/1000;if(isNaN(secDiff)){return navigator.mozL10n.formatValue('incorrectDate');}
|
||||
if(secDiff>maxDiff){return Promise.resolve(maxFormatter.format(time));}
|
||||
const{unit,value}=relativeTimeFormatId(time,relativeFmtOptions);return navigator.mozL10n.formatValue(unit,{value});},formatElement:function(element,time,maxDiff){maxDiff=maxDiff||86400*10;const secDiff=(Date.now()-time)/1000;if(isNaN(secDiff)){element.setAttribute('data-l10n-id','incorrectDate');}
|
||||
element.removeAttribute('data-l10n-id');if(secDiff>maxDiff){element.textContent=maxFormatter.format(time);}
|
||||
const{unit,value}=relativeTimeFormatId(time,relativeFmtOptions);navigator.mozL10n.setAttributes(element,unit,{value});},};},getFormattedUnit:function(type,style,v){if(!unitFormatData.hasOwnProperty(type)){throw new RangeError(`invalid type ${type}`);}
|
||||
if(!unitFormatGroups[type].styles.includes(style)){throw new RangeError(`invalid style ${style} for type ${type}`);}
|
||||
var units=unitFormatData[type];var scale=0;for(let i=1;i<units.length;i++){if(v<units[i].value*unitFormatGroups[type].rounding){scale=i-1;break;}else if(i===units.length-1){scale=i;}}
|
||||
var value=Math.round(v/units[scale].value*100)/100;return global.mozIntl.UnitFormat(navigator.languages,{unit:units[scale].name,style:style}).format(value);},}};const durationFormatOrder=['hour','minute','second','millisecond'];const durationFormatElements={'hour':{value:3600000,token:'hh'},'minute':{value:60000,token:'mm'},'second':{value:1000,token:'ss'},'millisecond':{value:10,token:'SS'}};const unitFormatData={'duration':[{'name':'second','value':1},{'name':'minute','value':60},{'name':'hour','value':60*60},{'name':'day','value':24*60*60},{'name':'month','value':30*24*60*60},],'digital':[{'name':'byte','value':1},{'name':'kilobyte','value':1024},{'name':'megabyte','value':1024*1024},{'name':'gigabyte','value':1024*1024*1024},{'name':'terabyte','value':1024*1024*1024*1024},],};const unitFormatGroups={'duration':{'units':['second','minute','hour','day','month'],'styles':['narrow'],'rounding':1},'digital':{'units':['byte','kilobyte','megabyte','gigabyte','terabyte'],'styles':['short'],'rounding':0.8}};function getDurationUnitIdx(name,defaultValue){if(!name){return defaultValue;}
|
||||
const pos=durationFormatOrder.indexOf(name);if(pos===-1){throw new Error('Unknown unit type: '+name);}
|
||||
return pos;}
|
||||
function splitIntoTimeUnits(v,maxUnitIdx,minUnitIdx){const units={};var input=Math.abs(v);for(var i=maxUnitIdx;i<=minUnitIdx;i++){const key=durationFormatOrder[i];const{value}=durationFormatElements[key];units[key]=i==minUnitIdx?Math.round(input/value):Math.floor(input/value);input-=units[key]*value;}
|
||||
return units;}
|
||||
function trimDurationPattern(string,maxUnit,minUnit){const maxToken=durationFormatElements[maxUnit].token;const minToken=durationFormatElements[minUnit].token;string=string.substring(string.indexOf(maxToken),string.indexOf(minToken)+minToken.length);return string;}
|
||||
function getDayPeriodTokenForDate(date,hourFormatter){const hourToken=hourFormatter.format(date);const newDate=new Date(date);newDate.setHours(parseInt(hourToken));return new Intl.DateTimeFormat(navigator.language, {hour:'numeric', hour12:true}).formatToParts(newDate).find(part => part.type === 'dayPeriod').value;}
|
||||
function computeTimeUnits(v){const units={};const millisecond=Math.round(v);const second=Math.round(millisecond/1000);const minute=Math.round(second/60);const hour=Math.round(minute/60);const day=Math.round(hour/24);const rawYear=day*400/146097;units.millisecond=millisecond;units.second=second;units.minute=minute;units.hour=hour;units.day=day;units.week=Math.round(day/7);units.month=Math.round(rawYear*12);units.quarter=Math.round(rawYear*4);units.year=Math.round(rawYear);return units;}
|
||||
function getBestMatchUnit(units){if(Math.abs(units.minute)<45){return'minute';}
|
||||
if(Math.abs(units.hour)<22){return'hour';}
|
||||
if(Math.abs(units.day)<7){return'day';}
|
||||
if(Math.abs(units.week)<4){return'week';}
|
||||
if(Math.abs(units.month)<11){return'month';}
|
||||
return'year';}
|
||||
function relativeTimeFormatId(x,options){const ms=x-Date.now();const units=computeTimeUnits(ms);const unit=options.unit==='bestFit'?getBestMatchUnit(units):options.unit;const v=units[unit];const tl=v<0?'-ago':'-until';const style=options.style||'long';const entry=unit+'s'+tl+'-'+style;return{unit:entry,value:Math.abs(v)};}
|
||||
function getUnitFormatGroupName(unitName){for(let groupName in unitFormatGroups){if(unitFormatGroups[groupName].units.includes(unitName)){return groupName;}}
|
||||
return undefined;}})(this);
|
||||
428
assets/webapps/download.gaiamobile.org/shared/style/buttons.css
Normal file
428
assets/webapps/download.gaiamobile.org/shared/style/buttons.css
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
/* ----------------------------------
|
||||
* Buttons
|
||||
* ---------------------------------- */
|
||||
|
||||
.button::-moz-focus-inner,
|
||||
.bb-button::-moz-focus-inner,
|
||||
button::-moz-focus-inner {
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button,
|
||||
.bb-button,
|
||||
.button {
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
width: 100%;
|
||||
height: 4rem;
|
||||
margin: 0 0 1rem;
|
||||
padding: 0 1.2rem;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
background: #d8d8d8;
|
||||
border: none;
|
||||
border-radius: 2rem;
|
||||
font-weight: normal;
|
||||
font-size: 1.6rem;
|
||||
line-height: 4rem;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Recommend */
|
||||
button.recommend,
|
||||
.bb-button.recommend {
|
||||
background-color: #00caf2;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Danger */
|
||||
button.danger,
|
||||
.danger.bb-button {
|
||||
background-color: #e51e1e;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Pressed */
|
||||
button:active,
|
||||
.bb-button:active,
|
||||
.button:active {
|
||||
background-color: #b2f2ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
button[data-icon],
|
||||
.bb-button[data-icon],
|
||||
.button[data-icon] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
button[data-icon]:before,
|
||||
.bb-button[data-icon]:before,
|
||||
.button[data-icon]:before {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -1.5rem;
|
||||
offset-inline-end: 1.5rem;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
button[data-icon]:active:before,
|
||||
.bb-button[data-icon]:active:before,
|
||||
.button[data-icon]:active:before {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Pressed with dark skin */
|
||||
.skin-dark button:active,
|
||||
.skin-dark .bb-button:active,
|
||||
.skin-dark .button:active {
|
||||
background-color: #00aacc;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
button[disabled],
|
||||
.bb-button[aria-disabled="true"],
|
||||
.button[aria-disabled="true"] {
|
||||
background-color: rgba(0,0,0,0.05);
|
||||
color: #c7c7c7;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
button[disabled].recommend,
|
||||
.bb-button[aria-disabled="true"].recommend,
|
||||
.button[aria-disabled="true"].recommend {
|
||||
background-color: #97cbd5;
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
button[disabled].danger,
|
||||
.bb-button[aria-disabled="true"].danger,
|
||||
.button[aria-disabled="true"].danger {
|
||||
background-color: #eb7474;
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
/* Disabled with dark background */
|
||||
.skin-dark button[disabled],
|
||||
.skin-dark .button[aria-disabled="true"],
|
||||
.skin-dark .bb-button[aria-disabled="true"] {
|
||||
background-color: #565656;
|
||||
color: rgba(255,255,255,0.4);
|
||||
}
|
||||
|
||||
.skin-dark button[disabled].recommend,
|
||||
.skin-dark .button[aria-disabled="true"].recommend,
|
||||
.skin-dark .bb-button[aria-disabled="true"].recommend {
|
||||
background-color: #006579;
|
||||
}
|
||||
|
||||
.skin-dark button[disabled].danger,
|
||||
.skin-dark .button[aria-disabled="true"].danger,
|
||||
.skin-dark .bb-button[aria-disabled="true"].danger {
|
||||
background-color: #730f0f;
|
||||
}
|
||||
|
||||
button[disabled]::-moz-selection,
|
||||
.button[aria-disabled="true"]::-moz-selection,
|
||||
.bb-button[aria-disabled="true"]::-moz-selection {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
/* ----------------------------------
|
||||
* Buttons inside lists
|
||||
* ---------------------------------- */
|
||||
|
||||
li button,
|
||||
li .bb-button,
|
||||
li .button {
|
||||
position: relative;
|
||||
border: 0.1rem solid #c7c7c7;
|
||||
background: rgba(0,0,0,0.05);
|
||||
margin: 0 0 1rem;
|
||||
overflow: hidden;
|
||||
border-radius: 0;
|
||||
display: flex;
|
||||
height: auto;
|
||||
min-height: 4rem;
|
||||
text-overflow: initial;
|
||||
white-space: normal;
|
||||
line-height: 2rem;
|
||||
padding: 1rem 1.2rem;
|
||||
}
|
||||
html[dir="ltr"] li button,
|
||||
html[dir="ltr"] li .bb-button,
|
||||
html[dir="ltr"] li .button {
|
||||
text-align: left;
|
||||
}
|
||||
html[dir="rtl"] li button,
|
||||
html[dir="rtl"] li .bb-button,
|
||||
html[dir="rtl"] li .button {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Press */
|
||||
li .bb-button:active:after,
|
||||
li .button:active:after,
|
||||
li button:active:after {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
li button:disabled,
|
||||
li .bb-button[aria-disabled="true"],
|
||||
li .button[aria-disabled="true"] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
li button.icon,
|
||||
li .bb-button.icon,
|
||||
li .button.icon {
|
||||
padding-inline-end: 4rem;
|
||||
}
|
||||
|
||||
li button.icon:before,
|
||||
li .bb-button.icon:before,
|
||||
li .button.icon:before {
|
||||
content: "";
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
offset-inline-end: 0.5rem;
|
||||
margin-top: -1.5rem;
|
||||
background: transparent no-repeat center center / 100% auto;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
li button[data-icon]:before,
|
||||
li .bb-button[data-icon]:before,
|
||||
li .button[data-icon]:before {
|
||||
offset-inline-end: 1rem;
|
||||
}
|
||||
|
||||
li button.icon-view:active,
|
||||
li .bb-button.icon-view:active,
|
||||
li .button.icon-view:active {
|
||||
background-color: #b2f2ff;
|
||||
}
|
||||
|
||||
li button[data-icon="expand"]:before,
|
||||
li .bb-button[data-icon="expand"]:before,
|
||||
li .button[data-icon="expand"]:before {
|
||||
color: #00aac5;
|
||||
top: unset;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
li button[data-icon="expand"][disabled]:before,
|
||||
li .bb-button[data-icon="expand"][aria-disabled="true"]:before,
|
||||
li .button[data-icon="expand"][aria-disabled="true"]:before {
|
||||
color: #A9A9A9;
|
||||
}
|
||||
|
||||
li button[data-icon="forward"]:before,
|
||||
li .bb-button[data-icon="forward"]:before,
|
||||
li .button[data-icon="forward"]:before {
|
||||
color: #686f72;
|
||||
}
|
||||
|
||||
/* Getting more space for text, as icon is shorter */
|
||||
li button.icon-dialog,
|
||||
li .bb-button.icon-dialog,
|
||||
li .button.icon-dialog {
|
||||
padding-inline-end: 3rem;
|
||||
}
|
||||
|
||||
li button.icon-dialog:before,
|
||||
li .bb-button.icon-dialog:before,
|
||||
li .button.icon-dialog:before {
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: auto;
|
||||
offset-inline-end: 0.8rem;
|
||||
bottom: 0.5rem;
|
||||
border-top: 0.7rem solid transparent;
|
||||
border-bottom: 0.7rem solid transparent;
|
||||
border-inline-start: 0.7rem solid #00aac5;
|
||||
z-index: 1;
|
||||
}
|
||||
html[dir="ltr"] li button.icon-dialog:before,
|
||||
html[dir="ltr"] li .bb-button.icon-dialog:before,
|
||||
html[dir="ltr"] li .button.icon-dialog:before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
html[dir="rtl"] li button.icon-dialog:before,
|
||||
html[dir="rtl"] li .bb-button.icon-dialog:before,
|
||||
html[dir="rtl"] li .button.icon-dialog:before {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
li button.icon-dialog:disabled:before,
|
||||
li .bb-button[aria-disabled="true"].icon-dialog:before,
|
||||
li .button[aria-disabled="true"].icon-dialog:before {
|
||||
border-inline-start: 0.7rem solid #a9a9a9;
|
||||
}
|
||||
|
||||
/* ----------------------------------
|
||||
* Theme: Dark
|
||||
* ---------------------------------- */
|
||||
|
||||
.skin-dark li button,
|
||||
.skin-dark li .bb-button,
|
||||
.skin-dark li .button {
|
||||
background-color: #454545;
|
||||
border: none;
|
||||
color: #fff;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.skin-dark li button:active,
|
||||
.skin-dark li .button:active,
|
||||
.skin-dark li .bb-button:active {
|
||||
background-color: #00aacc;
|
||||
}
|
||||
|
||||
.skin-dark li button.icon-view:active,
|
||||
.skin-dark li .button.icon-view:active,
|
||||
.skin-dark li .bb-button.icon-view:active {
|
||||
background-color: #00aacc;
|
||||
}
|
||||
|
||||
.skin-dark li button.icon-dialog:active:before,
|
||||
.skin-dark li .bb-button.icon-dialog:active:before,
|
||||
.skin-dark li .button.icon-dialog:active:before {
|
||||
border-inline-start: 0.7rem solid #b2f2ff;
|
||||
}
|
||||
|
||||
.skin-dark li button:disabled,
|
||||
.skin-dark li .bb-button[aria-disabled="true"],
|
||||
.skin-dark li .button[aria-disabled="true"] {
|
||||
background-color: #454545;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Inputs inside of .button */
|
||||
.button input,
|
||||
body[role="application"] .bb-button input,
|
||||
body[role="application"] .button input {
|
||||
border: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
/* select */
|
||||
select {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
font-size: 1.6rem;
|
||||
color: #333;
|
||||
margin: 0 0 1rem;
|
||||
padding: 0;
|
||||
padding-inline-start: 1.1rem;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
height: 4rem;
|
||||
border: 0.1rem solid #c7c7c7;
|
||||
background: rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.skin-dark select {
|
||||
background-color: rgba(87, 87, 87, 0.8);
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* remove dotted outline */
|
||||
select:-moz-focusring {
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 #333;
|
||||
}
|
||||
|
||||
.skin-dark select:-moz-focusring {
|
||||
text-shadow: 0 0 0 #fff;
|
||||
}
|
||||
|
||||
/* Hides dropdown arrow until bug #649849 is fixed */
|
||||
.bb-button.icon select,
|
||||
.button.icon select,
|
||||
.bb-button[data-icon] select,
|
||||
.button[data-icon] select {
|
||||
position: absolute;
|
||||
top: -0.6rem;
|
||||
offset-inline-start: 0;
|
||||
width: calc(100% + 3rem);
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-inline-end: 5rem;
|
||||
text-indent: 0;
|
||||
font-weight: 400;
|
||||
font-size: 1.7rem;
|
||||
color: rgba(0,0,0,0);
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
/**
|
||||
* The select element uses the text color to determine the color of the outline.
|
||||
* We put a text shadow with needed offset and no blur, so that replaces the text.
|
||||
*/
|
||||
html[dir="ltr"] .bb-button.icon select,
|
||||
html[dir="ltr"] .button.icon select,
|
||||
html[dir="ltr"] .bb-button[data-icon] select,
|
||||
html[dir="ltr"] .button[data-icon] select,
|
||||
html[dir="ltr"] .bb-button.icon-dialog select,
|
||||
html[dir="ltr"] .button.icon-dialog select {
|
||||
text-shadow: 1rem 0.5rem 0 #333;
|
||||
}
|
||||
html[dir="rtl"] .bb-button.icon select,
|
||||
html[dir="rtl"] .button.icon select,
|
||||
html[dir="rtl"] .bb-button[data-icon] select,
|
||||
html[dir="rtl"] .button[data-icon] select,
|
||||
html[dir="rtl"] .bb-button.icon-dialog select,
|
||||
html[dir="rtl"] .button.icon-dialog select {
|
||||
text-shadow: -1rem 0.5rem 0 #333;
|
||||
}
|
||||
|
||||
.bb-button.icon select option,
|
||||
.button.icon select option,
|
||||
.bb-button[data-icon] select option,
|
||||
.button[data-icon] select option {
|
||||
color: #000;
|
||||
border: 0;
|
||||
padding: 0.6rem 1.3rem;
|
||||
text-shadow: 0 0 0 rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
.bb-button.icon-dialog,
|
||||
.button.icon-dialog {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .skin-dark .bb-button.icon select,
|
||||
html[dir="ltr"] .skin-dark .button.icon select,
|
||||
html[dir="ltr"] .skin-dark .bb-button[data-icon] select,
|
||||
html[dir="ltr"] .skin-dark .button[data-icon] select,
|
||||
html[dir="ltr"] .skin-dark .bb-button.icon-dialog select,
|
||||
html[dir="ltr"] .skin-dark .button.icon-dialog select {
|
||||
text-shadow: 1rem 0.5rem 0 #fff;
|
||||
}
|
||||
html[dir="rtl"] .skin-dark .bb-button.icon select,
|
||||
html[dir="rtl"] .skin-dark .button.icon select,
|
||||
html[dir="rtl"] .skin-dark .bb-button[data-icon] select,
|
||||
html[dir="rtl"] .skin-dark .button[data-icon] select,
|
||||
html[dir="rtl"] .skin-dark .bb-button.icon-dialog select,
|
||||
html[dir="rtl"] .skin-dark .button.icon-dialog select {
|
||||
text-shadow: -1rem 0.5rem 0 #fff;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30"><path fill="#667174" fill-opacity=".7" d="m 18.2995,19.66 -5.056,-5.057 5.056,-5.056 c -0.31,-0.516 -0.62,-1.032 -0.93,-1.34 l -5.672,5.673 v 1.652 l 5.675,5.676 c 0.31,-0.515 0.722,-0.928 0.93,-1.547 z"/></svg>
|
||||
|
After Width: | Height: | Size: 294 B |
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30"><path fill="#667174" fill-opacity=".7" d="m 11.698,19.66 5.056,-5.057 -5.056,-5.056 c 0.31,-0.516 0.62,-1.032 0.93,-1.34 L 18.3,13.88 v 1.652 l -5.675,5.676 c -0.31,-0.515 -0.722,-0.928 -0.93,-1.547 z"/></svg>
|
||||
|
After Width: | Height: | Size: 292 B |
|
|
@ -0,0 +1,280 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Buttons</title>
|
||||
<link rel="stylesheet" href="../buttons.css">
|
||||
<link rel="stylesheet" href="../../elements/gaia-icons/gaia-icons-embedded.css">
|
||||
<link rel="stylesheet" href="../../elements/gaia-icons/bidi-helper.css">
|
||||
|
||||
<!--
|
||||
- These <style> and <script> elements are only used for the example code,
|
||||
- they are not needed for the real case.
|
||||
-->
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
label.bb-docs {
|
||||
font-family: sans-serif;
|
||||
font-size: 1.2rem;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
h2.bb-docs {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 300;
|
||||
color: #666;
|
||||
margin: -0.1rem 0 0;
|
||||
background-color: #f5f5f5;
|
||||
padding: 0.4rem 3rem;
|
||||
border: solid 0.1rem #e8e8e8;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.bb-docs {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
div.bb-docs.skin-organic {
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
div.bb-docs.skin-dark {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
body[role="application"] > [role="region"] {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[data-icon]:before {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
document.getElementById('dir').checked = false;
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body role="application">
|
||||
<p dir="ltr">
|
||||
<label class="bb-docs">
|
||||
<input id="dir" type="checkbox" checked="false"
|
||||
onchange="document.documentElement.dir = this.checked ? 'rtl' : 'ltr'">
|
||||
RTL mode
|
||||
</label>
|
||||
</p>
|
||||
<h2 class="bb-docs">Special buttons</h2>
|
||||
<div class="bb-docs skin-organic">
|
||||
<button>Default</button>
|
||||
<button class="recommend">Recommend</button>
|
||||
<button class="danger">Danger</button>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Buttons with icons</h2>
|
||||
<div class="bb-docs skin-organic">
|
||||
<button data-icon="forward" aria-label="forward" data-l10n-id="">Default</button>
|
||||
<button data-icon="forward" aria-label="forward" data-l10n-id="" class="recommend">Recommend</button>
|
||||
<button data-icon="forward" aria-label="forward" data-l10n-id="" class="danger">Danger</button>
|
||||
<button data-icon="forward-light" aria-label="forward-light" data-l10n-id="">Default</button>
|
||||
<button data-icon="back" aria-label="back" data-l10n-id="">Default</button>
|
||||
<button data-icon="back-light" aria-label="back-light" data-l10n-id="">Default</button>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Disabled</h2>
|
||||
<div class="bb-docs skin-organic">
|
||||
<button disabled>Default</button>
|
||||
<a href="#" role="button" aria-disabled="true" class="recommend bb-button">Recommend</a>
|
||||
<button disabled class="danger">Danger</button>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Skin dark</h2>
|
||||
<div class="bb-docs skin-dark">
|
||||
<button>Default</button>
|
||||
<button class="recommend">Recommend</button>
|
||||
<button class="danger">Danger</button>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Disabled</h2>
|
||||
<div class="bb-docs skin-dark">
|
||||
<button disabled>Default</button>
|
||||
<a href="#" role="button" aria-disabled="true" class="recommend bb-button">Recommend</a>
|
||||
<button disabled class="danger">Danger</button>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">List buttons</h2>
|
||||
<div class="bb-docs skin-organic">
|
||||
<ul>
|
||||
<li>
|
||||
<button>Default</button>
|
||||
</li>
|
||||
<li>
|
||||
<button disabled>Disabled</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="icon icon-view">
|
||||
Icon view button
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="icon icon-dialog">
|
||||
Icon dialog button
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<span class="button icon icon-dialog">
|
||||
<select>
|
||||
<option selected>Icon dialog with options</option>
|
||||
<option>option 1</option>
|
||||
<option>option 2</option>
|
||||
<option>option 3</option>
|
||||
</select>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<button class="icon icon-dialog" disabled>
|
||||
Icon dialog button disabled
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button data-icon="forward" aria-label="forward" data-l10n-id="">
|
||||
Side navigation
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button disabled data-icon="forward" aria-label="forward" data-l10n-id="">
|
||||
Side navigation
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-icon="expand" class="bb-button" aria-label="expand" data-l10n-id="">
|
||||
Tuesday Sept. 18, 2012
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" aria-disabled="true" data-icon="expand" class="bb-button" aria-label="expand" data-l10n-id="">
|
||||
Tuesday Sept. 18, 2012
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Skin Dark</h2>
|
||||
<div class="bb-docs skin-dark">
|
||||
<ul>
|
||||
<li>
|
||||
<button>Default</button>
|
||||
</li>
|
||||
<li>
|
||||
<button disabled>Disabled</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="icon icon-dialog">
|
||||
Dark icon dialog button
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button data-icon="forward" aria-label="forward" data-l10n-id="">
|
||||
Side navigation
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button disabled data-icon="forward" aria-label="forward" data-l10n-id="">
|
||||
Side navigation
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" data-icon="expand" class="bb-button" aria-label="expand" data-l10n-id="">
|
||||
Tuesday Sept. 18, 2012
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a role="button" aria-disabled="true" data-icon="expand" class="bb-button" aria-label="expand" data-l10n-id="">
|
||||
Tuesday Sept. 18, 2012
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Select</h2>
|
||||
<div class="bb-docs">
|
||||
<select>
|
||||
<option>option 1</option>
|
||||
<option>option 2</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Fake select</h2>
|
||||
<div class="bb-docs">
|
||||
<ul>
|
||||
<li>
|
||||
<span class="bb-button" data-icon="expand" aria-label="expand" data-l10n-id="">
|
||||
<select>
|
||||
<option>option 1</option>
|
||||
<option>option 2</option>
|
||||
</select>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Disabled select</h2>
|
||||
<div class="bb-docs">
|
||||
<ul>
|
||||
<li>
|
||||
<span aria-disabled="true" class="bb-button" data-icon="expand" aria-label="expand" data-l10n-id="">
|
||||
<select>
|
||||
<option>option 1</option>
|
||||
<option>option 2</option>
|
||||
</select>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Skin dark</h2>
|
||||
<div class="bb-docs skin-dark">
|
||||
<select>
|
||||
<option>option 1</option>
|
||||
<option>option 2</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<h2 class="bb-docs">Fake select</h2>
|
||||
<div class="bb-docs skin-dark">
|
||||
<ul>
|
||||
<li>
|
||||
<span class="bb-button" data-icon="expand" aria-label="expand" data-l10n-id="">
|
||||
<select>
|
||||
<option>option 1</option>
|
||||
<option>option 2</option>
|
||||
</select>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span aria-disabled="true" class="bb-button" data-icon="expand" aria-label="expand" data-l10n-id="">
|
||||
<select>
|
||||
<option>option 1</option>
|
||||
<option>option 2</option>
|
||||
</select>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
265
assets/webapps/download.gaiamobile.org/shared/style/confirm.css
Normal file
265
assets/webapps/download.gaiamobile.org/shared/style/confirm.css
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
/* ----------------------------------
|
||||
* Confirm
|
||||
* ---------------------------------- */
|
||||
|
||||
/* Main dialog setup */
|
||||
form[role="dialog"][data-type="confirm"] {
|
||||
background: #2d2d2d;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding-bottom: 7rem;
|
||||
font-size: 0;
|
||||
/* Using font-size: 0; we avoid the unwanted visual space (about 3px)
|
||||
created by white-spaces and break lines in the code betewen inline-block elements */
|
||||
color: #fff;
|
||||
}
|
||||
html[dir="ltr"] form[role="dialog"][data-type="confirm"] { text-align: left; }
|
||||
html[dir="rtl"] form[role="dialog"][data-type="confirm"] { text-align: right; }
|
||||
|
||||
form[role="dialog"][data-type="confirm"]:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 0.1rem;
|
||||
height: 100%;
|
||||
margin-inline-start: -0.1rem;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] > section {
|
||||
font-weight: 300;
|
||||
font-size: 2.2rem;
|
||||
color: #FAFAFA;
|
||||
padding: 0 1.5rem;
|
||||
box-sizing: padding-box;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
overflow-y: scroll;
|
||||
max-height: 100%;
|
||||
vertical-align: middle;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] h1 {
|
||||
font-weight: normal;
|
||||
font-size: 1.6rem;
|
||||
line-height: 1.5em;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
padding: 1rem 1.5rem 0;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/* Menu & buttons setup */
|
||||
form[role="dialog"][data-type="confirm"] menu {
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
padding: 1.5rem;
|
||||
background: #4d4d4d;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] menu button::-moz-focus-inner {
|
||||
border: none;
|
||||
outline: none;
|
||||
margin-top: -0.2rem; /* To fix line-height bug (697451) */
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] menu button {
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
width: 100%;
|
||||
height: 4rem;
|
||||
margin: 0 0 1rem;
|
||||
padding: 0 0.2rem;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
background: #d8d8d8;
|
||||
border: none;
|
||||
border-radius: 2rem;
|
||||
font-weight: normal;
|
||||
font-size: 1.6rem;
|
||||
line-height: 4rem;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
text-shadow: none;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Recommend */
|
||||
form[role="dialog"][data-type="confirm"] menu button.recommend {
|
||||
background-color: #00caf2;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Danger */
|
||||
form[role="dialog"][data-type="confirm"] menu button.danger {
|
||||
background-color: #e51e1e;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Pressed */
|
||||
form[role="dialog"][data-type="confirm"] menu button:active {
|
||||
background: #00aacc;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
form[role="dialog"][data-type="confirm"] > menu > button[disabled] {
|
||||
background-color: #565656;
|
||||
color: rgba(255,255,255,0.4);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] > menu > button[disabled].recommend {
|
||||
background-color: #006579;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] > menu > button[disabled].danger {
|
||||
background-color: #730f0f;
|
||||
}
|
||||
|
||||
button[disabled]::-moz-selection {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] menu button {
|
||||
margin: 0;
|
||||
margin-inline-end: 1rem;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] menu button:last-child {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Specific component code
|
||||
**
|
||||
** 1. Text in confirm dialog should not be selectable.
|
||||
*/
|
||||
form[role="dialog"][data-type="confirm"] p:nth-child(2) {
|
||||
margin: 1rem 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p {
|
||||
word-wrap: break-word;
|
||||
margin: 0;
|
||||
padding: 1rem 1.5rem;
|
||||
border-top: 0.1rem solid #686868;
|
||||
line-height: 3rem;
|
||||
-moz-user-select: none; /* 1 */
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p > span {
|
||||
font-size: 1.5rem;
|
||||
display: block;
|
||||
line-height: 1.7rem;
|
||||
color: rgba(255,255,255,0.6);
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p img {
|
||||
margin-inline-end: 2rem;
|
||||
}
|
||||
html[dir="ltr"] form[role="dialog"][data-type="confirm"] p img { float: left; }
|
||||
html[dir="rtl"] form[role="dialog"][data-type="confirm"] p img { float: right; }
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p strong {
|
||||
display: block;
|
||||
margin-top: 0.2rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] p small {
|
||||
font-size: 1.4rem;
|
||||
font-weight: normal;
|
||||
color: #cbcbcb;
|
||||
display: block;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] dl {
|
||||
border-top: 0.1rem solid #686868;
|
||||
margin: 1rem 0 0;
|
||||
overflow: hidden;
|
||||
padding-top: 1rem;
|
||||
font-size: 1.6rem;
|
||||
line-height: 2.2rem;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] dl > dt {
|
||||
clear: both;
|
||||
width: 7rem;
|
||||
padding-inline-start: 1.5rem;
|
||||
font-weight: 500;
|
||||
text-align: left;
|
||||
}
|
||||
html[dir="ltr"] form[role="dialog"][data-type="confirm"] dl > dt { float: left; }
|
||||
html[dir="rtl"] form[role="dialog"][data-type="confirm"] dl > dt { float: right; text-align: right; }
|
||||
|
||||
form[role="dialog"][data-type="confirm"] dl > dd {
|
||||
padding-inline-end: 1.5rem;
|
||||
font-weight: 300;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: top;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] dl > dd > div {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] figure {
|
||||
margin: 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] figure img {
|
||||
padding-inline-end: 1.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] figure figcaption {
|
||||
font-size: 2.1rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] ul {
|
||||
margin: 0;
|
||||
padding: 2rem 1.5rem;
|
||||
border-top: 0.1rem solid #686868;
|
||||
list-style: none;
|
||||
font-size: 1.6rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] ul li {
|
||||
word-wrap: break-word;
|
||||
line-height: 2rem;
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] ul li:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
form[role="dialog"][data-type="confirm"] ul li ul {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Confirm</title>
|
||||
<meta name="description" content="Prompts user to take action">
|
||||
|
||||
<link rel="stylesheet" href="../confirm.css">
|
||||
|
||||
<!--
|
||||
- These <style> and <script> elements are only used for the example code;
|
||||
- they are not required for the real use case.
|
||||
-->
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
#dir {
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
display: block;
|
||||
direction: ltr;
|
||||
background-color: white;
|
||||
}
|
||||
#dir input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onload = function(){
|
||||
var input = document.querySelector('#dir input');
|
||||
input.checked = false;
|
||||
input.onchange = function() {
|
||||
document.documentElement.dir = this.checked ? 'rtl' : 'ltr';
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body role="application">
|
||||
<label id="dir">
|
||||
<input type="checkbox"> RTL mode
|
||||
</label>
|
||||
|
||||
<form role="dialog" data-type="confirm">
|
||||
<section>
|
||||
<h1>Confirmation</h1>
|
||||
<p>Are you sure you want to delete this contact?</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button>Cancel</button>
|
||||
<button class="danger">Delete</button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Confirm</title>
|
||||
<meta name="description" content="Prompts user to take action">
|
||||
|
||||
<link rel="stylesheet" href="../confirm.css">
|
||||
|
||||
<!--
|
||||
- These <style> and <script> elements are only used for the example code;
|
||||
- they are not required for the real use case.
|
||||
-->
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
#dir {
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
display: block;
|
||||
direction: ltr;
|
||||
background-color: white;
|
||||
}
|
||||
#dir input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onload = function(){
|
||||
var input = document.querySelector('#dir input');
|
||||
input.checked = false;
|
||||
input.onchange = function() {
|
||||
document.documentElement.dir = this.checked ? 'rtl' : 'ltr';
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body role="application">
|
||||
<label id="dir">
|
||||
<input type="checkbox"> RTL mode
|
||||
</label>
|
||||
|
||||
<form role="dialog" data-type="confirm">
|
||||
<section>
|
||||
<h1>Confirmation</h1>
|
||||
<p dir="auto">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button>Cancel</button>
|
||||
<button class="danger">Delete</button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Confirm, w/o title</title>
|
||||
<meta name="description" content="Prompts user to take action">
|
||||
|
||||
<link rel="stylesheet" href="../confirm.css">
|
||||
|
||||
<!--
|
||||
- These <style> and <script> elements are only used for the example code;
|
||||
- they are not required for the real use case.
|
||||
-->
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
#dir {
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
display: block;
|
||||
direction: ltr;
|
||||
background-color: white;
|
||||
}
|
||||
#dir input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.onload = function(){
|
||||
var input = document.querySelector('#dir input');
|
||||
input.checked = false;
|
||||
input.onchange = function() {
|
||||
document.documentElement.dir = this.checked ? 'rtl' : 'ltr';
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body role="application">
|
||||
<label id="dir">
|
||||
<input type="checkbox"> RTL mode
|
||||
</label>
|
||||
|
||||
<form role="dialog" data-type="confirm">
|
||||
<section>
|
||||
<p dir="auto">Are you sure you want to delete this contact?</p>
|
||||
</section>
|
||||
<menu>
|
||||
<button>Cancel</button>
|
||||
<button class="danger">Delete</button>
|
||||
</menu>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
242
assets/webapps/download.gaiamobile.org/shared/style/lists.css
Normal file
242
assets/webapps/download.gaiamobile.org/shared/style/lists.css
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
/* ----------------------------------
|
||||
* Lists
|
||||
* ---------------------------------- */
|
||||
[data-type="list"] {
|
||||
font-weight: 400;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
[data-type="list"] ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[data-type="list"] strong {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Title divisors */
|
||||
[data-type="list"] header {
|
||||
padding: 0 1.5rem;
|
||||
margin: 0;
|
||||
font-size: 1.6rem;
|
||||
height: 3rem;
|
||||
line-height: 4rem;
|
||||
font-weight: normal;
|
||||
color: #ff4e00;
|
||||
text-transform: uppercase;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
html[dir="ltr"] [data-type="list"] header { text-align: left; }
|
||||
html[dir="rtl"] [data-type="list"] header { text-align: right; }
|
||||
|
||||
/* List items */
|
||||
[data-type="list"] li {
|
||||
width: 100%;
|
||||
height: 6rem;
|
||||
box-sizing: border-box;
|
||||
border-bottom: solid 0.1rem #e7e7e7;
|
||||
color: #333;
|
||||
margin: 0;
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[data-type="list"] li:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Pressed State */
|
||||
li a:active {
|
||||
background-color: transparent; /* remove default color for active state */
|
||||
}
|
||||
|
||||
[data-type="list"] li > a {
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
display: block;
|
||||
height: 6rem;
|
||||
position: relative;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
[data-type="list"].active li:after,
|
||||
[data-type="list"] li > a:after {
|
||||
content: "";
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
left: -1.5rem;
|
||||
top: 0;
|
||||
right: -1.5rem;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
[data-type="list"].active li:active:after,
|
||||
[data-type="list"] li > a:active:after {
|
||||
background-color: rgba(0,213,255,0.3);
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
[data-type="list"] li[aria-disabled="true"] {
|
||||
pointer-events: none;
|
||||
opacity: 0.2;
|
||||
border-color: #888;
|
||||
}
|
||||
|
||||
/* Graphic content */
|
||||
[data-type="list"] aside {
|
||||
margin: 0;
|
||||
margin-inline-end: 0.5rem;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
html[dir="ltr"] [data-type="list"] aside { float: left; }
|
||||
html[dir="rtl"] [data-type="list"] aside { float: right; }
|
||||
|
||||
[data-type="list"] li > a aside,
|
||||
[data-type="list"] li > a aside.icon {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[data-type="list"] aside.pack-end {
|
||||
margin: 0;
|
||||
margin-inline-start: 0.5rem;
|
||||
text-align: end;
|
||||
}
|
||||
html[dir="ltr"] [data-type="list"] aside.pack-end { float: right; }
|
||||
html[dir="rtl"] [data-type="list"] aside.pack-end { float: left; }
|
||||
|
||||
[data-type="list"] aside.icon {
|
||||
width: 3rem;
|
||||
height: 6rem;
|
||||
background-color: #fff;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
font-size: 0;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
html[dir="ltr"] [data-type="list"] aside.icon {
|
||||
background-position: left center;
|
||||
}
|
||||
html[dir="rtl"] [data-type="list"] aside.icon {
|
||||
background-position: right center;
|
||||
}
|
||||
|
||||
[data-type="list"] aside span[data-type=img],
|
||||
[data-type="list"] aside img {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
width: 5rem;
|
||||
height: 5rem;
|
||||
border-radius: 2.5rem;
|
||||
margin-top: 0.5rem;
|
||||
box-sizing: border-box;
|
||||
background: transparent center center / cover;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
[data-type="list"] [data-icon] {
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
[data-type="list"] [data-icon]:before {
|
||||
line-height: 6rem;
|
||||
text-align: center;
|
||||
width: 3rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Text content */
|
||||
[data-type="list"] li p {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border: none;
|
||||
display: block;
|
||||
margin: 0;
|
||||
color: #858585;
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
[data-type="list"] li p:first-of-type {
|
||||
font-size: 1.8rem;
|
||||
line-height: 2.2rem;
|
||||
color: #333;
|
||||
padding: 1rem 0 0;
|
||||
}
|
||||
|
||||
[data-type="list"] li p:only-child,
|
||||
[data-type="list"] li p:first-of-type:last-of-type {
|
||||
line-height: 4rem;
|
||||
}
|
||||
|
||||
[data-type="list"] li p em {
|
||||
font-size: 1.5rem;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
[data-type="list"] li p time {
|
||||
margin-inline-end: 0.3rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* Checkable content */
|
||||
[data-type="list"] li > .pack-checkbox,
|
||||
[data-type="list"] li > .pack-switch {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: -0.1rem;
|
||||
bottom: 0;
|
||||
/* Intentionally adding a conflict between right/left here: this will be
|
||||
* resolved differently whether we're in LTR or RTL mode. */
|
||||
right: -4rem;
|
||||
left: -4rem;
|
||||
width: calc(100% + 4rem);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[data-type="list"] li > .pack-checkbox input ~ span:after,
|
||||
[data-type="list"] li > .pack-switch input ~ span:after {
|
||||
/* because width is set in switches.css, the conflict between left/right will
|
||||
* be resolved in favor of "left" in LTR and "right" in RTL */
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
/* Edit mode */
|
||||
[data-type="list"] [data-type="edit"] li {
|
||||
padding-inline-start: 4rem;
|
||||
}
|
||||
|
||||
[data-type="list"] [data-type="edit"] li > .pack-checkbox,
|
||||
[data-type="list"] [data-type="edit"] li > .pack-switch {
|
||||
pointer-events: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
[data-type="list"] [data-type="edit"] li > a {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
[data-type="list"] [data-type="edit"] li > a:active:after,
|
||||
[data-type="list"] [data-type="edit"] li > a:hover:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-type="list"] [data-type="edit"] aside.pack-end {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Themes */
|
||||
.skin-comms [data-type="list"] header {
|
||||
color: #4997a7;
|
||||
}
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Lists</title>
|
||||
<meta name="description" content="Displaying an enumeration of a set of items ">
|
||||
|
||||
<link rel="stylesheet" href="../lists.css">
|
||||
|
||||
<!--
|
||||
- These <style>, <script> and <link> elements are only used for the example
|
||||
- code, they are not needed for the real case.
|
||||
-->
|
||||
<link rel="stylesheet" href="../../style/headers.css">
|
||||
<link rel="stylesheet" href="../../style/switches.css">
|
||||
<link rel="stylesheet" href="../../style/buttons.css">
|
||||
<link rel="stylesheet" href="../../elements/gaia-icons/gaia-icons-embedded.css">
|
||||
<link rel="stylesheet" href="../../elements/gaia-icons/bidi-helper.css">
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
|
||||
h2.pack-docs {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 300;
|
||||
color: #666;
|
||||
margin: -1px 0 0;
|
||||
background-color: #f5f5f5;
|
||||
padding: 0.4rem 0.4rem 0.4rem 3rem;
|
||||
border: solid 1px #e8e8e8;
|
||||
}
|
||||
|
||||
h2.pack-docs:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
[data-type="list"] li img[alt="placeholder"] {
|
||||
background: #ccc url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNS4wLjIsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkNhcGFfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHdpZHRoPSI1MHB4IiBoZWlnaHQ9IjUwcHgiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgNTAgNTAiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGxpbmUgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHgxPSIwIiB5MT0iMCIgeDI9IjUwIiB5Mj0iNTAiLz4NCjxsaW5lIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiB4MT0iNTAiIHkxPSIwIiB4Mj0iMC4wODIiIHkyPSI0OS45MTkiLz4NCjwvc3ZnPg0K);
|
||||
background-size: 100% 100%;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
[data-icon]:before {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
[data-type="list"] [data-icon="forward"]:before {
|
||||
color: #686f72;
|
||||
}
|
||||
|
||||
#settings-list { background-color: #eff0eb; }
|
||||
#settings-list li { border-color: #dcdcdc; }
|
||||
#settings-list button { max-width: 8rem; margin: 1rem 1rem 0 0; }
|
||||
#settings-list aside label { margin: 0 1rem 0 0; height: 100%; }
|
||||
#settings-list > header h2 { margin: 0 1.5rem; }
|
||||
</style>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
var dirInput = document.getElementById('dir');
|
||||
dirInput.checked = false;
|
||||
dirInput.onchange = function() {
|
||||
document.documentElement.dir = this.checked ? "rtl" : "ltr";
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body role="application">
|
||||
<p dir="ltr">
|
||||
<label class="bb-docs">
|
||||
<input id="dir" type="checkbox"> RTL mode
|
||||
</label>
|
||||
</p>
|
||||
<section data-type="list">
|
||||
<header>Title</header>
|
||||
<ul>
|
||||
<li>
|
||||
<p>Margherita <strong>Gomez</strong></p>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<aside class="pack-end" data-icon="forward" data-l10n-id="" aria-label="forward"></aside>
|
||||
<p>Margherita Clickable <strong>Gomez</strong></p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<aside class="pack-end">
|
||||
<img alt="placeholder" src="myimage.jpg">
|
||||
</aside>
|
||||
<a href="#">
|
||||
<p>Margherita <strong>Gomez</strong></p>
|
||||
<p>Family</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<header>Another title</header>
|
||||
<ul>
|
||||
<li aria-disabled="true">
|
||||
<aside class="pack-end">
|
||||
<img alt="placeholder" src="myimage.jpg">
|
||||
</aside>
|
||||
<a href="#">
|
||||
<p>Margherita <strong>Gomez</strong></p>
|
||||
<p>Family</p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<aside class="pack-end icon icon-nopic"></aside>
|
||||
<a href="#">
|
||||
<aside data-icon="call-outgoing" data-l10n-id="" aria-label="outgoing call">
|
||||
asidecall
|
||||
</aside>
|
||||
<p dir="auto">
|
||||
Margherita <strong>Gomez</strong>
|
||||
<em>(2)</em>
|
||||
</p>
|
||||
<p>
|
||||
<time datetime="17:43">5:43PM</time>
|
||||
Mobile, Vivo
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section data-type="list">
|
||||
<header>Edit mode</header>
|
||||
<ul data-type="edit">
|
||||
<li>
|
||||
<label class="pack-checkbox danger">
|
||||
<input type="checkbox">
|
||||
<span></span>
|
||||
</label>
|
||||
<aside class="pack-end">
|
||||
<img alt="placeholder" src="myimage.jpg">
|
||||
</aside>
|
||||
<a href="#">
|
||||
<p>Margherita <strong>Gomez</strong></p>
|
||||
<p>Family</p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<label class="pack-checkbox danger">
|
||||
<input type="checkbox">
|
||||
<span></span>
|
||||
</label>
|
||||
<a href="#">
|
||||
<aside data-icon="call-outgoing" data-l10n-id="" aria-label="outgoing call"></aside>
|
||||
<p dir="auto">
|
||||
Margherita <strong>Gomez</strong>
|
||||
<em>(2)</em>
|
||||
</p>
|
||||
<p>
|
||||
<time datetime="17:43">5:43PM</time>
|
||||
Mobile, Vivo
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section id="settings-list" role="region" class="skin-organic">
|
||||
<section data-type="list">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#">
|
||||
<aside data-icon="call-outgoing" data-l10n-id="" aria-label="outgoing call"></aside>
|
||||
<p>Phone lock</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<header>
|
||||
<h2>Settings style</h2>
|
||||
</header>
|
||||
<section data-type="list">
|
||||
<ul>
|
||||
<li>
|
||||
<aside class="pack-end">
|
||||
<button class="icon icon-dialog">Spain</button>
|
||||
</aside>
|
||||
<p>Time zone</p>
|
||||
<p>Choose your country</p>
|
||||
</li>
|
||||
<li>
|
||||
<aside class="pack-end">
|
||||
<label class="pack-switch">
|
||||
<input type="checkbox" checked>
|
||||
<span></span>
|
||||
</label>
|
||||
</aside>
|
||||
<p>Phone lock</p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in a new issue