Commit 78b26614 authored by Eric's avatar Eric
Browse files

enhancement/bugfix: Search for and zoom to node

Added search for and zoom to node button

needed to move the layer control button out of the way though.
while working on that found a way to disable the event that caused the layer control to expand when hovered over.
also forced the layer control popup  to *always* have a scroll bar, which should fix an issue with _some_ browsers...

Fixes #11
parent d0705e13
......@@ -963,6 +963,13 @@ function create_MapLayers($numNodes, $numLinks, $numMarkers)
var fiveGHzStations = new L.LayerGroup();
var otherStations = new L.LayerGroup();
var upgradeStations = new L.LayerGroup();\n
var allStations = L.layerGroup([
nineHundredMHzStations,
twoGHzStations,
threeGHzStations,
fiveGHzStations,
otherStations]);
";
if ($numLinks > 0)
......@@ -1227,15 +1234,15 @@ map.fullscreenControl.setPosition('verticalcenterleft');
EOD;
$Content .= <<< EOD
//the ruler
var rulerOptions = {position: 'verticalcenterleft',
lengthUnit: {
factor: 0.621371,
display: 'Miles',
decimal: 3}
};
L.control.ruler(rulerOptions).addTo(map);
document.getElementById('ruler').title = 'Ruler\\n(ESC 1x to stop, 2x to remove)';
//the search button
L.control.search({
layer: allStations,
initial: false,
zoom: 16,
position: 'verticalcenterleft',
hideMarkerOnCollapse: true
}).addTo(map);
//the watermark logo
L.Control.Watermark = L.Control.extend({
......@@ -1268,12 +1275,7 @@ L.control.watermark({position: 'bottomright'}).addTo(map);
*/
legend.addTo(map);
legendHidden.addTo(map);
/*
* Layer Control
*/
var layerControls = L.control.groupedLayers(baseLayers, groupedOverlays, {position: 'verticalcenterleft'}).addTo(map);
L.DomEvent.disableClickPropagation(layerControls._container);
L.DomEvent.disableScrollPropagation(layerControls._container);
/*
* Scale Control
*/
......@@ -1337,6 +1339,24 @@ EOD;
/* Attribution */
//attributionCtrl({position: 'bottomleft'}).addTo(map);\n
//the left side controls go in the order they are added.
//we want the ruler and the layers control to be the last two on the bottom
$Content .= <<< EOD
//the ruler
var rulerOptions = {position: 'verticalcenterleft',
lengthUnit: {
factor: 0.621371,
display: 'Miles',
decimal: 3}
};
L.control.ruler(rulerOptions).addTo(map);
document.getElementById('ruler').title = 'Ruler\\n(ESC 1x to stop, 2x to remove)';
//Grouped Layer Control
var layerControls = L.control.groupedLayers(baseLayers, groupedOverlays, {position: 'verticalcenterleft'}).addTo(map);
L.DomEvent.disableClickPropagation(layerControls._container);
L.DomEvent.disableScrollPropagation(layerControls._container);
EOD;
return $Content;
}
?>
......
.leaflet-container .leaflet-control-search {
position:relative;
float:left;
background:#fff;
color:#1978cf;
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
background-color: rgba(255, 255, 255, 0.8);
z-index:1000;
margin-left: 10px;
margin-top: 10px;
}
.leaflet-control-search.search-exp {/*expanded*/
background: #fff;
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
.leaflet-control-search .search-input {
display:block;
float:left;
background: #fff;
border:1px solid #666;
border-radius:2px;
height:22px;
padding:0 20px 0 2px;
margin:4px 0 4px 4px;
}
.leaflet-control-search.search-load .search-input {
background: url('../images/loader.gif') no-repeat center right #fff;
}
.leaflet-control-search.search-load .search-cancel {
visibility:hidden;
}
.leaflet-control-search .search-cancel {
display:block;
width:22px;
height:22px;
position:absolute;
right:28px;
margin:6px 0;
background: url('../images/search-icon.png') no-repeat 0 -46px;
text-decoration:none;
filter: alpha(opacity=80);
opacity: 0.8;
}
.leaflet-control-search .search-cancel:hover {
filter: alpha(opacity=100);
opacity: 1;
}
.leaflet-control-search .search-cancel span {
display:none;/* comment for cancel button imageless */
font-size:18px;
line-height:20px;
color:#ccc;
font-weight:bold;
}
.leaflet-control-search .search-cancel:hover span {
color:#aaa;
}
.leaflet-control-search .search-button {
display:block;
float:left;
width:30px;
height:30px;
background: url('../images/search-icon.png') no-repeat 4px 4px #fff;
border-radius:4px;
}
.leaflet-control-search .search-button:hover {
background: url('../images/search-icon.png') no-repeat 4px -20px #fafafa;
}
.leaflet-control-search .search-tooltip {
position:absolute;
top:100%;
left:0;
float:left;
list-style: none;
padding-left: 0;
min-width:120px;
max-height:122px;
box-shadow: 1px 1px 6px rgba(0,0,0,0.4);
background-color: rgba(0, 0, 0, 0.25);
z-index:1010;
overflow-y:auto;
overflow-x:hidden;
cursor: pointer;
}
.leaflet-control-search .search-tip {
margin:2px;
padding:2px 4px;
display:block;
color:black;
background: #eee;
border-radius:.25em;
text-decoration:none;
white-space:nowrap;
vertical-align:center;
}
.leaflet-control-search .search-button:hover {
background-color: #f4f4f4;
}
.leaflet-control-search .search-tip-select,
.leaflet-control-search .search-tip:hover {
background-color: #fff;
}
.leaflet-control-search .search-alert {
cursor:pointer;
clear:both;
font-size:.75em;
margin-bottom:5px;
padding:0 .25em;
color:#e00;
font-weight:bold;
border-radius:.25em;
}
.leaflet-control-layers-group-name {
font-weight: bold;
margin-bottom: .2em;
margin-left: 3px;
}
.leaflet-control-layers-group {
margin-bottom: .5em;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
padding-right: 10px;
}
.leaflet-control-layers-group-name{font-weight:700;margin-bottom:.2em;margin-left:3px}.leaflet-control-layers-group{margin-bottom:.5em}.leaflet-control-layers-scrollbar{overflow-y:scroll;padding-right:10px}
\ No newline at end of file
......@@ -208,7 +208,8 @@ MAP_DETAILS {
display: inline;
}
.leaflet-control-layers-expanded, .leaflet-control-layers-list {
height: 200px !important;
height: 200px !important;
overflow: auto !important;
}
/** New stuff for the popup tabs **/
......
This diff is collapsed.
/* global L */
// A layer control which provides for layer groupings.
// Author: Ishmael Smyrnow
L.Control.GroupedLayers = L.Control.extend({
options: {
collapsed: true,
position: 'topright',
autoZIndex: true,
exclusiveGroups: [],
groupCheckboxes: false
},
initialize: function (baseLayers, groupedOverlays, options) {
var i, j;
L.Util.setOptions(this, options);
this._layers = [];
this._lastZIndex = 0;
this._handlingClick = false;
this._groupList = [];
this._domGroups = [];
for (i in baseLayers) {
this._addLayer(baseLayers[i], i);
}
for (i in groupedOverlays) {
for (j in groupedOverlays[i]) {
this._addLayer(groupedOverlays[i][j], j, i, true);
}
}
},
onAdd: function (map) {
this._initLayout();
this._update();
map
.on('layeradd', this._onLayerChange, this)
.on('layerremove', this._onLayerChange, this);
return this._container;
},
onRemove: function (map) {
map
.off('layeradd', this._onLayerChange, this)
.off('layerremove', this._onLayerChange, this);
},
addBaseLayer: function (layer, name) {
this._addLayer(layer, name);
this._update();
return this;
},
addOverlay: function (layer, name, group) {
this._addLayer(layer, name, group, true);
this._update();
return this;
},
removeLayer: function (layer) {
var id = L.Util.stamp(layer);
var _layer = this._getLayer(id);
if (_layer) {
delete this._layers[this._layers.indexOf(_layer)];
}
this._update();
return this;
},
_getLayer: function (id) {
for (var i = 0; i < this._layers.length; i++) {
if (this._layers[i] && L.stamp(this._layers[i].layer) === id) {
return this._layers[i];
}
}
},
_initLayout: function () {
var className = 'leaflet-control-layers',
container = this._container = L.DomUtil.create('div', className);
// Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released
container.setAttribute('aria-haspopup', true);
if (L.Browser.touch) {
L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation);
} else {
L.DomEvent.disableClickPropagation(container);
L.DomEvent.on(container, 'wheel', L.DomEvent.stopPropagation);
}
var form = this._form = L.DomUtil.create('form', className + '-list');
if (this.options.collapsed) {
if (!L.Browser.android) {
// L.DomEvent
// .on(container, 'mouseover', this._expand, this)
// .on(container, 'mouseout', this._collapse, this);
}
var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container);
link.href = '#';
link.title = 'Layers';
if (L.Browser.touch) {
L.DomEvent
.on(link, 'click', L.DomEvent.stop)
.on(link, 'click', this._expand, this);
} else {
L.DomEvent.on(link, 'focus', this._expand, this);
}
this._map.on('click', this._collapse, this);
// TODO keyboard accessibility
} else {
this._expand();
}
this._baseLayersList = L.DomUtil.create('div', className + '-base', form);
this._separator = L.DomUtil.create('div', className + '-separator', form);
this._overlaysList = L.DomUtil.create('div', className + '-overlays', form);
container.appendChild(form);
},
_addLayer: function (layer, name, group, overlay) {
var id = L.Util.stamp(layer);
var _layer = {
layer: layer,
name: name,
overlay: overlay
};
this._layers.push(_layer);
group = group || '';
var groupId = this._indexOf(this._groupList, group);
if (groupId === -1) {
groupId = this._groupList.push(group) - 1;
}
var exclusive = (this._indexOf(this.options.exclusiveGroups, group) !== -1);
_layer.group = {
name: group,
id: groupId,
exclusive: exclusive
};
if (this.options.autoZIndex && layer.setZIndex) {
this._lastZIndex++;
layer.setZIndex(this._lastZIndex);
}
},
_update: function () {
if (!this._container) {
return;
}
this._baseLayersList.innerHTML = '';
this._overlaysList.innerHTML = '';
this._domGroups.length = 0;
var baseLayersPresent = false,
overlaysPresent = false,
i, obj;
for (var i = 0; i < this._layers.length; i++) {
obj = this._layers[i];
this._addItem(obj);
overlaysPresent = overlaysPresent || obj.overlay;
baseLayersPresent = baseLayersPresent || !obj.overlay;
}
this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none';
},
_onLayerChange: function (e) {
var obj = this._getLayer(L.Util.stamp(e.layer)),
type;
if (!obj) {
return;
}
if (!this._handlingClick) {
this._update();
}
if (obj.overlay) {
type = e.type === 'layeradd' ? 'overlayadd' : 'overlayremove';
} else {
type = e.type === 'layeradd' ? 'baselayerchange' : null;
}
if (type) {
this._map.fire(type, obj);
}
},
// IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe)
_createRadioElement: function (name, checked) {
var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + name + '"';
if (checked) {
radioHtml += ' checked="checked"';
}
radioHtml += '/>';
var radioFragment = document.createElement('div');
radioFragment.innerHTML = radioHtml;
return radioFragment.firstChild;
},
_addItem: function (obj) {
var label = document.createElement('label'),
input,
checked = this._map.hasLayer(obj.layer),
container,
groupRadioName;
if (obj.overlay) {
if (obj.group.exclusive) {
groupRadioName = 'leaflet-exclusive-group-layer-' + obj.group.id;
input = this._createRadioElement(groupRadioName, checked);
} else {
input = document.createElement('input');
input.type = 'checkbox';
input.className = 'leaflet-control-layers-selector';
input.defaultChecked = checked;
}
} else {
input = this._createRadioElement('leaflet-base-layers', checked);
}
input.layerId = L.Util.stamp(obj.layer);
input.groupID = obj.group.id;
L.DomEvent.on(input, 'click', this._onInputClick, this);
var name = document.createElement('span');
name.innerHTML = ' ' + obj.name;
label.appendChild(input);
label.appendChild(name);
if (obj.overlay) {
container = this._overlaysList;
var groupContainer = this._domGroups[obj.group.id];
// Create the group container if it doesn't exist
if (!groupContainer) {
groupContainer = document.createElement('div');
groupContainer.className = 'leaflet-control-layers-group';
groupContainer.id = 'leaflet-control-layers-group-' + obj.group.id;
var groupLabel = document.createElement('label');
groupLabel.className = 'leaflet-control-layers-group-label';
if (obj.group.name !== '' && !obj.group.exclusive) {
// ------ add a group checkbox with an _onInputClickGroup function
if (this.options.groupCheckboxes) {
var groupInput = document.createElement('input');
groupInput.type = 'checkbox';
groupInput.className = 'leaflet-control-layers-group-selector';
groupInput.groupID = obj.group.id;
groupInput.legend = this;
L.DomEvent.on(groupInput, 'click', this._onGroupInputClick, groupInput);
groupLabel.appendChild(groupInput);
}
}
var groupName = document.createElement('span');
groupName.className = 'leaflet-control-layers-group-name';
groupName.innerHTML = obj.group.name;
groupLabel.appendChild(groupName);
groupContainer.appendChild(groupLabel);
container.appendChild(groupContainer);
this._domGroups[obj.group.id] = groupContainer;
}
container = groupContainer;
} else {
container = this._baseLayersList;
}
container.appendChild(label);
return label;
},
_onGroupInputClick: function () {
var i, input, obj;
var this_legend = this.legend;
this_legend._handlingClick = true;
var inputs = this_legend._form.getElementsByTagName('input');
var inputsLen = inputs.length;
for (i = 0; i < inputsLen; i++) {
input = inputs[i];
if (input.groupID === this.groupID && input.className === 'leaflet-control-layers-selector') {
input.checked = this.checked;
obj = this_legend._getLayer(input.layerId);
if (input.checked && !this_legend._map.hasLayer(obj.layer)) {
this_legend._map.addLayer(obj.layer);
} else if (!input.checked && this_legend._map.hasLayer(obj.layer)) {
this_legend._map.removeLayer(obj.layer);
}
}
}
this_legend._handlingClick = false;
},
_onInputClick: function () {
var i, input, obj,
inputs = this._form.getElementsByTagName('input'),
inputsLen = inputs.length;
this._handlingClick = true;
for (i = 0; i < inputsLen; i++) {
input = inputs[i];
if (input.className === 'leaflet-control-layers-selector') {
obj = this._getLayer(input.layerId);
if (input.checked && !this._map.hasLayer(obj.layer)) {
this._map.addLayer(obj.layer);
} else if (!input.checked && this._map.hasLayer(obj.layer)) {
this._map.removeLayer(obj.layer);
}
}
}
this._handlingClick = false;
},
_expand: function () {
L.DomUtil.addClass(this._container, 'leaflet-control-layers-expanded');
// permits to have a scrollbar if overlays heighter than the map.
var acceptableHeight = this._map._size.y - (this._container.offsetTop * 4);
if (acceptableHeight < this._form.clientHeight) {
L.DomUtil.addClass(this._form, 'leaflet-control-layers-scrollbar');
this._form.style.height = acceptableHeight + 'px';
}
},
_collapse: function () {
this._container.className = this._container.className.replace(' leaflet-control-layers-expanded', '');
},
_indexOf: function (arr, obj) {
for (var i = 0, j = arr.length; i < j; i++) {
if (arr[i] === obj) {
return i;