mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-02-09 07:30:01 +00:00
Introduce geolayer widget for specifying layers for geomap
This commit is contained in:
parent
29f4d3488b
commit
7f4f48d4ba
@ -130,8 +130,8 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
|||||||
DataWidget.prototype.refresh = function(changedTiddlers) {
|
DataWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
// Refresh our attributes
|
// Refresh our attributes
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
// Refresh our children
|
// Refresh our children, and indicate that we refreshed if any of our attribute values have changed
|
||||||
return this.refreshChildren(changedTiddlers);
|
return this.refreshChildren(changedTiddlers) || $tw.utils.count(changedAttributes) > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.data = DataWidget;
|
exports.data = DataWidget;
|
||||||
|
@ -100,7 +100,7 @@ TestCaseWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
this.refreshSelf();
|
this.refreshSelf();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return this.contentRoot.refresh(changedTiddlers);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,9 +20,14 @@ This demo requires that the API keys needed to access external services be obtai
|
|||||||
! Map Showing All Features and Markers
|
! Map Showing All Features and Markers
|
||||||
|
|
||||||
<$geomap
|
<$geomap
|
||||||
markers="[all[tiddlers+shadows]tag[$:/tags/GeoMarker]]"
|
|
||||||
features="[all[tiddlers+shadows]tag[$:/tags/GeoFeature]]"
|
|
||||||
state=<<qualify "$:/state/demo-map">>
|
state=<<qualify "$:/state/demo-map">>
|
||||||
/>
|
>
|
||||||
|
<$list filter="[all[tiddlers+shadows]tag[$:/tags/GeoMarker]]">
|
||||||
|
<$geolayer lat={{!!lat}} long={{!!long}} alt={{!!alt}} color={{!!color}}/>
|
||||||
|
</$list>
|
||||||
|
<$list filter="[all[tiddlers+shadows]tag[$:/tags/GeoFeature]]">
|
||||||
|
<$geolayer json={{!!text}} color={{!!color}}/>
|
||||||
|
</$list>
|
||||||
|
</$geomap>
|
||||||
|
|
||||||
<<tabs tabsList:"[all[tiddlers+shadows]tag[$:/tags/GeospatialDemo]]" default:"GeoMarkers">>
|
<<tabs tabsList:"[all[tiddlers+shadows]tag[$:/tags/GeospatialDemo]]" default:"GeoMarkers">>
|
||||||
|
@ -10,11 +10,11 @@ title: ui/geofeature
|
|||||||
|
|
||||||
!! Mapped
|
!! Mapped
|
||||||
|
|
||||||
|
|
||||||
<$geomap
|
<$geomap
|
||||||
features="[<currentTiddler>]"
|
|
||||||
state=<<qualify "$:/state/demo-map">>
|
state=<<qualify "$:/state/demo-map">>
|
||||||
/>
|
>
|
||||||
|
<$geolayer json={{!!text}} color={{!!color}}/>
|
||||||
|
</$geomap>
|
||||||
|
|
||||||
!! Intersect with other features
|
!! Intersect with other features
|
||||||
|
|
||||||
|
@ -64,9 +64,10 @@ title: ui/geomarker
|
|||||||
!! Mapped
|
!! Mapped
|
||||||
|
|
||||||
<$geomap
|
<$geomap
|
||||||
markers="[<currentTiddler>]"
|
|
||||||
state=<<qualify "$:/state/demo-map">>
|
state=<<qualify "$:/state/demo-map">>
|
||||||
/>
|
>
|
||||||
|
<$geolayer lat={{!!lat}} long={{!!long}} alt={{!!alt}} color={{!!color}}/>
|
||||||
|
</$geomap>
|
||||||
|
|
||||||
!! Distance to other markers
|
!! Distance to other markers
|
||||||
|
|
||||||
|
@ -49,8 +49,11 @@ Click to get photos of user
|
|||||||
|
|
||||||
<$geomap
|
<$geomap
|
||||||
state=<<qualify "$:/state/demo-map">>
|
state=<<qualify "$:/state/demo-map">>
|
||||||
markers="[all[tiddlers+shadows]tag[$:/tags/FlickrPhoto]]"
|
>
|
||||||
/>
|
<$list filter="[all[tiddlers+shadows]tag[$:/tags/FlickrPhoto]]">
|
||||||
|
<$geolayer lat={{!!lat}} long={{!!long}} alt={{!!alt}} color={{!!color}}/>
|
||||||
|
</$list>
|
||||||
|
</$geomap>
|
||||||
"""/>
|
"""/>
|
||||||
</$testcase>
|
</$testcase>
|
||||||
|
|
||||||
@ -74,8 +77,11 @@ Click to get photos from group
|
|||||||
|
|
||||||
<$geomap
|
<$geomap
|
||||||
state=<<qualify "$:/state/demo-map">>
|
state=<<qualify "$:/state/demo-map">>
|
||||||
markers="[all[tiddlers+shadows]tag[$:/tags/FlickrPhoto]]"
|
>
|
||||||
/>
|
<$list filter="[all[tiddlers+shadows]tag[$:/tags/FlickrPhoto]]">
|
||||||
|
<$geolayer lat={{!!lat}} long={{!!long}} alt={{!!alt}} color={{!!color}}/>
|
||||||
|
</$list>
|
||||||
|
</$geomap>
|
||||||
"""/>
|
"""/>
|
||||||
</$testcase>
|
</$testcase>
|
||||||
|
|
||||||
@ -99,8 +105,11 @@ Click to get photos from album
|
|||||||
|
|
||||||
<$geomap
|
<$geomap
|
||||||
state=<<qualify "$:/state/demo-map">>
|
state=<<qualify "$:/state/demo-map">>
|
||||||
markers="[all[tiddlers+shadows]tag[$:/tags/FlickrPhoto]]"
|
>
|
||||||
/>
|
<$list filter="[all[tiddlers+shadows]tag[$:/tags/FlickrPhoto]]">
|
||||||
|
<$geolayer lat={{!!lat}} long={{!!long}} alt={{!!alt}} color={{!!color}}/>
|
||||||
|
</$list>
|
||||||
|
</$geomap>
|
||||||
"""/>
|
"""/>
|
||||||
</$testcase>
|
</$testcase>
|
||||||
|
|
||||||
@ -123,7 +132,10 @@ Click to get interesting photos
|
|||||||
|
|
||||||
<$geomap
|
<$geomap
|
||||||
state=<<qualify "$:/state/demo-map">>
|
state=<<qualify "$:/state/demo-map">>
|
||||||
markers="[all[tiddlers+shadows]tag[$:/tags/FlickrPhoto]]"
|
>
|
||||||
/>
|
<$list filter="[all[tiddlers+shadows]tag[$:/tags/FlickrPhoto]]">
|
||||||
|
<$geolayer lat={{!!lat}} long={{!!long}} alt={{!!alt}} color={{!!color}}/>
|
||||||
|
</$list>
|
||||||
|
</$geomap>
|
||||||
"""/>
|
"""/>
|
||||||
</$testcase>
|
</$testcase>
|
||||||
|
20
plugins/tiddlywiki/geospatial/docs/geolayer.tid
Normal file
20
plugins/tiddlywiki/geospatial/docs/geolayer.tid
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
title: $:/plugins/tiddlywiki/geospatial/docs/geolayer
|
||||||
|
caption: geolayer widget
|
||||||
|
tags: $:/tags/GeospatialDocs
|
||||||
|
|
||||||
|
!! `<$geolayer>` widget
|
||||||
|
|
||||||
|
The `<$geolayer>` widget is used inside the `<$geomap>` widget to indicate the layers and markers to display.
|
||||||
|
|
||||||
|
The following attributes are supported:
|
||||||
|
|
||||||
|
|!Attribute |!Description |
|
||||||
|
|''json'' |Optional GeoJSON Feature Collection to be rendered |
|
||||||
|
|''lat'' |Optional latitude of marker if json attribute missing |
|
||||||
|
|''long'' |Optional longitude of marker if json attribute missing |
|
||||||
|
|''alt'' |Optional altitude of marker if json attribute missing |
|
||||||
|
|
||||||
|
Note that the `<$geolayer>` widget can be used in one of two modes:
|
||||||
|
|
||||||
|
* With the ''json'' attibute specifying the layer to be drawn
|
||||||
|
* With the ''lat'', ''long'' and optional ''alt'' attributes specifying a marker to be drawn
|
@ -4,15 +4,12 @@ tags: $:/tags/GeospatialDocs
|
|||||||
|
|
||||||
!! `<$geomap>` widget
|
!! `<$geomap>` widget
|
||||||
|
|
||||||
The `<$geomap>` widget displays an interactive map using [[Leaflet.js|https://leafletjs.com/]].
|
The `<$geomap>` widget displays an interactive map using [[Leaflet.js|https://leafletjs.com/]]. `<$geolayer>` widgets inside the `<$geomap>` widget are used to indicate the layers and markers to display.
|
||||||
|
|
||||||
The following attributes are supported:
|
The following attributes are supported:
|
||||||
|
|
||||||
|!Attribute |!Description |
|
|!Attribute |!Description |
|
||||||
|''state'' |The title of a state tiddler used to track the state of the map in the `zoom`, `long` and `lat` fields |
|
|''state'' |The title of a state tiddler used to track the state of the map in the `zoom`, `long` and `lat` fields |
|
||||||
|''features'' |A filter identifying the GeoJSON feature tiddlers to be displayed on the map |
|
|
||||||
|''markers'' |A filter identifying the GeoJSON marker tiddlers to be displayed on the map |
|
|
||||||
|
|
||||||
|
|
||||||
!! Examples
|
!! Examples
|
||||||
|
|
||||||
@ -45,8 +42,11 @@ The following attributes are supported:
|
|||||||
text="""This is Oxford!"""/>
|
text="""This is Oxford!"""/>
|
||||||
<$data title="Output" text="""<$geomap
|
<$data title="Output" text="""<$geomap
|
||||||
state=<<qualify "$:/state/demo-map">>
|
state=<<qualify "$:/state/demo-map">>
|
||||||
markers="[all[tiddlers+shadows]tag[$:/tags/GeoMarker]]"
|
>
|
||||||
/>
|
<$list filter="[all[tiddlers+shadows]tag[$:/tags/GeoMarker]]">
|
||||||
|
<$geolayer lat={{!!lat}} long={{!!long}} alt={{!!alt}} color={{!!color}}/>
|
||||||
|
</$list>
|
||||||
|
</$geomap>
|
||||||
"""/>
|
"""/>
|
||||||
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
|
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
|
||||||
</$testcase>
|
</$testcase>
|
||||||
@ -87,8 +87,19 @@ The following attributes are supported:
|
|||||||
}"""/>
|
}"""/>
|
||||||
<$data title="Output" text="""<$geomap
|
<$data title="Output" text="""<$geomap
|
||||||
state=<<qualify "$:/state/demo-map">>
|
state=<<qualify "$:/state/demo-map">>
|
||||||
features="[all[tiddlers+shadows]tag[$:/tags/GeoFeature]]"
|
>
|
||||||
/>
|
<$list filter="[all[tiddlers+shadows]tag[$:/tags/GeoFeature]]">
|
||||||
|
<$geolayer json={{!!text}} color={{!!color}}/>
|
||||||
|
</$list>
|
||||||
|
</$geomap>
|
||||||
"""/>
|
"""/>
|
||||||
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
|
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
|
||||||
</$testcase>
|
</$testcase>
|
||||||
|
|
||||||
|
<$testcase>
|
||||||
|
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/widgets/geomap"/>
|
||||||
|
</$testcase>
|
||||||
|
|
||||||
|
<$testcase>
|
||||||
|
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/widgets/geomap-refresh"/>
|
||||||
|
</$testcase>
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
title: $:/plugins/tiddlywiki/geospatial/tests/widgets/geomap-refresh
|
||||||
|
description: refreshing of geomap widget
|
||||||
|
type: text/vnd.tiddlywiki-multiple
|
||||||
|
tags: [[$:/tags/wiki-test-spec]]
|
||||||
|
|
||||||
|
title: Description
|
||||||
|
text: Map using dynamic geolayer to represent features
|
||||||
|
+
|
||||||
|
title: Layer
|
||||||
|
tags: $:/tags/GeoFeature
|
||||||
|
type: application/json
|
||||||
|
color: red
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"id": "An example geofeature feature",
|
||||||
|
"properties": {
|
||||||
|
"custom": "A custom property of this feature",
|
||||||
|
"color": "#ff8"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[-90,35],
|
||||||
|
[-90,30],
|
||||||
|
[-85,30],
|
||||||
|
[-85,35],
|
||||||
|
[-90,35]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
+
|
||||||
|
title: Output
|
||||||
|
|
||||||
|
<$button>
|
||||||
|
<$action-setfield $tiddler="$:/state/layer" $value="yes"/>
|
||||||
|
Click here to enable the layer
|
||||||
|
</$button>
|
||||||
|
|
||||||
|
<$geomap
|
||||||
|
state=<<qualify "$:/state/demo-map">>
|
||||||
|
>
|
||||||
|
<$geolayer
|
||||||
|
json={{{ [{$:/state/layer}match[yes]then{Layer}else[]] }}}
|
||||||
|
colorFilter="[<currentTiddler>jsonget[properties],[color]else[red]]"
|
||||||
|
/>
|
||||||
|
</$geomap>
|
||||||
|
+
|
||||||
|
title: ExpectedResult
|
||||||
|
|
||||||
|
<p>Winchester,Oxford,</p>
|
53
plugins/tiddlywiki/geospatial/tests/widgets/geomap.tid
Normal file
53
plugins/tiddlywiki/geospatial/tests/widgets/geomap.tid
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
title: $:/plugins/tiddlywiki/geospatial/tests/widgets/geomap
|
||||||
|
description: geomap widget
|
||||||
|
type: text/vnd.tiddlywiki-multiple
|
||||||
|
tags: [[$:/tags/wiki-test-spec]]
|
||||||
|
|
||||||
|
title: Description
|
||||||
|
text: Map using geolayer to represent features
|
||||||
|
+
|
||||||
|
title: Layer
|
||||||
|
tags: $:/tags/GeoFeature
|
||||||
|
type: application/json
|
||||||
|
color: red
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"id": "An example geofeature feature",
|
||||||
|
"properties": {
|
||||||
|
"custom": "A custom property of this feature",
|
||||||
|
"color": "#ff8"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[-90,35],
|
||||||
|
[-90,30],
|
||||||
|
[-85,30],
|
||||||
|
[-85,35],
|
||||||
|
[-90,35]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
+
|
||||||
|
title: Output
|
||||||
|
|
||||||
|
<$geomap
|
||||||
|
state=<<qualify "$:/state/demo-map">>
|
||||||
|
>
|
||||||
|
<$geolayer
|
||||||
|
json={{Layer}}
|
||||||
|
colorFilter="[<currentTiddler>jsonget[properties],[color]else[red]]"
|
||||||
|
/>
|
||||||
|
</$geomap>
|
||||||
|
+
|
||||||
|
title: ExpectedResult
|
||||||
|
|
||||||
|
<p>Winchester,Oxford,</p>
|
17
plugins/tiddlywiki/geospatial/widgets/geolayer.js
Normal file
17
plugins/tiddlywiki/geospatial/widgets/geolayer.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/plugins/tiddlywiki/innerwiki/geolayer.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget
|
||||||
|
|
||||||
|
geolayer widget to represent a layer for a geomap widget. Clone of the data widget
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.geolayer = require("$:/core/modules/widgets/data.js").data;
|
||||||
|
|
||||||
|
})();
|
@ -31,28 +31,40 @@ GeomapWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
this.parentDomNode = parent;
|
this.parentDomNode = parent;
|
||||||
this.computeAttributes();
|
this.computeAttributes();
|
||||||
this.execute();
|
this.execute();
|
||||||
|
// Render the children into a hidden DOM node
|
||||||
|
var parser = {
|
||||||
|
tree: [{
|
||||||
|
type: "widget",
|
||||||
|
attributes: {},
|
||||||
|
orderedAttributes: [],
|
||||||
|
children: this.parseTreeNode.children || []
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
this.contentRoot = this.wiki.makeWidget(parser,{
|
||||||
|
document: $tw.fakeDocument,
|
||||||
|
parentWidget: this
|
||||||
|
});
|
||||||
|
this.contentContainer = $tw.fakeDocument.createElement("div");
|
||||||
|
this.contentRoot.render(this.contentContainer,null);
|
||||||
// Render a wrapper for the map
|
// Render a wrapper for the map
|
||||||
var domNode = this.document.createElement("div");
|
this.domNode = this.document.createElement("div");
|
||||||
domNode.style.width = "100%";
|
this.domNode.style.width = "100%";
|
||||||
domNode.style.height = "600px";
|
this.domNode.style.height = "600px";
|
||||||
// Insert it into the DOM
|
// Insert it into the DOM
|
||||||
parent.insertBefore(domNode,nextSibling);
|
parent.insertBefore(this.domNode,nextSibling);
|
||||||
this.domNodes.push(domNode);
|
this.domNodes.push(this.domNode);
|
||||||
// Render the map
|
// Render the map
|
||||||
if($tw.browser) {
|
if($tw.browser) {
|
||||||
this.renderMap(domNode);
|
this.renderMap();
|
||||||
|
this.refreshMap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
GeomapWidget.prototype.renderMap = function(domNode) {
|
GeomapWidget.prototype.renderMap = function() {
|
||||||
var self = this;
|
|
||||||
// Create the map
|
// Create the map
|
||||||
this.map = $tw.Leaflet.map(domNode);
|
this.map = $tw.Leaflet.map(this.domNode);
|
||||||
// Set the position
|
// No layers rendered
|
||||||
if(!this.setMapView()) {
|
this.renderedLayers = [];
|
||||||
// Default to showing the whole world
|
|
||||||
this.map.fitWorld();
|
|
||||||
}
|
|
||||||
// Setup the tile layer
|
// Setup the tile layer
|
||||||
const tiles = $tw.Leaflet.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
const tiles = $tw.Leaflet.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
maxZoom: 19,
|
maxZoom: 19,
|
||||||
@ -60,6 +72,22 @@ GeomapWidget.prototype.renderMap = function(domNode) {
|
|||||||
}).addTo(this.map);
|
}).addTo(this.map);
|
||||||
// Disable Leaflet attribution
|
// Disable Leaflet attribution
|
||||||
this.map.attributionControl.setPrefix("");
|
this.map.attributionControl.setPrefix("");
|
||||||
|
// Add scale
|
||||||
|
$tw.Leaflet.control.scale().addTo(this.map);
|
||||||
|
};
|
||||||
|
|
||||||
|
GeomapWidget.prototype.refreshMap = function() {
|
||||||
|
var self = this;
|
||||||
|
// Remove any previously rendered layers
|
||||||
|
$tw.utils.each(this.renderedLayers,function(layer) {
|
||||||
|
self.map.removeLayer(layer);
|
||||||
|
});
|
||||||
|
this.renderedLayers = [];
|
||||||
|
// Set the position
|
||||||
|
if(!this.setMapView()) {
|
||||||
|
// Default to showing the whole world
|
||||||
|
this.map.fitWorld();
|
||||||
|
}
|
||||||
// Create default icon
|
// Create default icon
|
||||||
const iconProportions = 365/560,
|
const iconProportions = 365/560,
|
||||||
iconHeight = 50;
|
iconHeight = 50;
|
||||||
@ -69,8 +97,6 @@ GeomapWidget.prototype.renderMap = function(domNode) {
|
|||||||
iconAnchor: [(iconHeight * iconProportions) / 2, iconHeight], // Position of the anchor within the icon
|
iconAnchor: [(iconHeight * iconProportions) / 2, iconHeight], // Position of the anchor within the icon
|
||||||
popupAnchor: [0, -iconHeight] // Position of the popup anchor relative to the icon anchor
|
popupAnchor: [0, -iconHeight] // Position of the popup anchor relative to the icon anchor
|
||||||
});
|
});
|
||||||
// Add scale
|
|
||||||
$tw.Leaflet.control.scale().addTo(this.map);
|
|
||||||
// Listen for pan and zoom events and update the state tiddler
|
// Listen for pan and zoom events and update the state tiddler
|
||||||
this.map.on("moveend zoomend",function(event) {
|
this.map.on("moveend zoomend",function(event) {
|
||||||
if(self.geomapStateTitle) {
|
if(self.geomapStateTitle) {
|
||||||
@ -90,24 +116,43 @@ GeomapWidget.prototype.renderMap = function(domNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Track the geofeatures filter
|
// Make a marker cluster
|
||||||
this.trackerGeoFeaturesFilter = new FilterTracker({
|
var markers = $tw.Leaflet.markerClusterGroup({
|
||||||
wiki: this.wiki,
|
maxClusterRadius: 40
|
||||||
widget: this,
|
});
|
||||||
filter: this.geomapFeaturesFilter,
|
this.map.addLayer(markers);
|
||||||
enter: function(title,tiddler) {
|
// Process embedded geolayer widgets
|
||||||
var text = (tiddler && tiddler.fields.text) || "[]",
|
this.findChildrenDataWidgets(this.contentRoot.children,"geolayer",function(widget) {
|
||||||
geoJson = $tw.utils.parseJSONSafe(text,[]),
|
var jsonText = widget.getAttribute("json"),
|
||||||
layer = $tw.Leaflet.geoJSON(geoJson,{
|
geoJson = [];
|
||||||
|
if(jsonText) {
|
||||||
|
geoJson = $tw.utils.parseJSONSafe(jsonText,[]);
|
||||||
|
} else if(widget.hasAttribute("lat") && widget.hasAttribute("long")) {
|
||||||
|
var lat = $tw.utils.parseNumber(widget.getAttribute("lat","0")),
|
||||||
|
long = $tw.utils.parseNumber(widget.getAttribute("long","0")),
|
||||||
|
alt = $tw.utils.parseNumber(widget.getAttribute("alt","0"));
|
||||||
|
geoJson = {
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [long,lat,alt]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var layer = $tw.Leaflet.geoJSON(geoJson,{
|
||||||
style: function(geoJsonFeature) {
|
style: function(geoJsonFeature) {
|
||||||
return {
|
return {
|
||||||
color: (tiddler && tiddler.getFieldString("color")) || "yellow"
|
color: widget.getAttribute("color","yellow")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pointToLayer: function(geoJsonPoint,latlng) {
|
pointToLayer: function(geoJsonPoint,latlng) {
|
||||||
return L.circleMarker(latlng,{
|
$tw.Leaflet.marker(latlng,{icon: myIcon,draggable: false}).addTo(markers);
|
||||||
radius: 8
|
return markers;
|
||||||
});
|
|
||||||
},
|
},
|
||||||
onEachFeature: function(feature,layer) {
|
onEachFeature: function(feature,layer) {
|
||||||
if(feature.properties) {
|
if(feature.properties) {
|
||||||
@ -115,40 +160,7 @@ GeomapWidget.prototype.renderMap = function(domNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).addTo(self.map);
|
}).addTo(self.map);
|
||||||
return layer;
|
self.renderedLayers.push(layer);
|
||||||
},
|
|
||||||
leave: function(title,tiddler,data) {
|
|
||||||
data.remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Track the geomarkers filter
|
|
||||||
var markers = $tw.Leaflet.markerClusterGroup({
|
|
||||||
maxClusterRadius: 40
|
|
||||||
});
|
|
||||||
this.map.addLayer(markers);
|
|
||||||
this.trackerGeoMarkersFilter = new FilterTracker({
|
|
||||||
wiki: this.wiki,
|
|
||||||
widget: this,
|
|
||||||
filter: this.geomapMarkerFilter,
|
|
||||||
enter: function(title,tiddler) {
|
|
||||||
var lat = $tw.utils.parseNumber((tiddler && tiddler.fields.lat) || "0"),
|
|
||||||
long = $tw.utils.parseNumber((tiddler && tiddler.fields.long) || "0"),
|
|
||||||
alt = $tw.utils.parseNumber((tiddler && tiddler.fields.alt) || "0"),
|
|
||||||
caption = (tiddler && tiddler.fields.caption) || title,
|
|
||||||
icon = myIcon;
|
|
||||||
if(tiddler && tiddler.fields["icon-url"]) {
|
|
||||||
icon = new $tw.Leaflet.Icon({
|
|
||||||
iconUrl: tiddler && tiddler.fields["icon-url"],
|
|
||||||
iconSize: [32, 32], // Size of the icon
|
|
||||||
iconAnchor: [16, 32], // Position of the anchor within the icon
|
|
||||||
popupAnchor: [16, -32] // Position of the popup anchor relative to the icon anchor
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return $tw.Leaflet.marker([lat,long,alt],{icon: icon,draggable: false}).bindPopup(caption).addTo(markers);
|
|
||||||
},
|
|
||||||
leave: function(title,tiddler,data) {
|
|
||||||
data.remove();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -169,8 +181,6 @@ Compute the internal state of the widget
|
|||||||
*/
|
*/
|
||||||
GeomapWidget.prototype.execute = function() {
|
GeomapWidget.prototype.execute = function() {
|
||||||
this.geomapStateTitle = this.getAttribute("state");
|
this.geomapStateTitle = this.getAttribute("state");
|
||||||
this.geomapMarkerFilter = this.getAttribute("markers");
|
|
||||||
this.geomapFeaturesFilter = this.getAttribute("features");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -178,11 +188,6 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
|
|||||||
*/
|
*/
|
||||||
GeomapWidget.prototype.refresh = function(changedTiddlers) {
|
GeomapWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
// Refresh entire widget if layers or marker filter changes
|
|
||||||
if(changedAttributes.features || changedAttributes.markers || changedAttributes.state) {
|
|
||||||
this.refreshSelf();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Set zoom and position if the state tiddler has changed
|
// Set zoom and position if the state tiddler has changed
|
||||||
if(changedAttributes.state) {
|
if(changedAttributes.state) {
|
||||||
this.geomapStateTitle = this.getAttribute("state");
|
this.geomapStateTitle = this.getAttribute("state");
|
||||||
@ -190,63 +195,15 @@ GeomapWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
if(changedAttributes.state || changedTiddlers[this.geomapStateTitle]) {
|
if(changedAttributes.state || changedTiddlers[this.geomapStateTitle]) {
|
||||||
this.setMapView();
|
this.setMapView();
|
||||||
}
|
}
|
||||||
// Check whether the layers or markers need updating
|
// Refresh child nodes, and rerender map if there have been any changes
|
||||||
this.trackerGeoFeaturesFilter.refresh(changedTiddlers);
|
var result = this.contentRoot.refresh(changedTiddlers);
|
||||||
this.trackerGeoMarkersFilter.refresh(changedTiddlers);
|
if(result) {
|
||||||
// No children to refresh
|
this.refreshMap();
|
||||||
return false;
|
}
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.geomap = GeomapWidget;
|
exports.geomap = GeomapWidget;
|
||||||
|
|
||||||
function FilterTracker(options) {
|
|
||||||
var self = this;
|
|
||||||
// Save parameters
|
|
||||||
this.filter = options.filter;
|
|
||||||
this.wiki = options.wiki;
|
|
||||||
this.widget = options.widget;
|
|
||||||
this.enter = options.enter;
|
|
||||||
this.leave = options.leave;
|
|
||||||
this.update = options.update;
|
|
||||||
// Calculate initial result set and call enter for each entry
|
|
||||||
this.items = Object.create(null);
|
|
||||||
$tw.utils.each(this.wiki.filterTiddlers(this.filter,this.widget),function(title) {
|
|
||||||
self.items[title] = self.enter(title,self.wiki.getTiddler(title));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
FilterTracker.prototype.refresh = function(changedTiddlers) {
|
|
||||||
var self = this;
|
|
||||||
var newItems = this.wiki.filterTiddlers(this.filter,this.widget);
|
|
||||||
// Go through the new items and call update or enter as appropriate
|
|
||||||
$tw.utils.each(newItems,function(title) {
|
|
||||||
// Check if this item is already known
|
|
||||||
if(title in self.items) {
|
|
||||||
// Issue an update if the underlying tiddler has changed
|
|
||||||
if(changedTiddlers[title]) {
|
|
||||||
// Use the update method if provided
|
|
||||||
if(self.update) {
|
|
||||||
self.update(title,self.wiki.getTiddler(title),self.items[title]);
|
|
||||||
} else {
|
|
||||||
// Otherwise leave and enter is equivalent to update
|
|
||||||
self.leave(title,self.wiki.getTiddler(title),self.items[title]);
|
|
||||||
self.items[title] = self.enter(title,self.wiki.getTiddler(title));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// It's a new item, so we need to enter it
|
|
||||||
self.items[title] = self.enter(title,self.wiki.getTiddler(title));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Call leave for any items that are no longer in the list
|
|
||||||
$tw.utils.each(Object.keys(this.items),function(title) {
|
|
||||||
if(newItems.indexOf(title) === -1) {
|
|
||||||
// Remove this item
|
|
||||||
self.leave(title,self.wiki.getTiddler(title),self.items[title]);
|
|
||||||
delete self.items[title];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user