CruisersWiki:Ol3chartlet.js
From CruisersWiki
(Difference between revisions)
(walkLayers) |
|||
(26 intermediate revisions not shown) | |||
Line 7: | Line 7: | ||
*/ | */ | ||
- | (function() { | + | loadCss( 'https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.5.0/ol-debug.css' ) |
- | var | + | |
- | + | 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, | MAX_RESOLUTION: 20480, | ||
MIN_RESOLUTION: 0.625, | 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, | crossDomain: true, | ||
dataType: 'text', | dataType: 'text', | ||
//cache: false, | //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 || {} | + | options = options || {} |
var layerConfig = [ | var layerConfig = [ | ||
'config', | 'config', | ||
- | + | Navionics.depthUnits[ options.depthUnit ] || 1, | |
- | (options.safeDepth || 20).toFixed(2), | + | ( options.safeDepth || 20 ).toFixed( 2 ), |
options.sonar ? 1 : 0 | options.sonar ? 1 : 0 | ||
- | ] | + | ] |
params = $.param({ | params = $.param({ | ||
LAYERS: layerConfig.join('_'), | LAYERS: layerConfig.join('_'), | ||
TRANSPARENT: !! options.transparency, | TRANSPARENT: !! options.transparency, | ||
UGC: !! options.showUGC, | UGC: !! options.showUGC, | ||
- | navtoken: | + | navtoken: options.token |
- | }) | + | }) |
- | return | + | 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 ) | ||
- | return | + | 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 ] | |
- | url: | + | 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: { | params: { | ||
FORMAT: 'JPG', | FORMAT: 'JPG', | ||
Line 127: | Line 177: | ||
attributions: [ | attributions: [ | ||
new ol.Attribution({ | new ol.Attribution({ | ||
- | html: 'Tiles by ESRI <a href="' + | + | html: 'Tiles by ESRI <a href="' + Esri.uri_map[ id ] + '">Acknowledgements</a>' |
}) | }) | ||
] | ] | ||
Line 133: | Line 183: | ||
}; | }; | ||
- | + | ol.inherits( Esri.source, ol.source.TileArcGISRest ) | |
- | + | */ | |
- | url: | + | Esri.source = function ( id ) { |
+ | ol.source.XYZ.call( this, { | ||
+ | url: Esri.uri_map[ id ] + '/tile/{z}/{y}/{x}', | ||
crossOrigin: null, | crossOrigin: null, | ||
attributions: [ | attributions: [ | ||
new ol.Attribution({ | new ol.Attribution({ | ||
- | html: 'Tiles by ESRI <a href="' + | + | html: 'Tiles by ESRI <a href="' + Esri.uri_map[ id ] + '">Acknowledgements</a>' |
}) | }) | ||
], | ], | ||
}) | }) | ||
}; | }; | ||
- | |||
- | |||
- | |||
- | function ol3Chartlet(chartlet_div, standalone) { | + | ol.inherits( Esri.source, ol.source.XYZ ) |
+ | |||
+ | function ol3Chartlet( chartlet_div, standalone ) { | ||
this.styleLoadHooks = []; | this.styleLoadHooks = []; | ||
console.log('ol3Chartlet'); | console.log('ol3Chartlet'); | ||
- | this.params = parseParams(standalone && location.hash ? decodeURI(location.hash.slice(1)) : $(chartlet_div).text()) | + | this.params = parseParams( |
- | this.params.standalone = standalone | + | standalone && location.hash |
- | + | ? decodeURI( location.hash.slice( 1 )) | |
- | + | : $( chartlet_div ).text() | |
- | + | ) | |
- | + | this.params.standalone = standalone | |
- | + | ||
- | + | var layers = this.createLayers() | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | var layers = | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
var map = this.map = new ol.Map({ | var map = this.map = new ol.Map({ | ||
Line 297: | Line 239: | ||
}); | }); | ||
- | loadWikiCss('CruisersWiki:Ol3-layerswitcher.css') | + | 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({ | var layerSwitcher = new ol.control.LayerSwitcher({ | ||
- | // tipLabel: ' | + | // tipLabel: 'Legend' // Optional label for button |
}); | }); | ||
map.addControl(layerSwitcher); | map.addControl(layerSwitcher); | ||
- | }) | + | }) |
if (standalone) { | if (standalone) { | ||
Line 309: | Line 258: | ||
this.trackHash(); | this.trackHash(); | ||
this.addGraticule(); | this.addGraticule(); | ||
+ | this.addCentreControl( map ); | ||
+ | |||
} else if (this.params.pageFeatures) { | } else if (this.params.pageFeatures) { | ||
this.addPoiLayer(); | 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 | // add to a layer group | ||
ol3Chartlet.prototype.addNonBaseLayer = function (new_layer) { | ol3Chartlet.prototype.addNonBaseLayer = function (new_layer) { | ||
+ | this.map.getLayers().push( new_layer ) | ||
+ | /* | ||
this.map.getLayers().forEach( | this.map.getLayers().forEach( | ||
function(layer) { | function(layer) { | ||
- | if (layer.get('title') === overlaysGroupName) { | + | if (layer.get('title') === this.overlaysGroupName) { |
layer.getLayers().push(new_layer); | layer.getLayers().push(new_layer); | ||
} | } | ||
} | } | ||
- | ) | + | ) |
- | } | + | */ |
+ | } | ||
ol3Chartlet.prototype.trackHash = function() { | ol3Chartlet.prototype.trackHash = function() { | ||
Line 357: | Line 396: | ||
} | } | ||
setHashTimeoutID = window.setTimeout(setHash, setHashDelay); | setHashTimeoutID = window.setTimeout(setHash, setHashDelay); | ||
- | } | + | } |
view.on('change:center', onChangeCenterZoom); | view.on('change:center', onChangeCenterZoom); | ||
Line 373: | Line 412: | ||
view.setZoom(params.zoom); | view.setZoom(params.zoom); | ||
} | } | ||
- | }) | + | }) |
- | } | + | } |
// Create the graticule | // Create the graticule | ||
ol3Chartlet.prototype.addGraticule = function () { // after http://map.openseamap.org/javascript/grid_wgs.js | ol3Chartlet.prototype.addGraticule = function () { // after http://map.openseamap.org/javascript/grid_wgs.js | ||
var this_ = this; | var this_ = this; | ||
- | + | loadWikiJs( 'CruisersWiki:Ol3chartlet-graticule.js' ) | |
+ | .then( function () { | ||
var layer = graticuleLayer(this_.map); | var layer = graticuleLayer(this_.map); | ||
this_.addNonBaseLayer(layer); | this_.addNonBaseLayer(layer); | ||
- | }) | + | }) |
/* | /* | ||
var graticule = new ol.Graticule({ | var graticule = new ol.Graticule({ | ||
Line 410: | Line 450: | ||
options.addFeature = addFeature; | options.addFeature = addFeature; | ||
- | + | loadWikiJs( | |
- | $('.chartlet-test').length == 0 ? 'CruisersWiki:Ol3chartlet-features.js' : 'CruisersWiki:Ol3chartlet-features-test.js' | + | $('.chartlet-test').length == 0 ? 'CruisersWiki:Ol3chartlet-features.js' : 'CruisersWiki:Ol3chartlet-features-test.js' |
- | + | ) | |
- | + | .then( function () { | |
- | + | loadFeatures(options); | |
- | ) | + | }) |
}; | }; | ||
- | + | ||
var source = new ol.source.Vector({ | var source = new ol.source.Vector({ | ||
loader: loader, | loader: loader, | ||
}); | }); | ||
- | + | ||
var layer = new ol.layer.Vector({ | var layer = new ol.layer.Vector({ | ||
title: 'POI', | title: 'POI', | ||
Line 445: | Line 485: | ||
} | } | ||
}; | }; | ||
- | + | ||
this.styleLoadHooks.push(addFeature); | this.styleLoadHooks.push(addFeature); | ||
Line 452: | Line 492: | ||
var geom = feature.getGeometry(); | var geom = feature.getGeometry(); | ||
var style; | var style; | ||
- | if (geom.getType() == 'Point') { | + | if (geom.getType() == 'Point') { |
var styleOptions = { | var styleOptions = { | ||
//zIndex: 2 | //zIndex: 2 | ||
Line 463: | Line 503: | ||
fill: this_.getStyle(category, 'Fill'), | fill: this_.getStyle(category, 'Fill'), | ||
stroke: this_.getStyle(category, 'Stroke'), | stroke: this_.getStyle(category, 'Stroke'), | ||
- | }); | + | }); |
} | } | ||
return style; | return style; | ||
}; | }; | ||
- | + | ||
this.addNonBaseLayer(layer); | 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.trackPointer(); | ||
this.highlightFeatures(); | this.highlightFeatures(); | ||
Line 482: | Line 526: | ||
ol3Chartlet.prototype.loadStyles = function () { | ol3Chartlet.prototype.loadStyles = function () { | ||
var this_ = this; | 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) { | ol3Chartlet.prototype.getStyle = function (category, subType) { | ||
Line 503: | Line 548: | ||
return style; | return style; | ||
} | } | ||
- | + | ||
ol3Chartlet.prototype.isClickableLayer = function (layer) { | ol3Chartlet.prototype.isClickableLayer = function (layer) { | ||
return ! layer.get('noclickable'); | return ! layer.get('noclickable'); | ||
}; | }; | ||
- | + | ||
ol3Chartlet.prototype.initPopups = function () { | ol3Chartlet.prototype.initPopups = function () { | ||
var map = this.map; | var map = this.map; | ||
Line 513: | Line 558: | ||
map.addOverlay(popup); | map.addOverlay(popup); | ||
- | var popTemplate = | + | var popTemplate = |
'<div class="cw-popup-name"><a href="{href}" target="_blank">{name}</a></div>\n' + | '<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-category">{category}</div>\n' + | ||
Line 522: | Line 567: | ||
var feature = map.forEachFeatureAtPixel( | var feature = map.forEachFeatureAtPixel( | ||
evt.pixel, | evt.pixel, | ||
- | function(feature) { | + | function(feature, layer) { |
return feature; | return feature; | ||
}, | }, | ||
- | + | { layerFilter: this.isClickableLayer } | |
- | + | ); | |
- | + | ||
if (feature && ! feature.get('noclickable')) { | if (feature && ! feature.get('noclickable')) { | ||
- | var data = { | + | var data = { |
href: feature.get("url"), | href: feature.get("url"), | ||
name: feature.get("name"), | name: feature.get("name"), | ||
Line 572: | Line 616: | ||
} | } | ||
} | } | ||
- | + | ||
var highlightOverlay = new ol.layer.Vector({ | var highlightOverlay = new ol.layer.Vector({ | ||
source: new ol.source.Vector(), | source: new ol.source.Vector(), | ||
Line 581: | Line 625: | ||
var highlight; | var highlight; | ||
- | + | ||
var highlightFeature = function(evt) { | var highlightFeature = function(evt) { | ||
if (evt.dragging) { | if (evt.dragging) { | ||
Line 587: | Line 631: | ||
} | } | ||
var pixel = map.getEventPixel(evt.originalEvent); | var pixel = map.getEventPixel(evt.originalEvent); | ||
- | + | ||
var feature = map.forEachFeatureAtPixel(pixel, function(feature) { | var feature = map.forEachFeatureAtPixel(pixel, function(feature) { | ||
return feature; | return feature; | ||
Line 606: | Line 650: | ||
}; | }; | ||
- | function dmsh2deg(dmsh) { | + | ol3Chartlet.prototype.addStoreVisibilityToolstoreVisibilitystoreVisibility = function () { |
- | var dmsFactors = [1, 60, 3600] | + | if ( $( '#cw-save-layers' ).length > 0 ) |
- | var deg = 0 | + | return |
- | if (!dmsh) | + | var $a = $( '<a id="cw-save-layers" style="cursor:pointer">Save layers</a>' ) |
- | return deg | + | .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('_') | + | 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 674: | Line 763: | ||
} | } | ||
- | function | + | function chartlet() { |
var $chartlets = $('.chartlet'); | var $chartlets = $('.chartlet'); | ||
if ($chartlets.length === 0) { | if ($chartlets.length === 0) { | ||
return; | 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() | |
+ | |||
+ | }) | ||
+ | ; | ||
// </pre> | // </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() }) ; //