Improved www.ttss.krakow.pl
Jacek Kowalski
2017-05-04 53747186cf6157b8f604345f241e9df9a893c768
Service worker draft
6 files modified
2 files added
187 ■■■■ changed files
common.js 27 ●●●● patch | view | raw | blame | history
index.html 1 ●●●● patch | view | raw | blame | history
index.js 3 ●●●● patch | view | raw | blame | history
map.html 1 ●●●● patch | view | raw | blame | history
map.js 1 ●●●● patch | view | raw | blame | history
serviceworker-install.js 10 ●●●●● patch | view | raw | blame | history
serviceworker.js 135 ●●●●● patch | view | raw | blame | history
version.php 9 ●●●● patch | view | raw | blame | history
common.js
@@ -4,31 +4,10 @@
    'Zajezdnia Podgórze' : 'P',
};
var script_version;
var script_version_xhr;
// Check for website updates
/* Check for website updates */
function checkVersion() {
    if(script_version_xhr) script_version_xhr.abort();
    script_version_xhr = $.get(
        'version.php'
    ).done(function(data) {
        if(!script_version) {
            script_version = data;
            return;
        }
        if(script_version != data) {
            fail(lang.error_new_version);
            location.reload(true);
        }
    });
}
function checkVersionInit() {
    checkVersion();
    setInterval(checkVersion, 3600000);
    $.get('version.php');
    setTimeout(checkVersion, 600000);
}
/* Parsing of received JSON parts */
index.html
@@ -137,5 +137,6 @@
        <script tyle="text/javascript" src="lang_pl.js" id="lang_script"></script>
        <script tyle="text/javascript" src="common.js"></script>
        <script type="text/javascript" src="index.js"></script>
        <script tyle="text/javascript" src="serviceworker-install.js"></script>
    </body>
</html>
index.js
@@ -403,8 +403,7 @@
    hash();
    
    window.addEventListener('hashchange', hash);
    checkVersionInit();
}
init();
checkVersion();
map.html
@@ -19,5 +19,6 @@
<script tyle="text/javascript" src="lang_pl.js" id="lang_script"></script>
<script tyle="text/javascript" src="common.js"></script>
<script tyle="text/javascript" src="map.js"></script>
<script tyle="text/javascript" src="serviceworker-install.js"></script>
</body>
</html>
map.js
@@ -761,3 +761,4 @@
}
init();
checkVersion();
serviceworker-install.js
New file
@@ -0,0 +1,10 @@
if('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('/serviceworker.js').then(function(registration) {
            console.log('Service Worker registration successful. ', registration);
            navigator.serviceWorker.controller.postMessage({action: 'skipWaiting'});
        }).catch(function(err) {
            console.log('Service Worker registration failed. ', err);
        });
    });
}
serviceworker.js
New file
@@ -0,0 +1,135 @@
'use strict';
var CACHE = 'ttss-app-v1';
var CACHE_RESOURCES = [
    '/version.php',
    '/',
    '/common.js',
    '/index.css',
    '/index.html',
    '/index.js',
    '/lang_en.js',
    '/lang_pl.js',
    '/map.css',
    '/map.html',
    '/map.js',
    '/serviceworker-install.js',
    'https://code.jquery.com/jquery-3.1.1.min.js',
    'https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList',
    'https://openlayers.org/en/v4.1.0/build/ol.js'
];
var self = this;
this.addEventListener('install', event => {
    event.waitUntil(
        caches.open(CACHE).then(cache => {
            return cache.addAll(CACHE_RESOURCES);
        })
    );
});
this.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => response || fetch(event.request))
    );
    if(event.request.url.endsWith('/version.php')) {
        event.waitUntil(
            Promise.all([
                caches.open(CACHE),
                fetch(event.request)
            ]).then(results => {
                var cache = results[0];
                var v2 = results[1];
                var v2copy = v2.clone();
                return Promise.all([
                    cache.match(event.request).then(v1 => v1.json()),
                    v2copy.json()
                ]).then(results => {
                    var v1json = results[0];
                    var v2json = results[1];
                    return updateCache(cache, v1json, v2json).then(_ => cache.put(event.request, v2)).then(function() {
                        console.log('Service Worker: update successful!');
                        self.skipWaiting();
                        postMessage({action: 'updated'});
                    });
                });
            }).catch(function(error) {
                console.log('Service Worker: update failed: ', error);
                postMessage({action: 'updateFailed'});
            })
        );
    }
});
this.addEventListener('activate', event => {
    event.waitUntil(
        caches.keys().then(keyList => Promise.all(
            keyList.map(key => {
                if (key != CACHE) {
                    return caches.delete(key);
                }
            })
        )).then(caches.open(CACHE)).then(cache => cache.keys()).then(keys =>
            console.log(keys)
            /*Promise.all(
            keys.map(key => {
                console.log(key);
                if(!(key in CACHE_RESOURCES)) {
                    //return cache.delete(key);
                }
            })*/
        )
    );
});
function postMessage(message) {
    self.clients.matchAll().then(clients => {
        clients.forEach(client => {
            client.postMessage(message);
        });
    });
}
function updateCache(cache, cachedVersion, currentVersion) {
    var remove = [];
    var add = [];
    for(var cachedFile in cachedVersion) {
        if(!currentVersion[cachedFile]) {
            remove.push('/' + cachedFile);
        } else if(cachedVersion[cachedFile] != currentVersion[cachedFile]) {
            add.push('/' + cachedFile);
        }
    }
    for(var currentFile in currentVersion) {
        if(CACHE_RESOURCES.indexOf('/' + currentFile) === -1) {
            continue;
        } else if(!cachedVersion[currentFile]) {
            add.push('/' + currentFile);
        }
    }
    console.log('Service Worker: updating files: ', add);
    console.log('Service Worker: deleting files: ', remove);
    return cache.addAll(add).then(function() {
        return Promise.all(
            remove.map(filename => {
                return caches.delete(filename)
            })
        );
    });
}
this.addEventListener('message', function(event) {
    switch(event.data.action) {
        case 'skipWaiting':
            self.skipWaiting();
        break;
    }
});
version.php
@@ -1,2 +1,9 @@
<?php
echo max(array_map('filemtime', glob('*.{html,js,css}', GLOB_NOSORT|GLOB_BRACE)));
$files = glob('*.{html,js,css}', GLOB_NOSORT|GLOB_BRACE);
echo json_encode(
    array_combine(
        $files,
        array_map('filemtime', $files)
    )
);