/*
MapBBCode, a JavaScript library for parsing, displaying and editing [map] code.
Version 1.2.0 built on 25.12.2013
http://mapbbcode.org
(c) 2013, Ilya Zverev
*/
(function (window, document, undefined) {
var L = window.L;
/*
* List of public-use layers.
*/
window._tempLL = window.layerList;
window.layerList = {
// some entries in this list were adapted from the https://github.com/leaflet-extras/leaflet-providers list (it has BSD 2-clause license)
list: {
"OpenStreetMap": "L.tileLayer('http://tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Map © OpenStreetMap', minZoom: 0, maxZoom: 19 })",
"OpenStreetMap DE": "L.tileLayer('http://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', { attribution: 'Map © OpenStreetMap', minZoom: 0, maxZoom: 18 })",
"OpenStreetMap FR": "L.tileLayer('http://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', { subdomains: 'abc', attribution: 'Map © OpenStreetMap | Tiles © OSM France', minZoom: 0, maxZoom: 20 })",
"Hike & Bike": "L.layerGroup([ L.tileLayer('http://toolserver.org/tiles/hikebike/{z}/{x}/{y}.png', { attribution: 'Map © OSM | Tiles © Colin Marquardt' } ), L.tileLayer('http://toolserver.org/~cmarqu/hill/{z}/{x}/{y}.png', { minZoom: 0, maxZoom: 17 }) ])",
"CycleMap": "L.tileLayer('http://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png', { attribution: 'Map © OSM | Tiles © Andy Allan', minZoom: 0, maxZoom: 18 })",
"OpenMapSurfer": "L.tileLayer('http://openmapsurfer.uni-hd.de/tiles/roads/x={x}&y={y}&z={z}', { attribution: 'Map © OSM | Tiles © GIScience Heidelberg', minZoom: 0, maxZoom: 19 })",
"OpenMapSurfer Contour": "L.layerGroup([ L.tileLayer('http://openmapsurfer.uni-hd.de/tiles/roads/x={x}&y={y}&z={z}', { attribution: 'Map © OSM | Tiles © GIScience Heidelberg', minZoom: 0, maxZoom: 19 }), L.tileLayer('http://openmapsurfer.uni-hd.de/tiles/asterc/x={x}&y={y}&z={z}') ])",
"OpenMapSurfer Grayscale": "L.tileLayer('http://openmapsurfer.uni-hd.de/tiles/roadsg/x={x}&y={y}&z={z}', { attribution: 'Map © OSM | Tiles © GIScience Heidelberg', minZoom: 0, maxZoom: 19 })",
"Humanitarian": "L.tileLayer('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', { attribution: 'Map © OpenStreetMap | Tiles © Humanitarian OSM Team', minZoom: 0, maxZoom: 19 })",
"Transport": "L.tileLayer('http://{s}.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png', { attribution: 'Map © OSM | Tiles © Andy Allan', minZoom: 0, maxZoom: 18 })",
"Landscape": "L.tileLayer('http://{s}.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png', { attribution: 'Map © OSM | Tiles © Andy Allan', minZoom: 0, maxZoom: 18 })",
"Outdoors": "L.tileLayer('http://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png', { attribution: 'Map © OSM | Tiles © Andy Allan', minZoom: 0, maxZoom: 18 })",
"MapQuest Open": "L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpeg', { attribution: 'Map © OSM | Tiles © MapQuest', subdomains: '1234', minZoom: 0, maxZoom: 18 })",
"Stamen Toner": "L.tileLayer('http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png', { attribution: 'Map © OSM | Tiles © Stamen Design', minZoom: 0, maxZoom: 20 })",
"Stamen Toner Lite": "L.tileLayer('http://{s}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png', { attribution: 'Map © OSM | Tiles © Stamen Design', minZoom: 0, maxZoom: 20 })",
"Stamen Watercolor": "L.tileLayer('http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.png', { attribution: 'Map © OSM | Tiles © Stamen Design', minZoom: 3, maxZoom: 16 })",
"Cloudmade": "L.tileLayer('http://{s}.tile.cloudmade.com/{apiKey}/{styleID}/256/{z}/{x}/{y}.png', { attribution: 'Map © OSM | Tiles © CloudMade', apiKey: '{key:http://account.cloudmade.com/register}', styleID: '1', minZoom: 0, maxZoom: 18 })",
"MapBox": "L.tileLayer('http://{s}.tiles.mapbox.com/v3/{key:https://www.mapbox.com/#signup}/{z}/{x}/{y}.png', { subdomains: 'abcd', attribution: 'Map © OpenStreetMap' })"
},
getSortedKeys: function() {
var result = [], k;
for( k in this.list )
if( this.list.hasOwnProperty(k) )
result.push(k);
result.sort();
return result;
},
requiresKey: function( layer ) {
var reKeyC = /{key(?::[^}]+)?}/,
l = this.list[layer];
return l && reKeyC.test(l);
},
getKeyLink: function( layer ) {
var reKeyC = /{key:([^}]+)}/,
l = this.list[layer],
m = l && l.match(reKeyC);
return m && m.length > 1 && m[1] ? m[1] : '';
},
getLayerName: function( layer ) {
if( typeof layer !== 'string' )
return '';
var p1 = layer.indexOf(':'),
p2 = layer.indexOf('|'),
p = p1 > p2 && p2 > 0 ? p2 : p1;
return p > 0 ? layer.substring(0, p) : layer;
},
getLeafletLayer: function( layerId, LL ) {
/* jshint unused: false */
var L = LL || window.L,
reKeyC = /{key(?::[^}]+)?}/,
m = layerId.match(/^(.+?\|)?(.+?)(?::([^'"]+))?$/);
var idx = m && m.length > 2 && m[2] ? m[2] : '',
title = m && m.length > 1 && m[1] && m[1].length > 0 ? m[1] : idx,
keys = m && m.length > 3 && m[3] ? m[3].split(':') : [];
if( this.list[idx] ) {
var layer = this.list[idx], keyPos = 0;
while( reKeyC.test(layer) && keyPos < keys.length ) {
layer = layer.replace(reKeyC, keys[keyPos++]);
}
if( !reKeyC.test(layer) ) {
try {
var done = eval(layer);
if( done ) {
if( !done.options )
done.options = {};
done.options.name = title;
return done;
}
} catch(e) {}
}
}
return null;
},
getLeafletLayers: function( layers, LL ) {
var l = typeof layers === 'string' ? layers.split(',') : layers,
result = [], i, osmidx = -1;
for( i = 0; i < l.length; i++ ) {
var layer = this.getLeafletLayer(l[i], LL);
if( layer ) {
result.push(layer);
if( osmidx < 0 && this.isOpenStreetMapLayer(layer) )
osmidx = result.length - 1;
}
}
if( osmidx > 0 ) {
var tmp = result[osmidx];
result[osmidx] = result[0];
result[0] = tmp;
} else if( osmidx < 0 && result.length > 0 ) {
result.unshift(this.getLeafletLayer('OpenStreetMap', LL));
}
return result;
},
isOpenStreetMapLayer: function( layer ) {
if( typeof layer === 'string' || layer.substring )
return layer.indexOf('openstreetmap.org') > 0;
var l = layer.options && layer._url ? layer : (layer.getLayers ? layer.getLayers()[0] : {});
if( l.options && l._url )
return (l.options.attribution && l.options.attribution.indexOf('openstreetmap.org') > 0) || l._url.indexOf('tile.openstreetmap.') > 0 || l._url.indexOf('opencyclemap.org') > 0 || l._url.indexOf('stamen.com') > 0 || l._url.indexOf('server.arcgisonline.com') > 0;
return false;
}
};
// merge layerList entries that were added before this script was loaded
if( window._tempLL ) {
if( window._tempLL.list ) {
var i;
for( i in window._tempLL.list ) {
if( window._tempLL.list.hasOwnProperty(i) )
window.layerList.list[i] = window._tempLL.list[i];
}
}
delete window._tempLL;
}
/*
* Configuration panel for some of MapBBCodeUI properties
* Callback is invoked every time any of the options is changed
*/
window.MapBBCodeConfig = L.Class.extend({
includes: L.Mixin.Events,
options: {
layers: [],
defaultZoom: 2,
defaultPosition: [22, 11],
viewWidth: 600,
viewHeight: 300,
fullViewHeight: 600,
editorHeight: 400,
windowWidth: 800,
windowHeight: 500,
fullFromStart: false,
editorInWindow: true,
editorTypeFixed: false,
maxLayers: 5
},
strings: {},
initialize: function( options ) {
L.setOptions(this, options);
},
setStrings: function( strings ) {
this.strings = L.extend({}, this.strings, strings);
},
addLayer: function( id ) {
this._layerSwitcher.addLayer(id);
},
_updateDivSize:function (el) {
var width, height, mode = this._mode;
if( mode === 'view' && this.options.fullFromStart )
mode = 'full';
if( mode === 'edit' && this.options.editorInWindow )
mode = 'window';
if( mode === 'view' ) {
width = '' + this.options.viewWidth + 'px';
height = '' + this.options.viewHeight + 'px';
} else if( mode === 'full' ) {
width = '100%';
height = '' + this.options.fullViewHeight + 'px';
} else if( mode === 'edit' ) {
width = '100%';
height = '' + this.options.editorHeight + 'px';
} else if( mode === 'window' ) {
width = this.options.windowWidth || this.options.viewWidth;
height = this.options.windowHeight || this.options.editorHeight;
if( width ) width += 'px';
if( height) height += 'px';
}
el.style.width = width;
el.style.height = height;
},
_latLngToArray: function( latlng ) {
return [
L.Util.formatNum(latlng.lat, 5),
L.Util.formatNum(latlng.lng, 5)
];
},
_updateFullTitle: function( mode, fs ) {
if( this._mode === 'view' ) {
mode.setContent(this.strings.view);
mode.setTitle(this.strings.viewTitle);
fs.setContent(this.options.fullFromStart ? this.strings.viewFull : this.strings.viewNormal);
fs.setTitle(this.options.fullFromStart ? this.strings.viewFullTitle : this.strings.viewNormalTitle);
} else if( this._mode === 'edit' ) {
mode.setContent(this.strings.editor);
mode.setTitle(this.strings.editorTitle);
fs.setContent(this.options.editorInWindow ? this.strings.editInWindow : this.strings.editInPanel);
fs.setTitle(this.options.editorInWindow ? this.strings.editInWindowTitle : this.strings.editInPanelTitle);
}
},
// options is an object with a lot of properties
bindLayerAdder: function( options ) {
function getElement(id) {
return typeof id === 'string' ? document.getElementById(id) : id;
}
var select = getElement(options.select),
addButton = getElement(options.button),
keyBlock = getElement(options.keyBlock),
keyTitle = getElement(options.keyTitle),
keyValue = getElement(options.keyValue);
keyBlock.style.display = 'none';
keyValue.value = '';
if( !addButton.value )
addButton.value = this.strings.addLayer;
var onSelectChange = function(e) {
var target = (window.event && window.event.srcElement) || e.target || e.srcElement,
layer = target.value;
var link = layer ? window.layerList.getKeyLink(layer) : '';
if( link ) {
keyTitle.innerHTML = this.strings.keyNeeded.replace('%s', link);
keyValue.value = '';
keyBlock.style.display = options.keyBlockDisplay || 'inline';
} else {
keyBlock.style.display = 'none';
}
addButton.disabled = layer ? false : true;
};
L.DomEvent.on(select, 'change', onSelectChange, this);
var populateSelect = function() {
var i, layerKeys = window.layerList.getSortedKeys(),
layers = this.options.layers, layers0 = [];
for( i = 0; i < layers.length; i++ ) {
layers0.push(layers[i].indexOf(':') < 0 ? layers[i] :
layers[i].substring(0, layers[i].indexOf(':')));
}
while( select.firstChild ) {
select.removeChild(select.firstChild);
}
var opt = document.createElement('option');
opt.value = '';
opt.selected = true;
opt.innerHTML = this.strings.selectLayer + '...';
select.appendChild(opt);
for( i = 0; i < layerKeys.length; i++ ) {
var j, found = false;
for( j = 0; j < layers0.length; j++ )
if( layers0[j] == layerKeys[i] )
found = true;
if( found )
continue;
opt = document.createElement('option');
opt.innerHTML = layerKeys[i];
opt.value = layerKeys[i];
select.appendChild(opt);
}
onSelectChange.call(this, {target: select});
};
L.DomEvent.on(addButton, 'click', function() {
var layer = select.value;
if( !layer )
return;
var needKey = window.layerList.requiresKey(layer),
key = keyValue.value.replace(/^\s+|\s+$/g, '');
if( needKey && !key.length ) {
window.alert(this.strings.keyNeededAlert);
} else {
this.addLayer(needKey ? layer + ':' + key : layer);
}
}, this);
this.on('show change', function() {
populateSelect.call(this);
}, this);
},
show: function( element ) {
var el = typeof element === 'string' ? document.getElementById(element) : element;
if( !el )
return;
this._mode = 'view';
var mapDiv = document.createElement('div');
el.appendChild(mapDiv);
this._updateDivSize(mapDiv);
var map = L.map(mapDiv, { zoomControl: false }).setView(this.options.defaultPosition && this.options.defaultPosition.length == 2 ? this.options.defaultPosition : [22, 11], this.options.defaultZoom);
map.addControl(new L.Control.Zoom({ zoomInTitle: this.strings.zoomInTitle, zoomOutTitle: this.strings.zoomOutTitle }));
if( map.attributionControl )
map.attributionControl.setPrefix('MapBBCode');
var layerSwitcher = L.staticLayerSwitcher(this.options.layers, { editable: true, maxLayers: this.options.maxLayers, enforceOSM: true });
map.addControl(layerSwitcher);
layerSwitcher.on('layerschanged', function(e) {
this.options.layers = e.layers;
this.fire('change', this.options);
}, this);
layerSwitcher.on('selectionchanged', function(e) {
this.fire('layerselected', { id: e.selectedId });
}, this);
this.options.layers = layerSwitcher.getLayerIds();
this._layerSwitcher = layerSwitcher;
map.on('moveend zoomend', function() {
this.options.defaultPosition = this._latLngToArray(map.getCenter());
this.options.defaultZoom = map.getZoom();
this.fire('change', this.options);
}, this);
var fs = L.functionButtons([{ content: 'full' }], { position: 'topright' });
var modeButton = L.functionButtons([{ content: 'mode' }], { position: 'topright' });
var widthButton = L.functionButtons([{ content: '◂', title: this.strings.shrinkTitle }, { content: '▸', title: this.strings.growTitle }], { position: 'bottomright' });
var heightButton = L.functionButtons([{ content: '▴', title: this.strings.shrinkTitle }, { content: '▾', title: this.strings.growTitle }], { position: 'bottomleft' });
var toggleWidthButton = function() {
var isFull = this._mode === 'view' ? this.options.fullFromStart : !this.options.editorInWindow;
if( isFull )
map.removeControl(widthButton);
else
map.addControl(widthButton);
};
fs.on('clicked', function() {
var isFull = this._mode === 'view' ? this.options.fullFromStart : !this.options.editorInWindow;
if( this._mode === 'view' )
this.options.fullFromStart = !isFull;
else
this.options.editorInWindow = isFull;
toggleWidthButton.call(this);
this._updateFullTitle(modeButton, fs);
this._updateDivSize(mapDiv);
map.invalidateSize();
this.fire('change', this.options);
}, this);
modeButton.on('clicked', function() {
this._mode = this._mode === 'view' ? 'edit' : 'view';
if( this.options.fullFromStart == this.options.editorInWindow )
toggleWidthButton.call(this);
if( this.options.editorTypeFixed ) {
if( this._mode === 'view' )
map.addControl(fs);
else
map.removeControl(fs);
}
this._updateFullTitle(modeButton, fs);
this._updateDivSize(mapDiv);
map.invalidateSize();
}, this);
widthButton.on('clicked', function(e) {
var delta = e.idx * 100 - 50,
value = this._mode === 'view' ? this.options.viewWidth : this.options.windowWidth;
if( value + delta >= 400 && value + delta <= 1000 ) {
// more strict checks
if( this._mode === 'view' ) {
if( !this.options.fullFromStart ) {
this.options.viewWidth += delta;
this._updateDivSize(mapDiv);
map.invalidateSize();
this.fire('change', this.options);
}
} else if( this._mode === 'edit' ) {
if( this.options.editorInWindow ) {
this.options.windowWidth += delta;
this._updateDivSize(mapDiv);
map.invalidateSize();
this.fire('change', this.options);
}
}
}
}, this);
heightButton.on('clicked', function(e) {
var delta = e.idx * 100 - 50, value;
if( this._mode === 'view' )
value = this.options.fullFromStart ? this.options.fullViewHeight : this.options.viewHeight;
else if( this._mode === 'edit' )
value = this.options.editorInWindow ? this.options.windowHeight : this.options.editorHeight;
if( value + delta >= 200 && value + delta <= 800 ) {
if( this._mode === 'view' ) {
if( this.options.fullFromStart )
this.options.fullViewHeight += delta;
else
this.options.viewHeight += delta;
} else if( this._mode === 'edit' ) {
if( this.options.editorInWindow )
this.options.windowHeight += delta;
else
this.options.editorHeight += delta;
}
this._updateDivSize(mapDiv);
map.invalidateSize();
this.fire('change', this.options);
}
}, this);
map.addControl(modeButton);
map.addControl(fs);
map.addControl(widthButton);
map.addControl(heightButton);
this._updateFullTitle(modeButton, fs);
this.fire('show', this.options);
}
});
/*
* Layer switcher control that isn't a popup button.
* Does not support overlay layers.
*/
L.StaticLayerSwitcher = L.Control.extend({
includes: L.Mixin.Events,
options: {
position: 'topright',
editable: false,
bgColor: 'white',
selectedColor: '#ddd',
enforceOSM: false,
maxLayers: 7
},
initialize: function( layers, options ) {
L.setOptions(this, options);
this._layers = [];
this._selected = 0;
this._layerList = window.layerList && 'isOpenStreetMapLayer' in window.layerList;
if( layers ) {
if( 'push' in layers && 'splice' in layers ) { // in IE arrays can be [object Object]
for( var i = 0; i < layers.length; i++ )
this.addLayer(layers[i]);
} else {
for( var id in layers )
this.addLayer(id, layers[id]);
}
}
},
getLayers: function() {
var result = [];
for( var i = 0; i < this._layers.length; i++ )
result.push(this._layers[i].layer);
return result;
},
getLayerIds: function() {
var result = [];
for( var i = 0; i < this._layers.length; i++ )
result.push(this._layers[i].id);
return result;
},
getSelectedLayer: function() {
return this._layers.length > 0 && this._selected < this._layers.length ? this._layers[this._selected].layer : null;
},
getSelectedLayerId: function() {
return this._layers.length > 0 && this._selected < this._layers.length ? this._layers[this._selected].id : '';
},
updateId: function( layer, id ) {
var i = this._findLayer(layer),
l = i >= 0 && this._layers[i];
if( l && l.id !== id ) {
l.id = id;
if( l.fromList ) {
var onMap = this._map && this._map.hasLayer(layer),
newLayer = this._layerList ? window.layerList.getLeafletLayer(id) : null;
if( onMap )
this._map.removeLayer(layer);
if( newLayer ) {
l.layer = newLayer;
if( onMap )
this._map.addLayer(newLayer);
} else {
this._layers.splice(i, 1);
}
}
this._update();
return layer;
}
return null;
},
addLayer: function( id, layer ) {
if( this._layers.length >= this.options.maxLayers )
return;
var l = layer || (this._layerList && window.layerList.getLeafletLayer(id));
if( l ) {
this._layers.push({ id: id, layer: l, fromList: !layer });
var osmidx = this._findFirstOSMLayer();
if( osmidx > 0 ) {
var tmp = this._layers[osmidx];
this._layers[osmidx] = this._layers[0];
this._layers[0] = tmp;
}
if( this._map )
this._addMandatoryOSMLayer();
this._update();
this.fire('layerschanged', { layers: this.getLayerIds() });
if( this._layers.length == 1 )
this.fire('selectionchanged', { selected: this.getSelectedLayer(), selectedId: this.getSelectedLayerId() });
return layer;
}
return null;
},
removeLayer: function( layer ) {
var i = this._findLayer(layer);
if( i >= 0 ) {
var removingSelected = this._selected == i;
if( removingSelected )
this._map.removeLayer(layer);
this._layers.splice(i, 1);
if( i === 0 ) {
// if first layer is not OSM layer, swap it with first OSM layer
var osmidx = this._findFirstOSMLayer();
if( osmidx > 0 ) {
var tmp = this._layers[osmidx];
this._layers[osmidx] = this._layers[0];
this._layers[0] = tmp;
}
}
if( this._selected >= this._layers.length && this._selected > 0 )
this._selected = this._layers.length - 1;
this._addMandatoryOSMLayer();
this._update();
this.fire('layerschanged', { layers: this.getLayerIds() });
if( removingSelected )
this.fire('selectionchanged', { selected: this.getSelectedLayer(), selectedId: this.getSelectedLayerId() });
return layer;
}
return null;
},
moveLayer: function( layer, moveDown ) {
var pos = this._findLayer(layer),
newPos = moveDown ? pos + 1 : pos - 1;
if( pos >= 0 && newPos >= 0 && newPos < this._layers.length ) {
if( this.options.enforceOSM && pos + newPos == 1 && this._layerList &&
!window.layerList.isOpenStreetMapLayer(this._layers[1].layer) ) {
var nextOSM = this._findFirstOSMLayer(1);
if( pos === 0 && nextOSM > 1 )
newPos = nextOSM;
else
return;
}
var tmp = this._layers[pos];
this._layers[pos] = this._layers[newPos];
this._layers[newPos] = tmp;
if( pos == this._selected )
this._selected = newPos;
else if( newPos == this._selected )
this._selected = pos;
this._update();
this.fire('layerschanged', { layers: this.getLayerIds() });
}
},
_findFirstOSMLayer: function( start ) {
if( !this._layerList || !this.options.enforceOSM )
return start || 0;
var i = start || 0;
while( i < this._layers.length && !window.layerList.isOpenStreetMapLayer(this._layers[i].layer) )
i++;
if( i >= this._layers.length )
i = -1;
return i;
},
_addMandatoryOSMLayer: function() {
if( this.options.enforceOSM && this._layers.length > 0 && this._findFirstOSMLayer() < 0 ) {
var layer = L.tileLayer('http://tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Map © OpenStreetMap', minZoom: 0, maxZoom: 19 });
if( this._selected < this._layers.length )
this._selected++;
this._layers.unshift({ id: 'OpenStreetMap', layer: layer, fromList: false });
}
},
_findLayer: function( layer ) {
for( var i = 0; i < this._layers.length; i++ )
if( this._layers[i].layer === layer )
return i;
return -1;
},
onAdd: function( map ) {
var container = L.DomUtil.create('div', 'leaflet-bar');
if (!L.Browser.touch) {
L.DomEvent.disableClickPropagation(container);
L.DomEvent.on(container, 'mousewheel', L.DomEvent.stopPropagation);
} else {
L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation);
}
this._map = map;
this._container = container;
this._addMandatoryOSMLayer();
this._update();
return container;
},
// accepts value at index in this._layers array
_createItem: function( layerMeta ) {
var div = document.createElement('div');
div.style.backgroundColor = this.options.bgColor;
this._addHoverStyle(div, 'backgroundColor', this.options.selectedColor);
div.style.padding = '4px 10px';
div.style.margin = '0';
div.style.color = 'black';
div.style.cursor = 'default';
var label = !layerMeta.fromList ? layerMeta.id : (this._layerList ? window.layerList.getLayerName(layerMeta.id) : 'Layer');
div.appendChild(document.createTextNode(label));
if( this.options.editable )
div.appendChild(this._createLayerControls(layerMeta.layer));
L.DomEvent.on(div, 'click', function() {
var index = this._findLayer(layerMeta.layer);
if( this._selected != index ) {
this._selected = index;
this._update();
this.fire('selectionchanged', { selected: this.getSelectedLayer(), selectedId: this.getSelectedLayerId() });
}
}, this);
return div;
},
_createLayerControls: function( layer ) {
var upClick = document.createElement('span');
upClick.innerHTML ='▴'; // ▴
upClick.style.cursor = 'pointer';
this._addHoverStyle(upClick, 'color', '#aaa');
L.DomEvent.on(upClick, 'click', function() {
this.moveLayer(layer, false);
}, this);
var downClick = document.createElement('span');
downClick.innerHTML ='▾'; // ▾
downClick.style.cursor = 'pointer';
downClick.style.marginLeft = '6px';
this._addHoverStyle(downClick, 'color', '#aaa');
L.DomEvent.on(downClick, 'click', function() {
this.moveLayer(layer, true);
}, this);
var xClick = document.createElement('span');
xClick.innerHTML ='⨯'; // ⨯
xClick.style.cursor = 'pointer';
xClick.style.marginLeft = '6px';
this._addHoverStyle(xClick, 'color', '#aaa');
L.DomEvent.on(xClick, 'click', function() {
this.removeLayer(layer);
}, this);
var span = document.createElement('span');
span.style.fontSize = '12pt';
span.style.marginLeft = '12px';
span.appendChild(upClick);
span.appendChild(downClick);
span.appendChild(xClick);
L.DomEvent.on(span, 'click', L.DomEvent.stopPropagation);
return span;
},
_addHoverStyle: function( element, name, value ) {
var defaultValue = element.style[name];
L.DomEvent.on(element, 'mouseover', function() {
if( element.style[name] !== value ) {
defaultValue = element.style[name];
element.style[name] = value;
}
});
element.resetHoverStyle = function() {
element.style[name] = defaultValue;
};
element.updateHoverDefault = function() {
defaultValue = element.style[name];
};
L.DomEvent.on(element, 'mouseout', element.resetHoverStyle);
},
_recursiveCall: function( element, functionName ) {
if( element && element[functionName] ) {
element[functionName].call(element);
var children = element.getElementsByTagName('*');
for( var j = 0; j < children.length; j++ )
if( children[j][functionName] )
children[j][functionName].call(children[j]);
}
},
_update: function() {
if( !this._container )
return;
var presentDivs = [];
for( var i = 0; i < this._layers.length; i++ ) {
var l = this._layers[i];
if( !l.div )
l.div = this._createItem(l);
else
this._recursiveCall(l.div, 'resetHoverStyle');
l.div.style.background = this._selected == i ? this.options.selectedColor : this.options.bgColor;
l.div.style.borderTop = i ? '1px solid ' + this.options.selectedColor : '0';
this._recursiveCall(l.div, 'updateHoverDefault');
this._container.appendChild(l.div);
presentDivs.push(l.div);
if( this._map.hasLayer(l.layer) && this._selected != i )
this._map.removeLayer(l.layer);
else if( !this._map.hasLayer(l.layer) && this._selected == i )
this._map.addLayer(l.layer);
}
var alldivs = this._container.childNodes, found;
for( var j = 0; j < alldivs.length; j++ ) {
found = false;
for( var k = 0; k < presentDivs.length; k++ )
if( presentDivs[k] === alldivs[j] )
found = true;
if( !found )
this._container.removeChild(alldivs[j]);
}
}
});
L.staticLayerSwitcher = function( layers, options ) {
return new L.StaticLayerSwitcher(layers, options);
};
/*
* A leaflet button with icon or text and click listener.
*/
L.FunctionButtons = L.Control.extend({
includes: L.Mixin.Events,
initialize: function( buttons, options ) {
if( !('push' in buttons && 'splice' in buttons) )
buttons = [buttons];
this._buttons = buttons;
if( !options && buttons.length > 0 && 'position' in buttons[0] )
options = { position: buttons[0].position };
L.Control.prototype.initialize.call(this, options);
},
onAdd: function( map ) {
this._map = map;
this._links = [];
var container = L.DomUtil.create('div', 'leaflet-bar');
for( var i = 0; i < this._buttons.length; i++ ) {
var button = this._buttons[i],
link = L.DomUtil.create('a', '', container);
link._buttonIndex = i; // todo: remove?
link.href = button.href || '#';
if( button.href )
link.target = 'funcbtn';
link.style.padding = '0 4px';
link.style.width = 'auto';
link.style.minWidth = '20px';
if( button.bgColor )
link.style.backgroundColor = button.bgColor;
if( button.title )
link.title = button.title;
button.link = link;
this._updateContent(i);
var stop = L.DomEvent.stopPropagation;
L.DomEvent
.on(link, 'click', stop)
.on(link, 'mousedown', stop)
.on(link, 'dblclick', stop);
if( !button.href )
L.DomEvent
.on(link, 'click', L.DomEvent.preventDefault)
.on(link, 'click', this.clicked, this);
}
return container;
},
_updateContent: function( n ) {
if( n >= this._buttons.length )
return;
var button = this._buttons[n],
link = button.link,
content = button.content;
if( !link )
return;
if( content === undefined || content === false || content === null || content === '' )
link.innerHTML = button.alt || ' ';
else if( typeof content === 'string' ) {
var ext = content.length < 4 ? '' : content.substring(content.length - 4),
isData = content.substring(0, 11) === 'data:image/';
if( ext === '.png' || ext === '.gif' || ext === '.jpg' || isData ) {
link.style.width = '' + (button.imageSize || 26) + 'px';
link.style.height = '' + (button.imageSize || 26) + 'px';
link.style.padding = '0';
link.style.backgroundImage = 'url(' + content + ')';
link.style.backgroundRepeat = 'no-repeat';
link.style.backgroundPosition = button.bgPos ? (-button.bgPos[0]) + 'px ' + (-button.bgPos[1]) + 'px' : '0px 0px';
} else
link.innerHTML = content;
} else {
while( link.firstChild )
link.removeChild(link.firstChild);
link.appendChild(content);
}
},
setContent: function( n, content ) {
if( content === undefined ) {
content = n;
n = 0;
}
if( n < this._buttons.length ) {
this._buttons[n].content = content;
this._updateContent(n);
}
},
setTitle: function( n, title ) {
if( title === undefined ) {
title = n;
n = 0;
}
if( n < this._buttons.length ) {
var button = this._buttons[n];
button.title = title;
if( button.link )
button.link.title = title;
}
},
setBgPos: function( n, bgPos ) {
if( bgPos === undefined ) {
bgPos = n;
n = 0;
}
if( n < this._buttons.length ) {
var button = this._buttons[n];
button.bgPos = bgPos;
if( button.link )
button.link.style.backgroundPosition = bgPos ? (-bgPos[0]) + 'px ' + (-bgPos[1]) + 'px' : '0px 0px';
}
},
setHref: function( n, href ) {
if( href === undefined ) {
href = n;
n = 0;
}
if( n < this._buttons.length ) {
var button = this._buttons[n];
button.href = href;
if( button.link )
button.link.href = href;
}
},
clicked: function(e) {
var link = (window.event && window.event.srcElement) || e.target || e.srcElement;
while( link && 'tagName' in link && link.tagName !== 'A' && !('_buttonIndex' in link ) )
link = link.parentNode;
if( '_buttonIndex' in link ) {
var button = this._buttons[link._buttonIndex];
if( button ) {
if( 'callback' in button )
button.callback.call(button.context);
this.fire('clicked', { idx: link._buttonIndex });
}
}
}
});
L.functionButtons = function( buttons, options ) {
return new L.FunctionButtons(buttons, options);
};
/*
* Helper method from the old class. It is not recommended to use it, please use L.functionButtons().
*/
L.functionButton = function( content, button, options ) {
if( button )
button.content = content;
else
button = { content: content };
return L.functionButtons([button], options);
};
window.MapBBCodeConfig.include({ strings: {
"view": "View",
"editor": "Editor",
"editInWindow": "Window",
"editInPanel": "Panel",
"viewNormal": "Normal",
"viewFull": "Full width only",
"viewTitle": "Adjusting browsing panel",
"editorTitle": "Adjusting editor panel or window",
"editInWindowTitle": "Editor will be opened in a popup window",
"editInPanelTitle": "Editor will appear inside a page",
"viewNormalTitle": "Map panel will have \"fullscreen\" button",
"viewFullTitle": "Map panel will always have maximum size",
"growTitle": "Click to grow the panel",
"shrinkTitle": "Click to shrink the panel",
"zoomInTitle": "Zoom in",
"zoomOutTitle": "Zoom out",
"selectLayer": "Select layer",
"addLayer": "Add layer",
"keyNeeded": "This layer needs a developer key (how to get it)",
"keyNeededAlert": "This layer needs a developer key"
}});
}(window, document));