CruisersWiki:Ol3chartlet.js

From CruisersWiki

(Difference between revisions)
Jump to: navigation, search
(walkLayers)
 
(158 intermediate revisions not shown)
Line 1: Line 1:
 +
// <pre>
/*
/*
   ol3Chartlet.js
   ol3Chartlet.js
Line 6: Line 7:
*/
*/
-
addOnloadHook(function() {
+
loadCss( 'https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.5.0/ol-debug.css' )
-
    var $chartlets = $('.ol3-chartlet');
+
loadJs( 'https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.5.0/ol-debug.js' ) // use debug version, to allow patch below
-
     if ($chartlets.length === 0) {
+
.then( function () {
-
         return;
+
    // try to recover from /extensions/TreeAndMenu/dtree.js overwriting Node
 +
     if (Node.ELEMENT_NODE === undefined) {
 +
         if (document.firstElementChild.__proto__.ELEMENT_NODE == 1) {
 +
            Node = document.firstElementChild.__proto__;
 +
        } else {
 +
            Node.ELEMENT_NODE = 1
 +
        }
 +
        ol.xml.isNode = function(value) {
 +
            //  return value instanceof Node;
 +
            return typeof value.nodeName === "string";
 +
        };
     }
     }
-
 
+
   
-
     var standalone_div = $('#ol3-chartlet-standalone')[0];
+
     var walkLayers = function ( item, action ) {
-
     var standalone = !! standalone_div;
+
        if ( item.getLayers )
-
 
+
            item.getLayers().forEach(
-
     var nx = {
+
                function ( i ) {
-
         navKey: 'Navionics_webapi_00572',
+
                    walkLayers( i, action )
-
         domain: 'www.cruiserswiki.org',
+
            })
-
         navToken: null,
+
        else
-
        BASE_TILE_SERVER: '//backend.navionics.io',
+
            action( item )
-
        TILE_SUFFIX: '/tile/{z}/{x}/{y}',
+
     }
-
         KEY_REQ_SUFFIX: '/tile/get_key',
+
   
 +
     var Navionics = {
 +
         token: null,
 +
        KEY: 'Navionics_webapi_00572',
 +
         DOMAIN: 'www.cruiserswiki.org',
 +
         TILE_URL: 'https://tile{1-5}.navionics.com/tile/{z}/{x}/{y}',
 +
         TOKEN_URL: 'https://tile1.navionics.com/tile/get_key',
         MAX_RESOLUTION: 20480,
         MAX_RESOLUTION: 20480,
         MIN_RESOLUTION: 0.625,
         MIN_RESOLUTION: 0.625,
-
        disclaimer_msg: '&copy; Navionics <a href="http://www.navionics.com/en/acknowledgements" target="_new" class="navionics-acknowledgements">Acknowledgements</a> | Not to be used for navigation',
 
-
    };
 
-
    nx.init = function(callback) {
+
         disclaimer_msg: '', //'<b>&copy; Navionics</b> <a href="http://www.navionics.com/en/acknowledgements" target="_new" class="navionics-acknowledgements">Acknowledgements</a> | Not to be used for navigation',
-
         // set location for Navionics images
+
        depthUnits: {
-
        //~ $('body').attr('data-root', 'http://webapiv2.navionics.com/dist/webapi/images');
+
            'm': 1, 'metre': 1, 'meter': 1,
 +
            'ft': 2, 'feet': 2,
 +
            'fathom': 3,
 +
        },
-
         if ( nx.navToken ) {
+
         attribution: [
-
             callback();
+
             '<div class="navionics-attribution navionics-off">',
-
        } else {
+
                '<a class="navionics-logo" href="http://www.navionics.com/" target="_blank">',
-
            // requestNavToken
+
                    '<span></span>',
-
            var targetUrl = nx.BASE_TILE_SERVER + nx.KEY_REQ_SUFFIX;
+
                '</a>',
-
             $.ajax({
+
                '<div class="navionics-acknowledgements">',
-
                url: targetUrl + '/' + nx.navKey + '/' + nx.domain,
+
                    '<div>',
-
                 async: !!callback,
+
                        '<a href="http://www.navionics.com/en/acknowledgements" target="_blank">',
 +
                            'Acknowledgements',
 +
                        '</a>',
 +
                        '<span> | Not to be used for navigation</span>',
 +
                    '</div>',
 +
                '</div>',
 +
             '</div>'
 +
        ].join(''),
 +
    }
 +
 
 +
    Navionics.getToken = function () {
 +
        if ( Navionics.token != null )
 +
            return Navionics.token
 +
        var url = Navionics.TOKEN_URL  + '/' + Navionics.KEY + '/' + Navionics.DOMAIN
 +
        return Navionics.token = Promise.resolve( $.ajax({
 +
                 url: url,
                 crossDomain: true,
                 crossDomain: true,
                 dataType: 'text',
                 dataType: 'text',
-
                 cache: false,
+
                 //cache: false,
-
                error: function() {
+
            })
-
                  return console.log(arguments);
+
        )
-
                },
+
    }
-
                success: function(data, textStatus, jqXHR) {
+
 
-
                    nx.navToken = data;
+
    Navionics.source = function ( options ) {
-
                    callback();
+
        options = options || {}
-
                }
+
        var sourceOptions = {
-
             });
+
            crossOrigin: 'anonymous',
 +
             maxResolution: Navionics.MAX_RESOLUTION,
 +
            minResolution: Navionics.MIN_RESOLUTION
         }
         }
-
    };
+
        ol.source.XYZ.call( this, sourceOptions )
-
    nx.formatTileUrl = function (options) { // sonar, overlay, depthUnit, safeDepth, showUGC
+
         var self = this
-
         options = options || {};
+
         Navionics.getToken()
-
         sType = options.sonar ? 1 : 0;
+
         .then( function ( token ) {
-
         sAlpha = options.overlay ? 'TRUE' : 'FALSE';
+
            options.token = token
-
        sUgc = options.showUGC ? 'TRUE' : 'FALSE';
+
             var url = Navionics.getTileUrl( options )
-
        sDepthUnit = {
+
            self.setUrl( url )
-
             'm': 1, 'metre': 1, 'meter': 1,
+
         })
-
            'ft': 2, 'feet': 2,
+
        .catch( function( err ) {
-
            'fathom': 3,
+
          return console.log( 'Navionics.getToken', err )
-
        } [options.depthUnit] || 1;
+
         })
-
        // sDepthLevel = (options.safeDepth || 10).toFixed(2);
+
     }
-
         sDepthLevel = (options.safeDepth || 20).toFixed(0);
+
-
        params = $.param({
+
-
            LAYERS: 'config_' + sDepthUnit + '_' + sDepthLevel + '_' + sType,
+
-
            TRANSPARENT: sAlpha,
+
-
            UGC: sUgc,
+
-
            navtoken: nx.navToken
+
-
         });
+
-
        return nx.BASE_TILE_SERVER + nx.TILE_SUFFIX + '?' + params;
+
-
     };
+
-
     nx.getTileUrl = function (options, callback) { // sonar, overlay, depthUnit, safeDepth, showUGC
+
     ol.inherits( Navionics.source, ol.source.XYZ )
-
        nx.init(function () {
+
-
            callback(nx.formatTileUrl(options))
+
-
        });
+
-
    };
+
-
     nx.new_source = function (options) {
+
     Navionics.getTileUrl = function ( options ) { // sonar, overlay, depthUnit, safeDepth, showUGC
-
         var source = new ol.source.XYZ({
+
         options = options || {}
-
             crossOrigin: 'anonymous',
+
        var layerConfig = [
-
             attributions: [
+
             'config',
-
                new ol.Attribution({
+
             Navionics.depthUnits[ options.depthUnit ] || 1,
-
                    html: nx.disclaimer_msg
+
            ( options.safeDepth || 20 ).toFixed( 2 ),
-
                })
+
            options.sonar ? 1 : 0
-
             ],
+
        ]
-
             maxResolution: nx.MAX_RESOLUTION,
+
        params = $.param({
-
             minResolution: nx.MIN_RESOLUTION
+
            LAYERS: layerConfig.join('_'),
-
         });
+
             TRANSPARENT: !! options.transparency,
 +
             UGC: !! options.showUGC,
 +
             navtoken: options.token
 +
         })
 +
        return Navionics.TILE_URL + '?' + params
 +
    }
-
        nx.getTileUrl(
+
    Navionics.monitorAttribution = function ( map ) {
-
             options,
+
        var layers = []
-
             function (url) {
+
 
-
                 source.setUrl(url);
+
        function checkLayer ( l ) {
 +
             var title = l.get( 'title' )
 +
             if ( title && title.indexOf( 'Navionics' ) != -1 ) {
 +
                 layers.push( l )
             }
             }
-
         );
+
         }
 +
        walkLayers( map, checkLayer )
-
         return source;
+
         if ( layers.length == 0 )
-
    };
+
            return
 +
        var attribution = $( Navionics.attribution )
 +
        var control = new ol.control.Control({ element: attribution.get( 0 ) })
 +
        map.addControl( control )
-
    var esri = {};
+
        function attributionVisibility ( evt ) {
-
    esri.uris = {
+
            // console.log( 'change:visible', evt )
-
        'satellite': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
+
            var visible = this.getVisible()
-
        'topo': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
+
            attribution.toggleClass( 'navionics-off', ! visible )
-
        'light-gray': "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer",
+
         }
-
        'dark-gray': "http://services.arcgisonline.com/arcgis/rest/services/Canvas/World_Dark_Gray_Base/MapServer",
+
-
        'streets': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
+
-
        'hybrid': "http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer",
+
-
         'oceans': "http://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Reference/MapServer",
+
-
        'national-geographic': "http://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer",
+
-
    };
+
-
    function ol3Chartlet() {
+
        for ( var i=0, li=layers.length; i < li; i++ ) {
-
        console.log('ol3Chartlet');
+
            var layer = layers[ i ]
-
        var $chartlet = $(this);
+
            layer.on( 'change', attributionVisibility.bind( layer ))
-
        var params = parseParams(standalone && location.hash ? location.hash.slice(1) : $chartlet.text());
+
            layer.on( 'change:visible', attributionVisibility.bind( layer ))
 +
        }
 +
    }
-
        var iconFeature = new ol.Feature({
+
    var Esri = {
-
             geometry: new ol.geom.Point(ol.proj.transform([params.lon, params.lat], 'EPSG:4326', 'EPSG:3857')),
+
        uri_map: {
-
             name: 'Test marker',
+
             'satellite': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
-
         });
+
            'topo': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
 +
            'terrain': 'http://server.arcgisonline.com/arcgis/rest/services/World_Terrain_Base/MapServer',
 +
            'physical': 'http://services.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer',
 +
            'relief': 'http://server.arcgisonline.com/arcgis/rest/services/World_Shaded_Relief/MapServer',
 +
            'light-gray': "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer",
 +
            'dark-gray': "http://services.arcgisonline.com/arcgis/rest/services/Canvas/World_Dark_Gray_Base/MapServer",
 +
            'street': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
 +
            'places': "http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer",
 +
            'oceans-reference': "http://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Reference/MapServer",
 +
            'oceans': 'http://server.arcgisonline.com/arcgis/rest/services/Ocean_Basemap/MapServer',
 +
            'national-geographic': "http://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer",
 +
            'transportation': "https://server.arcgisonline.com/ArcGIS/rest/services/Reference/World_Transportation/MapServer"
 +
        },
 +
    }
 +
/*
 +
    Esri.source = function ( id ) {
 +
        ol.source.TileArcGISRest.call( this, {
 +
             url: Esri.uri_map[ id ],
 +
            params: {
 +
                FORMAT: 'JPG',
 +
                TRANSPARENT: false,
 +
            },
 +
            attributions: [
 +
                new ol.Attribution({
 +
                    html: 'Tiles by ESRI <a href="' + Esri.uri_map[ id ] + '">Acknowledgements</a>'
 +
                })
 +
            ]
 +
         })
 +
    };
-
        iconFeature.setStyle(
+
    ol.inherits( Esri.source, ol.source.TileArcGISRest )
-
            new ol.style.Style({
+
*/
-
                image: new ol.style.Icon({
+
    Esri.source = function ( id ) {
-
                    anchor: [0, 1],
+
        ol.source.XYZ.call( this, {
-
                    anchorXUnits: 'fraction',
+
            url: Esri.uri_map[ id ] + '/tile/{z}/{y}/{x}',
-
                    anchorYUnits: 'fraction',
+
            crossOrigin: null,
-
                    // anchorYUnits: 'pixels',
+
            attributions: [
-
                    opacity: 1,
+
                new ol.Attribution({
-
                     src: '/images/e/e7/Flag_icon.png'
+
                     html: 'Tiles by ESRI <a href="' + Esri.uri_map[ id ] + '">Acknowledgements</a>'
                 })
                 })
-
             })
+
             ],
-
         );
+
         })
 +
    };
-
        // var vectorLayer = new ol.layer.Vector({
+
    ol.inherits( Esri.source, ol.source.XYZ )
-
        //    title: 'POI',
+
-
        //    source: new ol.source.Vector({
+
-
        //        features: [iconFeature]
+
-
        //    })
+
-
        // });
+
-
        var openseamap = new ol.layer.Tile({
+
    function ol3Chartlet( chartlet_div, standalone ) {
-
            title: 'OpenSeaMap',
+
        this.styleLoadHooks = [];
-
            visible: false,
+
-
            source: new ol.source.XYZ({
+
-
                url: 'http://t1.openseamap.org/seamark/{z}/{x}/{y}.png',
+
-
                crossOrigin: null,
+
-
                attributions: [
+
-
                    new ol.Attribution({
+
-
                        html: 'Tiles by <a href="http://www.openseamap.org">OpenSeaMap</a>'
+
-
                    })
+
-
                ],
+
-
            })
+
-
        });
+
-
         var nx_layer = new ol.layer.Tile({
+
         console.log('ol3Chartlet');
-
            title: 'Navionics',
+
-
            type: 'base',
+
-
            source: nx.new_source()
+
-
        });
+
-
         var nx_layer_ovl = new ol.layer.Tile({
+
         this.params = parseParams(
-
             title: 'Navionics',
+
             standalone && location.hash
-
             // type: 'base',
+
             ? decodeURI( location.hash.slice( 1 ))
-
             // visible: false,
+
             : $( chartlet_div ).text()
-
            source: nx.new_source({overlay:true})
+
         )
-
         });
+
        this.params.standalone = standalone
 +
       
 +
        var layers = this.createLayers()
-
         var esri_layer = new ol.layer.Tile({
+
         var map = this.map = new ol.Map({
-
             title: 'ESRI World Imagery',
+
             target: chartlet_div,
-
             type: 'base',
+
             layers: layers,
-
             source: new ol.source.TileArcGISRest({
+
             view: new ol.View({
-
                 url: esri.uris.satellite,
+
                 center: ol.proj.transform([this.params.lon, this.params.lat], 'EPSG:4326', 'EPSG:3857'),
-
                params: {
+
                 zoom: this.params.zoom
-
                    FORMAT: 'JPG',
+
-
                    TRANSPARENT: false,
+
-
                 },
+
-
                attributions: [
+
-
                    new ol.Attribution({
+
-
                        html: 'Powered by ESRI <a href="' + esri.uris.satellite + '">Acknowledgements</a>'
+
-
                    })
+
-
                ]
+
             }),
             }),
-
        });
+
            interactions: ol.interaction.defaults(
-
 
+
                 standalone ? {}
-
        var view = new ol.View({
+
                : {
-
                center: ol.proj.transform([params.lon, params.lat], 'EPSG:4326', 'EPSG:3857'),
+
                     mouseWheelZoom:false,
-
                 zoom: params.zoom
+
                     // doubleClickZoom :false,
-
            });
+
                 }
-
 
+
            ),
-
        var map = new ol.Map({
+
-
            target: this,
+
-
            layers: [
+
-
                new ol.layer.Group({
+
-
                     'title': 'Base',
+
-
                     layers: [
+
-
                        new ol.layer.Tile({
+
-
                            title: 'OSM',
+
-
                            type: 'base',
+
-
                            source: new ol.source.OSM()
+
-
                        }),
+
-
                        esri_layer,
+
-
                        new ol.layer.Tile({
+
-
                            title: 'Water color',
+
-
                            type: 'base',
+
-
                            source: new ol.source.Stamen({
+
-
                                layer: 'watercolor'
+
-
                            })
+
-
                        }),
+
-
                        //~ new ol.layer.Vector({
+
-
                            //~ title: 'Plain background',
+
-
                            //~ type: 'base',
+
-
                            //~ source: new ol.source.Vector({
+
-
                            //~ })
+
-
                        //~ }),
+
-
                    ]
+
-
                 }),
+
-
                new ol.layer.Group({
+
-
                    title: 'Layers',
+
-
                    layers: [
+
-
                        openseamap,
+
-
                        nx_layer_ovl
+
-
                    ]
+
-
                })
+
-
            ],
+
-
            view: view,
+
             controls: ol.control.defaults({
             controls: ol.control.defaults({
-
                 attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
+
                 attributionOptions: /** @type {olx.control.AttributionOptions} */ {
                     collapsible: false
                     collapsible: false
 +
                }
 +
            }).extend([
 +
                new ol.control.FullScreen(),
 +
                new ol.control.ScaleLine({
 +
                    units: 'nautical'
                 })
                 })
-
             })
+
             ])
         });
         });
-
         map.addControl(new ol.control.ScaleLine({
+
         this.restoreVisibility()
-
            units: 'nautical'
+
-
        }));
+
-
         loadWikiCss('MediaWiki:Ol3-layerswitcher.css');
+
         Navionics.monitorAttribution( map )
-
         loadWikiScript("MediaWiki:Ol3-layerswitcher.js", function () {
+
 
 +
        // loadWikiCss( 'CruisersWiki:Ol3-layerswitcher.css' )
 +
         // loadWikiJs( 'CruisersWiki:Ol3-layerswitcher.js')
 +
        loadCss( 'https://cdn.jsdelivr.net/gh/walkermatt/[email protected]/src/ol3-layerswitcher.css' )
 +
        loadJs( 'https://cdn.jsdelivr.net/gh/walkermatt/[email protected]/src/ol3-layerswitcher.js' )
 +
        .then( function () {
             var layerSwitcher = new ol.control.LayerSwitcher({
             var layerSwitcher = new ol.control.LayerSwitcher({
-
                 // tipLabel: 'Légende' // Optional label for button
+
                 // tipLabel: 'Legend' // Optional label for button
             });
             });
             map.addControl(layerSwitcher);
             map.addControl(layerSwitcher);
-
         });
+
         })
         if (standalone) {
         if (standalone) {
-
             initStandalone (map, params);
+
             this.params.page && this.addPoiLayer();
 +
            this.trackHash();
 +
            this.addGraticule();
 +
            this.addCentreControl( map );
 +
 
 +
        } else if (this.params.pageFeatures) {
 +
            this.addPoiLayer();
         }
         }
 +
 +
        this.addStoreVisibilityToolstoreVisibilitystoreVisibility()
     };
     };
-
     function initStandalone (map, params) {
+
     ol3Chartlet.prototype.createLayers = function () {
 +
        var layerDefs = [
 +
            // overlays
 +
            [ 'o', 's', '', 'Navionics Boating', new Navionics.source({ transparency: true }) ],
 +
            [ 'o', '', '', 'ESRI Transportation', new Esri.source( 'transportation' ) ],
 +
            [ 'o', '', 'i', 'ESRI Boundaries and Places', new Esri.source( 'places' ) ],
 +
            [ 'o', '', 'i', 'OpenSeaMap', new ol.source.XYZ({
 +
                        url: 'http://t1.openseamap.org/seamark/{z}/{x}/{y}.png',
 +
                        crossOrigin: null,
 +
                        attributions: [
 +
                            new ol.Attribution({
 +
                                html: 'Tiles by <a href="http://www.openseamap.org">OpenSeaMap</a>'
 +
                            })
 +
                        ],
 +
                    })
 +
            ],
 +
            // baselayers
 +
            [ '-b', '', '', 'Navionics', new Navionics.source() ],
 +
            [ 'b', 's', '', 'Water color', new ol.source.Stamen({
 +
                        layer: 'watercolor',
 +
                        //~ url: 'http://tile.stamen.com/watercolor/{z}/{x}/{y}.jpg'
 +
                        //~ url: 'https://stamen-tiles-{a-d}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg'
 +
                    })
 +
            ],
 +
            [ 'b', '', '', 'OpenStreetMap',  new ol.source.OSM() ],
 +
            [ 'b', '', 'i', 'ESRI World Imagery',  new Esri.source( 'satellite' ) ],
 +
            [ '-b', '', '', 'ESRI World Street Map', new Esri.source( 'street' ) ],
 +
            [ '-b', '', '', 'OSM base', new ol.source.OSM({
 +
                        crossOrigin: null,
 +
                        url: 'http://{a-c}.tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png'
 +
                    })
 +
            ],
 +
            [ '-b', '', '', new ol.layer.Vector({
 +
                    title: 'No background',
 +
                    source: new ol.source.Vector({})
 +
            })],
 +
        ]
 +
       
 +
        var baseLayers = []
 +
        var overlays = []
 +
 
 +
        for (var i = 0; i < layerDefs.length; i++) {
 +
            var row = layerDefs[ i ]
 +
            var title = row[ 3 ]
 +
            var l = typeof title != 'string' ? title : new ol.layer.Tile({
 +
                title: title,
 +
                source: row[ 4 ]
 +
            })
 +
 
 +
            l.set( 'visible', this.params.standalone ? row[ 1 ] == 's' : row[ 2 ] == 'i' )
 +
            switch ( row[ 0 ] ) {  
 +
                case 'b':
 +
                    l.set( 'type' , 'base' )
 +
                    baseLayers.push( l )
 +
                    break
 +
                case 'o':
 +
                    overlays.push( l )
 +
            }
 +
        }
 +
/*
 +
        this.baselayersGroupName = 'Base';
 +
        this.overlaysGroupName = 'Overlays';
 +
        var layers = [
 +
            new ol.layer.Group({
 +
                title: this.baselayersGroupName,
 +
                layers: baseLayers
 +
            }),
 +
            new ol.layer.Group({
 +
                    title: this.overlaysGroupName,
 +
                    layers: overlays
 +
            })
 +
        ]
 +
*/
 +
        var layers = baseLayers.concat( overlays )
 +
        return layers
 +
    }
 +
   
 +
    ol3Chartlet.prototype.addCentreControl = function ( map ) {
 +
        var elem = $( '<div class="chartlet-centre"></div>' ).get( 0 )
 +
        var control = new ol.control.Control({ element: elem })
 +
        map.addControl( control )
 +
    }
 +
 
 +
    // add to a layer group
 +
    ol3Chartlet.prototype.addNonBaseLayer = function (new_layer) {
 +
        this.map.getLayers().push( new_layer )
 +
/*
 +
        this.map.getLayers().forEach(
 +
            function(layer) {
 +
                if (layer.get('title') === this.overlaysGroupName) {
 +
                    layer.getLayers().push(new_layer);
 +
                }
 +
            }
 +
        )
 +
*/
 +
    }
 +
    ol3Chartlet.prototype.trackHash = function() {
         var doNotTrackHash = false;
         var doNotTrackHash = false;
         var setHashTimeoutID = null;
         var setHashTimeoutID = null;
-
         var view = map.getView();
+
         var view = this.map.getView();
 +
        var params = this.params;
         var onChangeCenterZoom = function () {
         var onChangeCenterZoom = function () {
Line 276: Line 386:
                 //console.log(center, zoom);
                 //console.log(center, zoom);
-
                 location.hash= 'lat=' + round(params.lat) + '|lon=' + round(params.lon) + '|zoom=' + params.zoom
+
                 location.hash = 'lat=' + round(params.lat) + '|lon=' + round(params.lon)
 +
                    + '|zoom=' + params.zoom
                     + (params.layer ? '|layer=' + params.layer : '')
                     + (params.layer ? '|layer=' + params.layer : '')
                     + (params.page ? '|page=' + params.page : '');
                     + (params.page ? '|page=' + params.page : '');
Line 285: Line 396:
             }
             }
             setHashTimeoutID = window.setTimeout(setHash, setHashDelay);
             setHashTimeoutID = window.setTimeout(setHash, setHashDelay);
-
         };
+
         }
         view.on('change:center', onChangeCenterZoom);
         view.on('change:center', onChangeCenterZoom);
         view.on('change:resolution', onChangeCenterZoom);
         view.on('change:resolution', onChangeCenterZoom);
-
         var trackHash = function trackHash() {
+
         window.addEventListener('hashchange',  function () {
             if (!location.hash || doNotTrackHash) {
             if (!location.hash || doNotTrackHash) {
                 doNotTrackHash = false;
                 doNotTrackHash = false;
Line 301: Line 412:
                 view.setZoom(params.zoom);
                 view.setZoom(params.zoom);
             }
             }
-
         };
+
         })
 +
    }
-
         window.onhashchange = trackHash;
+
    // Create the graticule
 +
    ol3Chartlet.prototype.addGraticule = function () { // after http://map.openseamap.org/javascript/grid_wgs.js
 +
         var this_ = this;
 +
        loadWikiJs( 'CruisersWiki:Ol3chartlet-graticule.js' )
 +
        .then( function () {
 +
            var layer = graticuleLayer(this_.map);
 +
            this_.addNonBaseLayer(layer);
 +
        })
 +
        /*
 +
        var graticule = new ol.Graticule({
 +
            map: this.map,
 +
            // the style to use for the lines, optional.
 +
            strokeStyle: new ol.style.Stroke({
 +
                color: 'rgba(255,120,0,0.9)',
 +
                width: 2,
 +
                lineDash: [0.5, 4]
 +
            })
 +
        });
 +
        // graticule.setMap(this.map);
 +
        */
 +
    };
-
        // load kml
+
    ol3Chartlet.prototype.addPoiLayer = function () {
-
        function add_kml_layer (kml) {
+
        var options = $.extend({}, this.params);
-
            if (!kml)
+
-
                return;
+
-
            // kml_uri='http://openlayers.org/en/v3.13.1/examples/data/kml/2012-02-10.kml';
+
-
            var format = new ol.format.KML({
+
-
                showPointNames: false,
+
-
            });
+
-
            var loader = function(extent, resolution, projection) {
+
-
                /**
+
-
                * @param {ol.Extent} extent Extent.
+
-
                * @param {number} resolution Resolution.
+
-
                * @param {ol.proj.Projection} projection Projection.
+
-
                * @this {ol.source.Vector|ol.VectorTile}
+
-
                */
+
-
                var xml_tree = ol.xml.parse(kml);
+
-
                var features = format.readFeatures(
+
        var loader = function(extent, resolution, projection) {
-
                    xml_tree,
+
            /**
-
                    {featureProjection: projection}
+
            * @param {ol.Extent} extent Extent.
-
                );
+
            * @param {number} resolution Resolution.
 +
            * @param {ol.proj.Projection} projection Projection.
 +
            * @this {ol.source.Vector|ol.VectorTile}
 +
            */
 +
            options.projection = projection;
 +
            options.addFeature = addFeature;
-
                 this.addFeatures(features);
+
            loadWikiJs(
-
            };
+
                 $('.chartlet-test').length == 0 ? 'CruisersWiki:Ol3chartlet-features.js' : 'CruisersWiki:Ol3chartlet-features-test.js'
-
            var kml_layer = new ol.layer.Vector({
+
            )
-
                title: 'POI',
+
            .then( function () {
-
                visible:true,
+
                 loadFeatures(options);
-
                source: new ol.source.Vector({
+
             })
-
                    loader: loader,
+
        };
-
                 })
+
-
             });
+
-
            // add to the proper layer group
+
        var source = new ol.source.Vector({
-
            map.getLayers().forEach(
+
            loader: loader,
-
                function(layer) {
+
        });
-
                    if (layer.get('title') === 'Layers') {
+
-
                        layer.getLayers().push(kml_layer);
+
-
                    }
+
-
                }
+
-
            );
+
-
        }
+
-
         // load coord grid
+
         var layer = new ol.layer.Vector({
-
        function add_coord_grid () { // after http://map.openseamap.org/javascript/grid_wgs.js
+
            title: 'POI',
 +
            visible: true,
 +
            style: styleFunction,
 +
            source: source,
 +
        });
-
            var gridSizeText = null;
+
        var this_ = this;
-
            var gridSizeDiv = null;
+
        var defferedFeatures = [];
 +
        function addFeature (feature) {
 +
            if (!this_.styles) {
 +
                defferedFeatures.push(feature);
 +
                return;
 +
            }
 +
            if (defferedFeatures) {
 +
                source.addFeatures(defferedFeatures);
 +
                defferedFeatures = null;
 +
            }
 +
            if (feature) {
 +
                source.addFeature(feature);
 +
            }
 +
        };
-
            var zoomUnits = null;
+
        this.styleLoadHooks.push(addFeature);
-
             // in Winkelsekunden
+
        function styleFunction (feature, resolution) {
-
             var gridUnits = [
+
             var category = feature.get('category') || 'other';
-
                 //3,        // 0.05'
+
             var geom = feature.getGeometry();
-
                 6, 12, 30,  // 0.1' 0.2' 0.5'
+
            var style;
-
                 1*60, 2*60, 3*60, 5*60, 10*60, 20*60, 30*60,
+
            if (geom.getType() == 'Point') {
-
                 1*3600, 2*3600, 3*3600, 4*3600, 6*3600, 10*3600, 15*3600, 30*3600, 45*3600];
+
                 var styleOptions = {
 +
                    //zIndex: 2
 +
                };
 +
                options.icons && (styleOptions.image = this_.getStyle(category, 'Icon'));
 +
                 options.captions && (styleOptions.text = this_.getTextStyle(category, feature.get('name')));
 +
                style = new ol.style.Style(styleOptions);
 +
            } else {
 +
                 style = new ol.style.Style({
 +
                    fill: this_.getStyle(category, 'Fill'),
 +
                    stroke: this_.getStyle(category, 'Stroke'),
 +
                 });
 +
            }
 +
            return style;
 +
        };
-
            var gridPixelDistance = 100;
+
        this.addNonBaseLayer(layer);
-
            //---------------------------------------------------------
+
//       loadWikiCss('CruisersWiki:tOl3-popup.css');
-
            // Find matching grid unit (minutes) or return null
+
//       loadWikiJs( 'CruisersWiki:tOl3-popup.js' )
-
            //---------------------------------------------------------
+
        loadCss( 'https://cdn.jsdelivr.net/gh/walkermatt/ol3-[email protected]/src/ol3-popup.css' );
 +
        loadJs( 'https://cdn.jsdelivr.net/gh/walkermatt/ol3-[email protected]/src/ol3-popup.js' )
 +
        .then( this.initPopups.bind( this ))
-
            var getGridUnit = function (distance) {
+
        this.trackPointer();
 +
        this.highlightFeatures();
 +
        this.loadStyles();
 +
    };
-
                if (zoomUnits)
+
    ol3Chartlet.prototype.styles = null;
-
                    return zoomUnits[map.getView().getZoom()];
+
    ol3Chartlet.prototype.styleLoadHooks = null;
-
                for (var i=0; i<gridUnits.length; i++) {
+
    ol3Chartlet.prototype.loadStyles = function () {
-
                    if (distance < gridUnits[i])
+
        var this_ = this;
-
                        return gridUnits[i];
+
        loadWikiJs(
-
                }
+
            $('.chartlet-test').length == 0 ? 'CruisersWiki:Ol3chartlet-styles.js' : 'CruisersWiki:Ol3chartlet-styles-test.js'
-
                return null;
+
        )
-
            };
+
        .then( function () { return loadStyles() })
 +
        .then( function (styles) {
 +
            this_.styles = styles;
 +
            var hooks = this_.styleLoadHooks;
 +
            this_.styleLoadHooks = [];
 +
            hooks.map( function(fn) { fn() });
 +
        });
 +
    };
-
            //---------------------------------------------------------
+
    ol3Chartlet.prototype.getStyle = function (category, subType) {
-
            // Format gridsize
+
        var style = this.styles[category + '.' + subType];
-
            //---------------------------------------------------------
+
        return style ? style : this.styles['default'  + '.' + subType];
 +
    }
-
            var dd = function (n) {
+
    ol3Chartlet.prototype.getTextStyle = function (category, text) {
-
                return parseInt(n) >= 10 ? n : '0'+n;
+
        var style = this.getStyle(category, 'Text').clone();
-
            };
+
        style.setText(text);
 +
        return style;
 +
    }
-
            var formatGridSize = function (s) {
+
    ol3Chartlet.prototype.isClickableLayer = function (layer) {
-
                var h = Math.floor(s / 3600);
+
        return ! layer.get('noclickable');
-
                var m = s % 3600 / 60;
+
    };
-
                return (h ? h + "°" : "") + (m ? m + "'" : "");
+
-
            };
+
-
            var formatDegrees = function (s, unit) {
+
    ol3Chartlet.prototype.initPopups = function () {
-
                return Math.floor(s / 3600) + "°"
+
        var map = this.map;
-
                    + (unit % 3600 ? dd(s % 3600 / 60) + "'" : "")
+
        var popup = new ol.Overlay.Popup();
-
            };
+
        map.addOverlay(popup);
-
            var loader = function(extent, resolution, projection) {
+
        var popTemplate =
-
                /**
+
            '<div class="cw-popup-name"><a href="{href}" target="_blank">{name}</a></div>\n' +
-
                * @param {ol.Extent} extent Extent.
+
            '<div class="cw-popup-category">{category}</div>\n' +
-
                * @param {number} resolution Resolution.
+
            '<div class="cw-popup-content">{content}</div>';
-
                * @param {ol.proj.Projection} projection Projection.
+
-
                * @this {ol.source.Vector|ol.VectorTile}
+
-
                */
+
-
                 var lonlat_extent = ol.proj.transformExtent(extent, view.getProjection(), 'EPSG:4326');
+
        // display popup on click
 +
        map.on('click', function(evt) {
 +
            var feature = map.forEachFeatureAtPixel(
 +
                evt.pixel,
 +
                function(feature, layer) {
 +
                  return feature;
 +
                },
 +
                { layerFilter: this.isClickableLayer }
 +
            );
 +
            if (feature && ! feature.get('noclickable')) {
 +
                 var data = {
 +
                    href: feature.get("url"),
 +
                    name: feature.get("name"),
 +
                    category: feature.get("category"),
 +
                    content: feature.get("description"),
 +
                };
 +
                popup.show(evt.coordinate, format(popTemplate, data));
 +
            } else {
 +
                popup.hide();
 +
            }
 +
        });
 +
    };
-
                //---------------------------------------------------------
+
    ol3Chartlet.prototype.trackPointer = function () {
-
                // Grid unit
+
        // change mouse cursor when over marker
-
                //---------------------------------------------------------
+
        var map = this.map;
 +
        map.on('pointermove', function(e) {
 +
            //~ if (e.dragging) {
 +
              //~ $(element).popover('destroy');
 +
              //~ return;
 +
            //~ }
 +
            var pixel = map.getEventPixel(e.originalEvent);
 +
            var hit = map.hasFeatureAtPixel(pixel, this.isClickableLayer);
 +
            map.getTarget().style.cursor = hit ? 'pointer' : '';
 +
        });
 +
    };
-
                var seconds = 3600 * (lonlat_extent[3] - lonlat_extent[1]);
+
    ol3Chartlet.prototype.highlightFeatures = function () {
 +
        var map = this.map;
 +
        var highlightStyle;
 +
        this.styleLoadHooks.push(function () {
 +
            highlightStyle = new ol.style.Style({
 +
                fill: this.getStyle('highlight', 'Fill'),
 +
                stroke: this.getStyle('highlight', 'Stroke'),
 +
            });
 +
        }.bind(this));
-
                var unit = getGridUnit (seconds / map.getSize()[1] * gridPixelDistance);
+
        function styleFunction (feature, resolution) {
 +
            var geom = feature.getGeometry();
 +
            if (geom.getType() != 'Point') {
 +
                return highlightStyle;
 +
            }
 +
        }
-
                //---------------------------------------------------------
+
        var highlightOverlay = new ol.layer.Vector({
-
                // Compute grid
+
            source: new ol.source.Vector(),
-
                //---------------------------------------------------------
+
            map: map,
 +
            style: styleFunction
 +
        });
 +
        highlightOverlay.set('noclickable', true);
-
                var x1 = Math.max (-180.0*3600, Math.ceil  (3600 * lonlat_extent[0] / unit) * unit);
+
        var highlight;
-
                var x2 = Math.min (+180.0*3600, Math.floor (3600 * lonlat_extent[2] / unit) * unit);
+
-
                var y1 = Math.max ( -90.0*3600, Math.ceil  (3600 * lonlat_extent[1] / unit) * unit);
+
-
                var y2 = Math.min ( +90.0*3600, Math.floor (3600 * lonlat_extent[3] / unit) * unit);
+
-
                 var features = [];
+
        var highlightFeature = function(evt) {
 +
            if (evt.dragging) {
 +
                 return;
 +
            }
 +
            var pixel = map.getEventPixel(evt.originalEvent);
-
                //---------------------------------------------------------
+
            var feature = map.forEachFeatureAtPixel(pixel, function(feature) {
-
                 // Vertical lines
+
                 return feature;
-
                //---------------------------------------------------------
+
            });
-
                for (var x=x1; x<=x2; x+= unit) {
+
            if (feature !== highlight) {
-
                    var l = new ol.geom.LineString([
+
                if (highlight) {
-
                        ol.proj.transform([x/3600, Math.min(+85, lonlat_extent[3])], 'EPSG:4326', view.getProjection()),
+
                     highlightOverlay.getSource().removeFeature(highlight);
-
                        ol.proj.transform([x/3600, Math.min(+85, lonlat_extent[1])], 'EPSG:4326', view.getProjection())
+
-
                     ]);
+
-
                    var f = new ol.Feature(l);
+
-
                    f.setStyle(new ol.style.Style({
+
-
                        stroke: new ol.style.Stroke({
+
-
                            color: "#666666",
+
-
                            width: 1,
+
-
                            //~ strokeOpacity: 0.8
+
-
                        }),
+
-
                        text: new ol.style.Text({
+
-
                            text: formatDegrees (Math.abs(x), unit),
+
-
                            textAlign: 'end',
+
-
                            textBaseline: 'top',
+
-
                            offsetX: 0,
+
-
                            offsetY: - map.getSize()[1] / 2,
+
-
                            rotation: - Math.PI / 2,
+
-
                            scale: 1.5,
+
-
                            //~ labelAlign: "lt",
+
-
                        }),
+
-
                    }));
+
-
                    features.push (f);
+
                 }
                 }
-
 
+
                 if (feature) {
-
                //---------------------------------------------------------
+
                     highlightOverlay.getSource().addFeature(feature);
-
                // Horizontal lines
+
-
                //---------------------------------------------------------
+
-
 
+
-
                 for (var y=y1; y<=y2; y+=unit) {
+
-
                     var l = new ol.geom.LineString([
+
-
                        ol.proj.transform([Math.max(-180, lonlat_extent[0]), y/3600], 'EPSG:4326', view.getProjection()),
+
-
                        ol.proj.transform([Math.min(+180, lonlat_extent[2]), y/3600], 'EPSG:4326', view.getProjection())
+
-
                    ]);
+
-
                    var f = new ol.Feature(l);
+
-
                    f.setStyle(new ol.style.Style({
+
-
                        stroke: new ol.style.Stroke({
+
-
                            color: "#666666",
+
-
                            width: 1,
+
-
                            //~ strokeOpacity: 0.8
+
-
                        }),
+
-
                        text: new ol.style.Text({
+
-
                            text: formatDegrees (Math.abs(y), unit),
+
-
                            textAlign: 'start',
+
-
                            textBaseline: 'top',
+
-
                            offsetX: - map.getSize()[0] / 2,
+
-
                            offsetY: 0,
+
-
                            rotation: 0,
+
-
                            scale: 1.5,
+
-
                            //~ labelAlign: "lt",
+
-
                        }),
+
-
                    }));
+
-
                    features.push (f);
+
                 }
                 }
 +
                highlight = feature;
 +
            }
 +
        };
-
                this.clear();
+
        map.on('pointermove', highlightFeature);
 +
    };
-
                this.addFeatures(features);
+
    ol3Chartlet.prototype.addStoreVisibilityToolstoreVisibilitystoreVisibility = function () {
-
             };
+
        if ( $( '#cw-save-layers' ).length > 0 )
 +
             return
 +
        var $a = $( '<a id="cw-save-layers" style="cursor:pointer">Save layers</a>' )
 +
            .click( this.storeVisibility.bind( this ))
-
            var coord_grid = new ol.layer.Vector({
+
        $( '#p-tb ul' ).append( $( '<li>' ).append( $a ))
-
                title: 'coord_grid',
+
    }
-
                visible:true,
+
 
-
                source: new ol.source.Vector({
+
    ol3Chartlet.prototype.storeVisibility = function () {
-
                    loader: loader,
+
        var standalone = this.params.standalone
-
                    strategy: ol.loadingstrategy.bbox
+
        var visibility = Storage.get( 'cw-layers-visibility' )
-
                 })
+
       
-
             });
+
        if ( ! visibility || ! visibility[ standalone ] )
 +
            visibility = {
 +
                true: {},
 +
                 false: {},
 +
             }
-
            // add to the proper layer group
+
        function getVisibility ( layer ) {
-
            map.getLayers().forEach(
+
            var name = layer.get( 'title' )
-
                function(layer) {
+
            visibility[ standalone ][ name ] = layer.getVisible()
-
                    if (layer.get('title') === 'Layers') {
+
-
                        layer.getLayers().push(coord_grid);
+
-
                    }
+
-
                }
+
-
            );
+
         }
         }
-
         add_coord_grid ();
+
         walkLayers( this.map, getVisibility )
-
         function init_popups() {
+
         Storage.set( 'cw-layers-visibility', visibility )
-
            var popup = new ol.Overlay.Popup();
+
    }
-
            map.addOverlay(popup);
+
-
            // display popup on click
+
    ol3Chartlet.prototype.restoreVisibility = function () {
-
            map.on('click', function(evt) {
+
        var standalone = this.params.standalone
-
                var feature = map.forEachFeatureAtPixel(evt.pixel,
+
        var visibility = Storage.get( 'cw-layers-visibility' )
-
                    function(feature) {
+
        if ( ! visibility || ! visibility[ standalone ] )
-
                      return feature;
+
             return
-
                    });
+
-
                if (feature) {
+
-
                    popup.show(evt.coordinate,
+
-
                        '<div class="cw-popup-name">' + feature.get("name") + '</div>' +
+
-
                        '<div class="cw-popup-category">' + feature.get("styleUrl").split('#')[1] + '</div>' +
+
-
                        '<div class="cw-popup-content">' + feature.get("description") + '<div>'
+
-
                    );
+
-
                } else {
+
-
                    popup.hide();
+
-
                }
+
-
             });
+
-
            // change mouse cursor when over marker
+
        function setVisibility ( layer ) {
-
            map.on('pointermove', function(e) {
+
            var name = layer.get( 'title' )
-
                //~ if (e.dragging) {
+
            var isVisible = visibility[ standalone ][ name ]
-
                  //~ $(element).popover('destroy');
+
            if ( isVisible != null )
-
                  //~ return;
+
                 layer.setVisible( isVisible )
-
                //~ }
+
-
                var pixel = map.getEventPixel(e.originalEvent);
+
-
                var hit = map.hasFeatureAtPixel(pixel);
+
-
                 map.getTarget().style.cursor = hit ? 'pointer' : '';
+
-
              });
+
         }
         }
-
         if (params.page) {
+
         walkLayers( this.map, setVisibility )
-
            loadWikiScript('MediaWiki:GetKml.js', function () {
+
-
                getKml(
+
-
                    {
+
-
                        page: params.page,
+
-
                        decorated: true
+
-
                    },
+
-
                    add_kml_layer
+
-
                );
+
-
            });
+
-
 
+
-
            loadWikiCss('MediaWiki:Ol3-popup.css');
+
-
            loadWikiScript("MediaWiki:Ol3-popup.js", init_popups);
+
-
        }
+
     }
     }
-
     function dmsh2deg(dmsh) {
+
     function dmsh2deg( dmsh ) {
-
         var dmsFactors = [1, 60, 3600];
+
         var dmsFactors = [ 1, 60, 3600 ]
-
         var deg = 0;
+
         var deg = 0
-
         if (!dmsh)
+
         if ( ! dmsh )
-
             return deg;
+
             return deg
-
         var parts = dmsh.split('_');
+
         var parts = dmsh.split( '_' )
-
         for (var i=0, li = parts.length; i < li; i++) {
+
         for ( var i=0, li = parts.length; i < li; i++ ) {
-
             var p = parts[i];
+
             var p = parts[ i ]
-
             if (isNaN(+ p)) {
+
             if ( isNaN(+ p) ) {
                 if (p == 'S' || p == 's' || p == 'W' || p == 'w')
                 if (p == 'S' || p == 's' || p == 'W' || p == 'w')
-
                     deg = -deg;
+
                     deg = -deg
-
                 break;
+
                 break
             } else {
             } else {
-
                 deg += p / dmsFactors[i];
+
                 deg += p / dmsFactors[i]
             }
             }
         }
         }
-
         return deg;
+
         return deg
     }
     }
Line 587: Line 718:
     function parseParams(param_str) {
     function parseParams(param_str) {
-
         var out = {};
+
         var out = {
-
         var params = param_str.split('|');
+
            icons: true,
 +
            //recursive: 1,
 +
            //childrenlocations: true,
 +
            //captions: true,
 +
         };
 +
        var params = param_str.split('|');
         for (var i=0, li = params.length; i < li; i++) {
         for (var i=0, li = params.length; i < li; i++) {
             var keyVal = params[i].split('=', 2);
             var keyVal = params[i].split('=', 2);
-
             var key = keyVal[0].replace(/^\s+|\s+$/g, '').toLowerCase();
+
             var key = $.trim(keyVal[0] || '').toLowerCase();
-
             var val = keyVal[1].replace(/^\s+|\s+$/g, '');
+
             var val = $.trim(keyVal[1] || '');
             if (key == 'lon') {
             if (key == 'lon') {
                 out.lon = dmsh2deg(val);
                 out.lon = dmsh2deg(val);
Line 604: Line 740:
             } else if (key == 'page') {
             } else if (key == 'page') {
                 out.page = val;
                 out.page = val;
 +
            } else if (key == 'pagefeatures') {
 +
                out.pageFeatures = !!val;
 +
            } else if (key == 'captions') {
 +
                out.captions = !!val;
 +
            } else if (key == 'childrenlocations') {
 +
                out.childrenlocations = true;
 +
                out.recursive = 1;
 +
            } else if (key == 'recursive') {
 +
                out.recursive = val;
 +
            } else if (key == 'icons') {
 +
                out.icons = !!val;
 +
            } else if (key == 'nopagelocation') {
 +
                out.nopagelocation = !!val;
             }
             }
         }
         }
Line 614: Line 763:
     }
     }
-
     // if (standalone && location.hash) {
+
     function chartlet() {
-
    //    $('body').empty().append(standalone_div);
+
        var $chartlets = $('.chartlet');
-
    //    $('body').addClass('cw-chartlet-extend');
+
         if ($chartlets.length === 0) {
-
    // }
+
-
 
+
-
    loadWikiCss('CruisersWiki:Ol3chartlet.css');
+
-
    loadCss("http://cdnjs.cloudflare.com/ajax/libs/ol3/3.13.1/ol.css");
+
-
    // use debug version, to allow patch below
+
-
    loadScript("http://cdnjs.cloudflare.com/ajax/libs/ol3/3.13.1/ol-debug.js", function () {
+
-
         if (typeof ol === 'undefined') {
+
             return;
             return;
         }
         }
-
         // patch ol.xml as /extensions/TreeAndMenu/dtree.js overwrites Node
+
        var standalone_div = $('.chartlet-standalone')[0];
-
         ol.xml.isNode = goog.userAgent.IE ? ol.xml.isNodeIE_ : function(value) {
+
 
-
             //  return value instanceof Node;
+
         // if (standalone && location.hash) {
-
             return typeof value.nodeName === "string";
+
        //     $('body').empty().append(standalone_div);
-
         };
+
        //    $('body').addClass('cw-chartlet-extend');
 +
         // }
 +
 
 +
        // fill in to a full window if URL hash is set
 +
        if (standalone_div && location.hash) {
 +
            var body = document.body;
 +
            $('body').addClass('chartlet-extend');
 +
            while (body.firstChild) {
 +
                body.removeChild(body.firstChild);
 +
            }
 +
            body.appendChild(standalone_div);
 +
 
 +
            setImmediate(function() {
 +
                new ol3Chartlet( standalone_div, true );
 +
             });
 +
        } else {
 +
             $chartlets.each( function () {
 +
                new ol3Chartlet( this, !! standalone_div );
 +
            });
 +
         }
 +
    };
 +
 
 +
    chartlet()
-
        $chartlets.each(ol3Chartlet);
+
})
-
    });
+
;
-
});
+
// </pre>

Latest revision as of 12:09, 16 January 2020

//
/*
   ol3Chartlet.js

   Copyright (c) 2016 Vadim Shlyakhov
   Licensed MIT
*/

loadCss( 'https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.5.0/ol-debug.css' )

loadJs( 'https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.5.0/ol-debug.js' ) // use debug version, to allow patch below
.then( function () {
    // try to recover from /extensions/TreeAndMenu/dtree.js overwriting Node
    if (Node.ELEMENT_NODE === undefined) {
        if (document.firstElementChild.__proto__.ELEMENT_NODE == 1) {
            Node = document.firstElementChild.__proto__;
        } else {
            Node.ELEMENT_NODE = 1
        }
        ol.xml.isNode = function(value) {
            //   return value instanceof Node;
            return typeof value.nodeName === "string";
        };
    }
    
    var walkLayers = function ( item, action ) {
        if ( item.getLayers )
            item.getLayers().forEach(
                function ( i ) {
                    walkLayers( i, action )
            })
        else
            action( item )
    }
    
    var Navionics = {
        token: null,
        KEY: 'Navionics_webapi_00572',
        DOMAIN: 'www.cruiserswiki.org',
        TILE_URL: 'https://tile{1-5}.navionics.com/tile/{z}/{x}/{y}',
        TOKEN_URL: 'https://tile1.navionics.com/tile/get_key',
        MAX_RESOLUTION: 20480,
        MIN_RESOLUTION: 0.625,

        disclaimer_msg: '', //'<b>© Navionics</b> <a href="http://www.navionics.com/en/acknowledgements" target="_new" class="navionics-acknowledgements">Acknowledgements</a> | Not to be used for navigation',
        depthUnits: {
            'm': 1, 'metre': 1, 'meter': 1,
            'ft': 2, 'feet': 2,
            'fathom': 3,
        },

        attribution: [
            '<div class="navionics-attribution navionics-off">',
                '<a class="navionics-logo" href="http://www.navionics.com/" target="_blank">',
                    '<span></span>',
                '</a>',
                '<div class="navionics-acknowledgements">',
                    '<div>',
                        '<a href="http://www.navionics.com/en/acknowledgements" target="_blank">',
                            'Acknowledgements',
                        '</a>',
                        '<span> | Not to be used for navigation</span>',
                    '</div>',
                '</div>',
            '</div>'
        ].join(''),
    }

    Navionics.getToken = function () {
        if ( Navionics.token != null )
            return Navionics.token
        var url = Navionics.TOKEN_URL  + '/' + Navionics.KEY + '/' + Navionics.DOMAIN
        return Navionics.token = Promise.resolve( $.ajax({
                url: url,
                crossDomain: true,
                dataType: 'text',
                //cache: false,
            })
        )
    }

    Navionics.source = function ( options ) {
        options = options || {}
        var sourceOptions = {
            crossOrigin: 'anonymous',
            maxResolution: Navionics.MAX_RESOLUTION,
            minResolution: Navionics.MIN_RESOLUTION
        }
        ol.source.XYZ.call( this, sourceOptions )

        var self = this
        Navionics.getToken()
        .then( function ( token ) {
            options.token = token
            var url = Navionics.getTileUrl( options )
            self.setUrl( url )
        })
        .catch( function( err ) {
          return console.log( 'Navionics.getToken', err )
        })
    }

    ol.inherits( Navionics.source, ol.source.XYZ )

    Navionics.getTileUrl = function ( options ) { // sonar, overlay, depthUnit, safeDepth, showUGC
        options = options || {}
        var layerConfig = [
            'config',
            Navionics.depthUnits[ options.depthUnit ] || 1,
            ( options.safeDepth || 20 ).toFixed( 2 ),
            options.sonar ? 1 : 0
        ]
        params = $.param({
            LAYERS: layerConfig.join('_'),
            TRANSPARENT: !! options.transparency,
            UGC: !! options.showUGC,
            navtoken: options.token
        })
        return Navionics.TILE_URL + '?' + params 
    }

    Navionics.monitorAttribution = function ( map ) {
        var layers = []

        function checkLayer ( l ) {
            var title = l.get( 'title' )
            if ( title && title.indexOf( 'Navionics' ) != -1 ) {
                layers.push( l )
            }
        }
        walkLayers( map, checkLayer )

        if ( layers.length == 0 )
            return
        var attribution = $( Navionics.attribution )
        var control = new ol.control.Control({ element: attribution.get( 0 ) })
        map.addControl( control )

        function attributionVisibility ( evt ) {
            // console.log( 'change:visible', evt )
            var visible = this.getVisible()
            attribution.toggleClass( 'navionics-off', ! visible )
        }

        for ( var i=0, li=layers.length; i < li; i++ ) {
            var layer = layers[ i ]
            layer.on( 'change', attributionVisibility.bind( layer ))
            layer.on( 'change:visible', attributionVisibility.bind( layer ))
        }
    }

    var Esri = {
        uri_map: {
            'satellite': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
            'topo': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
            'terrain': 'http://server.arcgisonline.com/arcgis/rest/services/World_Terrain_Base/MapServer',
            'physical': 'http://services.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer',
            'relief': 'http://server.arcgisonline.com/arcgis/rest/services/World_Shaded_Relief/MapServer',
            'light-gray': "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer",
            'dark-gray': "http://services.arcgisonline.com/arcgis/rest/services/Canvas/World_Dark_Gray_Base/MapServer",
            'street': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
            'places': "http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer",
            'oceans-reference': "http://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Reference/MapServer",
            'oceans': 'http://server.arcgisonline.com/arcgis/rest/services/Ocean_Basemap/MapServer',
            'national-geographic': "http://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer",
            'transportation': "https://server.arcgisonline.com/ArcGIS/rest/services/Reference/World_Transportation/MapServer"
        },
    }
/*
    Esri.source = function ( id ) {
        ol.source.TileArcGISRest.call( this, {
            url: Esri.uri_map[ id ],
            params: {
                FORMAT: 'JPG',
                TRANSPARENT: false,
            },
            attributions: [
                new ol.Attribution({
                    html: 'Tiles by ESRI <a href="' + Esri.uri_map[ id ] + '">Acknowledgements</a>'
                })
            ]
        })
    };

    ol.inherits( Esri.source, ol.source.TileArcGISRest )
*/
    Esri.source = function ( id ) {
        ol.source.XYZ.call( this, {
            url: Esri.uri_map[ id ] + '/tile/{z}/{y}/{x}',
            crossOrigin: null,
            attributions: [
                new ol.Attribution({
                    html: 'Tiles by ESRI <a href="' + Esri.uri_map[ id ] + '">Acknowledgements</a>'
                })
            ],
        })
    };

    ol.inherits( Esri.source, ol.source.XYZ )

    function ol3Chartlet( chartlet_div, standalone ) {
        this.styleLoadHooks = [];

        console.log('ol3Chartlet');

        this.params = parseParams(
            standalone && location.hash
            ? decodeURI( location.hash.slice( 1 ))
            : $( chartlet_div ).text()
        )
        this.params.standalone = standalone
        
        var layers = this.createLayers()

        var map = this.map = new ol.Map({
            target: chartlet_div,
            layers: layers,
            view: new ol.View({
                center: ol.proj.transform([this.params.lon, this.params.lat], 'EPSG:4326', 'EPSG:3857'),
                zoom: this.params.zoom
            }),
            interactions: ol.interaction.defaults(
                standalone ? {}
                : {
                    mouseWheelZoom:false,
                    // doubleClickZoom :false,
                }
            ),
            controls: ol.control.defaults({
                attributionOptions: /** @type {olx.control.AttributionOptions} */ {
                    collapsible: false
                }
            }).extend([
                new ol.control.FullScreen(),
                new ol.control.ScaleLine({
                    units: 'nautical'
                })
            ])
        });

        this.restoreVisibility()

        Navionics.monitorAttribution( map )

        // loadWikiCss( 'CruisersWiki:Ol3-layerswitcher.css' )
        // loadWikiJs( 'CruisersWiki:Ol3-layerswitcher.js')
        loadCss( 'https://cdn.jsdelivr.net/gh/walkermatt/[email protected]/src/ol3-layerswitcher.css' )
        loadJs( 'https://cdn.jsdelivr.net/gh/walkermatt/[email protected]/src/ol3-layerswitcher.js' )
        .then( function () {
            var layerSwitcher = new ol.control.LayerSwitcher({
                // tipLabel: 'Legend' // Optional label for button
            });
            map.addControl(layerSwitcher);
        })

        if (standalone) {
            this.params.page && this.addPoiLayer();
            this.trackHash();
            this.addGraticule();
            this.addCentreControl( map );

        } else if (this.params.pageFeatures) {
            this.addPoiLayer();
        }

        this.addStoreVisibilityToolstoreVisibilitystoreVisibility()
    };

    ol3Chartlet.prototype.createLayers = function () {
        var layerDefs = [
            // overlays
            [ 'o', 's', '', 'Navionics Boating', new Navionics.source({ transparency: true }) ],
            [ 'o', '', '', 'ESRI Transportation', new Esri.source( 'transportation' ) ],
            [ 'o', '', 'i', 'ESRI Boundaries and Places', new Esri.source( 'places' ) ],
            [ 'o', '', 'i', 'OpenSeaMap', new ol.source.XYZ({
                        url: 'http://t1.openseamap.org/seamark/{z}/{x}/{y}.png',
                        crossOrigin: null,
                        attributions: [
                            new ol.Attribution({
                                html: 'Tiles by <a href="http://www.openseamap.org">OpenSeaMap</a>'
                            })
                        ],
                    })
            ],
            // baselayers
            [ '-b', '', '', 'Navionics', new Navionics.source() ],
            [ 'b', 's', '', 'Water color', new ol.source.Stamen({
                        layer: 'watercolor',
                        //~ url: 'http://tile.stamen.com/watercolor/{z}/{x}/{y}.jpg'
                        //~ url: 'https://stamen-tiles-{a-d}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg'
                    })
            ],
            [ 'b', '', '', 'OpenStreetMap',  new ol.source.OSM() ],
            [ 'b', '', 'i', 'ESRI World Imagery',  new Esri.source( 'satellite' ) ],
            [ '-b', '', '', 'ESRI World Street Map', new Esri.source( 'street' ) ],
            [ '-b', '', '', 'OSM base', new ol.source.OSM({
                        crossOrigin: null,
                        url: 'http://{a-c}.tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png'
                    })
            ],
            [ '-b', '', '', new ol.layer.Vector({
                    title: 'No background',
                    source: new ol.source.Vector({})
            })],
        ]
        
        var baseLayers = []
        var overlays = []

        for (var i = 0; i < layerDefs.length; i++) {
            var row = layerDefs[ i ]
            var title = row[ 3 ]
            var l = typeof title != 'string' ? title : new ol.layer.Tile({
                title: title,
                source: row[ 4 ]
            })

            l.set( 'visible', this.params.standalone ? row[ 1 ] == 's' : row[ 2 ] == 'i' )
            switch ( row[ 0 ] ) { 
                case 'b':
                    l.set( 'type' , 'base' )
                    baseLayers.push( l )
                    break
                case 'o': 
                    overlays.push( l )
            }
        }
/*
        this.baselayersGroupName = 'Base';
        this.overlaysGroupName = 'Overlays';
        var layers = [
            new ol.layer.Group({
                title: this.baselayersGroupName,
                layers: baseLayers
            }),
            new ol.layer.Group({
                    title: this.overlaysGroupName,
                    layers: overlays
            })
        ]
*/
        var layers = baseLayers.concat( overlays )
        return layers
    }
    
    ol3Chartlet.prototype.addCentreControl = function ( map ) {
        var elem = $( '<div class="chartlet-centre"></div>' ).get( 0 )
        var control = new ol.control.Control({ element: elem })
        map.addControl( control )
    }

    // add to a layer group
    ol3Chartlet.prototype.addNonBaseLayer = function (new_layer) {
        this.map.getLayers().push( new_layer )
/*
        this.map.getLayers().forEach(
            function(layer) {
                if (layer.get('title') === this.overlaysGroupName) {
                    layer.getLayers().push(new_layer);
                }
            }
        )
*/
    }

    ol3Chartlet.prototype.trackHash = function() {
        var doNotTrackHash = false;
        var setHashTimeoutID = null;

        var view = this.map.getView();
        var params = this.params;

        var onChangeCenterZoom = function () {
            var setHashDelay = 1000;

            var setHash = function () {
                var centre = view.getCenter();
                var lonlat = ol.proj.transform(centre, view.getProjection(), 'EPSG:4326');

                doNotTrackHash = true;
                setHashTimeoutID = null;

                params.lon = lonlat[0];
                params.lat = lonlat[1];
                params.zoom = view.getZoom();
                //console.log(center, zoom);

                location.hash = 'lat=' + round(params.lat) + '|lon=' + round(params.lon)
                    + '|zoom=' + params.zoom
                    + (params.layer ? '|layer=' + params.layer : '')
                    + (params.page ? '|page=' + params.page : '');
            };

            if (setHashTimeoutID) {
                window.clearTimeout(setHashTimeoutID);
            }
            setHashTimeoutID = window.setTimeout(setHash, setHashDelay);
        }

        view.on('change:center', onChangeCenterZoom);
        view.on('change:resolution', onChangeCenterZoom);

        window.addEventListener('hashchange',  function () {
            if (!location.hash || doNotTrackHash) {
                doNotTrackHash = false;
                return;
            }
            params = parseParams(location.hash.slice(1));
            if (params.lat != null && params.lon != null) {
                var centre = [params.lon, params.lat];
                view.setCenter(ol.proj.transform(centre, 'EPSG:4326', view.getProjection()))
                view.setZoom(params.zoom);
            }
        })
    }

    // Create the graticule
    ol3Chartlet.prototype.addGraticule = function () { // after http://map.openseamap.org/javascript/grid_wgs.js
        var this_ = this;
        loadWikiJs( 'CruisersWiki:Ol3chartlet-graticule.js' )
        .then( function () {
            var layer = graticuleLayer(this_.map);
            this_.addNonBaseLayer(layer);
        })
        /*
        var graticule = new ol.Graticule({
            map: this.map,
            // the style to use for the lines, optional.
            strokeStyle: new ol.style.Stroke({
                color: 'rgba(255,120,0,0.9)',
                width: 2,
                lineDash: [0.5, 4]
            })
        });
        // graticule.setMap(this.map);
        */
    };

    ol3Chartlet.prototype.addPoiLayer = function () {
        var options = $.extend({}, this.params);

        var loader = function(extent, resolution, projection) {
            /**
            * @param {ol.Extent} extent Extent.
            * @param {number} resolution Resolution.
            * @param {ol.proj.Projection} projection Projection.
            * @this {ol.source.Vector|ol.VectorTile}
            */
            options.projection = projection;
            options.addFeature = addFeature;

            loadWikiJs(
                $('.chartlet-test').length == 0 ? 'CruisersWiki:Ol3chartlet-features.js' : 'CruisersWiki:Ol3chartlet-features-test.js'
            )
            .then( function () {
                loadFeatures(options);
            })
        };

        var source = new ol.source.Vector({
            loader: loader,
        });

        var layer = new ol.layer.Vector({
            title: 'POI',
            visible: true,
            style: styleFunction,
            source: source,
        });

        var this_ = this;

        var defferedFeatures = [];
        function addFeature (feature) {
            if (!this_.styles) {
                defferedFeatures.push(feature);
                return;
            }
            if (defferedFeatures) {
                source.addFeatures(defferedFeatures);
                defferedFeatures = null;
            }
            if (feature) {
                source.addFeature(feature);
            }
        };

        this.styleLoadHooks.push(addFeature);

        function styleFunction (feature, resolution) {
            var category = feature.get('category') || 'other';
            var geom = feature.getGeometry();
            var style;
            if (geom.getType() == 'Point') {
                var styleOptions = {
                    //zIndex: 2
                };
                options.icons && (styleOptions.image = this_.getStyle(category, 'Icon'));
                options.captions && (styleOptions.text = this_.getTextStyle(category, feature.get('name')));
                style = new ol.style.Style(styleOptions);
            } else {
                style = new ol.style.Style({
                    fill: this_.getStyle(category, 'Fill'),
                    stroke: this_.getStyle(category, 'Stroke'),
                });
            }
            return style;
        };

        this.addNonBaseLayer(layer);

//        loadWikiCss('CruisersWiki:tOl3-popup.css');
//        loadWikiJs( 'CruisersWiki:tOl3-popup.js' )
        loadCss( 'https://cdn.jsdelivr.net/gh/walkermatt/[email protected]/src/ol3-popup.css' );
        loadJs( 'https://cdn.jsdelivr.net/gh/walkermatt/[email protected]/src/ol3-popup.js' )
        .then( this.initPopups.bind( this ))

        this.trackPointer();
        this.highlightFeatures();
        this.loadStyles();
    };

    ol3Chartlet.prototype.styles = null;
    ol3Chartlet.prototype.styleLoadHooks = null;

    ol3Chartlet.prototype.loadStyles = function () {
        var this_ = this;
        loadWikiJs(
            $('.chartlet-test').length == 0 ? 'CruisersWiki:Ol3chartlet-styles.js' : 'CruisersWiki:Ol3chartlet-styles-test.js'
        )
        .then( function () { return loadStyles() })
        .then( function (styles) {
            this_.styles = styles;
            var hooks = this_.styleLoadHooks;
            this_.styleLoadHooks = [];
            hooks.map( function(fn) { fn() });
        });
    };

    ol3Chartlet.prototype.getStyle = function (category, subType) {
        var style = this.styles[category + '.' + subType];
        return style ? style : this.styles['default'  + '.' + subType];
    }

    ol3Chartlet.prototype.getTextStyle = function (category, text) {
        var style = this.getStyle(category, 'Text').clone();
        style.setText(text);
        return style;
    }

    ol3Chartlet.prototype.isClickableLayer = function (layer) {
        return ! layer.get('noclickable');
    };

    ol3Chartlet.prototype.initPopups = function () {
        var map = this.map;
        var popup = new ol.Overlay.Popup();
        map.addOverlay(popup);

        var popTemplate =
            '<div class="cw-popup-name"><a href="{href}" target="_blank">{name}</a></div>\n' +
            '<div class="cw-popup-category">{category}</div>\n' +
            '<div class="cw-popup-content">{content}</div>';

        // display popup on click
        map.on('click', function(evt) {
            var feature = map.forEachFeatureAtPixel(
                evt.pixel,
                function(feature, layer) {
                  return feature;
                },
                { layerFilter: this.isClickableLayer }
            );
            if (feature && ! feature.get('noclickable')) {
                var data = {
                    href: feature.get("url"),
                    name: feature.get("name"),
                    category: feature.get("category"),
                    content: feature.get("description"),
                };
                popup.show(evt.coordinate, format(popTemplate, data));
            } else {
                popup.hide();
            }
        });
    };

    ol3Chartlet.prototype.trackPointer = function () {
        // change mouse cursor when over marker
        var map = this.map;
        map.on('pointermove', function(e) {
            //~ if (e.dragging) {
              //~ $(element).popover('destroy');
              //~ return;
            //~ }
            var pixel = map.getEventPixel(e.originalEvent);
            var hit = map.hasFeatureAtPixel(pixel, this.isClickableLayer);
            map.getTarget().style.cursor = hit ? 'pointer' : '';
        });
    };

    ol3Chartlet.prototype.highlightFeatures = function () {
        var map = this.map;
        var highlightStyle;
        this.styleLoadHooks.push(function () {
            highlightStyle = new ol.style.Style({
                fill: this.getStyle('highlight', 'Fill'),
                stroke: this.getStyle('highlight', 'Stroke'),
            });
        }.bind(this));

        function styleFunction (feature, resolution) {
            var geom = feature.getGeometry();
            if (geom.getType() != 'Point') {
                return highlightStyle;
            }
        }

        var highlightOverlay = new ol.layer.Vector({
            source: new ol.source.Vector(),
            map: map,
            style: styleFunction
        });
        highlightOverlay.set('noclickable', true);

        var highlight;

        var highlightFeature = function(evt) {
            if (evt.dragging) {
                return;
            }
            var pixel = map.getEventPixel(evt.originalEvent);

            var feature = map.forEachFeatureAtPixel(pixel, function(feature) {
                return feature;
            });

            if (feature !== highlight) {
                if (highlight) {
                    highlightOverlay.getSource().removeFeature(highlight);
                }
                if (feature) {
                    highlightOverlay.getSource().addFeature(feature);
                }
                highlight = feature;
            }
        };

        map.on('pointermove', highlightFeature);
    };

    ol3Chartlet.prototype.addStoreVisibilityToolstoreVisibilitystoreVisibility = function () {
        if ( $( '#cw-save-layers' ).length > 0 )
            return
        var $a = $( '<a id="cw-save-layers" style="cursor:pointer">Save layers</a>' )
            .click( this.storeVisibility.bind( this ))

        $( '#p-tb ul' ).append( $( '<li>' ).append( $a ))
    }

    ol3Chartlet.prototype.storeVisibility = function () {
        var standalone = this.params.standalone
        var visibility = Storage.get( 'cw-layers-visibility' )
        
        if ( ! visibility || ! visibility[ standalone ] )
            visibility = {
                true: {},
                false: {},
            }

        function getVisibility ( layer ) {
            var name = layer.get( 'title' )
            visibility[ standalone ][ name ] = layer.getVisible()
        }

        walkLayers( this.map, getVisibility )

        Storage.set( 'cw-layers-visibility', visibility )
    }

    ol3Chartlet.prototype.restoreVisibility = function () {
        var standalone = this.params.standalone
        var visibility = Storage.get( 'cw-layers-visibility' )
        if ( ! visibility || ! visibility[ standalone ] )
            return

        function setVisibility ( layer ) {
            var name = layer.get( 'title' )
            var isVisible = visibility[ standalone ][ name ]
            if ( isVisible != null )
                layer.setVisible( isVisible )
        }

        walkLayers( this.map, setVisibility )
    }

    function dmsh2deg( dmsh ) {
        var dmsFactors = [ 1, 60, 3600 ]
        var deg = 0
        if ( ! dmsh )
            return deg

        var parts = dmsh.split( '_' )
        for ( var i=0, li = parts.length; i < li; i++ ) {
            var p = parts[ i ]
            if ( isNaN(+ p) ) {
                if (p == 'S' || p == 's' || p == 'W' || p == 'w')
                    deg = -deg
                break
            } else {
                deg += p / dmsFactors[i]
            }
        }
        return deg
    }

    var zoomDelta = 0; // -3; // adjust zoom levels

    function parseParams(param_str) {
        var out = {
            icons: true,
            //recursive: 1,
            //childrenlocations: true,
            //captions: true,
        };

        var params = param_str.split('|');
        for (var i=0, li = params.length; i < li; i++) {
            var keyVal = params[i].split('=', 2);
            var key = $.trim(keyVal[0] || '').toLowerCase();
            var val = $.trim(keyVal[1] || '');
            if (key == 'lon') {
                out.lon = dmsh2deg(val);
            } else if (key == 'lat') {
                out.lat = dmsh2deg(val);
            } else if (key == 'zoom') {
                out.zoom = +(val || 12) + zoomDelta;
            } else if (key == 'layer') {
                out.layer = val || 'N';
            } else if (key == 'page') {
                out.page = val;
            } else if (key == 'pagefeatures') {
                out.pageFeatures = !!val;
            } else if (key == 'captions') {
                out.captions = !!val;
            } else if (key == 'childrenlocations') {
                out.childrenlocations = true;
                out.recursive = 1;
            } else if (key == 'recursive') {
                out.recursive = val;
            } else if (key == 'icons') {
                out.icons = !!val;
            } else if (key == 'nopagelocation') {
                out.nopagelocation = !!val;
            }
        }
        return out;
    }

    function round(val) {
        var fact = 100000;
        return Math.round(val * fact) / fact;
    }

    function chartlet() {
        var $chartlets = $('.chartlet');
        if ($chartlets.length === 0) {
            return;
        }

        var standalone_div = $('.chartlet-standalone')[0];

        // if (standalone && location.hash) {
        //     $('body').empty().append(standalone_div);
        //     $('body').addClass('cw-chartlet-extend');
        // }

        // fill in to a full window if URL hash is set
        if (standalone_div && location.hash) {
            var body = document.body;
            $('body').addClass('chartlet-extend');
            while (body.firstChild) {
                body.removeChild(body.firstChild);
            }
            body.appendChild(standalone_div);

            setImmediate(function() {
                new ol3Chartlet( standalone_div, true );
            });
        } else {
            $chartlets.each( function () {
                new ol3Chartlet( this, !! standalone_div );
            });
        }
    };

    chartlet()

})
;
// 
Personal tools
advertisement
Friends of Cruisers Wiki