mirror of
https://github.com/Esri/offline-editor-js.git
synced 2025-12-15 15:20:05 +00:00
660 lines
28 KiB
HTML
660 lines
28 KiB
HTML
<!DOCTYPE html>
|
|
<html manifest="appcache-features.appcache">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<!--The viewport meta tag is used to improve the presentation and behavior of the samples
|
|
on iOS devices-->
|
|
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
|
|
|
|
<!--
|
|
|
|
This sample demonstrates using an application manifest to store features and tiles locally.
|
|
|
|
The use cases for using this sample are to ensure you can reload and restart you application
|
|
one it is offline.
|
|
|
|
It is strongly recommended that you use your own optimized build of the ArcGIS API for JavaScript
|
|
using the Web Optimizer: http://jso.arcgis.com/. You can reference the CDN or host it on your
|
|
own web server.
|
|
|
|
Use the Grunt task in the /samples diretory to help generate the manifest file. There is manual
|
|
work involved in determining which files need to go into the manifest. The included manifest
|
|
file should work with this sample to give you an idea of what goes into the manifest.
|
|
|
|
A few things to know about manifest files:
|
|
- You cannot load an online url that has a redirect.
|
|
- If there is an error encountered, the manifest file will stop loading
|
|
- The /utils/appCacheManager.js library will auto detect if the manifest changed and
|
|
ask if you want to reload the application.
|
|
|
|
-->
|
|
|
|
<title>AppCache Tiles and Features</title>
|
|
|
|
<!-- Bootstrap core CSS -->
|
|
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="../samples/widgets/modal/css/modal-popup.css">
|
|
<link rel="stylesheet" href="http://js.arcgis.com/3.10/js/dojo/dijit/themes/claro/claro.css">
|
|
<link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">
|
|
<link rel="stylesheet" href="http://esri.github.io/bootstrap-map-js/src/css/bootstrapmap.css">
|
|
|
|
<style>
|
|
#mapDiv {
|
|
min-height: 500px;
|
|
max-height: 1000px;
|
|
}
|
|
|
|
body {
|
|
background-color: #ffffff;
|
|
overflow: hidden;
|
|
font-family: "Trebuchet MS";
|
|
}
|
|
|
|
#loader-gif{
|
|
visibility: hidden;
|
|
}
|
|
|
|
/* Override mod-popup default */
|
|
.mod-popup-stop-input {color: black;}
|
|
.span-pending {color: blue; padding-left: 1em;}
|
|
|
|
.floatRight { float: right;}
|
|
.container { padding: 20px;}
|
|
</style>
|
|
|
|
<!--<script>-->
|
|
<!--// If you need to catch AppCache errors as early as possible to troubleshoot errors.-->
|
|
<!--window.applicationCache.addEventListener("error",function(err){-->
|
|
<!--console.log("ApplicationCache listener: " + err.toString());-->
|
|
<!--if (confirm('There was a problem setting this app up for offline. Reload?')) {-->
|
|
<!--window.location.reload();-->
|
|
<!--console.log("App cache reloaded");-->
|
|
<!--}-->
|
|
<!--},false)-->
|
|
<!--</script>-->
|
|
<script src="../vendor/offline/offline.min.js"></script>
|
|
<script>
|
|
Offline.options = {
|
|
checks: {
|
|
image: {
|
|
url: function() {
|
|
return 'http://esri.github.io/offline-editor-js/tiny-image.png?_=' + (Math.floor(Math.random() * 1000000000));
|
|
}
|
|
},
|
|
active: 'image'
|
|
}
|
|
}
|
|
|
|
var locationPath = location.pathname.replace(/\/[^/]+$/, "");
|
|
var dojoConfig = {
|
|
paths: {
|
|
vendor: locationPath + "/../vendor",
|
|
utils: locationPath + "/../utils",
|
|
widgets: locationPath + "/widgets"
|
|
}
|
|
}
|
|
</script>
|
|
<!-- Required when using the offline-editor-js library with Safari -->
|
|
<script src="../vendor/IndexedDBShim/dist/IndexedDBShim.js"></script>
|
|
|
|
<!--
|
|
This is a locally hosted optimized build of the ArcGIS JS API
|
|
To create your own optimized build go to: http://http://jso.arcgis.com/
|
|
-->
|
|
<script src="../samples/jsolib/dojo.js" data-dojo-config="async: true"></script>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Our buttons and online/offline indicator -->
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-xs-10">
|
|
<div class="form form-group btn-group" data-toggle="buttons">
|
|
<button class="btn btn-success" id="btn-get-tiles">1. Download Tiles</button>
|
|
<button class="btn btn-success" disabled id="btn-online-offline">2. Go Offline</button>
|
|
</div>
|
|
<span class="span-pending">Pending Edits <span id="span-pending-edits" class="badge">0</span></span>
|
|
<img id="loader-gif" src="images/loading.gif"/>
|
|
</div>
|
|
<div class="col-xs-2">
|
|
<!-- this indicates whether app is offline (down) or online (up) -->
|
|
<button id="btn-state" class="btn btn-success btn-large floatRight">
|
|
<span id="state-span" class="glyphicon glyphicon-link"> Up</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-xs-12">
|
|
<div id="mapDiv"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Stub for modal popup -->
|
|
<div id="modal-popup"></div>
|
|
|
|
<script>
|
|
require(["esri/map","esri/layers/FeatureLayer",
|
|
"utils/appCacheManager",
|
|
"esri/renderers/SimpleRenderer","esri/symbols/SimpleMarkerSymbol",
|
|
"esri/Color",
|
|
"esri/tasks/query",
|
|
"dojo/on",
|
|
"esri/graphic",
|
|
"widgets/modal/popup",
|
|
"//esri.github.io/bootstrap-map-js/src/js/bootstrapmap.js",
|
|
"../dist/offline-tiles-advanced-src.js",
|
|
"../dist/offline-edit-src.js",
|
|
"dojo/domReady!"],
|
|
function(Map,FeatureLayer,AppCacheManager,
|
|
SimpleRenderer,SimpleMarkerSymbol,Color,Query,
|
|
on,Graphic,ModalPopup,BootstrapMap) {
|
|
|
|
initAppCacheManager();
|
|
|
|
var _isOnline = true;
|
|
var defaultSymbol;
|
|
|
|
// Variables for editing handling
|
|
var currentFeature, busStopFeatureLayer, offlineFeaturesManager;
|
|
var pendingEdits = document.getElementById("span-pending-edits");
|
|
var imgOfflineIndicator = document.getElementById("state-span");
|
|
var btnState = document.getElementById("btn-state");
|
|
|
|
// Variables for handling tiles
|
|
var tileLayer;
|
|
var _currentExtent = null;
|
|
var _wantToCancel;
|
|
var globalState = {};
|
|
var btnGetTiles = document.getElementById("btn-get-tiles");
|
|
var btnOnlineOffline = document.getElementById("btn-online-offline");
|
|
|
|
// Important settings for determining which tile layers gets stored for offline use.
|
|
var minZoomAdjust = -1, maxZoomAdjust = 1, resetZoom = 18;
|
|
var EXTENT_BUFFER = 0; //buffers the map extent in meters
|
|
|
|
// Misc.
|
|
var appCacheManager;
|
|
var loading = document.getElementById("loader-gif");
|
|
|
|
// Variables for modal popup
|
|
var popup,closeBtn,saveBtn,deleteBtn,stopMainID,stopID,stopRoutes,stopNames;
|
|
|
|
// Modify symbol size based on screen size.
|
|
// Bigger screens get smaller symbols. Smaller screens get larger symbols.
|
|
var width = window.innerWidth
|
|
|| document.documentElement.clientWidth
|
|
|| document.body.clientWidth;
|
|
|
|
var height = window.innerHeight
|
|
|| document.documentElement.clientHeight
|
|
|| document.body.clientHeight;
|
|
|
|
if (height > 768 || width > 1024) {
|
|
defaultSymbol= new SimpleMarkerSymbol().setStyle(
|
|
SimpleMarkerSymbol.STYLE_DIAMOND).setColor(
|
|
new Color([255,0,0,0.5])).setSize(20);
|
|
}
|
|
else{
|
|
defaultSymbol= new SimpleMarkerSymbol().setStyle(
|
|
SimpleMarkerSymbol.STYLE_DIAMOND).setColor(
|
|
new Color([255,0,0,0.5])).setSize(35);
|
|
}
|
|
|
|
var editsStore = new O.esri.Edit.EditStore();
|
|
|
|
initModalPopup();
|
|
|
|
/**
|
|
* There have been a few bugs in the offline detection library (offline.min.js)
|
|
* This is a utility check to 100% validate if the application is online or
|
|
* offline prior to launching any map functionality.
|
|
*/
|
|
verifyOnline(function(result){ console.log("VERIFY ONLINE " + result)
|
|
result == true ? _isOnline = true : _isOnline = false;
|
|
startMap();
|
|
});
|
|
|
|
function initModalPopup(){
|
|
popup = new ModalPopup({animation: true, animationDuration: 1},"modal-popup");
|
|
|
|
// Variables for modal popup
|
|
closeBtn = document.getElementById("mod-popup-close-btn");
|
|
saveBtn = document.getElementById("mod-popup-save-btn");
|
|
deleteBtn = document.getElementById("mod-popup-delete-btn");
|
|
stopMainID = document.getElementById("stop-main-id");
|
|
stopID = document.getElementById("stop-id");
|
|
stopRoutes = document.getElementById("stop-routes");
|
|
stopNames = document.getElementById("stop-names");
|
|
}
|
|
|
|
function startMap(){
|
|
|
|
//Make sure map shows up after a browser refresh
|
|
Offline.check();
|
|
Offline.state === 'up' ? resetZoom = 18 : resetZoom = 17;
|
|
|
|
tileLayer = new O.esri.Tiles.OfflineTileEnablerLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",function(evt){
|
|
console.log("Tile Layer initialized for offline. App state is: " + Offline.state);
|
|
},_isOnline);
|
|
|
|
tileLayer.offline.proxyPath = null;
|
|
|
|
var map = BootstrapMap.create("mapDiv",{
|
|
center: [-104.99,39.75], // long, lat
|
|
zoom: 17,
|
|
sliderStyle: "small"
|
|
});
|
|
|
|
map.addLayer(tileLayer);
|
|
|
|
busStopFeatureLayer = new FeatureLayer("http://services.arcgis.com/IZtlGBUe4KTzLOl4/arcgis/rest/services/BPX_RTD_BusStops2/FeatureServer/0", {
|
|
mode: FeatureLayer.MODE_SNAPSHOT,
|
|
outFields: ["OBJECTID","BSID","ROUTES","STOPNAME"]
|
|
});
|
|
|
|
//Set the graphics to red boxes to make it easy to click on them
|
|
//on a mobile device.
|
|
busStopFeatureLayer.setRenderer(new SimpleRenderer(defaultSymbol));
|
|
|
|
busStopFeatureLayer.on("update-end",function(evt){
|
|
|
|
// Set click listeners
|
|
on(btnGetTiles,"click",downloadTiles);
|
|
on(btnOnlineOffline, 'click', goOnlineOffline);
|
|
|
|
initOfflineFeaturesMgr();
|
|
setFeatureLayerClickHandler();
|
|
setModalPopupClickListeners();
|
|
|
|
var features = evt.target.graphics;
|
|
|
|
// Convert existing feature graphics into JSON.
|
|
// These are then stored in localStorage.
|
|
// If you want you can store multiple feature layers.
|
|
// Just be aware of the localStorage limitations.
|
|
busStopFeatureLayer.convertGraphicLayerToJSON(features,evt,function(features,layerDef){
|
|
|
|
if(typeof(Storage) !== "undefined") {
|
|
localStorage.offlineLayerDef = layerDef;
|
|
localStorage.offlineFeature = features;
|
|
console.log("Done pushing layerDef and features to localStorage.")
|
|
} else {
|
|
alert("The offline library is not supported on this browser.")
|
|
}
|
|
})
|
|
});
|
|
|
|
map.on("zoom-end",function(evt){
|
|
_currentExtent = evt.extent;
|
|
});
|
|
|
|
map.on("pan-end",function(evt){
|
|
_currentExtent = evt.extent;
|
|
});
|
|
|
|
map.on("load",function(evt){
|
|
|
|
_currentExtent = evt.map.extent;
|
|
updateOfflineUsage();
|
|
updateStatus();
|
|
|
|
if(_isOnline == false){
|
|
|
|
var featureLayer = JSON.parse(localStorage.offlineLayerDef);
|
|
var featuresArray = JSON.parse(localStorage.offlineFeature);
|
|
var geometryType = "esriGeometryPoint";
|
|
|
|
initOfflineFeaturesMgr();
|
|
|
|
busStopFeatureLayer.getFeatureDefinition(featureLayer,featuresArray,geometryType,function(featureDef){
|
|
|
|
busStopFeatureLayer = new FeatureLayer(featureDef,{
|
|
mode: FeatureLayer.MODE_SNAPSHOT,
|
|
outFields: ["OBJECTID","BSID","ROUTES","STOPNAME"]
|
|
});
|
|
|
|
// Set the graphic symbols to red diamond to make it easy to click on them
|
|
// on a mobile device.
|
|
busStopFeatureLayer.setRenderer(new SimpleRenderer(defaultSymbol));
|
|
var mapListen = map.on("update-end",function(evt){
|
|
console.log("Feature has been added back to the map while offline.");
|
|
on(btnGetTiles,"click",downloadTiles);
|
|
on(btnOnlineOffline, 'click', goOnlineOffline);
|
|
|
|
setFeatureLayerClickHandler();
|
|
setModalPopupClickListeners();
|
|
mapListen.remove();
|
|
})
|
|
map.addLayer(busStopFeatureLayer);
|
|
});
|
|
}
|
|
});
|
|
|
|
map.addLayer(busStopFeatureLayer);
|
|
}
|
|
|
|
/**
|
|
* **********************************************
|
|
* FEATURE LAYER MANAGEMENT CODE
|
|
* **********************************************
|
|
*/
|
|
|
|
function initOfflineFeaturesMgr(){
|
|
offlineFeaturesManager = new O.esri.Edit.OfflineFeaturesManager();
|
|
|
|
// IMPORTANT!!!
|
|
// A proxy page may be required to upload attachments.
|
|
// If you are using a CORS enabled server you may be ablew to set the proxyPath to null.
|
|
// Refer to "Using the Proxy Page" for more information: https://developers.arcgis.com/en/javascript/jshelp/ags_proxy.html
|
|
offlineFeaturesManager.proxyPath = null;
|
|
|
|
offlineFeaturesManager.on(offlineFeaturesManager.events.EDITS_ENQUEUED, updateStatus);
|
|
offlineFeaturesManager.on(offlineFeaturesManager.events.EDITS_SENT, updateStatus);
|
|
offlineFeaturesManager.on(offlineFeaturesManager.events.ALL_EDITS_SENT, updateStatus);
|
|
|
|
offlineFeaturesManager.extend(busStopFeatureLayer);
|
|
console.log("offlineFeaturesManager initialized.");
|
|
|
|
Offline.check();
|
|
Offline.on('up', goOnline);
|
|
Offline.on('down', goOffline);
|
|
|
|
// If the app is online then set offlineFeaturesManager to its online state
|
|
// This will force the library to check for pending edits and attempt to
|
|
// resend them to the Feature Service.
|
|
if(_isOnline == true){
|
|
offlineFeaturesManager.goOnline();
|
|
}
|
|
}
|
|
|
|
function updateStatus(){
|
|
if( editsStore.hasPendingEdits())
|
|
{
|
|
var edits = editsStore.retrieveEditsQueue();
|
|
pendingEdits.innerHTML = edits.length;
|
|
}
|
|
else
|
|
{
|
|
pendingEdits.innerHTML = "0";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Display modal popup when someone clicks on a feature
|
|
*/
|
|
function setFeatureLayerClickHandler(){
|
|
busStopFeatureLayer.on("click", function(evt) {
|
|
currentFeature = evt.graphic
|
|
|
|
var query = new Query();
|
|
query.objectIds = [evt.graphic.attributes.OBJECTID];
|
|
busStopFeatureLayer.selectFeatures(query,FeatureLayer.SELECTION_NEW,
|
|
function(evt){
|
|
console.log("Success: " + JSON.stringify(evt[0].attributes));
|
|
showModalPopup(evt[0]);
|
|
var atts = evt[0].attributes
|
|
stopID.value = atts.OBJECTID;
|
|
stopMainID.value = atts.BSID;
|
|
stopNames.value = atts.STOPNAME;
|
|
stopRoutes.value = atts.ROUTES;
|
|
},function(err){
|
|
console.log("ERROR " + JSON.stringify(err));
|
|
});
|
|
}.bind(this));
|
|
}
|
|
|
|
function setModalPopupClickListeners(){
|
|
closeBtn.onclick = function(evt){
|
|
hideModalPopup();
|
|
}
|
|
|
|
saveBtn.onclick = function(evt){
|
|
|
|
forceInternalOfflineCheck();
|
|
|
|
popup.graphic.attributes.ROUTES = stopRoutes.value;
|
|
popup.graphic.attributes.STOPNAME = stopNames.value;
|
|
|
|
busStopFeatureLayer.applyEdits(null,[popup.graphic],null,function(result){
|
|
console.log("Successfully saved changes to: " + popup.graphic.attributes.STOPNAME);
|
|
hideModalPopup();
|
|
},
|
|
function(err){
|
|
alert("There was a problem while trying to save: " + popup.graphic.attributes.STOPNAME);
|
|
})
|
|
}
|
|
|
|
deleteBtn.onclick = function(evt){
|
|
|
|
forceInternalOfflineCheck();
|
|
|
|
busStopFeatureLayer.applyEdits(null,null,[popup.graphic],function(result){
|
|
console.log("Successfully deleted: " + popup.graphic.attributes.STOPNAME);
|
|
hideModalPopup();
|
|
},
|
|
function(err){
|
|
alert("There was a problem while trying to delete: " + popup.graphic.attributes.STOPNAME);
|
|
})
|
|
}
|
|
}
|
|
|
|
function showModalPopup(graphic){
|
|
popup.graphic = graphic; // assign graphic to popup as a property.
|
|
popup.show();
|
|
}
|
|
|
|
function hideModalPopup(){
|
|
popup.hide();
|
|
}
|
|
|
|
/**
|
|
* ************************************
|
|
* TILE MANAGEMENT CODE
|
|
* ************************************
|
|
*/
|
|
|
|
/**
|
|
* Manually starts the process to download and store tiles
|
|
* in the local database
|
|
*/
|
|
function downloadTiles(){
|
|
tileLayer.deleteAllTiles(function(success,err){
|
|
if(success == false){
|
|
alert("There was a problem deleting the tile cache");
|
|
}
|
|
else{
|
|
console.log("success deleting tile cache");
|
|
|
|
if( globalState.downloadState == 'downloading')
|
|
{
|
|
console.log("cancel!");
|
|
_wantToCancel = true;
|
|
btnGetTiles.innerHTML = "cancelling..";
|
|
}
|
|
else
|
|
{
|
|
var zoom = tileLayer.getMinMaxLOD(minZoomAdjust,maxZoomAdjust);
|
|
|
|
var extent = tileLayer.getExtentBuffer(EXTENT_BUFFER,_currentExtent);
|
|
_wantToCancel = false;
|
|
tileLayer.prepareForOffline(zoom.min, zoom.max, extent, reportProgress.bind(this));
|
|
globalState.downloadState = 'downloading';
|
|
}
|
|
}
|
|
}.bind(this))
|
|
}
|
|
|
|
/**
|
|
* Reports the process while downloading tiles.
|
|
*/
|
|
function reportProgress(progress)
|
|
{
|
|
console.log("downloading tiles...");
|
|
if(progress.hasOwnProperty("countNow")){
|
|
var percent = Math.floor(progress.countNow / progress.countMax * 100);
|
|
btnGetTiles.innerHTML = 'Saving to phone ' + percent + "% - Tap to Cancel";
|
|
}
|
|
|
|
if( progress.finishedDownloading )
|
|
{
|
|
btnGetTiles.innerHTML = "Saving to phone 100% - Tap to Cancel";
|
|
updateOfflineUsage();
|
|
|
|
if( progress.cancelRequested )
|
|
{
|
|
globalState.downloadState = 'cancelled';
|
|
alert("Tile download was cancelled");
|
|
}
|
|
else
|
|
{
|
|
globalState.downloadState = 'downloaded';
|
|
btnOnlineOffline.disabled = false;
|
|
alert("Tile download complete");
|
|
}
|
|
|
|
btnGetTiles.innerHTML = '1. Download Tiles';
|
|
}
|
|
return _wantToCancel; //determines if a cancel request has been issued
|
|
}
|
|
|
|
/**
|
|
* ************************************
|
|
* HANDLE GOING ONLINE/OFFLINE
|
|
* ************************************
|
|
*/
|
|
|
|
function goOnline(){
|
|
console.log("Going online...");
|
|
|
|
loading.style.visibility = "visible";
|
|
|
|
offlineFeaturesManager.goOnline(function(success,error){
|
|
if(error === undefined){
|
|
btnOnlineOffline.innerHTML = "2. Go Offline";
|
|
imgOfflineIndicator.className = "glyphicon glyphicon-link";
|
|
imgOfflineIndicator.innerHTML = " Up";
|
|
btnState.className = "btn btn-success btn-large floatRight";
|
|
console.log("offlineFeatureManager is online.");
|
|
}
|
|
else{
|
|
alert("There was a problem syncing offline edits: " + JSON.stringify(error));
|
|
}
|
|
|
|
loading.style.visibility = "hidden";
|
|
});
|
|
|
|
updateOfflineUsage();
|
|
if(typeof tileLayer != "undefined") tileLayer.goOnline();
|
|
}
|
|
|
|
function goOffline(){
|
|
console.log("Going offline...");
|
|
btnOnlineOffline.innerHTML = "2. Go Online";
|
|
imgOfflineIndicator.className = "glyphicon glyphicon-thumbs-down";
|
|
imgOfflineIndicator.innerHTML = " Down";
|
|
btnState.className = "btn btn-danger btn-large floatRight";
|
|
offlineFeaturesManager.goOffline();
|
|
if(typeof tileLayer != "undefined") tileLayer.goOffline();
|
|
}
|
|
|
|
function goOnlineOffline(){
|
|
if(offlineFeaturesManager.getOnlineStatus() == offlineFeaturesManager.ONLINE){
|
|
goOffline();
|
|
}
|
|
else{
|
|
goOnline();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* For internal use - detecting amount of storage used and number of tiles stored.
|
|
*/
|
|
function updateOfflineUsage()
|
|
{
|
|
tileLayer.offline.store.usedSpace(function(result,err){
|
|
if(result != null){
|
|
console.log( "DB Tile count: " + result.tileCount + ", DB Bytes: " + result.sizeBytes);
|
|
}
|
|
else{
|
|
console.log("DB Tile count: " + count + ", DB Bytes: Error");
|
|
}
|
|
})
|
|
}
|
|
|
|
function forceInternalOfflineCheck(){
|
|
Offline.check();
|
|
if(Offline.state == "up"){
|
|
goOnline();
|
|
}
|
|
if(Offline.state == "down"){
|
|
goOffline();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attempts an http request to verify if app is online or offline.
|
|
* Use this in conjunction with the offline checker library: offline.min.js
|
|
* @param callback
|
|
*/
|
|
function verifyOnline(callback){
|
|
var req = new XMLHttpRequest();
|
|
req.open("GET", "images/blue-pin.png?" + (Math.floor(Math.random() * 1000000000)), true);
|
|
req.onload = function()
|
|
{
|
|
if( req.status === 200 && req.responseText !== "")
|
|
{
|
|
callback(true);
|
|
}
|
|
else
|
|
{
|
|
console.log("verifyOffline failed");
|
|
callback(false);
|
|
}
|
|
};
|
|
req.onerror = function(e)
|
|
{
|
|
console.log("appcache-features.html verifyOnline failed: " + e);
|
|
callback(false);
|
|
};
|
|
req.send(null);
|
|
}
|
|
|
|
/**
|
|
* ************************************
|
|
* APPCACHE MANAGEMENT CODE
|
|
* ************************************
|
|
*/
|
|
|
|
/**
|
|
* Listen for app cache events.
|
|
*/
|
|
function initAppCacheManager(){
|
|
appCacheManager = new AppCacheManager(true,true);
|
|
appCacheManager.on(appCacheManager.CACHE_EVENT,cacheEventHandler);
|
|
appCacheManager.on(appCacheManager.CACHE_ERROR,cacheErrorHandler);
|
|
appCacheManager.on(appCacheManager.CACHE_LOADED,cacheLoadedHandler);
|
|
}
|
|
|
|
function cacheLoadedHandler(evt){
|
|
if(evt == appCacheManager.CACHE_LOADED) console.log("Application cache successfully loaded!")
|
|
}
|
|
|
|
function cacheEventHandler(evt){
|
|
if(evt.hasOwnProperty("total")) console.log("CACHE EVENT loaded #:" + evt.loaded + ", out of " + evt.total);
|
|
}
|
|
|
|
function cacheErrorHandler(evt){
|
|
console.log("CACHE ERROR: " + JSON.stringify(evt));
|
|
alert("There was a problem loading the cache. Try reloading the app. ")
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<!-- Bootstrap core JavaScript
|
|
================================================== -->
|
|
<!-- Placed at the end of the document so the pages load faster -->
|
|
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
|
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
|
|
</body>
|
|
</html> |