CruisersWiki:Ol3chartlet.js
From CruisersWiki
(Difference between revisions)
(Navionics attribution updated) |
|||
Line 7: | Line 7: | ||
*/ | */ | ||
- | (function() { | + | Promise.all( [ |
- | var | + | // use debug version, to allow patch below |
- | + | loadJs( 'http://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol-debug.js'), | |
- | + | loadCss( 'http://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol.css' ) | |
- | + | ]) | |
+ | .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"; | ||
+ | }; | ||
+ | } | ||
+ | }) | ||
+ | .then( function () { | ||
+ | var Navionics = { | ||
+ | token: null, | ||
+ | KEY: 'Navionics_webapi_00572', | ||
+ | DOMAIN: 'www.cruiserswiki.org', | ||
BASE_TILE_SERVER: '//backend.navionics.io', | BASE_TILE_SERVER: '//backend.navionics.io', | ||
TILE_SUFFIX: '/tile/{z}/{x}/{y}', | TILE_SUFFIX: '/tile/{z}/{x}/{y}', | ||
Line 17: | Line 36: | ||
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>', | |
- | var | + | '<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.BASE_TILE_SERVER + Navionics.KEY_REQ_SUFFIX + '/' + Navionics.KEY + '/' + Navionics.DOMAIN | ||
+ | return Navionics.token = Promise.resolve( $.ajax({ | ||
+ | url: url, | ||
crossDomain: true, | crossDomain: true, | ||
dataType: 'text', | dataType: 'text', | ||
//cache: false, | //cache: false, | ||
- | + | }) | |
- | + | ) | |
- | + | .catch( function( err ) { | |
- | + | return console.log( 'Navionics.getToken', err ) | |
- | + | }) | |
- | + | } | |
- | + | ||
- | + | 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 ) | ||
+ | }) | ||
+ | } | ||
- | + | ol.inherits( Navionics.source, ol.source.XYZ ) | |
- | options = options || {} | + | |
+ | Navionics.getTileUrl = function ( options ) { // sonar, overlay, depthUnit, safeDepth, showUGC | ||
+ | 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.BASE_TILE_SERVER + Navionics.TILE_SUFFIX + '?' + params |
- | } | + | } |
- | + | Navionics.setAttribution = function ( map, layers ) { | |
- | + | if ( ! layers ) | |
- | + | return | |
- | + | if ( ! Array.isArray( layers )) | |
- | + | layers = [ layers ] | |
- | + | var attribution = $( Navionics.attribution ) | |
- | var | + | 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 | + | 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", | |
- | + | 'hybrid': "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", | |
- | } | + | }, |
- | + | } | |
- | + | /* | |
- | + | Esri.source = function ( id ) { | |
- | url: | + | ol.source.TileArcGISRest.call( this, { |
+ | url: Esri.uri_map[ id ], | ||
params: { | params: { | ||
FORMAT: 'JPG', | FORMAT: 'JPG', | ||
Line 127: | Line 163: | ||
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 169: | ||
}; | }; | ||
- | + | 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>' |
}) | }) | ||
], | ], | ||
}) | }) | ||
}; | }; | ||
- | + | ||
+ | ol.inherits( Esri.source, ol.source.XYZ ) | ||
+ | |||
var baselayersGroupName = 'Base'; | var baselayersGroupName = 'Base'; | ||
var overlaysGroupName = 'Overlays'; | var overlaysGroupName = 'Overlays'; | ||
Line 153: | Line 193: | ||
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 | + | var overlays |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
var openseamap = new ol.layer.Tile({ | var openseamap = new ol.layer.Tile({ | ||
title: 'OpenSeaMap', | title: 'OpenSeaMap', | ||
- | |||
source: new ol.source.XYZ({ | source: new ol.source.XYZ({ | ||
url: 'http://t1.openseamap.org/seamark/{z}/{x}/{y}.png', | url: 'http://t1.openseamap.org/seamark/{z}/{x}/{y}.png', | ||
Line 193: | Line 213: | ||
], | ], | ||
}) | }) | ||
- | }) | + | }) |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
var nx_layer_ovl = new ol.layer.Tile({ | var nx_layer_ovl = new ol.layer.Tile({ | ||
title: 'Navionics Boating', | title: 'Navionics Boating', | ||
- | source: | + | source: new Navionics.source({ transparency: true }), |
- | + | }) | |
- | + | ||
- | }) | + | |
- | var | + | var baseLayers |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
+ | var nx_layer = new ol.layer.Tile({ | ||
+ | title: 'Navionics', | ||
+ | source: new Navionics.source(), | ||
+ | }) | ||
var osm = new ol.layer.Tile({ | var osm = new ol.layer.Tile({ | ||
title: 'OpenStreetMap', | title: 'OpenStreetMap', | ||
source: new ol.source.OSM() | source: new ol.source.OSM() | ||
- | }) | + | }) |
var esri_world = new ol.layer.Tile({ | var esri_world = new ol.layer.Tile({ | ||
title: 'ESRI World Imagery', | title: 'ESRI World Imagery', | ||
- | source: | + | source: new Esri.source( 'satellite' ) |
- | }) | + | }) |
var esri_street = new ol.layer.Tile({ | var esri_street = new ol.layer.Tile({ | ||
title: 'ESRI World Street Map', | title: 'ESRI World Street Map', | ||
- | source: | + | source: new Esri.source( 'street' ) |
- | }) | + | }) |
var watercolor = new ol.layer.Tile({ | var watercolor = new ol.layer.Tile({ | ||
title: 'Water color', | title: 'Water color', | ||
Line 231: | Line 244: | ||
url: '//stamen-tiles-{a-d}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg' | url: '//stamen-tiles-{a-d}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg' | ||
}) | }) | ||
- | }) | + | }) |
var osm_base = new ol.layer.Tile({ | var osm_base = new ol.layer.Tile({ | ||
title: 'OSM base', | title: 'OSM base', | ||
Line 238: | Line 251: | ||
url: 'http://{a-c}.tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png' | url: 'http://{a-c}.tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png' | ||
}) | }) | ||
- | }) | + | }) |
var no_background = new ol.layer.Vector({ | var no_background = new ol.layer.Vector({ | ||
title: 'Plain background', | title: 'Plain background', | ||
source: new ol.source.Vector({ | source: new ol.source.Vector({ | ||
}) | }) | ||
- | }) | + | }) |
- | + | if ( standalone ) { | |
- | + | overlays = [ | |
- | // esri_street, | + | openseamap, |
- | + | nx_layer_ovl, | |
- | + | ] | |
- | + | openseamap.set( 'visible', false ) | |
- | esri_world, | + | |
- | + | baseLayers = [ | |
+ | osm, | ||
+ | esri_world, | ||
+ | // esri_street, | ||
+ | // osm_base, | ||
+ | // no_background, | ||
+ | watercolor, | ||
+ | // nx_layer, | ||
+ | ] | ||
+ | } else { | ||
+ | overlays = [ | ||
+ | openseamap, | ||
+ | nx_layer_ovl, | ||
+ | ] | ||
+ | nx_layer_ovl.set( 'visible', false ) | ||
+ | |||
+ | baseLayers = [ | ||
+ | osm, | ||
+ | // esri_street, | ||
+ | // osm_base, | ||
+ | // no_background, | ||
+ | watercolor, | ||
+ | esri_world, | ||
+ | ] | ||
+ | } | ||
for (var i = 0; i < baseLayers.length; i++) { | for (var i = 0; i < baseLayers.length; i++) { | ||
- | baseLayers[i].set('type', 'base') | + | baseLayers[i].set( 'type' , 'base' ) |
- | baseLayers[i].set('visible', false) | + | baseLayers[i].set( 'visible' , false ) |
} | } | ||
- | baseLayers[baseLayers.length-1].set('visible', true) | + | baseLayers[baseLayers.length-1].set( 'visible', true ) |
var layers = [ | var layers = [ | ||
Line 297: | Line 334: | ||
}); | }); | ||
- | loadWikiCss('CruisersWiki:Ol3-layerswitcher.css') | + | Navionics.setAttribution( map, nx_layer_ovl ) |
- | + | ||
+ | loadWikiCss( 'CruisersWiki:Ol3-layerswitcher.css' ) | ||
+ | loadWikiJs( 'CruisersWiki: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: 'Légende' // Optional label for button | ||
}); | }); | ||
map.addControl(layerSwitcher); | map.addControl(layerSwitcher); | ||
- | }) | + | }) |
if (standalone) { | if (standalone) { | ||
Line 309: | Line 349: | ||
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(); | ||
} | } | ||
}; | }; | ||
+ | |||
+ | 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 | ||
Line 379: | Line 427: | ||
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 459: | ||
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 494: | ||
} | } | ||
}; | }; | ||
- | + | ||
this.styleLoadHooks.push(addFeature); | this.styleLoadHooks.push(addFeature); | ||
Line 452: | Line 501: | ||
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 512: | ||
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:Ol3-popup.css'); | loadWikiCss('CruisersWiki:Ol3-popup.css'); | ||
- | + | loadWikiJs( 'CruisersWiki:Ol3-popup.js' ) | |
+ | .then( this.initPopups.bind( this )) | ||
+ | |||
this.trackPointer(); | this.trackPointer(); | ||
this.highlightFeatures(); | this.highlightFeatures(); | ||
Line 482: | Line 533: | ||
ol3Chartlet.prototype.loadStyles = function () { | ol3Chartlet.prototype.loadStyles = function () { | ||
var this_ = this; | var this_ = this; | ||
- | + | loadWikiJs( 'CruisersWiki:Ol3chartlet-styles.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 553: | ||
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 563: | ||
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 529: | Line 579: | ||
); | ); | ||
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 622: | ||
} | } | ||
} | } | ||
- | + | ||
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 631: | ||
var highlight; | var highlight; | ||
- | + | ||
var highlightFeature = function(evt) { | var highlightFeature = function(evt) { | ||
if (evt.dragging) { | if (evt.dragging) { | ||
Line 587: | Line 637: | ||
} | } | ||
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 674: | Line 724: | ||
} | } | ||
- | 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> |
Revision as of 14:36, 27 June 2017
///* ol3Chartlet.js Copyright (c) 2016 Vadim Shlyakhov Licensed MIT */ Promise.all( [ // use debug version, to allow patch below loadJs( 'http://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol-debug.js'), loadCss( 'http://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol.css' ) ]) .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"; }; } }) .then( function () { var Navionics = { token: null, KEY: 'Navionics_webapi_00572', DOMAIN: 'www.cruiserswiki.org', BASE_TILE_SERVER: '//backend.navionics.io', TILE_SUFFIX: '/tile/{z}/{x}/{y}', KEY_REQ_SUFFIX: '/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.BASE_TILE_SERVER + Navionics.KEY_REQ_SUFFIX + '/' + Navionics.KEY + '/' + Navionics.DOMAIN return Navionics.token = Promise.resolve( $.ajax({ url: url, crossDomain: true, dataType: 'text', //cache: false, }) ) .catch( function( err ) { return console.log( 'Navionics.getToken', err ) }) } 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 ) }) } 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.BASE_TILE_SERVER + Navionics.TILE_SUFFIX + '?' + params } Navionics.setAttribution = function ( map, layers ) { if ( ! layers ) return if ( ! Array.isArray( layers )) layers = [ layers ] 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", 'hybrid': "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", }, } /* 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 ) var baselayersGroupName = 'Base'; var overlaysGroupName = 'Overlays'; 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 overlays var openseamap = new ol.layer.Tile({ title: 'OpenSeaMap', 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_ovl = new ol.layer.Tile({ title: 'Navionics Boating', source: new Navionics.source({ transparency: true }), }) var baseLayers var nx_layer = new ol.layer.Tile({ title: 'Navionics', source: new Navionics.source(), }) var osm = new ol.layer.Tile({ title: 'OpenStreetMap', source: new ol.source.OSM() }) var esri_world = new ol.layer.Tile({ title: 'ESRI World Imagery', source: new Esri.source( 'satellite' ) }) var esri_street = new ol.layer.Tile({ title: 'ESRI World Street Map', source: new Esri.source( 'street' ) }) var watercolor = new ol.layer.Tile({ title: 'Water color', source: new ol.source.Stamen({ layer: 'watercolor', //~ url: 'http://tile.stamen.com/watercolor/{z}/{x}/{y}.jpg' url: '//stamen-tiles-{a-d}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg' }) }) var osm_base = new ol.layer.Tile({ title: 'OSM base', source: new ol.source.OSM({ crossOrigin: null, url: 'http://{a-c}.tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png' }) }) var no_background = new ol.layer.Vector({ title: 'Plain background', source: new ol.source.Vector({ }) }) if ( standalone ) { overlays = [ openseamap, nx_layer_ovl, ] openseamap.set( 'visible', false ) baseLayers = [ osm, esri_world, // esri_street, // osm_base, // no_background, watercolor, // nx_layer, ] } else { overlays = [ openseamap, nx_layer_ovl, ] nx_layer_ovl.set( 'visible', false ) baseLayers = [ osm, // esri_street, // osm_base, // no_background, watercolor, esri_world, ] } for (var i = 0; i < baseLayers.length; i++) { baseLayers[i].set( 'type' , 'base' ) baseLayers[i].set( 'visible' , false ) } baseLayers[baseLayers.length-1].set( 'visible', true ) var layers = [ new ol.layer.Group({ title: baselayersGroupName, layers: baseLayers }), new ol.layer.Group({ title: overlaysGroupName, layers: overlays }) ]; 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' }) ]) }); Navionics.setAttribution( map, nx_layer_ovl ) loadWikiCss( 'CruisersWiki:Ol3-layerswitcher.css' ) loadWikiJs( 'CruisersWiki:Ol3-layerswitcher.js') .then( function () { var layerSwitcher = new ol.control.LayerSwitcher({ // tipLabel: 'Légende' // 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(); } }; 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().forEach( function(layer) { if (layer.get('title') === 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:Ol3-popup.css'); loadWikiJs( 'CruisersWiki: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( 'CruisersWiki:Ol3chartlet-styles.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) { return feature; }, null, 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); }; 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() }) ; //