Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
|
|
@ -0,0 +1,565 @@
|
|||
;(function(window,undefined){'use strict';function L10nError(message,id,loc){this.name='L10nError';this.message=message;this.id=id;this.loc=loc;}
|
||||
L10nError.prototype=Object.create(Error.prototype);L10nError.prototype.constructor=L10nError;var io={_load:function(type,url,callback,sync){var xhr=new XMLHttpRequest();var needParse;if(xhr.overrideMimeType){xhr.overrideMimeType(type);}
|
||||
xhr.open('GET',url,!sync);if(type==='application/json'){if(sync){needParse=true;}else{xhr.responseType='json';}}
|
||||
xhr.addEventListener('load',function io_onload(e){if(e.target.status===200||e.target.status===0){var res=e.target.response||e.target.responseText;callback(null,needParse?JSON.parse(res):res);}else{callback(new L10nError('Not found: '+url));}});xhr.addEventListener('error',callback);xhr.addEventListener('timeout',callback);try{xhr.send(null);}catch(e){if(e.name==='NS_ERROR_FILE_NOT_FOUND'){callback(new L10nError('Not found: '+url));}else{throw e;}}},load:function(url,callback,sync){return io._load('text/plain',url,callback,sync);},loadJSON:function(url,callback,sync){return io._load('application/json',url,callback,sync);}};function EventEmitter(){}
|
||||
EventEmitter.prototype.emit=function ee_emit(){if(!this._listeners){return;}
|
||||
var args=Array.prototype.slice.call(arguments);var type=args.shift();if(!this._listeners[type]){return;}
|
||||
var typeListeners=this._listeners[type].slice();for(var i=0;i<typeListeners.length;i++){typeListeners[i].apply(this,args);}};EventEmitter.prototype.addEventListener=function ee_add(type,listener){if(!this._listeners){this._listeners={};}
|
||||
if(!(type in this._listeners)){this._listeners[type]=[];}
|
||||
this._listeners[type].push(listener);};EventEmitter.prototype.removeEventListener=function ee_rm(type,listener){if(!this._listeners){return;}
|
||||
var typeListeners=this._listeners[type];var pos=typeListeners.indexOf(listener);if(pos===-1){return;}
|
||||
typeListeners.splice(pos,1);};function getPluralRule(lang){var locales2rules={'af':3,'ak':4,'am':4,'ar':1,'asa':3,'az':0,'be':11,'bem':3,'bez':3,'bg':3,'bh':4,'bm':0,'bn':3,'bo':0,'br':20,'brx':3,'bs':11,'ca':3,'cgg':3,'chr':3,'cs':12,'cy':17,'da':3,'de':3,'dv':3,'dz':0,'ee':3,'el':3,'en':3,'eo':3,'es':3,'et':3,'eu':3,'fa':0,'ff':5,'fi':3,'fil':4,'fo':3,'fr':5,'fur':3,'fy':3,'ga':8,'gd':24,'gl':3,'gsw':3,'gu':3,'guw':4,'gv':23,'ha':3,'haw':3,'he':2,'hi':4,'hr':11,'hu':0,'id':0,'ig':0,'ii':0,'is':3,'it':3,'iu':7,'ja':0,'jmc':3,'jv':0,'ka':0,'kab':5,'kaj':3,'kcg':3,'kde':0,'kea':0,'kk':3,'kl':3,'km':0,'kn':0,'ko':0,'ksb':3,'ksh':21,'ku':3,'kw':7,'lag':18,'lb':3,'lg':3,'ln':4,'lo':0,'lt':10,'lv':6,'mas':3,'mg':4,'mk':16,'ml':3,'mn':3,'mo':9,'mr':3,'ms':0,'mt':15,'my':0,'nah':3,'naq':7,'nb':3,'nd':3,'ne':3,'nl':3,'nn':3,'no':3,'nr':3,'nso':4,'ny':3,'nyn':3,'om':3,'or':3,'pa':3,'pap':3,'pl':13,'ps':3,'pt':3,'rm':3,'ro':9,'rof':3,'ru':11,'rwk':3,'sah':0,'saq':3,'se':7,'seh':3,'ses':0,'sg':0,'sh':11,'shi':19,'sk':12,'sl':14,'sma':7,'smi':7,'smj':7,'smn':7,'sms':7,'sn':3,'so':3,'sq':3,'sr':11,'ss':3,'ssy':3,'st':3,'sv':3,'sw':3,'syr':3,'ta':3,'te':3,'teo':3,'th':0,'ti':4,'tig':3,'tk':3,'tl':4,'tn':3,'to':0,'tr':0,'ts':3,'tzm':22,'uk':11,'ur':3,'ve':3,'vi':0,'vun':3,'wa':4,'wae':3,'wo':0,'xh':3,'xog':3,'yo':0,'zh':0,'zu':3};function isIn(n,list){return list.indexOf(n)!==-1;}
|
||||
function isBetween(n,start,end){return typeof n===typeof start&&start<=n&&n<=end;}
|
||||
var pluralRules={'0':function(){return'other';},'1':function(n){if((isBetween((n%100),3,10))){return'few';}
|
||||
if(n===0){return'zero';}
|
||||
if((isBetween((n%100),11,99))){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'2':function(n){if(n!==0&&(n%10)===0){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'3':function(n){if(n===1){return'one';}
|
||||
return'other';},'4':function(n){if((isBetween(n,0,1))){return'one';}
|
||||
return'other';},'5':function(n){if((isBetween(n,0,2))&&n!==2){return'one';}
|
||||
return'other';},'6':function(n){if(n===0){return'zero';}
|
||||
if((n%10)===1&&(n%100)!==11){return'one';}
|
||||
return'other';},'7':function(n){if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'8':function(n){if((isBetween(n,3,6))){return'few';}
|
||||
if((isBetween(n,7,10))){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'9':function(n){if(n===0||n!==1&&(isBetween((n%100),1,19))){return'few';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'10':function(n){if((isBetween((n%10),2,9))&&!(isBetween((n%100),11,19))){return'few';}
|
||||
if((n%10)===1&&!(isBetween((n%100),11,19))){return'one';}
|
||||
return'other';},'11':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
|
||||
if((n%10)===0||(isBetween((n%10),5,9))||(isBetween((n%100),11,14))){return'many';}
|
||||
if((n%10)===1&&(n%100)!==11){return'one';}
|
||||
return'other';},'12':function(n){if((isBetween(n,2,4))){return'few';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'13':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
|
||||
if(n!==1&&(isBetween((n%10),0,1))||(isBetween((n%10),5,9))||(isBetween((n%100),12,14))){return'many';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'14':function(n){if((isBetween((n%100),3,4))){return'few';}
|
||||
if((n%100)===2){return'two';}
|
||||
if((n%100)===1){return'one';}
|
||||
return'other';},'15':function(n){if(n===0||(isBetween((n%100),2,10))){return'few';}
|
||||
if((isBetween((n%100),11,19))){return'many';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'16':function(n){if((n%10)===1&&n!==11){return'one';}
|
||||
return'other';},'17':function(n){if(n===3){return'few';}
|
||||
if(n===0){return'zero';}
|
||||
if(n===6){return'many';}
|
||||
if(n===2){return'two';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'18':function(n){if(n===0){return'zero';}
|
||||
if((isBetween(n,0,2))&&n!==0&&n!==2){return'one';}
|
||||
return'other';},'19':function(n){if((isBetween(n,2,10))){return'few';}
|
||||
if((isBetween(n,0,1))){return'one';}
|
||||
return'other';},'20':function(n){if((isBetween((n%10),3,4)||((n%10)===9))&&!(isBetween((n%100),10,19)||isBetween((n%100),70,79)||isBetween((n%100),90,99))){return'few';}
|
||||
if((n%1000000)===0&&n!==0){return'many';}
|
||||
if((n%10)===2&&!isIn((n%100),[12,72,92])){return'two';}
|
||||
if((n%10)===1&&!isIn((n%100),[11,71,91])){return'one';}
|
||||
return'other';},'21':function(n){if(n===0){return'zero';}
|
||||
if(n===1){return'one';}
|
||||
return'other';},'22':function(n){if((isBetween(n,0,1))||(isBetween(n,11,99))){return'one';}
|
||||
return'other';},'23':function(n){if((isBetween((n%10),1,2))||(n%20)===0){return'one';}
|
||||
return'other';},'24':function(n){if((isBetween(n,3,10)||isBetween(n,13,19))){return'few';}
|
||||
if(isIn(n,[2,12])){return'two';}
|
||||
if(isIn(n,[1,11])){return'one';}
|
||||
return'other';}};var index=locales2rules[lang.replace(/-.*$/,'')];if(!(index in pluralRules)){return function(){return'other';};}
|
||||
return pluralRules[index];}
|
||||
var MAX_PLACEABLES=100;var PropertiesParser={patterns:null,entryIds:null,init:function(){this.patterns={comment:/^\s*#|^\s*$/,entity:/^([^=\s]+)\s*=\s*(.*)$/,multiline:/[^\\]\\$/,index:/\{\[\s*(\w+)(?:\(([^\)]*)\))?\s*\]\}/i,unicode:/\\u([0-9a-fA-F]{1,4})/g,entries:/[^\r\n]+/g,controlChars:/\\([\\\n\r\t\b\f\{\}\"\'])/g,placeables:/\{\{\s*([^\s]*?)\s*\}\}/,};},parse:function(ctx,source){if(!this.patterns){this.init();}
|
||||
var ast=[];this.entryIds=Object.create(null);var entries=source.match(this.patterns.entries);if(!entries){return ast;}
|
||||
for(var i=0;i<entries.length;i++){var line=entries[i];if(this.patterns.comment.test(line)){continue;}
|
||||
while(this.patterns.multiline.test(line)&&i<entries.length){line=line.slice(0,-1)+entries[++i].trim();}
|
||||
var entityMatch=line.match(this.patterns.entity);if(entityMatch){try{this.parseEntity(entityMatch[1],entityMatch[2],ast);}catch(e){if(ctx){ctx._emitter.emit('parseerror',e);}else{throw e;}}}}
|
||||
return ast;},parseEntity:function(id,value,ast){var name,key;var pos=id.indexOf('[');if(pos!==-1){name=id.substr(0,pos);key=id.substring(pos+1,id.length-1);}else{name=id;key=null;}
|
||||
var nameElements=name.split('.');if(nameElements.length>2){throw new L10nError('Error in ID: "'+name+'".'+' Nested attributes are not supported.');}
|
||||
var attr;if(nameElements.length>1){name=nameElements[0];attr=nameElements[1];if(attr[0]==='$'){throw new L10nError('Attribute can\'t start with "$"',id);}}else{attr=null;}
|
||||
this.setEntityValue(name,attr,key,this.unescapeString(value),ast);},setEntityValue:function(id,attr,key,rawValue,ast){var pos,v;var value=rawValue.indexOf('{{')>-1?this.parseString(rawValue):rawValue;if(attr){pos=this.entryIds[id];if(pos===undefined){v={$i:id};if(key){v[attr]={};v[attr][key]=value;}else{v[attr]=value;}
|
||||
ast.push(v);this.entryIds[id]=ast.length-1;return;}
|
||||
if(key){if(typeof(ast[pos][attr])==='string'){ast[pos][attr]={$x:this.parseIndex(ast[pos][attr]),$v:{}};}
|
||||
ast[pos][attr].$v[key]=value;return;}
|
||||
ast[pos][attr]=value;return;}
|
||||
if(key){pos=this.entryIds[id];if(pos===undefined){v={};v[key]=value;ast.push({$i:id,$v:v});this.entryIds[id]=ast.length-1;return;}
|
||||
if(typeof(ast[pos].$v)==='string'){ast[pos].$x=this.parseIndex(ast[pos].$v);ast[pos].$v={};}
|
||||
ast[pos].$v[key]=value;return;}
|
||||
ast.push({$i:id,$v:value});this.entryIds[id]=ast.length-1;},parseString:function(str){var chunks=str.split(this.patterns.placeables);var complexStr=[];var len=chunks.length;var placeablesCount=(len-1)/2;if(placeablesCount>=MAX_PLACEABLES){throw new L10nError('Too many placeables ('+placeablesCount+', max allowed is '+MAX_PLACEABLES+')');}
|
||||
for(var i=0;i<chunks.length;i++){if(chunks[i].length===0){continue;}
|
||||
if(i%2===1){complexStr.push({t:'idOrVar',v:chunks[i]});}else{complexStr.push(chunks[i]);}}
|
||||
return complexStr;},unescapeString:function(str){if(str.lastIndexOf('\\')!==-1){str=str.replace(this.patterns.controlChars,'$1');}
|
||||
return str.replace(this.patterns.unicode,function(match,token){return unescape('%u'+'0000'.slice(token.length)+token);});},parseIndex:function(str){var match=str.match(this.patterns.index);if(!match){throw new L10nError('Malformed index');}
|
||||
if(match[2]){return[{t:'idOrVar',v:match[1]},match[2]];}else{return[{t:'idOrVar',v:match[1]}];}}};var KNOWN_MACROS=['plural'];var MAX_PLACEABLE_LENGTH=2500;var rePlaceables=/\{\{\s*(.+?)\s*\}\}/g;var nonLatin1=/[^\x01-\xFF]/;var FSI='\u2068';var PDI='\u2069';function createEntry(node,env){var keys=Object.keys(node);if(typeof node.$v==='string'&&keys.length===2){return node.$v;}
|
||||
var attrs;for(var i=0,key;key=keys[i];i++){if(key[0]==='$'){continue;}
|
||||
if(!attrs){attrs=Object.create(null);}
|
||||
attrs[key]=createAttribute(node[key],env,node.$i+'.'+key);}
|
||||
return{id:node.$i,value:node.$v!==undefined?node.$v:null,index:node.$x||null,attrs:attrs||null,env:env,dirty:false};}
|
||||
function createAttribute(node,env,id){if(typeof node==='string'){return node;}
|
||||
return{id:id,value:node.$v||(node!==undefined?node:null),index:node.$x||null,env:env,dirty:false};}
|
||||
function format(args,entity){if(typeof entity==='string'){return[{},entity];}
|
||||
if(entity.dirty){throw new L10nError('Cyclic reference detected: '+entity.id);}
|
||||
entity.dirty=true;var rv;try{rv=resolveValue({},args,entity.env,entity.value,entity.index);}finally{entity.dirty=false;}
|
||||
return rv;}
|
||||
function resolveIdentifier(args,env,id){if(KNOWN_MACROS.indexOf(id)>-1){return[{},env['__'+id]];}
|
||||
if(args&&args.hasOwnProperty(id)){if(typeof args[id]==='string'||(typeof args[id]==='number'&&!isNaN(args[id]))){return[{},args[id]];}else{throw new L10nError('Arg must be a string or a number: '+id);}}
|
||||
if(id in env&&id!=='__proto__'){return format(args,env[id]);}
|
||||
throw new L10nError('Unknown reference: '+id);}
|
||||
function subPlaceable(locals,args,env,id){var res;try{res=resolveIdentifier(args,env,id);}catch(err){return[{error:err},'{{ '+id+' }}'];}
|
||||
var value=res[1];if(typeof value==='number'){return res;}
|
||||
if(typeof value==='string'){if(value.length>=MAX_PLACEABLE_LENGTH){throw new L10nError('Too many characters in placeable ('+
|
||||
value.length+', max allowed is '+
|
||||
MAX_PLACEABLE_LENGTH+')');}
|
||||
if(locals.contextIsNonLatin1||value.match(nonLatin1)){res[1]=FSI+value+PDI;}
|
||||
return res;}
|
||||
return[{},'{{ '+id+' }}'];}
|
||||
function interpolate(locals,args,env,arr){return arr.reduce(function(prev,cur){if(typeof cur==='string'){return[prev[0],prev[1]+cur];}else if(cur.t==='idOrVar'){var placeable=subPlaceable(locals,args,env,cur.v);return[prev[0],prev[1]+placeable[1]];}},[locals,'']);}
|
||||
function resolveSelector(args,env,expr,index){var selectorName=index[0].v;var selector=resolveIdentifier(args,env,selectorName)[1];if(typeof selector!=='function'){return selector;}
|
||||
var argValue=index[1]?resolveIdentifier(args,env,index[1])[1]:undefined;if(selector===env.__plural){if(argValue===0&&'zero'in expr){return'zero';}
|
||||
if(argValue===1&&'one'in expr){return'one';}
|
||||
if(argValue===2&&'two'in expr){return'two';}}
|
||||
return selector(argValue);}
|
||||
function resolveValue(locals,args,env,expr,index){if(!expr){return[locals,expr];}
|
||||
if(typeof expr==='string'||typeof expr==='boolean'||typeof expr==='number'){return[locals,expr];}
|
||||
if(Array.isArray(expr)){locals.contextIsNonLatin1=expr.some(function($_){return typeof($_)==='string'&&$_.match(nonLatin1);});return interpolate(locals,args,env,expr);}
|
||||
if(index){var selector=resolveSelector(args,env,expr,index);if(expr.hasOwnProperty(selector)){return resolveValue(locals,args,env,expr[selector]);}}
|
||||
if('other'in expr){return resolveValue(locals,args,env,expr.other);}
|
||||
throw new L10nError('Unresolvable value');}
|
||||
var Resolver={createEntry:createEntry,format:format,rePlaceables:rePlaceables};function walkContent(node,fn){if(typeof node==='string'){return fn(node);}
|
||||
if(node.t==='idOrVar'){return node;}
|
||||
var rv=Array.isArray(node)?[]:{};var keys=Object.keys(node);for(var i=0,key;(key=keys[i]);i++){if(key==='$i'||key==='$x'){rv[key]=node[key];}else{rv[key]=walkContent(node[key],fn);}}
|
||||
return rv;}
|
||||
var reAlphas=/[a-zA-Z]/g;var reVowels=/[aeiouAEIOU]/g;var ACCENTED_MAP='\u0226\u0181\u0187\u1E12\u1E16\u0191\u0193\u0126\u012A'+'\u0134\u0136\u013F\u1E3E\u0220\u01FE\u01A4\u024A\u0158'+'\u015E\u0166\u016C\u1E7C\u1E86\u1E8A\u1E8E\u1E90'+'[\\]^_`'+'\u0227\u0180\u0188\u1E13\u1E17\u0192\u0260\u0127\u012B'+'\u0135\u0137\u0140\u1E3F\u019E\u01FF\u01A5\u024B\u0159'+'\u015F\u0167\u016D\u1E7D\u1E87\u1E8B\u1E8F\u1E91';var FLIPPED_MAP='\u2200\u0510\u2183p\u018E\u025F\u05E4HI\u017F'+'\u04FC\u02E5WNO\u0500\xD2\u1D1AS\u22A5\u2229\u0245'+'\uFF2DX\u028EZ'+'[\\]\u1D65_,'+'\u0250q\u0254p\u01DD\u025F\u0183\u0265\u0131\u027E'+'\u029E\u0285\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez';function makeLonger(val){return val.replace(reVowels,function(match){return match+match.toLowerCase();});}
|
||||
function replaceChars(map,val){return val.replace(reAlphas,function(match){return map.charAt(match.charCodeAt(0)-65);});}
|
||||
var reWords=/[^\W0-9_]+/g;function makeRTL(val){return val.replace(reWords,function(match){return'\u202e'+match+'\u202c';});}
|
||||
var reExcluded=/(%[EO]?\w|\{\s*.+?\s*\}|&[#\w]+;|<\s*.+?\s*>)/;function mapContent(fn,val){if(!val){return val;}
|
||||
var parts=val.split(reExcluded);var modified=parts.map(function(part){if(reExcluded.test(part)){return part;}
|
||||
return fn(part);});return modified.join('');}
|
||||
function Pseudo(id,name,charMap,modFn){this.id=id;this.translate=mapContent.bind(null,function(val){return replaceChars(charMap,modFn(val));});this.name=this.translate(name);}
|
||||
var PSEUDO={'fr-x-psaccent':new Pseudo('fr-x-psaccent','Runtime Accented',ACCENTED_MAP,makeLonger),'ar-x-psbidi':new Pseudo('ar-x-psbidi','Runtime Bidi',FLIPPED_MAP,makeRTL)};function Locale(id,ctx){this.id=id;this.ctx=ctx;this.isReady=false;this.entries=Object.create(null);this.entries.__plural=getPluralRule(this.isPseudo()?this.ctx.defaultLocale:id);}
|
||||
Locale.prototype.isPseudo=function(){return this.ctx.qps.indexOf(this.id)!==-1;};var bindingsIO={extra:function(id,ver,path,type,callback,errback){if(type==='properties'){type='text';}
|
||||
navigator.mozApps.getLocalizationResource(id,ver,path,type).then(callback.bind(null,null),errback);},app:function(id,ver,path,type,callback,errback,sync){switch(type){case'properties':io.load(path,callback,sync);break;case'json':io.loadJSON(path,callback,sync);break;}},};Locale.prototype.build=function L_build(callback){var sync=!callback;var ctx=this.ctx;var self=this;var l10nLoads=ctx.resLinks.length;function onL10nLoaded(err){if(err){ctx._emitter.emit('fetcherror',err);}
|
||||
if(--l10nLoads<=0){self.isReady=true;if(callback){callback();}}}
|
||||
if(l10nLoads===0){onL10nLoaded();return;}
|
||||
function onJSONLoaded(err,json){if(!err&&json){self.addAST(json);}
|
||||
onL10nLoaded(err);}
|
||||
function onPropLoaded(err,source){if(!err&&source){var ast=PropertiesParser.parse(ctx,source);self.addAST(ast);}
|
||||
onL10nLoaded(err);}
|
||||
var idToFetch=this.isPseudo()?ctx.defaultLocale:this.id;var appVersion=null;var source='app';if(typeof(navigator)!=='undefined'){source=navigator.mozL10n._config.localeSources[this.id]||'app';appVersion=navigator.mozL10n._config.appVersion;}
|
||||
for(var i=0;i<ctx.resLinks.length;i++){var resLink=decodeURI(ctx.resLinks[i]);var path=resLink.replace('{locale}',idToFetch);var type=path.substr(path.lastIndexOf('.')+1);var cb;switch(type){case'json':cb=onJSONLoaded;break;case'properties':cb=onPropLoaded;break;}
|
||||
bindingsIO[source](this.id,appVersion,path,type,cb,onL10nLoaded,sync);}};function createPseudoEntry(node,entries){return Resolver.createEntry(walkContent(node,PSEUDO[this.id].translate),entries);}
|
||||
Locale.prototype.addAST=function(ast){var createEntry=this.isPseudo()?createPseudoEntry.bind(this):Resolver.createEntry;for(var i=0;i<ast.length;i++){this.entries[ast[i].$i]=createEntry(ast[i],this.entries);}};function Context(id){this.id=id;this.isReady=false;this.isLoading=false;this.defaultLocale='en-US';this.availableLocales=[];this.supportedLocales=[];this.qps=[];this.resLinks=[];this.locales={};this._emitter=new EventEmitter();this._ready=new Promise(this.once.bind(this));}
|
||||
function reportMissing(id,err){this._emitter.emit('notfounderror',err);return id;}
|
||||
function getWithFallback(id){var cur=0;var loc;var locale;while(loc=this.supportedLocales[cur]){locale=this.getLocale(loc);if(!locale.isReady){locale.build(null);}
|
||||
var entry=locale.entries[id];if(entry===undefined){cur++;reportMissing.call(this,id,new L10nError('"'+id+'"'+' not found in '+loc+' in '+this.id,id,loc));continue;}
|
||||
return entry;}
|
||||
throw new L10nError('"'+id+'"'+' missing from all supported locales in '+this.id,id);}
|
||||
function formatTuple(args,entity){try{return Resolver.format(args,entity);}catch(err){this._emitter.emit('resolveerror',err);var locals={error:err};return[locals,entity.id];}}
|
||||
function formatValue(args,entity){if(typeof entity==='string'){return entity;}
|
||||
return formatTuple.call(this,args,entity)[1];}
|
||||
function formatEntity(args,entity){var entityTuple=formatTuple.call(this,args,entity);var value=entityTuple[1];var formatted={value:value,attrs:null,};if(entity.attrs){formatted.attrs=Object.create(null);}
|
||||
for(var key in entity.attrs){var attrTuple=formatTuple.call(this,args,entity.attrs[key]);formatted.attrs[key]=attrTuple[1];}
|
||||
return formatted;}
|
||||
function formatAsync(fn,id,args){return this._ready.then(getWithFallback.bind(this,id)).then(fn.bind(this,args),reportMissing.bind(this,id));}
|
||||
Context.prototype.formatValue=function(id,args){return formatAsync.call(this,formatValue,id,args);};Context.prototype.formatEntity=function(id,args){return formatAsync.call(this,formatEntity,id,args);};function legacyGet(fn,id,args){if(!this.isReady){throw new L10nError('Context not ready');}
|
||||
var entry;try{entry=getWithFallback.call(this,id);}catch(err){if(err.loc){throw err;}
|
||||
reportMissing.call(this,id,err);return'';}
|
||||
return fn.call(this,args,entry);}
|
||||
Context.prototype.get=function(id,args){return legacyGet.call(this,formatValue,id,args);};Context.prototype.getEntity=function(id,args){return legacyGet.call(this,formatEntity,id,args);};Context.prototype.getLocale=function getLocale(code){var locales=this.locales;if(locales[code]){return locales[code];}
|
||||
return locales[code]=new Locale(code,this);};function negotiate(available,requested,defaultLocale){var supportedLocale;for(var i=0;i<requested.length;i++){var locale=requested[i];if(available.indexOf(locale)!==-1){supportedLocale=locale;break;}}
|
||||
if(!supportedLocale||supportedLocale===defaultLocale){return[defaultLocale];}
|
||||
return[supportedLocale,defaultLocale];}
|
||||
function freeze(supported){var locale=this.getLocale(supported[0]);if(locale.isReady){setReady.call(this,supported);}else{locale.build(setReady.bind(this,supported));}}
|
||||
function setReady(supported){this.supportedLocales=supported;this.isReady=true;this._emitter.emit('ready');}
|
||||
Context.prototype.registerLocales=function(defLocale,available){if(defLocale){this.defaultLocale=defLocale;}
|
||||
this.availableLocales=[this.defaultLocale];this.qps=Object.keys(PSEUDO);if(available){for(var i=0,loc;loc=available[i];i++){if(this.availableLocales.indexOf(loc)===-1){this.availableLocales.push(loc);var pos=this.qps.indexOf(loc);if(pos!==-1){this.qps.splice(pos,1);}}}}};Context.prototype.requestLocales=function requestLocales(){if(this.isLoading&&!this.isReady){throw new L10nError('Context not ready');}
|
||||
this.isLoading=true;var requested=Array.prototype.slice.call(arguments);if(requested.length===0){throw new L10nError('No locales requested');}
|
||||
var supported=negotiate(this.availableLocales.concat(this.qps),requested,this.defaultLocale);if(this.supportedLocales[0]!==supported[0]){freeze.call(this,supported);}};Context.prototype.addEventListener=function(type,listener){this._emitter.addEventListener(type,listener);};Context.prototype.removeEventListener=function(type,listener){this._emitter.removeEventListener(type,listener);};Context.prototype.ready=function(callback){if(this.isReady){setTimeout(callback);}
|
||||
this.addEventListener('ready',callback);};Context.prototype.once=function(callback){if(this.isReady){setTimeout(callback);return;}
|
||||
var callAndRemove=(function(){this.removeEventListener('ready',callAndRemove);callback();}).bind(this);this.addEventListener('ready',callAndRemove);};var allowed={elements:['a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','sup','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr'],attributes:{global:['title','aria-label','aria-valuetext','aria-moz-hint'],a:['download'],area:['download','alt'],input:['alt','placeholder'],menuitem:['label'],menu:['label'],optgroup:['label'],option:['label'],track:['label'],img:['alt'],textarea:['placeholder'],th:['abbr']}};var rtlList=['ar','he','fa','ps','ar-x-psbidi','ur'];var nodeObserver=null;var pendingElements=null;var moConfig={attributes:true,characterData:false,childList:true,subtree:true,attributeFilter:['data-l10n-id','data-l10n-args']};navigator.mozL10n={ctx:null,get:function get(id,ctxdata){return navigator.mozL10n.ctx.get(id,ctxdata);},formatValue:function(id,ctxdata){return navigator.mozL10n.ctx.formatValue(id,ctxdata);},formatEntity:function(id,ctxdata){return navigator.mozL10n.ctx.formatEntity(id,ctxdata);},translateFragment:function(fragment){return translateFragment.call(navigator.mozL10n,fragment);},setAttributes:setL10nAttributes,getAttributes:getL10nAttributes,ready:function ready(callback){return navigator.mozL10n.ctx.ready(callback);},once:function once(callback){return navigator.mozL10n.ctx.once(callback);},get readyState(){return navigator.mozL10n.ctx.isReady?'complete':'loading';},language:{set code(lang){navigator.mozL10n.ctx.requestLocales(lang);},get code(){return navigator.mozL10n.ctx.supportedLocales[0];},get direction(){return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);}},qps:PSEUDO,_config:{appVersion:null,localeSources:Object.create(null),isPretranslated:false,},_getInternalAPI:function(){return{Error:L10nError,Context:Context,Locale:Locale,Resolver:Resolver,getPluralRule:getPluralRule,rePlaceables:rePlaceables,translateDocument:translateDocument,onMetaInjected:onMetaInjected,PropertiesParser:PropertiesParser,walkContent:walkContent,buildLocaleList:buildLocaleList};}};function getDirection(lang){return(rtlList.indexOf(lang)>=0)?'rtl':'ltr';}
|
||||
var readyStates={loading:0,interactive:1,complete:2};function whenInteractive(callback){if(readyStates[document.readyState]>=readyStates.interactive){callback();return;}
|
||||
document.addEventListener('readystatechange',function l10n_onrsc(){if(readyStates[document.readyState]>=readyStates.interactive){document.removeEventListener('readystatechange',l10n_onrsc);callback();}});}
|
||||
function initObserver(){nodeObserver=new MutationObserver(onMutations.bind(navigator.mozL10n));nodeObserver.observe(document,moConfig);}
|
||||
function init(pretranslate){if(!pretranslate){initObserver();}
|
||||
initResources.call(navigator.mozL10n);}
|
||||
function initResources(){var meta={};var nodes=document.head.querySelectorAll('link[rel="localization"],'+'meta[name="availableLanguages"],'+'meta[name="defaultLanguage"],'+'meta[name="appVersion"],'+'script[type="application/l10n"]');for(var i=0,node;node=nodes[i];i++){var type=node.getAttribute('rel')||node.nodeName.toLowerCase();switch(type){case'localization':this.ctx.resLinks.push(node.getAttribute('href'));break;case'meta':onMetaInjected.call(this,node,meta);break;case'script':onScriptInjected.call(this,node);break;}}
|
||||
var additionalLanguagesPromise;if(navigator.mozApps&&navigator.mozApps.getAdditionalLanguages){additionalLanguagesPromise=navigator.mozApps.getAdditionalLanguages().catch(function(e){console.error('Error while loading getAdditionalLanguages',e);});document.addEventListener('additionallanguageschange',function(evt){registerLocales.call(this,meta,evt.detail);this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}else{additionalLanguagesPromise=Promise.resolve();}
|
||||
additionalLanguagesPromise.then(function(extraLangs){registerLocales.call(this,meta,extraLangs);initLocale.call(this);}.bind(this));}
|
||||
function registerLocales(meta,extraLangs){var locales=buildLocaleList.call(this,meta,extraLangs);navigator.mozL10n._config.localeSources=locales[1];this.ctx.registerLocales(locales[0],Object.keys(locales[1]));}
|
||||
function getMatchingLangpack(appVersion,langpacks){for(var i=0,langpack;(langpack=langpacks[i]);i++){if(langpack.target===appVersion){return langpack;}}
|
||||
return null;}
|
||||
function buildLocaleList(meta,extraLangs){var loc,lp;var localeSources=Object.create(null);var defaultLocale=meta.defaultLanguage||this.ctx.defaultLocale;if(meta.availableLanguages){for(loc in meta.availableLanguages){localeSources[loc]='app';}}
|
||||
if(extraLangs){for(loc in extraLangs){lp=getMatchingLangpack(this._config.appVersion,extraLangs[loc]);if(!lp){continue;}
|
||||
if(!(loc in localeSources)||!meta.availableLanguages[loc]||parseInt(lp.revision)>meta.availableLanguages[loc]){localeSources[loc]='extra';}}}
|
||||
if(!(defaultLocale in localeSources)){localeSources[defaultLocale]='app';}
|
||||
return[defaultLocale,localeSources];}
|
||||
function splitAvailableLanguagesString(str){var langs={};str.split(',').forEach(function(lang){lang=lang.trim().split(':');langs[lang[0]]=parseInt(lang[1]);});return langs;}
|
||||
function onMetaInjected(node,meta){switch(node.getAttribute('name')){case'availableLanguages':meta.availableLanguages=splitAvailableLanguagesString(node.getAttribute('content'));break;case'defaultLanguage':meta.defaultLanguage=node.getAttribute('content');break;case'appVersion':navigator.mozL10n._config.appVersion=node.getAttribute('content');break;}}
|
||||
function onScriptInjected(node){var lang=node.getAttribute('lang');var locale=this.ctx.getLocale(lang);locale.addAST(JSON.parse(node.textContent));}
|
||||
function initLocale(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);window.addEventListener('languagechange',function l10n_langchange(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}
|
||||
function localizeMutations(mutations){var mutation;var targets=new Set();for(var i=0;i<mutations.length;i++){mutation=mutations[i];if(mutation.type==='childList'){var addedNode;for(var j=0;j<mutation.addedNodes.length;j++){addedNode=mutation.addedNodes[j];if(addedNode.nodeType!==Node.ELEMENT_NODE){continue;}
|
||||
targets.add(addedNode);}}
|
||||
if(mutation.type==='attributes'){targets.add(mutation.target);}}
|
||||
targets.forEach(function(target){if(target.childElementCount){translateFragment.call(this,target);}else if(target.hasAttribute('data-l10n-id')){translateElement.call(this,target);}},this);}
|
||||
function onMutations(mutations,self){self.disconnect();localizeMutations.call(this,mutations);self.observe(document,moConfig);}
|
||||
function onReady(){if(!navigator.mozL10n._config.isPretranslated){translateDocument.call(this);}
|
||||
navigator.mozL10n._config.isPretranslated=false;if(pendingElements){for(var i=0,element;element=pendingElements[i];i++){translateElement.call(this,element);}
|
||||
pendingElements=null;}
|
||||
if(!nodeObserver){initObserver();}
|
||||
fireLocalizedEvent.call(this);}
|
||||
function fireLocalizedEvent(){var event=new CustomEvent('localized',{'bubbles':false,'cancelable':false,'detail':{'language':this.ctx.supportedLocales[0]}});window.dispatchEvent(event);}
|
||||
var reOverlay=/<|&#?\w+;/;var reHtml=/[&<>]/g;var htmlEntities={'&':'&','<':'<','>':'>',};function translateDocument(){document.documentElement.lang=this.language.code;document.documentElement.dir=this.language.direction;translateFragment.call(this,document.documentElement);}
|
||||
function translateFragment(element){if(typeof element.hasAttribute==='function'&&element.hasAttribute('data-l10n-id')){translateElement.call(this,element);}
|
||||
var nodes=getTranslatableChildren(element);for(var i=0;i<nodes.length;i++){translateElement.call(this,nodes[i]);}}
|
||||
function setL10nAttributes(element,id,args){element.setAttribute('data-l10n-id',id);if(args){element.setAttribute('data-l10n-args',JSON.stringify(args));}}
|
||||
function getL10nAttributes(element){return{id:element.getAttribute('data-l10n-id'),args:JSON.parse(element.getAttribute('data-l10n-args'))};}
|
||||
function getTranslatableChildren(element){return element?element.querySelectorAll('*[data-l10n-id]'):[];}
|
||||
function camelCaseToDashed(string){if(string==='ariaValueText'){return'aria-valuetext';}
|
||||
return string.replace(/[A-Z]/g,function(match){return'-'+match.toLowerCase();}).replace(/^-/,'');}
|
||||
function escapeL10nArgs(match){return htmlEntities[match];}
|
||||
function translateElement(element){if(!this.ctx.isReady){if(!pendingElements){pendingElements=[];}
|
||||
pendingElements.push(element);return;}
|
||||
var l10nId=element.getAttribute('data-l10n-id');if(!l10nId){return false;}
|
||||
var l10nArgs=element.getAttribute('data-l10n-args');var entity=this.ctx.getEntity(l10nId,l10nArgs?JSON.parse(l10nArgs.replace(reHtml,escapeL10nArgs)):undefined);var value=entity.value;if(typeof value==='string'){if(!reOverlay.test(value)){element.textContent=value;}else{var translation=element.ownerDocument.createElement('template');translation.innerHTML=value;overlayElement(element,translation.content);}}
|
||||
for(var key in entity.attrs){var attrName=camelCaseToDashed(key);if(isAttrAllowed({name:attrName},element)){element.setAttribute(attrName,entity.attrs[key]);}}}
|
||||
function overlayElement(sourceElement,translationElement){var result=translationElement.ownerDocument.createDocumentFragment();var k,attr;var childElement;while((childElement=translationElement.childNodes[0])){translationElement.removeChild(childElement);if(childElement.nodeType===Node.TEXT_NODE){result.appendChild(childElement);continue;}
|
||||
var index=getIndexOfType(childElement);var sourceChild=getNthElementOfType(sourceElement,childElement,index);if(sourceChild){overlayElement(sourceChild,childElement);result.appendChild(sourceChild);continue;}
|
||||
if(isElementAllowed(childElement)){var sanitizedChild=childElement.ownerDocument.createElement(childElement.nodeName);overlayElement(sanitizedChild,childElement);result.appendChild(sanitizedChild);continue;}
|
||||
result.appendChild(document.createTextNode(childElement.textContent));}
|
||||
sourceElement.textContent='';sourceElement.appendChild(result);if(translationElement.attributes){for(k=0,attr;(attr=translationElement.attributes[k]);k++){if(isAttrAllowed(attr,sourceElement)){sourceElement.setAttribute(attr.name,attr.value);}}}}
|
||||
function isElementAllowed(element){return allowed.elements.indexOf(element.tagName.toLowerCase())!==-1;}
|
||||
function isAttrAllowed(attr,element){var attrName=attr.name.toLowerCase();var tagName=element.tagName.toLowerCase();if(allowed.attributes.global.indexOf(attrName)!==-1){return true;}
|
||||
if(!allowed.attributes[tagName]){return false;}
|
||||
if(allowed.attributes[tagName].indexOf(attrName)!==-1){return true;}
|
||||
if(tagName==='input'&&attrName==='value'){var type=element.type.toLowerCase();if(type==='submit'||type==='button'||type==='reset'){return true;}}
|
||||
return false;}
|
||||
function getNthElementOfType(context,element,index){var nthOfType=0;for(var i=0,child;child=context.children[i];i++){if(child.nodeType===Node.ELEMENT_NODE&&child.tagName===element.tagName){if(nthOfType===index){return child;}
|
||||
nthOfType++;}}
|
||||
return null;}
|
||||
function getIndexOfType(element){var index=0;var child;while((child=element.previousElementSibling)){if(child.tagName===element.tagName){index++;}}
|
||||
return index;}
|
||||
var DEBUG=false;navigator.mozL10n.ctx=new Context(window.document?document.URL:null);navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));navigator.mozL10n.ctx.addEventListener('notfounderror',function reportMissingEntity(e){if(DEBUG||e.loc==='en-US'){console.warn(e.toString());}});if(DEBUG){navigator.mozL10n.ctx.addEventListener('fetcherror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('parseerror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('resolveerror',console.error.bind(console));}
|
||||
if(window.document){navigator.mozL10n._config.isPretranslated=document.documentElement.lang===navigator.language;var forcePretranslate=!navigator.mozL10n._config.isPretranslated;whenInteractive(init.bind(navigator.mozL10n,forcePretranslate));}
|
||||
document.l10n={setAttributes:navigator.mozL10n.setAttributes,getAttributes:navigator.mozL10n.getAttributes,formatValue:function(id,args){return navigator.mozL10n.formatValue(id,args);},translateFragment:function(frag){return Promise.resolve(navigator.mozL10n.translateFragment(frag));},ready:new Promise(function(resolve){navigator.mozL10n.once(resolve);}),formatValues:function(){var keys=arguments;var resp=keys.map(function(key){if(Array.isArray(key)){return navigator.mozL10n.formatValue(key[0],key[1]);}
|
||||
return navigator.mozL10n.formatValue(key);});return Promise.all(resp);},requestLanguages:function(langs){navigator.mozL10n.ctx.requestLocales.apply(navigator.mozL10n.ctx,langs);},pseudo:{'fr-x-psaccent':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].translate(s));}},'ar-x-psbidi':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].translate(s));}}},};navigator.mozL10n.ready(function(){document.documentElement.setAttribute('langs',navigator.mozL10n.ctx.supportedLocales.join(' '));});navigator.mozL10n.once(function(){window.addEventListener('localized',function(){document.dispatchEvent(new CustomEvent('DOMRetranslated',{bubbles:false,cancelable:false}));});});})(this);;'use strict';(function(exports){var appMgr=navigator.mozApps.mgmt;var apps=null;window.performance.mark('homescreenStart@system.gaiamobile.org');appMgr.getAll().onsuccess=function onsuccess(event){apps=event.target.result;window.dispatchEvent(new CustomEvent('navigator-mozapps-ready'));};function ApplicationSource(store){this.store=store;this.entries=[];this.entriesByManifestUrl={};this.svPreviouslyInstalledApps=[];var pendingInstallRequests=[];function addSVEventListener(){window.addEventListener('singlevariant-ready',function svFileReady(ev){window.removeEventListener('singlevariant-ready',svFileReady);for(var i=0;i<pendingInstallRequests;i++){pendingInstallRequests[i]();}});}
|
||||
addSVEventListener();var self=this;function addIcons(){window.removeEventListener('navigator-mozapps-ready',addIcons);for(var i=0,iLen=apps.length;i<iLen;i++){self.makeIcons(apps[i]);}
|
||||
apps=null;}
|
||||
apps?addIcons():window.addEventListener('navigator-mozapps-ready',addIcons);function install(application){var manifest=application.manifest||application.updateManifest;if(manifest.role&&app.HIDDEN_ROLES.indexOf(manifest.role)!==-1){return;}
|
||||
this.addIconToGrid(application);var svApp=configurator.getSingleVariantApp(application.manifestURL);var lastElem=app.grid.getIndexLastIcon();if(configurator.isSimPresentOnFirstBoot&&svApp&&svApp.location<lastElem&&!this.isPreviouslyInstalled(application.manifestURL)){app.grid.popDivider();app.grid.removeNonVisualElements();lastElem=app.grid.getIndexLastIcon();app.grid.moveTo(lastElem,svApp.location);_moveAhead(svApp.location+1);this.addPreviouslyInstalledSvApp(application.manifestURL);app.itemStore.savePrevInstalledSvApp(this.svPreviouslyInstalledApps);}
|
||||
app.grid.render();app.itemStore.deferredSave(app.grid.getItems());}
|
||||
function _moveAhead(startPos){var elems=app.grid.getItems();for(var i=startPos,iLen=elems.length;i<iLen;i++){var item=elems[i];if(item instanceof GaiaGrid.Mozapp){var svApp=configurator.getSingleVariantApp(elems[i].identifier);if(svApp&&i>svApp.location){app.grid.moveTo(i,i-1);}}}}
|
||||
appMgr.oninstall=function oninstall(event){if(configurator.isSingleVariantReady){install.bind(this)(event.application);}else{pendingInstallRequests.push(install.bind(this,event.application));}}.bind(this);appMgr.onuninstall=function onuninstall(event){var application=event.application;var manifest=application.updateManifest||application.manifest;this.removeIconFromGrid(application.manifestURL);app.itemStore.deferredSave(app.grid.getItems());if(app.HIDDEN_ROLES.indexOf(manifest.role)!==-1){return;}}.bind(this);}
|
||||
ApplicationSource.prototype={synchronize:function(){var storeItems=this.store._allItems;var toAdd=[];var appIconsByManifestUrl={};for(var i=0,iLen=storeItems.length;i<iLen;i++){var item=storeItems[i];if(!(item instanceof GaiaGrid.Mozapp)){continue;}
|
||||
appIconsByManifestUrl[item.detail.manifestURL]=item;}
|
||||
for(i=0,iLen=this.entries.length;i<iLen;i++){var entry=this.entries[i];var manifest=entry.app.updateManifest||entry.app.manifest;if(!appIconsByManifestUrl[entry.detail.manifestURL]&&!manifest.entry_points){toAdd.push(entry);}else{delete appIconsByManifestUrl[entry.detail.manifestURL];}}
|
||||
for(i in appIconsByManifestUrl){this.removeIconFromGrid(i);}
|
||||
toAdd.forEach(function _toAdd(newApp){this.addIconToGrid(newApp.app);},this);app.itemStore.deferredSave(app.grid.getItems());},addIconToGrid:function(application){this.makeIcons(application);var appObject=this.mapToApp({manifestURL:application.manifestURL});app.grid.appendItemToExpandedGroup(appObject);app.grid.render();},removeIconFromGrid:function(manifestURL){var icons=app.grid.getIcons();var appObject=icons[manifestURL];if(appObject){appObject.removeFromGrid();}},populate:function(success){success(this.entries);},makeIcons:function(eachApp){var manifest=eachApp.manifest||eachApp.updateManifest;if(app.HIDDEN_ROLES.indexOf(manifest.role)!==-1){return;}
|
||||
function eachIcon(icon){if(!icon.icon){return;}
|
||||
icon.setPosition(this.store.getNextPosition());this.entries.push(icon);}
|
||||
this.entriesByManifestUrl[eachApp.manifestURL]=eachApp;if(manifest.entry_points){for(var i in manifest.entry_points){eachIcon.call(this,new GaiaGrid.Mozapp(eachApp,i));}}else{eachIcon.call(this,new GaiaGrid.Mozapp(eachApp));}},mapToApp:function(entry){var app=this.entriesByManifestUrl[entry.manifestURL];app=app||{manifestURL:entry.manifestURL,manifest:{name:'',icons:[]}};return new GaiaGrid.Mozapp(app,entry.entryPoint,{decoratedIconBlob:entry.decoratedIconBlob});},addPreviouslyInstalledSvApp:function(manifest){this.svPreviouslyInstalledApps.push({manifestURL:manifest});},isPreviouslyInstalled:function(manifest){for(var i=0,elemNum=this.svPreviouslyInstalledApps.length;i<elemNum;i++){if(this.svPreviouslyInstalledApps[i].manifestURL===manifest){return true;}}
|
||||
return false;}};exports.ApplicationSource=ApplicationSource;}(window));;'use strict';(function(exports){function AppManager(){var grid=document.querySelector('gaia-grid');var self=this;navigator.mozApps.getSelf().onsuccess=function(evt){self.app=evt.target.result;window.dispatchEvent(new CustomEvent('appmanager-ready'));};grid.addEventListener('removeitem',this);}
|
||||
AppManager.prototype={dialogVisible:false,get self(){return this.app;},handleItemRemoval:function(item){function errorLogger(err){console.error('Error while trying to remove',item.name,err);}
|
||||
switch(item.detail.type){case'bookmark':BookmarksDatabase.remove(item.identifier).catch(errorLogger);break;default:console.error('Cannot handle remove for item type ',item.detail.type);}},handleEvent:function(e){var nameObj={name:e.detail&&e.detail.name};switch(e.type){case'removeitem':if(this.dialogVisible){return;}
|
||||
this.dialogVisible=true;if(e.detail.detail.type=='app'){var request=navigator.mozApps.mgmt.uninstall(e.detail.app);request.onsuccess=()=>{e.detail.removeFromGrid();this.dialogVisible=false;};request.onerror=()=>{console.error('Error while trying to remove',e.detail.name,request.error);this.dialogVisible=false;};break;}
|
||||
var dialog=new ConfirmDialogHelper({type:'remove',title:{id:'delete-title',args:nameObj},body:{id:'delete-body',args:nameObj},cancel:{title:'cancel',cb:()=>{this.dialogVisible=false;}},confirm:{title:'delete',type:'danger',cb:()=>{e.detail.removeFromGrid();this.handleItemRemoval(e.detail);this.dialogVisible=false;}}});dialog.show(document.body);break;}}};exports.appManager=new AppManager();}(window));;'use strict';(function(exports){const APPEARANCE={OPAQUE:'opaque',SEMI_TRANSPARENT:'semi-transparent'};function StatusBar(){this.threshold=document.getElementById('search').clientHeight;if(!appManager.app){window.addEventListener('appmanager-ready',function onReady(){window.removeEventListener('appmanager-ready',onReady);this.onAppReady();}.bind(this));}else{this.onAppReady();}}
|
||||
StatusBar.prototype={handleEvent:function(e){switch(e.type){case'editmode-start':window.removeEventListener('context-menu-open',this);window.removeEventListener('context-menu-close',this);window.removeEventListener('gaia-confirm-open',this);window.removeEventListener('gaia-confirm-close',this);case'context-menu-open':case'gaia-confirm-open':window.removeEventListener('scroll',this);this.setAppearance(APPEARANCE.OPAQUE);break;case'editmode-end':window.addEventListener('context-menu-open',this);window.addEventListener('context-menu-close',this);window.addEventListener('gaia-confirm-open',this);window.addEventListener('gaia-confirm-close',this);case'context-menu-close':case'gaia-confirm-close':window.addEventListener('scroll',this);case'scroll':this.setAppearance(this.calculateAppearance());break;case'visibilitychange':if(document.hidden){break;}
|
||||
this.appearance=null;this.setAppearance(this.calculateAppearance());break;}},onAppReady:function(){var grid=app.grid;window.addEventListener('scroll',this);grid.addEventListener('editmode-start',this);grid.addEventListener('editmode-end',this);window.addEventListener('context-menu-close',this);window.addEventListener('context-menu-open',this);window.addEventListener('gaia-confirm-open',this);window.addEventListener('gaia-confirm-close',this);window.addEventListener('visibilitychange',this);this.setAppearance(APPEARANCE.SEMI_TRANSPARENT);},calculateAppearance:function(){return window.scrollY>this.threshold?APPEARANCE.OPAQUE:APPEARANCE.SEMI_TRANSPARENT;},setAppearance:function(value){if(this.appearance===value){return;}
|
||||
this.appearance=value;var meta=document.head.querySelector('meta[name="theme-color"]');if(value==APPEARANCE.OPAQUE){meta.content='black';}else{meta.content='transparent';}}};exports.statusBar=new StatusBar();}(window));;'use strict';(function(exports){var datastore;var DATASTORE_NAME='vertical_preferences_store';var readyState;var listeners=Object.create(null);function init(){return new Promise(function doInit(resolve,reject){if(readyState==='initialized'){resolve();return;}
|
||||
if(readyState==='initializing'){document.addEventListener('vps-initialized',function oninitalized(){document.removeEventListener('vps-initialized',oninitalized);resolve();});return;}
|
||||
readyState='initializing';if(!navigator.getDataStores){console.error('Preferences store: DataStore API is not working');reject({name:'NO_DATASTORE'});readyState='failed';return;}
|
||||
navigator.getDataStores(DATASTORE_NAME).then(function(ds){if(ds.length<1){console.error('Preferences store: Cannot get access to the Store');reject({name:'NO_ACCESS_TO_DATASTORE'});readyState='failed';return;}
|
||||
datastore=ds[0];datastore.addEventListener('change',onchangeHandler);readyState='initialized';document.dispatchEvent(new CustomEvent('vps-initialized'));resolve();},reject);});}
|
||||
function onchangeHandler(event){var operation=event.operation;var callbacks=listeners[operation];callbacks&&callbacks.forEach(function iterCallback(callback){datastore.get(event.id).then(function got(result){callback.method.call(callback.context||this,{type:operation,target:{name:event.id,value:result}});});});}
|
||||
function addEventListener(type,callback){var context;if(!(type in listeners)){listeners[type]=[];}
|
||||
var cb=callback;if(typeof cb==='object'){context=cb;cb=cb.handleEvent;}
|
||||
if(cb){listeners[type].push({method:cb,context:context});init();}}
|
||||
function removeEventListener(type,callback){if(!(type in listeners)){return false;}
|
||||
var callbacks=listeners[type];var length=callbacks.length;for(var i=0;i<length;i++){var thisCallback=callback;if(typeof thisCallback==='object'){thisCallback=callback.handleEvent;}
|
||||
if(callbacks[i]&&callbacks[i].method===thisCallback){callbacks.splice(i,1);return true;}}
|
||||
return false;}
|
||||
function get(id){return new Promise(function doGet(resolve,reject){init().then(function onInitialized(){datastore.get(id).then(resolve,reject);},reject);});}
|
||||
function put(id,value){return new Promise(function doAdd(resolve,reject){init().then(function onInitialized(){datastore.put(value,id).then(function success(){resolve();},reject);},reject);});}
|
||||
exports.verticalPreferences={get:get,put:put,addEventListener:addEventListener,removeEventListener:removeEventListener};}(window));;'use strict';(function(exports){var datastore;var DATASTORE_NAME='bookmarks_store';var readyState;var listeners=Object.create(null);function init(){return new Promise(function doInit(resolve,reject){if(readyState==='initialized'){resolve();return;}
|
||||
if(readyState==='initializing'){document.addEventListener('ds-initialized',function oninitalized(){document.removeEventListener('ds-initialized',oninitalized);resolve();});return;}
|
||||
readyState='initializing';if(!navigator.getDataStores){console.error('Bookmark store: DataStore API is not working');reject({name:'NO_DATASTORE'});readyState='failed';return;}
|
||||
navigator.getDataStores(DATASTORE_NAME).then(function(ds){if(ds.length<1){console.error('Bookmark store: Cannot get access to the Store');reject({name:'NO_ACCESS_TO_DATASTORE'});readyState='failed';return;}
|
||||
datastore=ds[0];datastore.addEventListener('change',onchangeHandler);readyState='initialized';document.dispatchEvent(new CustomEvent('ds-initialized'));resolve();},reject);});}
|
||||
function doGetAll(resolve,reject){var result=Object.create(null);var cursor=datastore.sync();function cursorResolve(task){switch(task.operation){case'update':case'add':result[task.data.id]=task.data;break;case'remove':delete result[task.data.id];break;case'clear':result=Object.create(null);break;case'done':resolve(result);return;}
|
||||
cursor.next().then(cursorResolve,reject);}
|
||||
cursor.next().then(cursorResolve,reject);}
|
||||
function get(id){return new Promise(function doGet(resolve,reject){init().then(function onInitialized(){datastore.get(id).then(resolve,reject);},reject);});}
|
||||
function getAll(){return new Promise(function doGet(resolve,reject){init().then(doGetAll.bind(null,resolve,reject),reject);});}
|
||||
function onchangeHandler(event){var operation=event.operation;var callbacks=listeners[operation];callbacks&&callbacks.forEach(function iterCallback(callback){datastore.get(event.id).then(function got(result){callback.method.call(callback.context||this,{type:operation,target:result||event});});});}
|
||||
function addEventListener(type,callback){var context;if(!(type in listeners)){listeners[type]=[];}
|
||||
var cb=callback;if(typeof cb==='object'){context=cb;cb=cb.handleEvent;}
|
||||
if(cb){listeners[type].push({method:cb,context:context});init();}}
|
||||
function removeEventListener(type,callback){if(!(type in listeners)){return false;}
|
||||
var callbacks=listeners[type];var length=callbacks.length;for(var i=0;i<length;i++){var thisCallback=callback;if(typeof thisCallback==='object'){thisCallback=callback.handleEvent;}
|
||||
if(callbacks[i]&&callbacks[i].method===thisCallback){callbacks.splice(i,1);return true;}}
|
||||
return false;}
|
||||
function add(data){return new Promise(function doAdd(resolve,reject){init().then(function onInitialized(){var id=data.url;Object.defineProperty(data,'id',{enumerable:true,configurable:false,writable:false,value:id});datastore.add(data,id).then(function add_success(){resolve(true);},function add_error(){datastore.put(data,id).then(function put_success(){resolve();},reject);});},reject);});}
|
||||
function getRevisionId(){return new Promise(function doGet(resolve,reject){init().then(function onInitialized(){resolve(datastore.revisionId);},reject);});}
|
||||
function put(data){return new Promise(function doAdd(resolve,reject){init().then(function onInitialized(){datastore.put(data,data.id).then(function success(){resolve();},reject);},reject);});}
|
||||
function remove(id){return new Promise(function doRemove(resolve,reject){init().then(function onInitialized(){datastore.remove(id).then(resolve,reject);},reject);});}
|
||||
function clear(){return new Promise(function doClear(resolve,reject){init().then(function onInitialized(){datastore.clear().then(resolve,reject);},reject);});}
|
||||
exports.BookmarksDatabase={get:get,getAll:getAll,getRevisionId:getRevisionId,addEventListener:addEventListener,removeEventListener:removeEventListener,add:add,put:put,remove:remove,clear:clear};}(window));;'use strict';var LazyLoader=(function(){function LazyLoader(){this._loaded={};this._isLoading={};}
|
||||
LazyLoader.prototype={_js:function(file,callback){var script=document.createElement('script');script.src=file;script.async=false;script.addEventListener('load',callback);document.head.appendChild(script);this._isLoading[file]=script;},_css:function(file,callback){var style=document.createElement('link');style.type='text/css';style.rel='stylesheet';style.href=file;document.head.appendChild(style);callback();},_html:function(domNode,callback){if(domNode.getAttribute('is')){this.load(['/shared/js/html_imports.js'],function(){HtmlImports.populate(callback);}.bind(this));return;}
|
||||
for(var i=0;i<domNode.childNodes.length;i++){if(domNode.childNodes[i].nodeType==document.COMMENT_NODE){domNode.innerHTML=domNode.childNodes[i].nodeValue;break;}}
|
||||
window.dispatchEvent(new CustomEvent('lazyload',{detail:domNode}));callback();},getJSON:function(file,mozSystem){return new Promise(function(resolve,reject){var xhr;if(mozSystem){xhr=new XMLHttpRequest({mozSystem:true});}else{xhr=new XMLHttpRequest();}
|
||||
xhr.open('GET',file,true);xhr.responseType='json';xhr.onerror=function(error){reject(error);};xhr.onload=function(){if(xhr.response!==null){resolve(xhr.response);}else{reject(new Error('No valid JSON object was found ('+
|
||||
xhr.status+' '+xhr.statusText+')'));}};xhr.send();});},load:function(files,callback){var deferred={};deferred.promise=new Promise(resolve=>{deferred.resolve=resolve;});if(!Array.isArray(files)){files=[files];}
|
||||
var loadsRemaining=files.length,self=this;function perFileCallback(file){if(self._isLoading[file]){delete self._isLoading[file];}
|
||||
self._loaded[file]=true;if(--loadsRemaining===0){deferred.resolve();if(callback){callback();}}}
|
||||
for(var i=0;i<files.length;i++){var file=files[i];if(this._loaded[file.id||file]){perFileCallback(file);}else if(this._isLoading[file]){this._isLoading[file].addEventListener('load',perFileCallback.bind(null,file));}else{var method,idx;if(typeof file==='string'){method=file.match(/\.([^.]+)$/)[1];idx=file;}else{method='html';idx=file.id;}
|
||||
this['_'+method](file,perFileCallback.bind(null,idx));}}
|
||||
return deferred.promise;}};return new LazyLoader();}());;'use strict';var rscheme=/^(?:[a-z\u00a1-\uffff0-9-+]+)(?::(?:\/\/)?)/i;var UrlHelper={a:null,getUrlFromInput:function urlHelper_getUrlFromInput(input){this.a=this.a||document.createElement('a');this.a.href=input;return this.a.href;},_getScheme:function(input){return(rscheme.exec(input)||[])[0];},hasScheme:function(input){return!!this._getScheme(input);},isURL:function urlHelper_isURL(input){return!UrlHelper.isNotURL(input);},isNotURL:function urlHelper_isNotURL(input){var case1Reg=/^(\?)|(\?.+\s)/;var case2Reg=/[\?\.\s\:]/;var case3Reg=/^(data|view-source)\:/;var str=input.trim();if(case1Reg.test(str)||!case2Reg.test(str)||this._getScheme(str)===str){return true;}
|
||||
if(case3Reg.test(str)){return false;}
|
||||
if(!this.hasScheme(str)){str='http://'+str;}
|
||||
if(!this.urlValidate){this.urlValidate=document.createElement('input');this.urlValidate.setAttribute('type','url');}
|
||||
this.urlValidate.setAttribute('value',str);return!this.urlValidate.validity.valid;},resolveUrl:function urlHelper_resolveURL(url,baseUrl){if(!url){return null;}
|
||||
try{return new URL(url,baseUrl).href;}catch(e){return null;}},getHostname:function urlHelper_getHostname(url){try{return new URL(url).hostname;}catch(e){return null;}}};;'use strict';(function WebManifestHelper(exports){var getManifest=function(url){return new Promise(function(resolve,reject){var xhr=new XMLHttpRequest({mozSystem:true});xhr.open('get',url,true);xhr.responseType='json';xhr.setRequestHeader('Accept','application/manifest+json');xhr.onload=function(){var status=xhr.status;var webManifest;if(status==200){if(!xhr.response){reject(new Error('Empty JSON response to '+url+', '+'possibly syntax error'));}
|
||||
webManifest=processRawManifest(xhr.response||{},url);resolve(webManifest);}else{reject(status);}};xhr.onerror=function(e){console.error('Unable to get web manifest');reject(e.target.status);};xhr.send();});};var processRawManifest=function(webManifest,manifestURL){if(!manifestURL){throw new Error('WebManifestHelper.processRawManifest:'+' no manifestURL given');}
|
||||
if('icons'in webManifest){webManifest.icons=processIcons(webManifest,manifestURL||'');}
|
||||
return webManifest;};const onlyDecimals=/^\d+$/,anyRegEx=new RegExp('any','i');var processIcons=function(manifest,baseURL){const obj={objectName:'manifest',object:manifest,property:'icons',expectedType:'array'},icons=[];var value=extractValue(obj);if(Array.isArray(value)){var processableIcons=value.filter(icon=>icon&&Object.prototype.hasOwnProperty.call(icon,'src')&&icon.src!=='');for(var potentialIcon of processableIcons){var src=processSrcMember(potentialIcon,baseURL);if(src!==undefined){var icon={src:src,type:processTypeMember(potentialIcon),sizes:processSizesMember(potentialIcon),density:processDensityMember(potentialIcon)};icons.push(icon);}}}
|
||||
return icons;function processTypeMember(icon){const obj={objectName:'icon',object:icon,property:'type',expectedType:'string'};var value=extractValue(obj),isParsable=(typeof value==='string'&&value.length>0);return(value===''||!isParsable)?undefined:value;}
|
||||
function processDensityMember(icon){const hasDensity=Object.prototype.hasOwnProperty.call(icon,'density'),rawValue=(hasDensity)?icon.density:undefined,value=parseFloat(rawValue),result=(Number.isNaN(value)||value===+Infinity||value<=0)?1.0:value;return result;}
|
||||
function processSrcMember(icon,baseURL){const obj={objectName:'icon',object:icon,property:'src',expectedType:'string'},value=extractValue(obj);var url;if(typeof value==='string'&&value.trim()!==''){try{url=new URL(value,baseURL).href;}catch(e){}}
|
||||
return url;}
|
||||
function processSizesMember(icon){const sizes=[],obj={objectName:'icon',object:icon,property:'sizes',expectedType:'string'};var value=extractValue(obj);value=(value)?value.trim():value;if(value){var validSizes=value.split(/\s+/).filter(isValidSizeValue);validSizes.forEach((size)=>sizes.push(size));}
|
||||
return sizes;function isValidSizeValue(size){if(anyRegEx.test(size)){return true;}
|
||||
size=size.toLowerCase();if(!size.contains('x')||size.indexOf('x')!==size.lastIndexOf('x')){return false;}
|
||||
const width=size.substring(0,size.indexOf('x'));const height=size.substring(size.indexOf('x')+1,size.length);const isValid=!(height.startsWith('0')||width.startsWith('0')||!onlyDecimals.test(width+height));return isValid;}}};function extractValue(obj){var value=obj.object[obj.property];const type=(Array.isArray(value))?'array':typeof value;if(type!==obj.expectedType){if(type!=='undefined'){var msg='Expected the '+obj.objectName+'s '+obj.property+' member to be a '+obj.expectedType;console.warn(msg);}
|
||||
value=undefined;}
|
||||
return value;}
|
||||
exports.WebManifestHelper={getManifest:getManifest,processRawManifest:processRawManifest};})(window);;'use strict';(function IconsHelper(exports){const ICON_CACHE_PERIOD=24*60*60*1000;const FETCH_XHR_TIMEOUT=10000;const DEBUG=false;var dataStore=null;function getDefaultIconSize(){var dpr=window.devicePixelRatio;return(dpr&&dpr>1)?142:84;}
|
||||
function sizeIsNearer(size1,size2,targetSize){var delta1=Math.abs(targetSize-size1);var delta2=Math.abs(targetSize-size2);return(delta1<=delta2);}
|
||||
function getIcon(uri,iconTargetSize,placeObj={},siteObj={}){var iconUrl=null;iconTargetSize=iconTargetSize*window.devicePixelRatio;if(siteObj.webManifestUrl&&siteObj.webManifest){iconUrl=getBestIconFromWebManifest(siteObj.webManifest,iconTargetSize);if(DEBUG&&iconUrl){console.log('Icon from Web Manifest');}}
|
||||
if(!iconUrl&&siteObj.manifest&&siteObj.manifest.icons){iconUrl=getBestIconFromWebManifest({icons:_convertToWebManifestIcons(siteObj.manifest,siteObj.origin||siteObj.manifest.origin)},iconTargetSize);if(DEBUG&&iconUrl){console.log('Icon from Firefox App Manifest');}}
|
||||
if(!iconUrl&&placeObj&&placeObj.icons){iconUrl=getBestIconFromMetaTags(placeObj.icons,iconTargetSize);if(DEBUG&&iconUrl){console.log('Icon from Meta tags');}}
|
||||
if(!iconUrl){var a=document.createElement('a');a.href=uri;iconUrl=a.origin+'/favicon.ico';if(iconTargetSize){iconUrl+='#-moz-resolution='+iconTargetSize+','+iconTargetSize;}
|
||||
DEBUG&&console.log('Icon from favicon.ico');}
|
||||
return new Promise(resolve=>{resolve(iconUrl);});}
|
||||
function getIconBlob(uri,iconTargetSize,placeObj={},siteObj={}){return new Promise((resolve,reject)=>{getIcon(uri,iconTargetSize,placeObj,siteObj).then(iconUrl=>{getStore().then(iconStore=>{iconStore.get(iconUrl).then(iconObj=>{if(!iconObj||!iconObj.timestamp||Date.now()-iconObj.timestamp>=ICON_CACHE_PERIOD){return fetchIconBlob(iconUrl).then(iconBlob=>{var img=document.createElement('img');var icon=new Icon(img,uri);icon.renderBlob(iconBlob,{size:iconTargetSize,onLoad:function(blob){var iconObj={blob:blob,originalUrl:iconUrl.toString(),timestamp:Date.now()};resolve(iconObj);iconStore.add(iconObj,iconUrl);},onerror:function(e){reject(`Failed to fetch icon ${iconUrl}`);}});}).catch(err=>{reject(`Failed to fetch icon ${iconUrl}: ${err}`);});}
|
||||
return resolve(iconObj);}).catch(err=>{reject(`Failed to get icon from dataStore: ${err}`);});}).catch(err=>{reject(`Error opening the dataStore: ${err}`);});});});}
|
||||
function setElementIcon(icon,targetSize){return getIconBlob(icon.bookmark.url,targetSize,icon.bookmark,icon.bookmark).then(iconObj=>{if(iconObj.blob){icon.icon=iconObj.blob;return Promise.resolve();}else if(icon.bookmark.icon){return fetchIconBlob(icon.bookmark.icon).then(iconBlob=>{icon.icon=iconBlob;return Promise.resolve();},Promise.reject.bind(Promise));}
|
||||
return Promise.reject('No icon data found');},Promise.reject.bind(Promise));}
|
||||
function getBestIconFromWebManifest(webManifest,iconSize){var icons=webManifest.icons;if(!icons){return null;}
|
||||
var maxSize=10000;var bestSize=maxSize;var iconURL=null;iconSize=iconSize||getDefaultIconSize();icons.forEach((potentialIcon)=>{if(!iconURL){iconURL=potentialIcon.src;}
|
||||
var sizes=Array.from(potentialIcon.sizes);var nearestSize=getNearestSize(sizes,iconSize,bestSize);if(nearestSize!==bestSize&&sizeIsNearer(nearestSize,bestSize,iconSize)){iconURL=potentialIcon.src;bestSize=nearestSize;}});return iconURL?iconURL:null;}
|
||||
function _convertToWebManifestIcons(manifest,origin){return Object.keys(manifest.icons).map(function(size){var url=manifest.icons[size];var sizes=[size+'x'+size];url=url.indexOf('http')>-1?url:origin+url;return{src:new URL(url),sizes:sizes};});}
|
||||
function getBestIconFromMetaTags(icons,iconSize){if(!icons){return null;}
|
||||
iconSize=iconSize||getDefaultIconSize();var iconURL=null;var bestSize=10000;Object.keys(icons).forEach((uri)=>{var potentialIcon=icons[uri];if(!iconURL){iconURL=uri;}
|
||||
var sizes=Array.from(potentialIcon.sizes);var nearestSize=getNearestSize(sizes,iconSize,bestSize);if(nearestSize!==bestSize&&sizeIsNearer(nearestSize,bestSize,iconSize)){iconURL=uri;bestSize=nearestSize;}
|
||||
if(potentialIcon.rel==='apple-touch-icon'||potentialIcon.rel==='apple-touch-icon-precomposed'){var moreInfoUrl='https://developer.mozilla.org/en-US/'+'Apps/Build/Icon_implementation_for_apps#General_icons_for_web_apps';console.warn('Warning: The apple-touch icons are being used '+'as a fallback only. They will be deprecated in '+'the future. See '+moreInfoUrl);}});return iconURL||null;}
|
||||
function getNearestSize(sizes,iconSize,bestSize){var bogusSize=10000;if(!bestSize){bestSize=bogusSize;}
|
||||
var nearestSize=sizes.reduce(function(nearestSize,sizeString,idx){var size=widthFromSizeString(sizeString);if(isNaN(size)){return nearestSize;}
|
||||
if(sizeIsNearer(size,nearestSize,iconSize)){return size;}else{return nearestSize;}},bestSize);return nearestSize===bogusSize?-1:nearestSize;}
|
||||
function widthFromSizeString(size){size=size||'';var xIndex=size.indexOf('x');if(!xIndex){return NaN;}
|
||||
return parseInt(size.substr(0,xIndex));}
|
||||
function getStore(){return new Promise(resolve=>{if(dataStore){return resolve(dataStore);}
|
||||
navigator.getDataStores('icons').then(stores=>{dataStore=stores[0];return resolve(dataStore);});});}
|
||||
function clear(){return getStore().then(iconStore=>{iconStore.clear();});}
|
||||
function fetchIcon(iconUrl){return new Promise((resolve,reject)=>{fetchIconBlob(iconUrl).then((iconBlob)=>{var img=document.createElement('img');img.src=URL.createObjectURL(iconBlob);img.onload=()=>{var iconSize=Math.max(img.naturalWidth,img.naturalHeight);resolve({blob:iconBlob,url:iconUrl,size:iconSize,timestamp:Date.now()});};img.onerror=()=>{reject(new Error(`Error while loading image.`));};}).catch((e)=>{reject(new Error(`Error while loading image: ${e}`));});});}
|
||||
function fetchIconBlob(iconUrl){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest({mozAnon:true,mozSystem:true});xhr.open('GET',iconUrl,true);xhr.responseType='blob';xhr.timeout=FETCH_XHR_TIMEOUT;xhr.send();xhr.onload=()=>{if(xhr.readyState===XMLHttpRequest.DONE&&xhr.status===200){var iconBlob=xhr.response;resolve(iconBlob);return;}
|
||||
reject(new Error(`Got HTTP status ${xhr.status} trying to load ${iconUrl}.`));};xhr.onerror=xhr.ontimeout=()=>{reject(new Error(`Error while getting ${iconUrl}.`));};});}
|
||||
exports.IconsHelper={getIcon:getIcon,getIconBlob:getIconBlob,setElementIcon:setElementIcon,getBestIconFromWebManifest:getBestIconFromWebManifest,getBestIconFromMetaTags:getBestIconFromMetaTags,fetchIcon:fetchIcon,fetchIconBlob:fetchIconBlob,get defaultIconSize(){return getDefaultIconSize();},clear:clear,getNearestSize:getNearestSize,};})(window);;'use strict';(function(exports){var eventTypesToListenFor=['added','updated','removed'];function BookmarkSource(store){this.store=store;this.entries=[];eventTypesToListenFor.forEach(function iterateTypes(type){BookmarksDatabase.addEventListener(type,this);},this);}
|
||||
BookmarkSource.prototype={synchronize:function(){var allAppBookmarks={};var toAdd=[];var icons=app.grid.getIcons();for(var i in icons){var icon=icons[i];if(icon.detail.type!=='bookmark'){continue;}
|
||||
allAppBookmarks[icon.detail.url]=icon;}
|
||||
for(var j=0,jLen=this.entries.length;j<jLen;j++){var entry=this.entries[j];if(!allAppBookmarks[entry.detail.url]){toAdd.push(entry);}else{delete allAppBookmarks[entry.detail.url];}}
|
||||
for(i in allAppBookmarks){this.removeIconFromGrid(allAppBookmarks[i].detail.url);}
|
||||
for(i=0;i<toAdd.length;i++){this.addIconToGrid(toAdd[i].detail);}
|
||||
app.itemStore.deferredSave(app.grid.getItems());},populate:function(success){var self=this;BookmarksDatabase.getAll().then(function(systemBookmarks){Object.keys(systemBookmarks).forEach(function(id){self.entries.push(new GaiaGrid.Bookmark(systemBookmarks[id]));});success(self.entries);},success);},handleEvent:function(e){switch(e.type){case'added':case'updated':this.addIconToGrid(e.target);app.itemStore.deferredSave(app.grid.getItems());break;case'removed':var id=e.target.id;this.removeIconFromGrid(id);break;}},addIconToGrid:function(detail){var icons=app.grid.getIcons();var existing=icons[detail.id];if(existing){existing.update(detail);app.grid.render();return;}
|
||||
var bookmark=new GaiaGrid.Bookmark(detail);bookmark.setPosition(this.store.getNextPosition());this.entries.push(bookmark);app.grid.appendItemToExpandedGroup(bookmark);app.grid.render();},removeIconFromGrid:function(url){var icons=app.grid.getIcons();var appObject=icons[url];if(appObject){appObject.removeFromGrid();}}};exports.BookmarkSource=BookmarkSource;}(window));;'use strict';(function(exports){const DB_VERSION=1;const DB_NAME='verticalhome';const DB_ITEM_STORE='items';const DB_SV_APP_STORE_NAME='svAppsInstalled';const DATASTORE_NAME='verticalhome_items_migration';const PREFS_STORE='vertical_preferences_store';var db;var datastore;function sort(entries,order){if(!order||!order.length){return entries;}
|
||||
var newEntries=[];function isEqual(lookFor,compareWith){if(!compareWith.detail||!lookFor){return false;}
|
||||
if(compareWith instanceof GaiaGrid.Mozapp){if(!lookFor.manifestURL||!compareWith.detail.manifestURL){return false;}
|
||||
if(compareWith.detail.entryPoint){return lookFor.manifestURL===compareWith.detail.manifestURL&&lookFor.entry_point===compareWith.detail.entryPoint;}else{return lookFor.manifestURL===compareWith.detail.manifestURL;}}else if(compareWith instanceof GaiaGrid.Bookmark){if(!lookFor.id||!compareWith.detail.id){return false;}
|
||||
return lookFor.id===compareWith.detail.id;}}
|
||||
for(var i=0,iLen=order.length;i<iLen;i++){for(var j=0,jLen=order[i].length;j<jLen;j++){var ind=entries.findIndex(isEqual.bind(null,order[i][j]));if(ind>=0){newEntries.push(entries.splice(ind,1)[0]);}}
|
||||
if(i<iLen-1){newEntries.push(new GaiaGrid.Divider());}}
|
||||
if(entries.length>0){if(configurator.isSimPresentOnFirstBoot){sortUnclassifiedApps(newEntries,entries);}else{newEntries.push(new GaiaGrid.Divider());newEntries=newEntries.concat(entries);}}
|
||||
for(i=0,iLen=newEntries.length;i<iLen;i++){if(newEntries[i].detail){newEntries[i].detail.index=i;}}
|
||||
return newEntries;}
|
||||
function sortUnclassifiedApps(dstEntries,orgEntries){function compareApps(appA,appB){var svAppA=null;var svAppB=null;if(appA){svAppA=configurator.getSingleVariantApp(appA.detail.manifestURL);}
|
||||
if(appB){svAppB=configurator.getSingleVariantApp(appB.detail.manifestURL);}
|
||||
var locA=svAppA&&svAppA.location!==undefined&&svAppA.location||Number.MAX_VALUE;var locB=svAppB&&svAppB.location!==undefined&&svAppB.location||Number.MAX_VALUE;var relPos=locA-locB;return relPos?(relPos>0?1:-1):0;}
|
||||
orgEntries.sort(compareApps);if(!configurator.getSingleVariantApp(orgEntries[0].detail.manifestURL)){dstEntries.push(new GaiaGrid.Divider());dstEntries=dstEntries.concat(orgEntries);}else{var sepAdded=false;for(var i=0,iLen=orgEntries.length;i<iLen;i++){var app=orgEntries[i];var svApp=configurator.getSingleVariantApp(app.detail.manifestURL);if(!svApp){if(!sepAdded){dstEntries.push(new GaiaGrid.Divider());sepAdded=true;}
|
||||
dstEntries.push(app);}else{if(svApp.location!==undefined){dstEntries.splice(svApp.location,0,app);}else{dstEntries.push(app);}}}}}
|
||||
function loadTable(table,indexName,iterator,aNext){newTxn(table,'readonly',function(txn,store){var index=store.index(indexName);index.openCursor().onsuccess=function onsuccess(event){var cursor=event.target.result;if(!cursor){return;}
|
||||
iterator(cursor.value);cursor.continue();};},aNext);}
|
||||
function newTxn(storeName,txnType,withTxnAndStore,successCb){var txn=db.transaction([storeName],txnType);var store=txn.objectStore(storeName);txn.oncomplete=function(event){if(successCb){successCb(event);}};txn.onerror=function(event){console.warn('Error during transaction.');};withTxnAndStore(txn,store);}
|
||||
function ItemStore(onsuccess){var self=this;this.applicationSource=new ApplicationSource(this);this.bookmarkSource=new BookmarkSource(this);this.sources=[this.applicationSource,this.bookmarkSource];this.ready=false;var isEmpty=false;self.gridOrder=null;var request=window.indexedDB.open(DB_NAME,DB_VERSION);request.onupgradeneeded=function _onupgradeneeded(event){var db=event.target.result;var oldVersion=event.oldVersion||0;switch(oldVersion){case 0:var objectStore=db.createObjectStore(DB_ITEM_STORE,{keyPath:'index'});objectStore.createIndex('index','index',{unique:true});isEmpty=true;var objectSV=db.createObjectStore(DB_SV_APP_STORE_NAME,{keyPath:'manifestURL'});objectSV.createIndex('indexSV','indexSV',{unique:true});}};request.onsuccess=function _onsuccess(){onsuccess&&onsuccess(isEmpty);db=request.result;var cb=self.fetch.bind(self,self.synchronize.bind(self));if(isEmpty){window.addEventListener('configuration-ready',function onReady(){window.removeEventListener('configuration-ready',onReady);self.gridOrder=configurator.getGrid();self.populate(cb);});}else{self.initSources(cb);}
|
||||
navigator.mozSetMessageHandler('connection',self.handleIAC.bind(self));};window.addEventListener('gaiagrid-cached-icons-rendered',this);}
|
||||
ItemStore.prototype={_renderedOnce:false,_deferredSaveArgs:[],_allItems:[],nextPosition:0,all:function(success){if(!this.ready){window.addEventListener('databaseready',this.all.bind(this,success));return;}
|
||||
success(this._allItems);},saveTable:function(table,objArr,column,checkPersist,aNext){newTxn(table,'readwrite',function(txn,store){store.clear();for(var i=0,iLen=objArr.length;i<iLen;i++){if(!checkPersist||(checkPersist&&objArr[i].persistToDB)){store.put(column?objArr[i][column]:objArr[i]);}}
|
||||
if(typeof aNext==='function'){aNext();}});},saveMigrationData:function(objArr,column,checkPersist){return datastore.clear().then(()=>{var chain=[];objArr.forEach((object)=>{if(!checkPersist||object.persistToDB){var data=column?object[column]:object;chain.push(datastore.put(data,data.index+1));}});return Promise.all(chain);});},saveItem:function(object,callback){if(object.index==null){console.error('Attempting to save object without `index`');return;}
|
||||
newTxn(DB_ITEM_STORE,'readwrite',function(txn,store){store.put(object);},callback);},deferredSave:function(){var args=Array.slice(arguments);if(this._renderedOnce){return this.save.apply(this,args);}
|
||||
this._deferredSaveArgs=args;},save:function(entries,aNext){entries=sort(entries,this.gridOrder);this.gridOrder=null;this.saveTable(DB_ITEM_STORE,entries,'detail',true,aNext);},savePrevInstalledSvApp:function(svApps,aNext){this.saveTable(DB_SV_APP_STORE_NAME,svApps,null,false,aNext);},fetch:function(callback){var cached={};var collected=[];function iterator(value){collected.push(value);}
|
||||
function iteratorSV(value){this.applicationSource.addPreviouslyInstalledSvApp(value.manifestURL);}
|
||||
loadTable(DB_SV_APP_STORE_NAME,'indexSV',iteratorSV.bind(this));loadTable(DB_ITEM_STORE,'index',iterator,finish.bind(this));function addIfUnique(item){if(!cached[item.identifier]){cached[item.identifier]=true;this._allItems.push(item);}}
|
||||
function finish(){for(var i=0,iLen=collected.length;i<iLen;i++){var thisItem=collected[i];if(thisItem.type==='app'){var itemObj=this.applicationSource.mapToApp(thisItem);addIfUnique.call(this,itemObj);}else if(thisItem.type==='divider'){var divider=new GaiaGrid.Divider(thisItem);this._allItems.push(divider);}else if(thisItem.type==='bookmark'){var bookmark=new GaiaGrid.Bookmark(thisItem);addIfUnique.call(this,bookmark);}}
|
||||
this.notifyReady();if(callback&&typeof callback==='function'){callback();}}},synchronize:function(){this.sources.forEach(function eachSource(source){source.synchronize();});},initSources:function(callback){var pending=this.sources.length;var allEntries=[];var self=this;var current=0;function handleSource(){var source=self.sources[current];current++;source.populate(next);}
|
||||
handleSource();function next(entries){allEntries=allEntries.concat(entries);if(!(--pending)){callback(allEntries);}else{handleSource();}}},populate:function(callback){this.initSources(function(entries){this.deferredSave(entries,callback);}.bind(this));},notifyReady:function(){this.ready=true;dispatchEvent(new CustomEvent('databaseready'));},getNextPosition:function(){var nextPosition=this.nextPosition;this.nextPosition++;return nextPosition;},handleIAC:function(connectionRequest){if(connectionRequest.keyword!=='verticalhome-migrate'){return;}
|
||||
var port=connectionRequest.port;port.onmessage=(event)=>{if(event.data.action!=='migrate'){console.error('Unhandled migration action requested:',event.data.action);return;}
|
||||
this.migrate(event.data.manifestURL);};port.start();},migrate:function(manifestURL){this.migratingTo=manifestURL;console.info('verticalhome migrating to '+this.migratingTo);if(this.migrating){return;}
|
||||
this.migrating=true;(datastore?Promise.resolve():navigator.getDataStores(DATASTORE_NAME).then(stores=>{datastore=stores[0];return Promise.resolve();},(e)=>{return Promise.reject(e);})).then(()=>{this.all(entries=>{this.saveMigrationData(entries,'detail',true).then(()=>{this.migrating=false;window.navigator.mozSettings.createLock().set({'homescreen.manifestURL':this.migratingTo});navigator.getDataStores(PREFS_STORE).then(stores=>{if(stores.length<1){console.error('Error opening verticalhome prefs datastore');return;}
|
||||
stores[0].put('migrated',true).then(()=>{window.close();},e=>{console.error('Error storing migration pref',e);window.close();});});});});},e=>{console.error('Error retrieving datastore',e);});},handleEvent:function(e){switch(e.type){case'gaiagrid-cached-icons-rendered':this._renderedOnce=true;window.removeEventListener('gaiagrid-cached-icons-rendered',this);if(this._deferredSaveArgs.length){this.save.apply(this,this._deferredSaveArgs);}
|
||||
break;}}};exports.ItemStore=ItemStore;}(window));;'use strict';(function(exports){const maxIconsPerRow=4;const iconScaleFactorMaxIconsPerRow=5;const minIconsPerRow=3;const iconScaleFactorMinIconsPerRow=3.8;const distanceBetweenIconsWithMinIconsPerRow=36;const distanceBetweenIconsWithMaxIconsPerRow=38;const eachTextRowHeight=20;var constraintSize;function GridLayout(gridView){this.gridView=gridView;if(window.verticalPreferences){verticalPreferences.get('grid.cols').then(value=>{this.cols=value;this.onReady();},this.onReady);verticalPreferences.addEventListener('updated',this);}else{this.onReady();}}
|
||||
GridLayout.prototype={minIconsPerRow:minIconsPerRow,maxIconsPerRow:maxIconsPerRow,_cols:minIconsPerRow,_offsetY:0,_percent:1,_dividerLineHeight:0,get percent(){return this._percent;},get cols(){return this._cols;},set cols(value){if(!value||value===this._cols){return;}
|
||||
if(window.verticalPreferences){verticalPreferences.put('grid.cols',value);}
|
||||
this._offsetY=0;this._percent=value==minIconsPerRow?1:minIconsPerRow/maxIconsPerRow;this._cols=value;},get constraintSize(){if(!constraintSize){this.calculateSize();}
|
||||
return constraintSize;},get gridItemHeight(){var height=this.gridIconSize+
|
||||
(this._cols===minIconsPerRow?distanceBetweenIconsWithMinIconsPerRow:distanceBetweenIconsWithMaxIconsPerRow);var defaultTextRows=2;var definedRows=parseInt(this.gridView.element.getAttribute('text-rows'),10);if(definedRows>defaultTextRows){height+=(definedRows-defaultTextRows)*eachTextRowHeight;}
|
||||
return height;},get gridItemWidth(){return this.constraintSize/this._cols;},get gridMaxIconSize(){var baseSize=(this.constraintSize/iconScaleFactorMinIconsPerRow);return baseSize*devicePixelRatio;},get gridIconSize(){var numCols=this._cols;var size=this.constraintSize/numCols;if(numCols===minIconsPerRow){size=this.constraintSize/iconScaleFactorMinIconsPerRow;}else if(numCols===maxIconsPerRow){size=this.constraintSize/iconScaleFactorMaxIconsPerRow;}
|
||||
return Math.floor(size);},get offsetY(){return this._offsetY;},set offsetY(value){this._offsetY=value;},stepYAxis:function(value){this._offsetY+=value;},handleEvent:function(e){switch(e.type){case'updated':var prop=e.target;if(prop.name==='grid.cols'){this.cols=parseInt(prop.value,10);this.gridView.render();}
|
||||
break;}},calculateSize:function(){constraintSize=Math.min(window.screen.width,window.screen.height);},onReady:function(){window.dispatchEvent(new CustomEvent('gaiagrid-layout-ready'));}};exports.GridLayout=GridLayout;}(window));;'use strict';(function(exports){const SHADOW_BLUR=1;const SHADOW_OFFSET_Y=1;const SHADOW_OFFSET_X=1;const SHADOW_COLOR='rgba(0, 0, 0, 0.2)';const DEFAULT_BACKGROUND_COLOR='rgb(228, 234, 238)';const UNSCALED_CANVAS_PADDING=2;const CANVAS_PADDING=UNSCALED_CANVAS_PADDING*devicePixelRatio;function IconRenderer(icon){this._icon=icon;}
|
||||
IconRenderer.TYPE={CLIP:'clip',FAVICON:'favicon',STANDARD:'standard',};IconRenderer.prototype={unscaledCanvasPadding:UNSCALED_CANVAS_PADDING*2,get _maxSize(){return this._icon.grid.layout.gridMaxIconSize;},_createCanvas:function(){const CANVAS_PADDING_BOTTOM=1*devicePixelRatio;var canvas=document.createElement('canvas');canvas.width=this._maxSize+(CANVAS_PADDING*2);canvas.height=this._maxSize+CANVAS_PADDING+CANVAS_PADDING_BOTTOM;return canvas;},_createClipCanvas:function(){var canvas=document.createElement('canvas');canvas.width=this._maxSize+(CANVAS_PADDING*2);canvas.height=this._maxSize+(CANVAS_PADDING*2);return canvas;},_decorateShadowCanvas:function(canvas){var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.shadowColor=SHADOW_COLOR;ctx.shadowBlur=SHADOW_BLUR;ctx.shadowOffsetY=SHADOW_OFFSET_Y;ctx.shadowOffsetX=SHADOW_OFFSET_X;return ctx;},clip:function(img){return new Promise((resolve)=>{var shadowCanvas=this._createCanvas();var shadowCtx=this._decorateShadowCanvas(shadowCanvas);var clipCanvas=this._createClipCanvas();var clipCtx=clipCanvas.getContext('2d',{willReadFrequently:true});clipCtx.beginPath();clipCtx.arc(clipCanvas.width/2,clipCanvas.height/2,clipCanvas.height/2,0,2*Math.PI);clipCtx.clip();clipCtx.drawImage(img,0,0,clipCanvas.width,clipCanvas.height);shadowCtx.drawImage(clipCanvas,CANVAS_PADDING,CANVAS_PADDING,this._maxSize,this._maxSize);shadowCanvas.toBlob(resolve);});},favicon:function(img){if(img.width>this._icon.grid.layout.gridIconSize/2){return this.clip(img);}
|
||||
return new Promise((resolve)=>{var shadowCanvas=this._createCanvas();var shadowCtx=this._decorateShadowCanvas(shadowCanvas);var iconWidth;var iconHeight;shadowCtx.beginPath();shadowCtx.arc(shadowCanvas.width/2,shadowCanvas.height/2,shadowCanvas.height/2-CANVAS_PADDING,0,2*Math.PI,false);shadowCtx.fillStyle=DEFAULT_BACKGROUND_COLOR;shadowCtx.fill();iconWidth=iconHeight=this._maxSize*0.55;shadowCtx.shadowBlur=0;shadowCtx.shadowOffsetY=0;shadowCtx.mozImageSmoothingEnabled=false;shadowCtx.drawImage(img,(shadowCanvas.width-iconWidth)/2,(shadowCanvas.height-iconHeight)/2,iconWidth,iconHeight);shadowCanvas.toBlob(resolve);});},standard:function(img){return new Promise((resolve)=>{var shadowCanvas=this._createCanvas();var shadowCtx=this._decorateShadowCanvas(shadowCanvas);shadowCtx.drawImage(img,CANVAS_PADDING,CANVAS_PADDING,this._maxSize,this._maxSize);shadowCanvas.toBlob(resolve);});}};exports.GridIconRenderer=IconRenderer;}(window));;'use strict';(function(exports){const APP_LAUNCH_TIMEOUT=3000;function GridView(config){this.config=config;this.clickIcon=this.clickIcon.bind(this);this.onVisibilityChange=this.onVisibilityChange.bind(this);if(config.features.zoom){this.zoom=new GridZoom(this);}
|
||||
this.layout=new GridLayout(this);if(config.element.hasAttribute('cols')){this.layout.cols=parseInt(config.element.getAttribute('cols'),10);}
|
||||
this.start();}
|
||||
GridView.prototype={icons:{},items:[],get element(){return this.config.element;},set cols(value){this.layout.cols=value;},_launchingApp:false,add:function(item,insertTo,expandGroup){if(!item){return;}
|
||||
if(item.identifier){if(this.icons[item.identifier]){console.log('Error, duplicate identifier: ',item.identifier,new Error().stack);return;}
|
||||
this.icons[item.identifier]=item;}else if(item.detail.type!=='divider'&&item.detail.type!=='placeholder'){console.log('Error, could not load identifier for object: ',JSON.stringify(item.detail));return;}
|
||||
if(!isNaN(parseFloat(insertTo))&&isFinite(insertTo)){this.items.splice(insertTo,0,item);}else{insertTo=this.items.length;this.items.push(item);}
|
||||
if(expandGroup){for(var i=insertTo+1,iLen=this.items.length;i<iLen;i++){var divider=this.items[i];if(divider.detail.type==='divider'){if(divider.detail.collapsed){divider.expand();}
|
||||
break;}}}},getNearestItemIndex:function(x,y,isRow){var foundIndex=null;var leastDistance=null;var itemMiddleOffset=this.layout.gridItemWidth/2;for(var i=0,iLen=this.items.length;i<iLen;i++){var item=this.items[i];if(!item.isDraggable()){continue;}
|
||||
if(this.config.features.disableSections&&item.detail.type==='divider'){continue;}
|
||||
if(item.detail.type!=='divider'&&item.element.classList.contains('collapsed')){continue;}
|
||||
var middleX=item.x+itemMiddleOffset;var middleY=item.y+item.pixelHeight/2;var xDistance=(isRow||item.detail.type==='divider')?0:x-middleX;var yDistance=y-middleY;var distance=Math.sqrt(xDistance*xDistance+
|
||||
yDistance*yDistance);if(leastDistance===null||distance<leastDistance){leastDistance=distance;foundIndex=i;}}
|
||||
return foundIndex;},start:function(){this.element.addEventListener('click',this.clickIcon);window.addEventListener('visibilitychange',this.onVisibilityChange);},stop:function(){this.element.removeEventListener('click',this.clickIcon);window.removeEventListener('visibilitychange',this.onVisibilityChange);},findItemFromElement:function(element,excludeCollapsedIcons){while(element&&element.parentNode!==this.element){element=element.parentNode;}
|
||||
if(!element){return null;}
|
||||
var i,iLen=this.items.length;var identifier=element.dataset.identifier;var icon=this.icons[identifier];if(!icon){for(i=0;i<iLen;i++){if(this.items[i].element===element){icon=this.items[i];break;}}}
|
||||
if(icon&&excludeCollapsedIcons){if(icon.detail.type!=='divider'&&icon.detail.type!=='placeholder'&&icon.element.classList.contains('collapsed')){for(i=icon.detail.index+1;i<iLen;i++){if(this.items[i].detail.type==='divider'){return this.items[i];}}
|
||||
console.warn('Collapsed icon found with no group');icon=null;}}
|
||||
return icon;},onVisibilityChange:function(){this._launchingApp=false;},clickIcon:function(e){e.preventDefault();var inEditMode=this.dragdrop&&this.dragdrop.inEditMode;var action='launch';if(e.target.classList.contains('remove')){action='remove';}
|
||||
var icon=this.findItemFromElement(e.target);if(!icon){return;}
|
||||
if(action==='launch'){if(inEditMode&&e.target.classList.contains('icon')){if(!icon.isEditable()){return;}
|
||||
action='edit';}else{if(!icon[action]){return;}
|
||||
icon.element.classList.add('launching');var returnTimeout=500;setTimeout(function stateReturn(){if(icon.element){icon.element.classList.remove('launching');}},returnTimeout);}}
|
||||
if((icon.detail.type==='app'||icon.detail.type==='bookmark')&&this._launchingApp){return;}
|
||||
if((icon.detail.type==='app'&&icon.appState==='ready')||icon.detail.type==='bookmark'){this._launchingApp=true;if(this._launchingTimeout){window.clearTimeout(this._launchingTimeout);this._launchingTimeout=null;}
|
||||
this._launchingTimeout=window.setTimeout(function(){this._launchingTimeout=null;this._launchingApp=false;}.bind(this),APP_LAUNCH_TIMEOUT);}
|
||||
icon[action](e.target);},cleanItems:function(skipDivider){var appCount=0;var toRemove=[];this.items.forEach(function(item,idx){if(item instanceof GaiaGrid.Divider){if(appCount===0){toRemove.push(idx);}
|
||||
appCount=0;}else{appCount++;}},this);toRemove.reverse();toRemove.forEach(function(idx){var removed=this.items.splice(idx,1)[0];removed.remove();},this);if(skipDivider){return;}
|
||||
var lastItem=this.items[this.items.length-1];if(!lastItem||!(lastItem instanceof GaiaGrid.Divider)){this.items.push(new GaiaGrid.Divider());}},removeAllPlaceholders:function(){var toSplice=[];var previousItem;this.items.forEach(function(item,idx){if(item instanceof GaiaGrid.Placeholder){if((!previousItem||(previousItem&&previousItem instanceof GaiaGrid.Divider))&&this.dragdrop&&this.dragdrop.inDragAction){return;}
|
||||
toSplice.push(idx);}
|
||||
previousItem=item;},this);toSplice.reverse().forEach(function(idx){this.items.splice(idx,1)[0].remove();},this);},clear:function(){for(var i=0,iLen=this.items.length;i<iLen;i++){var item=this.items[i];if(item.element){this.element.removeChild(item.element);item.element=null;item.lastX=null;item.lastY=null;item.lastScale=null;}}
|
||||
this.items=[];this.icons={};},createPlaceholders:function(coordinates,idx,count){var isRTL=(document.documentElement.dir==='rtl');for(var i=0;i<count;i++){var item=new GaiaGrid.Placeholder();this.items.splice(idx+i,0,item);item.setPosition(idx+i);var xPosition=(coordinates[0]+i)*this.layout.gridItemWidth;if(isRTL){xPosition=(this.layout.constraintSize-this.layout.gridItemWidth)-
|
||||
xPosition;}
|
||||
item.setCoordinates(xPosition,this.layout.offsetY);item.render();}},render:function(options){var self=this;options=options||{};this.removeAllPlaceholders();this.cleanItems(options.skipDivider);var oldHeight=this.layout.offsetY;this.layout.offsetY=0;var x=0;var y=0;function step(item){var pixelHeight=item.pixelHeight;self.layout.stepYAxis(pixelHeight);x=0;y++;}
|
||||
var pendingCachedIcons=0;var onCachedIconRendered=()=>{if(--pendingCachedIcons<=0){this.element.removeEventListener('cached-icon-rendered',onCachedIconRendered);this.element.dispatchEvent(new CustomEvent('cached-icons-rendered'));}};this.element.addEventListener('cached-icon-rendered',onCachedIconRendered);var nextDivider=null;var oddDivider=true;var isRTL=(document.documentElement.dir==='rtl');for(var idx=0;idx<this.items.length;idx++){var item=this.items[idx];if(options.rerender&&item.element){this.element.removeChild(item.element);item.element=null;}
|
||||
if(item.detail.type==='divider'){nextDivider=null;}else{if(!nextDivider){for(var i=idx+1;i<this.items.length;i++){if(this.items[i].detail.type==='divider'){nextDivider=this.items[i];oddDivider=!oddDivider;break;}}
|
||||
if(nextDivider&&!nextDivider.detail.collapsed){this.layout.offsetY+=nextDivider.headerHeight;}}
|
||||
if(nextDivider&&nextDivider.detail.collapsed){item.setPosition(idx);continue;}}
|
||||
if(x>0&&item.gridWidth>1&&x+item.gridWidth>=this.layout.cols){var remaining=this.layout.cols-x;this.createPlaceholders([x,y],idx,remaining);idx+=remaining;item=this.items[idx];var lastItemInRow=this.items[idx-1];step(lastItemInRow);}
|
||||
item.setPosition(idx);if(!options.skipItems){item.hasCachedIcon&&++pendingCachedIcons;var xPosition=x*this.layout.gridItemWidth;if(isRTL){xPosition=(this.layout.constraintSize-this.layout.gridItemWidth)-
|
||||
xPosition;}
|
||||
item.setCoordinates(xPosition,this.layout.offsetY);if(!item.active){item.render();}
|
||||
if(item.detail.type==='divider'){if(oddDivider){item.element.classList.add('odd');}else{item.element.classList.remove('odd');}}}
|
||||
x+=item.gridWidth;if((x>=this.layout.cols)&&(idx<this.items.length-1)){step(item);}}
|
||||
if(this.layout.offsetY!=oldHeight){if(this.dragdrop&&this.dragdrop.inDragAction){this.layout.offsetY=oldHeight;}else{this.element.dispatchEvent(new CustomEvent('gaiagrid-resize',{detail:this.layout.offsetY}));}}
|
||||
this.element.setAttribute('cols',this.layout.cols);pendingCachedIcons===0&&onCachedIconRendered();this.loadDragDrop();},loadDragDrop:function(){if(!this.dragdrop&&this.config.features.dragdrop){LazyLoader.load('shared/elements/gaia_grid/js/grid_dragdrop.js',()=>{if(this.dragdrop){return;}
|
||||
this.dragdrop=new GridDragDrop(this);});}}};exports.GridView=GridView;}(window));;window.GaiaGrid=(function(win){'use strict';var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaGridBaseurl||'/shared/elements/gaia_grid/';proto.createdCallback=function(){var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._styleHack();this._grid=new GridView({element:this,features:{dragdrop:this.getAttribute('dragdrop')!==null,zoom:this.getAttribute('zoom')!==null,disableSections:this.getAttribute('disable-sections')!==null}});shadow.appendChild(this._template);};proto.add=function(){this._grid.add.apply(this._grid,arguments);};proto.clear=function(){this._grid.clear.apply(this._grid,arguments);};proto.render=function(){this._grid.layout.calculateSize();this._grid.render.apply(this._grid,arguments);};proto.start=function(){this._grid.start.apply(this._grid,arguments);};proto.stop=function(){this._grid.stop.apply(this._grid,arguments);};proto.getIcons=function(){return this._grid.icons;};proto.getItems=function(){return this._grid.items;};proto.getIcon=function(identifier){return this._grid.icons[identifier];};proto.removeIconByIdentifier=function(identifier){delete this._grid.icons[identifier];};proto.removeItemByIndex=function(itemIndex){this._grid.items.splice(itemIndex,1);};proto.popDivider=function(){var items=this._grid.items;if(items.length&&items[items.length-1].detail.type==='divider'){return items.pop();}
|
||||
return null;};proto.appendItem=function(item){var items=this._grid.items;var lastIndex=items.length-1;if(items[lastIndex].detail.type==='divider'){this.add(item,lastIndex);}else{this.add(item);}};proto.appendItemToExpandedGroup=function(item){var items=this._grid.items;var lastIndex=items.length-1;if(items[lastIndex].detail.type==='divider'&&items[lastIndex].detail.collapsed){items[lastIndex].expand();}
|
||||
this.appendItem(item);};proto.setEditHeaderElement=function(element){if(this._grid.dragdrop){this._grid.dragdrop.editHeaderElement=element;}};Object.defineProperty(proto,'maxIconSize',{get:function(){return this._grid.layout.gridMaxIconSize;}});proto.getIndexLastIcon=function(){var items=this._grid.items;for(var i=this._grid.items.length-1;i>=0;i--){if(items[i]instanceof GaiaGrid.Mozapp){return i;}}};proto.removeNonVisualElements=function(){var nonVisualElements=[GaiaGrid.Placeholder];function isNonVisual(elem){var retVal=false;for(var i=0,iLen=nonVisualElements.length;i<iLen&&!retVal;i++){retVal=elem instanceof nonVisualElements[i];}
|
||||
return retVal;}
|
||||
var i=0;var iLen=this._grid.items.length;while(i<iLen){this._grid.items[i].detail.index=i;if(isNonVisual(this._grid.items[i])){this._grid.items.splice(i,1);iLen-=1;}else{i+=1;}}};proto.moveTo=function(orig,dst){this._grid.items.splice(dst,0,this._grid.items.splice(orig,1)[0]);};proto._styleHack=function(){var style=this._template.querySelector('style');this.appendChild(style.cloneNode(true));};var stylesheet=baseurl+'style.css';var template=document.createElement('template');template.innerHTML=`<style scoped>
|
||||
@import url(${stylesheet});</style>
|
||||
<content></content>`;return document.registerElement('gaia-grid',{prototype:proto});})(window);;'use strict';(function(exports){const ICON_BLOB_DECORATED_EVENT='iconblobdecorated';const ICON_BLOB_ERROR_EVENT='gaiagrid-iconbloberror';const FETCH_XHR_TIMEOUT=10000;function fetchBlob(uri){return new Promise(function(accept,reject){var xhr=new XMLHttpRequest({mozAnon:true,mozSystem:true});xhr.open('GET',uri,true);xhr.responseType='blob';xhr.timeout=FETCH_XHR_TIMEOUT;xhr.send();xhr.onload=function(){var status=xhr.status;if(status!==0&&status!==200){reject(new Error('Got HTTP status '+status+' trying to load '+uri));return;}
|
||||
accept(xhr.response);};xhr.onerror=xhr.ontimeout=function(){reject(new Error('Error while HTTP GET: ',uri));};});}
|
||||
function GridItem(){this.detail={};}
|
||||
GridItem.prototype={x:0,y:0,pixelHeight:0,gridWidth:1,scale:1,persistToDB:true,lastX:null,lastY:null,lastScale:null,get hasCachedIcon(){return this.detail&&this.detail.decoratedIconBlob;},renderer:GridIconRenderer.TYPE.STANDARD,iconState:'none',get defaultIcon(){return'/shared/elements/gaia_grid/images/default_icon.png';},get grid(){return document.getElementsByTagName('gaia-grid')[0]._grid;},isRemovable:function(){return false;},isEditable:function(){return false;},isDraggable:function(){return true;},isIconFromOrigin:function(){return this.icon.startsWith('http')||this.icon.startsWith('app:');},setPosition:function(position){this.detail.index=position;},setCoordinates:function(x,y){this.x=x;this.y=y;},requestAttention:function(){var rect={x:this.x,y:this.y,width:this.gridWidth*this.grid.layout.gridItemWidth,height:this.pixelHeight};this.grid.element.dispatchEvent(new CustomEvent('gaiagrid-attention',{detail:rect}));},closestIconSizeFromList:function(choices){if(!choices){return 0;}
|
||||
var sizes=Object.keys(choices);if(!sizes.length){return 0;}
|
||||
var maxSize=this.grid.layout.gridMaxIconSize;var filter=(a)=>a>=maxSize?a:0;var bestSize=Math.min(...sizes.map(filter));bestSize=bestSize||Math.max(...sizes);return bestSize||0;},closestIconFromList:function(choices){var icon;if(Array.isArray(choices)){var manifest={'icons':choices};var maxSize=this.grid.layout.gridMaxIconSize;icon=window.IconsHelper.getBestIconFromWebManifest(manifest,maxSize);return icon?(new URL(icon,this.app.manifestURL)).href:null;}
|
||||
var accurateSize=this.closestIconSizeFromList(choices);if(accurateSize===0){return this.defaultIcon;}
|
||||
icon=choices[accurateSize];if(!UrlHelper.hasScheme(icon)){icon=this.app.origin+icon;}
|
||||
return icon;},renderIconFromSrc:function(url){var background=new Image();background.src=url;background.onload=this._decorateIcon.bind(this,background);},renderIconFromBlob:function(blob){var background=new Image();background.src=URL.createObjectURL(blob);background.onload=()=>{this._decorateIcon(background);URL.revokeObjectURL(background.src);};background.onerror=()=>{URL.revokeObjectURL(background.src);if(this.hasCachedIcon){this._stampElementWithIcon('blobcache');this._displayDecoratedIcon(this.detail.decoratedIconBlob,true);return;}
|
||||
this.renderIconFromSrc(this.defaultIcon);this._stampElementWithIcon(this.defaultIcon);};},_decorateIcon:function(img){var strategy=this.detail.renderer||this.renderer;this.rendererInstance=new GridIconRenderer(this);this.rendererInstance[strategy](img).then(this._displayDecoratedIcon.bind(this));},_displayDecoratedIcon:function(blob,isCachedIcon){if(!this.element){return;}
|
||||
var style=this.element.style;if(!style.backgroundSize){style.height=this.grid.layout.gridItemHeight+'px';var backgroundHeight=((this.grid.layout.gridIconSize*(1/this.grid.layout.percent))+
|
||||
GridIconRenderer.prototype.unscaledCanvasPadding);if(this.grid.layout.gridItemHeight>backgroundHeight){style.backgroundSize=backgroundHeight+'px';}else{style.backgroundSize=style.height;}}
|
||||
if(isCachedIcon){var url=URL.createObjectURL(blob);style.backgroundImage='url('+url+')';this.element.dataset.backgroundImage=url;var img=new Image();img.onload=img.onerror=()=>{this.grid.element.dispatchEvent(new CustomEvent('cached-icon-rendered'));};img.src=url;return;}
|
||||
this._compareBlobs(blob,this.detail.decoratedIconBlob).then((equal)=>{if(equal){return;}
|
||||
style.backgroundImage='url('+URL.createObjectURL(blob)+')';this.detail.decoratedIconBlob=blob;this.grid.element.dispatchEvent(new CustomEvent(ICON_BLOB_DECORATED_EVENT,{detail:this}));var bgImg=this.element.dataset.backgroundImage;bgImg&&URL.revokeObjectURL(bgImg);});},_compareBlobs:function(blob1,blob2){return new Promise(function(resolve){if(!blob1||!blob2||blob1.type!==blob2.type||blob1.size!==blob2.size){resolve(false);return;}
|
||||
var startBytes=127;var bytesHash=16;var reader=new FileReader();reader.onloadend=function(){var result1=reader.result;reader=new FileReader();reader.onloadend=reader.onerror=function(){resolve(result1===reader.result);};reader.readAsDataURL(blob2.slice(startBytes,startBytes+bytesHash));};reader.onerror=function(){resolve(false);};reader.readAsDataURL(blob1.slice(startBytes,startBytes+bytesHash));});},fetchIconBlob:function(){return fetchBlob(this.icon);},_stampElementWithIcon:function(uri){if(!this.element||uri.startsWith('data:')){return;}
|
||||
if(uri.length>255){uri=uri.slice(0,255);}
|
||||
this.element.dataset.testIcon=uri;},renderIcon:function(renderCachedIcon){var icon=this.icon;this.iconState='pending';if(!icon){return;}
|
||||
if(renderCachedIcon&&this.hasCachedIcon){this._displayDecoratedIcon(this.detail.decoratedIconBlob,true);var resolveIcon=()=>{this.grid.element.removeEventListener('cached-icons-rendered',resolveIcon);this.doRenderIcon(icon);};this.grid.element.addEventListener('cached-icons-rendered',resolveIcon);}else{this.doRenderIcon(icon);}},doRenderIcon:function(icon){if(!this.isIconFromOrigin()){this._stampElementWithIcon(icon);this.renderIconFromSrc(icon);this.iconState='success';return Promise.resolve();}
|
||||
var eventTarget=this.grid.element;var blobNotFound=()=>{this.iconState='error';if(!this.hasCachedIcon){this.renderIconFromSrc(this.defaultIcon);this._stampElementWithIcon(this.defaultIcon);}else{this._stampElementWithIcon('blobcache');}
|
||||
eventTarget.dispatchEvent(new CustomEvent(ICON_BLOB_ERROR_EVENT,{detail:this}));};return this.fetchIconBlob().then((blob)=>{if(!blob){return blobNotFound();}
|
||||
this.renderIconFromBlob(blob);this.iconState='success';this._stampElementWithIcon(icon);}).catch((err)=>{blobNotFound();});},removeFromGrid:function(){var idx=this.grid.items.indexOf(this);if(idx===-1){console.error('Attempting to remove self before item has been added!');return;}
|
||||
this.grid.items.splice(idx,1);delete this.grid.icons[this.identifier];if(this.element){this.element.parentNode.removeChild(this.element);}
|
||||
this.grid.render({from:idx-1});},remove:function(){this.grid.element.dispatchEvent(new CustomEvent('removeitem',{detail:this}));},render:function(){var scale=this.grid.layout.percent*this.scale;if(!this.element){var tile=document.createElement('div');tile.className='icon';tile.dataset.identifier=this.identifier;tile.dataset.isDraggable=this.isDraggable();tile.setAttribute('role','link');tile.setAttribute('tabindex',0);tile.style.width=(this.grid.layout.constraintSize/3)+'px';var nameContainerEl=document.createElement('p');nameContainerEl.style.marginTop=((this.grid.layout.gridIconSize*(1/this.grid.layout.percent))+
|
||||
(GridIconRenderer.prototype.unscaledCanvasPadding/2))+'px';tile.appendChild(nameContainerEl);var nameEl=document.createElement('span');nameEl.className='title';nameEl.setAttribute('dir','auto');nameContainerEl.appendChild(nameEl);if(this.isRemovable()){var removeEl=document.createElement('span');removeEl.className='remove';tile.appendChild(removeEl);}
|
||||
this.element=tile;this.updateTitle();this.renderIcon(true);this.grid.element.appendChild(tile);}
|
||||
this.transform(this.x,this.y,scale);},transform:function(x,y,scale,element){scale=scale||1;if(!element){if(x===this.lastX&&y===this.lastY&&scale===this.lastScale){return;}
|
||||
element=this.element;this.lastX=x;this.lastY=y;this.lastScale=scale;}
|
||||
element.style.transform='translate('+x+'px,'+y+'px) scale('+scale+')';},setActive:function(active){if(active){this.element.classList.add('active');this.active=true;}else{this.element.classList.remove('active');this.active=false;}},updateTitle:function(){if(!this.element){return;}
|
||||
var nameEl=this.element.querySelector('.title');if(this.asyncName){this.asyncName().then(function(name){nameEl.textContent=name;});}else{nameEl.textContent=this.name;}},updateFromDatastore:function(record){var iconChanged=record.icon!==this.icon;var nameChanged=record.name!==this.name;var type=this.detail.type;var lastIcon=this.icon;record.type=type;this.detail=record;if(nameChanged){this.updateTitle();}
|
||||
if(iconChanged&&record.icon){this.renderIcon();}else if(!record.icon){this.detail.icon=lastIcon;}}};exports.GaiaGrid.GridItem=GridItem;}(window));;'use strict';(function(exports){const TYPE='bookmark';function Bookmark(record,features){this.detail=record;this.features=features||{};this.detail.type=TYPE;}
|
||||
Bookmark.prototype={__proto__:GaiaGrid.GridItem.prototype,renderer:GridIconRenderer.TYPE.FAVICON,get pixelHeight(){return this.grid.layout.gridItemHeight;},gridWidth:1,get name(){return this.detail.name;},get icon(){return this.detail.icon||this.defaultIcon;},get identifier(){return this.detail.id;},update:GaiaGrid.GridItem.prototype.updateFromDatastore,isEditable:function(){return this.features&&this.features.isEditable!==false;},isRemovable:function(){return this.features&&this.features.isRemovable!==false;},isDraggable:function(){return this.features&&this.features.isDraggable!==false;},render:function(){GaiaGrid.GridItem.prototype.render.call(this);this.element.classList.add('bookmark');if(this.isEditable()){this.element.classList.add('editable');}},launch:function(){var features={name:this.name,icon:this.icon,remote:true};var url=this.detail.url;if(this.features.search){features.searchName=this.name;features.searchUrl=url;}
|
||||
window.open(url,'_samescope',Object.keys(features).map(function eachFeature(key){return encodeURIComponent(key)+'='+
|
||||
encodeURIComponent(features[key]);}).join(','));},edit:function(){new MozActivity({name:'save-bookmark',data:{type:'url',url:this.detail.id}});}};exports.GaiaGrid.Bookmark=Bookmark;}(window));;'use strict';(function(exports){function Divider(){this.detail={type:'divider',index:0};}
|
||||
Divider.prototype={__proto__:GaiaGrid.GridItem.prototype,x:0,y:0,headerHeight:0,get pixelHeight(){return(this.grid.layout.cols>3)?50:60;},gridWidth:4,scale:1,render:function(){if(!this.element){var divider=this.element=document.createElement('section');divider.className='divider';var span=document.createElement('span');span.className='spacer';divider.appendChild(span);this.grid.element.appendChild(divider);}
|
||||
this.element.style.transform='translate(0 ,'+this.y+'px)';},remove:function(){if(this.element){this.element.parentNode.removeChild(this.element);}},isDraggable:function(){return false;}};exports.GaiaGrid.Divider=Divider;}(window));;'use strict';(function(exports){const IDENTIFIER_SEP='-';var MOZAPP_EVENTS=['downloadsuccess','downloaderror','downloadavailable','downloadapplied','progress'];var APP_LOADING='loading';var APP_ERROR='error';var APP_UNRECOVERABLE='unrecoverable';var APP_PAUSED='paused';var APP_READY='ready';function localizeString(str){var userLang=document.documentElement.lang;if(navigator.mozL10n&&navigator.mozL10n.ctx.qps.indexOf(userLang)!==-1){return navigator.mozL10n.qps[userLang].translate(str);}
|
||||
return str;}
|
||||
function Mozapp(app,entryPoint,details){this.app=app;this.entryPoint=entryPoint;this.detail={type:'app',manifestURL:app.manifestURL,entryPoint:entryPoint,index:0,decoratedIconBlob:details&&details.decoratedIconBlob};MOZAPP_EVENTS.forEach(function(type){this.app['on'+type]=this.handleEvent.bind(this);},this);this.setAppState(this._determineState(app));}
|
||||
Mozapp.HIDDEN_ROLES=['system','input','homescreen','search','addon','langpack'];Mozapp.prototype={__proto__:GaiaGrid.GridItem.prototype,_isHiddenRole:function(){var manifest=this.app.manifest;if(!manifest||!manifest.role){return null;}
|
||||
return Mozapp.HIDDEN_ROLES.indexOf(manifest.role)!==-1;},_determineState:function(app){if(app.installState==='pending'&&!app.downloadAvailable&&!app.readyToApplyDownload){return APP_UNRECOVERABLE;}
|
||||
if(app.downloading){return APP_LOADING;}
|
||||
if(app.downloadError&&app.downloadError.name){if(app.downloadError.name==='DOWNLOAD_CANCELED'){return APP_PAUSED;}
|
||||
return APP_ERROR;}
|
||||
if(app.installState==='pending'){return APP_PAUSED;}
|
||||
return APP_READY;},handleEvent:function(event){switch(event.type){case'progress':case'downloaderror':case'downloadsuccess':this.setAppState(this._determineState(this.app));break;case'downloadapplied':if(this._isHiddenRole()){console.warn('Removing hidden app from the grid',this.name);return this.removeFromGrid();}
|
||||
delete this._accurateIcon;delete this._accurateIconSize;this.setAppState(this._determineState(this.app));this.renderIcon();window.dispatchEvent(new CustomEvent('downloadapplied',{detail:{id:this.app.manifestURL}}));break;}},fetchIconBlob:function(){if(!this._accurateIconSize){this._accurateIconSize=this.closestIconSizeFromList(this.descriptor.icons);}
|
||||
var result=this._accurateIconSize?navigator.mozApps.mgmt.getIcon(this.app,this._accurateIconSize,this.entryPoint||''):GaiaGrid.GridItem.prototype.fetchIconBlob.call(this);return result;},get pixelHeight(){return this.grid.layout.gridItemHeight;},gridWidth:1,get name(){var userLang=document.documentElement.lang;if(navigator.mozL10n&&userLang in navigator.mozL10n.qps){return navigator.mozL10n.qps[userLang].translate(this.descriptor.short_name||this.descriptor.name);}
|
||||
var locales=this.descriptor.locales;var localized=locales&&locales[userLang]&&(locales[userLang].short_name||locales[userLang].name);return localized||this.descriptor.short_name||this.descriptor.name;},asyncName:function(){var userLang=document.documentElement.lang;var ep=this.entryPoint||undefined;if(!this.app.getLocalizedValue){return new Promise((resolve,reject)=>{reject();});}
|
||||
return this.app.getLocalizedValue('short_name',userLang,ep).then(shortName=>localizeString(shortName),this.app.getLocalizedValue.bind(this.app,'name',userLang,ep)).then(name=>localizeString(name),()=>this.name);},get icon(){var icon=this._accurateIcon;if(!icon){icon=this._accurateIcon=this.closestIconFromList(this.descriptor.icons);}
|
||||
return icon;},get descriptor(){var manifest=this.app.manifest||this.app.updateManifest;if(this.entryPoint&&manifest.entry_points&&manifest.entry_points[this.entryPoint]){return manifest.entry_points[this.entryPoint];}
|
||||
return manifest;},identifierSeparator:IDENTIFIER_SEP,get identifier(){var identifier=[this.app.manifestURL];if(this.entryPoint){identifier.push(this.entryPoint);}
|
||||
return identifier.join(IDENTIFIER_SEP);},isRemovable:function(){return this.app.removable;},unrecoverableError:function(){navigator.mozApps.mgmt.uninstall(this.app);},cancel:function(){var dialog=new ConfirmDialogHelper({type:'pause',title:{id:'gaia-grid-stop-download-title',args:{name:this.name}},body:'gaia-grid-stop-download-body',cancel:{title:'gaia-grid-cancel'},confirm:{title:'gaia-grid-stop-download-action',type:'danger',cb:()=>this.app.cancelDownload()}});dialog.show(document.body);},resume:function(){var dialog=new ConfirmDialogHelper({type:'resume',title:'gaia-grid-resume-download-title',body:{id:'gaia-grid-resume-download-body',args:{name:this.name}},cancel:{title:'gaia-grid-cancel'},confirm:{title:'gaia-grid-resume-download-action',cb:()=>{this.setAppState(APP_LOADING);this.app.download();}}});dialog.show(document.body);},setAppState:function(state){this.appState=state;if(this.element){this.element.dataset.appState=state;}},render:function(){var needsStateSet=!this.element;GaiaGrid.GridItem.prototype.render.apply(this,arguments);if(needsStateSet){this.setAppState(this.appState);}},launch:function(){var app=this.app;switch(this._determineState(app)){case APP_UNRECOVERABLE:return this.unrecoverableError();case APP_ERROR:case APP_PAUSED:return this.resume();case APP_LOADING:return this.cancel();}
|
||||
window.performance.mark('appLaunch@'+app.origin);if(this.entryPoint){return app.launch(this.entryPoint);}
|
||||
return app.launch();}};exports.GaiaGrid.Mozapp=Mozapp;}(window));;'use strict';(function(exports){const COLLAPSE_RATIO=0.33;const COLLAPSED_GROUP_SIZE=6;const COLLAPSED_GROUP_MARGIN_LEFT=23;const COLLAPSED_GROUP_MARGIN_RIGHT=53;const TOGGLE_TIMEOUT=250;function Group(detail){this.detail=detail||{};this.detail.type='divider';this.detail.index=0;this.pendingCollapse=this.detail.collapsed=!!this.detail.collapsed;}
|
||||
Group.prototype={__proto__:GaiaGrid.GridItem.prototype,gridWidth:4,get headerHeight(){return this.detail.collapsed?20:30;},pendingCollapse:false,pendingCollapseTimeout:null,backgroundHeight:0,lastBackgroundHeight:null,separatorHeight:0,collapseRatio:COLLAPSE_RATIO,get pixelHeight(){return this.detail.collapsed?this.backgroundHeight:this.separatorHeight;},get size(){var size=0;for(var i=this.detail.index-1,items=this.grid.items;i>=0&&items[i].detail.type!=='divider';i--){size++;}
|
||||
return size;},_createElement:function(){var group=this.element=document.createElement('section');group.className='divider group newly-created';var span=document.createElement('span');span.className='background';group.appendChild(span);this.backgroundSpanElement=span;span=document.createElement('span');span.className='shadow';group.appendChild(span);this.shadowSpanElement=span;span=document.createElement('span');span.className='header';group.appendChild(span);this.headerSpanElement=span;span=document.createElement('span');span.className='gripper';this.headerSpanElement.appendChild(span);var button=document.createElement('button');button.className='toggle';button.dataset.l10nId='gaia-grid-toggle-expanded';this.headerSpanElement.appendChild(button);this.toggleElement=button;span=document.createElement('span');span.className='separator';group.appendChild(span);this.dividerSpanElement=span;this.dividerSpanElement.appendChild(document.createElement('span'));this.grid.element.appendChild(group);this.separatorHeight=this.dividerSpanElement.clientHeight;this.lastBackgroundHeight=null;},_renderChildren:function(nApps){var isRTL=(document.documentElement.dir==='rtl');if(!this.detail.collapsed){this.element.classList.remove('collapsed');return;}
|
||||
this.element.classList.add('collapsed');var y=this.y;var index=this.detail.index;var width=Math.round((this.grid.layout.constraintSize-
|
||||
COLLAPSED_GROUP_MARGIN_LEFT-COLLAPSED_GROUP_MARGIN_RIGHT)/COLLAPSED_GROUP_SIZE);var x=isRTL?(this.grid.layout.constraintSize-COLLAPSED_GROUP_MARGIN_RIGHT):COLLAPSED_GROUP_MARGIN_LEFT;y+=this.headerHeight;var maxGridItemWidth=this.grid.layout.constraintSize/this.grid.layout.minIconsPerRow;this.collapseRatio=(maxGridItemWidth/this.grid.layout.gridItemWidth)*COLLAPSE_RATIO;for(var i=index-nApps;i<index;i++){var item=this.grid.items[i];if(this.detail.collapsed){item.scale=this.collapseRatio;var itemVisible=(i-(index-nApps))<COLLAPSED_GROUP_SIZE;if(!itemVisible){item.setCoordinates(isRTL?x+width:x-width,y);}else{item.setCoordinates(x,y);x+=isRTL?-width:width;}
|
||||
item.render();item.element.classList.add('collapsed');if(!itemVisible){item.element.classList.add('hidden');}}}},getRealYPosition:function(nApps){if(this.detail.collapsed){return this.y;}
|
||||
return this.grid.items[this.detail.index-nApps].y-
|
||||
this.headerHeight;},render:function(){var createdElements=false;if(!this.element){createdElements=true;this._createElement();}
|
||||
var nApps=this.size;this._renderChildren(nApps);var y=this.getRealYPosition(nApps);if(y!==this.lastY){this.headerSpanElement.style.transform='translate(0px, '+y+'px)';}
|
||||
if(this.toggleElement){var toggleLabel=this.detail.collapsed?'collapsed':'expanded';this.toggleElement.dataset.l10nId='gaia-grid-toggle-'+toggleLabel;}
|
||||
if(this.detail.collapsed){this.backgroundHeight=Math.round(this.collapseRatio*this.grid.layout.gridIconSize*1.5);}else{var height=Math.ceil(nApps/this.grid.layout.cols);this.backgroundHeight=(height||1)*this.grid.layout.gridItemHeight;}
|
||||
this.backgroundHeight+=this.headerHeight;if(y!=this.lastY||this.backgroundHeight!==this.lastBackgroundHeight){this.backgroundSpanElement.style.transform='translate(0px, '+y+'px) scale(1, '+this.backgroundHeight+')';this.shadowSpanElement.style.transform='translateY('+y+'px)';this.shadowSpanElement.style.height=this.backgroundHeight+'px';this.dividerSpanElement.style.transform='translate(0px, '+(y+this.backgroundHeight)+'px)';}
|
||||
this.lastBackgroundHeight=this.backgroundHeight;this.lastY=y;this.backgroundHeight+=this.separatorHeight;if(createdElements){this.element.clientTop;this.element.classList.remove('newly-created');}},forEachItem:function(callback){var nApps=this.size;var index=this.detail.index;for(var i=index-nApps;i<index;i++){callback(this.grid.items[i]);}},setActive:function(active){GaiaGrid.GridItem.prototype.setActive.call(this,active);this.collapse();var callback=active?function(item){item.element.classList.add('active');}:function(item){item.element.classList.remove('active');};this.forEachItem(callback);},_rerenderOnToggle:function(){if(this.pendingCollapseTimeout){clearTimeout(this.pendingCollapseTimeout);this.pendingCollapseTimeout=null;}
|
||||
if(this.toggleElement){this.toggleElement.classList.add('toggling');setTimeout(()=>{this.toggleElement.classList.remove('toggling');},TOGGLE_TIMEOUT);}
|
||||
this.pendingCollapseTimeout=setTimeout(()=>{this.detail.collapsed=this.pendingCollapse;this.pendingCollapseTimeout=null;if(!this.detail.collapsed){this.forEachItem(function(item){item.scale=1;if(item.element){item.element.classList.remove('collapsed');item.element.classList.remove('hidden');}});}
|
||||
if(this.active){this.render();}
|
||||
this.grid.render();var dragging=this.grid.dragdrop&&this.grid.dragdrop.inDragAction;if(dragging){this.grid.dragdrop.updateIconPosition();}else{window.dispatchEvent(new CustomEvent('gaiagrid-saveitems'));this.requestAttention();}},20);},collapse:function(){if(this.detail.collapsed){return;}
|
||||
this.pendingCollapse=true;this._rerenderOnToggle();},expand:function(){if(!this.detail.collapsed){return;}
|
||||
this.pendingCollapse=false;this._rerenderOnToggle();},launch:function(target){if(target!==this.toggleElement){return;}
|
||||
if(this.detail.collapsed){this.expand();}else{this.collapse();}},remove:function(){if(this.element){this.element.parentNode.removeChild(this.element);}},isDraggable:function(){return true;},requestAttention:function(){var rect={x:0,y:this.getRealYPosition(this.size),width:this.gridWidth*this.grid.layout.gridItemWidth,height:this.backgroundHeight};this.grid.element.dispatchEvent(new CustomEvent('gaiagrid-attention',{detail:rect}));}};exports.GaiaGrid.Divider=Group;}(window));;'use strict';(function(exports){function Placeholder(){this.detail={type:'placeholder',index:0};}
|
||||
Placeholder.prototype={__proto__:GaiaGrid.GridItem.prototype,get pixelHeight(){return this.grid.layout.gridItemHeight;},createsGroupOnDrop:false,gridWidth:1,persistToDB:false,get name(){return'';},render:function(){if(!this.element){var tile=document.createElement('div');tile.className='icon placeholder';tile.style.height=this.pixelHeight+'px';this.element=tile;this.grid.element.appendChild(tile);}
|
||||
this.transform(this.x,this.y,this.grid.layout.percent);},remove:function(){if(this.element){this.element.parentNode.removeChild(this.element);}}};exports.GaiaGrid.Placeholder=Placeholder;}(window));;window.COMPONENTS_BASE_URL='/shared/elements/';;'use strict';(function(exports){const HIDDEN_ROLES=['system','input','homescreen','theme','addon','langpack'];const EDIT_MODE_TRANSITION_STYLE='transform 0.25s ease 0s, height 0s ease 0.5s';function App(){window.performance.mark('navigationLoaded');this.grid=document.getElementById('icons');this.grid.addEventListener('iconblobdecorated',this);this.grid.addEventListener('gaiagrid-iconbloberror',this);this.grid.addEventListener('gaiagrid-attention',this);this.grid.addEventListener('gaiagrid-resize',this);this.grid.addEventListener('cached-icons-rendered',this);this.grid.addEventListener('edititem',this);this.grid.addEventListener('editmode-start',this);this.grid.addEventListener('editmode-end',this);window.addEventListener('hashchange',this);window.addEventListener('gaiagrid-saveitems',this);window.addEventListener('online',this.retryFailedIcons.bind(this));var editModeDone=document.getElementById('exit-edit-mode');editModeDone.addEventListener('click',this.exitEditMode);window.addEventListener('gaiagrid-dragdrop-begin',this);window.addEventListener('gaiagrid-dragdrop-finish',this);window.addEventListener('context-menu-open',this);window.addEventListener('context-menu-close',this);window.addEventListener('gaia-confirm-open',this);window.addEventListener('gaia-confirm-close',this);this.layoutReady=false;window.addEventListener('gaiagrid-layout-ready',this);this._iconsToRetry=[];document.addEventListener('visibilitychange',this);window.performance.mark('navigationInteractive');}
|
||||
App.prototype={HIDDEN_ROLES:HIDDEN_ROLES,EDIT_MODE_TRANSITION_STYLE:EDIT_MODE_TRANSITION_STYLE,retryFailedIcons:function(){if(!this._iconsToRetry.length){return;}
|
||||
var icons=this.grid.getIcons();var iconId;while((iconId=this._iconsToRetry.shift())){var icon=icons[iconId];if(!icon){continue;}
|
||||
icon.renderIcon();}},init:function(){this.itemStore=new ItemStore((firstTime)=>{if(!firstTime){return;}
|
||||
LazyLoader.load(['shared/js/icc_helper.js','shared/js/version_helper.js','js/configurator.js'],function onLoad(){exports.configurator=new Configurator();});});this.itemStore.all(function _all(results){results.forEach(function _eachResult(result){this.grid.add(result);},this);if(this.layoutReady){this.renderGrid();}else{window.addEventListener('gaiagrid-layout-ready',function onReady(){window.removeEventListener('gaiagrid-layout-ready',onReady);this.renderGrid();}.bind(this));}
|
||||
window.performance.mark('visuallyLoaded');window.performance.mark('contentInteractive');window.addEventListener('localized',this.onLocalized.bind(this));LazyLoader.load(['shared/elements/gaia-header/dist/gaia-header.js','js/contextmenu_handler.js','/shared/js/homescreens/confirm_dialog_helper.js'],function(){window.performance.mark('fullyLoaded');});}.bind(this));},renderGrid:function(){this.grid.setEditHeaderElement(document.getElementById('edit-header'));this.grid.render();},start:function(){this.grid.start();},stop:function(){this.grid.stop();},onLocalized:function(){var items=this.grid.getItems();items.forEach(function eachItem(item){if(!item.name){return;}
|
||||
item.updateTitle();});this.renderGrid();},exitEditMode:function(e){e.preventDefault();window.dispatchEvent(new CustomEvent('hashchange'));},handleEvent:function(e){switch(e.type){case'cached-icons-rendered':window.dispatchEvent(new CustomEvent('gaiagrid-cached-icons-rendered'));break;case'iconblobdecorated':var item=e.detail;this.itemStore.saveItem(item.detail,()=>{item.element.classList.add('test-icon-cached');});break;case'edititem':var icon=e.detail;if(icon.detail.type!='divider'){return;}
|
||||
LazyLoader.load('js/edit_group.js',()=>{groupEditor.edit(icon);});break;case'gaiagrid-iconbloberror':this._iconsToRetry.push(e.detail.identifier);break;case'gaiagrid-attention':var offsetTop=this.grid.offsetTop;var scrollTop=window.scrollY;var gridHeight=document.body.clientHeight;if(this.grid._grid.dragdrop.inEditMode){gridHeight-=offsetTop;}else{scrollTop-=offsetTop;}
|
||||
var rect=e.detail;if(scrollTop+gridHeight<rect.y+rect.height){scrollTop=(rect.y+rect.height)-gridHeight;}
|
||||
if(scrollTop>rect.y){scrollTop=rect.y;}
|
||||
if(!this.grid._grid.dragdrop.inEditMode){scrollTop+=offsetTop;}
|
||||
if(scrollTop!==window.scrollY){document.body.style.overflow='';requestAnimationFrame(()=>{requestAnimationFrame(()=>{window.scrollTo({left:0,top:scrollTop,behavior:'smooth'});});});}
|
||||
break;case'gaiagrid-resize':var height=e.detail;var oldHeight=this.grid.clientHeight;if(this.gridResizeTimeout!==null){clearTimeout(this.gridResizeTimeout);this.gridResizeTimeout=null;}
|
||||
if(height<oldHeight){var viewHeight=document.body.clientHeight;var scrollBottom=window.scrollY+viewHeight;var padding=window.getComputedStyle?parseInt(window.getComputedStyle(this.grid).paddingBottom):0;var maxScrollBottom=height+this.grid.offsetTop+padding;if(scrollBottom>=maxScrollBottom){requestAnimationFrame(()=>{requestAnimationFrame(()=>{window.scrollTo({left:0,top:maxScrollBottom-viewHeight,behavior:'smooth'});});});}}
|
||||
if(height===oldHeight){break;}
|
||||
this.grid.style.height=height+'px';break;case'gaiagrid-saveitems':this.itemStore.save(this.grid.getItems());break;case'context-menu-open':case'gaia-confirm-open':document.body.classList.add('fixed-overlay-shown');case'gaiagrid-dragdrop-begin':window.removeEventListener('hashchange',this);break;case'context-menu-close':case'gaia-confirm-close':document.body.classList.remove('fixed-overlay-shown');case'gaiagrid-dragdrop-finish':window.addEventListener('hashchange',this);break;case'gaiagrid-layout-ready':this.layoutReady=true;window.removeEventListener('gaiagrid-layout-ready',this);break;case'visibilitychange':if(document.hidden){document.body.style.overflow='hidden';}else{setTimeout(function(){document.body.style.overflow='';});}
|
||||
break;case'editmode-start':this.grid.style.transition=this.EDIT_MODE_TRANSITION_STYLE;break;case'editmode-end':this.grid.style.transition='';break;case'hashchange':var editor=exports.groupEditor;if(editor&&!editor.hidden){return;}
|
||||
var _grid=this.grid._grid;if(_grid.dragdrop&&_grid.dragdrop.inEditMode){_grid.dragdrop.exitEditMode();return;}
|
||||
if(document.hidden){return;}
|
||||
window.scrollTo({left:0,top:0,behavior:'smooth'});}}};exports.configurator={getSingleVariantApp:function(){return{};},get isSingleVariantReady(){return true;},get isSimPresentOnFirstBoot(){return false;},getItems:function(role){return{};}};exports.app=new App();exports.app.init();}(window));;(function(exports){'use strict';function Search(){this._port=null;this.connected=false;this.pendingRender=false;if(!appManager.app){window.addEventListener('appmanager-ready',function onReady(){window.removeEventListener('appmanager-ready',onReady);this.onAppReady();}.bind(this));}else{this.onAppReady();}
|
||||
var input=document.getElementById('search');input.addEventListener('click',this.open.bind(this));input.addEventListener('contextmenu',(e)=>{e.stopPropagation();});}
|
||||
Search.prototype={onAppReady:function onAppReady(){appManager.app.connect('search-results').then(function onConnectionAccepted(ports){ports.forEach(function(port){this._port=port;}.bind(this));this.connected=true;if(this.pendingRender){this.open();}}.bind(this),function onConnectionRejected(){});},open:function openRocketbar(e){window.scrollTo(0,0);e.stopPropagation();e.preventDefault();if(!this.connected){this.pendingRender=true;return;}
|
||||
this._port.postMessage({action:'render'});}};exports.search=new Search();})(window);
|
||||
113
assets/webapps/verticalhome.gaiamobile.org/index.html
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en-US" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
<meta name="theme-color" content="transparent">
|
||||
<title>FirefoxOS Homescreen</title>
|
||||
|
||||
<link rel="stylesheet" href="style/css/app.css">
|
||||
<link rel="stylesheet" href="style/css/search.css">
|
||||
<link rel="stylesheet" href="shared/elements/gaia_grid/style/external.css">
|
||||
<meta name="defaultLanguage" content="en-US">
|
||||
<meta name="availableLanguages" content="ar:201601260729, bg:201601260729, bn-BD:201601260729, ca:201601260729, cs:201601260729, da:201601260729, de:201601260729, el:201601260729, en-US:201601260729, es:201601260729, eu:201601260729, fr:201601260729, gl:201601260729, hr:201601260729, hu:201601260729, it:201601260729, ja:201601260729, km:201601260729, ko:201601260729, lt:201601260729, mk:201601260729, ms:201601260729, ne-NP:201601260729, nl:201601260729, pa:201601260729, pl:201601260729, pt-BR:201601260729, ro:201601260729, ru:201601260729, sk:201601260729, sq:201601260729, sr-Cyrl:201601260729, sr-Latn:201601260729, sv-SE:201601260729, tr:201601260729, zh-CN:201601260729, zh-TW:201601260729">
|
||||
<link rel="localization" href="/locales-obj/index.{locale}.json">
|
||||
|
||||
|
||||
|
||||
<!-- <script defer="" src="shared/js/l10n.js"></script> -->
|
||||
<!-- <link rel="stylesheet" href="shared/style/input_areas.css"> -->
|
||||
|
||||
<!-- Those libraries are loaded after rendering icons -->
|
||||
<!-- <script defer src="shared/js/homescreens/confirm_dialog_helper.js"></script> -->
|
||||
<!-- <script defer src="js/contextmenu_handler.js"></script> -->
|
||||
|
||||
<!-- Lazy load for Confirm dialog component -->
|
||||
<!-- <script defer src="/shared/js/component_utils.js"></script> -->
|
||||
<!-- <script defer src="/shared/elements/gaia_buttons/script.js"></script> -->
|
||||
<!-- <script defer src="/shared/elements/gaia_confirm/script.js"></script> -->
|
||||
<!-- <script defer src="/shared/elements/gaia_menu/script.js"></script> -->
|
||||
|
||||
<!-- Lazy load for Context Menu -->
|
||||
<!-- <script src="js/contextmenu_ui.js"></script> -->
|
||||
<!-- <script type="text/javascript" src="shared/js/omadrm/fl.js"></script> -->
|
||||
<!-- <script type="text/javascript" src="js/wallpaper.js"></script> -->
|
||||
|
||||
<!-- <script defer="" src="js/sources/application.js"></script> -->
|
||||
|
||||
<!-- <script defer="" src="js/app_manager.js"></script> -->
|
||||
<!-- <script defer="" src="js/statusbar.js"></script> -->
|
||||
<!-- <script defer="" src="shared/js/homescreens/vertical_preferences.js"></script> -->
|
||||
<!-- <script defer="" src="shared/js/bookmarks_database.js"></script> -->
|
||||
<!-- <script defer="" src="shared/js/lazy_loader.js"></script> -->
|
||||
<!-- <script defer="" src="shared/js/url_helper.js"></script> -->
|
||||
<!-- <script defer="" src="shared/js/web_manifest_helper.js"></script> -->
|
||||
<!-- <script defer="" src="shared/js/icons_helper.js"></script> -->
|
||||
|
||||
<!-- <script defer="" src="js/sources/bookmark.js"></script> -->
|
||||
<!-- <script defer="" src="js/stores/item.js"></script> -->
|
||||
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/js/grid_layout.js"></script> -->
|
||||
<!-- <script defer src="shared/elements/gaia_grid/js/grid_dragdrop.js"></script> -->
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/js/grid_icon_renderer.js"></script> -->
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/js/grid_view.js"></script> -->
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/script.js"></script> -->
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/js/items/grid_item.js"></script> -->
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/js/items/bookmark.js"></script> -->
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/js/items/divider.js"></script> -->
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/js/items/mozapp.js"></script> -->
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/js/items/group.js"></script> -->
|
||||
<!-- <script defer="" src="shared/elements/gaia_grid/js/items/placeholder.js"></script> -->
|
||||
|
||||
<!-- Gaia Components -->
|
||||
<!-- <script defer="" src="shared/elements/config.js"></script> -->
|
||||
<!-- <link rel="stylesheet" href="shared/elements/gaia-icons/gaia-icons.css"> -->
|
||||
<link rel="stylesheet" href="app://theme.gaiamobile.org/shared/elements/gaia-theme/gaia-theme.css">
|
||||
<!-- <script defer src="shared/elements/gaia-header/dist/gaia-header.js"></script> -->
|
||||
|
||||
<!-- <script defer="" src="js/app.js"></script> -->
|
||||
<!-- <script defer="" src="js/search.js"></script> --><script src="./gaia_build_defer_index.js" defer="" type="text/javascript"></script>
|
||||
<!-- <script defer src="shared/js/icc_helper.js"></script> -->
|
||||
<!-- <script defer src="shared/js/version_helper.js"></script> -->
|
||||
<!-- <script defer src="js/configurator.js"></script> -->
|
||||
<meta content="2.5" name="appVersion"></head>
|
||||
<body class="theme-media">
|
||||
<div id="curtain"></div>
|
||||
|
||||
<section id="edit-header" role="region">
|
||||
<gaia-header ignore-dir="">
|
||||
<h1 data-l10n-id="edit-mode">Edit</h1>
|
||||
<a href="#" data-l10n-id="edit-done" id="exit-edit-mode">Done</a>
|
||||
</gaia-header>
|
||||
</section>
|
||||
|
||||
<div id="search" role="button" aria-labelledby="search-input" aria-haspopup="true">
|
||||
<form id="search-form">
|
||||
<input id="search-input" x-inputmode="verbatim" role="presentation" placeholder="Search or enter address" data-l10n-id="search-or-enter-address" value="" dir="auto" type="text">
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<gaia-grid id="icons" dragdrop=""></gaia-grid>
|
||||
|
||||
<gaia-menu id="contextmenu-dialog" hidden="">
|
||||
<button id="homescreen-settings-action" data-l10n-id="homescreen-settings" type="button">Homescreen Settings</button>
|
||||
<button id="change-wallpaper-action" data-l10n-id="change-wallpaper" type="button">Change Wallpaper</button>
|
||||
</gaia-menu>
|
||||
|
||||
<section id="edit-group" role="region" hidden="">
|
||||
<gaia-header ignore-dir="" id="edit-group-header" action="close">
|
||||
<h1 data-l10n-id="edit-group-header">Edit group</h1>
|
||||
<button id="edit-group-save" disabled="" type="button" data-l10n-id="edit-done">Done</button>
|
||||
</gaia-header>
|
||||
|
||||
<form>
|
||||
<p>
|
||||
<input id="edit-group-title" x-inputmode="latin-prose" dir="auto" type="text">
|
||||
<button id="edit-group-title-clear" type="reset"></button>
|
||||
</p>
|
||||
</form>
|
||||
</section>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
20
assets/webapps/verticalhome.gaiamobile.org/js/app.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
;'use strict';(function(exports){const HIDDEN_ROLES=['system','input','homescreen','theme','addon','langpack'];const EDIT_MODE_TRANSITION_STYLE='transform 0.25s ease 0s, height 0s ease 0.5s';function App(){window.performance.mark('navigationLoaded');this.grid=document.getElementById('icons');this.grid.addEventListener('iconblobdecorated',this);this.grid.addEventListener('gaiagrid-iconbloberror',this);this.grid.addEventListener('gaiagrid-attention',this);this.grid.addEventListener('gaiagrid-resize',this);this.grid.addEventListener('cached-icons-rendered',this);this.grid.addEventListener('edititem',this);this.grid.addEventListener('editmode-start',this);this.grid.addEventListener('editmode-end',this);window.addEventListener('hashchange',this);window.addEventListener('gaiagrid-saveitems',this);window.addEventListener('online',this.retryFailedIcons.bind(this));var editModeDone=document.getElementById('exit-edit-mode');editModeDone.addEventListener('click',this.exitEditMode);window.addEventListener('gaiagrid-dragdrop-begin',this);window.addEventListener('gaiagrid-dragdrop-finish',this);window.addEventListener('context-menu-open',this);window.addEventListener('context-menu-close',this);window.addEventListener('gaia-confirm-open',this);window.addEventListener('gaia-confirm-close',this);this.layoutReady=false;window.addEventListener('gaiagrid-layout-ready',this);this._iconsToRetry=[];document.addEventListener('visibilitychange',this);window.performance.mark('navigationInteractive');}
|
||||
App.prototype={HIDDEN_ROLES:HIDDEN_ROLES,EDIT_MODE_TRANSITION_STYLE:EDIT_MODE_TRANSITION_STYLE,retryFailedIcons:function(){if(!this._iconsToRetry.length){return;}
|
||||
var icons=this.grid.getIcons();var iconId;while((iconId=this._iconsToRetry.shift())){var icon=icons[iconId];if(!icon){continue;}
|
||||
icon.renderIcon();}},init:function(){this.itemStore=new ItemStore((firstTime)=>{if(!firstTime){return;}
|
||||
LazyLoader.load(['shared/js/icc_helper.js','shared/js/version_helper.js','js/configurator.js'],function onLoad(){exports.configurator=new Configurator();});});this.itemStore.all(function _all(results){results.forEach(function _eachResult(result){this.grid.add(result);},this);if(this.layoutReady){this.renderGrid();}else{window.addEventListener('gaiagrid-layout-ready',function onReady(){window.removeEventListener('gaiagrid-layout-ready',onReady);this.renderGrid();}.bind(this));}
|
||||
window.performance.mark('visuallyLoaded');window.performance.mark('contentInteractive');window.addEventListener('localized',this.onLocalized.bind(this));LazyLoader.load(['shared/elements/gaia-header/dist/gaia-header.js','js/contextmenu_handler.js','/shared/js/homescreens/confirm_dialog_helper.js'],function(){window.performance.mark('fullyLoaded');});}.bind(this));},renderGrid:function(){this.grid.setEditHeaderElement(document.getElementById('edit-header'));this.grid.render();},start:function(){this.grid.start();},stop:function(){this.grid.stop();},onLocalized:function(){var items=this.grid.getItems();items.forEach(function eachItem(item){if(!item.name){return;}
|
||||
item.updateTitle();});this.renderGrid();},exitEditMode:function(e){e.preventDefault();window.dispatchEvent(new CustomEvent('hashchange'));},handleEvent:function(e){switch(e.type){case'cached-icons-rendered':window.dispatchEvent(new CustomEvent('gaiagrid-cached-icons-rendered'));break;case'iconblobdecorated':var item=e.detail;this.itemStore.saveItem(item.detail,()=>{item.element.classList.add('test-icon-cached');});break;case'edititem':var icon=e.detail;if(icon.detail.type!='divider'){return;}
|
||||
LazyLoader.load('js/edit_group.js',()=>{groupEditor.edit(icon);});break;case'gaiagrid-iconbloberror':this._iconsToRetry.push(e.detail.identifier);break;case'gaiagrid-attention':var offsetTop=this.grid.offsetTop;var scrollTop=window.scrollY;var gridHeight=document.body.clientHeight;if(this.grid._grid.dragdrop.inEditMode){gridHeight-=offsetTop;}else{scrollTop-=offsetTop;}
|
||||
var rect=e.detail;if(scrollTop+gridHeight<rect.y+rect.height){scrollTop=(rect.y+rect.height)-gridHeight;}
|
||||
if(scrollTop>rect.y){scrollTop=rect.y;}
|
||||
if(!this.grid._grid.dragdrop.inEditMode){scrollTop+=offsetTop;}
|
||||
if(scrollTop!==window.scrollY){document.body.style.overflow='';requestAnimationFrame(()=>{requestAnimationFrame(()=>{window.scrollTo({left:0,top:scrollTop,behavior:'smooth'});});});}
|
||||
break;case'gaiagrid-resize':var height=e.detail;var oldHeight=this.grid.clientHeight;if(this.gridResizeTimeout!==null){clearTimeout(this.gridResizeTimeout);this.gridResizeTimeout=null;}
|
||||
if(height<oldHeight){var viewHeight=document.body.clientHeight;var scrollBottom=window.scrollY+viewHeight;var padding=window.getComputedStyle?parseInt(window.getComputedStyle(this.grid).paddingBottom):0;var maxScrollBottom=height+this.grid.offsetTop+padding;if(scrollBottom>=maxScrollBottom){requestAnimationFrame(()=>{requestAnimationFrame(()=>{window.scrollTo({left:0,top:maxScrollBottom-viewHeight,behavior:'smooth'});});});}}
|
||||
if(height===oldHeight){break;}
|
||||
this.grid.style.height=height+'px';break;case'gaiagrid-saveitems':this.itemStore.save(this.grid.getItems());break;case'context-menu-open':case'gaia-confirm-open':document.body.classList.add('fixed-overlay-shown');case'gaiagrid-dragdrop-begin':window.removeEventListener('hashchange',this);break;case'context-menu-close':case'gaia-confirm-close':document.body.classList.remove('fixed-overlay-shown');case'gaiagrid-dragdrop-finish':window.addEventListener('hashchange',this);break;case'gaiagrid-layout-ready':this.layoutReady=true;window.removeEventListener('gaiagrid-layout-ready',this);break;case'visibilitychange':if(document.hidden){document.body.style.overflow='hidden';}else{setTimeout(function(){document.body.style.overflow='';});}
|
||||
break;case'editmode-start':this.grid.style.transition=this.EDIT_MODE_TRANSITION_STYLE;break;case'editmode-end':this.grid.style.transition='';break;case'hashchange':var editor=exports.groupEditor;if(editor&&!editor.hidden){return;}
|
||||
var _grid=this.grid._grid;if(_grid.dragdrop&&_grid.dragdrop.inEditMode){_grid.dragdrop.exitEditMode();return;}
|
||||
if(document.hidden){return;}
|
||||
window.scrollTo({left:0,top:0,behavior:'smooth'});}}};exports.configurator={getSingleVariantApp:function(){return{};},get isSingleVariantReady(){return true;},get isSimPresentOnFirstBoot(){return false;},getItems:function(role){return{};}};exports.app=new App();exports.app.init();}(window));
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
;'use strict';(function(exports){function AppManager(){var grid=document.querySelector('gaia-grid');var self=this;navigator.mozApps.getSelf().onsuccess=function(evt){self.app=evt.target.result;window.dispatchEvent(new CustomEvent('appmanager-ready'));};grid.addEventListener('removeitem',this);}
|
||||
AppManager.prototype={dialogVisible:false,get self(){return this.app;},handleItemRemoval:function(item){function errorLogger(err){console.error('Error while trying to remove',item.name,err);}
|
||||
switch(item.detail.type){case'bookmark':BookmarksDatabase.remove(item.identifier).catch(errorLogger);break;default:console.error('Cannot handle remove for item type ',item.detail.type);}},handleEvent:function(e){var nameObj={name:e.detail&&e.detail.name};switch(e.type){case'removeitem':if(this.dialogVisible){return;}
|
||||
this.dialogVisible=true;if(e.detail.detail.type=='app'){var request=navigator.mozApps.mgmt.uninstall(e.detail.app);request.onsuccess=()=>{e.detail.removeFromGrid();this.dialogVisible=false;};request.onerror=()=>{console.error('Error while trying to remove',e.detail.name,request.error);this.dialogVisible=false;};break;}
|
||||
var dialog=new ConfirmDialogHelper({type:'remove',title:{id:'delete-title',args:nameObj},body:{id:'delete-body',args:nameObj},cancel:{title:'cancel',cb:()=>{this.dialogVisible=false;}},confirm:{title:'delete',type:'danger',cb:()=>{e.detail.removeFromGrid();this.handleItemRemoval(e.detail);this.dialogVisible=false;}}});dialog.show(document.body);break;}}};exports.appManager=new AppManager();}(window));
|
||||
245
assets/webapps/verticalhome.gaiamobile.org/js/configurator.js
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
/* global IccHelper, verticalPreferences,
|
||||
VersionHelper, LazyLoader */
|
||||
/* exported configurator */
|
||||
|
||||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
|
||||
// We're going to use the mcc_mnc as a semaphore as well as to store its
|
||||
// value during the singleVariant file's processing time.
|
||||
var mcc_mnc;
|
||||
|
||||
// Globar configuration
|
||||
var conf = {};
|
||||
|
||||
// Path of the single variant configuration file
|
||||
var SINGLE_VARIANT_CONF_FILE = 'js/singlevariantconf.json';
|
||||
|
||||
// Keeps the list of single variant apps, indexed by manifestURL
|
||||
var singleVariantApps = {};
|
||||
var simPresentOnFirstBoot = true;
|
||||
|
||||
function loadSettingSIMPresent(currentMccMnc) {
|
||||
var settings = navigator.mozSettings;
|
||||
if (!settings) {
|
||||
console.log('Settings is not available');
|
||||
return;
|
||||
}
|
||||
var req = settings.createLock().get('ftu.simPresentOnFirstBoot');
|
||||
|
||||
req.onsuccess = function osv_success(e) {
|
||||
var simOnFirstBoot = req.result['ftu.simPresentOnFirstBoot'];
|
||||
simPresentOnFirstBoot = !simOnFirstBoot ||
|
||||
req.result['ftu.simPresentOnFirstBoot'] === currentMccMnc;
|
||||
};
|
||||
|
||||
req.onerror = function osv_error(e) {
|
||||
console.error('Error retrieving ftu.simPresentOnFirstBoot. ' + e);
|
||||
};
|
||||
}
|
||||
|
||||
function loadSingleVariantConf() {
|
||||
if (!IccHelper) {
|
||||
console.error('IccHelper isn\'t enabled. SingleVariant configuration' +
|
||||
' can\'t be loaded');
|
||||
return;
|
||||
}
|
||||
// Given a number returns a three characters string padding with zeroes
|
||||
// to the left until the desired length (3) is reached
|
||||
function normalizeCode(aCode) {
|
||||
var ncode = '' + aCode;
|
||||
while (ncode.length < 3) {
|
||||
ncode = '0' + ncode;
|
||||
}
|
||||
return ncode;
|
||||
}
|
||||
|
||||
var getMccMnc = function getMccMnc() {
|
||||
if (IccHelper.iccInfo) {
|
||||
var mcc = IccHelper.iccInfo.mcc;
|
||||
var mnc = IccHelper.iccInfo.mnc;
|
||||
if ((mcc !== undefined) && (mcc !== null) &&
|
||||
(mnc !== undefined) && (mnc !== null)) {
|
||||
return normalizeCode(mcc) + '-' + normalizeCode(mnc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function dispatchSVReadyEvent() {
|
||||
mcc_mnc = undefined;
|
||||
window.dispatchEvent(new CustomEvent('singlevariant-ready'));
|
||||
}
|
||||
|
||||
function loadSVConfFileSuccess(loadedData) {
|
||||
try {
|
||||
loadSettingSIMPresent(mcc_mnc);
|
||||
singleVariantApps = {};
|
||||
if (loadedData && loadedData[mcc_mnc]) {
|
||||
loadedData[mcc_mnc].forEach(function(app) {
|
||||
if (app.manifestURL) {
|
||||
singleVariantApps[app.manifestURL] = app;
|
||||
} else if (app.id) {
|
||||
singleVariantApps[app.id] = app;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('There is not singleVariant configuration for ' +
|
||||
mcc_mnc);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('There was an error loading singleVariant configuration',
|
||||
e);
|
||||
} finally {
|
||||
dispatchSVReadyEvent();
|
||||
}
|
||||
}
|
||||
|
||||
function loadSVConfFileError(e) {
|
||||
singleVariantApps = {};
|
||||
if (e.name === 'NS_ERROR_FILE_NOT_FOUND') {
|
||||
console.log('No single variant configuration file found');
|
||||
} else {
|
||||
console.error('Failed parsing singleVariant configuration file [' +
|
||||
SINGLE_VARIANT_CONF_FILE + ']: ', e);
|
||||
}
|
||||
dispatchSVReadyEvent();
|
||||
}
|
||||
|
||||
var iccHandler = function(evt) {
|
||||
mcc_mnc = getMccMnc();
|
||||
if (mcc_mnc) {
|
||||
IccHelper.removeEventListener('iccinfochange', iccHandler);
|
||||
LazyLoader.getJSON(SINGLE_VARIANT_CONF_FILE).then(
|
||||
loadSVConfFileSuccess, loadSVConfFileError
|
||||
);
|
||||
// No needed anymore
|
||||
iccHandler = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!iccHandler()) { // Maybe we already have the mcc and mnc...
|
||||
IccHelper.addEventListener('iccinfochange', iccHandler);
|
||||
}
|
||||
}
|
||||
|
||||
function onLoadInitJSON(loadedData) {
|
||||
conf = loadedData;
|
||||
setupColumns();
|
||||
window.dispatchEvent(new CustomEvent('configuration-ready'));
|
||||
loadSingleVariantConf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the default columns.
|
||||
*/
|
||||
function setupColumns() {
|
||||
var defaultCols = conf && conf.preferences &&
|
||||
conf.preferences['grid.cols'] || undefined;
|
||||
|
||||
if (defaultCols) {
|
||||
verticalPreferences.get('grid.cols').then(function(cols) {
|
||||
// Set the number of cols by default in preference's datastore
|
||||
!cols && verticalPreferences.put('grid.cols', defaultCols);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onErrorInitJSON(e) {
|
||||
conf = {};
|
||||
console.error('Failed parsing homescreen configuration file:' + e);
|
||||
window.dispatchEvent(new CustomEvent('configuration-ready'));
|
||||
loadSingleVariantConf();
|
||||
}
|
||||
|
||||
function handlerGridLayout(evt) {
|
||||
switch(evt.type) {
|
||||
case 'updated':
|
||||
if (evt.target.name === 'grid.layout') {
|
||||
verticalPreferences.removeEventListener('updated', handlerGridLayout);
|
||||
onLoadInitJSON(evt.target.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function load() {
|
||||
conf = {};
|
||||
|
||||
VersionHelper.getVersionInfo().then(function(verInfo) {
|
||||
if (verInfo.isUpgrade()) {
|
||||
verticalPreferences.get('grid.layout').then(function(grid) {
|
||||
if (!grid) {
|
||||
verticalPreferences.addEventListener('updated', handlerGridLayout);
|
||||
} else {
|
||||
onLoadInitJSON(grid);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
LazyLoader.getJSON('js/init.json').then(
|
||||
onLoadInitJSON, onErrorInitJSON
|
||||
);
|
||||
}
|
||||
}, function(err) {
|
||||
console.error('VersionHelper failed to lookup version settings, ' +
|
||||
'asumming no version upgrade.\n');
|
||||
});
|
||||
}
|
||||
|
||||
function Configurator() {
|
||||
load();
|
||||
}
|
||||
|
||||
Configurator.prototype = {
|
||||
getSection: function(section) {
|
||||
return conf[section];
|
||||
},
|
||||
|
||||
getGrid: function() {
|
||||
return conf.grid;
|
||||
},
|
||||
|
||||
getItems: function(role) {
|
||||
var items = {};
|
||||
|
||||
conf.grid.forEach(function forEachSection(section) {
|
||||
section.forEach(function forEachItem(item) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
if (item.role === role) {
|
||||
items[item.id] = item;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return items;
|
||||
},
|
||||
|
||||
getSingleVariantApp: function(manifestURL) {
|
||||
if (manifestURL in singleVariantApps) {
|
||||
var svApp = singleVariantApps[manifestURL];
|
||||
if (svApp.location !== undefined) {
|
||||
return svApp;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get isSingleVariantReady() {
|
||||
return !mcc_mnc;
|
||||
},
|
||||
|
||||
load: load,
|
||||
|
||||
get isSimPresentOnFirstBoot() {
|
||||
return simPresentOnFirstBoot;
|
||||
},
|
||||
|
||||
loadSettingSIMPresent: loadSettingSIMPresent
|
||||
};
|
||||
|
||||
exports.Configurator = Configurator;
|
||||
|
||||
}(window));
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
'use strict';
|
||||
/* global LazyLoader, contextMenuUI */
|
||||
|
||||
(function(exports) {
|
||||
|
||||
function ContextMenuHandler() {
|
||||
this.container = document.getElementById('icons').parentNode;
|
||||
this.container.addEventListener('contextmenu', this);
|
||||
this.container.addEventListener('touchstart', this);
|
||||
window.addEventListener('hashchange', this);
|
||||
}
|
||||
|
||||
ContextMenuHandler.prototype = {
|
||||
handleEvent: function(e) {
|
||||
switch(e.type) {
|
||||
case 'touchstart':
|
||||
this.canceled = e.touches.length > 1;
|
||||
break;
|
||||
|
||||
case 'contextmenu':
|
||||
if (this.canceled || app.grid._grid.dragdrop.inEditMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent the click when the finger is released
|
||||
e.preventDefault();
|
||||
|
||||
var resources = ['/shared/js/component_utils.js',
|
||||
'/shared/elements/gaia_buttons/script.js',
|
||||
'/shared/elements/gaia_menu/script.js',
|
||||
'js/contextmenu_ui.js'];
|
||||
LazyLoader.load(resources, function loaded() {
|
||||
// pass the event through for processing
|
||||
setTimeout(() => { contextMenuUI.show(e); });
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case 'hashchange':
|
||||
window.contextMenuUI && contextMenuUI.hide();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.contextMenuHandler = new ContextMenuHandler();
|
||||
|
||||
}(window));
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
'use strict';
|
||||
/* global LazyLoader */
|
||||
/* global MozActivity */
|
||||
/* global wallpaper */
|
||||
/* jshint nonew: false */
|
||||
|
||||
(function(exports) {
|
||||
|
||||
function ContextMenuUI() {
|
||||
this.grid = document.getElementById('icons');
|
||||
this.dialog = document.getElementById('contextmenu-dialog');
|
||||
this.wallpaperOption = document.getElementById('change-wallpaper-action');
|
||||
this.settingsOption = document.getElementById('homescreen-settings-action');
|
||||
|
||||
this.handleCancel = this._handleCancel.bind(this);
|
||||
}
|
||||
|
||||
ContextMenuUI.prototype = {
|
||||
show: function(e) {
|
||||
var nearestIndex = this.grid._grid.getNearestItemIndex(
|
||||
e.pageX,
|
||||
e.pageY - this.grid.offsetTop
|
||||
);
|
||||
|
||||
window.dispatchEvent(new CustomEvent('context-menu-open', {
|
||||
detail: {
|
||||
nearestIndex: nearestIndex
|
||||
}
|
||||
}));
|
||||
|
||||
this.dialog.addEventListener('gaiamenu-cancel', this.handleCancel);
|
||||
this.dialog.removeAttribute('hidden');
|
||||
this.wallpaperOption.addEventListener('click', this);
|
||||
this.settingsOption.addEventListener('click', this);
|
||||
window.addEventListener('visibilitychange', this);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.dialog.removeEventListener('gaiamenu-cancel', this.handleCancel);
|
||||
this.dialog.setAttribute('hidden', '');
|
||||
this.wallpaperOption.removeEventListener('click', this);
|
||||
this.settingsOption.removeEventListener('click', this);
|
||||
window.removeEventListener('visibilitychange', this);
|
||||
|
||||
window.dispatchEvent(new CustomEvent('context-menu-close'));
|
||||
},
|
||||
|
||||
_handleCancel: function(e) {
|
||||
this.hide();
|
||||
},
|
||||
|
||||
_actions: {
|
||||
'change-wallpaper-action': function() {
|
||||
LazyLoader.load([
|
||||
'shared/js/omadrm/fl.js',
|
||||
'js/wallpaper.js'
|
||||
], function() {
|
||||
this.hide();
|
||||
wallpaper.change();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'homescreen-settings-action': function() {
|
||||
this.hide();
|
||||
|
||||
new MozActivity({
|
||||
name: 'configure',
|
||||
data: {
|
||||
target: 'device',
|
||||
section: 'homescreens-list'
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function(e) {
|
||||
switch (e.type) {
|
||||
case 'click':
|
||||
this._actions[e.target.id].call(this);
|
||||
break;
|
||||
|
||||
case 'visibilitychange':
|
||||
if (document.hidden) {
|
||||
this.hide();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.contextMenuUI = new ContextMenuUI();
|
||||
|
||||
}(window));
|
||||
95
assets/webapps/verticalhome.gaiamobile.org/js/edit_group.js
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
'use strict';
|
||||
|
||||
/* global LazyLoader */
|
||||
|
||||
(function(exports) {
|
||||
|
||||
var resources = ['shared/style/input_areas.css', 'style/css/edit_group.css'];
|
||||
|
||||
function GroupEditor() {
|
||||
this.container = document.getElementById('edit-group');
|
||||
this.header = document.getElementById('edit-group-header');
|
||||
this.save = document.getElementById('edit-group-save');
|
||||
this.form = this.container.querySelector('form');
|
||||
this.clear = document.getElementById('edit-group-title-clear');
|
||||
this.nameField = document.getElementById('edit-group-title');
|
||||
}
|
||||
|
||||
GroupEditor.prototype = {
|
||||
handleEvent: function(e) {
|
||||
switch(e.type) {
|
||||
case 'click':
|
||||
case 'submit':
|
||||
this.group.name = this.nameField.value;
|
||||
this.close();
|
||||
break;
|
||||
|
||||
case 'action':
|
||||
case 'hashchange':
|
||||
this.nameField.blur();
|
||||
this.close();
|
||||
break;
|
||||
|
||||
case 'touchstart':
|
||||
e.preventDefault();
|
||||
this.nameField.value = '';
|
||||
this.checkSaveAction();
|
||||
break;
|
||||
|
||||
case 'input':
|
||||
this.checkSaveAction();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
edit: function(group) {
|
||||
LazyLoader.load(resources, () => {
|
||||
this.group = group;
|
||||
this.attachHandlers();
|
||||
this.nameField.value = group.name || '';
|
||||
this.checkSaveAction();
|
||||
document.body.classList.add('edit-group');
|
||||
this.container.hidden = false;
|
||||
setTimeout(() => {
|
||||
this.nameField.focus();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
close: function() {
|
||||
this.removeHandlers();
|
||||
this.container.hidden = true;
|
||||
document.body.classList.remove('edit-group');
|
||||
},
|
||||
|
||||
checkSaveAction: function() {
|
||||
var name = this.nameField.value.trim();
|
||||
this.save.disabled = name === this.group.name;
|
||||
},
|
||||
|
||||
attachHandlers: function() {
|
||||
this.header.addEventListener('action', this);
|
||||
this.save.addEventListener('click', this);
|
||||
this.form.addEventListener('input', this);
|
||||
this.form.addEventListener('submit', this);
|
||||
this.clear.addEventListener('touchstart', this);
|
||||
window.addEventListener('hashchange', this);
|
||||
},
|
||||
|
||||
removeHandlers: function() {
|
||||
this.header.removeEventListener('action', this);
|
||||
this.save.removeEventListener('click', this);
|
||||
this.form.removeEventListener('input', this);
|
||||
this.form.removeEventListener('submit', this);
|
||||
this.clear.removeEventListener('touchstart', this);
|
||||
window.removeEventListener('hashchange', this);
|
||||
},
|
||||
|
||||
get hidden() {
|
||||
return this.container.hidden;
|
||||
}
|
||||
};
|
||||
|
||||
exports.groupEditor = new GroupEditor();
|
||||
|
||||
})(window);
|
||||
1
assets/webapps/verticalhome.gaiamobile.org/js/init.json
Normal file
4
assets/webapps/verticalhome.gaiamobile.org/js/search.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
;(function(exports){'use strict';function Search(){this._port=null;this.connected=false;this.pendingRender=false;if(!appManager.app){window.addEventListener('appmanager-ready',function onReady(){window.removeEventListener('appmanager-ready',onReady);this.onAppReady();}.bind(this));}else{this.onAppReady();}
|
||||
var input=document.getElementById('search');input.addEventListener('click',this.open.bind(this));input.addEventListener('contextmenu',(e)=>{e.stopPropagation();});}
|
||||
Search.prototype={onAppReady:function onAppReady(){appManager.app.connect('search-results').then(function onConnectionAccepted(ports){ports.forEach(function(port){this._port=port;}.bind(this));this.connected=true;if(this.pendingRender){this.open();}}.bind(this),function onConnectionRejected(){});},open:function openRocketbar(e){window.scrollTo(0,0);e.stopPropagation();e.preventDefault();if(!this.connected){this.pendingRender=true;return;}
|
||||
this._port.postMessage({action:'render'});}};exports.search=new Search();})(window);
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
;'use strict';(function(exports){var appMgr=navigator.mozApps.mgmt;var apps=null;window.performance.mark('homescreenStart@system.gaiamobile.org');appMgr.getAll().onsuccess=function onsuccess(event){apps=event.target.result;window.dispatchEvent(new CustomEvent('navigator-mozapps-ready'));};function ApplicationSource(store){this.store=store;this.entries=[];this.entriesByManifestUrl={};this.svPreviouslyInstalledApps=[];var pendingInstallRequests=[];function addSVEventListener(){window.addEventListener('singlevariant-ready',function svFileReady(ev){window.removeEventListener('singlevariant-ready',svFileReady);for(var i=0;i<pendingInstallRequests;i++){pendingInstallRequests[i]();}});}
|
||||
addSVEventListener();var self=this;function addIcons(){window.removeEventListener('navigator-mozapps-ready',addIcons);for(var i=0,iLen=apps.length;i<iLen;i++){self.makeIcons(apps[i]);}
|
||||
apps=null;}
|
||||
apps?addIcons():window.addEventListener('navigator-mozapps-ready',addIcons);function install(application){var manifest=application.manifest||application.updateManifest;if(manifest.role&&app.HIDDEN_ROLES.indexOf(manifest.role)!==-1){return;}
|
||||
this.addIconToGrid(application);var svApp=configurator.getSingleVariantApp(application.manifestURL);var lastElem=app.grid.getIndexLastIcon();if(configurator.isSimPresentOnFirstBoot&&svApp&&svApp.location<lastElem&&!this.isPreviouslyInstalled(application.manifestURL)){app.grid.popDivider();app.grid.removeNonVisualElements();lastElem=app.grid.getIndexLastIcon();app.grid.moveTo(lastElem,svApp.location);_moveAhead(svApp.location+1);this.addPreviouslyInstalledSvApp(application.manifestURL);app.itemStore.savePrevInstalledSvApp(this.svPreviouslyInstalledApps);}
|
||||
app.grid.render();app.itemStore.deferredSave(app.grid.getItems());}
|
||||
function _moveAhead(startPos){var elems=app.grid.getItems();for(var i=startPos,iLen=elems.length;i<iLen;i++){var item=elems[i];if(item instanceof GaiaGrid.Mozapp){var svApp=configurator.getSingleVariantApp(elems[i].identifier);if(svApp&&i>svApp.location){app.grid.moveTo(i,i-1);}}}}
|
||||
appMgr.oninstall=function oninstall(event){if(configurator.isSingleVariantReady){install.bind(this)(event.application);}else{pendingInstallRequests.push(install.bind(this,event.application));}}.bind(this);appMgr.onuninstall=function onuninstall(event){var application=event.application;var manifest=application.updateManifest||application.manifest;this.removeIconFromGrid(application.manifestURL);app.itemStore.deferredSave(app.grid.getItems());if(app.HIDDEN_ROLES.indexOf(manifest.role)!==-1){return;}}.bind(this);}
|
||||
ApplicationSource.prototype={synchronize:function(){var storeItems=this.store._allItems;var toAdd=[];var appIconsByManifestUrl={};for(var i=0,iLen=storeItems.length;i<iLen;i++){var item=storeItems[i];if(!(item instanceof GaiaGrid.Mozapp)){continue;}
|
||||
appIconsByManifestUrl[item.detail.manifestURL]=item;}
|
||||
for(i=0,iLen=this.entries.length;i<iLen;i++){var entry=this.entries[i];var manifest=entry.app.updateManifest||entry.app.manifest;if(!appIconsByManifestUrl[entry.detail.manifestURL]&&!manifest.entry_points){toAdd.push(entry);}else{delete appIconsByManifestUrl[entry.detail.manifestURL];}}
|
||||
for(i in appIconsByManifestUrl){this.removeIconFromGrid(i);}
|
||||
toAdd.forEach(function _toAdd(newApp){this.addIconToGrid(newApp.app);},this);app.itemStore.deferredSave(app.grid.getItems());},addIconToGrid:function(application){this.makeIcons(application);var appObject=this.mapToApp({manifestURL:application.manifestURL});app.grid.appendItemToExpandedGroup(appObject);app.grid.render();},removeIconFromGrid:function(manifestURL){var icons=app.grid.getIcons();var appObject=icons[manifestURL];if(appObject){appObject.removeFromGrid();}},populate:function(success){success(this.entries);},makeIcons:function(eachApp){var manifest=eachApp.manifest||eachApp.updateManifest;if(app.HIDDEN_ROLES.indexOf(manifest.role)!==-1){return;}
|
||||
function eachIcon(icon){if(!icon.icon){return;}
|
||||
icon.setPosition(this.store.getNextPosition());this.entries.push(icon);}
|
||||
this.entriesByManifestUrl[eachApp.manifestURL]=eachApp;if(manifest.entry_points){for(var i in manifest.entry_points){eachIcon.call(this,new GaiaGrid.Mozapp(eachApp,i));}}else{eachIcon.call(this,new GaiaGrid.Mozapp(eachApp));}},mapToApp:function(entry){var app=this.entriesByManifestUrl[entry.manifestURL];app=app||{manifestURL:entry.manifestURL,manifest:{name:'',icons:[]}};return new GaiaGrid.Mozapp(app,entry.entryPoint,{decoratedIconBlob:entry.decoratedIconBlob});},addPreviouslyInstalledSvApp:function(manifest){this.svPreviouslyInstalledApps.push({manifestURL:manifest});},isPreviouslyInstalled:function(manifest){for(var i=0,elemNum=this.svPreviouslyInstalledApps.length;i<elemNum;i++){if(this.svPreviouslyInstalledApps[i].manifestURL===manifest){return true;}}
|
||||
return false;}};exports.ApplicationSource=ApplicationSource;}(window));
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
;'use strict';(function(exports){var eventTypesToListenFor=['added','updated','removed'];function BookmarkSource(store){this.store=store;this.entries=[];eventTypesToListenFor.forEach(function iterateTypes(type){BookmarksDatabase.addEventListener(type,this);},this);}
|
||||
BookmarkSource.prototype={synchronize:function(){var allAppBookmarks={};var toAdd=[];var icons=app.grid.getIcons();for(var i in icons){var icon=icons[i];if(icon.detail.type!=='bookmark'){continue;}
|
||||
allAppBookmarks[icon.detail.url]=icon;}
|
||||
for(var j=0,jLen=this.entries.length;j<jLen;j++){var entry=this.entries[j];if(!allAppBookmarks[entry.detail.url]){toAdd.push(entry);}else{delete allAppBookmarks[entry.detail.url];}}
|
||||
for(i in allAppBookmarks){this.removeIconFromGrid(allAppBookmarks[i].detail.url);}
|
||||
for(i=0;i<toAdd.length;i++){this.addIconToGrid(toAdd[i].detail);}
|
||||
app.itemStore.deferredSave(app.grid.getItems());},populate:function(success){var self=this;BookmarksDatabase.getAll().then(function(systemBookmarks){Object.keys(systemBookmarks).forEach(function(id){self.entries.push(new GaiaGrid.Bookmark(systemBookmarks[id]));});success(self.entries);},success);},handleEvent:function(e){switch(e.type){case'added':case'updated':this.addIconToGrid(e.target);app.itemStore.deferredSave(app.grid.getItems());break;case'removed':var id=e.target.id;this.removeIconFromGrid(id);break;}},addIconToGrid:function(detail){var icons=app.grid.getIcons();var existing=icons[detail.id];if(existing){existing.update(detail);app.grid.render();return;}
|
||||
var bookmark=new GaiaGrid.Bookmark(detail);bookmark.setPosition(this.store.getNextPosition());this.entries.push(bookmark);app.grid.appendItemToExpandedGroup(bookmark);app.grid.render();},removeIconFromGrid:function(url){var icons=app.grid.getIcons();var appObject=icons[url];if(appObject){appObject.removeFromGrid();}}};exports.BookmarkSource=BookmarkSource;}(window));
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
;'use strict';(function(exports){const APPEARANCE={OPAQUE:'opaque',SEMI_TRANSPARENT:'semi-transparent'};function StatusBar(){this.threshold=document.getElementById('search').clientHeight;if(!appManager.app){window.addEventListener('appmanager-ready',function onReady(){window.removeEventListener('appmanager-ready',onReady);this.onAppReady();}.bind(this));}else{this.onAppReady();}}
|
||||
StatusBar.prototype={handleEvent:function(e){switch(e.type){case'editmode-start':window.removeEventListener('context-menu-open',this);window.removeEventListener('context-menu-close',this);window.removeEventListener('gaia-confirm-open',this);window.removeEventListener('gaia-confirm-close',this);case'context-menu-open':case'gaia-confirm-open':window.removeEventListener('scroll',this);this.setAppearance(APPEARANCE.OPAQUE);break;case'editmode-end':window.addEventListener('context-menu-open',this);window.addEventListener('context-menu-close',this);window.addEventListener('gaia-confirm-open',this);window.addEventListener('gaia-confirm-close',this);case'context-menu-close':case'gaia-confirm-close':window.addEventListener('scroll',this);case'scroll':this.setAppearance(this.calculateAppearance());break;case'visibilitychange':if(document.hidden){break;}
|
||||
this.appearance=null;this.setAppearance(this.calculateAppearance());break;}},onAppReady:function(){var grid=app.grid;window.addEventListener('scroll',this);grid.addEventListener('editmode-start',this);grid.addEventListener('editmode-end',this);window.addEventListener('context-menu-close',this);window.addEventListener('context-menu-open',this);window.addEventListener('gaia-confirm-open',this);window.addEventListener('gaia-confirm-close',this);window.addEventListener('visibilitychange',this);this.setAppearance(APPEARANCE.SEMI_TRANSPARENT);},calculateAppearance:function(){return window.scrollY>this.threshold?APPEARANCE.OPAQUE:APPEARANCE.SEMI_TRANSPARENT;},setAppearance:function(value){if(this.appearance===value){return;}
|
||||
this.appearance=value;var meta=document.head.querySelector('meta[name="theme-color"]');if(value==APPEARANCE.OPAQUE){meta.content='black';}else{meta.content='transparent';}}};exports.statusBar=new StatusBar();}(window));
|
||||
35
assets/webapps/verticalhome.gaiamobile.org/js/stores/item.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
;'use strict';(function(exports){const DB_VERSION=1;const DB_NAME='verticalhome';const DB_ITEM_STORE='items';const DB_SV_APP_STORE_NAME='svAppsInstalled';const DATASTORE_NAME='verticalhome_items_migration';const PREFS_STORE='vertical_preferences_store';var db;var datastore;function sort(entries,order){if(!order||!order.length){return entries;}
|
||||
var newEntries=[];function isEqual(lookFor,compareWith){if(!compareWith.detail||!lookFor){return false;}
|
||||
if(compareWith instanceof GaiaGrid.Mozapp){if(!lookFor.manifestURL||!compareWith.detail.manifestURL){return false;}
|
||||
if(compareWith.detail.entryPoint){return lookFor.manifestURL===compareWith.detail.manifestURL&&lookFor.entry_point===compareWith.detail.entryPoint;}else{return lookFor.manifestURL===compareWith.detail.manifestURL;}}else if(compareWith instanceof GaiaGrid.Bookmark){if(!lookFor.id||!compareWith.detail.id){return false;}
|
||||
return lookFor.id===compareWith.detail.id;}}
|
||||
for(var i=0,iLen=order.length;i<iLen;i++){for(var j=0,jLen=order[i].length;j<jLen;j++){var ind=entries.findIndex(isEqual.bind(null,order[i][j]));if(ind>=0){newEntries.push(entries.splice(ind,1)[0]);}}
|
||||
if(i<iLen-1){newEntries.push(new GaiaGrid.Divider());}}
|
||||
if(entries.length>0){if(configurator.isSimPresentOnFirstBoot){sortUnclassifiedApps(newEntries,entries);}else{newEntries.push(new GaiaGrid.Divider());newEntries=newEntries.concat(entries);}}
|
||||
for(i=0,iLen=newEntries.length;i<iLen;i++){if(newEntries[i].detail){newEntries[i].detail.index=i;}}
|
||||
return newEntries;}
|
||||
function sortUnclassifiedApps(dstEntries,orgEntries){function compareApps(appA,appB){var svAppA=null;var svAppB=null;if(appA){svAppA=configurator.getSingleVariantApp(appA.detail.manifestURL);}
|
||||
if(appB){svAppB=configurator.getSingleVariantApp(appB.detail.manifestURL);}
|
||||
var locA=svAppA&&svAppA.location!==undefined&&svAppA.location||Number.MAX_VALUE;var locB=svAppB&&svAppB.location!==undefined&&svAppB.location||Number.MAX_VALUE;var relPos=locA-locB;return relPos?(relPos>0?1:-1):0;}
|
||||
orgEntries.sort(compareApps);if(!configurator.getSingleVariantApp(orgEntries[0].detail.manifestURL)){dstEntries.push(new GaiaGrid.Divider());dstEntries=dstEntries.concat(orgEntries);}else{var sepAdded=false;for(var i=0,iLen=orgEntries.length;i<iLen;i++){var app=orgEntries[i];var svApp=configurator.getSingleVariantApp(app.detail.manifestURL);if(!svApp){if(!sepAdded){dstEntries.push(new GaiaGrid.Divider());sepAdded=true;}
|
||||
dstEntries.push(app);}else{if(svApp.location!==undefined){dstEntries.splice(svApp.location,0,app);}else{dstEntries.push(app);}}}}}
|
||||
function loadTable(table,indexName,iterator,aNext){newTxn(table,'readonly',function(txn,store){var index=store.index(indexName);index.openCursor().onsuccess=function onsuccess(event){var cursor=event.target.result;if(!cursor){return;}
|
||||
iterator(cursor.value);cursor.continue();};},aNext);}
|
||||
function newTxn(storeName,txnType,withTxnAndStore,successCb){var txn=db.transaction([storeName],txnType);var store=txn.objectStore(storeName);txn.oncomplete=function(event){if(successCb){successCb(event);}};txn.onerror=function(event){console.warn('Error during transaction.');};withTxnAndStore(txn,store);}
|
||||
function ItemStore(onsuccess){var self=this;this.applicationSource=new ApplicationSource(this);this.bookmarkSource=new BookmarkSource(this);this.sources=[this.applicationSource,this.bookmarkSource];this.ready=false;var isEmpty=false;self.gridOrder=null;var request=window.indexedDB.open(DB_NAME,DB_VERSION);request.onupgradeneeded=function _onupgradeneeded(event){var db=event.target.result;var oldVersion=event.oldVersion||0;switch(oldVersion){case 0:var objectStore=db.createObjectStore(DB_ITEM_STORE,{keyPath:'index'});objectStore.createIndex('index','index',{unique:true});isEmpty=true;var objectSV=db.createObjectStore(DB_SV_APP_STORE_NAME,{keyPath:'manifestURL'});objectSV.createIndex('indexSV','indexSV',{unique:true});}};request.onsuccess=function _onsuccess(){onsuccess&&onsuccess(isEmpty);db=request.result;var cb=self.fetch.bind(self,self.synchronize.bind(self));if(isEmpty){window.addEventListener('configuration-ready',function onReady(){window.removeEventListener('configuration-ready',onReady);self.gridOrder=configurator.getGrid();self.populate(cb);});}else{self.initSources(cb);}
|
||||
navigator.mozSetMessageHandler('connection',self.handleIAC.bind(self));};window.addEventListener('gaiagrid-cached-icons-rendered',this);}
|
||||
ItemStore.prototype={_renderedOnce:false,_deferredSaveArgs:[],_allItems:[],nextPosition:0,all:function(success){if(!this.ready){window.addEventListener('databaseready',this.all.bind(this,success));return;}
|
||||
success(this._allItems);},saveTable:function(table,objArr,column,checkPersist,aNext){newTxn(table,'readwrite',function(txn,store){store.clear();for(var i=0,iLen=objArr.length;i<iLen;i++){if(!checkPersist||(checkPersist&&objArr[i].persistToDB)){store.put(column?objArr[i][column]:objArr[i]);}}
|
||||
if(typeof aNext==='function'){aNext();}});},saveMigrationData:function(objArr,column,checkPersist){return datastore.clear().then(()=>{var chain=[];objArr.forEach((object)=>{if(!checkPersist||object.persistToDB){var data=column?object[column]:object;chain.push(datastore.put(data,data.index+1));}});return Promise.all(chain);});},saveItem:function(object,callback){if(object.index==null){console.error('Attempting to save object without `index`');return;}
|
||||
newTxn(DB_ITEM_STORE,'readwrite',function(txn,store){store.put(object);},callback);},deferredSave:function(){var args=Array.slice(arguments);if(this._renderedOnce){return this.save.apply(this,args);}
|
||||
this._deferredSaveArgs=args;},save:function(entries,aNext){entries=sort(entries,this.gridOrder);this.gridOrder=null;this.saveTable(DB_ITEM_STORE,entries,'detail',true,aNext);},savePrevInstalledSvApp:function(svApps,aNext){this.saveTable(DB_SV_APP_STORE_NAME,svApps,null,false,aNext);},fetch:function(callback){var cached={};var collected=[];function iterator(value){collected.push(value);}
|
||||
function iteratorSV(value){this.applicationSource.addPreviouslyInstalledSvApp(value.manifestURL);}
|
||||
loadTable(DB_SV_APP_STORE_NAME,'indexSV',iteratorSV.bind(this));loadTable(DB_ITEM_STORE,'index',iterator,finish.bind(this));function addIfUnique(item){if(!cached[item.identifier]){cached[item.identifier]=true;this._allItems.push(item);}}
|
||||
function finish(){for(var i=0,iLen=collected.length;i<iLen;i++){var thisItem=collected[i];if(thisItem.type==='app'){var itemObj=this.applicationSource.mapToApp(thisItem);addIfUnique.call(this,itemObj);}else if(thisItem.type==='divider'){var divider=new GaiaGrid.Divider(thisItem);this._allItems.push(divider);}else if(thisItem.type==='bookmark'){var bookmark=new GaiaGrid.Bookmark(thisItem);addIfUnique.call(this,bookmark);}}
|
||||
this.notifyReady();if(callback&&typeof callback==='function'){callback();}}},synchronize:function(){this.sources.forEach(function eachSource(source){source.synchronize();});},initSources:function(callback){var pending=this.sources.length;var allEntries=[];var self=this;var current=0;function handleSource(){var source=self.sources[current];current++;source.populate(next);}
|
||||
handleSource();function next(entries){allEntries=allEntries.concat(entries);if(!(--pending)){callback(allEntries);}else{handleSource();}}},populate:function(callback){this.initSources(function(entries){this.deferredSave(entries,callback);}.bind(this));},notifyReady:function(){this.ready=true;dispatchEvent(new CustomEvent('databaseready'));},getNextPosition:function(){var nextPosition=this.nextPosition;this.nextPosition++;return nextPosition;},handleIAC:function(connectionRequest){if(connectionRequest.keyword!=='verticalhome-migrate'){return;}
|
||||
var port=connectionRequest.port;port.onmessage=(event)=>{if(event.data.action!=='migrate'){console.error('Unhandled migration action requested:',event.data.action);return;}
|
||||
this.migrate(event.data.manifestURL);};port.start();},migrate:function(manifestURL){this.migratingTo=manifestURL;console.info('verticalhome migrating to '+this.migratingTo);if(this.migrating){return;}
|
||||
this.migrating=true;(datastore?Promise.resolve():navigator.getDataStores(DATASTORE_NAME).then(stores=>{datastore=stores[0];return Promise.resolve();},(e)=>{return Promise.reject(e);})).then(()=>{this.all(entries=>{this.saveMigrationData(entries,'detail',true).then(()=>{this.migrating=false;window.navigator.mozSettings.createLock().set({'homescreen.manifestURL':this.migratingTo});navigator.getDataStores(PREFS_STORE).then(stores=>{if(stores.length<1){console.error('Error opening verticalhome prefs datastore');return;}
|
||||
stores[0].put('migrated',true).then(()=>{window.close();},e=>{console.error('Error storing migration pref',e);window.close();});});});});},e=>{console.error('Error retrieving datastore',e);});},handleEvent:function(e){switch(e.type){case'gaiagrid-cached-icons-rendered':this._renderedOnce=true;window.removeEventListener('gaiagrid-cached-icons-rendered',this);if(this._deferredSaveArgs.length){this.save.apply(this,this._deferredSaveArgs);}
|
||||
break;}}};exports.ItemStore=ItemStore;}(window));
|
||||
59
assets/webapps/verticalhome.gaiamobile.org/js/wallpaper.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
'use strict';
|
||||
/* global ForwardLock, MozActivity */
|
||||
|
||||
(function(exports) {
|
||||
|
||||
function Wallpaper() {
|
||||
// Do nothing...
|
||||
}
|
||||
|
||||
Wallpaper.prototype = {
|
||||
change: function() {
|
||||
// Ask for the locked content key first, because if it does not exist
|
||||
// we know there is no locked content on the phone and we don't have
|
||||
// to show the Locked Content app in the activity request.
|
||||
ForwardLock.getKey(function(secret) {
|
||||
var activity = new MozActivity({
|
||||
name: 'pick',
|
||||
data: {
|
||||
type: ['wallpaper', 'image/*'],
|
||||
includeLocked: (secret !== null),
|
||||
// XXX: This will not work with Desktop Fx / Simulator.
|
||||
width: Math.ceil(window.screen.width * window.devicePixelRatio),
|
||||
height: Math.ceil(window.screen.height * window.devicePixelRatio)
|
||||
}
|
||||
});
|
||||
|
||||
activity.onsuccess = function onWallpaperSuccess() {
|
||||
var blob = activity.result.blob;
|
||||
|
||||
if (!blob) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is a locked image from the locked content app, unlock it
|
||||
if (blob.type.split('/')[1] === ForwardLock.mimeSubtype) {
|
||||
ForwardLock.unlockBlob(secret, blob, function(unlocked) {
|
||||
setWallpaper(unlocked);
|
||||
});
|
||||
} else {
|
||||
setWallpaper(blob);
|
||||
}
|
||||
|
||||
function setWallpaper(blob) {
|
||||
navigator.mozSettings.createLock().set({
|
||||
'wallpaper.image': blob
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
activity.onerror = function onWallpaperError() {
|
||||
console.warn('pick failed!');
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
exports.wallpaper = new Wallpaper();
|
||||
|
||||
}(window));
|
||||
18
assets/webapps/verticalhome.gaiamobile.org/jsdoc.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "verticalhome",
|
||||
"tags": {
|
||||
"dictionaries": ["jsdoc"]
|
||||
},
|
||||
"source": {
|
||||
"include": ["apps/verticalhome/js/**/*.js"]
|
||||
},
|
||||
"plugins": [
|
||||
"plugins/markdown",
|
||||
"plugins/summarize"
|
||||
],
|
||||
"opts": {
|
||||
"private": true,
|
||||
"recurse": true,
|
||||
"destination": "docs/verticalhome"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"ابحث أو أدخل عنوانا"},{"$i":"delete-title","$v":["حذف ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":["سيتم حذف ",{"t":"idOrVar","v":"name"}," وجميع المعلومات الخاصة به."]},{"$i":"delete","$v":"حذف"},{"$i":"cancel","$v":"ألغِ"},{"$i":"homescreen-settings","$v":"إعدادات الشاشة الرئيسية"},{"$i":"change-wallpaper","$v":"تغيير صورة الخلفية"},{"$i":"edit-mode","$v":"حرّر"},{"$i":"edit-done","$v":"تم"},{"$i":"stop-download-title","$v":["توقف ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"هل تريد إيقاف التحميل؟"},{"$i":"stop-download-action","$v":"أوقف"},{"$i":"resume-download-title","$v":"إعادة تشغيل التنزيل"},{"$i":"resume-download-body","$v":["هل تريد تنزيل ",{"t":"idOrVar","v":"name"},"؟"]},{"$i":"resume-download-action","$v":"تنزيل"},{"$i":"edit-group-header","$v":"عدّل المجموعة"},{"$i":"gaia-grid-stop-download-title","$v":["إيقاف ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"هل تريد إيقاف التنزيل الجاري؟"},{"$i":"gaia-grid-stop-download-action","$v":"أوقِف"},{"$i":"gaia-grid-resume-download-title","$v":"أعِد التنزيل"},{"$i":"gaia-grid-resume-download-body","$v":["هل تريد تنزيل ",{"t":"idOrVar","v":"name"},"؟"]},{"$i":"gaia-grid-resume-download-action","$v":"نزِّل"},{"$i":"gaia-grid-cancel","$v":"ألغِ"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"وسّع المجموعة"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"اطو المجموعة"},{"$i":"gaia-grid-enter-group-name","$v":"أدخل اسما للمجموعة"},{"$i":"gaia-menu-cancel","$v":"ألغِ"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Търсете или въведете адрес"},{"$i":"delete-title","$v":["Изтриване на ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," и всички прилежащи данни ще бъдат изтрити."]},{"$i":"delete","$v":"Изтриване"},{"$i":"cancel","$v":"Отказ"},{"$i":"homescreen-settings","$v":"Настройки на началния екран"},{"$i":"change-wallpaper","$v":"Смяна на тапет"},{"$i":"edit-mode","$v":"Редактиране"},{"$i":"edit-done","$v":"Готово"},{"$i":"stop-download-title","$v":["Спиране на ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Желаете ли да спрете текущото изтегляне?"},{"$i":"stop-download-action","$v":"Спиране"},{"$i":"resume-download-title","$v":"Рестартиране на изтеглянето"},{"$i":"resume-download-body","$v":["Желаете ли да изтеглите ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Изтегляне"},{"$i":"edit-group-header","$v":"Редактиране на група"},{"$i":"gaia-grid-stop-download-title","$v":["Спиране на ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Желаете ли да спрете текущото изтегляне?"},{"$i":"gaia-grid-stop-download-action","$v":"Спиране"},{"$i":"gaia-grid-resume-download-title","$v":"Рестартиране на изтеглянето"},{"$i":"gaia-grid-resume-download-body","$v":["Желаете ли да изтеглите ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Изтегляне"},{"$i":"gaia-grid-cancel","$v":"Отказ"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Показване на групата"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Скриване на групата"},{"$i":"gaia-grid-enter-group-name","$v":"Въведете име на група"},{"$i":"gaia-menu-cancel","$v":"Отказ"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"অনুসন্ধান বা ঠিকানা দিন"},{"$i":"delete-title","$v":[{"t":"idOrVar","v":"name"}," অপসারণ"]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," ও এর সব তথ্য অপসারিত হবে।"]},{"$i":"delete","$v":"অপসারণ"},{"$i":"cancel","$v":"বাতিল"},{"$i":"homescreen-settings","$v":"হোমস্ক্রিন সেটিং"},{"$i":"change-wallpaper","$v":"ওয়ালপেপার পরিবর্তন"},{"$i":"edit-mode","$v":"সম্পাদনা"},{"$i":"edit-done","$v":"সম্পন্ন"},{"$i":"stop-download-title","$v":[{"t":"idOrVar","v":"name"}," থামান"]},{"$i":"stop-download-body","$v":"চলতে থাকা ডাউনলোডটি কে কি থামাতে চান?"},{"$i":"stop-download-action","$v":"থামুন"},{"$i":"resume-download-title","$v":"পুনরায় ডাউনলোড শুরু করুন"},{"$i":"resume-download-body","$v":["আপনি কি ",{"t":"idOrVar","v":"name"}," ডাউনলোড করবেন?"]},{"$i":"resume-download-action","$v":"ডাউনলোড"},{"$i":"edit-group-header","$v":"গ্রুপ সম্পাদনা করুন"},{"$i":"gaia-grid-stop-download-title","$v":[{"t":"idOrVar","v":"name"}," বন্ধ করুন"]},{"$i":"gaia-grid-stop-download-body","$v":"আপনি কি আপনার ডাউনলোড থামাতে চান?"},{"$i":"gaia-grid-stop-download-action","$v":"থামুন"},{"$i":"gaia-grid-resume-download-title","$v":"নতুন করে ডাউনলোড করুন"},{"$i":"gaia-grid-resume-download-body","$v":["আপনি কি ",{"t":"idOrVar","v":"name"}," ডাউনলোড করতে চান?"]},{"$i":"gaia-grid-resume-download-action","$v":"ডাউনলোড"},{"$i":"gaia-grid-cancel","$v":"বাতিল করুন"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"দল বর্ধিত করুন"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"দল বন্ধ করুন"},{"$i":"gaia-grid-enter-group-name","$v":"একটি গ্রুপের নাম প্রবেশ করান"},{"$i":"gaia-menu-cancel","$v":"বাতিল"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Escriviu una cerca o adreça"},{"$i":"delete-title","$v":["Elimina ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":["S'eliminarà «",{"t":"idOrVar","v":"name"},"» i totes les seves dades."]},{"$i":"delete","$v":"Elimina"},{"$i":"cancel","$v":"Cancel·la"},{"$i":"homescreen-settings","$v":"Paràmetres de la pantalla d'inici"},{"$i":"change-wallpaper","$v":"Canvia el fons de pantalla"},{"$i":"edit-mode","$v":"Edita"},{"$i":"edit-done","$v":"Fet"},{"$i":"stop-download-title","$v":["Atura ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Voleu aturar la baixada en curs?"},{"$i":"stop-download-action","$v":"Atura"},{"$i":"resume-download-title","$v":"Reinicia la baixada"},{"$i":"resume-download-body","$v":["Voleu baixar ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Baixa"},{"$i":"edit-group-header","$v":"Edita el grup"},{"$i":"gaia-grid-stop-download-title","$v":["Atura ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Voleu aturar la baixada en curs?"},{"$i":"gaia-grid-stop-download-action","$v":"Atura"},{"$i":"gaia-grid-resume-download-title","$v":"Reinicia la baixada"},{"$i":"gaia-grid-resume-download-body","$v":["Voleu baixar ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Baixa"},{"$i":"gaia-grid-cancel","$v":"Cancel·la"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expandeix el grup"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Redueix el grup"},{"$i":"gaia-grid-enter-group-name","$v":"Escriviu un nom del grup"},{"$i":"gaia-menu-cancel","$v":"Cancel·la"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Zadejte hledání nebo adresu"},{"$i":"delete-title","$v":["Smazání ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":["Aplikace ",{"t":"idOrVar","v":"name"}," a všechna související data budou smazána."]},{"$i":"delete","$v":"Smazat"},{"$i":"cancel","$v":"Zrušit"},{"$i":"homescreen-settings","$v":"Nastavení domovské obrazovky"},{"$i":"change-wallpaper","$v":"Změna tapety"},{"$i":"edit-mode","$v":"Úprava"},{"$i":"edit-done","$v":"Hotovo"},{"$i":"stop-download-title","$v":["Ukončení ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Chcete ukončit probíhající stahování?"},{"$i":"stop-download-action","$v":"Ukončit"},{"$i":"resume-download-title","$v":"Obnovení stahování"},{"$i":"resume-download-body","$v":["Chcete stáhnout ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Stáhnout"},{"$i":"edit-group-header","$v":"Upravit skupinu"},{"$i":"gaia-grid-stop-download-title","$v":["Ukončení ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Chcete ukončit probíhající stahování?"},{"$i":"gaia-grid-stop-download-action","$v":"Ukončit"},{"$i":"gaia-grid-resume-download-title","$v":"Obnovení stahování"},{"$i":"gaia-grid-resume-download-body","$v":["Chcete stáhnout aplikaci ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Stáhnout"},{"$i":"gaia-grid-cancel","$v":"Zrušit"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Rozbalit skupinu"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Sbalit skupinu"},{"$i":"gaia-grid-enter-group-name","$v":"Zadejte jméno skupiny"},{"$i":"gaia-menu-cancel","$v":"Zrušit"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Søg eller indtast adresse"},{"$i":"delete-title","$v":["Slet ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," og alle dens data vil blive slettet."]},{"$i":"delete","$v":"Slet"},{"$i":"cancel","$v":"Annuller"},{"$i":"homescreen-settings","$v":"Indstillinger til startskærm"},{"$i":"change-wallpaper","$v":"Skift baggrund"},{"$i":"edit-mode","$v":"Rediger"},{"$i":"edit-done","$v":"Færdig"},{"$i":"stop-download-title","$v":["Stop ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Vil du stoppe den igangværende filhentning?"},{"$i":"stop-download-action","$v":"Stop"},{"$i":"resume-download-title","$v":"Genstart filhentning"},{"$i":"resume-download-body","$v":["Vil du hente ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Hent"},{"$i":"edit-group-header","$v":"Rediger gruppe"},{"$i":"gaia-grid-stop-download-title","$v":["Stop ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Vil du stoppe den igangværende filhentning?"},{"$i":"gaia-grid-stop-download-action","$v":"Stop"},{"$i":"gaia-grid-resume-download-title","$v":"Genstart filhentning"},{"$i":"gaia-grid-resume-download-body","$v":["Vil du hente ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Hent"},{"$i":"gaia-grid-cancel","$v":"Annuller"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Udvid gruppe"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Sammenfold gruppe"},{"$i":"gaia-grid-enter-group-name","$v":"Angiv et gruppenavn"},{"$i":"gaia-menu-cancel","$v":"Annuller"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Suche oder Adresse"},{"$i":"delete-title","$v":[{"t":"idOrVar","v":"name"}," löschen"]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," und seine Daten werden gelöscht."]},{"$i":"delete","$v":"Löschen"},{"$i":"cancel","$v":"Abbrechen"},{"$i":"homescreen-settings","$v":"Startbildschirm-Einstellungen"},{"$i":"change-wallpaper","$v":"Hintergrund ändern"},{"$i":"edit-mode","$v":"Bearbeiten"},{"$i":"edit-done","$v":"Fertig"},{"$i":"stop-download-title","$v":[{"t":"idOrVar","v":"name"}," anhalten"]},{"$i":"stop-download-body","$v":"Soll der laufende Download angehalten werden?"},{"$i":"stop-download-action","$v":"Anhalten"},{"$i":"resume-download-title","$v":"Download neu starten"},{"$i":"resume-download-body","$v":["Soll ",{"t":"idOrVar","v":"name"}," heruntergeladen werden?"]},{"$i":"resume-download-action","$v":"Herunterladen"},{"$i":"edit-group-header","$v":"Gruppe bearbeiten"},{"$i":"gaia-grid-stop-download-title","$v":[{"t":"idOrVar","v":"name"}," anhalten"]},{"$i":"gaia-grid-stop-download-body","$v":"Soll der laufende Download angehalten werden?"},{"$i":"gaia-grid-stop-download-action","$v":"Anhalten"},{"$i":"gaia-grid-resume-download-title","$v":"Download neu starten"},{"$i":"gaia-grid-resume-download-body","$v":["Soll ",{"t":"idOrVar","v":"name"}," heruntergeladen werden?"]},{"$i":"gaia-grid-resume-download-action","$v":"Herunterladen"},{"$i":"gaia-grid-cancel","$v":"Abbrechen"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Gruppe ausklappen"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Gruppe einklappen"},{"$i":"gaia-grid-enter-group-name","$v":"Gruppennamen eingeben"},{"$i":"gaia-menu-cancel","$v":"Abbrechen"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Διεύθυνση ή αναζήτηση"},{"$i":"delete-title","$v":"Διαγράφη εφαρμογής"},{"$i":"delete-body","$v":["Η εφαρμογή ",{"t":"idOrVar","v":"name"}," και όλα της τα δεδομένα θα διαγραφούν."]},{"$i":"delete","$v":"Διαγραφή"},{"$i":"cancel","$v":"Ακύρωση"},{"$i":"homescreen-settings","$v":"Ρυθμίσεις αρχικής οθόνης"},{"$i":"change-wallpaper","$v":"Αλλαγή ταπετσαρίας"},{"$i":"edit-mode","$v":"Επεξεργασία"},{"$i":"edit-done","$v":"ΟΚ"},{"$i":"stop-download-title","$v":["Διακοπή ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Θέλετε να διακόψετε τη τρέχουσα λήψη;"},{"$i":"stop-download-action","$v":"Διακοπή"},{"$i":"resume-download-title","$v":"Επανεκκίνηση λήψης"},{"$i":"resume-download-body","$v":["Θέλετε να γίνει λήψη του ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Λήψη"},{"$i":"edit-group-header","$v":"Επεξεργασία ομάδας"},{"$i":"gaia-grid-stop-download-title","$v":["Διακοπή ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Θέλετε να διακόψετε τη τρέχουσα λήψη;"},{"$i":"gaia-grid-stop-download-action","$v":"Διακοπή"},{"$i":"gaia-grid-resume-download-title","$v":"Επανεκκίνηση λήψης"},{"$i":"gaia-grid-resume-download-body","$v":["Θέλετε να γίνει λήψη του ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Λήψη"},{"$i":"gaia-grid-cancel","$v":"Ακύρωση"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Επέκταση ομάδας"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Αναδίπλωση ομάδας"},{"$i":"gaia-grid-enter-group-name","$v":"Εισάγετε ένα όνομα ομάδας"},{"$i":"gaia-menu-cancel","$v":"Ακύρωση"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Search or enter address"},{"$i":"delete-title","$v":["Delete ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," and all of its data will be deleted."]},{"$i":"delete","$v":"Delete"},{"$i":"cancel","$v":"Cancel"},{"$i":"homescreen-settings","$v":"Homescreen Settings"},{"$i":"change-wallpaper","$v":"Change Wallpaper"},{"$i":"edit-mode","$v":"Edit"},{"$i":"edit-done","$v":"Done"},{"$i":"stop-download-title","$v":["Stop ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Do you want to stop the download in progress?"},{"$i":"stop-download-action","$v":"Stop"},{"$i":"resume-download-title","$v":"Restart Download"},{"$i":"resume-download-body","$v":["Do you want to download ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Download"},{"$i":"edit-group-header","$v":"Edit group"},{"$i":"gaia-grid-stop-download-title","$v":["Stop ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Do you want to stop the download in progress?"},{"$i":"gaia-grid-stop-download-action","$v":"Stop"},{"$i":"gaia-grid-resume-download-title","$v":"Restart Download"},{"$i":"gaia-grid-resume-download-body","$v":["Do you want to download ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Download"},{"$i":"gaia-grid-cancel","$v":"Cancel"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expand group"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Collapse group"},{"$i":"gaia-grid-enter-group-name","$v":"Enter a group name"},{"$i":"gaia-menu-cancel","$v":"Cancel"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Busque o escriba dirección"},{"$i":"delete-title","$v":["Borrar ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," y todos sus datos serán borrados."]},{"$i":"delete","$v":"Borrar"},{"$i":"cancel","$v":"Cancelar"},{"$i":"homescreen-settings","$v":"Ajustes pantalla de inicio"},{"$i":"change-wallpaper","$v":"Cambiar fondo de pantalla"},{"$i":"edit-mode","$v":"Editar"},{"$i":"edit-done","$v":"Hecho"},{"$i":"stop-download-title","$v":["Parar ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"¿Desea parar la descarga en curso?"},{"$i":"stop-download-action","$v":"Parar"},{"$i":"resume-download-title","$v":"Reiniciar descarga"},{"$i":"resume-download-body","$v":["¿Quiere descargar ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Descargar"},{"$i":"edit-group-header","$v":"Editar grupo"},{"$i":"gaia-grid-stop-download-title","$v":["Parar ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"¿Desea parar la descarga en curso?"},{"$i":"gaia-grid-stop-download-action","$v":"Parar"},{"$i":"gaia-grid-resume-download-title","$v":"Reiniciar descarga"},{"$i":"gaia-grid-resume-download-body","$v":["¿Desea descargar ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Descargar"},{"$i":"gaia-grid-cancel","$v":"Cancelar"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expandir grupo"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Contraer grupo"},{"$i":"gaia-grid-enter-group-name","$v":"Escriba nombre de grupo"},{"$i":"gaia-menu-cancel","$v":"Cancelar"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Bilatu / idatzi helbidea"},{"$i":"delete-title","$v":["Ezabatu ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," eta bere datu guztiak ezabatuko dira."]},{"$i":"delete","$v":"Ezabatu"},{"$i":"cancel","$v":"Utzi"},{"$i":"homescreen-settings","$v":"Pantaila nagusiaren ezarpenak"},{"$i":"change-wallpaper","$v":"Aldatu horma-papera"},{"$i":"edit-mode","$v":"Editatu"},{"$i":"edit-done","$v":"Eginda"},{"$i":"stop-download-title","$v":["Gelditu ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Abian dagoen deskarga gelditu nahi duzu?"},{"$i":"stop-download-action","$v":"Gelditu"},{"$i":"resume-download-title","$v":"Berrabiarazi deskarga"},{"$i":"resume-download-body","$v":[{"t":"idOrVar","v":"name"}," deskargatu nahi duzu?"]},{"$i":"resume-download-action","$v":"Deskargatu"},{"$i":"edit-group-header","$v":"Editatu taldea"},{"$i":"gaia-grid-stop-download-title","$v":["Gelditu ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Uneko deskarga gelditu nahi duzu?"},{"$i":"gaia-grid-stop-download-action","$v":"Gelditu"},{"$i":"gaia-grid-resume-download-title","$v":"Berrabiarazi deskarga"},{"$i":"gaia-grid-resume-download-body","$v":[{"t":"idOrVar","v":"name"}," deskargatu nahi duzu?"]},{"$i":"gaia-grid-resume-download-action","$v":"Deskargatu"},{"$i":"gaia-grid-cancel","$v":"Utzi"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Zabaldu taldea"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Tolestu taldea"},{"$i":"gaia-grid-enter-group-name","$v":"Sartu taldearen izena"},{"$i":"gaia-menu-cancel","$v":"Utzi"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Recherche ou adresse"},{"$i":"delete-title","$v":["Supprimer ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," et toutes ses données seront supprimés."]},{"$i":"delete","$v":"Supprimer"},{"$i":"cancel","$v":"Annuler"},{"$i":"homescreen-settings","$v":"Paramètres de l’écran d’accueil"},{"$i":"change-wallpaper","$v":"Changer le fond d’écran"},{"$i":"edit-mode","$v":"Mode édition"},{"$i":"edit-done","$v":"Terminé"},{"$i":"stop-download-title","$v":["Arrêter ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Voulez-vous arrêter le téléchargement en cours ?"},{"$i":"stop-download-action","$v":"Arrêter"},{"$i":"resume-download-title","$v":"Redémarrer le téléchargement"},{"$i":"resume-download-body","$v":["Voulez-vous télécharger ",{"t":"idOrVar","v":"name"}," ?"]},{"$i":"resume-download-action","$v":"Télécharger"},{"$i":"edit-group-header","$v":"Modifier le groupe"},{"$i":"gaia-grid-stop-download-title","$v":["Arrêter ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Voulez-vous arrêter le téléchargement en cours ?"},{"$i":"gaia-grid-stop-download-action","$v":"Arrêter"},{"$i":"gaia-grid-resume-download-title","$v":"Redémarrer le téléchargement"},{"$i":"gaia-grid-resume-download-body","$v":["Voulez-vous télécharger ",{"t":"idOrVar","v":"name"}," ?"]},{"$i":"gaia-grid-resume-download-action","$v":"Télécharger"},{"$i":"gaia-grid-cancel","$v":"Annuler"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Développer le groupe"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Réduire le groupe"},{"$i":"gaia-grid-enter-group-name","$v":"Saisir un nom de groupe"},{"$i":"gaia-menu-cancel","$v":"Annuler"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Buscar ou enderezo"},{"$i":"delete-title","$v":["Eliminar",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":["Eliminarase ",{"t":"idOrVar","v":"name"}," e todos os seus datos."]},{"$i":"delete","$v":"Eliminar"},{"$i":"cancel","$v":"Cancelar"},{"$i":"homescreen-settings","$v":"Axustes pantalla inicial"},{"$i":"change-wallpaper","$v":"Cambiar fondo de pantalla"},{"$i":"edit-mode","$v":"Editar"},{"$i":"edit-done","$v":"Feito"},{"$i":"stop-download-title","$v":["Deter ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Quere deter a descarga en progreso?"},{"$i":"stop-download-action","$v":"Deter"},{"$i":"resume-download-title","$v":"Reiniciar a descarga"},{"$i":"resume-download-body","$v":["Quere descargar ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Descargar"},{"$i":"edit-group-header","$v":"Editar grupo"},{"$i":"gaia-grid-stop-download-title","$v":["Deter ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Quere deter a descarga en progreso?"},{"$i":"gaia-grid-stop-download-action","$v":"Deter"},{"$i":"gaia-grid-resume-download-title","$v":"Reiniciar a descarga"},{"$i":"gaia-grid-resume-download-body","$v":["Quere descargar ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Descargar"},{"$i":"gaia-grid-cancel","$v":"Cancelar"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expandir grupo"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Contraer grupo"},{"$i":"gaia-grid-enter-group-name","$v":"Escriba un nome de grupo"},{"$i":"gaia-menu-cancel","$v":"Cancelar"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Search or enter address"},{"$i":"delete-title","$v":["Obriši ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," i svi pripadajući podaci će biti obrisani."]},{"$i":"delete","$v":"Obriši"},{"$i":"cancel","$v":"Cancel"},{"$i":"homescreen-settings","$v":"Homescreen Settings"},{"$i":"change-wallpaper","$v":"Promijeni pozadinsku sliku"},{"$i":"edit-mode","$v":"Edit"},{"$i":"edit-done","$v":"Done"},{"$i":"stop-download-title","$v":["Stop ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Do you want to stop the download in progress?"},{"$i":"stop-download-action","$v":"Stop"},{"$i":"resume-download-title","$v":"Ponovno pokretanje preuzimanja"},{"$i":"resume-download-body","$v":["Želite li preuzeti ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Download"},{"$i":"edit-group-header","$v":"Edit group"},{"$i":"gaia-grid-stop-download-title","$v":["Stop ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Do you want to stop the download in progress?"},{"$i":"gaia-grid-stop-download-action","$v":"Stop"},{"$i":"gaia-grid-resume-download-title","$v":"Restart Download"},{"$i":"gaia-grid-resume-download-body","$v":["Do you want to download ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Download"},{"$i":"gaia-grid-cancel","$v":"Cancel"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expand group"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Collapse group"},{"$i":"gaia-grid-enter-group-name","$v":"Enter a group name"},{"$i":"gaia-menu-cancel","$v":"Cancel"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Keresés vagy cím"},{"$i":"delete-title","$v":[{"t":"idOrVar","v":"name"}," törlése"]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," és minden adata törlésre kerül."]},{"$i":"delete","$v":"Törlés"},{"$i":"cancel","$v":"Mégse"},{"$i":"homescreen-settings","$v":"Kezdőképernyő beállítások"},{"$i":"change-wallpaper","$v":"Háttér módosítása"},{"$i":"edit-mode","$v":"Szerkesztés"},{"$i":"edit-done","$v":"Kész"},{"$i":"stop-download-title","$v":[{"t":"idOrVar","v":"name"}," leálltása"]},{"$i":"stop-download-body","$v":"Le szeretné állítani a folyamatban lévő letöltést?"},{"$i":"stop-download-action","$v":"Leállítás"},{"$i":"resume-download-title","$v":"Letöltés újraindítása"},{"$i":"resume-download-body","$v":["Szeretné letölteni ezt: ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Letöltés"},{"$i":"edit-group-header","$v":"Csoport szerkesztése"},{"$i":"gaia-grid-stop-download-title","$v":[{"t":"idOrVar","v":"name"}," leállítása"]},{"$i":"gaia-grid-stop-download-body","$v":"Le szeretné állítani a folyamatban lévő letöltést?"},{"$i":"gaia-grid-stop-download-action","$v":"Leállítás"},{"$i":"gaia-grid-resume-download-title","$v":"Letöltés újraindítása"},{"$i":"gaia-grid-resume-download-body","$v":["Szeretné letölteni ezt: ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Letöltés"},{"$i":"gaia-grid-cancel","$v":"Mégse"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Csoport kibontása"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Csoport összecsukása"},{"$i":"gaia-grid-enter-group-name","$v":"Írjon be csoportnevet"},{"$i":"gaia-menu-cancel","$v":"Mégse"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Cerca o scrivi un indirizzo"},{"$i":"delete-title","$v":["Elimina ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," e tutti i relativi dati verranno eliminati."]},{"$i":"delete","$v":"Elimina"},{"$i":"cancel","$v":"Annulla"},{"$i":"homescreen-settings","$v":"Impostazioni schermata"},{"$i":"change-wallpaper","$v":"Cambia sfondo"},{"$i":"edit-mode","$v":"Modifica"},{"$i":"edit-done","$v":"Fine"},{"$i":"stop-download-title","$v":["Interrompi ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Interrompere il download in corso?"},{"$i":"stop-download-action","$v":"Interrompi"},{"$i":"resume-download-title","$v":"Riavvio download"},{"$i":"resume-download-body","$v":["Procedere con il download di ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Scarica"},{"$i":"edit-group-header","$v":"Modifica gruppo"},{"$i":"gaia-grid-stop-download-title","$v":["Interrompi ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Interrompere il download in corso?"},{"$i":"gaia-grid-stop-download-action","$v":"Interrompi"},{"$i":"gaia-grid-resume-download-title","$v":"Riavvio download"},{"$i":"gaia-grid-resume-download-body","$v":["Procedere con il download di ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Scarica"},{"$i":"gaia-grid-cancel","$v":"Annulla"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Espandi gruppo"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Contrai gruppo"},{"$i":"gaia-grid-enter-group-name","$v":"Inserire un nome per il gruppo"},{"$i":"gaia-menu-cancel","$v":"Annulla"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"検索語またはアドレス"},{"$i":"delete-title","$v":[{"t":"idOrVar","v":"name"}," の削除"]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," とそのすべてのデータを削除します。"]},{"$i":"delete","$v":"削除"},{"$i":"cancel","$v":"キャンセル"},{"$i":"homescreen-settings","$v":"ホーム画面設定"},{"$i":"change-wallpaper","$v":"壁紙を変更"},{"$i":"edit-mode","$v":"編集"},{"$i":"edit-done","$v":"完了"},{"$i":"stop-download-title","$v":[{"t":"idOrVar","v":"name"}," のダウンロード中止"]},{"$i":"stop-download-body","$v":"ダウンロードを中止しますか?"},{"$i":"stop-download-action","$v":"中止"},{"$i":"resume-download-title","$v":"ダウンロードの再開"},{"$i":"resume-download-body","$v":[{"t":"idOrVar","v":"name"}," をダウンロードしますか?"]},{"$i":"resume-download-action","$v":"ダウンロード"},{"$i":"edit-group-header","$v":"グループの編集"},{"$i":"gaia-grid-stop-download-title","$v":[{"t":"idOrVar","v":"name"}," を中止"]},{"$i":"gaia-grid-stop-download-body","$v":"ダウンロードを中止してもよろしいですか?"},{"$i":"gaia-grid-stop-download-action","$v":"中止"},{"$i":"gaia-grid-resume-download-title","$v":"ダウンロード再開"},{"$i":"gaia-grid-resume-download-body","$v":[{"t":"idOrVar","v":"name"}," のダウンロードを再開しますか?"]},{"$i":"gaia-grid-resume-download-action","$v":"ダウンロード"},{"$i":"gaia-grid-cancel","$v":"キャンセル"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"グループを展開する"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"グループを折りたたむ"},{"$i":"gaia-grid-enter-group-name","$v":"グループ名を入力してください"},{"$i":"gaia-menu-cancel","$v":"キャンセル"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"ស្វែងរក ឬបញ្ចូលអាសយដ្ឋាន"},{"$i":"delete-title","$v":["លុប ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," និងទិន្នន័យទាំងអស់របស់វានឹងត្រូវលុប។"]},{"$i":"delete","$v":"លុប"},{"$i":"cancel","$v":"បោះបង់"},{"$i":"homescreen-settings","$v":"ការកំណត់អេក្រង់ដើម"},{"$i":"change-wallpaper","$v":"ប្ដូរផ្ទាំងរូបភាព"},{"$i":"edit-mode","$v":"កែសម្រួល"},{"$i":"edit-done","$v":"រួចរាល់"},{"$i":"stop-download-title","$v":["បញ្ឈប់ ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"តើអ្នកចង់បញ្ឈប់ការទាញយកដែលកំពុងដំណើរការឬ?"},{"$i":"stop-download-action","$v":"ឈប់"},{"$i":"resume-download-title","$v":"ចាប់ផ្ដើមទាញយកឡើងវិញ"},{"$i":"resume-download-body","$v":["តើអ្នកចង់ទាញយក ",{"t":"idOrVar","v":"name"},"ឬ?"]},{"$i":"resume-download-action","$v":"ទាញយក"},{"$i":"edit-group-header","$v":"Edit group"},{"$i":"gaia-grid-stop-download-title","$v":["បញ្ឈប់ ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"តើអ្នកចង់បញ្ឈប់ការទាញយកដែលកំពុងដំណើរការ?"},{"$i":"gaia-grid-stop-download-action","$v":"បញ្ឈប់"},{"$i":"gaia-grid-resume-download-title","$v":"ចាប់ផ្ដើមទាញយកឡើងវិញ"},{"$i":"gaia-grid-resume-download-body","$v":["តើអ្នកចង់ទាញយក ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"ទាញយក"},{"$i":"gaia-grid-cancel","$v":"បោះបង់"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expand group"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Collapse group"},{"$i":"gaia-grid-enter-group-name","$v":"Enter a group name"},{"$i":"gaia-menu-cancel","$v":"បោះបង់"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"검색어나 주소 입력"},{"$i":"delete-title","$v":[{"t":"idOrVar","v":"name"}," 삭제"]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," 항목과 데이터가 모두 삭제됩니다."]},{"$i":"delete","$v":"삭제"},{"$i":"cancel","$v":"취소"},{"$i":"homescreen-settings","$v":"홈스크린 설정"},{"$i":"change-wallpaper","$v":"바탕화면 변경"},{"$i":"edit-mode","$v":"수정"},{"$i":"edit-done","$v":"완료"},{"$i":"stop-download-title","$v":[{"t":"idOrVar","v":"name"}," 중지"]},{"$i":"stop-download-body","$v":"진행중인 다운로드를 취소하시겠습니까?"},{"$i":"stop-download-action","$v":"중지"},{"$i":"resume-download-title","$v":"다운로드 재시작"},{"$i":"resume-download-body","$v":[{"t":"idOrVar","v":"name"}," 항목을 다운로드 하시겠습니까?"]},{"$i":"resume-download-action","$v":"다운로드"},{"$i":"edit-group-header","$v":"그룹 편집"},{"$i":"gaia-grid-stop-download-title","$v":[{"t":"idOrVar","v":"name"}," 중지"]},{"$i":"gaia-grid-stop-download-body","$v":"진행중인 다운로드를 취소하시겠습니까?"},{"$i":"gaia-grid-stop-download-action","$v":"중지"},{"$i":"gaia-grid-resume-download-title","$v":"다운로드 재시작"},{"$i":"gaia-grid-resume-download-body","$v":[{"t":"idOrVar","v":"name"}," 항목을 다운로드 하시겠습니까?"]},{"$i":"gaia-grid-resume-download-action","$v":"다운로드"},{"$i":"gaia-grid-cancel","$v":"취소"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"그룹 열기"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"그룹 닫기"},{"$i":"gaia-grid-enter-group-name","$v":"그룹 이름 입력"},{"$i":"gaia-menu-cancel","$v":"취소"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Ieškokite arba įveskite adresą"},{"$i":"delete-title","$v":["„",{"t":"idOrVar","v":"name"},"“ šalinimas"]},{"$i":"delete-body","$v":["Ar pašalinti „",{"t":"idOrVar","v":"name"},"“ ir visus susijusius duomenis?"]},{"$i":"delete","$v":"Šalinti"},{"$i":"cancel","$v":"Atsisakyti"},{"$i":"homescreen-settings","$v":"Pradžios ekrano nuostatos"},{"$i":"change-wallpaper","$v":"Keisti ekrano foną"},{"$i":"edit-mode","$v":"Taisa"},{"$i":"edit-done","$v":"Baigta"},{"$i":"stop-download-title","$v":["„",{"t":"idOrVar","v":"name"},"“ parsiuntimo nutraukimas"]},{"$i":"stop-download-body","$v":"Ar norite nutraukti vykstantį parsiuntimą?"},{"$i":"stop-download-action","$v":"Nutraukti"},{"$i":"resume-download-title","$v":"Parsiuntimo kartojimas"},{"$i":"resume-download-body","$v":["Ar norite parsiųsti „",{"t":"idOrVar","v":"name"},"“?"]},{"$i":"resume-download-action","$v":"Parsiųsti"},{"$i":"edit-group-header","$v":"Edit group"},{"$i":"gaia-grid-stop-download-title","$v":["Parsiuntimo „",{"t":"idOrVar","v":"name"},"“ nutraukimas"]},{"$i":"gaia-grid-stop-download-body","$v":"Ar norite nutraukti vykstantį parsiuntimą?ss?"},{"$i":"gaia-grid-stop-download-action","$v":"Nutraukti"},{"$i":"gaia-grid-resume-download-title","$v":"Parsiuntimo kartojimas"},{"$i":"gaia-grid-resume-download-body","$v":["Ar norite parsiųsti „",{"t":"idOrVar","v":"name"},"“?"]},{"$i":"gaia-grid-resume-download-action","$v":"Parsiųsti"},{"$i":"gaia-grid-cancel","$v":"Atsisakyti"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expand group"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Collapse group"},{"$i":"gaia-grid-enter-group-name","$v":"Enter a group name"},{"$i":"gaia-menu-cancel","$v":"Atsisakyti"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Search or enter address"},{"$i":"delete-title","$v":["Delete ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," and all of its data will be deleted."]},{"$i":"delete","$v":"Delete"},{"$i":"cancel","$v":"Cancel"},{"$i":"homescreen-settings","$v":"Homescreen Settings"},{"$i":"change-wallpaper","$v":"Change Wallpaper"},{"$i":"edit-mode","$v":"Edit"},{"$i":"edit-done","$v":"Done"},{"$i":"stop-download-title","$v":["Stop ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Do you want to stop the download in progress?"},{"$i":"stop-download-action","$v":"Stop"},{"$i":"resume-download-title","$v":"Restart Download"},{"$i":"resume-download-body","$v":["Do you want to download ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Download"},{"$i":"edit-group-header","$v":"Edit group"},{"$i":"gaia-grid-stop-download-title","$v":["Stop ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Do you want to stop the download in progress?"},{"$i":"gaia-grid-stop-download-action","$v":"Stop"},{"$i":"gaia-grid-resume-download-title","$v":"Restart Download"},{"$i":"gaia-grid-resume-download-body","$v":["Do you want to download ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Download"},{"$i":"gaia-grid-cancel","$v":"Cancel"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expand group"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Collapse group"},{"$i":"gaia-grid-enter-group-name","$v":"Enter a group name"},{"$i":"gaia-menu-cancel","$v":"Cancel"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Cari atau masukkan alamat"},{"$i":"delete-title","$v":["Hapus ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," dan semua datanya akan dihapuskan."]},{"$i":"delete","$v":"Hapus"},{"$i":"cancel","$v":"Batal"},{"$i":"homescreen-settings","$v":"Tetapan Skrin Utama"},{"$i":"change-wallpaper","$v":"Tukar Kertas Dinding"},{"$i":"edit-mode","$v":"Sunting"},{"$i":"edit-done","$v":"Selesai"},{"$i":"stop-download-title","$v":["Henti ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Adakah anda ingin menghentikan muat turun sedang berlangsung?"},{"$i":"stop-download-action","$v":"Henti"},{"$i":"resume-download-title","$v":"Ulang mula muat turun"},{"$i":"resume-download-body","$v":["Adakah anda ingin muat turun ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Muat turun"},{"$i":"edit-group-header","$v":"Edit group"},{"$i":"gaia-grid-stop-download-title","$v":["Henti ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Adakah anda ingin menghentikan muat turun yang sedang berlangsung?"},{"$i":"gaia-grid-stop-download-action","$v":"Henti"},{"$i":"gaia-grid-resume-download-title","$v":"Mula semula Muat turun"},{"$i":"gaia-grid-resume-download-body","$v":["Adakah anda ingin memuat turun ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Muat Turun"},{"$i":"gaia-grid-cancel","$v":"Batal"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expand group"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Collapse group"},{"$i":"gaia-grid-enter-group-name","$v":"Enter a group name"},{"$i":"gaia-menu-cancel","$v":"Batal"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Search or enter address"},{"$i":"delete-title","$v":[{"t":"idOrVar","v":"name"}," मेट"]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," र यसका सम्पूर्ण डाटाहरु मेटाइनेछ।"]},{"$i":"delete","$v":"मेट्नुहोस्"},{"$i":"cancel","$v":"Cancel"},{"$i":"homescreen-settings","$v":"Homescreen Settings"},{"$i":"change-wallpaper","$v":"वालपपेर बदल्नुहोस"},{"$i":"edit-mode","$v":"सम्पादन गर्नुहोस्"},{"$i":"edit-done","$v":"पूरा भयो"},{"$i":"stop-download-title","$v":["Stop ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Do you want to stop the download in progress?"},{"$i":"stop-download-action","$v":"Stop"},{"$i":"resume-download-title","$v":"डाउनलोड पुन: सुरु गर्नुहोस"},{"$i":"resume-download-body","$v":["के तपाई ",{"t":"idOrVar","v":"name"}," डाउनलोड गर्न चाहनुहुन्छ?"]},{"$i":"resume-download-action","$v":"Download"},{"$i":"edit-group-header","$v":"Edit group"},{"$i":"gaia-grid-stop-download-title","$v":["बन्द",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"तपाई यो डाउनलोडको प्रगतिलाई रोक्न चाहनुहुन्छ? "},{"$i":"gaia-grid-stop-download-action","$v":"बन्द"},{"$i":"gaia-grid-resume-download-title","$v":"डाउनलोड फेरी सुरु गर्नुहोस्"},{"$i":"gaia-grid-resume-download-body","$v":["के तपाई ",{"t":"idOrVar","v":"name"}," डाउनलोड गर्न चाहनुहुन्छ?"]},{"$i":"gaia-grid-resume-download-action","$v":"डाउनलोड"},{"$i":"gaia-grid-cancel","$v":"रद्द गर्नुहोस्"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expand group"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Collapse group"},{"$i":"gaia-grid-enter-group-name","$v":"Enter a group name"},{"$i":"gaia-menu-cancel","$v":"रद्द गर्नुहोस्"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Voer zoekterm of adres in"},{"$i":"delete-title","$v":[{"t":"idOrVar","v":"name"}," verwijderen"]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," en alle gegevens ervan zullen worden verwijderd."]},{"$i":"delete","$v":"Verwijderen"},{"$i":"cancel","$v":"Annuleren"},{"$i":"homescreen-settings","$v":"Startscherminstellingen"},{"$i":"change-wallpaper","$v":"Achtergrond wijzigen"},{"$i":"edit-mode","$v":"Bewerken"},{"$i":"edit-done","$v":"Gereed"},{"$i":"stop-download-title","$v":[{"t":"idOrVar","v":"name"}," stoppen"]},{"$i":"stop-download-body","$v":"Wilt u de actieve download stoppen?"},{"$i":"stop-download-action","$v":"Stoppen"},{"$i":"resume-download-title","$v":"Download herstarten"},{"$i":"resume-download-body","$v":["Wilt u ",{"t":"idOrVar","v":"name"}," downloaden?"]},{"$i":"resume-download-action","$v":"Downloaden"},{"$i":"edit-group-header","$v":"Groep bewerken"},{"$i":"gaia-grid-stop-download-title","$v":[{"t":"idOrVar","v":"name"}," stoppen"]},{"$i":"gaia-grid-stop-download-body","$v":"Wilt u de actieve download stoppen?"},{"$i":"gaia-grid-stop-download-action","$v":"Stoppen"},{"$i":"gaia-grid-resume-download-title","$v":"Download herstarten"},{"$i":"gaia-grid-resume-download-body","$v":["Wilt u ",{"t":"idOrVar","v":"name"}," downloaden?"]},{"$i":"gaia-grid-resume-download-action","$v":"Downloaden"},{"$i":"gaia-grid-cancel","$v":"Annuleren"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Groep uitvouwen"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Groep samenvouwen"},{"$i":"gaia-grid-enter-group-name","$v":"Voer een groepsnaam in"},{"$i":"gaia-menu-cancel","$v":"Annuleren"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"ਖੋਜੋ ਜਾਂ ਸਿਰਨਾਵਾਂ ਦਿਓ"},{"$i":"delete-title","$v":[{"t":"idOrVar","v":"name"}," ਹਟਾਓ"]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," ਤੇ ਇਸ ਦਾ ਸਾਰਾ ਡਾਟਾ ਹਟਾਇਆ ਜਾਵੇਗਾ।"]},{"$i":"delete","$v":"ਹਟਾਓ"},{"$i":"cancel","$v":"ਰੱਦ ਕਰੋ"},{"$i":"homescreen-settings","$v":"ਮੁੱਖ ਸਕਰੀਨ ਸੈਟਿੰਗ"},{"$i":"change-wallpaper","$v":"ਵਾਲਪੇਪਰ ਬਦਲੋ"},{"$i":"edit-mode","$v":"ਸੋਧ"},{"$i":"edit-done","$v":"ਮੁਕੰਮਲ"},{"$i":"stop-download-title","$v":[{"t":"idOrVar","v":"name"}," ਰੋਕੋ"]},{"$i":"stop-download-body","$v":"ਕੀ ਤੁਸੀਂ ਜਾਰੀ ਡਾਊਨਲੋਡ ਨੂੰ ਰੋਕਣਾ ਚਾਹੁੰਦੇ ਹੋ?"},{"$i":"stop-download-action","$v":"ਰੋਕੋ"},{"$i":"resume-download-title","$v":"ਡਾਊਨਲੋਡ ਮੁੜ-ਚਾਲੂ"},{"$i":"resume-download-body","$v":["ਕੀ ਤੁਸੀਂ ",{"t":"idOrVar","v":"name"}," ਡਾਊਨਲੋਡ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"]},{"$i":"resume-download-action","$v":"ਡਾਊਨਲੋਡ"},{"$i":"edit-group-header","$v":"Edit group"},{"$i":"gaia-grid-stop-download-title","$v":[{"t":"idOrVar","v":"name"}," ਰੋਕੋ"]},{"$i":"gaia-grid-stop-download-body","$v":"ਕੀ ਤੁਸੀਂ ਚੱਲ ਰਹੇ ਡਾਊਨਲੋਡ ਨੂੰ ਰੋਕਣਾ ਚਾਹੁੰਦੇ ਹੋ?"},{"$i":"gaia-grid-stop-download-action","$v":"ਰੋਕੋ"},{"$i":"gaia-grid-resume-download-title","$v":"ਡਾਊਨਲੋਡ ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"},{"$i":"gaia-grid-resume-download-body","$v":["ਕੀ ਤੁਸੀਂ ",{"t":"idOrVar","v":"name"}," ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"]},{"$i":"gaia-grid-resume-download-action","$v":"ਡਾਊਨਲੋਡ"},{"$i":"gaia-grid-cancel","$v":"ਰੱਦ ਕਰੋ"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expand group"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Collapse group"},{"$i":"gaia-grid-enter-group-name","$v":"Enter a group name"},{"$i":"gaia-menu-cancel","$v":"ਰੱਦ ਕਰੋ"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Podaj adres lub szukaj"},{"$i":"delete-title","$v":["Usuwanie „",{"t":"idOrVar","v":"name"},"”"]},{"$i":"delete-body","$v":["Aplikacja „",{"t":"idOrVar","v":"name"},"” i wszystkie powiązane z nią dane zostaną usunięte."]},{"$i":"delete","$v":"Usuń"},{"$i":"cancel","$v":"Anuluj"},{"$i":"homescreen-settings","$v":"Ustawienia ekranu głównego"},{"$i":"change-wallpaper","$v":"Zmień tło ekranu"},{"$i":"edit-mode","$v":"Edycja"},{"$i":"edit-done","$v":"Gotowe"},{"$i":"stop-download-title","$v":["Zatrzymywanie pobierania „",{"t":"idOrVar","v":"name"},"”"]},{"$i":"stop-download-body","$v":"Zatrzymać aktywne pobieranie aplikacji?"},{"$i":"stop-download-action","$v":"Zatrzymaj"},{"$i":"resume-download-title","$v":"Wznawianie pobierania"},{"$i":"resume-download-body","$v":["Pobrać aplikację „",{"t":"idOrVar","v":"name"},"”?"]},{"$i":"resume-download-action","$v":"Pobierz"},{"$i":"edit-group-header","$v":"Edycja grupy"},{"$i":"gaia-grid-stop-download-title","$v":["Zatrzymywanie pobierania „",{"t":"idOrVar","v":"name"},"”"]},{"$i":"gaia-grid-stop-download-body","$v":"Zatrzymać aktywne pobieranie aplikacji?"},{"$i":"gaia-grid-stop-download-action","$v":"Zatrzymaj"},{"$i":"gaia-grid-resume-download-title","$v":"Wznawianie pobierania"},{"$i":"gaia-grid-resume-download-body","$v":["Pobrać aplikację „",{"t":"idOrVar","v":"name"},"”?"]},{"$i":"gaia-grid-resume-download-action","$v":"Pobierz"},{"$i":"gaia-grid-cancel","$v":"Anuluj"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Rozwiń grupę"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Zwiń grupę"},{"$i":"gaia-grid-enter-group-name","$v":"Wprowadź nazwę grupy"},{"$i":"gaia-menu-cancel","$v":"Anuluj"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Pesquisar ou navegar"},{"$i":"delete-title","$v":["Apagar ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," e todos os seus dados serão apagados."]},{"$i":"delete","$v":"Apagar"},{"$i":"cancel","$v":"Cancelar"},{"$i":"homescreen-settings","$v":"Configurações da tela principal"},{"$i":"change-wallpaper","$v":"Mudar papel de parede"},{"$i":"edit-mode","$v":"Editar"},{"$i":"edit-done","$v":"Pronto"},{"$i":"stop-download-title","$v":["Parar ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Você quer parar o download em progresso?"},{"$i":"stop-download-action","$v":"Parar"},{"$i":"resume-download-title","$v":"Reiniciar download"},{"$i":"resume-download-body","$v":["Deseja baixar ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Baixar"},{"$i":"edit-group-header","$v":"Editar grupo"},{"$i":"gaia-grid-stop-download-title","$v":["Parar ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Deseja interromper o download em progresso?"},{"$i":"gaia-grid-stop-download-action","$v":"Parar"},{"$i":"gaia-grid-resume-download-title","$v":"Reiniciar Download"},{"$i":"gaia-grid-resume-download-body","$v":["Você deseja transferir ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Download"},{"$i":"gaia-grid-cancel","$v":"Cancelar"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expandir grupo"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Recolher grupo"},{"$i":"gaia-grid-enter-group-name","$v":"Digite o nome do grupo"},{"$i":"gaia-menu-cancel","$v":"Cancelar"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Caută sau introdu adresa"},{"$i":"delete-title","$v":["Șterge ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," și toate datele sale vor fi șterse."]},{"$i":"delete","$v":"Șterge"},{"$i":"cancel","$v":"Renunță"},{"$i":"homescreen-settings","$v":"Setări pentru ecran principal"},{"$i":"change-wallpaper","$v":"Schimbă fundalul"},{"$i":"edit-mode","$v":"Editează"},{"$i":"edit-done","$v":"Gata"},{"$i":"stop-download-title","$v":["Oprește ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Dorești să oprești descărcarea în desfășurare?"},{"$i":"stop-download-action","$v":"Oprește"},{"$i":"resume-download-title","$v":"Repornește descărcarea"},{"$i":"resume-download-body","$v":["Dorești să descarci ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Descarcă"},{"$i":"edit-group-header","$v":"Editează grupul"},{"$i":"gaia-grid-stop-download-title","$v":["Oprește ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Dorești să oprești descărcarea în desfășurare?"},{"$i":"gaia-grid-stop-download-action","$v":"Oprește"},{"$i":"gaia-grid-resume-download-title","$v":"Repornește descărcarea"},{"$i":"gaia-grid-resume-download-body","$v":["Dorești să descarci ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Descarcă"},{"$i":"gaia-grid-cancel","$v":"Renunță"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Extinde grupul"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Restânge grupul"},{"$i":"gaia-grid-enter-group-name","$v":"Intro un nume de grup"},{"$i":"gaia-menu-cancel","$v":"Renunță"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Поиск или адрес"},{"$i":"delete-title","$v":["Удаление ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," и все его данные будут удалены."]},{"$i":"delete","$v":"Удалить"},{"$i":"cancel","$v":"Отмена"},{"$i":"homescreen-settings","$v":"Параметры Домашнего экрана"},{"$i":"change-wallpaper","$v":"Сменить обои"},{"$i":"edit-mode","$v":"Изменить"},{"$i":"edit-done","$v":"Готово"},{"$i":"stop-download-title","$v":["Остановка ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Вы хотите остановить процесс загрузки?"},{"$i":"stop-download-action","$v":"Остановить"},{"$i":"resume-download-title","$v":"Перезапуск загрузки"},{"$i":"resume-download-body","$v":["Вы хотите загрузить ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Загрузить"},{"$i":"edit-group-header","$v":"Изменить группу"},{"$i":"gaia-grid-stop-download-title","$v":["Остановка ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Вы хотите остановить процесс загрузки?"},{"$i":"gaia-grid-stop-download-action","$v":"Остановить"},{"$i":"gaia-grid-resume-download-title","$v":"Перезапуск загрузки"},{"$i":"gaia-grid-resume-download-body","$v":["Вы хотите загрузить ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Загрузить"},{"$i":"gaia-grid-cancel","$v":"Отмена"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Развернуть группу"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Свернуть группу"},{"$i":"gaia-grid-enter-group-name","$v":"Введите имя группы"},{"$i":"gaia-menu-cancel","$v":"Отмена"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Zadajte adresu/vyhľadávanie"},{"$i":"delete-title","$v":["Odstrániť ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," a všetky jej údaje budú odstránené."]},{"$i":"delete","$v":"Odstrániť"},{"$i":"cancel","$v":"Zrušiť"},{"$i":"homescreen-settings","$v":"Nastavenia Úvodnej obrazovky"},{"$i":"change-wallpaper","$v":"Zmeniť tapetu"},{"$i":"edit-mode","$v":"Upraviť"},{"$i":"edit-done","$v":"Hotovo"},{"$i":"stop-download-title","$v":["Zastaviť ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Naozaj chcete zastaviť prebiehajúce preberanie súboru?"},{"$i":"stop-download-action","$v":"Zastaviť"},{"$i":"resume-download-title","$v":"Reštartovať preberanie"},{"$i":"resume-download-body","$v":["Chcete prevziať ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Prevziať"},{"$i":"edit-group-header","$v":"Úprava skupiny"},{"$i":"gaia-grid-stop-download-title","$v":["Zastaviť ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Naozaj chcete zastaviť prebiehajúce preberanie?"},{"$i":"gaia-grid-stop-download-action","$v":"Zastaviť"},{"$i":"gaia-grid-resume-download-title","$v":"Reštartovanie preberania"},{"$i":"gaia-grid-resume-download-body","$v":["Chcete prevziať ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Prevziať"},{"$i":"gaia-grid-cancel","$v":"Zrušiť"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Rozbaliť skupinu"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Zbaliť skupinu"},{"$i":"gaia-grid-enter-group-name","$v":"Zadajte názov skupiny"},{"$i":"gaia-menu-cancel","$v":"Zrušiť"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Kërkoni ose jepni një adresë"},{"$i":"delete-title","$v":["Fshijeni ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," dhe krejt të dhënat e tij do të fshihen."]},{"$i":"delete","$v":"Fshije"},{"$i":"cancel","$v":"Anulojeni"},{"$i":"homescreen-settings","$v":"Rregullime Kreu"},{"$i":"change-wallpaper","$v":"Ndërroni Sfondin"},{"$i":"edit-mode","$v":"Përpunim"},{"$i":"edit-done","$v":"U bë"},{"$i":"stop-download-title","$v":["Ndaleni ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Doni të ndalet shkarkimi që po kryhet?"},{"$i":"stop-download-action","$v":"Ndale"},{"$i":"resume-download-title","$v":"Riniseni Shkarkimin"},{"$i":"resume-download-body","$v":["Doni të shkarkohet ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Shkarkoje"},{"$i":"edit-group-header","$v":"Përpunoni grupin"},{"$i":"gaia-grid-stop-download-title","$v":["Ndaleni ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Doni të ndalet shkarkimi që po kryhet?"},{"$i":"gaia-grid-stop-download-action","$v":"Ndale"},{"$i":"gaia-grid-resume-download-title","$v":"Rinisni Shkarkimin"},{"$i":"gaia-grid-resume-download-body","$v":["Doni të shkarkohet ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Shkarkoje"},{"$i":"gaia-grid-cancel","$v":"Anulojeni"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Zgjeroje grupin"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Tkurre grupin"},{"$i":"gaia-grid-enter-group-name","$v":"Jepni emër grupi"},{"$i":"gaia-menu-cancel","$v":"Anulojeni"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Појам или адреса"},{"$i":"delete-title","$v":["Обриши ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," и сви његови подаци ће бити обрисани."]},{"$i":"delete","$v":"Обриши"},{"$i":"cancel","$v":"Откажи"},{"$i":"homescreen-settings","$v":"Поставке почетног екрана"},{"$i":"change-wallpaper","$v":"Промени позадинску слику"},{"$i":"edit-mode","$v":"Уређивање"},{"$i":"edit-done","$v":"Готово"},{"$i":"stop-download-title","$v":["Заустави ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Да ли желите да зауставите преузимање?"},{"$i":"stop-download-action","$v":"Заустави"},{"$i":"resume-download-title","$v":"Рестартуј преузимање"},{"$i":"resume-download-body","$v":["Да ли желите да преузмете ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Преузми"},{"$i":"edit-group-header","$v":"Уреди групу"},{"$i":"gaia-grid-stop-download-title","$v":["Заустави ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Да ли желите да зауставите преузимање?"},{"$i":"gaia-grid-stop-download-action","$v":"Заустави"},{"$i":"gaia-grid-resume-download-title","$v":"Рестартуј преузимање"},{"$i":"gaia-grid-resume-download-body","$v":["Да ли желите да преузмете ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Преузми"},{"$i":"gaia-grid-cancel","$v":"Откажи"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Прошири групу"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Скупи групу"},{"$i":"gaia-grid-enter-group-name","$v":"Унесите име групе"},{"$i":"gaia-menu-cancel","$v":"Откажи"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Pojam ili adresa"},{"$i":"delete-title","$v":["Obriši ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," i svi njegovi podaci će biti obrisani."]},{"$i":"delete","$v":"Obriši"},{"$i":"cancel","$v":"Otkaži"},{"$i":"homescreen-settings","$v":"Postavke početnog ekrana"},{"$i":"change-wallpaper","$v":"Promeni pozadinsku sliku"},{"$i":"edit-mode","$v":"Uređivanje"},{"$i":"edit-done","$v":"Gotovo"},{"$i":"stop-download-title","$v":["Zaustavi ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Da li želite da zaustavite preuzimanje?"},{"$i":"stop-download-action","$v":"Zaustavi"},{"$i":"resume-download-title","$v":"Restartuj preuzimanje"},{"$i":"resume-download-body","$v":["Da li želite da preuzmete ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Preuzmi"},{"$i":"edit-group-header","$v":"Uredi grupu"},{"$i":"gaia-grid-stop-download-title","$v":["Zaustavi ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Da li želite da zaustavite preuzimanje?"},{"$i":"gaia-grid-stop-download-action","$v":"Zaustavi"},{"$i":"gaia-grid-resume-download-title","$v":"Restartuj preuzimanje"},{"$i":"gaia-grid-resume-download-body","$v":["Da li želite da preuzmete ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Preuzmi"},{"$i":"gaia-grid-cancel","$v":"Otkaži"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Proširi grupu"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Skupi grupu"},{"$i":"gaia-grid-enter-group-name","$v":"Unesite ime grupe"},{"$i":"gaia-menu-cancel","$v":"Otkaži"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Sök eller ange adress"},{"$i":"delete-title","$v":["Ta bort ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," och all dess data kommer att tas bort."]},{"$i":"delete","$v":"Ta bort"},{"$i":"cancel","$v":"Avbryt"},{"$i":"homescreen-settings","$v":"Inställningar hemskärm"},{"$i":"change-wallpaper","$v":"Ändra bakgrundsbild"},{"$i":"edit-mode","$v":"Redigera"},{"$i":"edit-done","$v":"Klar"},{"$i":"stop-download-title","$v":["Avbryt ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"Vill du avbryta pågående nedladdning?"},{"$i":"stop-download-action","$v":"Avbryt"},{"$i":"resume-download-title","$v":"Återuppta nedladdning"},{"$i":"resume-download-body","$v":["Vill du hämta ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"Hämta"},{"$i":"edit-group-header","$v":"Redigera grupp"},{"$i":"gaia-grid-stop-download-title","$v":["Avbryt ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"Vill du avbryta pågående nedladdning??"},{"$i":"gaia-grid-stop-download-action","$v":"Avbryt"},{"$i":"gaia-grid-resume-download-title","$v":"Återuppta nedladdning"},{"$i":"gaia-grid-resume-download-body","$v":["Vill du hämta ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"gaia-grid-resume-download-action","$v":"Hämta"},{"$i":"gaia-grid-cancel","$v":"Avbryt"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Expandera grupp"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Minimera grupp"},{"$i":"gaia-grid-enter-group-name","$v":"Ange ett gruppnamn"},{"$i":"gaia-menu-cancel","$v":"Avbryt"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"Arama yap veya adres gir"},{"$i":"delete-title","$v":[{"t":"idOrVar","v":"name"}," uygulamasını sil"]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," ve tüm verileri silinecek."]},{"$i":"delete","$v":"Sil"},{"$i":"cancel","$v":"İptal"},{"$i":"homescreen-settings","$v":"Ana ekran ayarları"},{"$i":"change-wallpaper","$v":"Duvar kâğıdını değiştir"},{"$i":"edit-mode","$v":"Düzenle"},{"$i":"edit-done","$v":"Bitti"},{"$i":"stop-download-title","$v":[{"t":"idOrVar","v":"name"}," indirmesini durdur"]},{"$i":"stop-download-body","$v":"Devam eden indirmeyi durdurmak istiyor musunuz?"},{"$i":"stop-download-action","$v":"Durdur"},{"$i":"resume-download-title","$v":"İndirmeyi yeniden başlat"},{"$i":"resume-download-body","$v":[{"t":"idOrVar","v":"name"}," uygulamasını indirmek istiyor musunuz?"]},{"$i":"resume-download-action","$v":"İndir"},{"$i":"edit-group-header","$v":"Grubu düzenle"},{"$i":"gaia-grid-stop-download-title","$v":[{"t":"idOrVar","v":"name"}," indirmesini durdur"]},{"$i":"gaia-grid-stop-download-body","$v":"Devam eden indirmeyi durdurmak istiyor musunuz?"},{"$i":"gaia-grid-stop-download-action","$v":"Durdur"},{"$i":"gaia-grid-resume-download-title","$v":"İndirmeyi yeniden başlat"},{"$i":"gaia-grid-resume-download-body","$v":[{"t":"idOrVar","v":"name"}," indirilsin mi?"]},{"$i":"gaia-grid-resume-download-action","$v":"İndir"},{"$i":"gaia-grid-cancel","$v":"İptal"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"Grubu genişlet"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"Grubu daralt"},{"$i":"gaia-grid-enter-group-name","$v":"Bir grup adı girin"},{"$i":"gaia-menu-cancel","$v":"İptal"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"搜索或输入网址"},{"$i":"delete-title","$v":["删除“",{"t":"idOrVar","v":"name"},"”"]},{"$i":"delete-body","$v":["“",{"t":"idOrVar","v":"name"},"”及其所有数据将被删除。"]},{"$i":"delete","$v":"删除"},{"$i":"cancel","$v":"取消"},{"$i":"homescreen-settings","$v":"主屏幕设置"},{"$i":"change-wallpaper","$v":"更改壁纸"},{"$i":"edit-mode","$v":"编辑"},{"$i":"edit-done","$v":"完成"},{"$i":"stop-download-title","$v":["停止 ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"您确定要停止正在进行的下载吗?"},{"$i":"stop-download-action","$v":"停止"},{"$i":"resume-download-title","$v":"重新开始下载"},{"$i":"resume-download-body","$v":["你是否想下载 ",{"t":"idOrVar","v":"name"},"?"]},{"$i":"resume-download-action","$v":"下载"},{"$i":"edit-group-header","$v":"编辑分组"},{"$i":"gaia-grid-stop-download-title","$v":["停止 ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"您确定要停止正在进行的下载吗?"},{"$i":"gaia-grid-stop-download-action","$v":"停止"},{"$i":"gaia-grid-resume-download-title","$v":"重新开始下载"},{"$i":"gaia-grid-resume-download-body","$v":["你是否想下载 ",{"t":"idOrVar","v":"name"}," ?"]},{"$i":"gaia-grid-resume-download-action","$v":"下载"},{"$i":"gaia-grid-cancel","$v":"取消"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"展开分组"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"折叠分组"},{"$i":"gaia-grid-enter-group-name","$v":"请输入一个分组名称"},{"$i":"gaia-menu-cancel","$v":"取消"}]
|
||||
|
|
@ -0,0 +1 @@
|
|||
[{"$i":"search-or-enter-address","placeholder":"搜尋或輸入網址"},{"$i":"delete-title","$v":["刪除 ",{"t":"idOrVar","v":"name"}]},{"$i":"delete-body","$v":[{"t":"idOrVar","v":"name"}," 與其所有資料將會被刪除。"]},{"$i":"delete","$v":"刪除"},{"$i":"cancel","$v":"取消"},{"$i":"homescreen-settings","$v":"主畫面選項"},{"$i":"change-wallpaper","$v":"修改桌面背景"},{"$i":"edit-mode","$v":"編輯"},{"$i":"edit-done","$v":"完成"},{"$i":"stop-download-title","$v":["停止 ",{"t":"idOrVar","v":"name"}]},{"$i":"stop-download-body","$v":"您想要停止正在進行中的下載嗎?"},{"$i":"stop-download-action","$v":"停止"},{"$i":"resume-download-title","$v":"重新開始下載"},{"$i":"resume-download-body","$v":["想要下載 ",{"t":"idOrVar","v":"name"}," 嗎?"]},{"$i":"resume-download-action","$v":"下載"},{"$i":"edit-group-header","$v":"編輯群組"},{"$i":"gaia-grid-stop-download-title","$v":["停止 ",{"t":"idOrVar","v":"name"}]},{"$i":"gaia-grid-stop-download-body","$v":"您想要停止正在進行中的下載嗎?"},{"$i":"gaia-grid-stop-download-action","$v":"停止"},{"$i":"gaia-grid-resume-download-title","$v":"重新開始下載"},{"$i":"gaia-grid-resume-download-body","$v":["想要下載 ",{"t":"idOrVar","v":"name"}," 嗎?"]},{"$i":"gaia-grid-resume-download-action","$v":"下載"},{"$i":"gaia-grid-cancel","$v":"取消"},{"$i":"gaia-grid-toggle-collapsed","ariaLabel":"展開群組"},{"$i":"gaia-grid-toggle-expanded","ariaLabel":"摺疊群組"},{"$i":"gaia-grid-enter-group-name","$v":"輸入群組名稱"},{"$i":"gaia-menu-cancel","$v":"取消"}]
|
||||
1
assets/webapps/verticalhome.gaiamobile.org/manifest.webapp
Executable file
|
|
@ -0,0 +1 @@
|
|||
{"name":"Legacy Home Screen","description":"Gaia Home Screen.","launch_path":"/index.html","type":"certified","role":"homescreen","developer":{"name":"The Gaia Team","url":"https://github.com/mozilla-b2g/gaia"},"permissions":{"themeable":{},"mobileconnection":{},"open-remote-window":{},"webapps-manage":{},"systemXHR":{},"settings":{"access":"readwrite"},"moz-extremely-unstable-and-will-change-webcomponents":{}},"default_locale":"en-US","locales":{"ar":{"name":"الشاشة الرئيسية الواردة","description":"الشاشة الرئيسية لجايا"},"bg":{"name":"Legacy Home Screen","description":"Gaia Home Screen."},"bn-BD":{"name":"লেগ্যাসি হোম স্ক্রিন","description":"গাইয়া হোম স্ক্রিন"},"ca":{"name":"Pantalla d'inici antiga","description":"Pantalla d'inici del Gaia."},"cs":{"name":"Klasická domovská obrazovka","description":"Domovská obrazovka systému Gaia"},"da":{"name":"Ældre startskærm","description":"Gaia startskærm."},"de":{"name":"Startbildschirm","description":"Startbildschirm für Gaia"},"el":{"name":"Αρχική οθόνη","description":"Αρχική οθόνη Gaia"},"en-US":{"name":"Legacy Home Screen","description":"Gaia Home Screen."},"es":{"name":"Pantalla de inicio antigua","description":"Pantalla de inicio de Gaia."},"eu":{"name":"Hasiera-pantaila zaharra","description":"Gaia hasiera-pantaila."},"fr":{"name":"Ancien écran d’accueil","description":"Ancien écran d’accueil de Gaia."},"gl":{"name":"Pantalla inicial predeterminada","description":"Pantalla inicial de Gaia."},"hr":{"name":"Legacy Home Screen","description":"Gaia Home Screen."},"hu":{"name":"Legacy Home Screen","description":"Gaia kezdőképernyő"},"it":{"name":"Schermata principale legacy","description":"Schermata principale Gaia."},"ja":{"name":"従来のホーム画面","description":"Gaia のホーム画面"},"km":{"name":"Legacy Home Screen","description":"Gaia Home Screen."},"ko":{"name":"기존 홈 스크린","description":"Gaia 홈 스크린"},"lt":{"name":"Pradžios ekranas","description":"„Gaia“ pradžios ekranas"},"mk":{"name":"Legacy Home Screen","description":"Gaia Home Screen."},"ms":{"name":"Legacy Home Screen","description":"Gaia Home Screen."},"ne-NP":{"name":"Legacy Home Screen","description":"Gaia Home Screen."},"nl":{"name":"Oude startscherm","description":"Gaia-startscherm"},"pa":{"name":"ਮੁੱਖ ਸਕਰੀਨ","description":"ਗੀਗਾ ਮੁੱਖ ਸਕਰੀਨ"},"pl":{"name":"Ekran główny","description":"Ekran główny Gaia"},"pt-BR":{"name":"Tela inicial","description":"Tela inicial do Gaia"},"ro":{"name":"Legacy Home Screen","description":"Gaia Home Screen."},"ru":{"name":"Старый домашний экран","description":"Домашний экран Gaia"},"sk":{"name":"Úvodná obrazovka","description":"Úvodná obrazovka Gaia"},"sq":{"name":"Kryet e Dikurshme","description":"Kreu i Gaia-s"},"sr-Cyrl":{"name":"Првобитни почетни екран","description":"Gaia почетни екран"},"sr-Latn":{"name":"Prvobitni početni ekran","description":"Gaia početni ekran"},"sv-SE":{"name":"Hemskärm","description":"Gaia hemskärm"},"tr":{"name":"Legacy Home Screen","description":"Gaia Home Screen."},"zh-CN":{"name":"旧版主屏幕","description":"Gaia 主屏幕"},"zh-TW":{"name":"傳統主畫面","description":"Gaia 主畫面。"}},"icons":{"84":"/style/icons/vertical_84.png","126":"/style/icons/vertical_126.png","142":"/style/icons/vertical_142.png","189":"/style/icons/vertical_189.png","284":"/style/icons/vertical_284.png"},"orientation":"default","datastores-access":{"bookmarks_store":{"readonly":false,"description":"Display bookmarks"}},"datastores-owned":{"vertical_preferences_store":{"access":"readwrite","description":"Stores preferences"},"verticalhome_items_migration":{"access":"readwrite","description":"Stores grid item configuration"}},"connections":{"verticalhome-migrate":{"handler_path":"/index.html","description":"Exports settings and switches home screen","rules":{"minimumAccessLevel":"certified"}}},"origin":"app://verticalhome.gaiamobile.org","version":"2.5"}
|
||||
|
|
@ -0,0 +1 @@
|
|||
;window.COMPONENTS_BASE_URL='/shared/elements/';
|
||||
1686
assets/webapps/verticalhome.gaiamobile.org/shared/elements/gaia-header/dist/gaia-header.js
vendored
Normal file
|
|
@ -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 @@
|
|||
<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" viewBox="0 0 30 30"><path fill="#667174" fill-opacity=".7" d="M11.8,19.9l4.9-4.9l-4.9-4.9c0.3-0.5,0.6-1,0.9-1.3l5.5,5.5c0,0.3,0,0.5,0,0.8c0,0.3,0,0.5,0,0.8l-5.5,5.5 C12.4,20.9,12,20.5,11.8,19.9z"/></svg>
|
||||
|
After Width: | Height: | Size: 243 B |
|
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
/* global ComponentUtils */
|
||||
|
||||
window.GaiaButtons = (function(win) {
|
||||
// Extend from the HTMLElement prototype
|
||||
var proto = Object.create(HTMLElement.prototype);
|
||||
|
||||
// Allow baseurl to be overridden (used for demo page)
|
||||
var baseurl = window.GaiaButtonsBaseurl ||
|
||||
'/shared/elements/gaia_buttons/';
|
||||
|
||||
proto.createdCallback = function() {
|
||||
ComponentUtils.style.call(this, baseurl);
|
||||
};
|
||||
|
||||
// Register and return the constructor
|
||||
return document.registerElement('gaia-buttons', { prototype: proto });
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
/* ---------------------------------------
|
||||
* gaia-buttons:
|
||||
* Container for buttons e.g:
|
||||
* action menu, confirm, edit mode, FTU
|
||||
* --------------------------------------- */
|
||||
|
||||
gaia-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 7rem;
|
||||
box-sizing: border-box;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
gaia-buttons:not(.inline) {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
border-top: 0.1rem solid #e7e7e7;
|
||||
padding: 0;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
/* this 'end' padding must match the buttons 'start' margin */
|
||||
gaia-buttons:not(.inline):-moz-dir(ltr) { padding-right: 1.5rem; }
|
||||
gaia-buttons:not(.inline):-moz-dir(rtl) { padding-left: 1.5rem; }
|
||||
|
||||
gaia-buttons.inline a,
|
||||
gaia-buttons.inline button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner {
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a,
|
||||
button {
|
||||
position: relative;
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
width: 100%;
|
||||
height: 4rem;
|
||||
margin: 0;
|
||||
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-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
:-moz-dir(ltr) a,
|
||||
:-moz-dir(ltr) button {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
:-moz-dir(rtl) a,
|
||||
:-moz-dir(rtl) button {
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
|
||||
/* Recommend */
|
||||
a.recommend,
|
||||
button.recommend {
|
||||
background-color: #00caf2;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Danger */
|
||||
a.danger,
|
||||
button.danger {
|
||||
background-color: #e51e1e;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Pressed */
|
||||
a:active,
|
||||
button:active {
|
||||
background-color: #b2f2ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
a::-moz-selection,
|
||||
button::-moz-selection {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
a[aria-disabled="true"],
|
||||
button[disabled] {
|
||||
background-color: rgba(0,0,0,0.05);
|
||||
color: #c7c7c7;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
a[aria-disabled="true"].recommend,
|
||||
button[disabled].recommend {
|
||||
background-color: #97cbd5;
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
a[aria-disabled="true"].danger,
|
||||
button[disabled].danger {
|
||||
background-color: #eb7474;
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
a[aria-disabled="true"]::-moz-selection,
|
||||
button[disabled]::-moz-selection {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
/* Hidden */
|
||||
[hidden] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
a.icon,
|
||||
button.icon {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
a.icon:before,
|
||||
button.icon:before {
|
||||
content: "";
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -1.5rem;
|
||||
background: transparent no-repeat center center / 100% auto;
|
||||
}
|
||||
:-moz-dir(ltr) a.icon:before,
|
||||
:-moz-dir(ltr) button.icon:before { right: 0.5rem; }
|
||||
:-moz-dir(rtl) a.icon:before,
|
||||
:-moz-dir(rtl) button.icon:before { left: 0.5rem; }
|
||||
|
||||
a.icon-next:before,
|
||||
button.icon-next:before {
|
||||
background-size: 3rem;
|
||||
}
|
||||
:-moz-dir(ltr) a.icon-next:before,
|
||||
:-moz-dir(ltr) button.icon-next:before {
|
||||
background-image: url(images/right-light.svg);
|
||||
}
|
||||
:-moz-dir(rtl) a.icon-next:before,
|
||||
:-moz-dir(rtl) button.icon-next:before {
|
||||
background-image: url(images/left-light.svg);
|
||||
}
|
||||
|
||||
a.icon-previous:before,
|
||||
button.icon-previous:before {
|
||||
background-size: 3rem;
|
||||
}
|
||||
:-moz-dir(ltr) a.icon-previous:before,
|
||||
:-moz-dir(ltr) button.icon-previous:before {
|
||||
left: 0.5rem;
|
||||
background-image: url(images/left-light.svg);
|
||||
}
|
||||
:-moz-dir(rtl) a.icon-previous:before,
|
||||
:-moz-dir(rtl) button.icon-previous:before {
|
||||
right: 0.5rem;
|
||||
background-image: url(images/right-light.svg);
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
SKIN: dark
|
||||
----------------------------------------------------------------- */
|
||||
|
||||
gaia-buttons[skin="dark"] {
|
||||
background: #4d4d4d;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Pressed */
|
||||
[skin="dark"] a:active,
|
||||
[skin="dark"] button:active {
|
||||
background-color: #00aacc;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
[skin="dark"] a[aria-disabled="true"],
|
||||
[skin="dark"] button[disabled] {
|
||||
background-color: #565656;
|
||||
color: rgba(255,255,255,0.4);
|
||||
}
|
||||
|
||||
[skin="dark"] a[aria-disabled="true"].recommend,
|
||||
[skin="dark"] button[disabled].recommend {
|
||||
background-color: #006579;
|
||||
}
|
||||
|
||||
[skin="dark"] a[aria-disabled="true"].danger,
|
||||
[skin="dark"] button[disabled].danger {
|
||||
background-color: #730f0f;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
Transitions
|
||||
----------------------------------------------------------------- */
|
||||
|
||||
[transition] {
|
||||
display: flex;
|
||||
transition: visibility var(--transition-duration);
|
||||
}
|
||||
|
||||
[transition][hidden] {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
[transition="slide"] {
|
||||
transform: translateY(0);
|
||||
transition: transform var(--transition-duration) ease,
|
||||
visibility var(--transition-duration);
|
||||
}
|
||||
|
||||
[transition="slide"][hidden] {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
[transition="fade"] {
|
||||
opacity: 1;
|
||||
transition: opacity var(--transition-duration) ease,
|
||||
visibility var(--transition-duration);
|
||||
}
|
||||
|
||||
[transition="fade"][hidden] {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
RESPONSIVE: tablet
|
||||
----------------------------------------------------------------- */
|
||||
|
||||
@media (min-width: 768px) {
|
||||
|
||||
gaia-buttons {
|
||||
height: 10rem;
|
||||
}
|
||||
|
||||
gaia-buttons:not(.inline) {
|
||||
border-top-width: 0.2rem;
|
||||
}
|
||||
/* this 'end' padding must match the buttons 'start' margin */
|
||||
gaia-buttons:not(.inline):-moz-dir(ltr) { padding-right: 3rem; }
|
||||
gaia-buttons:not(.inline):-moz-dir(rtl) { padding-left: 3rem; }
|
||||
|
||||
a,
|
||||
button {
|
||||
font-size: 2rem;
|
||||
height: 5rem;
|
||||
line-height: 5rem;
|
||||
border-radius: 2.5rem;
|
||||
max-width: 40rem;
|
||||
}
|
||||
:-moz-dir(ltr) a,
|
||||
:-moz-dir(ltr) button {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
:-moz-dir(rtl) a,
|
||||
:-moz-dir(rtl) button {
|
||||
margin-right: 3rem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
'use strict';
|
||||
/* global ComponentUtils */
|
||||
|
||||
/**
|
||||
* The gaia-confirm component displays a dialog in which the user has a
|
||||
* choice to confirm or cancel the action. It may be displayed along with a
|
||||
* title, description, and image. Buttons may also be configured.
|
||||
* @requires GaiaButtons
|
||||
*/
|
||||
window.GaiaConfirm = (function(win) {
|
||||
// Extend from the HTMLElement prototype
|
||||
var proto = Object.create(HTMLElement.prototype);
|
||||
|
||||
// Allow baseurl to be overridden (used for demo page)
|
||||
var baseurl = window.GaiaConfirmBaseurl ||
|
||||
'/shared/elements/gaia_confirm/';
|
||||
|
||||
/**
|
||||
preventDefault and prevent other listeners from hearing abut changes to a
|
||||
particular event object.
|
||||
|
||||
@param {Array[Element]|Null} unless a list of elements to allow events to hit.
|
||||
@param {Event} event triggered by addEventListener, etc...
|
||||
*/
|
||||
function eatEvent(unless, event) {
|
||||
// prevent handlers from everything else unless the target is on the list.
|
||||
if (unless && unless.indexOf(event.target) !== -1) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
proto.createdCallback = function() {
|
||||
var shadow = this.createShadowRoot();
|
||||
this._template = template.content.cloneNode(true);
|
||||
|
||||
shadow.appendChild(this._template);
|
||||
ComponentUtils.style.call(this, baseurl);
|
||||
|
||||
var confirm = this.querySelector('gaia-buttons .confirm');
|
||||
var cancel = this.querySelector('gaia-buttons .cancel');
|
||||
|
||||
if (confirm) {
|
||||
confirm.addEventListener('click', (e) => {
|
||||
eatEvent(null, e);
|
||||
this.dispatchEvent(new CustomEvent('confirm'));
|
||||
});
|
||||
}
|
||||
|
||||
if (cancel) {
|
||||
cancel.addEventListener('click', (e) => {
|
||||
eatEvent(null, e);
|
||||
this.dispatchEvent(new CustomEvent('cancel'));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var template = document.createElement('template');
|
||||
template.innerHTML = `<form role="dialog" class="confirm">
|
||||
<section>
|
||||
<content select="h1"></content>
|
||||
<content select="p"></content>
|
||||
</section>
|
||||
<content select="gaia-buttons">
|
||||
</content>
|
||||
</form>`;
|
||||
|
||||
// Register and return the constructor
|
||||
return document.registerElement('gaia-confirm', { prototype: proto });
|
||||
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/* ----------------------------------
|
||||
* Confirm
|
||||
* ---------------------------------- */
|
||||
|
||||
/* Main dialog setup */
|
||||
gaia-confirm {
|
||||
background: #2d2d2d;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding-bottom: 7rem;
|
||||
font-size: 0;
|
||||
text-align: start;
|
||||
/* 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;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
transition: transform ease-in-out 0.3s, visibility 0.3s;
|
||||
/**
|
||||
magic number ideally to place confirm dialogs on top.
|
||||
*/
|
||||
z-index: 2147483646;
|
||||
}
|
||||
|
||||
gaia-confirm[hidden] {
|
||||
transform: translateY(100%);
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.confirm section {
|
||||
height: 100%;
|
||||
font-weight: 300;
|
||||
font-size: 2.2rem;
|
||||
color: #FAFAFA;
|
||||
padding: 0 1.5rem;
|
||||
box-sizing: padding-box;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
max-height: 100%;
|
||||
vertical-align: middle;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: normal;
|
||||
font-size: 1.6rem;
|
||||
line-height: 1.5em;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
padding: 1rem 1.5rem 0;
|
||||
overflow: hidden;
|
||||
max-height: 7rem;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/* Specific component code */
|
||||
p {
|
||||
word-wrap: break-word;
|
||||
margin: 1rem 0 0;
|
||||
padding: 1rem 1.5rem;
|
||||
border-top: 0.1rem solid #686868;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
p img {
|
||||
margin-inline-end: 2rem;
|
||||
}
|
||||
p img:-moz-dir(ltr) { float: left; }
|
||||
p img:-moz-dir(rtl) { float: right; }
|
||||
|
||||
p strong {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
p small {
|
||||
font-size: 1.4rem;
|
||||
font-weight: normal;
|
||||
color: #cbcbcb;
|
||||
display: block;
|
||||
}
|
||||
|
||||
dl {
|
||||
border-top: 0.1rem solid #686868;
|
||||
margin: 1rem 0 0;
|
||||
overflow: hidden;
|
||||
padding-top: 1rem;
|
||||
font-size: 1.6rem;
|
||||
line-height: 2.2rem;
|
||||
}
|
||||
|
||||
dl > dt {
|
||||
clear: both;
|
||||
width: 7rem;
|
||||
padding-inline-start: 1.5rem;
|
||||
font-weight: 500;
|
||||
text-align: start;
|
||||
}
|
||||
dl > dt:-moz-dir(ltr) { float: left; }
|
||||
dl > dt:-moz-dir(rtl) { float: right; }
|
||||
|
||||
dl > dd {
|
||||
padding-inline-end: 1.5rem;
|
||||
font-weight: 300;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: top;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
figure img {
|
||||
padding-inline-end: 1.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
figure figcaption {
|
||||
font-size: 2.1rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 2rem 1.5rem;
|
||||
border-top: 0.1rem solid #686868;
|
||||
list-style: none;
|
||||
font-size: 1.6rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
ul li {
|
||||
word-wrap: break-word;
|
||||
line-height: 2rem;
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
ul li:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
ul li ul {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 312 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,844 @@
|
|||
'use strict';
|
||||
/* global devicePixelRatio */
|
||||
/* global GaiaGrid */
|
||||
|
||||
(function(exports) {
|
||||
|
||||
const ACTIVE_SCALE = 1.4;
|
||||
|
||||
/* This is an alternative delay used to initiate icon movement when in edit
|
||||
* mode. The normal contextmenu delay is too long once we're in edit mode
|
||||
* and causes user confusion, but a short delay globally would cause too many
|
||||
* accidental triggers of edit mode.
|
||||
*/
|
||||
const EDIT_LONG_PRESS_DELAY = 200;
|
||||
|
||||
/* The movement threshold to use for the above synthetic long-press. */
|
||||
const EDIT_LONG_PRESS_THRESHOLD = 4 * devicePixelRatio;
|
||||
|
||||
/* This delay is the time passed once users stop the finger over an icon and
|
||||
* the rearrange is performed */
|
||||
const REARRANGE_DELAY = 30;
|
||||
|
||||
/* The page is scrolled via javascript if an icon is being moved, and is
|
||||
* within a length of a page edge configured by this value */
|
||||
const EDGE_PAGE_THRESHOLD = 50;
|
||||
|
||||
/* This is the delay before calling finish when handling touchend. */
|
||||
const TOUCH_END_FINISH_DELAY = 20;
|
||||
|
||||
/* The maximum frequency with which the grid will be rearranged in response
|
||||
* to the item position changing, in ms.
|
||||
*/
|
||||
const REARRANGE_FREQUENCY = 100;
|
||||
|
||||
/* The amount of cool-down time after a rearrange animation. To avoid
|
||||
* rearranging too frequently and causing jank and user confusion.
|
||||
*/
|
||||
const REARRANGE_COOLDOWN = 750;
|
||||
|
||||
const SCREEN_HEIGHT = window.innerHeight;
|
||||
|
||||
const scrollStep = Math.round(SCREEN_HEIGHT / EDGE_PAGE_THRESHOLD);
|
||||
|
||||
/* The scroll step will be 5 times bigger over the edge */
|
||||
const maxScrollStepFactor = 5;
|
||||
|
||||
function DragDrop(gridView) {
|
||||
this.gridView = gridView;
|
||||
this.container = gridView.element;
|
||||
this.scrollable = document.documentElement;
|
||||
this.container.addEventListener('touchstart', this);
|
||||
this.container.addEventListener('touchmove', this);
|
||||
this.container.addEventListener('touchend', this);
|
||||
window.addEventListener('touchcancel', this);
|
||||
this.container.addEventListener('click', this);
|
||||
this.container.addEventListener('contextmenu', this);
|
||||
}
|
||||
|
||||
DragDrop.prototype = {
|
||||
|
||||
/**
|
||||
* The current touchmove target.
|
||||
* @type {DomElement}
|
||||
*/
|
||||
target: null,
|
||||
|
||||
/**
|
||||
* The edit-mode long-press timeout
|
||||
*/
|
||||
longPressTimeout: null,
|
||||
|
||||
/**
|
||||
* The position of the first touchstart of the current event block
|
||||
*/
|
||||
touchStart: { x: 0, y: 0, screenX: 0, screenY: 0 },
|
||||
|
||||
/**
|
||||
* If we have moved an icon, this indicates that we need to save the state
|
||||
* @type {boolean}
|
||||
*/
|
||||
dirty: false,
|
||||
|
||||
/**
|
||||
* Whether or not we are in edit mode.
|
||||
* @type {boolean}
|
||||
*/
|
||||
inEditMode: false,
|
||||
|
||||
/**
|
||||
* The item being hovered over.
|
||||
* @type {GaiaGrid.GridItem}
|
||||
*/
|
||||
hoverItem: null,
|
||||
|
||||
/**
|
||||
* The group being hovered over.
|
||||
* @type {GaiaGrid.Group}
|
||||
*/
|
||||
hoverGroup: null,
|
||||
|
||||
/*
|
||||
* An element that's aligned to the top of the grid and should be
|
||||
* considered as obscuring the grid when in edit mode.
|
||||
*/
|
||||
editHeaderElement: null,
|
||||
|
||||
/**
|
||||
* The timeout used to rearrange the grid during dragging.
|
||||
*/
|
||||
rearrangeGridTimeout: null,
|
||||
|
||||
/**
|
||||
* The time of the last reposition call.
|
||||
*/
|
||||
lastRepositionTime: 0,
|
||||
|
||||
/**
|
||||
* Returns the maximum active scale value.
|
||||
*/
|
||||
get activeScale() {
|
||||
return ACTIVE_SCALE;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if we are currently dragging an icon.
|
||||
*/
|
||||
get inDragAction() {
|
||||
return this.target && this.target.classList.contains('active');
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the delay before calling finish in response to a touch-end event.
|
||||
*/
|
||||
get touchEndFinishDelay() {
|
||||
return TOUCH_END_FINISH_DELAY;
|
||||
},
|
||||
|
||||
/**
|
||||
* Begins the drag/drop interaction.
|
||||
* Enlarges the icon.
|
||||
* Sets additional data to make the touchmove handler faster.
|
||||
*/
|
||||
begin: function(e) {
|
||||
// Stop icon launching while we are in active state
|
||||
this.gridView.stop();
|
||||
window.dispatchEvent(new CustomEvent('gaiagrid-dragdrop-begin'));
|
||||
|
||||
this.hoverItem = null;
|
||||
this.rearrangeDelay = null;
|
||||
this.doRearrange = null;
|
||||
this.enterEditMode();
|
||||
this.container.classList.add('dragging');
|
||||
this.icon.scale = ACTIVE_SCALE;
|
||||
this.icon.setActive(true);
|
||||
this.container.parentNode.style.overflow = 'hidden';
|
||||
|
||||
// Work around e.pageX/e.pageY being null (to make it easier to work with
|
||||
// injected events, or old versions of Marionette)
|
||||
this.initialPageX = (typeof e.pageX === 'undefined') ?
|
||||
this.icon.x : e.pageX;
|
||||
this.initialPageY = (typeof e.pageY === 'undefined') ?
|
||||
this.icon.y : e.pageY;
|
||||
this.currentTouch = {
|
||||
pageX: this.initialPageX,
|
||||
pageY: this.initialPageY
|
||||
};
|
||||
|
||||
var items = this.gridView.items;
|
||||
var lastElement = items[items.length - 1];
|
||||
this.maxScroll = lastElement.y + lastElement.pixelHeight +
|
||||
(this.icon.pixelHeight * ACTIVE_SCALE);
|
||||
|
||||
// If this is a group, or the sole icon in a group, make sure the
|
||||
// surrounding groups are marked as invalid-drop so you can't initiate a
|
||||
// move that would have no result.
|
||||
var itemIndex = this.icon.detail.index;
|
||||
if (this.icon.detail.type === 'divider') {
|
||||
this.icon.element.classList.add('invalid-drop');
|
||||
if (itemIndex > 0) {
|
||||
for (var i = itemIndex - 1; i >= 0; i--) {
|
||||
var item = items[i];
|
||||
if (item.detail.type === 'divider') {
|
||||
item.element.classList.add('invalid-drop');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var itemBefore = itemIndex ? items[itemIndex - 1] : null;
|
||||
var itemAfter = items[itemIndex + 1];
|
||||
|
||||
if ((itemAfter.detail.type === 'placeholder' ||
|
||||
itemAfter.detail.type === 'divider') &&
|
||||
(!itemBefore || itemBefore.detail.type === 'divider')) {
|
||||
if (itemBefore) {
|
||||
itemBefore.element.classList.add('invalid-drop');
|
||||
}
|
||||
var group, groupIndex = itemIndex;
|
||||
do {
|
||||
group = items[++groupIndex];
|
||||
} while (group.detail.type !== 'divider');
|
||||
group.element.classList.add('invalid-drop');
|
||||
}
|
||||
}
|
||||
|
||||
// Redraw the icon at the new position and scale
|
||||
this.updateIconPosition();
|
||||
|
||||
// Rearrange grid to highlight the group underneath the icon
|
||||
this.rearrangeGrid();
|
||||
},
|
||||
|
||||
finish: function() {
|
||||
// Complete the repositioning timeout
|
||||
if (this.rearrangeGridTimeout !== null) {
|
||||
this.rearrangeGrid();
|
||||
}
|
||||
|
||||
// Remove the dragging property after the icon has transitioned into
|
||||
// place to avoid jank due to animations starting that are disabled
|
||||
// when dragging.
|
||||
this.icon.element.addEventListener('transitionend', this);
|
||||
this.currentTouch = null;
|
||||
|
||||
if (this.doRearrange !== null) {
|
||||
if (this.rearrangeDelay) {
|
||||
clearTimeout(this.rearrangeDelay);
|
||||
}
|
||||
this.doRearrange.call(this);
|
||||
} else {
|
||||
this.icon.requestAttention();
|
||||
}
|
||||
|
||||
// Hand back responsibility to Grid view to render the dragged item.
|
||||
this.icon.scale = 1;
|
||||
this.icon.setActive(false);
|
||||
this.icon.element.classList.remove('hovering');
|
||||
this.target = null;
|
||||
|
||||
this.gridView.render();
|
||||
|
||||
// Save icon state if we need to
|
||||
if (this.dirty) {
|
||||
window.dispatchEvent(new CustomEvent('gaiagrid-saveitems'));
|
||||
}
|
||||
this.dirty = false;
|
||||
|
||||
setTimeout(function nextTick() {
|
||||
this.gridView.start();
|
||||
window.dispatchEvent(new CustomEvent('gaiagrid-dragdrop-finish'));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
finalize: function() {
|
||||
this.container.parentNode.style.overflow = '';
|
||||
this.container.classList.remove('dragging');
|
||||
this.container.classList.remove('hover-over-top');
|
||||
if (this.icon) {
|
||||
this.icon.element.removeEventListener('transitionend', this);
|
||||
this.icon = null;
|
||||
}
|
||||
if (this.hoverItem) {
|
||||
this.hoverItem.element.classList.remove('hovered');
|
||||
this.hoverItem = null;
|
||||
}
|
||||
if (this.hoverGroup) {
|
||||
this.hoverGroup.element.classList.remove('drop-target');
|
||||
this.hoverGroup = null;
|
||||
}
|
||||
for (var i = 0, iLen = this.gridView.items.length;
|
||||
i < iLen; i++) {
|
||||
var item = this.gridView.items[i];
|
||||
item.element.classList.remove('invalid-drop');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The closer to edge the faster (bigger step).
|
||||
** Distance 0px -> 5 times faster
|
||||
** Distance 25px -> 2.5 times faster
|
||||
** Distance 50px (EDGE_PAGE_THRESHOLD) -> 0 times
|
||||
*/
|
||||
getScrollStep: function(distanceToEdge) {
|
||||
var factor = maxScrollStepFactor;
|
||||
|
||||
if (distanceToEdge > 0) {
|
||||
factor *= ((EDGE_PAGE_THRESHOLD - distanceToEdge) /
|
||||
EDGE_PAGE_THRESHOLD);
|
||||
}
|
||||
|
||||
return Math.round(scrollStep * factor);
|
||||
},
|
||||
|
||||
/**
|
||||
* Positions the dragged icon, rearranges the grid and scrolls the page if
|
||||
* needed.
|
||||
* The page is scrolled via javascript if an icon is being moved,
|
||||
* and is within a percentage of a page edge.
|
||||
*/
|
||||
positionAndScrollIfNeeded: function() {
|
||||
var touch = this.currentTouch;
|
||||
if (!touch || !this.inDragAction) {
|
||||
this.isScrolling = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var scrollStep;
|
||||
var docScroll = this.scrollable.scrollTop;
|
||||
var distanceFromTop = Math.abs(touch.pageY - docScroll);
|
||||
var distanceFromHeader = distanceFromTop -
|
||||
(this.editHeaderElement ? this.editHeaderElement.clientHeight : 0);
|
||||
this.isScrolling = true;
|
||||
|
||||
if (distanceFromTop > SCREEN_HEIGHT - EDGE_PAGE_THRESHOLD) {
|
||||
var maxY = this.maxScroll;
|
||||
scrollStep = this.getScrollStep(SCREEN_HEIGHT - distanceFromTop);
|
||||
// We cannot exceed the maximum scroll value
|
||||
if (touch.pageY >= maxY || maxY - touch.pageY < scrollStep) {
|
||||
this.isScrolling = false;
|
||||
}
|
||||
} else if (touch.pageY > 0 && distanceFromHeader < EDGE_PAGE_THRESHOLD) {
|
||||
// We cannot go below the minimum scroll value
|
||||
scrollStep = -this.getScrollStep(distanceFromHeader);
|
||||
scrollStep = Math.max(scrollStep, -this.scrollable.scrollTop);
|
||||
if (scrollStep >= 0) {
|
||||
this.isScrolling = false;
|
||||
}
|
||||
} else {
|
||||
this.isScrolling = false;
|
||||
}
|
||||
|
||||
if (!this.isScrolling) {
|
||||
this.updateIconPosition();
|
||||
this.deferredRearrangeGrid();
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateIconPosition();
|
||||
this.scrollable.scrollTop += scrollStep;
|
||||
touch.pageY += scrollStep;
|
||||
|
||||
exports.requestAnimationFrame(this.positionAndScrollIfNeeded.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlights the group of the given icon index, or the group if the index
|
||||
* belongs to a group.
|
||||
* @param {Integer} index The grid index of the icon or group.
|
||||
*/
|
||||
highlightGroup: function(index) {
|
||||
for (var i = index, iLen = this.gridView.items.length;
|
||||
i < iLen; i++) {
|
||||
var item = this.gridView.items[i];
|
||||
if (item.detail.type === 'divider') {
|
||||
if (this.hoverGroup != item) {
|
||||
if (this.hoverGroup) {
|
||||
this.hoverGroup.element.classList.remove('drop-target');
|
||||
}
|
||||
this.hoverGroup = item;
|
||||
item.element.classList.add('drop-target');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
inFirstGroup: function(index) {
|
||||
for (var i = index; i >= 0; i--) {
|
||||
if (this.gridView.items[i].detail.type === 'divider') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Positions an icon on the grid using the current touch coordinates.
|
||||
*/
|
||||
updateIconPosition: function() {
|
||||
var oldX = this.icon.x;
|
||||
var oldY = this.icon.y;
|
||||
var newX = this.currentTouch.pageX - (this.initialPageX - this.icon.x);
|
||||
var newY = this.currentTouch.pageY - (this.initialPageY - this.icon.y);
|
||||
|
||||
// Adjust new icon coordinates for the slightly inflated scale so that
|
||||
// it appears centered around the touch point. Dividers aren't scaled
|
||||
// during dragging.
|
||||
if (this.icon.detail.type !== 'divider') {
|
||||
newX = newX - ((this.icon.scale * this.gridView.layout.gridItemWidth) -
|
||||
this.gridView.layout.gridItemWidth) / 2;
|
||||
newY = newY - ((this.icon.scale * this.icon.pixelHeight) -
|
||||
this.icon.pixelHeight) / 2;
|
||||
}
|
||||
|
||||
this.icon.setCoordinates(newX, newY);
|
||||
this.icon.render();
|
||||
this.icon.setCoordinates(oldX, oldY);
|
||||
},
|
||||
|
||||
/**
|
||||
* Will call rearrangeGrid after a short period, calculated based on how
|
||||
* recently the grid was last rearranged.
|
||||
*/
|
||||
deferredRearrangeGrid: function() {
|
||||
if (this.rearrangeGridTimeout !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var delay = Math.max(
|
||||
REARRANGE_FREQUENCY, REARRANGE_COOLDOWN -
|
||||
Math.max(0, Date.now() - this.lastRepositionTime));
|
||||
this.rearrangeGridTimeout = setTimeout(() => {
|
||||
this.rearrangeGridTimeout = null;
|
||||
this.rearrangeGrid();
|
||||
}, delay);
|
||||
},
|
||||
|
||||
/**
|
||||
* Rearranges the grid icons and groups based on the current position of
|
||||
* the dragged icon.
|
||||
*/
|
||||
rearrangeGrid: function() {
|
||||
if (this.rearrangeGridTimeout !== null) {
|
||||
clearTimeout(this.rearrangeGridTimeout);
|
||||
this.rearrangeGridTimeout = null;
|
||||
}
|
||||
|
||||
if (this.isScrolling) {
|
||||
// We don't want the grid to shift while we're auto-scrolling
|
||||
return;
|
||||
}
|
||||
|
||||
var iconIsDivider = this.icon.detail.type === 'divider';
|
||||
var pageX = this.currentTouch.pageX - (this.initialPageX - this.icon.x);
|
||||
var pageY = this.currentTouch.pageY - (this.initialPageY - this.icon.y);
|
||||
|
||||
// Reposition in the icons array if necessary.
|
||||
// Find the icon with the closest X/Y position of the move,
|
||||
// and insert ours before it.
|
||||
var foundIndex = 0;
|
||||
var insertDividerAtTop = !this.gridView.config.features.disableSections;
|
||||
pageX += this.gridView.layout.gridItemWidth / 2;
|
||||
pageY += this.icon.pixelHeight / 2;
|
||||
if (pageY >= 0) {
|
||||
foundIndex =
|
||||
this.gridView.getNearestItemIndex(pageX, pageY, iconIsDivider);
|
||||
|
||||
// If we're dragging a group over the first icon, a divider will
|
||||
// be inserted at the top.
|
||||
if (!(iconIsDivider && foundIndex === 0)) {
|
||||
this.container.classList.remove('hover-over-top');
|
||||
insertDividerAtTop = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the rearrange callback and hover item if we aren't hovering over
|
||||
// anything.
|
||||
this.doRearrange = null;
|
||||
if (this.rearrangeDelay) {
|
||||
clearTimeout(this.rearrangeDelay);
|
||||
this.rearrangeDelay = null;
|
||||
}
|
||||
if (this.hoverItem) {
|
||||
this.hoverItem.element.classList.remove('hovered');
|
||||
this.hoverItem = null;
|
||||
}
|
||||
|
||||
// Add the 'hovering' class to the dragged icon.
|
||||
if (foundIndex !== null) {
|
||||
this.icon.element.classList.add('hovering');
|
||||
} else {
|
||||
this.icon.element.classList.remove('hovering');
|
||||
}
|
||||
|
||||
// Nothing to do if we find the dragged icon or no icon
|
||||
if (!insertDividerAtTop &&
|
||||
(foundIndex === null || foundIndex === this.icon.detail.index)) {
|
||||
if (!iconIsDivider) {
|
||||
this.highlightGroup(this.icon.detail.index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var foundItem = this.gridView.items[foundIndex];
|
||||
|
||||
// If we're a divider being dragged, only allow dropping on either the
|
||||
// first item or another divider.
|
||||
if (iconIsDivider &&
|
||||
foundIndex > 0 &&
|
||||
foundItem.detail.type !== 'divider') {
|
||||
// Remove the hovering class from a group if it's not hovering over
|
||||
// a valid drop position or itself.
|
||||
this.icon.element.classList.remove('hovering');
|
||||
return;
|
||||
}
|
||||
|
||||
// If the item isn't a group, trigger the
|
||||
// hovered state on the found item.
|
||||
if (!insertDividerAtTop && !iconIsDivider) {
|
||||
this.hoverItem = foundItem;
|
||||
this.hoverItem.element.classList.add('hovered');
|
||||
}
|
||||
|
||||
// Delay rearranging when we're dragging groups to when they're dropped
|
||||
var rearrangeAfterDelay = !iconIsDivider;
|
||||
|
||||
// Determine if we want to create a new divider. We do this when hovering
|
||||
// over a divider with an icon, or when dragging an icon to the very top
|
||||
// of the grid.
|
||||
var createDivider = insertDividerAtTop;
|
||||
if (!insertDividerAtTop && !iconIsDivider &&
|
||||
(foundItem.detail.type === 'divider')) {
|
||||
// Allow dropping into a collapsed group if the new position is in
|
||||
// the top 2/3 of the group.
|
||||
if (foundItem.detail.collapsed &&
|
||||
pageY <= foundItem.y + (foundItem.pixelHeight * 2/3)) {
|
||||
rearrangeAfterDelay = false;
|
||||
foundItem.element.classList.remove('hovered');
|
||||
|
||||
// When dragging an item forwards, it gets placed after the found
|
||||
// item, adjust to the item before the divider.
|
||||
if (this.icon.detail.index < foundIndex) {
|
||||
foundItem = this.gridView.items[foundIndex - 1];
|
||||
}
|
||||
} else {
|
||||
createDivider = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (createDivider) {
|
||||
// Remove the group background highlight if we're between groups
|
||||
if (this.hoverGroup) {
|
||||
this.hoverGroup.element.classList.remove('drop-target');
|
||||
this.hoverGroup = null;
|
||||
}
|
||||
|
||||
// Cancel rearrangement if it would have no effect.
|
||||
var redundantRearrange = false;
|
||||
if (insertDividerAtTop) {
|
||||
if (iconIsDivider) {
|
||||
redundantRearrange = this.inFirstGroup(this.icon.detail.index - 1);
|
||||
} else {
|
||||
redundantRearrange =
|
||||
(this.icon.detail.index === 0 &&
|
||||
this.gridView.items[1].detail.type === 'placeholder');
|
||||
}
|
||||
} else {
|
||||
redundantRearrange = this.gridView.items[foundIndex].element.
|
||||
classList.contains('invalid-drop');
|
||||
}
|
||||
|
||||
if (redundantRearrange) {
|
||||
if (this.hoverItem) {
|
||||
this.hoverItem.element.classList.remove('hovered');
|
||||
this.hoverItem = null;
|
||||
}
|
||||
return;
|
||||
} else if (insertDividerAtTop) {
|
||||
this.container.classList.add('hover-over-top');
|
||||
}
|
||||
|
||||
this.doRearrange =
|
||||
this.createNewDivider.bind(this,
|
||||
insertDividerAtTop ? null : foundItem);
|
||||
} else {
|
||||
if (!iconIsDivider) {
|
||||
// Change the display of the group the icon is hovering over to
|
||||
// indicate it can be dropped.
|
||||
this.highlightGroup(foundIndex);
|
||||
}
|
||||
|
||||
this.doRearrange = this.rearrange.bind(this, foundItem);
|
||||
|
||||
if (rearrangeAfterDelay) {
|
||||
this.rearrangeDelay =
|
||||
setTimeout(this.doRearrange.bind(this), REARRANGE_DELAY);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new divider in GridView.items and rearranges the currently
|
||||
* dragged icon into the newly created section.
|
||||
* @param {Object} tDivider The divider after which to place a new divider,
|
||||
* or null to insert a divider at the beginning on the grid.
|
||||
*/
|
||||
createNewDivider: function(tDivider) {
|
||||
var items = this.gridView.items;
|
||||
var tIndex = tDivider ? items.indexOf(tDivider) + 1 : 0;
|
||||
|
||||
// Create the new divider
|
||||
var newDivider = new GaiaGrid.Divider();
|
||||
items.splice(tIndex, 0, newDivider);
|
||||
|
||||
// Place the dragged item into the new empty section
|
||||
var sIndex = items.indexOf(this.icon);
|
||||
this.rearrange(sIndex >= tIndex ? newDivider : tDivider);
|
||||
|
||||
// Make sure the new divider/group is in view
|
||||
newDivider.requestAttention();
|
||||
},
|
||||
|
||||
/**
|
||||
* Rearranges items in GridView.items
|
||||
* @param {Object} tItem The item to position the dragged icon at.
|
||||
*/
|
||||
rearrange: function(tItem) {
|
||||
// Clear the rearrange callback
|
||||
this.doRearrange = null;
|
||||
this.rearrangeDelay = null;
|
||||
|
||||
// We get a reference to the position of this.icon within the items
|
||||
// array. Because placeholders are shifting around while we are dragging,
|
||||
// we can't trust the detail.index attribute. This will be fixed on every
|
||||
// render call though.
|
||||
var sIndex = this.gridView.items.indexOf(this.icon);
|
||||
var tIndex = this.gridView.items.indexOf(tItem);
|
||||
|
||||
// Check how many items we need to rearrange (if it's a group, there will
|
||||
// be multiple items.
|
||||
var eIndex = sIndex;
|
||||
if (this.icon.detail.type === 'divider') {
|
||||
for (; sIndex > 0 &&
|
||||
this.gridView.items[sIndex - 1].detail.type !== 'divider';
|
||||
sIndex--) {}
|
||||
|
||||
// Modify the tIndex to make sure we're inserting immediately after
|
||||
// another divider or at the start of the container.
|
||||
if (this.gridView.items[tIndex].detail.type === 'divider') {
|
||||
tIndex++;
|
||||
} else {
|
||||
tIndex = 0;
|
||||
}
|
||||
|
||||
if (sIndex === tIndex) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
} else if (sIndex < tIndex) {
|
||||
tIndex++;
|
||||
}
|
||||
|
||||
// We may have changed tIndex, so refresh our item pointer
|
||||
tItem = this.gridView.items[tIndex];
|
||||
|
||||
// Remove the items from the array
|
||||
var lastItemOffset = eIndex - sIndex;
|
||||
var toInsert = this.gridView.items.splice(sIndex, lastItemOffset + 1);
|
||||
|
||||
// Craft the parameter list to reinsert the items at the correct place
|
||||
toInsert.unshift(tItem ? this.gridView.items.indexOf(tItem) :
|
||||
this.gridView.items.length, 0);
|
||||
|
||||
// Reinsert items
|
||||
this.rearrangeDelay = null;
|
||||
this.dirty = true;
|
||||
this.gridView.items.splice.apply(this.gridView.items, toInsert);
|
||||
|
||||
var oldX = this.icon.x;
|
||||
var oldY = this.icon.y;
|
||||
this.gridView.render();
|
||||
|
||||
// In this case, we don't want to compensate for the icon moving, so
|
||||
// we need to correct our initial values to stop the icon from jumping
|
||||
// after rearranging.
|
||||
this.initialPageX -= oldX - this.icon.x;
|
||||
this.initialPageY -= oldY - this.icon.y;
|
||||
|
||||
this.lastRepositionTime = Date.now();
|
||||
},
|
||||
|
||||
enterEditMode: function() {
|
||||
this.inEditMode = true;
|
||||
this.container.classList.add('edit-mode');
|
||||
document.body.classList.add('edit-mode');
|
||||
this.gridView.element.dispatchEvent(
|
||||
new CustomEvent('editmode-start'));
|
||||
document.addEventListener('visibilitychange', this);
|
||||
this.gridView.render();
|
||||
},
|
||||
|
||||
exitEditMode: function() {
|
||||
// If we're in the middle of a drag, cancel it.
|
||||
if (this.icon) {
|
||||
this.finish();
|
||||
this.finalize();
|
||||
}
|
||||
|
||||
this.inEditMode = false;
|
||||
this.cancelLongPressTimeout();
|
||||
this.container.classList.remove('edit-mode');
|
||||
document.body.classList.remove('edit-mode');
|
||||
this.gridView.element.dispatchEvent(new CustomEvent('editmode-end'));
|
||||
document.removeEventListener('visibilitychange', this);
|
||||
this.gridView.render();
|
||||
},
|
||||
|
||||
cancelLongPressTimeout: function() {
|
||||
if (this.longPressTimeout !== null) {
|
||||
clearTimeout(this.longPressTimeout);
|
||||
this.longPressTimeout = null;
|
||||
}
|
||||
},
|
||||
|
||||
inLongPressThreshold: function(x, y) {
|
||||
return (
|
||||
Math.abs(x - this.touchStart.screenX) < EDIT_LONG_PRESS_THRESHOLD &&
|
||||
Math.abs(y - this.touchStart.screenY) < EDIT_LONG_PRESS_THRESHOLD);
|
||||
},
|
||||
|
||||
/**
|
||||
* General event handler.
|
||||
*/
|
||||
handleEvent: function(e) {
|
||||
switch(e.type) {
|
||||
case 'visibilitychange':
|
||||
if (document.hidden) {
|
||||
this.exitEditMode();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'touchstart':
|
||||
this.cancelLongPressTimeout();
|
||||
|
||||
if (e.touches.length > 1) {
|
||||
if (this.inDragAction) {
|
||||
this.finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.inEditMode && !this.icon) {
|
||||
this.touchStart.x = e.touches[0].pageX;
|
||||
this.touchStart.y = e.touches[0].pageY;
|
||||
this.touchStart.screenX = e.touches[0].screenX;
|
||||
this.touchStart.screenY = e.touches[0].screenY;
|
||||
this.longPressTimeout = setTimeout(() => {
|
||||
this.longPressTimeout = null;
|
||||
this.handleEvent({
|
||||
type: 'contextmenu',
|
||||
target: e.target,
|
||||
pageX: this.touchStart.x,
|
||||
pageY: this.touchStart.y,
|
||||
preventDefault: function() {},
|
||||
stopImmediatePropagation: function() {}
|
||||
});
|
||||
}, EDIT_LONG_PRESS_DELAY);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'contextmenu':
|
||||
this.cancelLongPressTimeout();
|
||||
|
||||
if (this.icon) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.defaultPrevented) {
|
||||
// other handlers already handled this.
|
||||
// in the future, we should use the shadow root and dispatch a
|
||||
// "contextmenu" event from here instead.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!e.target) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.icon = this.gridView.findItemFromElement(e.target, true);
|
||||
|
||||
if (!this.icon || !this.icon.element || !this.icon.isDraggable() ||
|
||||
this.icon.detail.type === 'placeholder') {
|
||||
this.icon = null;
|
||||
return;
|
||||
}
|
||||
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
|
||||
this.target = this.icon.element;
|
||||
this.begin(e);
|
||||
|
||||
break;
|
||||
|
||||
case 'touchmove':
|
||||
var touch = e.touches[0];
|
||||
|
||||
if (this.inDragAction) {
|
||||
this.currentTouch = {
|
||||
pageX: touch.pageX,
|
||||
pageY: touch.pageY
|
||||
};
|
||||
|
||||
if (!this.isScrolling) {
|
||||
this.positionAndScrollIfNeeded();
|
||||
}
|
||||
} else if (this.longPressTimeout !== null &&
|
||||
!this.inLongPressThreshold(touch.screenX,
|
||||
touch.screenY)) {
|
||||
this.cancelLongPressTimeout();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'click':
|
||||
case 'touchcancel':
|
||||
if (this.inDragAction) {
|
||||
this.finish();
|
||||
this.finalize();
|
||||
}
|
||||
|
||||
this.cancelLongPressTimeout();
|
||||
break;
|
||||
|
||||
case 'touchend':
|
||||
if (this.inDragAction) {
|
||||
// Ensure the app is not launched
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
|
||||
// As contextmenu event can be synthesized, it's possible for it
|
||||
// to happen in the same event-loop as touchend, meaning
|
||||
// finish would be called immediately after begin. This would
|
||||
// mean that the icon doesn't get a chance to transition and
|
||||
// the transitionend that we expect won't be called, so finalize
|
||||
// also won't be called, leaving us in an inconsistent state.
|
||||
// It would be so great if there was a transitionstart event :(
|
||||
setTimeout(() => { this.finish(); }, TOUCH_END_FINISH_DELAY);
|
||||
}
|
||||
|
||||
this.cancelLongPressTimeout();
|
||||
break;
|
||||
|
||||
case 'transitionend':
|
||||
this.finalize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.GridDragDrop = DragDrop;
|
||||
|
||||
}(window));
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
;'use strict';(function(exports){const SHADOW_BLUR=1;const SHADOW_OFFSET_Y=1;const SHADOW_OFFSET_X=1;const SHADOW_COLOR='rgba(0, 0, 0, 0.2)';const DEFAULT_BACKGROUND_COLOR='rgb(228, 234, 238)';const UNSCALED_CANVAS_PADDING=2;const CANVAS_PADDING=UNSCALED_CANVAS_PADDING*devicePixelRatio;function IconRenderer(icon){this._icon=icon;}
|
||||
IconRenderer.TYPE={CLIP:'clip',FAVICON:'favicon',STANDARD:'standard',};IconRenderer.prototype={unscaledCanvasPadding:UNSCALED_CANVAS_PADDING*2,get _maxSize(){return this._icon.grid.layout.gridMaxIconSize;},_createCanvas:function(){const CANVAS_PADDING_BOTTOM=1*devicePixelRatio;var canvas=document.createElement('canvas');canvas.width=this._maxSize+(CANVAS_PADDING*2);canvas.height=this._maxSize+CANVAS_PADDING+CANVAS_PADDING_BOTTOM;return canvas;},_createClipCanvas:function(){var canvas=document.createElement('canvas');canvas.width=this._maxSize+(CANVAS_PADDING*2);canvas.height=this._maxSize+(CANVAS_PADDING*2);return canvas;},_decorateShadowCanvas:function(canvas){var ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.shadowColor=SHADOW_COLOR;ctx.shadowBlur=SHADOW_BLUR;ctx.shadowOffsetY=SHADOW_OFFSET_Y;ctx.shadowOffsetX=SHADOW_OFFSET_X;return ctx;},clip:function(img){return new Promise((resolve)=>{var shadowCanvas=this._createCanvas();var shadowCtx=this._decorateShadowCanvas(shadowCanvas);var clipCanvas=this._createClipCanvas();var clipCtx=clipCanvas.getContext('2d',{willReadFrequently:true});clipCtx.beginPath();clipCtx.arc(clipCanvas.width/2,clipCanvas.height/2,clipCanvas.height/2,0,2*Math.PI);clipCtx.clip();clipCtx.drawImage(img,0,0,clipCanvas.width,clipCanvas.height);shadowCtx.drawImage(clipCanvas,CANVAS_PADDING,CANVAS_PADDING,this._maxSize,this._maxSize);shadowCanvas.toBlob(resolve);});},favicon:function(img){if(img.width>this._icon.grid.layout.gridIconSize/2){return this.clip(img);}
|
||||
return new Promise((resolve)=>{var shadowCanvas=this._createCanvas();var shadowCtx=this._decorateShadowCanvas(shadowCanvas);var iconWidth;var iconHeight;shadowCtx.beginPath();shadowCtx.arc(shadowCanvas.width/2,shadowCanvas.height/2,shadowCanvas.height/2-CANVAS_PADDING,0,2*Math.PI,false);shadowCtx.fillStyle=DEFAULT_BACKGROUND_COLOR;shadowCtx.fill();iconWidth=iconHeight=this._maxSize*0.55;shadowCtx.shadowBlur=0;shadowCtx.shadowOffsetY=0;shadowCtx.mozImageSmoothingEnabled=false;shadowCtx.drawImage(img,(shadowCanvas.width-iconWidth)/2,(shadowCanvas.height-iconHeight)/2,iconWidth,iconHeight);shadowCanvas.toBlob(resolve);});},standard:function(img){return new Promise((resolve)=>{var shadowCanvas=this._createCanvas();var shadowCtx=this._decorateShadowCanvas(shadowCanvas);shadowCtx.drawImage(img,CANVAS_PADDING,CANVAS_PADDING,this._maxSize,this._maxSize);shadowCanvas.toBlob(resolve);});}};exports.GridIconRenderer=IconRenderer;}(window));
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
;'use strict';(function(exports){const maxIconsPerRow=4;const iconScaleFactorMaxIconsPerRow=5;const minIconsPerRow=3;const iconScaleFactorMinIconsPerRow=3.8;const distanceBetweenIconsWithMinIconsPerRow=36;const distanceBetweenIconsWithMaxIconsPerRow=38;const eachTextRowHeight=20;var constraintSize;function GridLayout(gridView){this.gridView=gridView;if(window.verticalPreferences){verticalPreferences.get('grid.cols').then(value=>{this.cols=value;this.onReady();},this.onReady);verticalPreferences.addEventListener('updated',this);}else{this.onReady();}}
|
||||
GridLayout.prototype={minIconsPerRow:minIconsPerRow,maxIconsPerRow:maxIconsPerRow,_cols:minIconsPerRow,_offsetY:0,_percent:1,_dividerLineHeight:0,get percent(){return this._percent;},get cols(){return this._cols;},set cols(value){if(!value||value===this._cols){return;}
|
||||
if(window.verticalPreferences){verticalPreferences.put('grid.cols',value);}
|
||||
this._offsetY=0;this._percent=value==minIconsPerRow?1:minIconsPerRow/maxIconsPerRow;this._cols=value;},get constraintSize(){if(!constraintSize){this.calculateSize();}
|
||||
return constraintSize;},get gridItemHeight(){var height=this.gridIconSize+
|
||||
(this._cols===minIconsPerRow?distanceBetweenIconsWithMinIconsPerRow:distanceBetweenIconsWithMaxIconsPerRow);var defaultTextRows=2;var definedRows=parseInt(this.gridView.element.getAttribute('text-rows'),10);if(definedRows>defaultTextRows){height+=(definedRows-defaultTextRows)*eachTextRowHeight;}
|
||||
return height;},get gridItemWidth(){return this.constraintSize/this._cols;},get gridMaxIconSize(){var baseSize=(this.constraintSize/iconScaleFactorMinIconsPerRow);return baseSize*devicePixelRatio;},get gridIconSize(){var numCols=this._cols;var size=this.constraintSize/numCols;if(numCols===minIconsPerRow){size=this.constraintSize/iconScaleFactorMinIconsPerRow;}else if(numCols===maxIconsPerRow){size=this.constraintSize/iconScaleFactorMaxIconsPerRow;}
|
||||
return Math.floor(size);},get offsetY(){return this._offsetY;},set offsetY(value){this._offsetY=value;},stepYAxis:function(value){this._offsetY+=value;},handleEvent:function(e){switch(e.type){case'updated':var prop=e.target;if(prop.name==='grid.cols'){this.cols=parseInt(prop.value,10);this.gridView.render();}
|
||||
break;}},calculateSize:function(){constraintSize=Math.min(window.screen.width,window.screen.height);},onReady:function(){window.dispatchEvent(new CustomEvent('gaiagrid-layout-ready'));}};exports.GridLayout=GridLayout;}(window));
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
;'use strict';(function(exports){const APP_LAUNCH_TIMEOUT=3000;function GridView(config){this.config=config;this.clickIcon=this.clickIcon.bind(this);this.onVisibilityChange=this.onVisibilityChange.bind(this);if(config.features.zoom){this.zoom=new GridZoom(this);}
|
||||
this.layout=new GridLayout(this);if(config.element.hasAttribute('cols')){this.layout.cols=parseInt(config.element.getAttribute('cols'),10);}
|
||||
this.start();}
|
||||
GridView.prototype={icons:{},items:[],get element(){return this.config.element;},set cols(value){this.layout.cols=value;},_launchingApp:false,add:function(item,insertTo,expandGroup){if(!item){return;}
|
||||
if(item.identifier){if(this.icons[item.identifier]){console.log('Error, duplicate identifier: ',item.identifier,new Error().stack);return;}
|
||||
this.icons[item.identifier]=item;}else if(item.detail.type!=='divider'&&item.detail.type!=='placeholder'){console.log('Error, could not load identifier for object: ',JSON.stringify(item.detail));return;}
|
||||
if(!isNaN(parseFloat(insertTo))&&isFinite(insertTo)){this.items.splice(insertTo,0,item);}else{insertTo=this.items.length;this.items.push(item);}
|
||||
if(expandGroup){for(var i=insertTo+1,iLen=this.items.length;i<iLen;i++){var divider=this.items[i];if(divider.detail.type==='divider'){if(divider.detail.collapsed){divider.expand();}
|
||||
break;}}}},getNearestItemIndex:function(x,y,isRow){var foundIndex=null;var leastDistance=null;var itemMiddleOffset=this.layout.gridItemWidth/2;for(var i=0,iLen=this.items.length;i<iLen;i++){var item=this.items[i];if(!item.isDraggable()){continue;}
|
||||
if(this.config.features.disableSections&&item.detail.type==='divider'){continue;}
|
||||
if(item.detail.type!=='divider'&&item.element.classList.contains('collapsed')){continue;}
|
||||
var middleX=item.x+itemMiddleOffset;var middleY=item.y+item.pixelHeight/2;var xDistance=(isRow||item.detail.type==='divider')?0:x-middleX;var yDistance=y-middleY;var distance=Math.sqrt(xDistance*xDistance+
|
||||
yDistance*yDistance);if(leastDistance===null||distance<leastDistance){leastDistance=distance;foundIndex=i;}}
|
||||
return foundIndex;},start:function(){this.element.addEventListener('click',this.clickIcon);window.addEventListener('visibilitychange',this.onVisibilityChange);},stop:function(){this.element.removeEventListener('click',this.clickIcon);window.removeEventListener('visibilitychange',this.onVisibilityChange);},findItemFromElement:function(element,excludeCollapsedIcons){while(element&&element.parentNode!==this.element){element=element.parentNode;}
|
||||
if(!element){return null;}
|
||||
var i,iLen=this.items.length;var identifier=element.dataset.identifier;var icon=this.icons[identifier];if(!icon){for(i=0;i<iLen;i++){if(this.items[i].element===element){icon=this.items[i];break;}}}
|
||||
if(icon&&excludeCollapsedIcons){if(icon.detail.type!=='divider'&&icon.detail.type!=='placeholder'&&icon.element.classList.contains('collapsed')){for(i=icon.detail.index+1;i<iLen;i++){if(this.items[i].detail.type==='divider'){return this.items[i];}}
|
||||
console.warn('Collapsed icon found with no group');icon=null;}}
|
||||
return icon;},onVisibilityChange:function(){this._launchingApp=false;},clickIcon:function(e){e.preventDefault();var inEditMode=this.dragdrop&&this.dragdrop.inEditMode;var action='launch';if(e.target.classList.contains('remove')){action='remove';}
|
||||
var icon=this.findItemFromElement(e.target);if(!icon){return;}
|
||||
if(action==='launch'){if(inEditMode&&e.target.classList.contains('icon')){if(!icon.isEditable()){return;}
|
||||
action='edit';}else{if(!icon[action]){return;}
|
||||
icon.element.classList.add('launching');var returnTimeout=500;setTimeout(function stateReturn(){if(icon.element){icon.element.classList.remove('launching');}},returnTimeout);}}
|
||||
if((icon.detail.type==='app'||icon.detail.type==='bookmark')&&this._launchingApp){return;}
|
||||
if((icon.detail.type==='app'&&icon.appState==='ready')||icon.detail.type==='bookmark'){this._launchingApp=true;if(this._launchingTimeout){window.clearTimeout(this._launchingTimeout);this._launchingTimeout=null;}
|
||||
this._launchingTimeout=window.setTimeout(function(){this._launchingTimeout=null;this._launchingApp=false;}.bind(this),APP_LAUNCH_TIMEOUT);}
|
||||
icon[action](e.target);},cleanItems:function(skipDivider){var appCount=0;var toRemove=[];this.items.forEach(function(item,idx){if(item instanceof GaiaGrid.Divider){if(appCount===0){toRemove.push(idx);}
|
||||
appCount=0;}else{appCount++;}},this);toRemove.reverse();toRemove.forEach(function(idx){var removed=this.items.splice(idx,1)[0];removed.remove();},this);if(skipDivider){return;}
|
||||
var lastItem=this.items[this.items.length-1];if(!lastItem||!(lastItem instanceof GaiaGrid.Divider)){this.items.push(new GaiaGrid.Divider());}},removeAllPlaceholders:function(){var toSplice=[];var previousItem;this.items.forEach(function(item,idx){if(item instanceof GaiaGrid.Placeholder){if((!previousItem||(previousItem&&previousItem instanceof GaiaGrid.Divider))&&this.dragdrop&&this.dragdrop.inDragAction){return;}
|
||||
toSplice.push(idx);}
|
||||
previousItem=item;},this);toSplice.reverse().forEach(function(idx){this.items.splice(idx,1)[0].remove();},this);},clear:function(){for(var i=0,iLen=this.items.length;i<iLen;i++){var item=this.items[i];if(item.element){this.element.removeChild(item.element);item.element=null;item.lastX=null;item.lastY=null;item.lastScale=null;}}
|
||||
this.items=[];this.icons={};},createPlaceholders:function(coordinates,idx,count){var isRTL=(document.documentElement.dir==='rtl');for(var i=0;i<count;i++){var item=new GaiaGrid.Placeholder();this.items.splice(idx+i,0,item);item.setPosition(idx+i);var xPosition=(coordinates[0]+i)*this.layout.gridItemWidth;if(isRTL){xPosition=(this.layout.constraintSize-this.layout.gridItemWidth)-
|
||||
xPosition;}
|
||||
item.setCoordinates(xPosition,this.layout.offsetY);item.render();}},render:function(options){var self=this;options=options||{};this.removeAllPlaceholders();this.cleanItems(options.skipDivider);var oldHeight=this.layout.offsetY;this.layout.offsetY=0;var x=0;var y=0;function step(item){var pixelHeight=item.pixelHeight;self.layout.stepYAxis(pixelHeight);x=0;y++;}
|
||||
var pendingCachedIcons=0;var onCachedIconRendered=()=>{if(--pendingCachedIcons<=0){this.element.removeEventListener('cached-icon-rendered',onCachedIconRendered);this.element.dispatchEvent(new CustomEvent('cached-icons-rendered'));}};this.element.addEventListener('cached-icon-rendered',onCachedIconRendered);var nextDivider=null;var oddDivider=true;var isRTL=(document.documentElement.dir==='rtl');for(var idx=0;idx<this.items.length;idx++){var item=this.items[idx];if(options.rerender&&item.element){this.element.removeChild(item.element);item.element=null;}
|
||||
if(item.detail.type==='divider'){nextDivider=null;}else{if(!nextDivider){for(var i=idx+1;i<this.items.length;i++){if(this.items[i].detail.type==='divider'){nextDivider=this.items[i];oddDivider=!oddDivider;break;}}
|
||||
if(nextDivider&&!nextDivider.detail.collapsed){this.layout.offsetY+=nextDivider.headerHeight;}}
|
||||
if(nextDivider&&nextDivider.detail.collapsed){item.setPosition(idx);continue;}}
|
||||
if(x>0&&item.gridWidth>1&&x+item.gridWidth>=this.layout.cols){var remaining=this.layout.cols-x;this.createPlaceholders([x,y],idx,remaining);idx+=remaining;item=this.items[idx];var lastItemInRow=this.items[idx-1];step(lastItemInRow);}
|
||||
item.setPosition(idx);if(!options.skipItems){item.hasCachedIcon&&++pendingCachedIcons;var xPosition=x*this.layout.gridItemWidth;if(isRTL){xPosition=(this.layout.constraintSize-this.layout.gridItemWidth)-
|
||||
xPosition;}
|
||||
item.setCoordinates(xPosition,this.layout.offsetY);if(!item.active){item.render();}
|
||||
if(item.detail.type==='divider'){if(oddDivider){item.element.classList.add('odd');}else{item.element.classList.remove('odd');}}}
|
||||
x+=item.gridWidth;if((x>=this.layout.cols)&&(idx<this.items.length-1)){step(item);}}
|
||||
if(this.layout.offsetY!=oldHeight){if(this.dragdrop&&this.dragdrop.inDragAction){this.layout.offsetY=oldHeight;}else{this.element.dispatchEvent(new CustomEvent('gaiagrid-resize',{detail:this.layout.offsetY}));}}
|
||||
this.element.setAttribute('cols',this.layout.cols);pendingCachedIcons===0&&onCachedIconRendered();this.loadDragDrop();},loadDragDrop:function(){if(!this.dragdrop&&this.config.features.dragdrop){LazyLoader.load('shared/elements/gaia_grid/js/grid_dragdrop.js',()=>{if(this.dragdrop){return;}
|
||||
this.dragdrop=new GridDragDrop(this);});}}};exports.GridView=GridView;}(window));
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
|
||||
const pinchThreshold = Math.round(window.innerWidth / 12);
|
||||
|
||||
function GridZoom(gridView) {
|
||||
this.gridView = gridView;
|
||||
|
||||
this.touches = 0;
|
||||
this.zoomStartTouches = [];
|
||||
this.zoomStartDistance = 0;
|
||||
|
||||
this.container = document.getElementById('zoom');
|
||||
this.arrows = this.container.querySelector('.arrows');
|
||||
this.curtain = this.container.querySelector('.curtain');
|
||||
this.indicator = this.container.querySelector('.indicator');
|
||||
|
||||
this.start();
|
||||
window.addEventListener('gaiagrid-dragdrop-begin', this.stop.bind(this));
|
||||
window.addEventListener('gaiagrid-dragdrop-finish', this.start.bind(this));
|
||||
}
|
||||
|
||||
GridZoom.prototype = {
|
||||
|
||||
/**
|
||||
* Starts listening for touchstart events.
|
||||
* This is what starts listening events to start the drag & drop operation.
|
||||
*/
|
||||
start: function() {
|
||||
window.addEventListener('touchstart', this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops listening for touchstart events.
|
||||
* This will effectively disable pinch-to-zoom.
|
||||
*/
|
||||
stop: function() {
|
||||
window.removeEventListener('touchstart', this);
|
||||
},
|
||||
|
||||
_attachGestureListeners: function() {
|
||||
window.addEventListener('touchmove', this);
|
||||
window.addEventListener('touchend', this);
|
||||
},
|
||||
|
||||
_stopGestureListeners: function() {
|
||||
window.removeEventListener('touchmove', this);
|
||||
window.removeEventListener('touchend', this);
|
||||
},
|
||||
|
||||
_resetState: function() {
|
||||
this.zoomInProgress = false;
|
||||
|
||||
this.container.hidden = true;
|
||||
this.indicator.classList.remove('active');
|
||||
this.arrows.classList.remove('zooming', 'grow', 'shrink');
|
||||
this.arrows.style.transform = '';
|
||||
},
|
||||
|
||||
/**
|
||||
* General Event Handler
|
||||
*/
|
||||
handleEvent: function(e) {
|
||||
if (e.type === 'touchend' && this.zoomStartTouches) {
|
||||
if (!this.zoomInProgress) {
|
||||
this._resetState();
|
||||
}
|
||||
|
||||
this._stopGestureListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!e.touches || e.touches.length !== 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort touches by ascending pageX position.
|
||||
var touches = [e.touches[0], e.touches[1]].sort(function(a, b) {
|
||||
return a.pageX - b.pageX;
|
||||
});
|
||||
|
||||
var touchDistance = Math.sqrt(
|
||||
(touches[0].pageX - touches[1].pageX) *
|
||||
(touches[0].pageX - touches[1].pageX) +
|
||||
(touches[0].pageY - touches[1].pageY) *
|
||||
(touches[0].pageY - touches[1].pageY));
|
||||
|
||||
var layout = this.gridView.layout;
|
||||
|
||||
switch(e.type) {
|
||||
case 'touchstart':
|
||||
this.container.hidden = false;
|
||||
this.zoomStartTouches = touches;
|
||||
this.zoomStartDistance = touchDistance;
|
||||
|
||||
if (layout.cols < layout.maxIconsPerRow) {
|
||||
this.arrows.classList.add('grow');
|
||||
} else {
|
||||
this.arrows.classList.add('shrink');
|
||||
}
|
||||
|
||||
this.indicator.dataset.cols = layout.cols;
|
||||
this._attachGestureListeners();
|
||||
break;
|
||||
|
||||
case 'touchmove':
|
||||
if (layout.cols < layout.maxIconsPerRow &&
|
||||
touchDistance < this.zoomStartDistance &&
|
||||
Math.abs(touchDistance - this.zoomStartDistance) >
|
||||
pinchThreshold) {
|
||||
this.gridView.cols = layout.maxIconsPerRow;
|
||||
this.zoomInProgress = true;
|
||||
} else if (layout.cols > layout.minIconsPerRow &&
|
||||
touchDistance > this.zoomStartDistance &&
|
||||
Math.abs(touchDistance - this.zoomStartDistance) >
|
||||
pinchThreshold) {
|
||||
this.gridView.cols = layout.minIconsPerRow;
|
||||
this.zoomInProgress = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// For now just implement a canned animation
|
||||
this._stopGestureListeners();
|
||||
|
||||
var ontransitionend = function() {
|
||||
this.arrows.removeEventListener('transitionend', ontransitionend);
|
||||
// Change the indicator color at the end.
|
||||
this.indicator.classList.add('active');
|
||||
|
||||
this.gridView.render();
|
||||
|
||||
// Reset zoom element state after a set time.
|
||||
var zoomHideTime = 400;
|
||||
setTimeout(this._resetState.bind(this), zoomHideTime);
|
||||
}.bind(this);
|
||||
|
||||
this.arrows.addEventListener('transitionend', ontransitionend);
|
||||
|
||||
this.indicator.dataset.cols = layout.cols;
|
||||
|
||||
this.arrows.classList.add('zooming');
|
||||
// Force a sync reflow
|
||||
document.body.clientHeight;
|
||||
var scaleTransform = 'scale(1)';
|
||||
if (this.zoomInProgress && touchDistance < this.zoomStartDistance) {
|
||||
scaleTransform = 'scale(0.4)';
|
||||
}
|
||||
this.arrows.style.transform = scaleTransform;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
exports.GridZoom = GridZoom;
|
||||
|
||||
}(window));
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
;'use strict';(function(exports){const TYPE='bookmark';function Bookmark(record,features){this.detail=record;this.features=features||{};this.detail.type=TYPE;}
|
||||
Bookmark.prototype={__proto__:GaiaGrid.GridItem.prototype,renderer:GridIconRenderer.TYPE.FAVICON,get pixelHeight(){return this.grid.layout.gridItemHeight;},gridWidth:1,get name(){return this.detail.name;},get icon(){return this.detail.icon||this.defaultIcon;},get identifier(){return this.detail.id;},update:GaiaGrid.GridItem.prototype.updateFromDatastore,isEditable:function(){return this.features&&this.features.isEditable!==false;},isRemovable:function(){return this.features&&this.features.isRemovable!==false;},isDraggable:function(){return this.features&&this.features.isDraggable!==false;},render:function(){GaiaGrid.GridItem.prototype.render.call(this);this.element.classList.add('bookmark');if(this.isEditable()){this.element.classList.add('editable');}},launch:function(){var features={name:this.name,icon:this.icon,remote:true};var url=this.detail.url;if(this.features.search){features.searchName=this.name;features.searchUrl=url;}
|
||||
window.open(url,'_samescope',Object.keys(features).map(function eachFeature(key){return encodeURIComponent(key)+'='+
|
||||
encodeURIComponent(features[key]);}).join(','));},edit:function(){new MozActivity({name:'save-bookmark',data:{type:'url',url:this.detail.id}});}};exports.GaiaGrid.Bookmark=Bookmark;}(window));
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
;'use strict';(function(exports){function Divider(){this.detail={type:'divider',index:0};}
|
||||
Divider.prototype={__proto__:GaiaGrid.GridItem.prototype,x:0,y:0,headerHeight:0,get pixelHeight(){return(this.grid.layout.cols>3)?50:60;},gridWidth:4,scale:1,render:function(){if(!this.element){var divider=this.element=document.createElement('section');divider.className='divider';var span=document.createElement('span');span.className='spacer';divider.appendChild(span);this.grid.element.appendChild(divider);}
|
||||
this.element.style.transform='translate(0 ,'+this.y+'px)';},remove:function(){if(this.element){this.element.parentNode.removeChild(this.element);}},isDraggable:function(){return false;}};exports.GaiaGrid.Divider=Divider;}(window));
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
;'use strict';(function(exports){const ICON_BLOB_DECORATED_EVENT='iconblobdecorated';const ICON_BLOB_ERROR_EVENT='gaiagrid-iconbloberror';const FETCH_XHR_TIMEOUT=10000;function fetchBlob(uri){return new Promise(function(accept,reject){var xhr=new XMLHttpRequest({mozAnon:true,mozSystem:true});xhr.open('GET',uri,true);xhr.responseType='blob';xhr.timeout=FETCH_XHR_TIMEOUT;xhr.send();xhr.onload=function(){var status=xhr.status;if(status!==0&&status!==200){reject(new Error('Got HTTP status '+status+' trying to load '+uri));return;}
|
||||
accept(xhr.response);};xhr.onerror=xhr.ontimeout=function(){reject(new Error('Error while HTTP GET: ',uri));};});}
|
||||
function GridItem(){this.detail={};}
|
||||
GridItem.prototype={x:0,y:0,pixelHeight:0,gridWidth:1,scale:1,persistToDB:true,lastX:null,lastY:null,lastScale:null,get hasCachedIcon(){return this.detail&&this.detail.decoratedIconBlob;},renderer:GridIconRenderer.TYPE.STANDARD,iconState:'none',get defaultIcon(){return'/shared/elements/gaia_grid/images/default_icon.png';},get grid(){return document.getElementsByTagName('gaia-grid')[0]._grid;},isRemovable:function(){return false;},isEditable:function(){return false;},isDraggable:function(){return true;},isIconFromOrigin:function(){return this.icon.startsWith('http')||this.icon.startsWith('app:');},setPosition:function(position){this.detail.index=position;},setCoordinates:function(x,y){this.x=x;this.y=y;},requestAttention:function(){var rect={x:this.x,y:this.y,width:this.gridWidth*this.grid.layout.gridItemWidth,height:this.pixelHeight};this.grid.element.dispatchEvent(new CustomEvent('gaiagrid-attention',{detail:rect}));},closestIconSizeFromList:function(choices){if(!choices){return 0;}
|
||||
var sizes=Object.keys(choices);if(!sizes.length){return 0;}
|
||||
var maxSize=this.grid.layout.gridMaxIconSize;var filter=(a)=>a>=maxSize?a:0;var bestSize=Math.min(...sizes.map(filter));bestSize=bestSize||Math.max(...sizes);return bestSize||0;},closestIconFromList:function(choices){var icon;if(Array.isArray(choices)){var manifest={'icons':choices};var maxSize=this.grid.layout.gridMaxIconSize;icon=window.IconsHelper.getBestIconFromWebManifest(manifest,maxSize);return icon?(new URL(icon,this.app.manifestURL)).href:null;}
|
||||
var accurateSize=this.closestIconSizeFromList(choices);if(accurateSize===0){return this.defaultIcon;}
|
||||
icon=choices[accurateSize];if(!UrlHelper.hasScheme(icon)){icon=this.app.origin+icon;}
|
||||
return icon;},renderIconFromSrc:function(url){var background=new Image();background.src=url;background.onload=this._decorateIcon.bind(this,background);},renderIconFromBlob:function(blob){var background=new Image();background.src=URL.createObjectURL(blob);background.onload=()=>{this._decorateIcon(background);URL.revokeObjectURL(background.src);};background.onerror=()=>{URL.revokeObjectURL(background.src);if(this.hasCachedIcon){this._stampElementWithIcon('blobcache');this._displayDecoratedIcon(this.detail.decoratedIconBlob,true);return;}
|
||||
this.renderIconFromSrc(this.defaultIcon);this._stampElementWithIcon(this.defaultIcon);};},_decorateIcon:function(img){var strategy=this.detail.renderer||this.renderer;this.rendererInstance=new GridIconRenderer(this);this.rendererInstance[strategy](img).then(this._displayDecoratedIcon.bind(this));},_displayDecoratedIcon:function(blob,isCachedIcon){if(!this.element){return;}
|
||||
var style=this.element.style;if(!style.backgroundSize){style.height=this.grid.layout.gridItemHeight+'px';var backgroundHeight=((this.grid.layout.gridIconSize*(1/this.grid.layout.percent))+
|
||||
GridIconRenderer.prototype.unscaledCanvasPadding);if(this.grid.layout.gridItemHeight>backgroundHeight){style.backgroundSize=backgroundHeight+'px';}else{style.backgroundSize=style.height;}}
|
||||
if(isCachedIcon){var url=URL.createObjectURL(blob);style.backgroundImage='url('+url+')';this.element.dataset.backgroundImage=url;var img=new Image();img.onload=img.onerror=()=>{this.grid.element.dispatchEvent(new CustomEvent('cached-icon-rendered'));};img.src=url;return;}
|
||||
this._compareBlobs(blob,this.detail.decoratedIconBlob).then((equal)=>{if(equal){return;}
|
||||
style.backgroundImage='url('+URL.createObjectURL(blob)+')';this.detail.decoratedIconBlob=blob;this.grid.element.dispatchEvent(new CustomEvent(ICON_BLOB_DECORATED_EVENT,{detail:this}));var bgImg=this.element.dataset.backgroundImage;bgImg&&URL.revokeObjectURL(bgImg);});},_compareBlobs:function(blob1,blob2){return new Promise(function(resolve){if(!blob1||!blob2||blob1.type!==blob2.type||blob1.size!==blob2.size){resolve(false);return;}
|
||||
var startBytes=127;var bytesHash=16;var reader=new FileReader();reader.onloadend=function(){var result1=reader.result;reader=new FileReader();reader.onloadend=reader.onerror=function(){resolve(result1===reader.result);};reader.readAsDataURL(blob2.slice(startBytes,startBytes+bytesHash));};reader.onerror=function(){resolve(false);};reader.readAsDataURL(blob1.slice(startBytes,startBytes+bytesHash));});},fetchIconBlob:function(){return fetchBlob(this.icon);},_stampElementWithIcon:function(uri){if(!this.element||uri.startsWith('data:')){return;}
|
||||
if(uri.length>255){uri=uri.slice(0,255);}
|
||||
this.element.dataset.testIcon=uri;},renderIcon:function(renderCachedIcon){var icon=this.icon;this.iconState='pending';if(!icon){return;}
|
||||
if(renderCachedIcon&&this.hasCachedIcon){this._displayDecoratedIcon(this.detail.decoratedIconBlob,true);var resolveIcon=()=>{this.grid.element.removeEventListener('cached-icons-rendered',resolveIcon);this.doRenderIcon(icon);};this.grid.element.addEventListener('cached-icons-rendered',resolveIcon);}else{this.doRenderIcon(icon);}},doRenderIcon:function(icon){if(!this.isIconFromOrigin()){this._stampElementWithIcon(icon);this.renderIconFromSrc(icon);this.iconState='success';return Promise.resolve();}
|
||||
var eventTarget=this.grid.element;var blobNotFound=()=>{this.iconState='error';if(!this.hasCachedIcon){this.renderIconFromSrc(this.defaultIcon);this._stampElementWithIcon(this.defaultIcon);}else{this._stampElementWithIcon('blobcache');}
|
||||
eventTarget.dispatchEvent(new CustomEvent(ICON_BLOB_ERROR_EVENT,{detail:this}));};return this.fetchIconBlob().then((blob)=>{if(!blob){return blobNotFound();}
|
||||
this.renderIconFromBlob(blob);this.iconState='success';this._stampElementWithIcon(icon);}).catch((err)=>{blobNotFound();});},removeFromGrid:function(){var idx=this.grid.items.indexOf(this);if(idx===-1){console.error('Attempting to remove self before item has been added!');return;}
|
||||
this.grid.items.splice(idx,1);delete this.grid.icons[this.identifier];if(this.element){this.element.parentNode.removeChild(this.element);}
|
||||
this.grid.render({from:idx-1});},remove:function(){this.grid.element.dispatchEvent(new CustomEvent('removeitem',{detail:this}));},render:function(){var scale=this.grid.layout.percent*this.scale;if(!this.element){var tile=document.createElement('div');tile.className='icon';tile.dataset.identifier=this.identifier;tile.dataset.isDraggable=this.isDraggable();tile.setAttribute('role','link');tile.setAttribute('tabindex',0);tile.style.width=(this.grid.layout.constraintSize/3)+'px';var nameContainerEl=document.createElement('p');nameContainerEl.style.marginTop=((this.grid.layout.gridIconSize*(1/this.grid.layout.percent))+
|
||||
(GridIconRenderer.prototype.unscaledCanvasPadding/2))+'px';tile.appendChild(nameContainerEl);var nameEl=document.createElement('span');nameEl.className='title';nameEl.setAttribute('dir','auto');nameContainerEl.appendChild(nameEl);if(this.isRemovable()){var removeEl=document.createElement('span');removeEl.className='remove';tile.appendChild(removeEl);}
|
||||
this.element=tile;this.updateTitle();this.renderIcon(true);this.grid.element.appendChild(tile);}
|
||||
this.transform(this.x,this.y,scale);},transform:function(x,y,scale,element){scale=scale||1;if(!element){if(x===this.lastX&&y===this.lastY&&scale===this.lastScale){return;}
|
||||
element=this.element;this.lastX=x;this.lastY=y;this.lastScale=scale;}
|
||||
element.style.transform='translate('+x+'px,'+y+'px) scale('+scale+')';},setActive:function(active){if(active){this.element.classList.add('active');this.active=true;}else{this.element.classList.remove('active');this.active=false;}},updateTitle:function(){if(!this.element){return;}
|
||||
var nameEl=this.element.querySelector('.title');if(this.asyncName){this.asyncName().then(function(name){nameEl.textContent=name;});}else{nameEl.textContent=this.name;}},updateFromDatastore:function(record){var iconChanged=record.icon!==this.icon;var nameChanged=record.name!==this.name;var type=this.detail.type;var lastIcon=this.icon;record.type=type;this.detail=record;if(nameChanged){this.updateTitle();}
|
||||
if(iconChanged&&record.icon){this.renderIcon();}else if(!record.icon){this.detail.icon=lastIcon;}}};exports.GaiaGrid.GridItem=GridItem;}(window));
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
;'use strict';(function(exports){const COLLAPSE_RATIO=0.33;const COLLAPSED_GROUP_SIZE=6;const COLLAPSED_GROUP_MARGIN_LEFT=23;const COLLAPSED_GROUP_MARGIN_RIGHT=53;const TOGGLE_TIMEOUT=250;function Group(detail){this.detail=detail||{};this.detail.type='divider';this.detail.index=0;this.pendingCollapse=this.detail.collapsed=!!this.detail.collapsed;}
|
||||
Group.prototype={__proto__:GaiaGrid.GridItem.prototype,gridWidth:4,get headerHeight(){return this.detail.collapsed?20:30;},pendingCollapse:false,pendingCollapseTimeout:null,backgroundHeight:0,lastBackgroundHeight:null,separatorHeight:0,collapseRatio:COLLAPSE_RATIO,get pixelHeight(){return this.detail.collapsed?this.backgroundHeight:this.separatorHeight;},get size(){var size=0;for(var i=this.detail.index-1,items=this.grid.items;i>=0&&items[i].detail.type!=='divider';i--){size++;}
|
||||
return size;},_createElement:function(){var group=this.element=document.createElement('section');group.className='divider group newly-created';var span=document.createElement('span');span.className='background';group.appendChild(span);this.backgroundSpanElement=span;span=document.createElement('span');span.className='shadow';group.appendChild(span);this.shadowSpanElement=span;span=document.createElement('span');span.className='header';group.appendChild(span);this.headerSpanElement=span;span=document.createElement('span');span.className='gripper';this.headerSpanElement.appendChild(span);var button=document.createElement('button');button.className='toggle';button.dataset.l10nId='gaia-grid-toggle-expanded';this.headerSpanElement.appendChild(button);this.toggleElement=button;span=document.createElement('span');span.className='separator';group.appendChild(span);this.dividerSpanElement=span;this.dividerSpanElement.appendChild(document.createElement('span'));this.grid.element.appendChild(group);this.separatorHeight=this.dividerSpanElement.clientHeight;this.lastBackgroundHeight=null;},_renderChildren:function(nApps){var isRTL=(document.documentElement.dir==='rtl');if(!this.detail.collapsed){this.element.classList.remove('collapsed');return;}
|
||||
this.element.classList.add('collapsed');var y=this.y;var index=this.detail.index;var width=Math.round((this.grid.layout.constraintSize-
|
||||
COLLAPSED_GROUP_MARGIN_LEFT-COLLAPSED_GROUP_MARGIN_RIGHT)/COLLAPSED_GROUP_SIZE);var x=isRTL?(this.grid.layout.constraintSize-COLLAPSED_GROUP_MARGIN_RIGHT):COLLAPSED_GROUP_MARGIN_LEFT;y+=this.headerHeight;var maxGridItemWidth=this.grid.layout.constraintSize/this.grid.layout.minIconsPerRow;this.collapseRatio=(maxGridItemWidth/this.grid.layout.gridItemWidth)*COLLAPSE_RATIO;for(var i=index-nApps;i<index;i++){var item=this.grid.items[i];if(this.detail.collapsed){item.scale=this.collapseRatio;var itemVisible=(i-(index-nApps))<COLLAPSED_GROUP_SIZE;if(!itemVisible){item.setCoordinates(isRTL?x+width:x-width,y);}else{item.setCoordinates(x,y);x+=isRTL?-width:width;}
|
||||
item.render();item.element.classList.add('collapsed');if(!itemVisible){item.element.classList.add('hidden');}}}},getRealYPosition:function(nApps){if(this.detail.collapsed){return this.y;}
|
||||
return this.grid.items[this.detail.index-nApps].y-
|
||||
this.headerHeight;},render:function(){var createdElements=false;if(!this.element){createdElements=true;this._createElement();}
|
||||
var nApps=this.size;this._renderChildren(nApps);var y=this.getRealYPosition(nApps);if(y!==this.lastY){this.headerSpanElement.style.transform='translate(0px, '+y+'px)';}
|
||||
if(this.toggleElement){var toggleLabel=this.detail.collapsed?'collapsed':'expanded';this.toggleElement.dataset.l10nId='gaia-grid-toggle-'+toggleLabel;}
|
||||
if(this.detail.collapsed){this.backgroundHeight=Math.round(this.collapseRatio*this.grid.layout.gridIconSize*1.5);}else{var height=Math.ceil(nApps/this.grid.layout.cols);this.backgroundHeight=(height||1)*this.grid.layout.gridItemHeight;}
|
||||
this.backgroundHeight+=this.headerHeight;if(y!=this.lastY||this.backgroundHeight!==this.lastBackgroundHeight){this.backgroundSpanElement.style.transform='translate(0px, '+y+'px) scale(1, '+this.backgroundHeight+')';this.shadowSpanElement.style.transform='translateY('+y+'px)';this.shadowSpanElement.style.height=this.backgroundHeight+'px';this.dividerSpanElement.style.transform='translate(0px, '+(y+this.backgroundHeight)+'px)';}
|
||||
this.lastBackgroundHeight=this.backgroundHeight;this.lastY=y;this.backgroundHeight+=this.separatorHeight;if(createdElements){this.element.clientTop;this.element.classList.remove('newly-created');}},forEachItem:function(callback){var nApps=this.size;var index=this.detail.index;for(var i=index-nApps;i<index;i++){callback(this.grid.items[i]);}},setActive:function(active){GaiaGrid.GridItem.prototype.setActive.call(this,active);this.collapse();var callback=active?function(item){item.element.classList.add('active');}:function(item){item.element.classList.remove('active');};this.forEachItem(callback);},_rerenderOnToggle:function(){if(this.pendingCollapseTimeout){clearTimeout(this.pendingCollapseTimeout);this.pendingCollapseTimeout=null;}
|
||||
if(this.toggleElement){this.toggleElement.classList.add('toggling');setTimeout(()=>{this.toggleElement.classList.remove('toggling');},TOGGLE_TIMEOUT);}
|
||||
this.pendingCollapseTimeout=setTimeout(()=>{this.detail.collapsed=this.pendingCollapse;this.pendingCollapseTimeout=null;if(!this.detail.collapsed){this.forEachItem(function(item){item.scale=1;if(item.element){item.element.classList.remove('collapsed');item.element.classList.remove('hidden');}});}
|
||||
if(this.active){this.render();}
|
||||
this.grid.render();var dragging=this.grid.dragdrop&&this.grid.dragdrop.inDragAction;if(dragging){this.grid.dragdrop.updateIconPosition();}else{window.dispatchEvent(new CustomEvent('gaiagrid-saveitems'));this.requestAttention();}},20);},collapse:function(){if(this.detail.collapsed){return;}
|
||||
this.pendingCollapse=true;this._rerenderOnToggle();},expand:function(){if(!this.detail.collapsed){return;}
|
||||
this.pendingCollapse=false;this._rerenderOnToggle();},launch:function(target){if(target!==this.toggleElement){return;}
|
||||
if(this.detail.collapsed){this.expand();}else{this.collapse();}},remove:function(){if(this.element){this.element.parentNode.removeChild(this.element);}},isDraggable:function(){return true;},requestAttention:function(){var rect={x:0,y:this.getRealYPosition(this.size),width:this.gridWidth*this.grid.layout.gridItemWidth,height:this.backgroundHeight};this.grid.element.dispatchEvent(new CustomEvent('gaiagrid-attention',{detail:rect}));}};exports.GaiaGrid.Divider=Group;}(window));
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
'use strict';
|
||||
/* global GaiaGrid */
|
||||
/* global GridIconRenderer */
|
||||
/* global MozActivity */
|
||||
/* jshint nonew: false */
|
||||
|
||||
(function(exports) {
|
||||
|
||||
const TYPE = 'marketplace-app';
|
||||
|
||||
/**
|
||||
* Represents a single bookmark icon on the homepage.
|
||||
*/
|
||||
function MarketPlaceApp(record) {
|
||||
this.detail = record;
|
||||
this.detail.type = TYPE;
|
||||
}
|
||||
|
||||
MarketPlaceApp.prototype = {
|
||||
|
||||
__proto__: GaiaGrid.Bookmark.prototype,
|
||||
|
||||
renderer: GridIconRenderer.TYPE.STANDARD,
|
||||
|
||||
/**
|
||||
* Returns the icon image path.
|
||||
*/
|
||||
get icon() {
|
||||
var icon = this._accurateIcon;
|
||||
|
||||
if (!icon) {
|
||||
icon = this._accurateIcon = this.closestIconFromList(
|
||||
this.detail.icons);
|
||||
}
|
||||
|
||||
return icon;
|
||||
},
|
||||
|
||||
launch: function() {
|
||||
new MozActivity({
|
||||
name: 'marketplace-app',
|
||||
data: {
|
||||
slug: this.detail.slug
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
exports.GaiaGrid.MarketPlaceApp = MarketPlaceApp;
|
||||
|
||||
}(window));
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
;'use strict';(function(exports){const IDENTIFIER_SEP='-';var MOZAPP_EVENTS=['downloadsuccess','downloaderror','downloadavailable','downloadapplied','progress'];var APP_LOADING='loading';var APP_ERROR='error';var APP_UNRECOVERABLE='unrecoverable';var APP_PAUSED='paused';var APP_READY='ready';function localizeString(str){var userLang=document.documentElement.lang;if(navigator.mozL10n&&navigator.mozL10n.ctx.qps.indexOf(userLang)!==-1){return navigator.mozL10n.qps[userLang].translate(str);}
|
||||
return str;}
|
||||
function Mozapp(app,entryPoint,details){this.app=app;this.entryPoint=entryPoint;this.detail={type:'app',manifestURL:app.manifestURL,entryPoint:entryPoint,index:0,decoratedIconBlob:details&&details.decoratedIconBlob};MOZAPP_EVENTS.forEach(function(type){this.app['on'+type]=this.handleEvent.bind(this);},this);this.setAppState(this._determineState(app));}
|
||||
Mozapp.HIDDEN_ROLES=['system','input','homescreen','search','addon','langpack'];Mozapp.prototype={__proto__:GaiaGrid.GridItem.prototype,_isHiddenRole:function(){var manifest=this.app.manifest;if(!manifest||!manifest.role){return null;}
|
||||
return Mozapp.HIDDEN_ROLES.indexOf(manifest.role)!==-1;},_determineState:function(app){if(app.installState==='pending'&&!app.downloadAvailable&&!app.readyToApplyDownload){return APP_UNRECOVERABLE;}
|
||||
if(app.downloading){return APP_LOADING;}
|
||||
if(app.downloadError&&app.downloadError.name){if(app.downloadError.name==='DOWNLOAD_CANCELED'){return APP_PAUSED;}
|
||||
return APP_ERROR;}
|
||||
if(app.installState==='pending'){return APP_PAUSED;}
|
||||
return APP_READY;},handleEvent:function(event){switch(event.type){case'progress':case'downloaderror':case'downloadsuccess':this.setAppState(this._determineState(this.app));break;case'downloadapplied':if(this._isHiddenRole()){console.warn('Removing hidden app from the grid',this.name);return this.removeFromGrid();}
|
||||
delete this._accurateIcon;delete this._accurateIconSize;this.setAppState(this._determineState(this.app));this.renderIcon();window.dispatchEvent(new CustomEvent('downloadapplied',{detail:{id:this.app.manifestURL}}));break;}},fetchIconBlob:function(){if(!this._accurateIconSize){this._accurateIconSize=this.closestIconSizeFromList(this.descriptor.icons);}
|
||||
var result=this._accurateIconSize?navigator.mozApps.mgmt.getIcon(this.app,this._accurateIconSize,this.entryPoint||''):GaiaGrid.GridItem.prototype.fetchIconBlob.call(this);return result;},get pixelHeight(){return this.grid.layout.gridItemHeight;},gridWidth:1,get name(){var userLang=document.documentElement.lang;if(navigator.mozL10n&&userLang in navigator.mozL10n.qps){return navigator.mozL10n.qps[userLang].translate(this.descriptor.short_name||this.descriptor.name);}
|
||||
var locales=this.descriptor.locales;var localized=locales&&locales[userLang]&&(locales[userLang].short_name||locales[userLang].name);return localized||this.descriptor.short_name||this.descriptor.name;},asyncName:function(){var userLang=document.documentElement.lang;var ep=this.entryPoint||undefined;if(!this.app.getLocalizedValue){return new Promise((resolve,reject)=>{reject();});}
|
||||
return this.app.getLocalizedValue('short_name',userLang,ep).then(shortName=>localizeString(shortName),this.app.getLocalizedValue.bind(this.app,'name',userLang,ep)).then(name=>localizeString(name),()=>this.name);},get icon(){var icon=this._accurateIcon;if(!icon){icon=this._accurateIcon=this.closestIconFromList(this.descriptor.icons);}
|
||||
return icon;},get descriptor(){var manifest=this.app.manifest||this.app.updateManifest;if(this.entryPoint&&manifest.entry_points&&manifest.entry_points[this.entryPoint]){return manifest.entry_points[this.entryPoint];}
|
||||
return manifest;},identifierSeparator:IDENTIFIER_SEP,get identifier(){var identifier=[this.app.manifestURL];if(this.entryPoint){identifier.push(this.entryPoint);}
|
||||
return identifier.join(IDENTIFIER_SEP);},isRemovable:function(){return this.app.removable;},unrecoverableError:function(){navigator.mozApps.mgmt.uninstall(this.app);},cancel:function(){var dialog=new ConfirmDialogHelper({type:'pause',title:{id:'gaia-grid-stop-download-title',args:{name:this.name}},body:'gaia-grid-stop-download-body',cancel:{title:'gaia-grid-cancel'},confirm:{title:'gaia-grid-stop-download-action',type:'danger',cb:()=>this.app.cancelDownload()}});dialog.show(document.body);},resume:function(){var dialog=new ConfirmDialogHelper({type:'resume',title:'gaia-grid-resume-download-title',body:{id:'gaia-grid-resume-download-body',args:{name:this.name}},cancel:{title:'gaia-grid-cancel'},confirm:{title:'gaia-grid-resume-download-action',cb:()=>{this.setAppState(APP_LOADING);this.app.download();}}});dialog.show(document.body);},setAppState:function(state){this.appState=state;if(this.element){this.element.dataset.appState=state;}},render:function(){var needsStateSet=!this.element;GaiaGrid.GridItem.prototype.render.apply(this,arguments);if(needsStateSet){this.setAppState(this.appState);}},launch:function(){var app=this.app;switch(this._determineState(app)){case APP_UNRECOVERABLE:return this.unrecoverableError();case APP_ERROR:case APP_PAUSED:return this.resume();case APP_LOADING:return this.cancel();}
|
||||
window.performance.mark('appLaunch@'+app.origin);if(this.entryPoint){return app.launch(this.entryPoint);}
|
||||
return app.launch();}};exports.GaiaGrid.Mozapp=Mozapp;}(window));
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
;'use strict';(function(exports){function Placeholder(){this.detail={type:'placeholder',index:0};}
|
||||
Placeholder.prototype={__proto__:GaiaGrid.GridItem.prototype,get pixelHeight(){return this.grid.layout.gridItemHeight;},createsGroupOnDrop:false,gridWidth:1,persistToDB:false,get name(){return'';},render:function(){if(!this.element){var tile=document.createElement('div');tile.className='icon placeholder';tile.style.height=this.pixelHeight+'px';this.element=tile;this.grid.element.appendChild(tile);}
|
||||
this.transform(this.x,this.y,this.grid.layout.percent);},remove:function(){if(this.element){this.element.parentNode.removeChild(this.element);}}};exports.GaiaGrid.Placeholder=Placeholder;}(window));
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
;window.GaiaGrid=(function(win){'use strict';var proto=Object.create(HTMLElement.prototype);var baseurl=window.GaiaGridBaseurl||'/shared/elements/gaia_grid/';proto.createdCallback=function(){var shadow=this.createShadowRoot();this._template=template.content.cloneNode(true);this._styleHack();this._grid=new GridView({element:this,features:{dragdrop:this.getAttribute('dragdrop')!==null,zoom:this.getAttribute('zoom')!==null,disableSections:this.getAttribute('disable-sections')!==null}});shadow.appendChild(this._template);};proto.add=function(){this._grid.add.apply(this._grid,arguments);};proto.clear=function(){this._grid.clear.apply(this._grid,arguments);};proto.render=function(){this._grid.layout.calculateSize();this._grid.render.apply(this._grid,arguments);};proto.start=function(){this._grid.start.apply(this._grid,arguments);};proto.stop=function(){this._grid.stop.apply(this._grid,arguments);};proto.getIcons=function(){return this._grid.icons;};proto.getItems=function(){return this._grid.items;};proto.getIcon=function(identifier){return this._grid.icons[identifier];};proto.removeIconByIdentifier=function(identifier){delete this._grid.icons[identifier];};proto.removeItemByIndex=function(itemIndex){this._grid.items.splice(itemIndex,1);};proto.popDivider=function(){var items=this._grid.items;if(items.length&&items[items.length-1].detail.type==='divider'){return items.pop();}
|
||||
return null;};proto.appendItem=function(item){var items=this._grid.items;var lastIndex=items.length-1;if(items[lastIndex].detail.type==='divider'){this.add(item,lastIndex);}else{this.add(item);}};proto.appendItemToExpandedGroup=function(item){var items=this._grid.items;var lastIndex=items.length-1;if(items[lastIndex].detail.type==='divider'&&items[lastIndex].detail.collapsed){items[lastIndex].expand();}
|
||||
this.appendItem(item);};proto.setEditHeaderElement=function(element){if(this._grid.dragdrop){this._grid.dragdrop.editHeaderElement=element;}};Object.defineProperty(proto,'maxIconSize',{get:function(){return this._grid.layout.gridMaxIconSize;}});proto.getIndexLastIcon=function(){var items=this._grid.items;for(var i=this._grid.items.length-1;i>=0;i--){if(items[i]instanceof GaiaGrid.Mozapp){return i;}}};proto.removeNonVisualElements=function(){var nonVisualElements=[GaiaGrid.Placeholder];function isNonVisual(elem){var retVal=false;for(var i=0,iLen=nonVisualElements.length;i<iLen&&!retVal;i++){retVal=elem instanceof nonVisualElements[i];}
|
||||
return retVal;}
|
||||
var i=0;var iLen=this._grid.items.length;while(i<iLen){this._grid.items[i].detail.index=i;if(isNonVisual(this._grid.items[i])){this._grid.items.splice(i,1);iLen-=1;}else{i+=1;}}};proto.moveTo=function(orig,dst){this._grid.items.splice(dst,0,this._grid.items.splice(orig,1)[0]);};proto._styleHack=function(){var style=this._template.querySelector('style');this.appendChild(style.cloneNode(true));};var stylesheet=baseurl+'style.css';var template=document.createElement('template');template.innerHTML=`<style scoped>
|
||||
@import url(${stylesheet});</style>
|
||||
<content></content>`;return document.registerElement('gaia-grid',{prototype:proto});})(window);
|
||||
|
|
@ -0,0 +1,409 @@
|
|||
.icon[data-app-state="loading"]:after {
|
||||
content: "";
|
||||
background: no-repeat top center url('images/app_install_spinner.png');
|
||||
background-size: contain;
|
||||
height: 8.4rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
/**
|
||||
Keyframe must be defined outside of the web component.
|
||||
See bug 1018269
|
||||
*/
|
||||
|
||||
animation: rotate 2.25s linear infinite;
|
||||
}
|
||||
|
||||
.icon[data-app-state="loading"] {
|
||||
/**
|
||||
We must align this value with the value of [data-app-state]:after height the background size
|
||||
here is overridden at the element level elsewhere which causes the spinner to be aligned too
|
||||
low.
|
||||
*/
|
||||
background-size: 8.4rem !important;
|
||||
background-image: url('images/app_installing.png') !important;
|
||||
}
|
||||
|
||||
.icon[data-app-state="unrecoverable"] {
|
||||
background-image: url('images/app_install_unrecoverable.png') !important;
|
||||
}
|
||||
|
||||
.icon[data-app-state="error"] {
|
||||
background-image: url('images/app_install_failed.png') !important;
|
||||
}
|
||||
|
||||
.icon[data-app-state="paused"] {
|
||||
background-image: url('images/app_install_canceled.png') !important;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
transform-origin: 0 0;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
background: no-repeat top center;
|
||||
z-index: 3;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.icon.launching {
|
||||
opacity: .65;
|
||||
}
|
||||
|
||||
/* XXX: Override the .remove element */
|
||||
.edit-mode .collection.hovered .remove {
|
||||
background: url(images/add.png) no-repeat;
|
||||
background-size: 2rem;
|
||||
}
|
||||
|
||||
.icon p {
|
||||
pointer-events: none;
|
||||
height: 3.2rem;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.icon .title {
|
||||
display: inline-block;
|
||||
margin-top: 0.1rem;
|
||||
/* We need this rule in order not to hide the drop shadow */
|
||||
padding: 0 0.2rem 1rem;
|
||||
text-shadow: 0.1rem 0.1rem 0.3rem rgba(0, 0, 0, 0.3),
|
||||
0.2rem 0.4rem 1rem rgba(0, 0, 0, 0.4);
|
||||
font-size: 1.4rem;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: calc(100% - 0.4rem);
|
||||
box-sizing: border-box;
|
||||
vertical-align: top;
|
||||
transition: opacity var(--transition-duration);
|
||||
}
|
||||
|
||||
/* We allow more space for text in the search app by hooking into the text-rows attribute on gaia-grid. */
|
||||
[text-rows="3"] .icon .title {
|
||||
height: 5.8rem;
|
||||
}
|
||||
|
||||
[cols="4"] .icon .title {
|
||||
/* Font size is the same independent on grid configuration */
|
||||
font-size: calc(1.2rem * 1.333);
|
||||
margin-top: 0.5rem;
|
||||
line-height: 1.94rem;
|
||||
}
|
||||
|
||||
.edit-mode .icon.collapsed {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.icon.collapsed .title {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.icon.hidden {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.divider {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
padding-top: 2.3rem;
|
||||
border-left: 0.6rem solid transparent;
|
||||
border-right: 0.6rem solid transparent;
|
||||
box-sizing: border-box;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
[cols="4"] .divider {
|
||||
padding-top: 1.6rem;
|
||||
}
|
||||
|
||||
.divider span.spacer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
display: block;
|
||||
background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0.5));
|
||||
margin: 0 25%;
|
||||
width: 50%;
|
||||
height: 0.2rem;
|
||||
transition: opacity var(--transition-duration);
|
||||
}
|
||||
|
||||
.dragging .icon.active:not(.hidden) {
|
||||
z-index: 6;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.dragging .divider:not(.group),
|
||||
.icon:not(.active),
|
||||
.dropped {
|
||||
transition: transform var(--transition-duration),
|
||||
opacity var(--transition-duration);
|
||||
}
|
||||
|
||||
.icon.active {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.edit-mode .icon .remove {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0.1rem;
|
||||
left: 0.5rem;
|
||||
width: 2.6rem;
|
||||
height: 2.6rem;
|
||||
background: url(images/remove.png) no-repeat;
|
||||
background-size: 2rem;
|
||||
/*
|
||||
Ensure that remove is on top of the icon and has some extra
|
||||
padding so it is easy to click.
|
||||
*/
|
||||
z-index: 200;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.icon .remove,
|
||||
.icon.collapsed .remove,
|
||||
.edit-mode .icon.active .remove {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.edit-mode .icon.editable .title {
|
||||
background-color: rgba(132, 132, 132, 0.7);
|
||||
border-radius: 2rem;
|
||||
margin-top: .4rem;
|
||||
padding: 0 1rem;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/*
|
||||
Disable events for placeholders, so we don't trigger touch events in edit mode.
|
||||
We only do this in edit-mode, otherwise we might trigger entering edit mode
|
||||
instead of the context menu.
|
||||
*/
|
||||
.edit-mode .placeholder {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#confirm-message {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.dragging .group.active {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.divider.group {
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.group > span {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transition: background-color var(--transition-duration),
|
||||
opacity var(--transition-duration);
|
||||
}
|
||||
|
||||
.group:not(.active):not(.newly-created) > span {
|
||||
transition: background-color var(--transition-duration),
|
||||
opacity var(--transition-duration),
|
||||
transform var(--transition-duration);
|
||||
}
|
||||
|
||||
.group.active > span {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.group .header {
|
||||
height: 4rem;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.group .header span,
|
||||
.group .header button {
|
||||
position: absolute;
|
||||
height: 4rem;
|
||||
top: 0;
|
||||
|
||||
background-position: center top;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 2rem;
|
||||
|
||||
transition: transform 0.25s, opacity 0.25s;
|
||||
}
|
||||
|
||||
.group .header .gripper {
|
||||
left: calc(50% - 4.2rem);
|
||||
width: 8.4rem;
|
||||
background-image: url('images/move_gripper.png');
|
||||
opacity: 0;
|
||||
transform: translate(0, -100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.edit-mode .group:not(.collapsed) .header .gripper {
|
||||
opacity: 1;
|
||||
transform: translate(0, 0);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.group .header .toggle {
|
||||
width: 5.34rem;
|
||||
right: 0;
|
||||
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
background-color: transparent;
|
||||
background-image: url('images/collapse_arrow.png');
|
||||
transform-origin: 50% 1.6rem;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.group .header .toggle.toggling {
|
||||
opacity: 0.5;
|
||||
transition: transform 0.25s;
|
||||
}
|
||||
|
||||
.group.collapsed .header .toggle {
|
||||
transform: translateY(2rem) rotateZ(180deg);
|
||||
}
|
||||
|
||||
.group.active .header .toggle {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.group .background {
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
height: 0.1rem;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.group.odd:not(.newly-created) .background,
|
||||
.edit-mode .group:not(.newly-created) .background {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.group.active .background {
|
||||
background-color: rgba(51, 51, 51, 0.9);
|
||||
}
|
||||
|
||||
.group.hovering .background,
|
||||
.group.drop-target .background {
|
||||
background-color: rgba(27, 185, 225, 0.5);
|
||||
}
|
||||
|
||||
.group .shadow {
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.edit-mode .group.active .shadow {
|
||||
background-color: transparent;
|
||||
box-shadow: 0 0.9rem 1.2rem rgba(0, 0, 0, 0.63);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.group .separator {
|
||||
margin: 0;
|
||||
height: 0.8rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.group .separator > span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: transform 0.25s, opacity 0.25s;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.group.odd .separator {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.group.odd .separator > span {
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.edit-mode .group .separator,
|
||||
.edit-mode .group .separator > span {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* For preventing entering edit mode when long-pressing on a placeholder */
|
||||
.edit-mode .group .background,
|
||||
.edit-mode .group .shadow,
|
||||
|
||||
.group.collapsed .header,
|
||||
.group.collapsed .background,
|
||||
.group.collapsed .shadow {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.edit-mode .group.collapsed .background {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.dragging .group:not(.active) .separator {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.dragging .group:not(.active):not(.invalid-drop) .separator > span {
|
||||
background-color: #0095dd;
|
||||
transform: scaleY(0.325);
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.dragging .group.hovered:not(.active) .separator > span {
|
||||
transform: scaleY(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* A hint element for dragging items to the top of the group */
|
||||
.edit-mode::after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 0.8rem;
|
||||
z-index: 2;
|
||||
opacity: 0;
|
||||
background-color: #0095dd;
|
||||
|
||||
position: relative;
|
||||
top: -0.8rem;
|
||||
transition: opacity 0.25s;
|
||||
}
|
||||
|
||||
.edit-mode.hover-over-top::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Shift container downwards when hovering over the top to reveal the group
|
||||
* creation hint.
|
||||
*/
|
||||
.edit-mode {
|
||||
transition: transform 0.25s;
|
||||
}
|
||||
|
||||
.edit-mode.hover-over-top {
|
||||
transform: translateY(0.8rem);
|
||||
}
|
||||
|
||||
/* RTL View */
|
||||
:-moz-dir(rtl) .group .header .toggle {
|
||||
left: 0;
|
||||
right: unset;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
Some css properties are global (keyframes) and cannot be specified
|
||||
to to only apply to our shadow dom so we hack around this by including
|
||||
this file without scoping it.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
Bug 1018269 - we need to specify the keyframe outside
|
||||
of the web component...
|
||||
*/
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotate(1deg)
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg)
|
||||
}
|
||||
}
|
||||
|
||||
:-moz-dir(rtl) gaia-grid {
|
||||
direction: ltr;
|
||||
}
|
||||
|
After Width: | Height: | Size: 178 B |
|
After Width: | Height: | Size: 245 B |
|
|
@ -0,0 +1,62 @@
|
|||
'use strict';
|
||||
/* global ComponentUtils */
|
||||
|
||||
window.GaiaMenu = (function(win) {
|
||||
// Extend from HTMLElement prototype
|
||||
var proto = Object.create(HTMLElement.prototype);
|
||||
|
||||
// Allow baseurl to be overridden (used for demo page)
|
||||
var baseurl = window.GaiaMenuBaseurl ||
|
||||
'/shared/elements/gaia_menu/';
|
||||
|
||||
proto.createdCallback = function () {
|
||||
var shadow = this.createShadowRoot();
|
||||
|
||||
this._template = template.content.cloneNode(true);
|
||||
|
||||
var cancelButton = this._template.querySelector('.gaia-menu-cancel button');
|
||||
|
||||
cancelButton.addEventListener('click', function () {
|
||||
this.hide();
|
||||
this.dispatchEvent(new CustomEvent('gaiamenu-cancel'));
|
||||
}.bind(this));
|
||||
|
||||
shadow.appendChild(this._template);
|
||||
|
||||
ComponentUtils.style.call(this, baseurl);
|
||||
|
||||
document.l10n.ready.then(this.localize.bind(this));
|
||||
document.addEventListener('DOMRetranslated', this.localize.bind(this));
|
||||
};
|
||||
|
||||
proto.localize = function() {
|
||||
document.l10n.formatValue('gaia-menu-cancel').then(value => {
|
||||
this.shadowRoot.querySelector('button').textContent = value;
|
||||
});
|
||||
};
|
||||
|
||||
proto.show = function() {
|
||||
this.removeAttribute('hidden');
|
||||
};
|
||||
|
||||
proto.hide = function() {
|
||||
this.setAttribute('hidden', 'hidden');
|
||||
};
|
||||
|
||||
var template = document.createElement('template');
|
||||
|
||||
template.innerHTML =
|
||||
`<form role="dialog" data-type="action">
|
||||
<content select="header"></content>
|
||||
<menu>
|
||||
<content select="button"></content>
|
||||
<span class="gaia-menu-cancel">
|
||||
<button>Cancel</button>
|
||||
</span>
|
||||
</menu>
|
||||
</form>`;
|
||||
|
||||
// Register and return the constructor
|
||||
return document.registerElement('gaia-menu', { prototype: proto });
|
||||
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,314 @@
|
|||
/* ----------------------------------
|
||||
* gaia_menu
|
||||
* ---------------------------------- */
|
||||
|
||||
/* default alignment follows the UI direction, not the content direction */
|
||||
:-moz-dir(ltr) [dir] { text-align: left; }
|
||||
:-moz-dir(rtl) [dir] { text-align: right; }
|
||||
|
||||
/* Main dialog setup */
|
||||
gaia-menu {
|
||||
background-color: #2d2d2d;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 0 0 7rem;
|
||||
/**
|
||||
* Using "font-size: 0" to avoid the unwanted visual space (about 3px) created
|
||||
* by white spaces and line breaks in the code between inline-block elements.
|
||||
*/
|
||||
font-size: 0;
|
||||
color: #fff;
|
||||
display: block;
|
||||
transition: transform ease-in-out var(--transition-duration),
|
||||
visibility var(--transition-duration);
|
||||
}
|
||||
|
||||
gaia-menu[hidden] {
|
||||
transform: translateY(100%);
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
gaia-menu:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 0.1rem;
|
||||
height: 100%;
|
||||
margin-inline-start: -0.1rem;
|
||||
}
|
||||
|
||||
header {
|
||||
-moz-box-sizing: border-box;
|
||||
font-size: 1.6rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
height: 5rem;
|
||||
line-height: 4.9rem;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
font-weight: normal;
|
||||
padding: 0 3rem;
|
||||
border-bottom: 0.1rem solid #616262;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 1.6rem;
|
||||
line-height: 4.9rem;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Generic set of actions in toolbar */
|
||||
header menu.toolbar {
|
||||
height: 100%;
|
||||
margin: 0 -3rem;
|
||||
margin-inline-start: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
header:-moz-dir(ltr) menu.toolbar { float: right; }
|
||||
header:-moz-dir(rtl) menu.toolbar { float: left; }
|
||||
|
||||
header menu.toolbar a,
|
||||
header menu.toolbar button {
|
||||
-moz-box-sizing: border-box;
|
||||
position: relative;
|
||||
width: auto;
|
||||
min-width: 5rem;
|
||||
height: 4.9rem;
|
||||
margin-bottom: 0;
|
||||
padding: 0 1rem;
|
||||
border-radius: 0;
|
||||
line-height: 4.9rem;
|
||||
background: none;
|
||||
text-align: center;
|
||||
text-shadow: none;
|
||||
z-index: 5;
|
||||
}
|
||||
header:-moz-dir(ltr) menu.toolbar a,
|
||||
header:-moz-dir(ltr) menu.toolbar button {
|
||||
float: left;
|
||||
}
|
||||
header:-moz-dir(rtl) menu.toolbar a,
|
||||
header:-moz-dir(rtl) menu.toolbar button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
header a,
|
||||
header button {
|
||||
border: none;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
font-weight: 400;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.1em;
|
||||
color: #fff;
|
||||
border-radius: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner {
|
||||
outline: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Pressed state */
|
||||
header a:active .icon:after,
|
||||
header button:active .icon:after,
|
||||
header menu.toolbar a:active,
|
||||
header menu.toolbar button:active {
|
||||
background: #008aaa;
|
||||
}
|
||||
|
||||
/* Disabled state */
|
||||
header menu.toolbar a[aria-disabled="true"],
|
||||
header menu.toolbar button[disabled] {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Icon definitions */
|
||||
header .icon {
|
||||
position: relative;
|
||||
float: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 4rem;
|
||||
height: 4.9rem;
|
||||
margin: 0 -1rem;
|
||||
background: transparent no-repeat center center / 3rem auto;
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header .icon.icon-close {
|
||||
background-image: url(images/icons/close.png);
|
||||
}
|
||||
|
||||
header .icon.icon-back {
|
||||
background-image: url(images/icons/back.png);
|
||||
}
|
||||
|
||||
/* Navigation links (back, cancel, etc) */
|
||||
header > button,
|
||||
header > a {
|
||||
width: 5rem;
|
||||
height: 4.9rem;
|
||||
background: none;
|
||||
overflow: visible;
|
||||
margin: 0 -1rem;
|
||||
margin-inline-start: -3rem;
|
||||
position: relative;
|
||||
}
|
||||
header:-moz-dir(ltr) > button,
|
||||
header:-moz-dir(ltr) > a {
|
||||
float: left;
|
||||
}
|
||||
header:-moz-dir(rtl) > button,
|
||||
header:-moz-dir(rtl) > a {
|
||||
float: right;
|
||||
}
|
||||
|
||||
header > button::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
header > button .icon,
|
||||
header > a .icon {
|
||||
position: static;
|
||||
display: block;
|
||||
width: 3rem;
|
||||
height: 4.9rem;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
header > button .icon:after,
|
||||
header > a .icon:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
offset-inline-start: 0;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
width: 3rem;
|
||||
height: 4.9rem;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
section {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 7rem;
|
||||
left: 1.5rem;
|
||||
right: 1.5rem;
|
||||
bottom: 2rem;
|
||||
font-size: 1.6rem;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
/* Specific component code */
|
||||
menu {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-height: calc(100% - 13.5rem); /*header(5rem) + footer(7rem) + padding(1.5rem)*/
|
||||
height: auto;
|
||||
padding-top: 1.5rem;
|
||||
overflow: auto;
|
||||
width: auto;
|
||||
border: none;
|
||||
background: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 7rem;
|
||||
}
|
||||
|
||||
button {
|
||||
width: calc(100% - 3rem);
|
||||
height: 4rem;
|
||||
-moz-box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
font-weight: normal;
|
||||
line-height: 4rem;
|
||||
outline: none;
|
||||
font-size: 1.6rem;
|
||||
text-shadow: none;
|
||||
padding: 0 1.2rem;
|
||||
margin: 0 1.5rem 1rem;
|
||||
background: rgba(87, 87, 87, 0.8);
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
}
|
||||
button:-moz-dir(ltr) { text-align: left; }
|
||||
button:-moz-dir(rtl) { text-align: right; }
|
||||
|
||||
span.gaia-menu-cancel {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background: #4d4d4d;
|
||||
height: 7rem;
|
||||
offset-inline-start: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
span.gaia-menu-cancel button {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
offset-inline-start: 0;
|
||||
color: #333;
|
||||
background: #d8d8d8;
|
||||
text-align: center;
|
||||
border: none;
|
||||
margin-bottom: 1.5rem;
|
||||
border-radius: 2rem;
|
||||
}
|
||||
|
||||
button:nth-last-child(2) {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
/* Press state */
|
||||
button:active,
|
||||
span.gaia-menu-cancel button:active {
|
||||
background: #00aacc;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
button[disabled] {
|
||||
background-color: rgba(87, 87, 87, 0.8);
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
button[disabled]:last-child {
|
||||
background-color: #e7e7e7;
|
||||
color: #a6a6a6;
|
||||
opacity: 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
;'use strict';(function(exports){var datastore;var DATASTORE_NAME='bookmarks_store';var readyState;var listeners=Object.create(null);function init(){return new Promise(function doInit(resolve,reject){if(readyState==='initialized'){resolve();return;}
|
||||
if(readyState==='initializing'){document.addEventListener('ds-initialized',function oninitalized(){document.removeEventListener('ds-initialized',oninitalized);resolve();});return;}
|
||||
readyState='initializing';if(!navigator.getDataStores){console.error('Bookmark store: DataStore API is not working');reject({name:'NO_DATASTORE'});readyState='failed';return;}
|
||||
navigator.getDataStores(DATASTORE_NAME).then(function(ds){if(ds.length<1){console.error('Bookmark store: Cannot get access to the Store');reject({name:'NO_ACCESS_TO_DATASTORE'});readyState='failed';return;}
|
||||
datastore=ds[0];datastore.addEventListener('change',onchangeHandler);readyState='initialized';document.dispatchEvent(new CustomEvent('ds-initialized'));resolve();},reject);});}
|
||||
function doGetAll(resolve,reject){var result=Object.create(null);var cursor=datastore.sync();function cursorResolve(task){switch(task.operation){case'update':case'add':result[task.data.id]=task.data;break;case'remove':delete result[task.data.id];break;case'clear':result=Object.create(null);break;case'done':resolve(result);return;}
|
||||
cursor.next().then(cursorResolve,reject);}
|
||||
cursor.next().then(cursorResolve,reject);}
|
||||
function get(id){return new Promise(function doGet(resolve,reject){init().then(function onInitialized(){datastore.get(id).then(resolve,reject);},reject);});}
|
||||
function getAll(){return new Promise(function doGet(resolve,reject){init().then(doGetAll.bind(null,resolve,reject),reject);});}
|
||||
function onchangeHandler(event){var operation=event.operation;var callbacks=listeners[operation];callbacks&&callbacks.forEach(function iterCallback(callback){datastore.get(event.id).then(function got(result){callback.method.call(callback.context||this,{type:operation,target:result||event});});});}
|
||||
function addEventListener(type,callback){var context;if(!(type in listeners)){listeners[type]=[];}
|
||||
var cb=callback;if(typeof cb==='object'){context=cb;cb=cb.handleEvent;}
|
||||
if(cb){listeners[type].push({method:cb,context:context});init();}}
|
||||
function removeEventListener(type,callback){if(!(type in listeners)){return false;}
|
||||
var callbacks=listeners[type];var length=callbacks.length;for(var i=0;i<length;i++){var thisCallback=callback;if(typeof thisCallback==='object'){thisCallback=callback.handleEvent;}
|
||||
if(callbacks[i]&&callbacks[i].method===thisCallback){callbacks.splice(i,1);return true;}}
|
||||
return false;}
|
||||
function add(data){return new Promise(function doAdd(resolve,reject){init().then(function onInitialized(){var id=data.url;Object.defineProperty(data,'id',{enumerable:true,configurable:false,writable:false,value:id});datastore.add(data,id).then(function add_success(){resolve(true);},function add_error(){datastore.put(data,id).then(function put_success(){resolve();},reject);});},reject);});}
|
||||
function getRevisionId(){return new Promise(function doGet(resolve,reject){init().then(function onInitialized(){resolve(datastore.revisionId);},reject);});}
|
||||
function put(data){return new Promise(function doAdd(resolve,reject){init().then(function onInitialized(){datastore.put(data,data.id).then(function success(){resolve();},reject);},reject);});}
|
||||
function remove(id){return new Promise(function doRemove(resolve,reject){init().then(function onInitialized(){datastore.remove(id).then(resolve,reject);},reject);});}
|
||||
function clear(){return new Promise(function doClear(resolve,reject){init().then(function onInitialized(){datastore.clear().then(resolve,reject);},reject);});}
|
||||
exports.BookmarksDatabase={get:get,getAll:getAll,getRevisionId:getRevisionId,addEventListener:addEventListener,removeEventListener:removeEventListener,add:add,put:put,remove:remove,clear:clear};}(window));
|
||||
|
|
@ -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,147 @@
|
|||
/* global LazyLoader */
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
var resources = ['/shared/js/component_utils.js',
|
||||
'/shared/elements/gaia_buttons/script.js',
|
||||
'/shared/elements/gaia_confirm/script.js',
|
||||
'/shared/elements/gaia_menu/script.js'];
|
||||
/**
|
||||
Generic dialog helper this _depends_ on <gaia-confirm> but is not required
|
||||
to be loaded as part of the main gaia-confirm script.
|
||||
*/
|
||||
function ConfirmDialogHelper(config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
ConfirmDialogHelper.prototype = {
|
||||
show: function(parent) {
|
||||
LazyLoader.load(resources, this._show.bind(this, parent));
|
||||
},
|
||||
|
||||
_show: function(parent) {
|
||||
var config = this.config;
|
||||
var wrapper = document.createElement('div');
|
||||
|
||||
// only include a cancel button if the config was given...
|
||||
var cancelButton = config.cancel ?
|
||||
'<button class="cancel" type="button"></button>' :
|
||||
'';
|
||||
|
||||
wrapper.innerHTML =
|
||||
'<gaia-confirm>' +
|
||||
'<h1></h1>' +
|
||||
'<p></p>' +
|
||||
'<gaia-buttons skin="dark">' +
|
||||
cancelButton +
|
||||
'<button class="confirm" type="button"></button>' +
|
||||
'</gaia-buttons>' +
|
||||
'</gaia-confirm>';
|
||||
|
||||
var element = wrapper.firstElementChild;
|
||||
|
||||
this.element = element;
|
||||
|
||||
element.dataset.type = config.type;
|
||||
element.addEventListener('confirm', this);
|
||||
element.addEventListener('cancel', this);
|
||||
|
||||
// XXX: Primarily here for pressing the home screen button.
|
||||
// The home button triggers a hashchange of the homescreen.
|
||||
window.addEventListener('hashchange', this);
|
||||
// TODO: Add visibility change handling...
|
||||
|
||||
var title = element.querySelector('h1');
|
||||
var body = element.querySelector('p');
|
||||
var cancel = element.querySelector('.cancel');
|
||||
var confirm = element.querySelector('.confirm');
|
||||
|
||||
var setL10nAttributes = function (element, options){
|
||||
if ('string' === typeof options) {
|
||||
navigator.mozL10n.setAttributes(element, options);
|
||||
}
|
||||
|
||||
if(options.id) {
|
||||
navigator.mozL10n.setAttributes(element, options.id, options.args);
|
||||
}
|
||||
};
|
||||
|
||||
setL10nAttributes(title, config.title);
|
||||
setL10nAttributes(body, config.body);
|
||||
setL10nAttributes(confirm, config.confirm.title);
|
||||
|
||||
if (config.cancel) {
|
||||
setL10nAttributes(cancel, config.cancel.title);
|
||||
}
|
||||
|
||||
if (config.confirm.type) {
|
||||
confirm.classList.add(config.confirm.type);
|
||||
}
|
||||
|
||||
document.activeElement.blur();
|
||||
element.setAttribute('hidden', '');
|
||||
parent.appendChild(element);
|
||||
|
||||
// This nested requestAnimationFrame is to work around the coalescing
|
||||
// of the style changes associated with removing of the 'hidden'
|
||||
// attribute with the creation of the element.
|
||||
// For whatever reason, flushing the style with the usual trick of
|
||||
// accessing clientTop doesn't work, and a setTimeout requires an
|
||||
// unreasonably lengthy timeout (>50ms) to work, and that may not be
|
||||
// a reliable solution.
|
||||
// This work-around, though gross, appears to work consistently without
|
||||
// introducing too much lag or extra work.
|
||||
window.requestAnimationFrame(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
element.removeAttribute('hidden');
|
||||
window.dispatchEvent(new CustomEvent('gaia-confirm-open'));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure cleanup of our hacks!
|
||||
window.removeEventListener('hashchange', this);
|
||||
|
||||
this.element.addEventListener('transitionend',
|
||||
function removeAfterHide(e) {
|
||||
if (e.target !== this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
this.element = null;
|
||||
window.dispatchEvent(new CustomEvent('gaia-confirm-close'));
|
||||
}.bind(this));
|
||||
|
||||
this.element.setAttribute('hidden', '');
|
||||
},
|
||||
|
||||
handleEvent: function(e) {
|
||||
// Ensure we hide the dialog in the face of other errors.
|
||||
this.destroy();
|
||||
|
||||
switch (e.type) {
|
||||
case 'hashchange':
|
||||
// Hashchange is only here to trigger this to call destroy.
|
||||
break;
|
||||
case 'confirm':
|
||||
var confirm = this.config.confirm.cb;
|
||||
confirm && confirm();
|
||||
break;
|
||||
case 'cancel':
|
||||
var cancel = this.config.cancel.cb;
|
||||
cancel && cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// This name is intentionally verbose.
|
||||
window.ConfirmDialogHelper = ConfirmDialogHelper;
|
||||
}(window));
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
;'use strict';(function(exports){var datastore;var DATASTORE_NAME='vertical_preferences_store';var readyState;var listeners=Object.create(null);function init(){return new Promise(function doInit(resolve,reject){if(readyState==='initialized'){resolve();return;}
|
||||
if(readyState==='initializing'){document.addEventListener('vps-initialized',function oninitalized(){document.removeEventListener('vps-initialized',oninitalized);resolve();});return;}
|
||||
readyState='initializing';if(!navigator.getDataStores){console.error('Preferences store: DataStore API is not working');reject({name:'NO_DATASTORE'});readyState='failed';return;}
|
||||
navigator.getDataStores(DATASTORE_NAME).then(function(ds){if(ds.length<1){console.error('Preferences store: Cannot get access to the Store');reject({name:'NO_ACCESS_TO_DATASTORE'});readyState='failed';return;}
|
||||
datastore=ds[0];datastore.addEventListener('change',onchangeHandler);readyState='initialized';document.dispatchEvent(new CustomEvent('vps-initialized'));resolve();},reject);});}
|
||||
function onchangeHandler(event){var operation=event.operation;var callbacks=listeners[operation];callbacks&&callbacks.forEach(function iterCallback(callback){datastore.get(event.id).then(function got(result){callback.method.call(callback.context||this,{type:operation,target:{name:event.id,value:result}});});});}
|
||||
function addEventListener(type,callback){var context;if(!(type in listeners)){listeners[type]=[];}
|
||||
var cb=callback;if(typeof cb==='object'){context=cb;cb=cb.handleEvent;}
|
||||
if(cb){listeners[type].push({method:cb,context:context});init();}}
|
||||
function removeEventListener(type,callback){if(!(type in listeners)){return false;}
|
||||
var callbacks=listeners[type];var length=callbacks.length;for(var i=0;i<length;i++){var thisCallback=callback;if(typeof thisCallback==='object'){thisCallback=callback.handleEvent;}
|
||||
if(callbacks[i]&&callbacks[i].method===thisCallback){callbacks.splice(i,1);return true;}}
|
||||
return false;}
|
||||
function get(id){return new Promise(function doGet(resolve,reject){init().then(function onInitialized(){datastore.get(id).then(resolve,reject);},reject);});}
|
||||
function put(id,value){return new Promise(function doAdd(resolve,reject){init().then(function onInitialized(){datastore.put(value,id).then(function success(){resolve();},reject);},reject);});}
|
||||
exports.verticalPreferences={get:get,put:put,addEventListener:addEventListener,removeEventListener:removeEventListener};}(window));
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* IccHelper redirect calls to ICC related APIs to correct object. IccHelper is
|
||||
* created for backward compatibility of gaia master after the patch of
|
||||
* bug 814637 landed in m-c. In the patch the interface provided by IccManager
|
||||
* was moved to a MozIcc object. Details please refer to the URL[1].
|
||||
* The helper *MUST* be removed once all gaia developement no longer depend
|
||||
* on b2g26.
|
||||
* [1]: https://wiki.mozilla.org/WebAPI/WebIccManager/Multi-SIM
|
||||
*/
|
||||
(function(exports) {
|
||||
var _iccManager = navigator.mozIccManager;
|
||||
var _iccProxy = null;
|
||||
|
||||
Object.defineProperty(exports, 'IccHelper', {
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return _iccProxy;
|
||||
},
|
||||
// This is for code that sets value to IccHelper. And for unit tests that
|
||||
// mock IccHelper.
|
||||
set: function(value) {
|
||||
_iccProxy = value;
|
||||
}
|
||||
});
|
||||
|
||||
if (_iccManager && _iccManager.getIccById) {
|
||||
var activeIccObj = null;
|
||||
|
||||
var eventListeners = {};
|
||||
var cachedEventListeners = {}; // cache on + 'eventName' event handlers
|
||||
var events = ['cardstatechange', 'iccinfochange',
|
||||
'stkcommand', 'stksessionend'];
|
||||
|
||||
var getters = ['iccInfo', 'cardState'];
|
||||
var methods = ['sendStkResponse', 'sendStkMenuSelection',
|
||||
'sendStkTimerExpiration', 'sendStkEventDownload'];
|
||||
var domRequests = ['getCardLock', 'unlockCardLock', 'setCardLock',
|
||||
'getCardLockRetryCount', 'readContacts',
|
||||
'updateContact', 'iccOpenChannel', 'iccExchangeAPDU',
|
||||
'iccCloseChannel'];
|
||||
|
||||
var getterTemplate = function(name) {
|
||||
return function() {
|
||||
if (activeIccObj) {
|
||||
return activeIccObj[name];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var methodTemplate = function(name) {
|
||||
return function() {
|
||||
if (activeIccObj) {
|
||||
return activeIccObj[name].apply(activeIccObj, arguments);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Multi-SIM API available
|
||||
var createIccProxy = function() {
|
||||
var iccProxy = {
|
||||
addEventListener: function(eventName, callback) {
|
||||
if (typeof callback !== 'function') {
|
||||
return;
|
||||
}
|
||||
if (events.indexOf(eventName) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var listeners = eventListeners[eventName];
|
||||
if (listeners == null) {
|
||||
listeners = eventListeners[eventName] = [];
|
||||
}
|
||||
if (listeners.indexOf(callback) === -1) {
|
||||
listeners.push(callback);
|
||||
}
|
||||
},
|
||||
removeEventListener: function(eventName, callback) {
|
||||
var listeners = eventListeners[eventName];
|
||||
if (listeners) {
|
||||
var index = listeners.indexOf(callback);
|
||||
if (index !== -1) {
|
||||
listeners.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getters.forEach(function(getter) {
|
||||
Object.defineProperty(iccProxy, getter, {
|
||||
enumerable: true,
|
||||
get: getterTemplate(getter)
|
||||
});
|
||||
});
|
||||
|
||||
methods.forEach(function(method) {
|
||||
iccProxy[method] = methodTemplate(method);
|
||||
});
|
||||
|
||||
domRequests.forEach(function(request) {
|
||||
iccProxy[request] = methodTemplate(request);
|
||||
});
|
||||
|
||||
events.forEach(function(eventName) {
|
||||
// Define 'on' + eventName properties
|
||||
// Assigning an event handler and adding an event listener are
|
||||
// handled separately. We need to simulate the same behavior in
|
||||
// IccHelper.
|
||||
Object.defineProperty(iccProxy, 'on' + eventName, {
|
||||
enumerable: true,
|
||||
set: function(newListener) {
|
||||
var oldListener = cachedEventListeners[eventName];
|
||||
if (oldListener) {
|
||||
iccProxy.removeEventListener(eventName, oldListener);
|
||||
}
|
||||
cachedEventListeners[eventName] = newListener;
|
||||
|
||||
if (newListener) {
|
||||
iccProxy.addEventListener(eventName, newListener);
|
||||
}
|
||||
},
|
||||
get: function() {
|
||||
return cachedEventListeners[eventName];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return iccProxy;
|
||||
};
|
||||
|
||||
// Initialize icc proxy
|
||||
_iccProxy = createIccProxy();
|
||||
if (_iccManager.iccIds && _iccManager.iccIds.length) {
|
||||
activeIccObj = _iccManager.getIccById(_iccManager.iccIds[0]);
|
||||
|
||||
if (activeIccObj) {
|
||||
// register to callback
|
||||
events.forEach(function(eventName) {
|
||||
activeIccObj.addEventListener(eventName, function(event) {
|
||||
var listeners = eventListeners[eventName];
|
||||
if (listeners) {
|
||||
listeners.forEach(function(listener) {
|
||||
listener(event);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_iccManager.oniccdetected = function(event) {
|
||||
if (_iccProxy.cardState == null) {
|
||||
activeIccObj = _iccManager.getIccById(event.iccId);
|
||||
|
||||
if (activeIccObj) {
|
||||
// register to callback
|
||||
events.forEach(function(eventName) {
|
||||
activeIccObj.addEventListener(eventName, function(event) {
|
||||
var listeners = eventListeners[eventName];
|
||||
if (listeners) {
|
||||
listeners.forEach(function(listener) {
|
||||
listener(event);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// trigger cardstatechange and iccinfochange manually when a mozIcc
|
||||
// object becomes valid (detected).
|
||||
['cardstatechange', 'iccinfochange'].forEach(function(eventName) {
|
||||
if (eventListeners[eventName]) {
|
||||
eventListeners[eventName].forEach(function(listener) {
|
||||
listener();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
_iccProxy = _iccManager;
|
||||
}
|
||||
})(window);
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
;'use strict';(function IconsHelper(exports){const ICON_CACHE_PERIOD=24*60*60*1000;const FETCH_XHR_TIMEOUT=10000;const DEBUG=false;var dataStore=null;function getDefaultIconSize(){var dpr=window.devicePixelRatio;return(dpr&&dpr>1)?142:84;}
|
||||
function sizeIsNearer(size1,size2,targetSize){var delta1=Math.abs(targetSize-size1);var delta2=Math.abs(targetSize-size2);return(delta1<=delta2);}
|
||||
function getIcon(uri,iconTargetSize,placeObj={},siteObj={}){var iconUrl=null;iconTargetSize=iconTargetSize*window.devicePixelRatio;if(siteObj.webManifestUrl&&siteObj.webManifest){iconUrl=getBestIconFromWebManifest(siteObj.webManifest,iconTargetSize);if(DEBUG&&iconUrl){console.log('Icon from Web Manifest');}}
|
||||
if(!iconUrl&&siteObj.manifest&&siteObj.manifest.icons){iconUrl=getBestIconFromWebManifest({icons:_convertToWebManifestIcons(siteObj.manifest,siteObj.origin||siteObj.manifest.origin)},iconTargetSize);if(DEBUG&&iconUrl){console.log('Icon from Firefox App Manifest');}}
|
||||
if(!iconUrl&&placeObj&&placeObj.icons){iconUrl=getBestIconFromMetaTags(placeObj.icons,iconTargetSize);if(DEBUG&&iconUrl){console.log('Icon from Meta tags');}}
|
||||
if(!iconUrl){var a=document.createElement('a');a.href=uri;iconUrl=a.origin+'/favicon.ico';if(iconTargetSize){iconUrl+='#-moz-resolution='+iconTargetSize+','+iconTargetSize;}
|
||||
DEBUG&&console.log('Icon from favicon.ico');}
|
||||
return new Promise(resolve=>{resolve(iconUrl);});}
|
||||
function getIconBlob(uri,iconTargetSize,placeObj={},siteObj={}){return new Promise((resolve,reject)=>{getIcon(uri,iconTargetSize,placeObj,siteObj).then(iconUrl=>{getStore().then(iconStore=>{iconStore.get(iconUrl).then(iconObj=>{if(!iconObj||!iconObj.timestamp||Date.now()-iconObj.timestamp>=ICON_CACHE_PERIOD){return fetchIconBlob(iconUrl).then(iconBlob=>{var img=document.createElement('img');var icon=new Icon(img,uri);icon.renderBlob(iconBlob,{size:iconTargetSize,onLoad:function(blob){var iconObj={blob:blob,originalUrl:iconUrl.toString(),timestamp:Date.now()};resolve(iconObj);iconStore.add(iconObj,iconUrl);},onerror:function(e){reject(`Failed to fetch icon ${iconUrl}`);}});}).catch(err=>{reject(`Failed to fetch icon ${iconUrl}: ${err}`);});}
|
||||
return resolve(iconObj);}).catch(err=>{reject(`Failed to get icon from dataStore: ${err}`);});}).catch(err=>{reject(`Error opening the dataStore: ${err}`);});});});}
|
||||
function setElementIcon(icon,targetSize){return getIconBlob(icon.bookmark.url,targetSize,icon.bookmark,icon.bookmark).then(iconObj=>{if(iconObj.blob){icon.icon=iconObj.blob;return Promise.resolve();}else if(icon.bookmark.icon){return fetchIconBlob(icon.bookmark.icon).then(iconBlob=>{icon.icon=iconBlob;return Promise.resolve();},Promise.reject.bind(Promise));}
|
||||
return Promise.reject('No icon data found');},Promise.reject.bind(Promise));}
|
||||
function getBestIconFromWebManifest(webManifest,iconSize){var icons=webManifest.icons;if(!icons){return null;}
|
||||
var maxSize=10000;var bestSize=maxSize;var iconURL=null;iconSize=iconSize||getDefaultIconSize();icons.forEach((potentialIcon)=>{if(!iconURL){iconURL=potentialIcon.src;}
|
||||
var sizes=Array.from(potentialIcon.sizes);var nearestSize=getNearestSize(sizes,iconSize,bestSize);if(nearestSize!==bestSize&&sizeIsNearer(nearestSize,bestSize,iconSize)){iconURL=potentialIcon.src;bestSize=nearestSize;}});return iconURL?iconURL:null;}
|
||||
function _convertToWebManifestIcons(manifest,origin){return Object.keys(manifest.icons).map(function(size){var url=manifest.icons[size];var sizes=[size+'x'+size];url=url.indexOf('http')>-1?url:origin+url;return{src:new URL(url),sizes:sizes};});}
|
||||
function getBestIconFromMetaTags(icons,iconSize){if(!icons){return null;}
|
||||
iconSize=iconSize||getDefaultIconSize();var iconURL=null;var bestSize=10000;Object.keys(icons).forEach((uri)=>{var potentialIcon=icons[uri];if(!iconURL){iconURL=uri;}
|
||||
var sizes=Array.from(potentialIcon.sizes);var nearestSize=getNearestSize(sizes,iconSize,bestSize);if(nearestSize!==bestSize&&sizeIsNearer(nearestSize,bestSize,iconSize)){iconURL=uri;bestSize=nearestSize;}
|
||||
if(potentialIcon.rel==='apple-touch-icon'||potentialIcon.rel==='apple-touch-icon-precomposed'){var moreInfoUrl='https://developer.mozilla.org/en-US/'+'Apps/Build/Icon_implementation_for_apps#General_icons_for_web_apps';console.warn('Warning: The apple-touch icons are being used '+'as a fallback only. They will be deprecated in '+'the future. See '+moreInfoUrl);}});return iconURL||null;}
|
||||
function getNearestSize(sizes,iconSize,bestSize){var bogusSize=10000;if(!bestSize){bestSize=bogusSize;}
|
||||
var nearestSize=sizes.reduce(function(nearestSize,sizeString,idx){var size=widthFromSizeString(sizeString);if(isNaN(size)){return nearestSize;}
|
||||
if(sizeIsNearer(size,nearestSize,iconSize)){return size;}else{return nearestSize;}},bestSize);return nearestSize===bogusSize?-1:nearestSize;}
|
||||
function widthFromSizeString(size){size=size||'';var xIndex=size.indexOf('x');if(!xIndex){return NaN;}
|
||||
return parseInt(size.substr(0,xIndex));}
|
||||
function getStore(){return new Promise(resolve=>{if(dataStore){return resolve(dataStore);}
|
||||
navigator.getDataStores('icons').then(stores=>{dataStore=stores[0];return resolve(dataStore);});});}
|
||||
function clear(){return getStore().then(iconStore=>{iconStore.clear();});}
|
||||
function fetchIcon(iconUrl){return new Promise((resolve,reject)=>{fetchIconBlob(iconUrl).then((iconBlob)=>{var img=document.createElement('img');img.src=URL.createObjectURL(iconBlob);img.onload=()=>{var iconSize=Math.max(img.naturalWidth,img.naturalHeight);resolve({blob:iconBlob,url:iconUrl,size:iconSize,timestamp:Date.now()});};img.onerror=()=>{reject(new Error(`Error while loading image.`));};}).catch((e)=>{reject(new Error(`Error while loading image: ${e}`));});});}
|
||||
function fetchIconBlob(iconUrl){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest({mozAnon:true,mozSystem:true});xhr.open('GET',iconUrl,true);xhr.responseType='blob';xhr.timeout=FETCH_XHR_TIMEOUT;xhr.send();xhr.onload=()=>{if(xhr.readyState===XMLHttpRequest.DONE&&xhr.status===200){var iconBlob=xhr.response;resolve(iconBlob);return;}
|
||||
reject(new Error(`Got HTTP status ${xhr.status} trying to load ${iconUrl}.`));};xhr.onerror=xhr.ontimeout=()=>{reject(new Error(`Error while getting ${iconUrl}.`));};});}
|
||||
exports.IconsHelper={getIcon:getIcon,getIconBlob:getIconBlob,setElementIcon:setElementIcon,getBestIconFromWebManifest:getBestIconFromWebManifest,getBestIconFromMetaTags:getBestIconFromMetaTags,fetchIcon:fetchIcon,fetchIconBlob:fetchIconBlob,get defaultIconSize(){return getDefaultIconSize();},clear:clear,getNearestSize:getNearestSize,};})(window);
|
||||