diff --git a/CHANGELOG.md b/CHANGELOG.md index b9e6b4c5..45f8b27c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # offline-editor-js - Changelog +## Version 3.4.0 - September 13, 2016 + +Possible breaking changes. + +**Enhancements** +* Added base64 re-encoding to the tile database that results in a 2.7x (16/6) reduction in storage size. + +**Known Issues** +* Firefox v48.x is showing tiles as hidden when they should be visible. This issue existed at v3.3.2. + + ## Version 3.3.2 - August 24, 2016 No breaking changes. diff --git a/Gruntfile.js b/Gruntfile.js index 505a392e..72e505ee 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -33,6 +33,7 @@ module.exports = function(grunt) { 'lib/tiles/OfflineTilesNS.js', 'lib/tiles/TilesCore.js', 'lib/tiles/TilesStore.js', + 'lib/tiles/base64string.js', 'lib/tiles/tilingScheme.js', 'lib/tpk/autoCenterMap.js', 'lib/tpk/OfflineTpkNS.js', @@ -74,6 +75,7 @@ module.exports = function(grunt) { 'lib/tiles/OfflineTilesBasic.js', 'lib/tiles/OfflineTilesNS.js', 'lib/tiles/base64utils.js', + 'lib/tiles/base64string.js', 'lib/tiles/FileSaver.js', 'lib/tiles/TilesCore.js', 'lib/tiles/TilesStore.js', @@ -87,6 +89,7 @@ module.exports = function(grunt) { 'lib/tiles/OfflineTilesAdvanced.js', 'lib/tiles/OfflineTilesNS.js', 'lib/tiles/base64utils.js', + 'lib/tiles/base64string.js', 'lib/tiles/FileSaver.js', 'lib/tiles/TilesCore.js', 'lib/tiles/TilesStore.js', diff --git a/dist/offline-edit-advanced-src.js b/dist/offline-edit-advanced-src.js index eb953c22..cc5dd9e0 100644 --- a/dist/offline-edit-advanced-src.js +++ b/dist/offline-edit-advanced-src.js @@ -1,4 +1,4 @@ -/*! esri-offline-maps - v3.3.0 - 2016-07-12 +/*! esri-offline-maps - v3.4.0 - 2016-09-13 * Copyright (c) 2016 Environmental Systems Research Institute, Inc. * Apache License*/ // Configure offline/online detection diff --git a/dist/offline-edit-basic-src.js b/dist/offline-edit-basic-src.js index 3205403e..c38cd2c6 100644 --- a/dist/offline-edit-basic-src.js +++ b/dist/offline-edit-basic-src.js @@ -1,4 +1,4 @@ -/*! esri-offline-maps - v3.3.0 - 2016-07-12 +/*! esri-offline-maps - v3.4.0 - 2016-09-13 * Copyright (c) 2016 Environmental Systems Research Institute, Inc. * Apache License*/ // Configure offline/online detection diff --git a/dist/offline-tiles-advanced-min.js b/dist/offline-tiles-advanced-min.js index a94b1e23..dee7390c 100644 --- a/dist/offline-tiles-advanced-min.js +++ b/dist/offline-tiles-advanced-min.js @@ -30,7 +30,69 @@ return d<<16|65535&c},O.esri.Tiles.Base64Utils.stringToWord=function(a){for(var return d},O.esri.Tiles.Base64Utils.wordToString=function(a){for(var b=8,c=(1<e;e+=b)d.push(String.fromCharCode(a[e>>5]>>>e%32&c)) return d.join("")},O.esri.Tiles.Base64Utils.wordToHex=function(a){for(var b="0123456789abcdef",c=[],d=0,e=4*a.length;e>d;d++)c.push(b.charAt(a[d>>2]>>d%4*8+4&15)+b.charAt(a[d>>2]>>d%4*8&15)) return c.join("")},O.esri.Tiles.Base64Utils.wordToBase64=function(a){for(var b="=",c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d=[],e=0,f=4*a.length;f>e;e+=3)for(var g=(a[e>>2]>>8*(e%4)&255)<<16|(a[e+1>>2]>>8*((e+1)%4)&255)<<8|a[e+2>>2]>>8*((e+2)%4)&255,h=0;4>h;h++)8*e+6*h>32*a.length?d.push(b):d.push(c.charAt(g>>6*(3-h)&63)) -return d.join("")},O.esri.Tiles.saveAs=function(a){"use strict" +return d.join("")},O.esri.Tiles.Base64String={compressToUTF16:function(a){var b,c,d,e=[],f=0 +for(a=this.compress(a),b=0;b>1)+32)),d=(1&c)<<14 +break +case 1:e.push(String.fromCharCode(d+(c>>2)+32)),d=(3&c)<<13 +break +case 2:e.push(String.fromCharCode(d+(c>>3)+32)),d=(7&c)<<12 +break +case 3:e.push(String.fromCharCode(d+(c>>4)+32)),d=(15&c)<<11 +break +case 4:e.push(String.fromCharCode(d+(c>>5)+32)),d=(31&c)<<10 +break +case 5:e.push(String.fromCharCode(d+(c>>6)+32)),d=(63&c)<<9 +break +case 6:e.push(String.fromCharCode(d+(c>>7)+32)),d=(127&c)<<8 +break +case 7:e.push(String.fromCharCode(d+(c>>8)+32)),d=(255&c)<<7 +break +case 8:e.push(String.fromCharCode(d+(c>>9)+32)),d=(511&c)<<6 +break +case 9:e.push(String.fromCharCode(d+(c>>10)+32)),d=(1023&c)<<5 +break +case 10:e.push(String.fromCharCode(d+(c>>11)+32)),d=(2047&c)<<4 +break +case 11:e.push(String.fromCharCode(d+(c>>12)+32)),d=(4095&c)<<3 +break +case 12:e.push(String.fromCharCode(d+(c>>13)+32)),d=(8191&c)<<2 +break +case 13:e.push(String.fromCharCode(d+(c>>14)+32)),d=(16383&c)<<1 +break +case 14:e.push(String.fromCharCode(d+(c>>15)+32,(32767&c)+32)),f=0}return e.push(String.fromCharCode(d+32)),e.join("")},decompressFromUTF16:function(a){for(var b,c,d=[],e=0,f=0;f>14)),b=(16383&c)<<2 +break +case 2:d.push(String.fromCharCode(b|c>>13)),b=(8191&c)<<3 +break +case 3:d.push(String.fromCharCode(b|c>>12)),b=(4095&c)<<4 +break +case 4:d.push(String.fromCharCode(b|c>>11)),b=(2047&c)<<5 +break +case 5:d.push(String.fromCharCode(b|c>>10)),b=(1023&c)<<6 +break +case 6:d.push(String.fromCharCode(b|c>>9)),b=(511&c)<<7 +break +case 7:d.push(String.fromCharCode(b|c>>8)),b=(255&c)<<8 +break +case 8:d.push(String.fromCharCode(b|c>>7)),b=(127&c)<<9 +break +case 9:d.push(String.fromCharCode(b|c>>6)),b=(63&c)<<10 +break +case 10:d.push(String.fromCharCode(b|c>>5)),b=(31&c)<<11 +break +case 11:d.push(String.fromCharCode(b|c>>4)),b=(15&c)<<12 +break +case 12:d.push(String.fromCharCode(b|c>>3)),b=(7&c)<<13 +break +case 13:d.push(String.fromCharCode(b|c>>2)),b=(3&c)<<14 +break +case 14:d.push(String.fromCharCode(b|c>>1)),b=(1&c)<<15 +break +case 15:d.push(String.fromCharCode(b|c)),e=0}f++}return this.decompress(d.join(""))},_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",decompress:function(a){for(var b,c,d,e,f,g,h,i=[],j=1,k=a.charCodeAt(0)>>8;j<2*a.length&&(j<2*a.length-1||0===k);)j%2===0?(b=a.charCodeAt(j/2)>>8,c=255&a.charCodeAt(j/2),d=j/2+1>8:NaN):(b=255&a.charCodeAt((j-1)/2),(j+1)/2>8,d=255&a.charCodeAt((j+1)/2)):c=d=NaN),j+=3,e=b>>2,f=(3&b)<<4|c>>4,g=(15&c)<<2|d>>6,h=63&d,isNaN(c)||j==2*a.length+1&&k?g=h=64:(isNaN(d)||j==2*a.length&&k)&&(h=64),i.push(this._keyStr.charAt(e)),i.push(this._keyStr.charAt(f)),i.push(this._keyStr.charAt(g)),i.push(this._keyStr.charAt(h)) +return i.join("")},compress:function(a){var b,c,d,e,f,g,h,i,j=[],k=1,l=0,m=!1 +for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");l>4,d=(15&g)<<4|h>>2,e=(3&h)<<6|i,k%2===0?(b=c<<8,m=!0,64!=h&&(j.push(String.fromCharCode(b|d)),m=!1),64!=i&&(b=e<<8,m=!0)):(j.push(String.fromCharCode(b|c)),m=!1,64!=h&&(b=d<<8,m=!0),64!=i&&(j.push(String.fromCharCode(b|e)),m=!1)),k+=3 +return m?(j.push(String.fromCharCode(b)),j=j.join(""),j=String.fromCharCode(256|j.charCodeAt(0))+j.substring(1)):j=j.join(""),j}},O.esri.Tiles.saveAs=function(a){"use strict" var b=a.document,c=function(){return a.URL||a.webkitURL||a},d=a.URL||a.webkitURL||a,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),f=!a.externalHost&&"download"in e,g=a.webkitRequestFileSystem,h=a.requestFileSystem||g||a.mozRequestFileSystem,i=function(b){(a.setImmediate||a.setTimeout)(function(){throw b},0)},j="application/octet-stream",k=0,l=[],m=function(){for(var a=l.length;a--;){var b=l[a] "string"==typeof b?d.revokeObjectURL(b):b.remove()}l.length=0},n=function(a,b,c){b=[].concat(b) for(var d=b.length;d--;){var e=a["on"+b[d]] @@ -69,10 +131,12 @@ return c.level=b.level,c.resolution=b.resolution,c.scale=b.scale,b.hasOwnPropert var k=new f(parseFloat(d.initialExtent.xmin),parseFloat(d.initialExtent.ymin),parseFloat(d.initialExtent.xmax),parseFloat(d.initialExtent.ymax),i),l=new f(parseFloat(d.fullExtent.xmin),parseFloat(d.fullExtent.ymin),parseFloat(d.fullExtent.xmax),parseFloat(d.fullExtent.ymax),i),m=new g(d.tileInfo),n=new h(m.origin.x,m.origin.y,i) m.origin=n,m.lods=j,b({initExtent:k,fullExtent:l,tileInfo:m,resultObj:d})})}},O.esri.Tiles.TilesStore=function(){this._db=null,this.dbName="offline_tile_store",this.objectStoreName="tilepath",this.isSupported=function(){return!(!window.indexedDB&&!window.openDatabase)},this.store=function(a,b){try{var c=this._db.transaction([this.objectStoreName],"readwrite") c.oncomplete=function(){b(!0)},c.onerror=function(a){b(!1,a.target.error.message)} -var d=c.objectStore(this.objectStoreName),e=d.put(a) +var d=c.objectStore(this.objectStoreName) +a.img=O.esri.Tiles.Base64String.compress(a.img) +var e=d.put(a) e.onsuccess=function(){}}catch(f){b(!1,f.stack)}},this.retrieve=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),d=c.get(a) d.onsuccess=function(a){var c=a.target.result -void 0===c?b(!1,"not found"):b(!0,c)},d.onerror=function(a){b(!1,a)}}},this.deleteAll=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() +void 0===c?b(!1,"not found"):(c.img=O.esri.Tiles.Base64String.decompress(c.img),b(!0,c))},d.onerror=function(a){b(!1,a)}}},this.deleteAll=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() b.onsuccess=function(){a(!0)},b.onerror=function(b){a(!1,b)}}else a(!1,null)},this["delete"]=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName)["delete"](a) c.onsuccess=function(){b(!0)},c.onerror=function(a){b(!1,a)}}else b(!1,null)},this.getAllTiles=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() b.onsuccess=function(b){var c=b.target.result diff --git a/dist/offline-tiles-advanced-src.js b/dist/offline-tiles-advanced-src.js index fcfa5609..f9bcd488 100644 --- a/dist/offline-tiles-advanced-src.js +++ b/dist/offline-tiles-advanced-src.js @@ -1,4 +1,4 @@ -/*! esri-offline-maps - v3.3.0 - 2016-07-12 +/*! esri-offline-maps - v3.4.0 - 2016-09-13 * Copyright (c) 2016 Environmental Systems Research Institute, Inc. * Apache License*/ define([ @@ -661,6 +661,299 @@ O.esri.Tiles.Base64Utils.wordToBase64=function(/* word[] */wa){ }; /*jslint bitwise: false */ +// Copyright (c) 2013 Pieroxy +// This work is free. You can redistribute it and/or modify it +// under the terms of the WTFPL, Version 2 +// For more information see LICENSE.txt or http://www.wtfpl.net/ +// +// This lib is part of the lz-string project. +// For more information, the home page: +// http://pieroxy.net/blog/pages/lz-string/index.html +// +// Base64 compression / decompression for already compressed content (gif, png, jpg, mp3, ...) +// version 1.4.1 + +/*jslint bitwise: true */ +O.esri.Tiles.Base64String = { + + compressToUTF16 : function (input) { + var output = [], + i,c, + current, + status = 0; + + input = this.compress(input); + + for (i=0 ; i> 1)+32)); + current = (c & 1) << 14; + break; + case 1: + output.push(String.fromCharCode((current + (c >> 2))+32)); + current = (c & 3) << 13; + break; + case 2: + output.push(String.fromCharCode((current + (c >> 3))+32)); + current = (c & 7) << 12; + break; + case 3: + output.push(String.fromCharCode((current + (c >> 4))+32)); + current = (c & 15) << 11; + break; + case 4: + output.push(String.fromCharCode((current + (c >> 5))+32)); + current = (c & 31) << 10; + break; + case 5: + output.push(String.fromCharCode((current + (c >> 6))+32)); + current = (c & 63) << 9; + break; + case 6: + output.push(String.fromCharCode((current + (c >> 7))+32)); + current = (c & 127) << 8; + break; + case 7: + output.push(String.fromCharCode((current + (c >> 8))+32)); + current = (c & 255) << 7; + break; + case 8: + output.push(String.fromCharCode((current + (c >> 9))+32)); + current = (c & 511) << 6; + break; + case 9: + output.push(String.fromCharCode((current + (c >> 10))+32)); + current = (c & 1023) << 5; + break; + case 10: + output.push(String.fromCharCode((current + (c >> 11))+32)); + current = (c & 2047) << 4; + break; + case 11: + output.push(String.fromCharCode((current + (c >> 12))+32)); + current = (c & 4095) << 3; + break; + case 12: + output.push(String.fromCharCode((current + (c >> 13))+32)); + current = (c & 8191) << 2; + break; + case 13: + output.push(String.fromCharCode((current + (c >> 14))+32)); + current = (c & 16383) << 1; + break; + case 14: + output.push(String.fromCharCode((current + (c >> 15))+32, (c & 32767)+32)); + status = 0; + break; + } + } + output.push(String.fromCharCode(current + 32)); + return output.join(''); + }, + + + decompressFromUTF16 : function (input) { + var output = [], + current,c, + status=0, + i = 0; + + while (i < input.length) { + c = input.charCodeAt(i) - 32; + + switch (status++) { + case 0: + current = c << 1; + break; + case 1: + output.push(String.fromCharCode(current | (c >> 14))); + current = (c&16383) << 2; + break; + case 2: + output.push(String.fromCharCode(current | (c >> 13))); + current = (c&8191) << 3; + break; + case 3: + output.push(String.fromCharCode(current | (c >> 12))); + current = (c&4095) << 4; + break; + case 4: + output.push(String.fromCharCode(current | (c >> 11))); + current = (c&2047) << 5; + break; + case 5: + output.push(String.fromCharCode(current | (c >> 10))); + current = (c&1023) << 6; + break; + case 6: + output.push(String.fromCharCode(current | (c >> 9))); + current = (c&511) << 7; + break; + case 7: + output.push(String.fromCharCode(current | (c >> 8))); + current = (c&255) << 8; + break; + case 8: + output.push(String.fromCharCode(current | (c >> 7))); + current = (c&127) << 9; + break; + case 9: + output.push(String.fromCharCode(current | (c >> 6))); + current = (c&63) << 10; + break; + case 10: + output.push(String.fromCharCode(current | (c >> 5))); + current = (c&31) << 11; + break; + case 11: + output.push(String.fromCharCode(current | (c >> 4))); + current = (c&15) << 12; + break; + case 12: + output.push(String.fromCharCode(current | (c >> 3))); + current = (c&7) << 13; + break; + case 13: + output.push(String.fromCharCode(current | (c >> 2))); + current = (c&3) << 14; + break; + case 14: + output.push(String.fromCharCode(current | (c >> 1))); + current = (c&1) << 15; + break; + case 15: + output.push(String.fromCharCode(current | c)); + status=0; + break; + } + + + i++; + } + + return this.decompress(output.join('')); + //return output; + + }, + + + // private property + _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", // jshint ignore:line + + decompress : function (input) { + var output = []; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 1; + var odd = input.charCodeAt(0) >> 8; + + while (i < input.length*2 && (i < input.length*2-1 || odd===0)) { + + if (i%2===0) { + chr1 = input.charCodeAt(i/2) >> 8; + chr2 = input.charCodeAt(i/2) & 255; + if (i/2+1 < input.length) { + chr3 = input.charCodeAt(i / 2 + 1) >> 8; + } + else { + chr3 = NaN; + } + } else { + chr1 = input.charCodeAt((i-1)/2) & 255; + if ((i+1)/2 < input.length) { + chr2 = input.charCodeAt((i+1)/2) >> 8; + chr3 = input.charCodeAt((i+1)/2) & 255; + } else { + chr2 = chr3 = NaN; + } + } + i+=3; + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2) || (i==input.length*2+1 && odd)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3) || (i==input.length*2 && odd)) { + enc4 = 64; + } + + output.push(this._keyStr.charAt(enc1)); + output.push(this._keyStr.charAt(enc2)); + output.push(this._keyStr.charAt(enc3)); + output.push(this._keyStr.charAt(enc4)); + } + + return output.join(''); + }, + + compress : function (input) { + var output = [], + ol = 1, + output_, + chr1, chr2, chr3, + enc1, enc2, enc3, enc4, + i = 0, flush=false; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); // jshint ignore:line + + while (i < input.length) { + + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + if (ol%2===0) { + output_ = chr1 << 8; + flush = true; + + if (enc3 != 64) { + output.push(String.fromCharCode(output_ | chr2)); + flush = false; + } + if (enc4 != 64) { + output_ = chr3 << 8; + flush = true; + } + } else { + output.push(String.fromCharCode(output_ | chr1)); + flush = false; + + if (enc3 != 64) { + output_ = chr2 << 8; + flush = true; + } + if (enc4 != 64) { + output.push(String.fromCharCode(output_ | chr3)); + flush = false; + } + } + ol+=3; + } + + if (flush) { + output.push(String.fromCharCode(output_)); + output = output.join(''); + output = String.fromCharCode(output.charCodeAt(0)|256) + output.substring(1); + } else { + output = output.join(''); + } + + return output; + + } +}; + +/*jslint bitwise: false */ + /* FileSaver.js * A saveAs() FileSaver implementation. * 2013-10-21 @@ -918,7 +1211,7 @@ O.esri.Tiles.TilesCore = function(){ */ this._getTiles = function(image,imageType,url,tileid,store,query,showBlankTiles){ store.retrieve(url, function(success, offlineTile) - { console.log("TILE RETURN " + success + ", " + offlineTile.url); + { console.log("TILE RETURN " + success + ", " + offlineTile.url + ", " + tileid); /* when the .getTileUrl() callback is triggered we replace the temporary URL originally returned by the data:image url */ // search for the img with src="void:"+level+"-"+row+"-"+col and replace with actual url image = query("img[src="+tileid+"]")[0]; @@ -1348,6 +1641,7 @@ O.esri.Tiles.TilesStore = function(){ }; var objectStore = transaction.objectStore(this.objectStoreName); + urlDataPair.img = O.esri.Tiles.Base64String.compress(urlDataPair.img); var request = objectStore.put(urlDataPair); request.onsuccess = function() { @@ -1381,6 +1675,7 @@ O.esri.Tiles.TilesStore = function(){ } else { + result.img = O.esri.Tiles.Base64String.decompress(result.img); callback(true,result); } }; diff --git a/dist/offline-tiles-basic-min.js b/dist/offline-tiles-basic-min.js index f83c8aa7..8201b180 100644 --- a/dist/offline-tiles-basic-min.js +++ b/dist/offline-tiles-basic-min.js @@ -19,7 +19,69 @@ return d<<16|65535&c},O.esri.Tiles.Base64Utils.stringToWord=function(a){for(var return d},O.esri.Tiles.Base64Utils.wordToString=function(a){for(var b=8,c=(1<e;e+=b)d.push(String.fromCharCode(a[e>>5]>>>e%32&c)) return d.join("")},O.esri.Tiles.Base64Utils.wordToHex=function(a){for(var b="0123456789abcdef",c=[],d=0,e=4*a.length;e>d;d++)c.push(b.charAt(a[d>>2]>>d%4*8+4&15)+b.charAt(a[d>>2]>>d%4*8&15)) return c.join("")},O.esri.Tiles.Base64Utils.wordToBase64=function(a){for(var b="=",c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d=[],e=0,f=4*a.length;f>e;e+=3)for(var g=(a[e>>2]>>8*(e%4)&255)<<16|(a[e+1>>2]>>8*((e+1)%4)&255)<<8|a[e+2>>2]>>8*((e+2)%4)&255,h=0;4>h;h++)8*e+6*h>32*a.length?d.push(b):d.push(c.charAt(g>>6*(3-h)&63)) -return d.join("")},O.esri.Tiles.saveAs=function(a){"use strict" +return d.join("")},O.esri.Tiles.Base64String={compressToUTF16:function(a){var b,c,d,e=[],f=0 +for(a=this.compress(a),b=0;b>1)+32)),d=(1&c)<<14 +break +case 1:e.push(String.fromCharCode(d+(c>>2)+32)),d=(3&c)<<13 +break +case 2:e.push(String.fromCharCode(d+(c>>3)+32)),d=(7&c)<<12 +break +case 3:e.push(String.fromCharCode(d+(c>>4)+32)),d=(15&c)<<11 +break +case 4:e.push(String.fromCharCode(d+(c>>5)+32)),d=(31&c)<<10 +break +case 5:e.push(String.fromCharCode(d+(c>>6)+32)),d=(63&c)<<9 +break +case 6:e.push(String.fromCharCode(d+(c>>7)+32)),d=(127&c)<<8 +break +case 7:e.push(String.fromCharCode(d+(c>>8)+32)),d=(255&c)<<7 +break +case 8:e.push(String.fromCharCode(d+(c>>9)+32)),d=(511&c)<<6 +break +case 9:e.push(String.fromCharCode(d+(c>>10)+32)),d=(1023&c)<<5 +break +case 10:e.push(String.fromCharCode(d+(c>>11)+32)),d=(2047&c)<<4 +break +case 11:e.push(String.fromCharCode(d+(c>>12)+32)),d=(4095&c)<<3 +break +case 12:e.push(String.fromCharCode(d+(c>>13)+32)),d=(8191&c)<<2 +break +case 13:e.push(String.fromCharCode(d+(c>>14)+32)),d=(16383&c)<<1 +break +case 14:e.push(String.fromCharCode(d+(c>>15)+32,(32767&c)+32)),f=0}return e.push(String.fromCharCode(d+32)),e.join("")},decompressFromUTF16:function(a){for(var b,c,d=[],e=0,f=0;f>14)),b=(16383&c)<<2 +break +case 2:d.push(String.fromCharCode(b|c>>13)),b=(8191&c)<<3 +break +case 3:d.push(String.fromCharCode(b|c>>12)),b=(4095&c)<<4 +break +case 4:d.push(String.fromCharCode(b|c>>11)),b=(2047&c)<<5 +break +case 5:d.push(String.fromCharCode(b|c>>10)),b=(1023&c)<<6 +break +case 6:d.push(String.fromCharCode(b|c>>9)),b=(511&c)<<7 +break +case 7:d.push(String.fromCharCode(b|c>>8)),b=(255&c)<<8 +break +case 8:d.push(String.fromCharCode(b|c>>7)),b=(127&c)<<9 +break +case 9:d.push(String.fromCharCode(b|c>>6)),b=(63&c)<<10 +break +case 10:d.push(String.fromCharCode(b|c>>5)),b=(31&c)<<11 +break +case 11:d.push(String.fromCharCode(b|c>>4)),b=(15&c)<<12 +break +case 12:d.push(String.fromCharCode(b|c>>3)),b=(7&c)<<13 +break +case 13:d.push(String.fromCharCode(b|c>>2)),b=(3&c)<<14 +break +case 14:d.push(String.fromCharCode(b|c>>1)),b=(1&c)<<15 +break +case 15:d.push(String.fromCharCode(b|c)),e=0}f++}return this.decompress(d.join(""))},_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",decompress:function(a){for(var b,c,d,e,f,g,h,i=[],j=1,k=a.charCodeAt(0)>>8;j<2*a.length&&(j<2*a.length-1||0===k);)j%2===0?(b=a.charCodeAt(j/2)>>8,c=255&a.charCodeAt(j/2),d=j/2+1>8:NaN):(b=255&a.charCodeAt((j-1)/2),(j+1)/2>8,d=255&a.charCodeAt((j+1)/2)):c=d=NaN),j+=3,e=b>>2,f=(3&b)<<4|c>>4,g=(15&c)<<2|d>>6,h=63&d,isNaN(c)||j==2*a.length+1&&k?g=h=64:(isNaN(d)||j==2*a.length&&k)&&(h=64),i.push(this._keyStr.charAt(e)),i.push(this._keyStr.charAt(f)),i.push(this._keyStr.charAt(g)),i.push(this._keyStr.charAt(h)) +return i.join("")},compress:function(a){var b,c,d,e,f,g,h,i,j=[],k=1,l=0,m=!1 +for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");l>4,d=(15&g)<<4|h>>2,e=(3&h)<<6|i,k%2===0?(b=c<<8,m=!0,64!=h&&(j.push(String.fromCharCode(b|d)),m=!1),64!=i&&(b=e<<8,m=!0)):(j.push(String.fromCharCode(b|c)),m=!1,64!=h&&(b=d<<8,m=!0),64!=i&&(j.push(String.fromCharCode(b|e)),m=!1)),k+=3 +return m?(j.push(String.fromCharCode(b)),j=j.join(""),j=String.fromCharCode(256|j.charCodeAt(0))+j.substring(1)):j=j.join(""),j}},O.esri.Tiles.saveAs=function(a){"use strict" var b=a.document,c=function(){return a.URL||a.webkitURL||a},d=a.URL||a.webkitURL||a,e=b.createElementNS("http://www.w3.org/1999/xhtml","a"),f=!a.externalHost&&"download"in e,g=a.webkitRequestFileSystem,h=a.requestFileSystem||g||a.mozRequestFileSystem,i=function(b){(a.setImmediate||a.setTimeout)(function(){throw b},0)},j="application/octet-stream",k=0,l=[],m=function(){for(var a=l.length;a--;){var b=l[a] "string"==typeof b?d.revokeObjectURL(b):b.remove()}l.length=0},n=function(a,b,c){b=[].concat(b) for(var d=b.length;d--;){var e=a["on"+b[d]] @@ -58,10 +120,12 @@ return c.level=b.level,c.resolution=b.resolution,c.scale=b.scale,b.hasOwnPropert var k=new f(parseFloat(d.initialExtent.xmin),parseFloat(d.initialExtent.ymin),parseFloat(d.initialExtent.xmax),parseFloat(d.initialExtent.ymax),i),l=new f(parseFloat(d.fullExtent.xmin),parseFloat(d.fullExtent.ymin),parseFloat(d.fullExtent.xmax),parseFloat(d.fullExtent.ymax),i),m=new g(d.tileInfo),n=new h(m.origin.x,m.origin.y,i) m.origin=n,m.lods=j,b({initExtent:k,fullExtent:l,tileInfo:m,resultObj:d})})}},O.esri.Tiles.TilesStore=function(){this._db=null,this.dbName="offline_tile_store",this.objectStoreName="tilepath",this.isSupported=function(){return!(!window.indexedDB&&!window.openDatabase)},this.store=function(a,b){try{var c=this._db.transaction([this.objectStoreName],"readwrite") c.oncomplete=function(){b(!0)},c.onerror=function(a){b(!1,a.target.error.message)} -var d=c.objectStore(this.objectStoreName),e=d.put(a) +var d=c.objectStore(this.objectStoreName) +a.img=O.esri.Tiles.Base64String.compress(a.img) +var e=d.put(a) e.onsuccess=function(){}}catch(f){b(!1,f.stack)}},this.retrieve=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),d=c.get(a) d.onsuccess=function(a){var c=a.target.result -void 0===c?b(!1,"not found"):b(!0,c)},d.onerror=function(a){b(!1,a)}}},this.deleteAll=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() +void 0===c?b(!1,"not found"):(c.img=O.esri.Tiles.Base64String.decompress(c.img),b(!0,c))},d.onerror=function(a){b(!1,a)}}},this.deleteAll=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() b.onsuccess=function(){a(!0)},b.onerror=function(b){a(!1,b)}}else a(!1,null)},this["delete"]=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName)["delete"](a) c.onsuccess=function(){b(!0)},c.onerror=function(a){b(!1,a)}}else b(!1,null)},this.getAllTiles=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() b.onsuccess=function(b){var c=b.target.result diff --git a/dist/offline-tiles-basic-src.js b/dist/offline-tiles-basic-src.js index 769fba4e..5ba52b58 100644 --- a/dist/offline-tiles-basic-src.js +++ b/dist/offline-tiles-basic-src.js @@ -1,4 +1,4 @@ -/*! esri-offline-maps - v3.3.0 - 2016-07-12 +/*! esri-offline-maps - v3.4.0 - 2016-09-13 * Copyright (c) 2016 Environmental Systems Research Institute, Inc. * Apache License*/ define([ @@ -492,6 +492,299 @@ O.esri.Tiles.Base64Utils.wordToBase64=function(/* word[] */wa){ }; /*jslint bitwise: false */ +// Copyright (c) 2013 Pieroxy +// This work is free. You can redistribute it and/or modify it +// under the terms of the WTFPL, Version 2 +// For more information see LICENSE.txt or http://www.wtfpl.net/ +// +// This lib is part of the lz-string project. +// For more information, the home page: +// http://pieroxy.net/blog/pages/lz-string/index.html +// +// Base64 compression / decompression for already compressed content (gif, png, jpg, mp3, ...) +// version 1.4.1 + +/*jslint bitwise: true */ +O.esri.Tiles.Base64String = { + + compressToUTF16 : function (input) { + var output = [], + i,c, + current, + status = 0; + + input = this.compress(input); + + for (i=0 ; i> 1)+32)); + current = (c & 1) << 14; + break; + case 1: + output.push(String.fromCharCode((current + (c >> 2))+32)); + current = (c & 3) << 13; + break; + case 2: + output.push(String.fromCharCode((current + (c >> 3))+32)); + current = (c & 7) << 12; + break; + case 3: + output.push(String.fromCharCode((current + (c >> 4))+32)); + current = (c & 15) << 11; + break; + case 4: + output.push(String.fromCharCode((current + (c >> 5))+32)); + current = (c & 31) << 10; + break; + case 5: + output.push(String.fromCharCode((current + (c >> 6))+32)); + current = (c & 63) << 9; + break; + case 6: + output.push(String.fromCharCode((current + (c >> 7))+32)); + current = (c & 127) << 8; + break; + case 7: + output.push(String.fromCharCode((current + (c >> 8))+32)); + current = (c & 255) << 7; + break; + case 8: + output.push(String.fromCharCode((current + (c >> 9))+32)); + current = (c & 511) << 6; + break; + case 9: + output.push(String.fromCharCode((current + (c >> 10))+32)); + current = (c & 1023) << 5; + break; + case 10: + output.push(String.fromCharCode((current + (c >> 11))+32)); + current = (c & 2047) << 4; + break; + case 11: + output.push(String.fromCharCode((current + (c >> 12))+32)); + current = (c & 4095) << 3; + break; + case 12: + output.push(String.fromCharCode((current + (c >> 13))+32)); + current = (c & 8191) << 2; + break; + case 13: + output.push(String.fromCharCode((current + (c >> 14))+32)); + current = (c & 16383) << 1; + break; + case 14: + output.push(String.fromCharCode((current + (c >> 15))+32, (c & 32767)+32)); + status = 0; + break; + } + } + output.push(String.fromCharCode(current + 32)); + return output.join(''); + }, + + + decompressFromUTF16 : function (input) { + var output = [], + current,c, + status=0, + i = 0; + + while (i < input.length) { + c = input.charCodeAt(i) - 32; + + switch (status++) { + case 0: + current = c << 1; + break; + case 1: + output.push(String.fromCharCode(current | (c >> 14))); + current = (c&16383) << 2; + break; + case 2: + output.push(String.fromCharCode(current | (c >> 13))); + current = (c&8191) << 3; + break; + case 3: + output.push(String.fromCharCode(current | (c >> 12))); + current = (c&4095) << 4; + break; + case 4: + output.push(String.fromCharCode(current | (c >> 11))); + current = (c&2047) << 5; + break; + case 5: + output.push(String.fromCharCode(current | (c >> 10))); + current = (c&1023) << 6; + break; + case 6: + output.push(String.fromCharCode(current | (c >> 9))); + current = (c&511) << 7; + break; + case 7: + output.push(String.fromCharCode(current | (c >> 8))); + current = (c&255) << 8; + break; + case 8: + output.push(String.fromCharCode(current | (c >> 7))); + current = (c&127) << 9; + break; + case 9: + output.push(String.fromCharCode(current | (c >> 6))); + current = (c&63) << 10; + break; + case 10: + output.push(String.fromCharCode(current | (c >> 5))); + current = (c&31) << 11; + break; + case 11: + output.push(String.fromCharCode(current | (c >> 4))); + current = (c&15) << 12; + break; + case 12: + output.push(String.fromCharCode(current | (c >> 3))); + current = (c&7) << 13; + break; + case 13: + output.push(String.fromCharCode(current | (c >> 2))); + current = (c&3) << 14; + break; + case 14: + output.push(String.fromCharCode(current | (c >> 1))); + current = (c&1) << 15; + break; + case 15: + output.push(String.fromCharCode(current | c)); + status=0; + break; + } + + + i++; + } + + return this.decompress(output.join('')); + //return output; + + }, + + + // private property + _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", // jshint ignore:line + + decompress : function (input) { + var output = []; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 1; + var odd = input.charCodeAt(0) >> 8; + + while (i < input.length*2 && (i < input.length*2-1 || odd===0)) { + + if (i%2===0) { + chr1 = input.charCodeAt(i/2) >> 8; + chr2 = input.charCodeAt(i/2) & 255; + if (i/2+1 < input.length) { + chr3 = input.charCodeAt(i / 2 + 1) >> 8; + } + else { + chr3 = NaN; + } + } else { + chr1 = input.charCodeAt((i-1)/2) & 255; + if ((i+1)/2 < input.length) { + chr2 = input.charCodeAt((i+1)/2) >> 8; + chr3 = input.charCodeAt((i+1)/2) & 255; + } else { + chr2 = chr3 = NaN; + } + } + i+=3; + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2) || (i==input.length*2+1 && odd)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3) || (i==input.length*2 && odd)) { + enc4 = 64; + } + + output.push(this._keyStr.charAt(enc1)); + output.push(this._keyStr.charAt(enc2)); + output.push(this._keyStr.charAt(enc3)); + output.push(this._keyStr.charAt(enc4)); + } + + return output.join(''); + }, + + compress : function (input) { + var output = [], + ol = 1, + output_, + chr1, chr2, chr3, + enc1, enc2, enc3, enc4, + i = 0, flush=false; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); // jshint ignore:line + + while (i < input.length) { + + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + if (ol%2===0) { + output_ = chr1 << 8; + flush = true; + + if (enc3 != 64) { + output.push(String.fromCharCode(output_ | chr2)); + flush = false; + } + if (enc4 != 64) { + output_ = chr3 << 8; + flush = true; + } + } else { + output.push(String.fromCharCode(output_ | chr1)); + flush = false; + + if (enc3 != 64) { + output_ = chr2 << 8; + flush = true; + } + if (enc4 != 64) { + output.push(String.fromCharCode(output_ | chr3)); + flush = false; + } + } + ol+=3; + } + + if (flush) { + output.push(String.fromCharCode(output_)); + output = output.join(''); + output = String.fromCharCode(output.charCodeAt(0)|256) + output.substring(1); + } else { + output = output.join(''); + } + + return output; + + } +}; + +/*jslint bitwise: false */ + /* FileSaver.js * A saveAs() FileSaver implementation. * 2013-10-21 @@ -749,7 +1042,7 @@ O.esri.Tiles.TilesCore = function(){ */ this._getTiles = function(image,imageType,url,tileid,store,query,showBlankTiles){ store.retrieve(url, function(success, offlineTile) - { console.log("TILE RETURN " + success + ", " + offlineTile.url); + { console.log("TILE RETURN " + success + ", " + offlineTile.url + ", " + tileid); /* when the .getTileUrl() callback is triggered we replace the temporary URL originally returned by the data:image url */ // search for the img with src="void:"+level+"-"+row+"-"+col and replace with actual url image = query("img[src="+tileid+"]")[0]; @@ -1179,6 +1472,7 @@ O.esri.Tiles.TilesStore = function(){ }; var objectStore = transaction.objectStore(this.objectStoreName); + urlDataPair.img = O.esri.Tiles.Base64String.compress(urlDataPair.img); var request = objectStore.put(urlDataPair); request.onsuccess = function() { @@ -1212,6 +1506,7 @@ O.esri.Tiles.TilesStore = function(){ } else { + result.img = O.esri.Tiles.Base64String.decompress(result.img); callback(true,result); } }; diff --git a/dist/offline-tpk-min.js b/dist/offline-tpk-min.js index ae7c08a5..4b6e7381 100644 --- a/dist/offline-tpk-min.js +++ b/dist/offline-tpk-min.js @@ -51,10 +51,12 @@ return 1===b.length?"000"+b:2===b.length?"00"+b:3===b.length?"0"+b:b.substr(0,b. return 16+5*f},_getCacheFilePath:function(a,b,c,d){var e=[] return e.push(a),e.push("/"),e.push("L"),e.push(10>b?"0"+b:b),e.push("/"),e.push("R"),e.push(this._int2HexString(c)),e.push("C"),e.push(this._int2HexString(d)),e.join("")},_bytes2MBs:function(a){return(a>>>20)+"."+(2046&a)}})}),"undefined"!=typeof O?O.esri.TPK={}:(O={},O.esri={TPK:{},Tiles:{}}),O.esri.Tiles.TilesStore=function(){this._db=null,this.dbName="offline_tile_store",this.objectStoreName="tilepath",this.isSupported=function(){return!(!window.indexedDB&&!window.openDatabase)},this.store=function(a,b){try{var c=this._db.transaction([this.objectStoreName],"readwrite") c.oncomplete=function(){b(!0)},c.onerror=function(a){b(!1,a.target.error.message)} -var d=c.objectStore(this.objectStoreName),e=d.put(a) +var d=c.objectStore(this.objectStoreName) +a.img=O.esri.Tiles.Base64String.compress(a.img) +var e=d.put(a) e.onsuccess=function(){}}catch(f){b(!1,f.stack)}},this.retrieve=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName),d=c.get(a) d.onsuccess=function(a){var c=a.target.result -void 0===c?b(!1,"not found"):b(!0,c)},d.onerror=function(a){b(!1,a)}}},this.deleteAll=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() +void 0===c?b(!1,"not found"):(c.img=O.esri.Tiles.Base64String.decompress(c.img),b(!0,c))},d.onerror=function(a){b(!1,a)}}},this.deleteAll=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName).clear() b.onsuccess=function(){a(!0)},b.onerror=function(b){a(!1,b)}}else a(!1,null)},this["delete"]=function(a,b){if(null!==this._db){var c=this._db.transaction([this.objectStoreName],"readwrite").objectStore(this.objectStoreName)["delete"](a) c.onsuccess=function(){b(!0)},c.onerror=function(a){b(!1,a)}}else b(!1,null)},this.getAllTiles=function(a){if(null!==this._db){var b=this._db.transaction([this.objectStoreName]).objectStore(this.objectStoreName).openCursor() b.onsuccess=function(b){var c=b.target.result diff --git a/dist/offline-tpk-src.js b/dist/offline-tpk-src.js index 6fd468f7..40a00a83 100644 --- a/dist/offline-tpk-src.js +++ b/dist/offline-tpk-src.js @@ -1,4 +1,4 @@ -/*! esri-offline-maps - v3.3.0 - 2016-07-12 +/*! esri-offline-maps - v3.4.0 - 2016-09-13 * Copyright (c) 2016 Environmental Systems Research Institute, Inc. * Apache License*/ /** @@ -794,6 +794,7 @@ O.esri.Tiles.TilesStore = function(){ }; var objectStore = transaction.objectStore(this.objectStoreName); + urlDataPair.img = O.esri.Tiles.Base64String.compress(urlDataPair.img); var request = objectStore.put(urlDataPair); request.onsuccess = function() { @@ -827,6 +828,7 @@ O.esri.Tiles.TilesStore = function(){ } else { + result.img = O.esri.Tiles.Base64String.decompress(result.img); callback(true,result); } }; diff --git a/lib/tiles/LICENSE.md b/lib/tiles/LICENSE.md index 5300273b..d2eadabf 100644 --- a/lib/tiles/LICENSE.md +++ b/lib/tiles/LICENSE.md @@ -1,11 +1,16 @@ +## base64String.js +License for base64String.js is WTFPL, Version 2, http://www.wtfpl.net/ and provided courtesy and copyright of Pieroxy . + + +## FileSaver.js + License for FileSaver.js This software is licensed under the MIT/X11 license. MIT/X11 license ---------------- -Copyright © 2011 [Eli Grey][1]. +Copyright © 2011 [Eli Grey] http://eligrey.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -26,7 +31,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - - - [1]: http://eligrey.com \ No newline at end of file +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/lib/tiles/TilesCore.js b/lib/tiles/TilesCore.js index a9f88b92..185542fc 100644 --- a/lib/tiles/TilesCore.js +++ b/lib/tiles/TilesCore.js @@ -18,7 +18,7 @@ O.esri.Tiles.TilesCore = function(){ */ this._getTiles = function(image,imageType,url,tileid,store,query,showBlankTiles){ store.retrieve(url, function(success, offlineTile) - { console.log("TILE RETURN " + success + ", " + offlineTile.url); + { console.log("TILE RETURN " + success + ", " + offlineTile.url + ", " + tileid); /* when the .getTileUrl() callback is triggered we replace the temporary URL originally returned by the data:image url */ // search for the img with src="void:"+level+"-"+row+"-"+col and replace with actual url image = query("img[src="+tileid+"]")[0]; diff --git a/lib/tiles/TilesStore.js b/lib/tiles/TilesStore.js index 08dd376a..861f1778 100644 --- a/lib/tiles/TilesStore.js +++ b/lib/tiles/TilesStore.js @@ -53,6 +53,7 @@ O.esri.Tiles.TilesStore = function(){ }; var objectStore = transaction.objectStore(this.objectStoreName); + urlDataPair.img = O.esri.Tiles.Base64String.compress(urlDataPair.img); var request = objectStore.put(urlDataPair); request.onsuccess = function() { @@ -86,6 +87,7 @@ O.esri.Tiles.TilesStore = function(){ } else { + result.img = O.esri.Tiles.Base64String.decompress(result.img); callback(true,result); } }; diff --git a/lib/tiles/base64string.js b/lib/tiles/base64string.js new file mode 100644 index 00000000..7a4e8630 --- /dev/null +++ b/lib/tiles/base64string.js @@ -0,0 +1,292 @@ +// Copyright (c) 2013 Pieroxy +// This work is free. You can redistribute it and/or modify it +// under the terms of the WTFPL, Version 2 +// For more information see LICENSE.txt or http://www.wtfpl.net/ +// +// This lib is part of the lz-string project. +// For more information, the home page: +// http://pieroxy.net/blog/pages/lz-string/index.html +// +// Base64 compression / decompression for already compressed content (gif, png, jpg, mp3, ...) +// version 1.4.1 + +/*jslint bitwise: true */ +O.esri.Tiles.Base64String = { + + compressToUTF16 : function (input) { + var output = [], + i,c, + current, + status = 0; + + input = this.compress(input); + + for (i=0 ; i> 1)+32)); + current = (c & 1) << 14; + break; + case 1: + output.push(String.fromCharCode((current + (c >> 2))+32)); + current = (c & 3) << 13; + break; + case 2: + output.push(String.fromCharCode((current + (c >> 3))+32)); + current = (c & 7) << 12; + break; + case 3: + output.push(String.fromCharCode((current + (c >> 4))+32)); + current = (c & 15) << 11; + break; + case 4: + output.push(String.fromCharCode((current + (c >> 5))+32)); + current = (c & 31) << 10; + break; + case 5: + output.push(String.fromCharCode((current + (c >> 6))+32)); + current = (c & 63) << 9; + break; + case 6: + output.push(String.fromCharCode((current + (c >> 7))+32)); + current = (c & 127) << 8; + break; + case 7: + output.push(String.fromCharCode((current + (c >> 8))+32)); + current = (c & 255) << 7; + break; + case 8: + output.push(String.fromCharCode((current + (c >> 9))+32)); + current = (c & 511) << 6; + break; + case 9: + output.push(String.fromCharCode((current + (c >> 10))+32)); + current = (c & 1023) << 5; + break; + case 10: + output.push(String.fromCharCode((current + (c >> 11))+32)); + current = (c & 2047) << 4; + break; + case 11: + output.push(String.fromCharCode((current + (c >> 12))+32)); + current = (c & 4095) << 3; + break; + case 12: + output.push(String.fromCharCode((current + (c >> 13))+32)); + current = (c & 8191) << 2; + break; + case 13: + output.push(String.fromCharCode((current + (c >> 14))+32)); + current = (c & 16383) << 1; + break; + case 14: + output.push(String.fromCharCode((current + (c >> 15))+32, (c & 32767)+32)); + status = 0; + break; + } + } + output.push(String.fromCharCode(current + 32)); + return output.join(''); + }, + + + decompressFromUTF16 : function (input) { + var output = [], + current,c, + status=0, + i = 0; + + while (i < input.length) { + c = input.charCodeAt(i) - 32; + + switch (status++) { + case 0: + current = c << 1; + break; + case 1: + output.push(String.fromCharCode(current | (c >> 14))); + current = (c&16383) << 2; + break; + case 2: + output.push(String.fromCharCode(current | (c >> 13))); + current = (c&8191) << 3; + break; + case 3: + output.push(String.fromCharCode(current | (c >> 12))); + current = (c&4095) << 4; + break; + case 4: + output.push(String.fromCharCode(current | (c >> 11))); + current = (c&2047) << 5; + break; + case 5: + output.push(String.fromCharCode(current | (c >> 10))); + current = (c&1023) << 6; + break; + case 6: + output.push(String.fromCharCode(current | (c >> 9))); + current = (c&511) << 7; + break; + case 7: + output.push(String.fromCharCode(current | (c >> 8))); + current = (c&255) << 8; + break; + case 8: + output.push(String.fromCharCode(current | (c >> 7))); + current = (c&127) << 9; + break; + case 9: + output.push(String.fromCharCode(current | (c >> 6))); + current = (c&63) << 10; + break; + case 10: + output.push(String.fromCharCode(current | (c >> 5))); + current = (c&31) << 11; + break; + case 11: + output.push(String.fromCharCode(current | (c >> 4))); + current = (c&15) << 12; + break; + case 12: + output.push(String.fromCharCode(current | (c >> 3))); + current = (c&7) << 13; + break; + case 13: + output.push(String.fromCharCode(current | (c >> 2))); + current = (c&3) << 14; + break; + case 14: + output.push(String.fromCharCode(current | (c >> 1))); + current = (c&1) << 15; + break; + case 15: + output.push(String.fromCharCode(current | c)); + status=0; + break; + } + + + i++; + } + + return this.decompress(output.join('')); + //return output; + + }, + + + // private property + _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", // jshint ignore:line + + decompress : function (input) { + var output = []; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 1; + var odd = input.charCodeAt(0) >> 8; + + while (i < input.length*2 && (i < input.length*2-1 || odd===0)) { + + if (i%2===0) { + chr1 = input.charCodeAt(i/2) >> 8; + chr2 = input.charCodeAt(i/2) & 255; + if (i/2+1 < input.length) { + chr3 = input.charCodeAt(i / 2 + 1) >> 8; + } + else { + chr3 = NaN; + } + } else { + chr1 = input.charCodeAt((i-1)/2) & 255; + if ((i+1)/2 < input.length) { + chr2 = input.charCodeAt((i+1)/2) >> 8; + chr3 = input.charCodeAt((i+1)/2) & 255; + } else { + chr2 = chr3 = NaN; + } + } + i+=3; + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2) || (i==input.length*2+1 && odd)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3) || (i==input.length*2 && odd)) { + enc4 = 64; + } + + output.push(this._keyStr.charAt(enc1)); + output.push(this._keyStr.charAt(enc2)); + output.push(this._keyStr.charAt(enc3)); + output.push(this._keyStr.charAt(enc4)); + } + + return output.join(''); + }, + + compress : function (input) { + var output = [], + ol = 1, + output_, + chr1, chr2, chr3, + enc1, enc2, enc3, enc4, + i = 0, flush=false; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); // jshint ignore:line + + while (i < input.length) { + + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + if (ol%2===0) { + output_ = chr1 << 8; + flush = true; + + if (enc3 != 64) { + output.push(String.fromCharCode(output_ | chr2)); + flush = false; + } + if (enc4 != 64) { + output_ = chr3 << 8; + flush = true; + } + } else { + output.push(String.fromCharCode(output_ | chr1)); + flush = false; + + if (enc3 != 64) { + output_ = chr2 << 8; + flush = true; + } + if (enc4 != 64) { + output.push(String.fromCharCode(output_ | chr3)); + flush = false; + } + } + ol+=3; + } + + if (flush) { + output.push(String.fromCharCode(output_)); + output = output.join(''); + output = String.fromCharCode(output.charCodeAt(0)|256) + output.substring(1); + } else { + output = output.join(''); + } + + return output; + + } +}; + +/*jslint bitwise: false */ diff --git a/package.json b/package.json index 0e59a8b8..315948da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "esri-offline-maps", - "version": "3.3.2", + "version": "3.4.0", "description": "Lightweight set of libraries for working offline with map tiles and editing with ArcGIS feature services", "author": "Andy Gup (http://blog.andygup.net)", "license": "Apache 2.0", diff --git a/samples/package.json b/samples/package.json index c9ffcdcc..02ba7340 100644 --- a/samples/package.json +++ b/samples/package.json @@ -9,7 +9,7 @@ "appHomePage": "appcache-tiles.html", "optimizedApiURL": "../samples/jsolib", "arcGISBaseURL": "http://js.arcgis.com/3.14", - "version": "3.3.2", + "version": "3.4.0", "private": true, "description": "manifest generator project", "repository": {