text: /** remotestorage.js 0.10.0-beta, http://remotestorage.io, MIT-licensed **/
  (function(global){function getPromise(builder){var promise;if(typeof builder==="function"){setTimeout(function(){try{builder(promise)}catch(e){promise.reject(e)}},0)}var consumers=[],success,result;function notifyConsumer(consumer){if(success){var nextValue;if(consumer.fulfilled){try{nextValue=[consumer.fulfilled.apply(null,result)]}catch(exc){consumer.promise.reject(exc);return}}else{nextValue=result}if(nextValue[0]&&typeof nextValue[0].then==="function"){nextValue[0].then(consumer.promise.fulfill,consumer.promise.reject)}else{consumer.promise.fulfill.apply(null,nextValue)}}else{if(consumer.rejected){var ret;try{ret=consumer.rejected.apply(null,result)}catch(exc){consumer.promise.reject(exc);return}if(ret&&typeof ret.then==="function"){ret.then(consumer.promise.fulfill,consumer.promise.reject)}else{consumer.promise.fulfill(ret)}}else{consumer.promise.reject.apply(null,result)}}}function resolve(succ,res){if(result){console.error("WARNING: Can't resolve promise, already resolved!");return}success=succ;result=Array.prototype.slice.call(res);setTimeout(function(){var cl=consumers.length;if(cl===0&&!success){console.error("Possibly uncaught error: ",result,result[0]&&result[0].stack)}for(var i=0;i<cl;i++){notifyConsumer(consumers[i])}consumers=undefined},0)}promise={then:function(fulfilled,rejected){var consumer={fulfilled:typeof fulfilled==="function"?fulfilled:undefined,rejected:typeof rejected==="function"?rejected:undefined,promise:getPromise()};if(result){setTimeout(function(){notifyConsumer(consumer)},0)}else{consumers.push(consumer)}return consumer.promise},fulfill:function(){resolve(true,arguments);return this},reject:function(){resolve(false,arguments);return this}};return promise}global.promising=getPromise})(typeof window!="undefined"?window:global);(function(global){function logError(error){if(typeof error==="string"){console.error(error)}else{console.error(error.message,error.stack)}}function emitUnauthorized(status){var args=Array.prototype.slice.call(arguments);if(status===403||status===401){this._emit("error",new RemoteStorage.Unauthorized)}var p=promising();return p.fulfill.apply(p,args)}function shareFirst(path){return this.backend==="dropbox"&&path.match(/^\/public\/.*[^\/]$/)}var SyncedGetPutDelete={get:function(path,maxAge){var self=this;if(this.local){return this.local.get(path,maxAge)}else{return this.remote.get(path)}},put:function(path,body,contentType){if(shareFirst.bind(this)(path)){return SyncedGetPutDelete._wrapBusyDone.call(this,this.remote.put(path,body,contentType))}else if(this.local){return this.local.put(path,body,contentType)}else{return SyncedGetPutDelete._wrapBusyDone.call(this,this.remote.put(path,body,contentType))}},"delete":function(path){if(this.local){return this.local.delete(path)}else{return SyncedGetPutDelete._wrapBusyDone.call(this,this.remote.delete(path))}},_wrapBusyDone:function(result){var self=this;this._emit("wire-busy");return result.then(function(){var promise=promising();self._emit("wire-done",{success:true});return promise.fulfill.apply(promise,arguments)},function(err){self._emit("wire-done",{success:false});throw err})}};var RemoteStorage=function(){RemoteStorage.eventHandling(this,"ready","connected","disconnected","not-connected","conflict","error","features-loaded","connecting","authing","wire-busy","wire-done");this._pending=[];this._setGPD({get:this._pendingGPD("get"),put:this._pendingGPD("put"),"delete":this._pendingGPD("delete")});this._cleanups=[];this._pathHandlers={change:{}};this.apiKeys={};if(this.localStorageAvailable()){try{this.apiKeys=JSON.parse(localStorage["remotestorage:api-keys"])}catch(exc){}this.setBackend(localStorage["remotestorage:backend"]||"remotestorage")}var origOn=this.on;this.on=function(eventName,handler){if(eventName==="ready"&&this.remote.connected&&this._allLoaded){setTimeout(handler,0)}else if(eventName==="features-loaded"&&this._allLoaded){setTimeout(handler,0)}return origOn.call(this,eventName,handler)};this._init();this.on("ready",function(){if(this.local){setTimeout(this.local.fireInitial.bind(this.local),0)}}.bind(this))};RemoteStorage.DiscoveryError=function(message){Error.apply(this,arguments);this.message=message};RemoteStorage.DiscoveryError.prototype=Object.create(Error.prototype);RemoteStorage.Unauthorized=function(){Error.apply(this,arguments)};RemoteStorage.Unauthorized.prototype=Object.create(Error.prototype);RemoteStorage.log=function(){if(RemoteStorage._log){console.log.apply(console,arguments)}};RemoteStorage.prototype={connect:function(userAddress){this.setBackend("remotestorage");if(userAddress.indexOf("@")<0){this._emit("error",new RemoteStorage.DiscoveryError("User adress doesn't contain an @."));return}this.remote.configure(userAddress);this._emit("connecting");var discoveryTimeout=setTimeout(function(){this._emit("error",new RemoteStorage.DiscoveryError("No storage information found at that user address."))}.bind(this),5e3);RemoteStorage.Discover(userAddress,function(href,storageApi,authURL){clearTimeout(discoveryTimeout);if(!href){this._emit("error",new RemoteStorage.DiscoveryError("Failed to contact storage server."));return}this._emit("authing");this.remote.configure(userAddress,href,storageApi);if(!this.remote.connected){this.authorize(authURL)}}.bind(this))},disconnect:function(){if(this.remote){this.remote.configure(null,null,null,null)}this._setGPD({get:this._pendingGPD("get"),put:this._pendingGPD("put"),"delete":this._pendingGPD("delete")});var n=this._cleanups.length,i=0;var oneDone=function(){i++;if(i>=n){this._init();RemoteStorage.log("Done cleaning up, emitting disconnected and disconnect events");this._emit("disconnected")}}.bind(this);if(n>0){this._cleanups.forEach(function(cleanup){var cleanupResult=cleanup(this);if(typeof cleanup==="object"&&typeof cleanup.then==="function"){cleanupResult.then(oneDone)}else{oneDone()}}.bind(this))}else{oneDone()}},setBackend:function(what){this.backend=what;if(this.localStorageAvailable()){if(what){localStorage["remotestorage:backend"]=what}else{delete localStorage["remotestorage:backend"]}}},onChange:function(path,handler){if(!this._pathHandlers.change[path]){this._pathHandlers.change[path]=[]}this._pathHandlers.change[path].push(handler)},enableLog:function(){RemoteStorage._log=true},disableLog:function(){RemoteStorage._log=false},log:function(){RemoteStorage.log.apply(RemoteStorage,arguments)},setApiKeys:function(type,keys){if(keys){this.apiKeys[type]=keys}else{delete this.apiKeys[type]}if(this.localStorageAvailable()){localStorage["remotestorage:api-keys"]=JSON.stringify(this.apiKeys)}},_init:function(){var self=this,readyFired=false;function fireReady(){try{if(!readyFired){self._emit("ready");readyFired=true}}catch(e){console.error("'ready' failed: ",e,e.stack);self._emit("error",e)}}this._loadFeatures(function(features){this.log("[RemoteStorage] All features loaded");this.local=features.local&&new features.local;if(this.local&&this.remote){this._setGPD(SyncedGetPutDelete,this);this._bindChange(this.local)}else if(this.remote){this._setGPD(this.remote,this.remote)}if(this.remote){this.remote.on("connected",function(){fireReady();self._emit("connected")});this.remote.on("not-connected",function(){fireReady();self._emit("not-connected")});if(this.remote.connected){fireReady();self._emit("connected")}}this._collectCleanupFunctions();try{this._allLoaded=true;this._emit("features-loaded")}catch(exc){logError(exc);this._emit("error",exc)}this._processPending()}.bind(this))},_collectCleanupFunctions:function(){for(var i=0;i<this.features.length;i++){var cleanup=this.features[i].cleanup;if(typeof cleanup==="function"){this._cleanups.push(cleanup)}}},_loadFeatures:function(callback){var featureList=["WireClient","I18n","Dropbox","GoogleDrive","Access","Caching","Discover","Authorize","Widget","IndexedDB","LocalStorage","InMemoryStorage","Sync","BaseClient","Env"];var features=[];var featuresDone=0;var self=this;function featureDone(){featuresDone++;if(featuresDone===featureList.length){setTimeout(function(){features.caching=!!RemoteStorage.Caching;features.sync=!!RemoteStorage.Sync;["IndexedDB","LocalStorage","InMemoryStorage"].some(function(cachingLayer){if(features.some(function(feature){return feature.name===cachingLayer})){features.local=RemoteStorage[cachingLayer];return true}});self.features=features;callback(features)},0)}}function featureInitialized(name){self.log("[RemoteStorage] [FEATURE "+name+"] initialized.");features.push({name:name,init:RemoteStorage[name]._rs_init,supported:true,cleanup:RemoteStorage[name]._rs_cleanup});featureDone()}function featureFailed(name,err){self.log("[RemoteStorage] [FEATURE "+name+"] initialization failed ( "+err+")");featureDone()}function featureSupported(name,success){self.log("[RemoteStorage] [FEATURE "+name+"]"+success?"":" not"+" supported");if(!success){featureDone()}}function initFeature(name){var initResult;try{initResult=RemoteStorage[name]._rs_init(self)}catch(e){featureFailed(name,e);return}if(typeof initResult==="object"&&typeof initResult.then==="function"){initResult.then(function(){featureInitialized(name)},function(err){featureFailed(name,err)})}else{featureInitialized(name)}}featureList.forEach(function(featureName){self.log("[RemoteStorage] [FEATURE "+featureName+"] initializing...");var impl=RemoteStorage[featureName];var supported;if(impl){supported=!impl._rs_supported||impl._rs_supported();if(typeof supported==="object"){supported.then(function(){featureSupported(featureName,true);initFeature(featureName)},function(){featureSupported(featureName,false)})}else if(typeof supported==="boolean"){featureSupported(featureName,supported);if(supported){initFeature(featureName)}}}else{featureSupported(featureName,false)}})},localStorageAvailable:function(){try{return!!global.localStorage}catch(error){return false}},_setGPD:function(impl,context){function wrap(f){return function(){return f.apply(context,arguments).then(emitUnauthorized.bind(this))}}this.get=wrap(impl.get);this.put=wrap(impl.put);this.delete=wrap(impl.delete)},_pendingGPD:function(methodName){return function(){var promise=promising();this._pending.push({method:methodName,args:Array.prototype.slice.call(arguments),promise:promise});return promise}.bind(this)},_processPending:function(){this._pending.forEach(function(pending){try{this[pending.method].apply(this,pending.args).then(pending.promise.fulfill,pending.promise.reject)}catch(e){pending.promise.reject(e)}}.bind(this));this._pending=[]},_bindChange:function(object){object.on("change",this._dispatchEvent.bind(this,"change"))},_dispatchEvent:function(eventName,event){for(var path in this._pathHandlers[eventName]){var pl=path.length;var self=this;this._pathHandlers[eventName][path].forEach(function(handler){if(event.path.substr(0,pl)===path){var ev={};for(var key in event){ev[key]=event[key]}ev.relativePath=event.path.replace(new RegExp("^"+path),"");try{handler(ev)}catch(e){console.error("'change' handler failed: ",e,e.stack);self._emit("error",e)}}})}}};Object.defineProperty(RemoteStorage.prototype,"connected",{get:function(){return this.remote.connected}});global.RemoteStorage=RemoteStorage})(typeof window!=="undefined"?window:global);(function(global){var methods={addEventListener:function(eventName,handler){if(typeof eventName!=="string"){throw new Error("Argument eventName should be a string")}if(typeof handler!=="function"){throw new Error("Argument handler should be a function")}RemoteStorage.log("[Eventhandling] Adding event listener",eventName,handler);this._validateEvent(eventName);this._handlers[eventName].push(handler)},removeEventListener:function(eventName,handler){this._validateEvent(eventName);var hl=this._handlers[eventName].length;for(var i=0;i<hl;i++){if(this._handlers[eventName][i]===handler){this._handlers[eventName].splice(i,1);return}}},_emit:function(eventName){this._validateEvent(eventName);var args=Array.prototype.slice.call(arguments,1);this._handlers[eventName].forEach(function(handler){handler.apply(this,args)})},_validateEvent:function(eventName){if(!(eventName in this._handlers)){throw new Error("Unknown event: "+eventName)}},_delegateEvent:function(eventName,target){target.on(eventName,function(event){this._emit(eventName,event)}.bind(this))},_addEvent:function(eventName){this._handlers[eventName]=[]}};methods.on=methods.addEventListener;RemoteStorage.eventHandling=function(object){var eventNames=Array.prototype.slice.call(arguments,1);for(var key in methods){object[key]=methods[key]}object._handlers={};eventNames.forEach(function(eventName){object._addEvent(eventName)})}})(typeof window!=="undefined"?window:global);(function(global){var RS=RemoteStorage;var hasLocalStorage;var SETTINGS_KEY="remotestorage:wireclient";var API_2012=1,API_00=2,API_01=3,API_02=4,API_HEAD=5;var STORAGE_APIS={"draft-dejong-remotestorage-00":API_00,"draft-dejong-remotestorage-01":API_01,"draft-dejong-remotestorage-02":API_02,"https://www.w3.org/community/rww/wiki/read-write-web-00#simple":API_2012};var isArrayBufferView;if(typeof ArrayBufferView==="function"){isArrayBufferView=function(object){return object&&object instanceof ArrayBufferView}}else{var arrayBufferViews=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];isArrayBufferView=function(object){for(var i=0;i<8;i++){if(object instanceof arrayBufferViews[i]){return true}}return false}}function addQuotes(str){if(typeof str!=="string"){return str}if(str==="*"){return"*"}return'"'+str+'"'}function stripQuotes(str){if(typeof str!=="string"){return str}return str.replace(/^["']|["']$/g,"")}function readBinaryData(content,mimeType,callback){var blob=new Blob([content],{type:mimeType});var reader=new FileReader;reader.addEventListener("loadend",function(){callback(reader.result)});reader.readAsArrayBuffer(blob)}function cleanPath(path){return path.replace(/\/+/g,"/").split("/").map(encodeURIComponent).join("/")}function isFolder(path){return path.substr(-1)==="/"}function isFolderDescription(body){return body["@context"]==="http://remotestorage.io/spec/folder-description"&&typeof body["items"]==="object"}function isSuccessStatus(status){return[201,204,304].indexOf(status)>=0}function isErrorStatus(status){return[401,403,404,412].indexOf(status)>=0}var onErrorCb;RS.WireClient=function(rs){this.connected=false;RS.eventHandling(this,"change","connected","wire-busy","wire-done","not-connected");onErrorCb=function(error){if(error instanceof RemoteStorage.Unauthorized){this.configure(undefined,undefined,undefined,null)}}.bind(this);rs.on("error",onErrorCb);if(hasLocalStorage){var settings;try{settings=JSON.parse(localStorage[SETTINGS_KEY])}catch(e){}if(settings){setTimeout(function(){this.configure(settings.userAddress,settings.href,settings.storageApi,settings.token)}.bind(this),0)}}this._revisionCache={};if(this.connected){setTimeout(this._emit.bind(this),0,"connected")}};RS.WireClient.REQUEST_TIMEOUT=3e4;RS.WireClient.prototype={_request:function(method,uri,token,headers,body,getEtag,fakeRevision){if((method==="PUT"||method==="DELETE")&&uri[uri.length-1]==="/"){throw"Don't "+method+" on directories!"}var promise=promising();var revision;var reqType;var self=this;headers["Authorization"]="Bearer "+token;this._emit("wire-busy",{method:method,isFolder:isFolder(uri)});RS.WireClient.request(method,uri,{body:body,headers:headers},function(error,response){if(error){self._emit("wire-done",{method:method,isFolder:isFolder(uri),success:false});self.online=false;promise.reject(error)}else{self._emit("wire-done",{method:method,isFolder:isFolder(uri),success:true});self.online=true;if(isErrorStatus(response.status)){RemoteStorage.log("[WireClient] Error response status",response.status);if(getEtag){revision=stripQuotes(response.getResponseHeader("ETag"))}else{revision=undefined}promise.fulfill(response.status,undefined,undefined,revision)}else if(isSuccessStatus(response.status)||response.status===200&&method!=="GET"){revision=stripQuotes(response.getResponseHeader("ETag"));RemoteStorage.log("[WireClient] Successful request",revision);promise.fulfill(response.status,undefined,undefined,revision)}else{var mimeType=response.getResponseHeader("Content-Type");var body;if(getEtag){revision=stripQuotes(response.getResponseHeader("ETag"))}else{revision=response.status===200?fakeRevision:undefined}if(!mimeType||mimeType.match(/charset=binary/)){RS.WireClient.readBinaryData(response.response,mimeType,function(result){RemoteStorage.log("[WireClient] Successful request with unknown or binary mime-type",revision);promise.fulfill(response.status,result,mimeType,revision)})}else{if(mimeType&&mimeType.match(/^application\/json/)){body=JSON.parse(response.responseText)}else{body=response.responseText}RemoteStorage.log("[WireClient] Successful request",revision);promise.fulfill(response.status,body,mimeType,revision)}}}});return promise},configure:function(userAddress,href,storageApi,token){if(typeof userAddress!=="undefined"){this.userAddress=userAddress}if(typeof href!=="undefined"){this.href=href}if(typeof storageApi!=="undefined"){this.storageApi=storageApi}if(typeof token!=="undefined"){this.token=token}if(typeof this.storageApi!=="undefined"){this._storageApi=STORAGE_APIS[this.storageApi]||API_HEAD;this.supportsRevs=this._storageApi>=API_00}if(this.href&&this.token){this.connected=true;this.online=true;this._emit("connected")}else{this.connected=false}if(hasLocalStorage){localStorage[SETTINGS_KEY]=JSON.stringify({userAddress:this.userAddress,href:this.href,token:this.token,storageApi:this.storageApi})}RS.WireClient.configureHooks.forEach(function(hook){hook.call(this)}.bind(this))},stopWaitingForToken:function(){if(!this.connected){this._emit("not-connected")}},get:function(path,options){if(!this.connected){throw new Error("not connected (path: "+path+")")}if(!options){options={}}var headers={};if(this.supportsRevs){if(options.ifNoneMatch){headers["If-None-Match"]=addQuotes(options.ifNoneMatch)}}else if(options.ifNoneMatch){var oldRev=this._revisionCache[path]}var promise=this._request("GET",this.href+cleanPath(path),this.token,headers,undefined,this.supportsRevs,this._revisionCache[path]);if(isFolder(path)){return promise.then(function(status,body,contentType,revision){var itemsMap={};if(status===200&&typeof body==="object"){if(Object.keys(body).length===0){status=404}else if(isFolderDescription(body)){for(var item in body.items){this._revisionCache[path+item]=body.items[item].ETag}itemsMap=body.items}else{Object.keys(body).forEach(function(key){this._revisionCache[path+key]=body[key];itemsMap[key]={ETag:body[key]}}.bind(this))}return promising().fulfill(status,itemsMap,contentType,revision)}else{return promising().fulfill(status,body,contentType,revision)}}.bind(this))}else{return promise}},put:function(path,body,contentType,options){if(!this.connected){throw new Error("not connected (path: "+path+")")}if(!options){options={}}if(!contentType.match(/charset=/)){contentType+="; charset="+(body instanceof ArrayBuffer||isArrayBufferView(body)?"binary":"utf-8")}var headers={"Content-Type":contentType};if(this.supportsRevs){if(options.ifMatch){headers["If-Match"]=addQuotes(options.ifMatch)}if(options.ifNoneMatch){headers["If-None-Match"]=addQuotes(options.ifNoneMatch)}}return this._request("PUT",this.href+cleanPath(path),this.token,headers,body,this.supportsRevs)},"delete":function(path,options){if(!this.connected){throw new Error("not connected (path: "+path+")")}if(!options){options={}}var headers={};if(this.supportsRevs){if(options.ifMatch){headers["If-Match"]=addQuotes(options.ifMatch)}}return this._request("DELETE",this.href+cleanPath(path),this.token,headers,undefined,this.supportsRevs)}};RS.WireClient.cleanPath=cleanPath;RS.WireClient.isArrayBufferView=isArrayBufferView;RS.WireClient.readBinaryData=readBinaryData;RS.WireClient.request=function(method,url,options,callback){RemoteStorage.log("[WireClient]",method,url);callback=callback.bind(this);var timedOut=false;var timer=setTimeout(function(){timedOut=true;callback("timeout")},RS.WireClient.REQUEST_TIMEOUT);var xhr=new XMLHttpRequest;xhr.open(method,url,true);if(options.responseType){xhr.responseType=options.responseType}if(options.headers){for(var key in options.headers){xhr.setRequestHeader(key,options.headers[key])}}xhr.onload=function(){if(timedOut){return}clearTimeout(timer);callback(null,xhr)};xhr.onerror=function(error){if(timedOut){return}clearTimeout(timer);callback(error)};var body=options.body;if(typeof body==="object"){if(isArrayBufferView(body)){}else if(body instanceof ArrayBuffer){body=new Uint8Array(body)}else{body=JSON.stringify(body)}}xhr.send(body)};Object.defineProperty(RemoteStorage.WireClient.prototype,"storageType",{get:function(){if(this.storageApi){var spec=this.storageApi.match(/draft-dejong-(remotestorage-\d\d)/);return spec?spec[1]:"2012.04"}}});RS.WireClient.configureHooks=[];RS.WireClient._rs_init=function(remoteStorage){hasLocalStorage=remoteStorage.localStorageAvailable();remoteStorage.remote=new RS.WireClient(remoteStorage);this.online=true};RS.WireClient._rs_supported=function(){return!!global.XMLHttpRequest};RS.WireClient._rs_cleanup=function(remoteStorage){if(hasLocalStorage){delete localStorage[SETTINGS_KEY]}remoteStorage.removeEventListener("error",onErrorCb)}})(typeof window!=="undefined"?window:global);(function(global){var haveXMLHttpRequest,hasLocalStorage;var SETTINGS_KEY="remotestorage:discover";var cachedInfo={};RemoteStorage.Discover=function(userAddress,callback){if(userAddress in cachedInfo){var info=cachedInfo[userAddress];callback(info.href,info.type,info.authURL);return}var hostname=userAddress.split("@")[1];var params="?resource="+encodeURIComponent("acct:"+userAddress);var urls=["https://"+hostname+"/.well-known/webfinger"+params,"https://"+hostname+"/.well-known/host-meta.json"+params,"http://"+hostname+"/.well-known/webfinger"+params,"http://"+hostname+"/.well-known/host-meta.json"+params];function tryOne(){var xhr=new XMLHttpRequest;var url=urls.shift();if(!url){return callback()}RemoteStorage.log("[Discover] Trying URL",url);xhr.open("GET",url,true);xhr.onabort=xhr.onerror=function(){console.error("webfinger error",arguments,"(",url,")");tryOne()};xhr.onload=function(){if(xhr.status!==200){return tryOne()}var profile;try{profile=JSON.parse(xhr.responseText)}catch(e){RemoteStorage.log("[Discover] Failed to parse profile ",xhr.responseText,e);tryOne();return}if(!profile.links){RemoteStorage.log("[Discover] Profile has no links section ",JSON.stringify(profile));tryOne();return}var link;profile.links.forEach(function(l){if(l.rel==="remotestorage"){link=l}else if(l.rel==="remoteStorage"&&!link){link=l}});RemoteStorage.log("[Discover] Got profile",profile,"and link",link);if(link){var authURL=link.properties["http://tools.ietf.org/html/rfc6749#section-4.2"]||link.properties["auth-endpoint"],storageType=link.properties["http://remotestorage.io/spec/version"]||link.type;cachedInfo[userAddress]={href:link.href,type:storageType,authURL:authURL};if(hasLocalStorage){localStorage[SETTINGS_KEY]=JSON.stringify({cache:cachedInfo})}callback(link.href,storageType,authURL)}else{tryOne()}};xhr.send()}tryOne()};RemoteStorage.Discover._rs_init=function(remoteStorage){hasLocalStorage=remoteStorage.localStorageAvailable();if(hasLocalStorage){var settings;try{settings=JSON.parse(localStorage[SETTINGS_KEY])}catch(e){}if(settings){cachedInfo=settings.cache}}};RemoteStorage.Discover._rs_supported=function(){haveXMLHttpRequest=!!global.XMLHttpRequest;return haveXMLHttpRequest};RemoteStorage.Discover._rs_cleanup=function(){if(hasLocalStorage){delete localStorage[SETTINGS_KEY]}}})(typeof window!=="undefined"?window:global);(function(global){function extractParams(){var location=RemoteStorage.Authorize.getLocation(),hashPos=location.href.indexOf("#"),hash;if(hashPos===-1){return}hash=location.href.substring(hashPos+1);if(hash.indexOf("=")===-1){return}return hash.split("&").reduce(function(m,kvs){var kv=kvs.split("=");m[decodeURIComponent(kv[0])]=decodeURIComponent(kv[1]);return m},{})}RemoteStorage.Authorize=function(authURL,scope,redirectUri,clientId){RemoteStorage.log("[Authorize] authURL = ",authURL);var url=authURL;url+=authURL.indexOf("?")>0?"&":"?";url+="redirect_uri="+encodeURIComponent(redirectUri.replace(/#.*$/,""));url+="&scope="+encodeURIComponent(scope);url+="&client_id="+encodeURIComponent(clientId);url+="&response_type=token";RemoteStorage.Authorize.setLocation(url)};RemoteStorage.prototype.authorize=function(authURL){this.access.setStorageType(this.remote.storageType);var scope=this.access.scopeParameter;var redirectUri=String(RemoteStorage.Authorize.getLocation());var clientId=redirectUri.match(/^(https?:\/\/[^\/]+)/)[0];RemoteStorage.Authorize(authURL,scope,redirectUri,clientId)};RemoteStorage.Authorize.getLocation=function(){return global.document.location};RemoteStorage.Authorize.setLocation=function(location){if(typeof location==="string"){global.document.location.href=location}else if(typeof location==="object"){global.document.location=location}else{throw"Invalid location "+location}};RemoteStorage.Authorize._rs_supported=function(remoteStorage){return typeof document!=="undefined"};var onFeaturesLoaded;RemoteStorage.Authorize._rs_init=function(remoteStorage){onFeaturesLoaded=function(){var authParamsUsed=false;if(params){if(params.error){throw"Authorization server errored: "+params.error}if(params.access_token){remoteStorage.remote.configure(undefined,undefined,undefined,params.access_token);authParamsUsed=true}if(params.remotestorage){remoteStorage.connect(params.remotestorage);authParamsUsed=true}}if(!authParamsUsed){remoteStorage.remote.stopWaitingForToken()}};var params=extractParams(),location;if(params){location=RemoteStorage.Authorize.getLocation();location.hash=""}remoteStorage.on("features-loaded",onFeaturesLoaded)};RemoteStorage.Authorize._rs_cleanup=function(remoteStorage){remoteStorage.removeEventListener("features-loaded",onFeaturesLoaded)}})(typeof window!=="undefined"?window:global);(function(global){var SETTINGS_KEY="remotestorage:access";RemoteStorage.Access=function(){this.reset()};RemoteStorage.Access.prototype={claim:function(scope,mode){if(typeof scope!=="string"||scope.indexOf("/")!==-1||scope.length===0){throw new Error("Scope should be a non-empty string without forward slashes")}if(!mode.match(/^rw?$/)){throw new Error("Mode should be either 'r' or 'rw'")}this._adjustRootPaths(scope);this.scopeModeMap[scope]=mode},get:function(scope){return this.scopeModeMap[scope]},remove:function(scope){var savedMap={};var name;for(name in this.scopeModeMap){savedMap[name]=this.scopeModeMap[name]}this.reset();delete savedMap[scope];for(name in savedMap){this.set(name,savedMap[name])}},checkPermission:function(scope,mode){var actualMode=this.get(scope);return actualMode&&(mode==="r"||actualMode==="rw")},checkPathPermission:function(path,mode){if(this.checkPermission("*",mode)){return true}return!!this.checkPermission(this._getModuleName(path),mode)},reset:function(){this.rootPaths=[];this.scopeModeMap={}},_getModuleName:function(path){if(path[0]!=="/"){throw new Error("Path should start with a slash")}var moduleMatch=path.replace(/^\/public/,"").match(/^\/([^\/]*)\//);return moduleMatch?moduleMatch[1]:"*"},_adjustRootPaths:function(newScope){if("*"in this.scopeModeMap||newScope==="*"){this.rootPaths=["/"]}else if(!(newScope in this.scopeModeMap)){this.rootPaths.push("/"+newScope+"/");this.rootPaths.push("/public/"+newScope+"/")}},_scopeNameForParameter:function(scope){if(scope.name==="*"&&this.storageType){if(this.storageType==="2012.04"){return""}else if(this.storageType.match(/remotestorage-0[01]/)){return"root"}}return scope.name},setStorageType:function(type){this.storageType=type}};Object.defineProperty(RemoteStorage.Access.prototype,"scopes",{get:function(){return Object.keys(this.scopeModeMap).map(function(key){return{name:key,mode:this.scopeModeMap[key]}}.bind(this))}});Object.defineProperty(RemoteStorage.Access.prototype,"scopeParameter",{get:function(){return this.scopes.map(function(scope){return this._scopeNameForParameter(scope)+":"+scope.mode}.bind(this)).join(" ")}});Object.defineProperty(RemoteStorage.prototype,"access",{get:function(){var access=new RemoteStorage.Access;Object.defineProperty(this,"access",{value:access});return access},configurable:true});RemoteStorage.Access._rs_init=function(){}})(typeof window!=="undefined"?window:global);(function(pMode){var mode=pMode,env={},isBackground=false;RemoteStorage.Env=function(){return env};RemoteStorage.Env.isBrowser=function(){return mode==="browser"};RemoteStorage.Env.isNode=function(){return mode==="node"};RemoteStorage.Env.goBackground=function(){isBackground=true;RemoteStorage.Env._emit("background")};RemoteStorage.Env.goForeground=function(){isBackground=false;RemoteStorage.Env._emit("foreground")};RemoteStorage.Env._rs_init=function(remoteStorage){RemoteStorage.eventHandling(RemoteStorage.Env,"background","foreground");if(mode==="browser"){if(typeof document.hidden!=="undefined"){env.hiddenProperty="hidden";env.visibilityChangeEvent="visibilitychange"}else if(typeof document.mozHidden!=="undefined"){env.hiddenProperty="mozHidden";env.visibilityChangeEvent="mozvisibilitychange"}else if(typeof document.msHidden!=="undefined"){env.hiddenProperty="msHidden";env.visibilityChangeEvent="msvisibilitychange"}else if(typeof document.webkitHidden!=="undefined"){env.hiddenProperty="webkitHidden";env.visibilityChangeEvent="webkitvisibilitychange"}document.addEventListener(env.visibilityChangeEvent,function(){if(document[env.hiddenProperty]){RemoteStorage.Env.goBackground()}else{RemoteStorage.Env.goForeground()}},false)}};RemoteStorage.Env._rs_cleanup=function(remoteStorage){}})(typeof window!=="undefined"?"browser":"node");(function(){"use strict";var dictionary={view_info:'This app allows you to use your own storage. <a href="http://remotestorage.io/" target="_blank">Learn more!</a>',view_connect:"<strong>Connect</strong> remote storage",view_connecting:"Connecting <strong>%s</strong>",view_offline:"Offline",view_error_occured:"Sorry! An error occured.",view_confirm_reset:"Are you sure you want to reset everything? This will clear your local data and reload the page.",view_get_me_out:"Get me out of here!",view_error_plz_report:'If this problem persists, please <a href="http://remotestorage.io/community/" target="_blank">let us know</a>!',view_unauthorized:"Unauthorized! Click here to reconnect."};RemoteStorage.I18n={translate:function(){var str=arguments[0],params=Array.prototype.splice.call(arguments,1);if(typeof dictionary[str]!=="string"){throw"Unknown translation string: "+str}else{str=dictionary[str]}return str.replace(/%s/g,function(){return params.shift()})},getDictionary:function(){return dictionary},setDictionary:function(newDictionary){dictionary=newDictionary}}})();RemoteStorage.Assets={connectIcon:"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTYiIHdpZHRoPSIxNiIgdmVyc2lvbj0iMS4xIiB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAtMTAzNi40KSI+CiAgPHBhdGggZD0ibTEgMTA0Ny40di02aDd2LTRsNyA3LTcgN3YtNHoiIGZpbGw9IiNmZmYiLz4KIDwvZz4KPC9zdmc+Cg==",disconnectIcon:"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTYiIHdpZHRoPSIxNiIgdmVyc2lvbj0iMS4wIiB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KIDxwYXRoIHN0eWxlPSJibG9jay1wcm9ncmVzc2lvbjp0Yjt0ZXh0LWluZGVudDowO2NvbG9yOiMwMDAwMDA7dGV4dC10cmFuc2Zvcm06bm9uZSIgZD0ibTguMDAwMSAwYy0wLjQ3MTQgMC0wLjk2MTAzIDAuNTQxOS0wLjk1IDF2NmMtMC4wMDc0NyAwLjUyODMxIDAuNDIxNjMgMSAwLjk1IDFzMC45NTc0Ny0wLjQ3MTY5IDAuOTUtMXYtNmMwLjAxNDYyMi0wLjYwNTEtMC40Nzg2LTEtMC45NS0xem0tMy4zNDM4IDIuNWMtMC4wODcxODYgMC4wMTkyOTQtMC4xNzE2MyAwLjA1MDk1OS0wLjI1IDAuMDkzNzUtMi45OTk1IDEuNTcxNS0zLjkxODQgNC43OTc5LTMuMTI1IDcuNDY4OCAwLjc5MzQgMi42NyAzLjI3OTkgNC45MzcgNi42ODc1IDQuOTM3IDMuMzU5MiAwIDUuODc3Mi0yLjE0OSA2LjcxOTItNC43ODEgMC44NDEtMi42MzIxLTAuMDU4LTUuODIzNC0zLjEyNS03LjU5NC0wLjQzNC0wLjI1MzYtMS4wNTktMC4wODk5LTEuMzEzIDAuMzQzNy0wLjI1MzYgMC40MzM2LTAuMDkgMS4wNTg5IDAuMzQ0IDEuMzEyNSAyLjM5MDggMS4zNzk4IDIuODgyNSAzLjQ5NDQgMi4yODEyIDUuMzc1LTAuNjAxMiAxLjg4MDYtMi4zNDQgMy40Mzc1LTQuOTA2MiAzLjQzNzUtMi41NzU5IDAtNC4yOTc2LTEuNjUwMi00Ljg3NS0zLjU5MzgtMC41Nzc2LTEuOTQzNS0wLjA0Ny00LjA0OCAyLjE4NzMtNS4yMTg3IDAuMzc4Ny0wLjIwNjMgMC41NzkxLTAuNjkyNSAwLjQ1NTgtMS4xMDU3LTAuMTIzMi0wLjQxMzMtMC41NTcyLTAuNzEwMy0wLjk4Ny0wLjY3NTUtMC4wMzEzLTAuMDAxNS0wLjA2MjYtMC4wMDE1LTAuMDkzOCAweiIgZmlsbD0iI2ZmZiIvPgo8L3N2Zz4K",dropbox:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QgPEBAhEOpfuQAABhZJREFUWMPVl31snVUdxz+/5/2577e3b7QbHaOD0nXshW4ZZkpGQmJYZkJUDAaZzCBGAxGd+pdZQsJIjCaKgFu09GWybIggm8yhMCsY92rcOkPHunbdtKOUbX36svX23uc+xz+eDsrWlztiNJzk5D7JPS+fc8739/2dA5+EsqJtyK18ZlCKbX9Lk6fd1uo5xbTVZmtwa4v35Np5Mry4TLYXCzAnyhsry2SwrmnokdnaTruq6i3e0lXl0tqQlkURCxwdDp9Th5p3+p9iS8afqk/VZq9kaZoDN8apdU3B1KFnmLde7AkezH0n3V0UQOJpz2hIsqEhLU+WOeAagmtCxISYBe1nVf4vfWrByYdSpyf3W9ziLapy6JgbAduAiBn2S1rCQBYODAQP7H01/zxby4JpAW5s8mproxypiRKNGIJrQNT8EMA1wTGEU8MBP/q7umPw0dSbAA3N3n3zI2yLG2oScPgbNYWICY4Be86o/le6g0W576bPXQWwcqvXdJ2t1idMsA1hJoCoCRfGYdOhwsa4TUWFrr7pGmDrzAiQCHfD//Xxwk/33Z/6HoA0tnhLXZ3XMoYqsy4PYs4M4Ohg6pB2ddqO+vR6BWL27AARXbBNiBjwh9Oqs+O8ukcT4eaopjLqGsJSCdSX29SX23x/lctXlzgE1zBAANxWIQuGxlWNACxr8WozJp0lljKsGXbA0qGu1GRBxsTUQRAGLgboIuQVvHI8S+f7eeK2TLsDSQd296rhPaeDm09+PdX/gQYqN3uZ+jh7ro+oRusKDdgmVEY1GqstSiOhdegCmoQAIoImIWTPYIHdXVlyBYhaVwLA70+rPz7fllvLi2W5KcPw9q3eS/VJ7kmYgm1A3BIWV5osq7IIlMLUQJOrAXQBXQtr1BR2d2XpOu8TtULR+gq2nQh+vv8rqUdnNaKGZm/9qnJpmp/U+fxCB5lYsaGFdTYAY9L3jmNj9F9S7OgKVh9/KNVelBVf8untv8TYSS8gbsrHyh8C2LqQtGE0z9CJYfVuUblgRZv3WGOJvJG0cF8/lWPNdo+O93xsHYoVuqkL/xzIs/HPHt2DPg0Zko+v0I8vbfHun9aKE5sH9YaobJsf5V4mRLXv33kSlmAYwspqgw23R7A1EJlahKYOSsHTB0cZHQ9IOBA3NSrjGo4hWAY82xH8rH1b/jF2laoPAOb80jPqYtKTMdRcTQNd+xAgbgmuJbiGELfh3lsc7q41KQSTABBcC1qPjLH/XzniNqScsP1kgMsm9nJ34e2mNcmFAMby1qFPZyz1WlxXrprhuEUgUPDbd8Y59n6edbe61KZ1TF14vSfPLw5dYjhXIOMIM6lGAV+u0+tv+ttI/2+6/LsMQVXpUFCAqJkS9MT5anB2NGDjWxf5Yp3DvjN5th/LUhETolaRTqigxMGIWVKtHVyX2tGTJd2X5agUIfi8CmvUFOKGT++gT8wqLlKUgnwATxwq7P32m35Z+32pPQZA54MpH1iSb/XWZmx2VthTD1AATCBlCZ+dpwNg6EJjlUH3hQIKRaCujhZFaOPtfUH+8HvBnQceSP11yjA8vC616+A5FevL8jt/YiCR0HiQcAUVrnDHHO0jHTUNllXrpC0NRXiefjAxM4rhHLzQpZqf+eFFd/LkM17JGlu9p+xC8IgPhGlaqE1rNJZrxOzQok0dnjviY+nhbSntCH3DAWN+QMIWEhYsqTD4wYHChrPfSP9kqnmM6QAMkYtz4xqmDqeGA+rLNObGZVozkglx1ZfqZAvC2ZGAz9RYlEbAlsLoNd+Kx5RqO5/njKXDsnKdhCXFOaFAZUzjznlhyt5xIjiSLbBz2oVO98fRdalOoGZ5m/dUQ4pvJZ3Zr/CXlS5A74gabzlYePztr6U2faxr+eRy/RYvtjgjHauvkxvi9oTDXaGBuAUJWyh1hb3vqsOvfiG5/L/yMAE483BqdNeuXO3LvcGX3vEUhsZVsaYL9IzACz3BXcVOXvQOfKRsupBZv8R4bnW19rmqGPzqHz4BcMGn5U/Hgod5oiT3P3kvVj7rrfnx/pHBu7d7Azc1eY3/l0drzWbPXNjsGXySy38AbtMqneWU7BkAAAAASUVORK5CYII=",googledrive:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QgPEA85ztzJcQAABZVJREFUWMPtl1uoXVcVhr8x5tprn7M1NG1i0pQqSG2jLcXipYJXjPogqFgpaHMSFUkpIjU+leKbDxIQSiHgjZgmrfXgQ6SKj5Ji7YVS05aUUqKQlNLQeDnN5Zzk9Jy99xy/D3OttU/StDlV33TBZM3FXmuMf/5jjv+fG/7XL1vti9tnv3Dtnnf+87JY8YmZNxEMM1sZ7tWpjz764mriVqvKvmfb1ONLy3+dGyWu6EWbvQwoydv5BMSqFuereakmfnls1GP25IDaBGYYjplhljDz5tk7YMtPfurAf6UE9Z6tNwDPAPXwtcxL1x9n4zRgDjjm1gCyC6JpCLoW/OX65of1nzCwG6gNo3aYeXF981mTvK2/WWFiMmoj7X+z5JcE0N87c4e7b3EvyTwZT5/r8ezZHu6GuWGpSegJ8/ZeBu6fHv35s1/7t0rQv29mjWF/ATZ1L4bQwohrpkYc/sBpwhJYAVdKYECzYAESIk4Am3sf+sPCW2LAzb9jbpvMDXfD3fEqkRIcGdbsevlt9LylPYG1K6/K3QzK75uAr78lBgb3b7sc2cl2Uaa21sDiGMvB2iQeu/EMm6bKHjD3SUsCEChnpEAKiLisd/PB+UsyMPjZNwzzh1ixcnOfsFCX51NU/PTvA6pkTUdYw4R3zyu1ArMDqyvBQB82+FiJUQJ4C8YgVT1SSvSTs+vEmkcwe7qEsUnt233Aij0BW4ZPbfngKpRQs7hXpYQNvRiuEtATWOW4bLi+z04pJbCnBAkBJggBQlIBIZCUJM0Cm9+QgcED2+/G7BprdMZaAFZExm1FWcz+NLdj32G/6XfPCB5GoJKp7H5FARHRtgRI1y0/+cm7Lwpg+v7t64DvNd5S2mqirKXHy6RoArp1Ykrc2hKtKCtXlNEyoQ6Ydi498fF1F2FAdwEbV9UnZne+8q19Z7o63vTb+TPnRneeWxwxHGdyziii6wApQNEydKUUd5wHYGrftvci7tKKLSME5bvCaruynI9rNL7vdZgiHhiP898Wl8bMnxty+uyIhcURo1FgjSg1DCDph4uPfuR9AFbvvS25p2cxbiyKVuh2o1O44n2lLLacb5v75v5fX6yl5h753IwUD+YcRAQ5B6FMMhj0jboSRhnAE258wvp7Z7aYcbCYCeCGt97ubfICLDP/q4WZ32x7M20fPfb+hxbH9ZdjHOQIIoR74EDywA3coa6MqtJnrP+LmRmcB63ob8dA1wllRm95LVc//22S16TGeKqqpqoHk10ESGJj/zjjgIhAISKCyJmcY6Uu8Pbq7C0V6ABh35dzvYWQG0QAhmSYCaUlNhzdCrlX2jpE6tV4b9DYcGFKEgG8svQucoicC4CsII8zeTxutAEQzx1duPL3vrxjdlnou0SDLdTulxJQmalXNzN98jpEJiSo+qTeoEnsnWC5lVZNRhkOZiq0G8XCmz1gpp3j/ZYdYLhj9qCkn3fJQ4QKeh9OccWxz6O0hGKM9wakeoBEZ1BmqfOMyYFk4gXS+edG4J4ju6/644VK+AOJhSIYpVRBpn/qPVRL65A51dRavJoG2UQkOqf0hgVrGG7u6syoJDObB+55nRANb589Afy40W0UwkY91h39CiLweg1UU+W3ohLNvC2VurJ1htR6A3QaYPCjI7uvOvGGOlfv2XoSuBzEhmNfZXDqBrweUPVqUlWodneSG+6J1NTevThfDpEjmnsmzuuCPPfCvRvfcakT0S2Aeq9tYPr0ZryeBvOOlZBKUIEiCAVZwTgy41x6v6hm0LFZ4o7N7IuXPA+EDx+XjQ+tP/4lUrW2vCI1ydR0iYgmWdtu4yzG7bOiAdn8iYlA0iFJh1Z1JJv+ye2b3n1419XRH2riP0aqqlKClABIjUMW+rtSlw5qmCpgsynnl56/d+M/+P91wfUvQjDgTzx9h9AAAAAASUVORK5CYII=",remoteStorageIcon:"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzIiIHdpZHRoPSIzMiIgdmVyc2lvbj0iMS4xIiB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KIDxkZWZzPgogIDxyYWRpYWxHcmFkaWVudCBpZD0iYSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGN5PSI1NzEuNDIiIGN4PSIxMDQ2LjUiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoLjE0NDMzIDAgMCAuMTY2NjcgMTIwMS41IDg3Ny4xMSkiIHI9Ijk2Ij4KICAgPHN0b3Agc3RvcC1jb2xvcj0iI2ZmNGEwNCIgc3RvcC1vcGFjaXR5PSIuNzYxNTQiIG9mZnNldD0iMCIvPgogICA8c3RvcCBzdG9wLWNvbG9yPSIjZmY0YTA0IiBvZmZzZXQ9IjEiLz4KICA8L3JhZGlhbEdyYWRpZW50PgogPC9kZWZzPgogPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEzMzYuNiAtOTU2LjM1KSI+CiAgPHBhdGggc3R5bGU9ImNvbG9yOiMwMDAwMDAiIGQ9Im0xMzUyLjYgOTU2LjM1IDAuMjg4NiAxNS4xMzYgMTMuNTY3LTcuMTM1Mi0xMy44NTUtOC4wMDExemwtMTMuODU1IDguMDAxMSAxMy41NjcgNy4xMzUyIDAuMjg4Ny0xNS4xMzZ6bS0xMy44NTUgOC4wMDExdjE1Ljk5OGwxMi45NTgtNy44MTYyLTEyLjk1OC04LjE4MTV6bTAgMTUuOTk4IDEzLjg1NSA4LjAwMTEtMC42MDg5LTE1LjMxNy0xMy4yNDYgNy4zMTU2em0xMy44NTUgOC4wMDExIDEzLjg1NS04LjAwMTEtMTMuMjUxLTcuMzE1Ni0wLjYwNDQgMTUuMzE3em0xMy44NTUtOC4wMDExdi0xNS45OThsLTEyLjk2MiA4LjE4MTUgMTIuOTYyIDcuODE2MnoiIGZpbGw9InVybCgjYSkiLz4KIDwvZz4KPC9zdmc+Cg==",remoteStorageIconError:"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzIiIHdpZHRoPSIzMiIgdmVyc2lvbj0iMS4xIiB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KIDxkZWZzPgogIDxyYWRpYWxHcmFkaWVudCBpZD0iYSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGN5PSI1NzEuNDIiIGN4PSIxMDQ2LjUiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoLjE0NDMzIDAgMCAuMTY2NjcgMTIwMS41IDg3Ny4xMSkiIHI9Ijk2Ij4KICAgPHN0b3Agc3RvcC1jb2xvcj0iI2U5MDAwMCIgc3RvcC1vcGFjaXR5PSIuNzYwNzgiIG9mZnNldD0iMCIvPgogICA8c3RvcCBzdG9wLWNvbG9yPSIjZTkwMDAwIiBvZmZzZXQ9IjEiLz4KICA8L3JhZGlhbEdyYWRpZW50PgogPC9kZWZzPgogPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEzMzYuNiAtOTU2LjM1KSI+CiAgPHBhdGggc3R5bGU9ImNvbG9yOiMwMDAwMDAiIGQ9Im0xMzUyLjYgOTU2LjM1IDAuMjg4NiAxNS4xMzYgMTMuNTY3LTcuMTM1Mi0xMy44NTUtOC4wMDExemwtMTMuODU1IDguMDAxMSAxMy41NjcgNy4xMzUyIDAuMjg4Ny0xNS4xMzZ6bS0xMy44NTUgOC4wMDExdjE1Ljk5OGwxMi45NTgtNy44MTYyLTEyLjk1OC04LjE4MTV6bTAgMTUuOTk4IDEzLjg1NSA4LjAwMTEtMC42MDg5LTE1LjMxNy0xMy4yNDYgNy4zMTU2em0xMy44NTUgOC4wMDExIDEzLjg1NS04LjAwMTEtMTMuMjUxLTcuMzE1Ni0wLjYwNDQgMTUuMzE3em0xMy44NTUtOC4wMDExdi0xNS45OThsLTEyLjk2MiA4LjE4MTUgMTIuOTYyIDcuODE2MnoiIGZpbGw9InVybCgjYSkiLz4KIDwvZz4KPC9zdmc+Cg==",remoteStorageIconOffline:"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzIiIHdpZHRoPSIzMiIgdmVyc2lvbj0iMS4xIiB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIj4KIDxkZWZzPgogIDxyYWRpYWxHcmFkaWVudCBpZD0iYSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGN5PSI1NzEuNDIiIGN4PSIxMDQ2LjUiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoLjE0NDMzIDAgMCAuMTY2NjcgMTIwMS41IDg3Ny4xMSkiIHI9Ijk2Ij4KICAgPHN0b3Agc3RvcC1jb2xvcj0iIzY5Njk2OSIgc3RvcC1vcGFjaXR5PSIuNzYxNTQiIG9mZnNldD0iMCIvPgogICA8c3RvcCBzdG9wLWNvbG9yPSIjNjc2NzY3IiBvZmZzZXQ9IjEiLz4KICA8L3JhZGlhbEdyYWRpZW50PgogPC9kZWZzPgogPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEzMzYuNiAtOTU2LjM1KSI+CiAgPHBhdGggc3R5bGU9ImNvbG9yOiMwMDAwMDAiIGQ9Im0xMzUyLjYgOTU2LjM1IDAuMjg4NiAxNS4xMzYgMTMuNTY3LTcuMTM1Mi0xMy44NTUtOC4wMDExemwtMTMuODU1IDguMDAxMSAxMy41NjcgNy4xMzUyIDAuMjg4Ny0xNS4xMzZ6bS0xMy44NTUgOC4wMDExdjE1Ljk5OGwxMi45NTgtNy44MTYyLTEyLjk1OC04LjE4MTV6bTAgMTUuOTk4IDEzLjg1NSA4LjAwMTEtMC42MDg5LTE1LjMxNy0xMy4yNDYgNy4zMTU2em0xMy44NTUgOC4wMDExIDEzLjg1NS04LjAwMTEtMTMuMjUxLTcuMzE1Ni0wLjYwNDQgMTUuMzE3em0xMy44NTUtOC4wMDExdi0xNS45OThsLTEyLjk2MiA4LjE4MTUgMTIuOTYyIDcuODE2MnoiIGZpbGw9InVybCgjYSkiLz4KIDwvZz4KPC9zdmc+Cg==",syncIcon:"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDg3LjUgMTAwIiB4bWw6c3BhY2U9InByZXNlcnZlIiBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTUuOTk5OTk5IDE2IiB3aWR0aD0iMTYiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+CjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01LjUxMTIgLTc2LjUyNSkiIGRpc3BsYXk9Im5vbmUiPgoJPHBhdGggZGlzcGxheT0iaW5saW5lIiBkPSJtNTEuNDczIDQyLjI1NS0yLjIwNSAyLjIxMmMxLjQ3OCAxLjQ3NyAyLjI5NSAzLjQ0MiAyLjI5NSA1LjUzMyAwIDQuMzA5LTMuNTA0IDcuODEyLTcuODEyIDcuODEydi0xLjU2MmwtMy4xMjUgMy4xMjUgMy4xMjQgMy4xMjV2LTEuNTYyYzYuMDI5IDAgMTAuOTM4LTQuOTA2IDEwLjkzOC0xMC45MzggMC0yLjkyNy0xLjE0MS01LjY3Ni0zLjIxNS03Ljc0NXoiLz4KCTxwYXRoIGRpc3BsYXk9ImlubGluZSIgZD0ibTQ2Ljg3NSA0MC42MjUtMy4xMjUtMy4xMjV2MS41NjJjLTYuMDMgMC0xMC45MzggNC45MDctMTAuOTM4IDEwLjkzOCAwIDIuOTI3IDEuMTQxIDUuNjc2IDMuMjE3IDcuNzQ1bDIuMjAzLTIuMjEyYy0xLjQ3Ny0xLjQ3OS0yLjI5NC0zLjQ0Mi0yLjI5NC01LjUzMyAwLTQuMzA5IDMuNTA0LTcuODEyIDcuODEyLTcuODEydjEuNTYybDMuMTI1LTMuMTI1eiIvPgo8L2c+CjxwYXRoIGZpbGw9IiNmZmYiIGQ9Im0xMCAwbC0wLjc1IDEuOTA2MmMtMS4wMDc4LTAuMjk0Mi0zLjQ1ODYtMC43NzA4LTUuNjU2MiAwLjkzNzYgMC0wLjAwMDItMy45MzAyIDIuNTk0MS0yLjA5MzggNy41OTQybDEuNjU2Mi0wLjcxOTJzLTEuNTM5OS0zLjExMjIgMS42ODc2LTUuNTMxM2MwIDAgMS42OTU3LTEuMTMzOSAzLjY4NzQtMC41OTM3bC0wLjcxODcgMS44MTI0IDMuODEyNS0xLjYyNS0xLjYyNS0zLjc4MTJ6Ii8+PHBhdGggZmlsbD0iI2ZmZiIgZD0ibTE0IDUuNTYyNWwtMS42NTYgMC43MTg3czEuNTQxIDMuMTEzNS0xLjY4OCA1LjUzMDhjMCAwLTEuNzI3MiAxLjEzNS0zLjcxODUgMC41OTRsMC43NS0xLjgxMi0zLjgxMjUgMS41OTQgMS41OTM4IDMuODEyIDAuNzgxMi0xLjkwNmMxLjAxMTMgMC4yOTUgMy40NjE1IDAuNzY2IDUuNjU2LTAuOTM4IDAgMCAzLjkyOC0yLjU5NCAyLjA5NC03LjU5MzV6Ii8+Cjwvc3ZnPgo=",widget:'<div class="rs-bubble rs-hidden">   <div class="rs-bubble-text remotestorage-initial remotestorage-error remotestorage-authing remotestorage-offline">     <span class="rs-status-text">{{view_connect}}</span>   </div>   <div class="rs-bubble-expandable">     <!-- error -->     <div class="remotestorage-error">       <pre class="rs-status-text rs-error-msg">{{ERROR_MSG}}</pre>       <button class="remotestorage-reset">{{view_get_me_out}}</button>       <p class="rs-centered-text rs-error-plz-report">{{view_error_plz_report}}</p>     </div>     <!-- connected -->     <div class="rs-bubble-text remotestorage-connected">       <strong class="userAddress">{{USER_ADDRESS}}</strong>       <p class="remotestorage-unauthorized">{{view_unauthorized}}</p>     </div>     <div class="rs-content remotestorage-connected">       <button class="rs-sync" title="sync"><img></button>       <button class="rs-disconnect" title="disconnect"><img></button>     </div>     <!-- initial -->     <form novalidate class="remotestorage-initial">       <input type="email" placeholder="user@host" name="userAddress" novalidate>       <button class="connect" name="connect" title="connect" disabled="disabled">         <img>       </button>     </form>     <div class="rs-info-msg remotestorage-initial">{{view_info}}</div>   </div> </div> <img class="rs-dropbox rs-backends rs-action" alt="Connect to Dropbox"> <img class="rs-googledrive rs-backends rs-action" alt="Connect to Google Drive"> <img class="rs-cube rs-action"> ',widgetCss:'/** encoding:utf-8 **/ /* RESET */ #remotestorage-widget{text-align:left;}#remotestorage-widget input, #remotestorage-widget button{font-size:11px;}#remotestorage-widget form input[type=email]{margin-bottom:0;/* HTML5 Boilerplate */}#remotestorage-widget form input[type=submit]{margin-top:0;/* HTML5 Boilerplate */}/* /RESET */ #remotestorage-widget, #remotestorage-widget *{-moz-box-sizing:border-box;box-sizing:border-box;}#remotestorage-widget{position:absolute;right:10px;top:10px;font:normal 16px/100% sans-serif !important;user-select:none;-webkit-user-select:none;-moz-user-select:-moz-none;cursor:default;z-index:10000;}#remotestorage-widget .rs-bubble{background:rgba(80, 80, 80, .7);border-radius:5px 15px 5px 5px;color:white;font-size:0.8em;padding:5px;position:absolute;right:3px;top:9px;min-height:24px;white-space:nowrap;text-decoration:none;}.rs-bubble .rs-bubble-text{padding-right:32px;/* make sure the bubble doesn\'t "jump" when initially opening. */ min-width:182px;}#remotestorage-widget .rs-action{cursor:pointer;}/* less obtrusive cube when connected */ #remotestorage-widget.remotestorage-state-connected .rs-cube, #remotestorage-widget.remotestorage-state-busy .rs-cube{opacity:.3;-webkit-transition:opacity .3s ease;-moz-transition:opacity .3s ease;-ms-transition:opacity .3s ease;-o-transition:opacity .3s ease;transition:opacity .3s ease;}#remotestorage-widget.remotestorage-state-connected:hover .rs-cube, #remotestorage-widget.remotestorage-state-busy:hover .rs-cube, #remotestorage-widget.remotestorage-state-connected .rs-bubble:not(.rs-hidden) + .rs-cube{opacity:1 !important;}#remotestorage-widget .rs-backends{position:relative;top:5px;right:0;}#remotestorage-widget .rs-cube{position:relative;top:5px;right:0;}/* pulsing animation for cube when loading */ #remotestorage-widget .rs-cube.remotestorage-loading{-webkit-animation:remotestorage-loading .5s ease-in-out infinite alternate;-moz-animation:remotestorage-loading .5s ease-in-out infinite alternate;-o-animation:remotestorage-loading .5s ease-in-out infinite alternate;-ms-animation:remotestorage-loading .5s ease-in-out infinite alternate;animation:remotestorage-loading .5s ease-in-out infinite alternate;}@-webkit-keyframes remotestorage-loading{to{opacity:.7}}@-moz-keyframes remotestorage-loading{to{opacity:.7}}@-o-keyframes remotestorage-loading{to{opacity:.7}}@-ms-keyframes remotestorage-loading{to{opacity:.7}}@keyframes remotestorage-loading{to{opacity:.7}}#remotestorage-widget a{text-decoration:underline;color:inherit;}#remotestorage-widget form{margin-top:.7em;position:relative;}#remotestorage-widget form input{display:table-cell;vertical-align:top;border:none;border-radius:6px;font-weight:bold;color:white;outline:none;line-height:1.5em;height:2em;}#remotestorage-widget form input:disabled{color:#999;background:#444 !important;cursor:default !important;}#remotestorage-widget form input[type=email]:focus{background:#223;}#remotestorage-widget form input[type=email]{background:#000;width:100%;height:26px;padding:0 30px 0 5px;border-top:1px solid #111;border-bottom:1px solid #999;}#remotestorage-widget form input[type=email]:focus{background:#223;}#remotestorage-widget button:focus, #remotestorage-widget input:focus{box-shadow:0 0 4px #ccc;}#remotestorage-widget form input[type=email]::-webkit-input-placeholder{color:#999;}#remotestorage-widget form input[type=email]:-moz-placeholder{color:#999;}#remotestorage-widget form input[type=email]::-moz-placeholder{color:#999;}#remotestorage-widget form input[type=email]:-ms-input-placeholder{color:#999;}#remotestorage-widget form input[type=submit]{background:#000;cursor:pointer;padding:0 5px;}#remotestorage-widget form input[type=submit]:hover{background:#333;}#remotestorage-widget .rs-info-msg{font-size:10px;color:#eee;margin-top:0.7em;white-space:normal;}#remotestorage-widget .rs-info-msg.last-synced-message{display:inline;white-space:nowrap;margin-bottom:.7em}#remotestorage-widget .rs-info-msg a:hover, #remotestorage-widget .rs-info-msg a:active{color:#fff;}#remotestorage-widget button img{vertical-align:baseline;}#remotestorage-widget button{border:none;border-radius:6px;font-weight:bold;color:white;outline:none;line-height:1.5em;height:26px;width:26px;background:#000;cursor:pointer;margin:0;padding:5px;}#remotestorage-widget button:hover{background:#333;}#remotestorage-widget .rs-bubble button.connect{display:block;background:none;position:absolute;right:0;top:0;opacity:1;/* increase clickable area of connect button */ margin:-5px;padding:10px;width:36px;height:36px;}#remotestorage-widget .rs-bubble button.connect:not([disabled]):hover{background:rgba(150,150,150,.5);}#remotestorage-widget .rs-bubble button.connect[disabled]{opacity:.5;cursor:default !important;}#remotestorage-widget .rs-bubble button.rs-sync{position:relative;left:-5px;bottom:-5px;padding:4px 4px 0 4px;background:#555;}#remotestorage-widget .rs-bubble button.rs-sync:hover{background:#444;}#remotestorage-widget .rs-bubble button.rs-disconnect{background:#721;position:absolute;right:0;bottom:0;padding:4px 4px 0 4px;}#remotestorage-widget .rs-bubble button.rs-disconnect:hover{background:#921;}#remotestorage-widget .remotestorage-error-info{color:#f92;}#remotestorage-widget .remotestorage-reset{width:100%;background:#721;}#remotestorage-widget .remotestorage-reset:hover{background:#921;}#remotestorage-widget .rs-bubble .rs-content{margin-top:7px;}#remotestorage-widget pre{user-select:initial;-webkit-user-select:initial;-moz-user-select:text;max-width:27em;margin-top:1em;overflow:auto;}#remotestorage-widget .rs-centered-text{text-align:center;}#remotestorage-widget .rs-bubble.rs-hidden{padding-bottom:2px;border-radius:5px 15px 15px 5px;}#remotestorage-widget .rs-error-msg{min-height:5em;}.rs-bubble.rs-hidden .rs-bubble-expandable{display:none;}.remotestorage-state-connected .rs-bubble.rs-hidden{display:none;}.remotestorage-connected{display:none;}.remotestorage-state-connected .remotestorage-connected{display:block;}.remotestorage-initial{display:none;}.remotestorage-state-initial .remotestorage-initial{display:block;}.remotestorage-error{display:none;}.remotestorage-state-error .remotestorage-error{display:block;}.remotestorage-state-authing .remotestorage-authing{display:block;}.remotestorage-state-offline .remotestorage-connected, .remotestorage-state-offline .remotestorage-offline{display:block;}.remotestorage-unauthorized{display:none;}.remotestorage-state-unauthorized .rs-bubble.rs-hidden{display:none;}.remotestorage-state-unauthorized .remotestorage-connected, .remotestorage-state-unauthorized .remotestorage-unauthorized{display:block;}.remotestorage-state-unauthorized .rs-sync{display:none;}.remotestorage-state-busy .rs-bubble.rs-hidden{display:none;}.remotestorage-state-busy .rs-bubble{display:block;}.remotestorage-state-busy .remotestorage-connected{display:block;}.remotestorage-state-authing .rs-bubble-expandable{display:none;}'};
  (function(window){var hasLocalStorage;var LS_STATE_KEY="remotestorage:widget:state";var VALID_ENTRY_STATES={initial:true,connected:true,offline:true};function stateSetter(widget,state){RemoteStorage.log("[Widget] Producing stateSetter for",state);return function(){RemoteStorage.log("[Widget] Setting state",state,arguments);if(hasLocalStorage){localStorage[LS_STATE_KEY]=state}if(widget.view){if(widget.rs.remote){widget.view.setUserAddress(widget.rs.remote.userAddress)}widget.view.setState(state,arguments)}else{widget._rememberedState=state}}}function errorsHandler(widget){return function(error){if(error instanceof RemoteStorage.DiscoveryError){console.error("Discovery failed",error,'"'+error.message+'"');widget.view.setState("initial",[error.message])}else if(error instanceof RemoteStorage.SyncError){widget.view.setState("offline",[])}else if(error instanceof RemoteStorage.Unauthorized){widget.view.setState("unauthorized")}else{RemoteStorage.log("[Widget] Unknown error");widget.view.setState("error",[error])}}}function flashFor(evt){if(evt.method==="GET"&&evt.isFolder){return false}return true}RemoteStorage.Widget=function(remoteStorage){var self=this;var requestsToFlashFor=0;this.rs=remoteStorage;this.rs.remote.on("connected",stateSetter(this,"connected"));this.rs.on("disconnected",stateSetter(this,"initial"));this.rs.on("connecting",stateSetter(this,"authing"));this.rs.on("authing",stateSetter(this,"authing"));this.rs.on("error",errorsHandler(this));if(this.rs.remote){this.rs.remote.on("wire-busy",function(evt){if(flashFor(evt)){requestsToFlashFor++;stateSetter(self,"busy")()}});this.rs.remote.on("wire-done",function(evt){if(flashFor(evt)){requestsToFlashFor--;if(requestsToFlashFor<=0){stateSetter(self,"connected")()}}})}if(hasLocalStorage){var state=localStorage[LS_STATE_KEY];if(state&&VALID_ENTRY_STATES[state]){this._rememberedState=state}}};RemoteStorage.Widget.prototype={display:function(domID){if(!this.view){this.setView(new RemoteStorage.Widget.View(this.rs))}this.view.display.apply(this.view,arguments);return this},linkWidgetToSync:function(){if(typeof this.rs.sync==="object"&&typeof this.rs.sync.sync==="function"){this.view.on("sync",this.rs.sync.sync.bind(this.rs.sync))}else{RemoteStorage.log("[Widget] typeof this.rs.sync check fail",this.rs.sync);setTimeout(this.linkWidgetToSync.bind(this),1e3)}},setView:function(view){this.view=view;this.view.on("connect",function(options){if(typeof options==="string"){this.rs.connect(options)}else if(options.special){this.rs[options.special].connect(options)}}.bind(this));this.view.on("disconnect",this.rs.disconnect.bind(this.rs));this.linkWidgetToSync();try{this.view.on("reset",function(){var location=RemoteStorage.Authorize.getLocation();this.rs.on("disconnected",location.reload.bind(location));this.rs.disconnect()}.bind(this))}catch(e){if(e.message&&e.message.match(/Unknown event/)){}else{throw e}}if(this._rememberedState){setTimeout(stateSetter(this,this._rememberedState),0);delete this._rememberedState}}};RemoteStorage.prototype.displayWidget=function(domID){return this.widget.display(domID)};RemoteStorage.Widget._rs_init=function(remoteStorage){hasLocalStorage=remoteStorage.localStorageAvailable();if(!remoteStorage.widget){remoteStorage.widget=new RemoteStorage.Widget(remoteStorage)}};RemoteStorage.Widget._rs_supported=function(remoteStorage){return typeof document!=="undefined"}})(typeof window!=="undefined"?window:global);(function(window){var t=RemoteStorage.I18n.translate;var cEl=function(){return document.createElement.apply(document,arguments)};function gCl(parent,className){return parent.getElementsByClassName(className)[0]}function gTl(parent,tagName){return parent.getElementsByTagName(tagName)[0]}function removeClass(el,className){return el.classList.remove(className)}function addClass(el,className){return el.classList.add(className)}function stopPropagation(event){if(typeof event.stopPropagation==="function"){event.stopPropagation()}else{event.cancelBubble=true}}function setupButton(parent,className,iconName,eventListener){var element=gCl(parent,className);if(typeof iconName!=="undefined"){var img=gTl(element,"img");(img||element).src=RemoteStorage.Assets[iconName]}element.addEventListener("click",eventListener);return element}RemoteStorage.Widget.View=function(remoteStorage){this.rs=remoteStorage;if(typeof document==="undefined"){throw"Widget not supported"}RemoteStorage.eventHandling(this,"connect","disconnect","sync","display","reset");for(var event in this.events){this.events[event]=this.events[event].bind(this)}this.hideBubbleOnBodyClick=function(event){for(var p=event.target;p!==document.body;p=p.parentElement){if(p.id==="remotestorage-widget"){return}}this.hideBubble()}.bind(this)};RemoteStorage.Widget.View.prototype={connectGdrive:function(){this._emit("connect",{special:"googledrive"})},connectDropbox:function(){this._emit("connect",{special:"dropbox"})},setState:function(state,args){RemoteStorage.log("[View] widget.view.setState(",state,",",args,");");var s=this.states[state];if(typeof s==="undefined"){throw new Error("Bad State assigned to view: "+state)}s.apply(this,args)},setUserAddress:function(addr){this.userAddress=addr||"";var el;if(this.div&&(el=gTl(this.div,"form").userAddress)){el.value=this.userAddress}},toggleBubble:function(event){if(this.bubble.className.search("rs-hidden")<0){this.hideBubble(event)}else{this.showBubble(event)}},hideBubble:function(){addClass(this.bubble,"rs-hidden");document.body.removeEventListener("click",this.hideBubbleOnBodyClick)},showBubble:function(event){removeClass(this.bubble,"rs-hidden");if(typeof event!=="undefined"){stopPropagation(event)}document.body.addEventListener("click",this.hideBubbleOnBodyClick);gTl(this.bubble,"form").userAddress.focus()},display:function(domID){if(typeof this.div!=="undefined"){return this.div}var element=cEl("div");var style=cEl("style");style.innerHTML=RemoteStorage.Assets.widgetCss;element.id="remotestorage-widget";element.innerHTML=RemoteStorage.Assets.widget;element.appendChild(style);if(domID){var parent=document.getElementById(domID);if(!parent){throw'Failed to find target DOM element with id="'+domID+'"'}parent.appendChild(element)}else{document.body.appendChild(element)}setupButton(element,"rs-sync","syncIcon",this.events.sync);setupButton(element,"rs-disconnect","disconnectIcon",this.events.disconnect);setupButton(element,"remotestorage-reset",undefined,this.events.reset);var cb=setupButton(element,"connect","connectIcon",this.events.connect);this.form=gTl(element,"form");var el=this.form.userAddress;el.addEventListener("keyup",function(event){if(event.target.value){cb.removeAttribute("disabled")}else{cb.setAttribute("disabled","disabled")}});if(this.userAddress){el.value=this.userAddress}this.cube=setupButton(element,"rs-cube","remoteStorageIcon",this.toggleBubble.bind(this));setupButton(element,"rs-dropbox","dropbox",this.connectDropbox.bind(this));setupButton(element,"rs-googledrive","googledrive",this.connectGdrive.bind(this));var bubbleDontCatch={INPUT:true,BUTTON:true,IMG:true};var eventListener=function(event){if(!bubbleDontCatch[event.target.tagName]&&!this.div.classList.contains("remotestorage-state-unauthorized")){this.showBubble(event)}}.bind(this);this.bubble=setupButton(element,"rs-bubble",undefined,eventListener);this.hideBubble();this.div=element;this.states.initial.call(this);this.events.display.call(this);return this.div},_renderTranslatedInitialContent:function(){gCl(this.div,"rs-status-text").innerHTML=t("view_connect");gCl(this.div,"remotestorage-reset").innerHTML=t("view_get_me_out");gCl(this.div,"rs-error-plz-report").innerHTML=t("view_error_plz_report");gCl(this.div,"remotestorage-unauthorized").innerHTML=t("view_unauthorized")},states:{initial:function(message){var cube=this.cube;var info=message||t("view_info");this._renderTranslatedInitialContent();if(message){cube.src=RemoteStorage.Assets.remoteStorageIconError;removeClass(this.cube,"remotestorage-loading");this.showBubble();setTimeout(function(){cube.src=RemoteStorage.Assets.remoteStorageIcon},5e3)}else{this.hideBubble()}this.div.className="remotestorage-state-initial";var backends=1;if(this._activateBackend("dropbox")){backends+=1}if(this._activateBackend("googledrive")){backends+=1}gCl(this.div,"rs-bubble-text").style.paddingRight=backends*32+8+"px";var cb=gCl(this.div,"connect");if(this.form.userAddress.value){cb.removeAttribute("disabled")}var infoEl=gCl(this.div,"rs-info-msg");infoEl.innerHTML=info;if(message){infoEl.classList.add("remotestorage-error-info")}else{infoEl.classList.remove("remotestorage-error-info")}},authing:function(){this.div.removeEventListener("click",this.events.connect);this.div.className="remotestorage-state-authing";gCl(this.div,"rs-status-text").innerHTML=t("view_connecting",this.userAddress);addClass(this.cube,"remotestorage-loading")},connected:function(){this.div.className="remotestorage-state-connected";gCl(this.div,"userAddress").innerHTML=this.userAddress;this.cube.src=RemoteStorage.Assets.remoteStorageIcon;removeClass(this.cube,"remotestorage-loading");var icons={googledrive:gCl(this.div,"rs-googledrive"),dropbox:gCl(this.div,"rs-dropbox")};icons.googledrive.style.display=icons.dropbox.style.display="none";if(icons[this.rs.backend]){icons[this.rs.backend].style.display="inline-block";gCl(this.div,"rs-bubble-text").style.paddingRight=2*32+8+"px"}else{gCl(this.div,"rs-bubble-text").style.paddingRight=32+8+"px"}},busy:function(){this.div.className="remotestorage-state-busy";addClass(this.cube,"remotestorage-loading");this.hideBubble()},offline:function(){this.div.className="remotestorage-state-offline";this.cube.src=RemoteStorage.Assets.remoteStorageIconOffline;gCl(this.div,"rs-status-text").innerHTML=t("view_offline")},error:function(err){var errorMsg=err;this.div.className="remotestorage-state-error";gCl(this.div,"rs-bubble-text").innerHTML="<strong>"+t("view_error_occured")+"</strong>";if(err instanceof Error){errorMsg=err.message+"\n\n"+err.stack}gCl(this.div,"rs-error-msg").textContent=errorMsg;this.cube.src=RemoteStorage.Assets.remoteStorageIconError;this.showBubble()},unauthorized:function(){this.div.className="remotestorage-state-unauthorized";this.cube.src=RemoteStorage.Assets.remoteStorageIconError;this.showBubble();this.div.addEventListener("click",this.events.connect)}},events:{connect:function(event){stopPropagation(event);event.preventDefault();this._emit("connect",gTl(this.div,"form").userAddress.value)},sync:function(event){stopPropagation(event);event.preventDefault();this._emit("sync")},disconnect:function(event){stopPropagation(event);event.preventDefault();this._emit("disconnect")},reset:function(event){event.preventDefault();var result=window.confirm(t("view_confirm_reset"));if(result){this._emit("reset")}},display:function(event){if(event){event.preventDefault()}this._emit("display")}},_activateBackend:function activateBackend(backendName){var className="rs-"+backendName;if(this.rs.apiKeys[backendName]){gCl(this.div,className).style.display="inline-block";return true}else{gCl(this.div,className).style.display="none";return false}}}})(typeof window!=="undefined"?window:global);(function(global){var ValidatorContext=function(parent,collectMultiple){this.missing=[];this.schemas=parent?Object.create(parent.schemas):{};this.collectMultiple=collectMultiple;this.errors=[];this.handleError=collectMultiple?this.collectError:this.returnError};ValidatorContext.prototype.returnError=function(error){return error};ValidatorContext.prototype.collectError=function(error){if(error){this.errors.push(error)}return null};ValidatorContext.prototype.prefixErrors=function(startIndex,dataPath,schemaPath){for(var i=startIndex;i<this.errors.length;i++){this.errors[i]=this.errors[i].prefixWith(dataPath,schemaPath)}return this};ValidatorContext.prototype.getSchema=function(url){if(this.schemas[url]!=undefined){var schema=this.schemas[url];return schema}var baseUrl=url;var fragment="";if(url.indexOf("#")!=-1){fragment=url.substring(url.indexOf("#")+1);baseUrl=url.substring(0,url.indexOf("#"))}if(this.schemas[baseUrl]!=undefined){var schema=this.schemas[baseUrl];var pointerPath=decodeURIComponent(fragment);if(pointerPath==""){return schema}else if(pointerPath.charAt(0)!="/"){return undefined}var parts=pointerPath.split("/").slice(1);for(var i=0;i<parts.length;i++){var component=parts[i].replace("~1","/").replace("~0","~");if(schema[component]==undefined){schema=undefined;break}schema=schema[component]}if(schema!=undefined){return schema}}if(this.missing[baseUrl]==undefined){this.missing.push(baseUrl);this.missing[baseUrl]=baseUrl}};ValidatorContext.prototype.addSchema=function(url,schema){var map={};map[url]=schema;normSchema(schema,url);searchForTrustedSchemas(map,schema,url);for(var key in map){this.schemas[key]=map[key]}return map};ValidatorContext.prototype.validateAll=function validateAll(data,schema,dataPathParts,schemaPathParts){if(schema["$ref"]!=undefined){schema=this.getSchema(schema["$ref"]);if(!schema){return null}}var errorCount=this.errors.length;var error=this.validateBasic(data,schema)||this.validateNumeric(data,schema)||this.validateString(data,schema)||this.validateArray(data,schema)||this.validateObject(data,schema)||this.validateCombinations(data,schema)||null;if(error||errorCount!=this.errors.length){while(dataPathParts&&dataPathParts.length||schemaPathParts&&schemaPathParts.length){var dataPart=dataPathParts&&dataPathParts.length?""+dataPathParts.pop():null;var schemaPart=schemaPathParts&&schemaPathParts.length?""+schemaPathParts.pop():null;if(error){error=error.prefixWith(dataPart,schemaPart)}this.prefixErrors(errorCount,dataPart,schemaPart)}}return this.handleError(error)};function recursiveCompare(A,B){if(A===B){return true}if(typeof A=="object"&&typeof B=="object"){if(Array.isArray(A)!=Array.isArray(B)){return false}else if(Array.isArray(A)){if(A.length!=B.length){return false}for(var i=0;i<A.length;i++){if(!recursiveCompare(A[i],B[i])){return false}}}else{for(var key in A){if(B[key]===undefined&&A[key]!==undefined){return false}}for(var key in B){if(A[key]===undefined&&B[key]!==undefined){return false}}for(var key in A){if(!recursiveCompare(A[key],B[key])){return false}}}return true}return false}ValidatorContext.prototype.validateBasic=function validateBasic(data,schema){var error;if(error=this.validateType(data,schema)){return error.prefixWith(null,"type")}if(error=this.validateEnum(data,schema)){return error.prefixWith(null,"type")}return null};ValidatorContext.prototype.validateType=function validateType(data,schema){if(schema.type==undefined){return null}var dataType=typeof data;if(data==null){dataType="null"}else if(Array.isArray(data)){dataType="array"}var allowedTypes=schema.type;if(typeof allowedTypes!="object"){allowedTypes=[allowedTypes]}for(var i=0;i<allowedTypes.length;i++){var type=allowedTypes[i];if(type==dataType||type=="integer"&&dataType=="number"&&data%1==0){return null}}return new ValidationError(ErrorCodes.INVALID_TYPE,"invalid data type: "+dataType)};ValidatorContext.prototype.validateEnum=function validateEnum(data,schema){if(schema["enum"]==undefined){return null}for(var i=0;i<schema["enum"].length;i++){var enumVal=schema["enum"][i];if(recursiveCompare(data,enumVal)){return null}}return new ValidationError(ErrorCodes.ENUM_MISMATCH,"No enum match for: "+JSON.stringify(data))};ValidatorContext.prototype.validateNumeric=function validateNumeric(data,schema){return this.validateMultipleOf(data,schema)||this.validateMinMax(data,schema)||null};ValidatorContext.prototype.validateMultipleOf=function validateMultipleOf(data,schema){var multipleOf=schema.multipleOf||schema.divisibleBy;if(multipleOf==undefined){return null}if(typeof data=="number"){if(data%multipleOf!=0){return new ValidationError(ErrorCodes.NUMBER_MULTIPLE_OF,"Value "+data+" is not a multiple of "+multipleOf)}}return null};ValidatorContext.prototype.validateMinMax=function validateMinMax(data,schema){if(typeof data!="number"){return null}if(schema.minimum!=undefined){if(data<schema.minimum){return new ValidationError(ErrorCodes.NUMBER_MINIMUM,"Value "+data+" is less than minimum "+schema.minimum).prefixWith(null,"minimum")}if(schema.exclusiveMinimum&&data==schema.minimum){return new ValidationError(ErrorCodes.NUMBER_MINIMUM_EXCLUSIVE,"Value "+data+" is equal to exclusive minimum "+schema.minimum).prefixWith(null,"exclusiveMinimum")}}if(schema.maximum!=undefined){if(data>schema.maximum){return new ValidationError(ErrorCodes.NUMBER_MAXIMUM,"Value "+data+" is greater than maximum "+schema.maximum).prefixWith(null,"maximum")}if(schema.exclusiveMaximum&&data==schema.maximum){return new ValidationError(ErrorCodes.NUMBER_MAXIMUM_EXCLUSIVE,"Value "+data+" is equal to exclusive maximum "+schema.maximum).prefixWith(null,"exclusiveMaximum")}}return null};ValidatorContext.prototype.validateString=function validateString(data,schema){return this.validateStringLength(data,schema)||this.validateStringPattern(data,schema)||null};ValidatorContext.prototype.validateStringLength=function validateStringLength(data,schema){if(typeof data!="string"){return null}if(schema.minLength!=undefined){if(data.length<schema.minLength){return new ValidationError(ErrorCodes.STRING_LENGTH_SHORT,"String is too short ("+data.length+" chars), minimum "+schema.minLength).prefixWith(null,"minLength")}}if(schema.maxLength!=undefined){if(data.length>schema.maxLength){return new ValidationError(ErrorCodes.STRING_LENGTH_LONG,"String is too long ("+data.length+" chars), maximum "+schema.maxLength).prefixWith(null,"maxLength")}}return null};ValidatorContext.prototype.validateStringPattern=function validateStringPattern(data,schema){if(typeof data!="string"||schema.pattern==undefined){return null}var regexp=new RegExp(schema.pattern);if(!regexp.test(data)){return new ValidationError(ErrorCodes.STRING_PATTERN,"String does not match pattern").prefixWith(null,"pattern")}return null};ValidatorContext.prototype.validateArray=function validateArray(data,schema){if(!Array.isArray(data)){return null}return this.validateArrayLength(data,schema)||this.validateArrayUniqueItems(data,schema)||this.validateArrayItems(data,schema)||null};ValidatorContext.prototype.validateArrayLength=function validateArrayLength(data,schema){if(schema.minItems!=undefined){if(data.length<schema.minItems){var error=new ValidationError(ErrorCodes.ARRAY_LENGTH_SHORT,"Array is too short ("+data.length+"), minimum "+schema.minItems).prefixWith(null,"minItems");if(this.handleError(error)){return error}}}if(schema.maxItems!=undefined){if(data.length>schema.maxItems){var error=new ValidationError(ErrorCodes.ARRAY_LENGTH_LONG,"Array is too long ("+data.length+" chars), maximum "+schema.maxItems).prefixWith(null,"maxItems");if(this.handleError(error)){return error}}}return null};ValidatorContext.prototype.validateArrayUniqueItems=function validateArrayUniqueItems(data,schema){if(schema.uniqueItems){for(var i=0;i<data.length;i++){for(var j=i+1;j<data.length;j++){if(recursiveCompare(data[i],data[j])){var error=new ValidationError(ErrorCodes.ARRAY_UNIQUE,"Array items are not unique (indices "+i+" and "+j+")").prefixWith(null,"uniqueItems");if(this.handleError(error)){return error}}}}}return null};ValidatorContext.prototype.validateArrayItems=function validateArrayItems(data,schema){if(schema.items==undefined){return null}var error;if(Array.isArray(schema.items)){for(var i=0;i<data.length;i++){if(i<schema.items.length){if(error=this.validateAll(data[i],schema.items[i],[i],["items",i])){return error}}else if(schema.additionalItems!=undefined){if(typeof schema.additionalItems=="boolean"){if(!schema.additionalItems){error=new ValidationError(ErrorCodes.ARRAY_ADDITIONAL_ITEMS,"Additional items not allowed").prefixWith(""+i,"additionalItems");if(this.handleError(error)){return error}}}else if(error=this.validateAll(data[i],schema.additionalItems,[i],["additionalItems"])){return error}}}}else{for(var i=0;i<data.length;i++){if(error=this.validateAll(data[i],schema.items,[i],["items"])){return error}}}return null};ValidatorContext.prototype.validateObject=function validateObject(data,schema){if(typeof data!="object"||data==null||Array.isArray(data)){return null}return this.validateObjectMinMaxProperties(data,schema)||this.validateObjectRequiredProperties(data,schema)||this.validateObjectProperties(data,schema)||this.validateObjectDependencies(data,schema)||null};ValidatorContext.prototype.validateObjectMinMaxProperties=function validateObjectMinMaxProperties(data,schema){var keys=Object.keys(data);if(schema.minProperties!=undefined){if(keys.length<schema.minProperties){var error=new ValidationError(ErrorCodes.OBJECT_PROPERTIES_MINIMUM,"Too few properties defined ("+keys.length+"), minimum "+schema.minProperties).prefixWith(null,"minProperties");if(this.handleError(error)){return error}}}if(schema.maxProperties!=undefined){if(keys.length>schema.maxProperties){var error=new ValidationError(ErrorCodes.OBJECT_PROPERTIES_MAXIMUM,"Too many properties defined ("+keys.length+"), maximum "+schema.maxProperties).prefixWith(null,"maxProperties");if(this.handleError(error)){return error}}}return null};ValidatorContext.prototype.validateObjectRequiredProperties=function validateObjectRequiredProperties(data,schema){if(schema.required!=undefined){for(var i=0;i<schema.required.length;i++){var key=schema.required[i];if(data[key]===undefined){var error=new ValidationError(ErrorCodes.OBJECT_REQUIRED,"Missing required property: "+key).prefixWith(null,""+i).prefixWith(null,"required");if(this.handleError(error)){return error}}}}return null};ValidatorContext.prototype.validateObjectProperties=function validateObjectProperties(data,schema){var error;for(var key in data){var foundMatch=false;if(schema.properties!=undefined&&schema.properties[key]!=undefined){foundMatch=true;if(error=this.validateAll(data[key],schema.properties[key],[key],["properties",key])){return error}}if(schema.patternProperties!=undefined){for(var patternKey in schema.patternProperties){var regexp=new RegExp(patternKey);if(regexp.test(key)){foundMatch=true;if(error=this.validateAll(data[key],schema.patternProperties[patternKey],[key],["patternProperties",patternKey])){return error}}}}if(!foundMatch&&schema.additionalProperties!=undefined){if(typeof schema.additionalProperties=="boolean"){if(!schema.additionalProperties){error=new ValidationError(ErrorCodes.OBJECT_ADDITIONAL_PROPERTIES,"Additional properties not allowed").prefixWith(key,"additionalProperties");if(this.handleError(error)){return error}}}else{if(error=this.validateAll(data[key],schema.additionalProperties,[key],["additionalProperties"])){return error}}}}return null};ValidatorContext.prototype.validateObjectDependencies=function validateObjectDependencies(data,schema){var error;if(schema.dependencies!=undefined){for(var depKey in schema.dependencies){if(data[depKey]!==undefined){var dep=schema.dependencies[depKey];if(typeof dep=="string"){if(data[dep]===undefined){error=new ValidationError(ErrorCodes.OBJECT_DEPENDENCY_KEY,"Dependency failed - key must exist: "+dep).prefixWith(null,depKey).prefixWith(null,"dependencies");if(this.handleError(error)){return error}}}else if(Array.isArray(dep)){for(var i=0;i<dep.length;i++){var requiredKey=dep[i];if(data[requiredKey]===undefined){error=new ValidationError(ErrorCodes.OBJECT_DEPENDENCY_KEY,"Dependency failed - key must exist: "+requiredKey).prefixWith(null,""+i).prefixWith(null,depKey).prefixWith(null,"dependencies");if(this.handleError(error)){return error}}}}else{if(error=this.validateAll(data,dep,[],["dependencies",depKey])){return error}}}}}return null};ValidatorContext.prototype.validateCombinations=function validateCombinations(data,schema){var error;return this.validateAllOf(data,schema)||this.validateAnyOf(data,schema)||this.validateOneOf(data,schema)||this.validateNot(data,schema)||null};ValidatorContext.prototype.validateAllOf=function validateAllOf(data,schema){if(schema.allOf==undefined){return null}var error;for(var i=0;i<schema.allOf.length;i++){var subSchema=schema.allOf[i];if(error=this.validateAll(data,subSchema,[],["allOf",i])){return error}}return null};ValidatorContext.prototype.validateAnyOf=function validateAnyOf(data,schema){if(schema.anyOf==undefined){return null}var errors=[];var startErrorCount=this.errors.length;for(var i=0;i<schema.anyOf.length;i++){var subSchema=schema.anyOf[i];var errorCount=this.errors.length;var error=this.validateAll(data,subSchema,[],["anyOf",i]);if(error==null&&errorCount==this.errors.length){this.errors=this.errors.slice(0,startErrorCount);return null}if(error){errors.push(error.prefixWith(null,""+i).prefixWith(null,"anyOf"))}}errors=errors.concat(this.errors.slice(startErrorCount));this.errors=this.errors.slice(0,startErrorCount);return new ValidationError(ErrorCodes.ANY_OF_MISSING,'Data does not match any schemas from "anyOf"',"","/anyOf",errors)};ValidatorContext.prototype.validateOneOf=function validateOneOf(data,schema){if(schema.oneOf==undefined){return null}var validIndex=null;var errors=[];var startErrorCount=this.errors.length;for(var i=0;i<schema.oneOf.length;i++){var subSchema=schema.oneOf[i];var errorCount=this.errors.length;var error=this.validateAll(data,subSchema,[],["oneOf",i]);if(error==null&&errorCount==this.errors.length){if(validIndex==null){validIndex=i}else{this.errors=this.errors.slice(0,startErrorCount);return new ValidationError(ErrorCodes.ONE_OF_MULTIPLE,'Data is valid against more than one schema from "oneOf": indices '+validIndex+" and "+i,"","/oneOf")}}else if(error){errors.push(error.prefixWith(null,""+i).prefixWith(null,"oneOf"))}}if(validIndex==null){errors=errors.concat(this.errors.slice(startErrorCount));this.errors=this.errors.slice(0,startErrorCount);return new ValidationError(ErrorCodes.ONE_OF_MISSING,'Data does not match any schemas from "oneOf"',"","/oneOf",errors)}else{this.errors=this.errors.slice(0,startErrorCount)}return null};ValidatorContext.prototype.validateNot=function validateNot(data,schema){if(schema.not==undefined){return null}var oldErrorCount=this.errors.length;var error=this.validateAll(data,schema.not);var notErrors=this.errors.slice(oldErrorCount);this.errors=this.errors.slice(0,oldErrorCount);if(error==null&&notErrors.length==0){return new ValidationError(ErrorCodes.NOT_PASSED,'Data matches schema from "not"',"","/not")}return null};function parseURI(url){var m=String(url).replace(/^\s+|\s+$/g,"").match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);return m?{href:m[0]||"",protocol:m[1]||"",authority:m[2]||"",host:m[3]||"",hostname:m[4]||"",port:m[5]||"",pathname:m[6]||"",search:m[7]||"",hash:m[8]||""}:null}function resolveUrl(base,href){function removeDotSegments(input){var output=[];input.replace(/^(\.\.?(\/|$))+/,"").replace(/\/(\.(\/|$))+/g,"/").replace(/\/\.\.$/,"/../").replace(/\/?[^\/]*/g,function(p){if(p==="/.."){output.pop()}else{output.push(p)}});return output.join("").replace(/^\//,input.charAt(0)==="/"?"/":"")}href=parseURI(href||"");base=parseURI(base||"");return!href||!base?null:(href.protocol||base.protocol)+(href.protocol||href.authority?href.authority:base.authority)+removeDotSegments(href.protocol||href.authority||href.pathname.charAt(0)==="/"?href.pathname:href.pathname?(base.authority&&!base.pathname?"/":"")+base.pathname.slice(0,base.pathname.lastIndexOf("/")+1)+href.pathname:base.pathname)+(href.protocol||href.authority||href.pathname?href.search:href.search||base.search)+href.hash}function normSchema(schema,baseUri){if(baseUri==undefined){baseUri=schema.id}else if(typeof schema.id=="string"){baseUri=resolveUrl(baseUri,schema.id);schema.id=baseUri}if(typeof schema=="object"){if(Array.isArray(schema)){for(var i=0;i<schema.length;i++){normSchema(schema[i],baseUri)}}else if(typeof schema["$ref"]=="string"){schema["$ref"]=resolveUrl(baseUri,schema["$ref"])}else{for(var key in schema){if(key!="enum"){normSchema(schema[key],baseUri)}}}}}var ErrorCodes={INVALID_TYPE:0,ENUM_MISMATCH:1,ANY_OF_MISSING:10,ONE_OF_MISSING:11,ONE_OF_MULTIPLE:12,NOT_PASSED:13,NUMBER_MULTIPLE_OF:100,NUMBER_MINIMUM:101,NUMBER_MINIMUM_EXCLUSIVE:102,NUMBER_MAXIMUM:103,NUMBER_MAXIMUM_EXCLUSIVE:104,STRING_LENGTH_SHORT:200,STRING_LENGTH_LONG:201,STRING_PATTERN:202,OBJECT_PROPERTIES_MINIMUM:300,OBJECT_PROPERTIES_MAXIMUM:301,OBJECT_REQUIRED:302,OBJECT_ADDITIONAL_PROPERTIES:303,OBJECT_DEPENDENCY_KEY:304,ARRAY_LENGTH_SHORT:400,ARRAY_LENGTH_LONG:401,ARRAY_UNIQUE:402,ARRAY_ADDITIONAL_ITEMS:403};function ValidationError(code,message,dataPath,schemaPath,subErrors){if(code==undefined){throw new Error("No code supplied for error: "+message)}this.code=code;this.message=message;this.dataPath=dataPath?dataPath:"";this.schemaPath=schemaPath?schemaPath:"";this.subErrors=subErrors?subErrors:null}ValidationError.prototype={prefixWith:function(dataPrefix,schemaPrefix){if(dataPrefix!=null){dataPrefix=dataPrefix.replace("~","~0").replace("/","~1");this.dataPath="/"+dataPrefix+this.dataPath}if(schemaPrefix!=null){schemaPrefix=schemaPrefix.replace("~","~0").replace("/","~1");this.schemaPath="/"+schemaPrefix+this.schemaPath}if(this.subErrors!=null){for(var i=0;i<this.subErrors.length;i++){this.subErrors[i].prefixWith(dataPrefix,schemaPrefix)}}return this}};function searchForTrustedSchemas(map,schema,url){if(typeof schema.id=="string"){if(schema.id.substring(0,url.length)==url){var remainder=schema.id.substring(url.length);if(url.length>0&&url.charAt(url.length-1)=="/"||remainder.charAt(0)=="#"||remainder.charAt(0)=="?"){if(map[schema.id]==undefined){map[schema.id]=schema}}}}if(typeof schema=="object"){for(var key in schema){if(key!="enum"&&typeof schema[key]=="object"){searchForTrustedSchemas(map,schema[key],url)}}}return map}var globalContext=new ValidatorContext;var publicApi={validate:function(data,schema){var context=new ValidatorContext(globalContext);if(typeof schema=="string"){schema={$ref:schema}}var added=context.addSchema("",schema);var error=context.validateAll(data,schema);this.error=error;this.missing=context.missing;this.valid=error==null;return this.valid},validateResult:function(){var result={};this.validate.apply(result,arguments);return result},validateMultiple:function(data,schema){var context=new ValidatorContext(globalContext,true);if(typeof schema=="string"){schema={$ref:schema}}context.addSchema("",schema);context.validateAll(data,schema);var result={};result.errors=context.errors;result.missing=context.missing;result.valid=result.errors.length==0;return result},addSchema:function(url,schema){return globalContext.addSchema(url,schema)},getSchema:function(url){return globalContext.getSchema(url)},missing:[],error:null,normSchema:normSchema,resolveUrl:resolveUrl,errorCodes:ErrorCodes};global.tv4=publicApi})(typeof window!="undefined"?window:global);var CHARS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");Math.uuid=function(len,radix){var chars=CHARS,uuid=[],i;radix=radix||chars.length;if(len){for(i=0;i<len;i++)uuid[i]=chars[0|Math.random()*radix]}else{var r;uuid[8]=uuid[13]=uuid[18]=uuid[23]="-";uuid[14]="4";for(i=0;i<36;i++){if(!uuid[i]){r=0|Math.random()*16;uuid[i]=chars[i==19?r&3|8:r]}}}return uuid.join("")};(function(global){function deprecate(thing,replacement){console.log("WARNING: "+thing+" is deprecated. Use "+replacement+" instead.")}var RS=RemoteStorage;RS.BaseClient=function(storage,base){if(base[base.length-1]!=="/"){throw"Not a folder: "+base}if(base==="/"){this.makePath=function(path){return(path[0]==="/"?"":"/")+path}}this.storage=storage;this.base=base;var parts=this.base.split("/");if(parts.length>2){this.moduleName=parts[1]}else{this.moduleName="root"}RS.eventHandling(this,"change");this.on=this.on.bind(this);storage.onChange(this.base,this._fireChange.bind(this))};RS.BaseClient.prototype={extend:function(object){for(var key in object){this[key]=object[key]}return this},scope:function(path){return new RS.BaseClient(this.storage,this.makePath(path))},getListing:function(path,maxAge){if(typeof path!=="string"){path=""
  }else if(path.length>0&&path[path.length-1]!=="/"){throw"Not a folder: "+path}if(maxAgeInvalid(maxAge)){return promising().reject("Argument 'maxAge' of baseClient.getListing must be undefined or a number")}return this.storage.get(this.makePath(path),maxAge).then(function(status,body){return status===404?undefined:body})},getAll:function(path,maxAge){if(typeof path!=="string"){path=""}else if(path.length>0&&path[path.length-1]!=="/"){throw"Not a folder: "+path}if(maxAgeInvalid(maxAge)){return promising().reject("Argument 'maxAge' of baseClient.getAll must be undefined or a number")}return this.storage.get(this.makePath(path),maxAge).then(function(status,body){if(status===404){return}if(typeof body==="object"){var promise=promising();var count=Object.keys(body).length,i=0;if(count===0){return}for(var key in body){this.storage.get(this.makePath(path+key),maxAge).then(function(status,b){body[this.key]=b;i++;if(i===count){promise.fulfill(body)}}.bind({key:key}))}return promise}}.bind(this))},getFile:function(path,maxAge){if(typeof path!=="string"){return promising().reject("Argument 'path' of baseClient.getFile must be a string")}if(maxAgeInvalid(maxAge)){return promising().reject("Argument 'maxAge' of baseClient.getFile must be undefined or a number")}return this.storage.get(this.makePath(path),maxAge).then(function(status,body,mimeType,revision){return{data:body,mimeType:mimeType,revision:revision}})},storeFile:function(mimeType,path,body){if(typeof mimeType!=="string"){return promising().reject("Argument 'mimeType' of baseClient.storeFile must be a string")}if(typeof path!=="string"){return promising().reject("Argument 'path' of baseClient.storeFile must be a string")}if(typeof body!=="string"&&typeof body!=="object"){return promising().reject("Argument 'body' of baseClient.storeFile must be a string, ArrayBuffer, or ArrayBufferView")}var self=this;return this.storage.put(this.makePath(path),body,mimeType).then(function(status,_body,_mimeType,revision){if(status===200||status===201){return revision}else{throw"Request (PUT "+self.makePath(path)+") failed with status: "+status}})},getObject:function(path,maxAge){if(typeof path!=="string"){return promising().reject("Argument 'path' of baseClient.getObject must be a string")}if(maxAgeInvalid(maxAge)){return promising().reject("Argument 'maxAge' of baseClient.getObject must be undefined or a number")}return this.storage.get(this.makePath(path),maxAge).then(function(status,body,mimeType,revision){if(typeof body==="object"){return body}else if(typeof body!=="undefined"&&status===200){throw"Not an object: "+this.makePath(path)}})},storeObject:function(typeAlias,path,object){if(typeof typeAlias!=="string"){return promising().reject("Argument 'typeAlias' of baseClient.storeObject must be a string")}if(typeof path!=="string"){return promising().reject("Argument 'path' of baseClient.storeObject must be a string")}if(typeof object!=="object"){return promising().reject("Argument 'object' of baseClient.storeObject must be an object")}this._attachType(object,typeAlias);try{var validationResult=this.validate(object);if(!validationResult.valid){return promising(function(p){p.reject(validationResult)})}}catch(exc){if(!(exc instanceof RS.BaseClient.Types.SchemaNotFound)){return promising().reject(exc)}}return this.storage.put(this.makePath(path),object,"application/json; charset=UTF-8").then(function(status,_body,_mimeType,revision){if(status===200||status===201){return revision}else{throw"Request (PUT "+this.makePath(path)+") failed with status: "+status}}.bind(this))},remove:function(path){if(typeof path!=="string"){return promising().reject("Argument 'path' of baseClient.remove must be a string")}return this.storage.delete(this.makePath(path))},cache:function(path,strategy){if(typeof path!=="string"){throw"Argument 'path' of baseClient.cache must be a string"}if(strategy===false){deprecate("caching strategy <false>",'<"FLUSH">');strategy="FLUSH"}else if(strategy===undefined){strategy="ALL"}else if(typeof strategy!=="string"){deprecate("that caching strategy",'<"ALL">');strategy="ALL"}if(strategy!=="FLUSH"&&strategy!=="SEEN"&&strategy!=="ALL"){throw"Argument 'strategy' of baseclient.cache must be one of "+'["FLUSH", "SEEN", "ALL"]'}this.storage.caching.set(this.makePath(path),strategy);return this},flush:function(path){return this.storage.local.flush(path)},makePath:function(path){return this.base+(path||"")},_fireChange:function(event){this._emit("change",event)},_cleanPath:RS.WireClient.cleanPath,getItemURL:function(path){if(typeof path!=="string"){throw"Argument 'path' of baseClient.getItemURL must be a string"}if(this.storage.connected){path=this._cleanPath(this.makePath(path));return this.storage.remote.href+path}else{return undefined}},uuid:function(){return Math.uuid()}};RS.BaseClient._rs_init=function(){RS.prototype.scope=function(path){if(typeof path!=="string"){throw"Argument 'path' of baseClient.scope must be a string"}return new RS.BaseClient(this,path)}};maxAgeInvalid=function(maxAge){return typeof maxAge!=="undefined"&&typeof maxAge!=="number"}})(typeof window!=="undefined"?window:global);(function(global){RemoteStorage.BaseClient.Types={uris:{},schemas:{},aliases:{},declare:function(moduleName,alias,uri,schema){var fullAlias=moduleName+"/"+alias;if(schema.extends){var extendedAlias;var parts=schema.extends.split("/");if(parts.length===1){extendedAlias=moduleName+"/"+parts.shift()}else{extendedAlias=parts.join("/")}var extendedUri=this.uris[extendedAlias];if(!extendedUri){throw"Type '"+fullAlias+"' tries to extend unknown schema '"+extendedAlias+"'"}schema.extends=this.schemas[extendedUri]}this.uris[fullAlias]=uri;this.aliases[uri]=fullAlias;this.schemas[uri]=schema},resolveAlias:function(alias){return this.uris[alias]},getSchema:function(uri){return this.schemas[uri]},inScope:function(moduleName){var ml=moduleName.length;var schemas={};for(var alias in this.uris){if(alias.substr(0,ml+1)===moduleName+"/"){var uri=this.uris[alias];schemas[uri]=this.schemas[uri]}}return schemas}};var SchemaNotFound=function(uri){var error=new Error("Schema not found: "+uri);error.name="SchemaNotFound";return error};SchemaNotFound.prototype=Error.prototype;RemoteStorage.BaseClient.Types.SchemaNotFound=SchemaNotFound;RemoteStorage.BaseClient.prototype.extend({validate:function(object){var schema=RemoteStorage.BaseClient.Types.getSchema(object["@context"]);if(schema){return tv4.validateResult(object,schema)}else{throw new SchemaNotFound(object["@context"])}},declareType:function(alias,uri,schema){if(!schema){schema=uri;uri=this._defaultTypeURI(alias)}RemoteStorage.BaseClient.Types.declare(this.moduleName,alias,uri,schema)},_defaultTypeURI:function(alias){return"http://remotestoragejs.com/spec/modules/"+this.moduleName+"/"+alias},_attachType:function(object,alias){object["@context"]=RemoteStorage.BaseClient.Types.resolveAlias(alias)||this._defaultTypeURI(alias)}});Object.defineProperty(RemoteStorage.BaseClient.prototype,"schemas",{configurable:true,get:function(){return RemoteStorage.BaseClient.Types.inScope(this.moduleName)}})})(typeof window!=="undefined"?window:global);(function(){RemoteStorage.MODULES={};RemoteStorage.defineModule=function(moduleName,builder){RemoteStorage.MODULES[moduleName]=builder;Object.defineProperty(RemoteStorage.prototype,moduleName,{configurable:true,get:function(){var instance=this._loadModule(moduleName);Object.defineProperty(this,moduleName,{value:instance});return instance}});if(moduleName.indexOf("-")!==-1){var camelizedName=moduleName.replace(/\-[a-z]/g,function(s){return s[1].toUpperCase()});Object.defineProperty(RemoteStorage.prototype,camelizedName,{get:function(){return this[moduleName]}})}};RemoteStorage.prototype._loadModule=function(moduleName){var builder=RemoteStorage.MODULES[moduleName];if(builder){var module=builder(new RemoteStorage.BaseClient(this,"/"+moduleName+"/"),new RemoteStorage.BaseClient(this,"/public/"+moduleName+"/"));return module.exports}else{throw"Unknown module: "+moduleName}};RemoteStorage.prototype.defineModule=function(moduleName){console.log("remoteStorage.defineModule is deprecated, use RemoteStorage.defineModule instead!");RemoteStorage.defineModule.apply(RemoteStorage,arguments)}})();(function(){function loadTable(table,storage,paths){table.setAttribute("border","1");table.style.margin="8px";table.innerHTML="";var thead=document.createElement("thead");table.appendChild(thead);var titleRow=document.createElement("tr");thead.appendChild(titleRow);["Path","Content-Type","Revision"].forEach(function(label){var th=document.createElement("th");th.textContent=label;thead.appendChild(th)});var tbody=document.createElement("tbody");table.appendChild(tbody);function renderRow(tr,path,contentType,revision){[path,contentType,revision].forEach(function(value){var td=document.createElement("td");td.textContent=value||"";tr.appendChild(td)})}function loadRow(path){if(storage.connected===false){return}function processRow(status,body,contentType,revision){if(status===200){var tr=document.createElement("tr");tbody.appendChild(tr);renderRow(tr,path,contentType,revision);if(path[path.length-1]==="/"){for(var key in body){loadRow(path+key)}}}}storage.get(path).then(processRow)}paths.forEach(loadRow)}function renderWrapper(title,table,storage,paths){var wrapper=document.createElement("div");var heading=document.createElement("h2");heading.textContent=title;wrapper.appendChild(heading);var updateButton=document.createElement("button");updateButton.textContent="Refresh";updateButton.onclick=function(){loadTable(table,storage,paths)};wrapper.appendChild(updateButton);if(storage.reset){var resetButton=document.createElement("button");resetButton.textContent="Reset";resetButton.onclick=function(){storage.reset(function(newStorage){storage=newStorage;loadTable(table,storage,paths)})};wrapper.appendChild(resetButton)}wrapper.appendChild(table);loadTable(table,storage,paths);return wrapper}function renderLocalChanges(local){var wrapper=document.createElement("div");var heading=document.createElement("h2");heading.textContent="Outgoing changes";wrapper.appendChild(heading);var updateButton=document.createElement("button");updateButton.textContent="Refresh";wrapper.appendChild(updateButton);var list=document.createElement("ul");list.style.fontFamily="courier";wrapper.appendChild(list);function updateList(){local.changesBelow("/").then(function(changes){list.innerHTML="";changes.forEach(function(change){var el=document.createElement("li");el.textContent=JSON.stringify(change);list.appendChild(el)})})}updateButton.onclick=updateList;updateList();return wrapper}RemoteStorage.prototype.inspect=function(){var widget=document.createElement("div");widget.id="remotestorage-inspect";widget.style.position="absolute";widget.style.top=0;widget.style.left=0;widget.style.background="black";widget.style.color="white";widget.style.border="groove 5px #ccc";var controls=document.createElement("div");controls.style.position="absolute";controls.style.top=0;controls.style.left=0;var heading=document.createElement("strong");heading.textContent=" remotestorage.js inspector ";controls.appendChild(heading);var syncButton;if(this.local){syncButton=document.createElement("button");syncButton.textContent="Synchronize";controls.appendChild(syncButton)}var closeButton=document.createElement("button");closeButton.textContent="Close";closeButton.onclick=function(){document.body.removeChild(widget)};controls.appendChild(closeButton);widget.appendChild(controls);var remoteTable=document.createElement("table");var localTable=document.createElement("table");widget.appendChild(renderWrapper("Remote",remoteTable,this.remote,this.caching.rootPaths));if(this.local){widget.appendChild(renderWrapper("Local",localTable,this.local,["/"]));widget.appendChild(renderLocalChanges(this.local));syncButton.onclick=function(){this.log("sync clicked");this.sync().then(function(){this.log("SYNC FINISHED");loadTable(localTable,this.local,["/"])}.bind(this),function(err){console.error("SYNC FAILED",err,err.stack)})}.bind(this)}document.body.appendChild(widget)}})();(function(){var util={getEventEmitter:function(){var object={};var args=Array.prototype.slice.call(arguments);args.unshift(object);RemoteStorage.eventHandling.apply(RemoteStorage,args);object.emit=object._emit;return object},extend:function(target){var sources=Array.prototype.slice.call(arguments,1);sources.forEach(function(source){for(var key in source){target[key]=source[key]}});return target},asyncEach:function(array,callback){return this.asyncMap(array,callback).then(function(){return array})},asyncMap:function(array,callback){var promise=promising();var n=array.length,i=0;var results=[],errors=[];function oneDone(){i++;if(i===n){promise.fulfill(results,errors)}}array.forEach(function(item,index){var result;try{result=callback(item)}catch(exc){oneDone();errors[index]=exc}if(typeof result==="object"&&typeof result.then==="function"){result.then(function(res){results[index]=res;oneDone()},function(error){errors[index]=res;oneDone()})}else{oneDone();results[index]=result}});return promise},containingFolder:function(path){var folder=path.replace(/[^\/]+\/?$/,"");return folder===path?null:folder},isFolder:function(path){return path.substr(-1)==="/"},baseName:function(path){var parts=path.split("/");if(util.isFolder(path)){return parts[parts.length-2]+"/"}else{return parts[parts.length-1]}},bindAll:function(object){for(var key in this){if(typeof object[key]==="function"){object[key]=object[key].bind(object)}}}};Object.defineProperty(RemoteStorage.prototype,"util",{get:function(){console.log("DEPRECATION WARNING: remoteStorage.util is deprecated and will be removed with the next major release.");return util}})})();(function(global){var RS=RemoteStorage;var BASE_URL="https://www.googleapis.com";var AUTH_URL="https://accounts.google.com/o/oauth2/auth";var AUTH_SCOPE="https://www.googleapis.com/auth/drive";var GD_DIR_MIME_TYPE="application/vnd.google-apps.folder";var RS_DIR_MIME_TYPE="application/json; charset=UTF-8";function buildQueryString(params){return Object.keys(params).map(function(key){return encodeURIComponent(key)+"="+encodeURIComponent(params[key])}).join("&")}function fileNameFromMeta(meta){return encodeURIComponent(meta.title)+(meta.mimeType===GD_DIR_MIME_TYPE?"/":"")}function metaTitleFromFileName(filename){if(filename.substr(-1)==="/"){filename=filename.substr(0,filename.length-1)}return decodeURIComponent(filename)}function parentPath(path){return path.replace(/[^\/]+\/?$/,"")}function baseName(path){var parts=path.split("/");if(path.substr(-1)==="/"){return parts[parts.length-2]+"/"}else{return parts[parts.length-1]}}var Cache=function(maxAge){this.maxAge=maxAge;this._items={}};Cache.prototype={get:function(key){var item=this._items[key];var now=(new Date).getTime();return item&&item.t>=now-this.maxAge?item.v:undefined},set:function(key,value){this._items[key]={v:value,t:(new Date).getTime()}}};RS.GoogleDrive=function(remoteStorage,clientId){RS.eventHandling(this,"connected");this.rs=remoteStorage;this.clientId=clientId;this._fileIdCache=new Cache(60*5);setTimeout(function(){this.configure(undefined,undefined,undefined,localStorage["remotestorage:googledrive:token"])}.bind(this),0)};RS.GoogleDrive.prototype={configure:function(_x,_y,_z,token){if(token){localStorage["remotestorage:googledrive:token"]=token;this.token=token;this.connected=true;this._emit("connected")}else{this.connected=false;delete this.token;delete localStorage["remotestorage:googledrive:token"]}},connect:function(){this.rs.setBackend("googledrive");RS.Authorize(AUTH_URL,AUTH_SCOPE,String(RS.Authorize.getLocation()),this.clientId)},get:function(path,options){if(path.substr(-1)==="/"){return this._getFolder(path,options)}else{return this._getFile(path,options)}},put:function(path,body,contentType,options){var promise=promising();function putDone(error,response){if(error){promise.reject(error)}else if(response.status>=200&&response.status<300){var meta=JSON.parse(response.responseText);promise.fulfill(200,undefined,meta.mimeType,meta.etag)}else{promise.reject("PUT failed with status "+response.status+" ("+response.responseText+")")}}this._getFileId(path,function(idError,id){if(idError){promise.reject(idError);return}else if(id){this._updateFile(id,path,body,contentType,options,putDone)}else{this._createFile(path,body,contentType,options,putDone)}});return promise},"delete":function(path,options){var promise=promising();this._getFileId(path,function(idError,id){if(idError){promise.reject(idError)}else if(id){this._request("DELETE",BASE_URL+"/drive/v2/files/"+id,{},function(deleteError,response){if(deleteError){promise.reject(deleteError)}else if(response.status===200||response.status===204){promise.fulfill(200)}else{promise.reject("Delete failed: "+response.status+" ("+response.responseText+")")}})}else{promise.fulfill(200)}});return promise},_updateFile:function(id,path,body,contentType,options,callback){callback=callback.bind(this);var metadata={mimeType:contentType};this._request("PUT",BASE_URL+"/upload/drive/v2/files/"+id+"?uploadType=resumable",{body:JSON.stringify(metadata),headers:{"Content-Type":"application/json; charset=UTF-8"}},function(metadataError,response){if(metadataError){callback(metadataError)}else{this._request("PUT",response.getResponseHeader("Location"),{body:contentType.match(/^application\/json/)?JSON.stringify(body):body},callback)}})},_createFile:function(path,body,contentType,options,callback){callback=callback.bind(this);this._getParentId(path,function(parentIdError,parentId){if(parentIdError){callback(parentIdError);return}var fileName=baseName(path);var metadata={title:metaTitleFromFileName(fileName),mimeType:contentType,parents:[{kind:"drive#fileLink",id:parentId}]};this._request("POST",BASE_URL+"/upload/drive/v2/files?uploadType=resumable",{body:JSON.stringify(metadata),headers:{"Content-Type":"application/json; charset=UTF-8"}},function(metadataError,response){if(metadataError){callback(metadataError)}else{this._request("POST",response.getResponseHeader("Location"),{body:contentType.match(/^application\/json/)?JSON.stringify(body):body},callback)}})})},_getFile:function(path,options){var promise=promising();this._getFileId(path,function(idError,id){if(idError){promise.reject(idError)}else{this._getMeta(id,function(metaError,meta){var etagWithoutQuotes;if(typeof meta==="object"&&typeof meta.etag==="string"){etagWithoutQuotes=meta.etag.substring(1,meta.etag.length-1)}if(metaError){promise.reject(metaError)}else if(meta.downloadUrl){var options={};if(meta.mimeType.match(/charset=binary/)){options.responseType="blob"}this._request("GET",meta.downloadUrl,options,function(downloadError,response){if(downloadError){promise.reject(downloadError)}else{var body=response.response;if(meta.mimeType.match(/^application\/json/)){try{body=JSON.parse(body)}catch(e){}}promise.fulfill(200,body,meta.mimeType,etagWithoutQuotes)}})}else{promise.fulfill(200,"",meta.mimeType,etagWithoutQuotes)}})}});return promise},_getFolder:function(path,options){var promise=promising();this._getFileId(path,function(idError,id){var query,fields,data,i,etagWithoutQuotes,itemsMap;if(idError){promise.reject(idError)}else if(!id){promise.fulfill(404)}else{query="'"+id+"' in parents";fields="items(downloadUrl,etag,fileSize,id,mimeType,title)";this._request("GET",BASE_URL+"/drive/v2/files?"+"q="+encodeURIComponent(query)+"&fields="+encodeURIComponent(fields)+"&maxResults=1000",{},function(childrenError,response){if(childrenError){promise.reject(childrenError)}else{if(response.status===200){try{data=JSON.parse(response.responseText)}catch(e){promise.reject("non-JSON response from GoogleDrive");return}itemsMap={};for(i=0;i<data.items.length;i++){etagWithoutQuotes=data.items[i].etag.substring(1,data.items[i].etag.length-1);if(data.items[i].mimeType===GD_DIR_MIME_TYPE){this._fileIdCache.set(path+data.items[i].title+"/",data.items[i].id);itemsMap[data.items[i].title+"/"]={ETag:etagWithoutQuotes}}else{this._fileIdCache.set(path+data.items[i].title,data.items[i].id);itemsMap[data.items[i].title]={ETag:etagWithoutQuotes,"Content-Type":data.items[i].mimeType,"Content-Length":data.items[i].fileSize}}}promise.fulfill(200,itemsMap,RS_DIR_MIME_TYPE,undefined)}else{promise.reject("request failed or something: "+response.status)}}})}});return promise},_getParentId:function(path,callback){callback=callback.bind(this);var foldername=parentPath(path);this._getFileId(foldername,function(idError,parentId){if(idError){callback(idError)}else if(parentId){callback(null,parentId)}else{this._createFolder(foldername,callback)}})},_createFolder:function(path,callback){callback=callback.bind(this);this._getParentId(path,function(idError,parentId){if(idError){callback(idError)}else{this._request("POST",BASE_URL+"/drive/v2/files",{body:JSON.stringify({title:metaTitleFromFileName(baseName(path)),mimeType:GD_DIR_MIME_TYPE,parents:[{id:parentId}]}),headers:{"Content-Type":"application/json; charset=UTF-8"}},function(createError,response){if(createError){callback(createError)}else{var meta=JSON.parse(response.responseText);callback(null,meta.id)}})}})},_getFileId:function(path,callback){callback=callback.bind(this);var id;if(path==="/"){callback(null,"root")}else if(id=this._fileIdCache.get(path)){callback(null,id)}else{this._getFolder(parentPath(path)).then(function(){var id=this._fileIdCache.get(path);if(!id){callback("no file or folder found at the path: "+path,null);return}callback(null,id)}.bind(this),callback)}},_getMeta:function(id,callback){callback=callback.bind(this);this._request("GET",BASE_URL+"/drive/v2/files/"+id,{},function(err,response){if(err){callback(err)}else{if(response.status===200){callback(null,JSON.parse(response.responseText))}else{callback("request (getting metadata for "+id+") failed with status: "+response.status)}}})},_request:function(method,url,options,callback){callback=callback.bind(this);if(!options.headers){options.headers={}}options.headers["Authorization"]="Bearer "+this.token;RS.WireClient.request.call(this,method,url,options,function(err,xhr){if(xhr&&xhr.status===401){this.connect();return}callback(err,xhr)})}};RS.GoogleDrive._rs_init=function(remoteStorage){var config=remoteStorage.apiKeys.googledrive;if(config){remoteStorage.googledrive=new RS.GoogleDrive(remoteStorage,config.client_id);if(remoteStorage.backend==="googledrive"){remoteStorage._origRemote=remoteStorage.remote;remoteStorage.remote=remoteStorage.googledrive}}};RS.GoogleDrive._rs_supported=function(rs){return true};RS.GoogleDrive._rs_cleanup=function(remoteStorage){remoteStorage.setBackend(undefined);if(remoteStorage._origRemote){remoteStorage.remote=remoteStorage._origRemote;delete remoteStorage._origRemote}}})(this);(function(global){var RS=RemoteStorage;var hasLocalStorage;var AUTH_URL="https://www.dropbox.com/1/oauth2/authorize";var SETTINGS_KEY="remotestorage:dropbox";var cleanPath=RS.WireClient.cleanPath;function LowerCaseCache(defaultValue){this.defaultValue=defaultValue;this._storage={};this.set=this.justSet;this.delete=this.justDelete}LowerCaseCache.prototype={get:function(key){key=key.toLowerCase();var stored=this._storage[key];if(typeof stored==="undefined"){stored=this.defaultValue;this._storage[key]=stored}return stored},propagateSet:function(key,value){key=key.toLowerCase();if(this._storage[key]===value){return value}this._propagate(key,value);return this._storage[key]=value},propagateDelete:function(key){key=key.toLowerCase();this._propagate(key,this._storage[key]);return delete this._storage[key]},_activatePropagation:function(){this.set=this.propagateSet;this.delete=this.propagateDelete;return true},justSet:function(key,value){key=key.toLowerCase();return this._storage[key]=value},justDelete:function(key,value){key=key.toLowerCase();return delete this._storage[key]},_propagate:function(key,rev){var folders=key.split("/").slice(0,-1);var len=folders.length;var path="";for(var i=0;i<len;i++){path+=folders[i]+"/";if(!rev){rev=this._storage[path]+1}this._storage[path]=rev}}};var onErrorCb;RS.Dropbox=function(rs){this.rs=rs;this.connected=false;this.rs=rs;var self=this;onErrorCb=function(error){if(error instanceof RemoteStorage.Unauthorized){self.configure(null,null,null,null)}};RS.eventHandling(this,"change","connected");rs.on("error",onErrorCb);this.clientId=rs.apiKeys.dropbox.api_key;this._revCache=new LowerCaseCache("rev");this._itemRefs={};if(hasLocalStorage){var settings;try{settings=JSON.parse(localStorage[SETTINGS_KEY])}catch(e){}if(settings){this.configure(settings.userAddress,undefined,undefined,settings.token)}try{this._itemRefs=JSON.parse(localStorage[SETTINGS_KEY+":shares"])}catch(e){}}if(this.connected){setTimeout(this._emit.bind(this),0,"connected")}};RS.Dropbox.prototype={connect:function(){this.rs.setBackend("dropbox");if(this.token){hookIt(this.rs)}else{RS.Authorize(AUTH_URL,"",String(RS.Authorize.getLocation()),this.clientId)}},configure:function(userAddress,href,storageApi,token){RemoteStorage.log("dropbox configure",arguments);if(typeof token!=="undefined"){this.token=token}if(typeof userAddress!=="undefined"){this.userAddress=userAddress}if(this.token){this.connected=true;if(!this.userAddress){this.info().then(function(info){this.userAddress=info.display_name}.bind(this))}this._emit("connected")}else{this.connected=false}if(hasLocalStorage){localStorage[SETTINGS_KEY]=JSON.stringify({token:this.token,userAddress:this.userAddress})}},_getFolder:function(path,options){var url="https://api.dropbox.com/1/metadata/auto"+path;var promise=promising();var revCache=this._revCache;this._request("GET",url,{},function(err,resp){if(err){promise.reject(err)}else{var status=resp.status;if(status===304){promise.fulfill(status);return}var listing,body,mime,rev;try{body=JSON.parse(resp.responseText)}catch(e){promise.reject(e);return}rev=this._revCache.get(path);mime="application/json; charset=UTF-8";if(body.contents){listing=body.contents.reduce(function(m,item){var itemName=item.path.split("/").slice(-1)[0]+(item.is_dir?"/":"");if(item.is_dir){m[itemName]=revCache.get(path+itemName)}else{m[itemName]=item.rev}return m},{})}promise.fulfill(status,listing,mime,rev)}});return promise},get:function(path,options){RemoteStorage.log("dropbox.get",arguments);if(!this.connected){throw new Error("not connected (path: "+path+")")}path=cleanPath(path);var url="https://api-content.dropbox.com/1/files/auto"+path;var promise=this._sharePromise(path);var savedRev=this._revCache.get(path);if(savedRev===null){RemoteStorage.log(path," deleted 404");promise.fulfill(404);return promise}if(options&&options.ifNoneMatch&&savedRev&&savedRev===options.ifNoneMatch){RemoteStorage.log("nothing changed for",path,savedRev,options.ifNoneMatch);promise.fulfill(304);return promise}if(path.substr(-1)==="/"){return this._getFolder(path,options)}this._request("GET",url,{},function(err,resp){if(err){promise.reject(err)}else{var status=resp.status;var meta,body,mime,rev;if(status===404){promise.fulfill(404)}else if(status===200){body=resp.responseText;try{meta=JSON.parse(resp.getResponseHeader("x-dropbox-metadata"))}catch(e){promise.reject(e);return}mime=meta.mime_type;rev=meta.rev;this._revCache.set(path,rev);if(!resp.getResponseHeader("Content-Type")||resp.getResponseHeader("Content-Type").match(/charset=binary/)){RS.WireClient.readBinaryData(resp.response,mime,function(result){promise.fulfill(status,result,mime,rev)})}else{if(mime&&mime.search("application/json")>=0||true){try{body=JSON.parse(body);mime="application/json; charset=UTF-8"}catch(e){RS.log("Failed parsing Json, assume it is something else then",mime,path)}}promise.fulfill(status,body,mime,rev)}}else{promise.fulfill(status)}}});return promise},put:function(path,body,contentType,options){RemoteStorage.log("dropbox.put",arguments);if(!this.connected){throw new Error("not connected (path: "+path+")")}path=cleanPath(path);var promise=this._sharePromise(path);var revCache=this._revCache;var savedRev=revCache.get(path);if(options&&options.ifMatch&&savedRev&&savedRev!==options.ifMatch){promise.fulfill(412);return promise}if(!contentType.match(/charset=/)){contentType+="; charset="+(body instanceof ArrayBuffer||RS.WireClient.isArrayBufferView(body)?"binary":"utf-8")}var url="https://api-content.dropbox.com/1/files_put/auto"+path+"?";if(options&&options.ifMatch){url+="parent_rev="+encodeURIComponent(options.ifMatch)}if(body.length>150*1024*1024){RemoteStorage.log("files larger than 150MB not supported yet")}else{this._request("PUT",url,{body:body,headers:{"Content-Type":contentType}},function(err,resp){if(err){promise.reject(err)}else{var response=JSON.parse(resp.responseText);if(response.path!==path){promise.fulfill(412);this.rs.log("Dropbox created conflicting File ",response.path)}else{revCache.set(path,response.rev);promise.fulfill(resp.status)}}})}return promise},"delete":function(path,options){RemoteStorage.log("dropbox.delete ",arguments);if(!this.connected){throw new Error("not connected (path: "+path+")")}path=cleanPath(path);var promise=promising();var revCache=this._revCache;var savedRev=revCache.get(path);if(options.ifMatch&&savedRev&&options.ifMatch!==savedRev){promise.fulfill(412);return promise}var url="https://api.dropbox.com/1/fileops/delete?root=auto&path="+encodeURIComponent(path);this._request("POST",url,{},function(err,resp){if(err){promise.reject(error)}else{promise.fulfill(resp.status);revCache.delete(path)}});return promise.then(function(){var args=Array.prototype.slice.call(arguments);delete this._itemRefs[path];var p=promising();return p.fulfill.apply(p,args)}.bind(this))},_sharePromise:function(path){var promise=promising();var self=this;if(path.match(/^\/public\/.*[^\/]$/)&&typeof this._itemRefs[path]==="undefined"){RemoteStorage.log("shareing this one ",path);promise.then(function(){var args=Array.prototype.slice.call(arguments);var p=promising();RemoteStorage.log("calling share now");self.share(path).then(function(){RemoteStorage.log("shareing fullfilled promise",arguments);p.fulfill.apply(p,args)},function(err){RemoteStorage.log("shareing failed",err);p.fulfill.apply(p,args)});return p})}return promise},share:function(path){var url="https://api.dropbox.com/1/media/auto"+path;var promise=promising();var itemRefs=this._itemRefs;this._request("POST",url,{},function(err,resp){if(err){RemoteStorage.log(err);err.message='Shareing Dropbox Thingie("'+path+'") failed'+err.message;promise.reject(err)}else{try{var response=JSON.parse(resp.responseText);var url=response.url;itemRefs[path]=url;RemoteStorage.log("SHAREING URL :::: ",url," for ",path);if(hasLocalStorage){localStorage[SETTINGS_KEY+":shares"]=JSON.stringify(this._itemRefs)}promise.fulfill(url)}catch(err){err.message+="share error";promise.reject(err)}}});return promise},info:function(){var url="https://api.dropbox.com/1/account/info";var promise=promising();this._request("GET",url,{},function(err,resp){if(err){promise.reject(err)}else{try{var info=JSON.parse(resp.responseText);promise.fulfill(info)}catch(e){promise.reject(err)}}});return promise},_request:function(method,url,options,callback){callback=callback.bind(this);if(!options.headers){options.headers={}}options.headers["Authorization"]="Bearer "+this.token;RS.WireClient.request.call(this,method,url,options,function(err,xhr){if(xhr&&xhr.status===503){global.setTimeout(this._request(method,url,options,callback),3210)}else{callback(err,xhr)}})},fetchDelta:function(){var args=Array.prototype.slice.call(arguments);var promise=promising();var self=this;this._request("POST","https://api.dropbox.com/1/delta",{body:this._deltaCursor?"cursor="+encodeURIComponent(this._deltaCursor):"",headers:{"Content-Type":"application/x-www-form-urlencoded"}},function(error,response){if(error){this.rs.log("fetchDeltas",error);this.rs._emit("error",new RemoteStorage.SyncError("fetchDeltas failed"+error));promise.reject(error)}else{if(response.status!==200){if(response.status===400){this.rs._emit("error",new RemoteStorage.Unauthorized);promise.fulfill.apply(promise,args)
  }else{RemoteStorage.log("!!!!dropbox.fetchDelta returned "+response.status+response.responseText);promise.reject("dropbox.fetchDelta returned "+response.status+response.responseText)}return promise}var delta;try{delta=JSON.parse(response.responseText)}catch(error){RS.log("fetchDeltas can not parse response",error);return promise.reject("can not parse response of fetchDelta : "+error.message)}if(!delta.entries){RemoteStorage.log("!!!!!DropBox.fetchDeltas() NO ENTRIES FOUND!!",delta);return promise.reject("dropbox.fetchDeltas failed, no entries found")}if(delta.reset){this._revCache=new LowerCaseCache("rev");promise.then(function(){var args=Array.prototype.slice.call(arguments);self._revCache._activatePropagation();var p=promising();return p.fulfill.apply(p,args)})}if(delta.cursor){this._deltaCursor=delta.cursor}RemoteStorage.log("Delta : ",delta.entries);delta.entries.forEach(function(entry){var path=entry[0];var rev;if(!entry[1]){rev=null}else{if(entry[1].is_dir){return}rev=entry[1].rev}self._revCache.set(path,rev)});promise.fulfill.apply(promise,args)}});return promise}};function hookSync(rs){if(rs._dropboxOrigSync){return}rs._dropboxOrigSync=rs.sync.bind(rs);rs.sync=function(){return this.dropbox.fetchDelta.apply(this.dropbox,arguments).then(rs._dropboxOrigSync,function(err){rs._emit("error",new rs.SyncError(err))})}}function unHookSync(rs){if(!rs._dropboxOrigSync){return}rs.sync=rs._dropboxOrigSync;delete rs._dropboxOrigSync}function hookGetItemURL(rs){if(rs._origBaseClientGetItemURL){return}rs._origBaseClientGetItemURL=RS.BaseClient.prototype.getItemURL;RS.BaseClient.prototype.getItemURL=function(path){var ret=rs.dropbox._itemRefs[path];return ret?ret:""}}function unHookGetItemURL(rs){if(!rs._origBaseClieNtGetItemURL){return}RS.BaseClient.prototype.getItemURL=rs._origBaseClietGetItemURL;delete rs._origBaseClietGetItemURL}function hookRemote(rs){if(rs._origRemote){return}rs._origRemote=rs.remote;rs.remote=rs.dropbox}function unHookRemote(rs){if(rs._origRemote){rs.remote=rs._origRemote;delete rs._origRemote}}function hookIt(rs){hookRemote(rs);if(rs.sync){hookSync(rs)}hookGetItemURL(rs)}function unHookIt(rs){unHookRemote(rs);unHookSync(rs);unHookGetItemURL(rs)}RS.Dropbox._rs_init=function(rs){hasLocalStorage=rs.localStorageAvailable();if(rs.apiKeys.dropbox){rs.dropbox=new RS.Dropbox(rs)}if(rs.backend==="dropbox"){hookIt(rs)}};RS.Dropbox._rs_supported=function(){return true};RS.Dropbox._rs_cleanup=function(rs){unHookIt(rs);if(hasLocalStorage){delete localStorage[SETTINGS_KEY]}rs.removeEventListener("error",onErrorCb);rs.setBackend(undefined)}})(this);remoteStorage=new RemoteStorage;