leaflet api event listener argument access - javascript

I am using leaflet api with L.geoJson. the parts of code are
var indiaLayer= L.geoJson(india, {style: {weight: 2,
opacity: 1,
color: '#F7BE81',
dashArray: '10',
fillOpacity: 0.2}});
now i define an event listener on indiaLayer as
indiaLayer.on('click', clicked);
now if i want to access the first argument i.e. india inside clicked function, what should i use?. I consulted dom tree and figured out it to be
alert(this._layers.22.feature.id);
but it throws syntax error. can anyone help me out of it? thank you
i am attaching full code also
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.js"></script>
<script src="india.js" type="text/javascript"></script>
</head>
<body>
<div id = "map1" style="width: 1100px; height: 400px"> </div>
<div id = "zoom" style="width: 100px; height: 100px"></div>
<div id = "select" style="width: 100px; height:100px"></div>
<script>
var area = L.map('map1', {center: [27.8800,78.0800], zoom: 4 });
L.tileLayer('http://a.tiles.mapbox.com/v3/raj333.map-gugr5h08/{z}/{x}/{y}.png').addTo(area);
function zoomDeal()
{
var zoom=document.getElementById("zoom");
zoom.innerHTML= area.getZoom();
}
area.on('zoomend',zoomDeal);
var indiaLayer= L.geoJson(india, {style: {weight: 2,
opacity: 1,
color: '#F7BE81',
dashArray: '10',
fillOpacity: 0.2}});
area.addLayer(indiaLayer);
function clicked(){
if (area.getZoom() == 4) {
if (this.options.style.fillOpacity == 0.5)
{
this.setStyle({fillOpacity: 0.2});
this.options.style.fillOpacity=0.2;
var select = document.getElementById("select");
select.innerHTML = "";
}
else
{
this.setStyle({fillOpacity: 0.5});
this.options.style.fillOpacity=0.5;
var select = document.getElementById("select");
//select.innerHTML = "india";
alert(this._layers.22.feature.id);
}
}
}
indiaLayer.on('click', clicked);
</script>
</body>
</html>

Using the specific leaflet given id in the click handler can result in problems, as Leaflet might assign a different id if you load somewhere else.
The click handler on default throws in the event argument. Meaning that if you'd change your clicked function definition to:
function clicked (e) {
// do stuff etc.
}
You would be able to access the origin of the click (with e.target). In this case the layer.
Even nicer would be adding an onEachFeature function to the layer definition (where it reads out the JSON). Like in the example here: http://leafletjs.com/examples/geojson.html
The onEachFeature (http://leafletjs.com/reference.html#geojson-oneachfeature) gives you direct access to the feature that you try to access so to do what you want e.g.:
L.geoJson(india, {
onEachFeature: function (feature, layer) {
layer.on('click', function (e) {
alert(e.target.feature.id)
})
}
});

Related

How to select multiple features by mouse click event in ArcGIS JS API 3.x

I am trying to select multiple features in a feature layer by using "hold 'ctrl' button and mouse click event". I am using ArcGIS JS API 3.x.
I have created the US State boundary FeatureLayer by using FeatureCollection and able to display the layer on map. User wanted to select multiple states by mouse click while holding 'ctrl' or 'alt' key.
var featureLayer = new esri.layers.FeatureLayer(featureCollection, {
id: stateLayer,
opacity: 0.30,
visible: true,
infoTemplate: infoTemplate
});
g_esri.map.addLayer(featureLayer);
featureLayer.on("click", onBoundaryClick);
function onBoundaryClick(evt) {
var g = evt.graphic;
g_esri.map.infoWindow.setContent(g.getContent());
g_esri.map.infoWindow.show(evt.screenPoint, g_esri.map.getInfoWindowAnchor(evt.screenPoint));
formatInfotemplate(false, g);
}
I tried to follow some of the below links,
a. selecting-multiple-features-with-graphics
b. select-multiple-features-by-mouse-clicks
But couldn't able to get through,
It's been a long time I do not work with 3.xx API. Anyways maybe this example that I made for you can help you. The idea is basically listen to click events on the feature layer to catch selected graphics and then added to selected collection. When adding just check if the desire keys are pressed.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Labeling features client-side</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.35/esri/css/esri.css">
<style>
html, body, #map {
height: 100%; width: 100%; margin: 0; padding: 0;
}
</style>
<script src="https://js.arcgis.com/3.35/"></script>
<script>
var map;
require([
"esri/map",
"esri/geometry/Extent",
"esri/layers/FeatureLayer",
"esri/layers/GraphicsLayer",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/renderers/SimpleRenderer",
"esri/Color",
"dojo/domReady!"
], function(Map, Extent, FeatureLayer, GraphicsLayer,
SimpleLineSymbol, SimpleFillSymbol,
SimpleRenderer, Color)
{
const bbox = new Extent({"xmin": -1940058, "ymin": -814715, "xmax": 1683105, "ymax": 1446096, "spatialReference": {"wkid": 102003}});
const map = new Map("map", {
extent: bbox
});
const statesUrl = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3";
const states = new FeatureLayer(statesUrl, {
id: "states",
outFields: ["*"]
});
map.addLayer(states);
const color = new Color("#00ffff");
const line = new SimpleLineSymbol("solid", color, 1.5);
const symbol = new SimpleFillSymbol("solid", line, null);
const renderer = new SimpleRenderer(symbol);
const selected = new GraphicsLayer();
selected.setRenderer(renderer);
map.addLayer(selected);
let ctrl = false;
let shift = false;
map.on("key-down", function (evt) {
if (evt.key === "Control") {
ctrl = true;
} else if (evt.key === "Shift") {
shift = true;
}
});
map.on("key-up", function (evt) {
if (evt.key === "Control") {
ctrl = false;
} else if (evt.key === "Shift") {
shift = false;
}
});
states.on("click", function (evt) {
if (!ctrl && !shift) {
selected.clear();
}
selected.add(evt.graphic.clone());
console.log(`Selected: ${selected.graphics.length}`);
});
});
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>

JavaScript HTML alter HTML element from JavaScript code

I am currently displaying "LOADING STREET VIEW" while the image is loading. If it cannot find an image for the coordinate, I am popping up a dialog stating "Unable to load location in street view". I want to alter this so that I am not popping a dialog, but instead changing the LOADING STREET VIEW element to the image found at : https://maps.googleapis.com/maps/api/streetview?size=600x300&location=44.414382,11.013988&heading=151.78&pitch=-0.76 I'm very confused about referencing html elements in javascript code. From the research i've done, I think I need to be using document in my javascript code. All help is appreciated and you can find the code below:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script type="text/javascript">
function initialize() {
var markerPosition = new google.maps.LatLng(41.201316987470086, -82.98099300983233);
var panoramaOptions = {
position: markerPosition,
pov: {
heading: 165,
pitch: 0,
zoom: 1
}
};
var myPano = new google.maps.StreetViewPanorama(document.getElementById("pano"), panoramaOptions);
myPano.setVisible(false);
new google.maps.Marker({map: myPano, position: markerPosition, title: 'Feature'});
// add a variable that gets set when the position_changed handler gets fired off
var positionDidChange = false;
var newPov = {};
var listenerHandle = google.maps.event.addListener(myPano, 'position_changed', function () {
positionDidChange = true;
google.maps.event.removeListener(listenerHandle);
newPov.heading = google.maps.geometry.spherical.computeHeading(myPano.getPosition(), markerPosition);
newPov.pitch = 0;
newPov.zoom = 1;
myPano.setPov(newPov); myPano.setVisible(true);
});
// add a function that gets fired off to see if the position did change so that the user does not wait forever
setTimeout(function () {
if (!positionDidChange) {
alert("Unable to load location in street view");
}
}, 5000);
}
</script>
</head>
<body onload="initialize()">
<div id="pano" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0;"> LOADING STREET VIEW...</div>
</body>
</html>
You can control that text with document.getElementById('pano').innerHTML, for instance:
document.getElementById('pano').innerHTML = ' LOADING STREET VIEW..'; // what you have now
document.getElementById('pano').innerHTML = ''; //empty
Make a function that will replace the inner HTML of the div to the image:
var changeImage = function(){
var image = "http://www.myimage.com/image.png";
document.getElementById("pano").innerHTML = "<img src='" + image + "'>";
}
Then
if(!positionDidChange){
changeImage();
}

How to change color of a set of nodes in kinetic js?

SO I have a lot of Kinetic polygons, and I collect them and store in a variable like this:
var midr = layer.find('.midr');
I want to change their colors, so I want to delete them and draw them with different colour:
midr.on('mouseover',function(){
midr.destroy();
Boxes.MidR(color.R,color.G,color.B,1,'midr');
midr = layer.find('.midr');
});
midr.on('mouseout',function(){
midr.destroy();
Boxes.MidR(color.R,color.G,color.B,0,'midr');
midr = layer.find('.midr');
});
where:
var Boxes={
.....
MidR:function(R,G,B,A,group){
var C = shade(R,G,B,25,"+");
Mid_right.left(C.r,C.g,C.b,A,group);
var C = shade(R,G,B,20,"-");
Mid_right.back(C.r,C.g,C.b,A,group);
Mid_right.right(R,G,B,A,group);
Mid_right.bottom(R,G,B,A,group);
Mid_right.shelf(R,G,B,A,group);
}, ....
}
and
var Mid_right={
left:function(R,G,B,A,group){
frame([89,192,120,192,120,309,89,315],150,150,150,A,group);
frame([75,311,89,315,89,192,75,192],R,G,B,A,group)
},
right:function(R,G,B,A,group){
frame([99,193.5,99,306,118.5,309,118.5,193.5],R,G,B,A,group)
},
back:function(R,G,B,A,group){
frame([90.5,308,99,306,99,193.5,90.5,193.5],R,G,B,A,group);
},
shelf:function(R,G,B,A,group){
frame([90.5,270,118.5,266,99,264,90.5,265],R,G,B,A,group)
},
bottom:function(R,G,B,A,group){
frame([120,309,99,306,90.5,308,90.5,315],R,G,B,A,group)
}
};
and
function frame(array,R,G,B,A,group){
poly = new Kinetic.Polygon({
points: array,
stroke: 'white',
strokeWidth: 1,
name: group
});
if(R!=null||G!=null||B!=null){
poly.setFill('rgba('+R+','+G+','+B+','+A+')');
} else {
poly.setFill('rgba(0,0,0,0)');
};
layer.add(poly);
};
maybe it is kind of stupid and I could do it much easier, but there are other things I have to think about, which are not included here and I thought this should be a good way.
so what I want is to delete a set of polygons then redraw them with different colour, when the mouse hovers them and when it leaves, it should change back to original. but using destroy, redraw, and then collecting them again does not seem to work, dont know why. any ideas?
Instead of removing/recreating the poly, just use myPoly.setFill inside the mouseover and mouseleave events:
Add 2 additional properties to your poly: hoverColor and blurColor,
On mouseover: this.setFill(this.hoverColor);
On mouseleave: this.setFill(this.blurColor);
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/GTe9j/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.2.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
newPoly("red","green",[50,50, 100,50, 50,100]);
newPoly("blue","green",[100,50, 150,50, 150,100]);
newPoly("orange","green",[150,100, 150,150, 100,150]);
newPoly("purple","green",[100,150, 50,150, 50,100]);
function newPoly(hovercolor,blurcolor,array){
var poly = new Kinetic.Polygon({
points: array,
stroke: 'gray',
strokeWidth: 1,
fill:blurcolor
});
poly.hoverColor=hovercolor;
poly.blurColor=blurcolor;
poly.on("mouseover",function(){
this.setFill(this.hoverColor);
this.draw();
});
poly.on("mouseleave",function(){
this.setFill(this.blurColor);
this.draw();
});
layer.add(poly);
layer.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Hover over a triangle to change its hover-color</h4>
<div id="container"></div>
</body>
</html>

javascript map in leaflet how to refresh

i have a basic geoJson program in javascript by using leaflet API.
<html>
<head>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.js"></script>
<script src="india.js" type="text/javascript"></script>
</head>
<body>
<div id = "map1" style="width: 1100px; height: 400px"> </div>
<script>
var area = L.map('map1', {center: [27.8800,78.0800], zoom: 4 });
L.tileLayer('http://a.tiles.mapbox.com/v3/raj333.map-gugr5h08/{z}/{x}/{y}.png').addTo(area);
var indiaLayer= L.geoJson(india, {style: {weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.1}});
area.addLayer(indiaLayer);
function clicked(){
this.options.style.fillOpacity = 0.8;
//how to refresh layer in the given map
}
indiaLayer.on('click', clicked);
</script>
</body>
</html>
the problem is how would i automatically refresh the content of Layer on the map.
example here
function clicked(){
indiaLayer.style.fillOpacity = 0.8;
//how to refresh layer in the given map
}
indiaLayer.on('click', clicked);
when user click on indiaLayer , the fillOpacity variable changes but doesn't reflect back on map which is understood since i am not refreshing the map. I don't know how to do it.
please help
P/s: these are the functions available on indiaLayer object (i.e. this object inside clicked function...which one to use for this purpose or there exist none)
You can check the list of methods available of GEOJson in the Leaflef documentation This is the link to v.0.7.7, which is the closest available to used in this example.
Last time I've used
map._onResize();
and that help me refresh map. Maybe a little hack, but, it work.
In your code will be area._onResize()
P.S: Maybe you should try change the way to set new opacity value - try change
function clicked(){
this.options.style.fillOpacity = 0.8;
}
to that
function clicked(){
this.setStyle({fillOpacity: 0.2});
}
map.invalidateSize();
map._onResize() - it's a hack, and there is no guarantee that it won't be removed in future versions.
area.fitBounds(area.getBounds());

jQuery element.remove undo

I have code(thanks to roosteronacid) which removes web page elements when user click on them. I need to add additional functionality to undo action - revert removed elements. Any idea how to do element.remove undo with jQuery?
Regards,
Tomas
You can store a reference to removed elements by assigning the return value of remove() to a variable:
// Remove the element and save it in a variable
var removed = $('#myElement').remove();
Later, providing the variable is in scope, we can add the element back using various DOM insertion methods:
// Insert the removed element back into the body
removed.insertAfter('#anotherElement');
Looking at the code provided by roosteronacid, it doesn't save the reference so you would have to modify that code accordingly.
There is another method for this: .detach: http://api.jquery.com/detach/ that removes an element without destroying it.
You still have to "save" the element though (look at the example provided in the docs.)
You could take the approach many apps take for undo and save the complete body state before each remove, I've reworked #roosteronacid's code thus:
index.htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="index_files/jquery-1.js" type="text/javascript"></script>
<script src="index_files/index.js" type="text/javascript"></script>
<title>index</title>
<script type="text/javascript">var stack = Array();</script>
</head><body>
<h1>Test</h1>
<p>Test</p>
<div>Test</div>
Test
<span>Test</span>
Undo
</body></html>
index.js
$(function ()
{
initialise();
});
function initialise() {
$("* :not(body,a)").mouseenter(function ()
{
var that = $(this);
var offset = that.offset();
var div = $("<a />",
{
"title": "Click to remove this element",
css: {
"position": "absolute",
"background-color": "#898989",
"border": "solid 2px #000000",
"cursor": "crosshair",
width: that.width() + 6,
height: that.height() + 2
},
offset: {
top: offset.top - 4,
left: offset.left - 4
},
click: function ()
{
div.remove();
var state = $("body *");
stack.push(state);
that.remove();
},
mouseleave: function ()
{
div.fadeTo(200, 0, function ()
{
div.remove();
});
}
});
that.after(div.fadeTo(200, 0.5));
});
};
Well instead of removing them, you can do jQuery("#someElement").hide(); and then after if you want to get them back jQuery("#someElememt").show(); would be nice solution. Since its alters it display property.

Categories

Resources