I'm using leaflet-groupedlayercontrol to add my grouped layers to the map and I have a problem:
All the layers are deselected, but I want to select all by default. I am using checkboxes, not radio buttons.
var groupedOverlays = {
"Select": {}
};
groupedOverlays["Select"]["Group 1"] = groups[0];
groupedOverlays["Select"]["Group 2"] = groups[1];
groupedOverlays["Select"]["Group 3"] = groups[2];
// Use the custom grouped layer control, not "L.control.layers"
L.control.groupedLayers(null, groupedOverlays, {collapsed:false}).addTo(map);
I tried to select them with JS, but didn't worked.
If you know a solution for LeafletJS, but not for that particular plugin, it's ok too.
Whether a Leaflet layer is ""selected"" or not in the built-in L.Control.Layers depends on whether the layer is added to the map or not.
e.g. this will display a L.Control.Layers with the checkbox off:
L.control.layers({}, {
Foo: L.marker([0,0])
}).addTo(map)
...while this will display it with the checkbox on:
L.control.layers({}, {
Foo: L.marker([0,0]).addTo(map)
}).addTo(map)
I expect the behaviour of the GroupedLayers control to be similar. Just double-check whether you add the layers to the map or not. Also notice that the checkboxes' state updates whenever layers are added/removed to/from the map by any means, at any time.
Related
Is it possible to control (enable/disable) Google Places Autocomplete SearchBox (google.maps.places.SearchBox) service predictions?
Or in other words: is it possible to temporarily detach HTML input element from Autocomplete SearchBox service and then reattach it?
The thing is that I display service results just bellow HTML input element attached to SearchBox service. Problem is that after results are displayed and user focuses back on the input element, predictions are displayed over results and obscure their view. I would like to disable predictions until text in input element is changed by the user.
EDIT 26/Aug/2016:
Disable predictions is currently not supported by the Javascript API. Therefore I have just opened a feature request on Google. If you are interested in the feature please vote for it: Autocomplete SearchBox - Control (enable/disable) predictions..
EDIT 07/Sep/2016 - bounty award update:
Thanks to all of you who participated in answering and also in promoting the question.
Primary objective of the award was to find solution using currently available means. I am afraid this did not happen so I decided not to award the bounty.
Although none of answers bellow provides a solution, each provides some sort of lead, so thank you! Maybe those leads will point to a solution in future.
Secondary objective of the award (although not communicated directly) was to promote Autocomplete SearchBox - Control (enable/disable) predictions feature request. Its status changed to NeatIdea and has been assigned internal tracking number. It is a good sign.
What you can do is, After the user selects the place, you can add a class disabled to that input field.., This will help you enable/disable predictions based on class name.
And where you have the autocomplete code, you can wrap it within if else statement.
let field = document.getElementById('location');
if ( field.className.indexOf('disabled') > -1 ) {
google.maps.event.clearInstanceListeners(field);
}
else {
let autocomplete = new google.maps.places.Autocomplete( field, {types: ['geocode']} );
autocomplete.addListener('place_changed', () => {
let place = autocomplete.getPlace();
let filed_val = field.value; // incase you need it
field.classList.add('disabled');
});
}
This will remove the autocomplete after user selects a place.. and later if you want, you can remove the disabled class from this field and it will work again.
My solution in AngularJS – it is extract from a directive.
.pac-contained is created after instance of an Autocomplete service is created, e.g.: new google.maps.places.Autocomplete(…) or new google.maps.places.SearchBox(…).
What I do is to find just created .pac-container in the document, store its reference and mark that container as already processes (by adding an arbitrary class .predictions-control on it). "Marking" the container is needed only when more than one .pac-container is expected to be present in application.
Now with the reference I can control visibility (hide or show) of the .pac-contained with predictions.
// Container element with predictions.
var pacContainer = null;
/***
* Find predictions container without predictions-control class set.
* Then set predictions-control class to it and convert it into
* Angular's jqLite object.
* #return {jqLite object} - container or null when not found.
*/
function getPredictionsContainer() {
// Get div.pac-container without predictions-control class.
var e = document.querySelector('div.pac-container:not(.predictions-control)');
if (e){
var container = angular.element(e);
container.addClass('predictions-control');
console.log('predictions-control: Container found.');
return container;
} else {
console.warn('predictions-control: Container not found!');
}
return null;
} // getPredictionsContainer
/***
* Loop in 50ms intervals until container is found.
*/
function untilContainerFound(){
pacContainer = getPredictionsContainer();
if (pacContainer == null){
$timeout(untilContainerFound, 50);
}
} // untilContainerFound
this.init = function() {
untilContainerFound();
}; // this.init
/***
* Prevent predictions to be displayed when user clicks on the
* input element. It is achieved by adding ng-hide CSS class to
* predictions container. Predictions container is identified by
* ".pac-container" CSS class selector.
*/
this.hidePredictions = function() {
// If predictions container was not found at directive
// initialization try to find it now.
if (pacContainer === null){
pacContainer = getPredictionsContainer();
}
if (pacContainer){
console.log('predictions-control: Hiding predictions.');
pacContainer.addClass('ng-hide');
} else {
console.warn('predictions-control: Container not found!');
}
}; // this.hidePredictions
/***
* Show predictions again by removing ng-hide CSS class from
* predictions container.
*/
this.showPredictions = function() {
console.log('predictions-control: Showing predictions.');
if (pacContainer){
pacContainer.removeClass('ng-hide');
}
}; // this.showPredictions
Call init() right after service instance is created:
// Create SearchBox service for auto completing search terms.
autocomplete = new google.maps.places.SearchBox( inputElem[0] );
// OR
// autocomplete = new google.maps.places.Autocomplete( ..... );
autocomplete .addListener('places_changed', callback);
predictionsCtrl.init();
Note:
As long as it is guaranteed that two Autocomplete services are not created at the same time (e.g.: each service is on different tab) or can wait with creation of next service until .pac-container for previous service is found, it reliably works even with multiple instances of Autocomplete service.
There is no way, or much point in having one: predictions are the whole point of SearchBox, its reason to be. If you don't want predictions, you can just use Text Search in the Places library.
If the user clicks/focuses again on the search box, s/he probably didn't care for the results that get obscured by the suggestions. The same behavior is in Google Maps, and it's not an issue, is it?
If you can't put some space between the SearchBox and results (like in this tool), and you absolutely must disable suggestions for a moment, I'd say you can destroy the google.maps.places.SearchBox object and create a new one later, attached to the same HTML input element.
Possibly valuable information.
This is relevant around API V3.29 (not sure if it will always be accurate).
The div element that the API creates for the autocomplete has a class of "pac-container pac-logo".
Utilizing document.querySelector('.pac-container') you may be able to set it's style attribute to display: none on a click event elsewhere.
NOTE: When your users click back in the searchBox google will change the style attribute back to whatever is appropriate, so you only have to set it once, you shouldn't have to set it back again.
(this may be easier and cleaner than getting angular involved).
Hope that helps someone (I had to add a CSS rule to increase the z-index in an application to make the autocomplete show up)
If you add the disabled attributed to the textbox this will disable predictions.
Using readonly attribute does not.
This may help in some circumstances.
I am struggling with Javascript and Leaflet tryind to realize a dashboard.
I am trying to realize a choropleth map following this tutorial.
I need to change dynamically data display on map according to two select menu.
Selects:
<select class="c-select" id="methodSelected" name="methodSelected" required>
</select>
<select class="c-select" id="yearSelected" name="yearSelected" required>
</select>
I am holding changing on selects with
$("#methodSelected").change()
$("#yearSelected").change()
both are declared inside a
$(document).ready(function() {}
In this block I also declare the required variables and functions
var choroplethMap;
var q = d3_queue.queue();
q.defer(d3.json, "final2.geojson");
function ready(GeoJSON) {
...
makePlaceHolderChoroplethMap();
}
makePlaceHolderChoroplethMap is like that
function makePlaceHolderChoroplethMap() {
choroplethMap = L.map('choroplethContainer').setView([51.505, -0.09], 2);
L.tileLayer("url",
{
id: id,
attribution: attribution,
accessToken: accessToken
}
).addTo(choroplethMap);
Now when I will change values with the two select menu I want update map, so I put into $("#yearSelected").change() a call to makeChoroplethMap().
function makeChoroplethMap() {}
Inside this function I put code following tutorial previously linked.
The problem is that when I changed the values with that code I will re-add new layers over others previously added (Geojson, legend and control, as you can see)
So I tryed to leave only binding with data into makeChoroplethMap(),
geojson = L.geoJson(data,
{
style: style,
onEachFeature: onEachFeature
}
).addTo(choroplethMap);
but I recieve an error in info.addTo(choroplethMap); as t is undefined. I think because choroplethMap is not initialized. Map and select work, but controls are not displayed 'cause of error.
For now (I think I breaked something because yesteday worked) also geojson layer overstay over country also if I change values with select (the previously one putted does not go off also I change values).
So my question is: how can re-bind data without re-adding also legend and other control?
Add the legend and the GeoJSON layer once, when you're initializing the map. If you add them in makeChoroplethMap, you'll be re- adding them.
Then, use L.GeoJSON.clearLayers() and the
currently undocumented L.GeoJSON.addData() method to clear/add polygons.
I'm having issues setting the visibility of custom Google Maps API v3 overlays. I have a gmaps API page with various overlay, such as polygons, polylines and symbols. Each has an associated text label, made using a custom overlay I adapted from the answer to [this Stack Overflow post][1]
On page load, the actual overlays (polylines, polygons, markers etc - the built in API objects) work correctly. They are displayed based on the default checkbox states. However, the labels are all displayed, regardless if their check box was set by default. If I cycle the checkboxes, everything works correctly.
The overlays are stored as an object called 'overlays' with layout 'description: [polyline, customoverlaylabel]'
Checkbox example code:
<input type="checkbox" id="sun" onclick="refreshCheck('sun')">Sun</input>
This is how I sync whether a display is hidden or visible to the checkbox:
function refreshCheck(overlay) {
var box = document.getElementById(overlay).checked
var lines = overlays[overlay][0]
var text = overlays[overlay][1]
lines.setVisible(box, overlay)
if (box === true) {
text.show()
}
else {
text.hide()
}
}
This code refreshes all the checkmarks, at the end of the javascript head.
var overlayNames = []
for (var k in overlays) overlayNames.push(k)
for (var o in overlayNames) refreshCheck(overlayNames[o])
Here's the hide method of the custom text overlay:
TxtOverlay.prototype.hide = function(){
if (this.div_) {
this.div_.style.visibility = "hidden";
}
}
It's failing the if (this.div_) check, and not doing anything. If I remove the check, it produces an error since this.div_ doesn't exist.
One way to work around it would be to automatically cycle all checkbox states once the page loads (manually doing to solves it). There might be a more fundamental fix. No matter where I attempt to .hide() or .show() a label in my javascript, it doesn't work - it only works when referenced by the checkbox being clicked.
The issue is the moment when you call refreshChecks() .
You assume that the TxtOverlay's already have been added at this time, but that's not the case(that's why the div_'s are still null).
The TXToverlay's (like any object/shape) on a map will be added when the projection of the map is ready.
A possible approach would be:
Instead of using the visible-property of the shapes/markers/etc. to toggle their visibility use the map-property.
The TXTOverlay's are also MVCObject's, you only have to bind the map-property of the TXTOverlay's to the map-property of the related shape.
I am using amCharts pie chart (v3) and I want to customize the pop up balloon that comes on mouseover on a slice: in addition to routine text like [[value]] [[percent]],
(a) a text that depends on the data item, and
(b) provide different click options to the user depending on data item. Every data row might not have these possibilities in which case the options should not appear.
For example, the pie chart might show wine consumption by country. On hover, I want to provide the user two different click options - one to see consumption by season if available, plus another to see consumption by age group if available.
Is it possible to do so in amCharts? I saw an exit for event clickSlice() here http://docs.amcharts.com/3/javascriptcharts/AmPieChart but nothing on how to modify the balloon text on the fly and add behavior to the balloon that comes on hover.
Will greatly appreciate your help.
For writing dynamic text in the balloon you can also do the folowing:
"graphs": [{
"balloonFunction": function(graphDataItem, graph) {
var value = graphDataItem.values.value;
if (value < 500) {
return value + "<br>(Little)";
} else {
return value + "<br>(A Lot)";
}
}
}],
You can use the following tags: [[title]], [[description]], [[value]] and [[percent]]. says the documentation.
I have used description for a custom field, it works fine.
You can add any custom field to your data provider and then display it in your balloon in the same way as value:
{value:15, title:"slice title", someCustomField:"some custom data"}
and then:
chart.balloonText = "[[someCustomField]]";
I know from reading the assoc. Google group that there is not currently an event for clicking a specific point when using the marker map (only regionClick is implemented).
But was reading the docs and noticed the event Select which says:
select Fired when the user clicks a visual entity. To learn what has
been selected, call getSelection(). None
and
setSelection() none Selects the specified chart entities. Cancels any
previous selection. Selectable entities are regions with an assigned
value. A region correlates to a row in the data table (column index is
null). For this chart, only one entity can be selected at a time.
Extended description.
Would I be able to use this to get the entry that was clicked?
Example:
data.addRows([
['Rome', 2761477, 1285.31],
['Milan', 1324110, 181.76],
['Naples', 959574, 117.27],
['Turin', 907563, 130.17],
['Palermo', 655875, 158.9],
['Genoa', 607906, 243.60],
['Bologna', 380181, 140.7],
['Florence', 371282, 102.41]
]);
Somehow get that Milan was clicked? How would I do this? Or am I reading this wrong?
Google API for Geomaps: http://code.google.com/apis/chart/interactive/docs/gallery/geochart.html
Google Group stating there is no click event in Marker mode:
https://groups.google.com/forum/?fromgroups#!topic/google-visualization-api/K8uJoes8ZH0
You need call getSelection function when the select event is called. This function returns an array of objects. Each object have row and column attributes (if any). Use the row and the first column (0) to retrieve the label name (Rome, Milan, ...).
Example (http://jsfiddle.net/VtZQh/):
google.visualization.events.addListener(chart, 'select', function() {
var selection = chart.getSelection()[0];
var label = data.getValue(selection.row, 0);
alert(label);
});
Please refer to documentation to know more about getSelection.