How do add anchor in the image dynamically - javascript

When we use Google Maps, after we search something, Google will add a marker in the map. When we click on this marker, a detailed information window will show, just like this :
I search the "white house",then it create a marker "A".
This is not difficult. However I found something more interesting:
In the map view, even we do not search anything, when the map zoom to some specified level, there will be some anchors generated. If the mouse over it or click it, it will show something accordingly, see the image:
Here see the point "14H and F st NW". I did not search for it, but it show me an anchor. When I click it, it show me a information window accordingly.
But when I use Firebug to see what is downloading, I found that they are just images. I can not find any <a> tag in the HTML.
Also, through Firebug, I found when the map level changed, the browser will send a request to the server to get the features inside the current map view. The response are JSON format. It contain the location and name of the features, then it add the anchors in the map.
But I wonder how do they implement it?
Possible manner to implement this:
1)when the map zoom or pan,request feature location data from server,suppose they get the following data(just take the white house for example):
data:{{name:'white house',Latitude:-77 longitude:38}}
2)bind mouse over event to the map div,something like this:
$("#map").mousemove(function(e){
for(var i=0;i<data.length;i++){
if(e.clientX=getImageX(data[i].x) && e.clientY=getImageY(data[i].y)){
//it mean that the mouse is overing this feature,now set the cousor and show the tip
//show tip,see the iamge:
}
}
});
3)bind the click event to the map div"
$("#map").mousemove(function(e){
for(var i=0;i<data.length;i++){
if(e.clientX=getImageX(data[i].x) && e.clientY=getImageY(data[i].y)){
//it mean that the mouse is clicking this feature,show the infomation window
//show tip,see the iamge:
}
}
});
The above is what I can thougth until now. But it seems that it is not enough, there are still some problems:
1) The tip can information window can show only if the user click or mouser over the very point which is the same as the Latitude and longitude of the feature,but in google Map,you will find that if the mouse over the marker(at any point of the marker),the tip will show. The area which will cause the tip show is the same as the the area of the marker.
It seems that google do someting like this:
$("#map").mousemove(function(e){
for(var i=0;i<data.length;i++){
if(e.clientX.insideTheMarker(data[i]) && e.clientY=insideTheMarker(data[i])){
//it mean that the mouse is clicking this feature,show the infomation window
}
}
});
But the marder size is not the same,how do they caculate the real area which will make the tip show?
2)in the eventhandle function,I haev to iterator all the features to see if the current mouse's location is match with any of the feature,if the featrues in current map view is so many,so it must cause performance problem.

It is likely an onclick event for the image or the map div. You can put an onclick handler on any DOM element. In this case they probably If they put the event on the map div since there is likely to be a lot of images that would have events and that could be a performance issue.
When you handle the click event for a child element in a parent element it is called event delegation. jQuery provides 2 functions for doing event delegation .live and .delegate. Other libraries also provide this functionality, but you can read about the basics this general javascript turorial or this jQuery specific tutorial.
They are probably doing something like (modified from here):
// Get the map canvas
var mapcanvas = document.getElementById('map_canvas');
// Quick and simple cross-browser event handler - to compensate for IE's attachEvent handler
function addEvent(obj, evt, fn, capture) {
if ( window.attachEvent ) {
obj.attachEvent("on" + evt, fn);
}
else {
if ( !capture ) capture = false; // capture
obj.addEventListener(evt, fn, capture)
}
}
// Check to see if the node that was clicked is an anchor tag. If so, proceed per usual.
addEvent(mapcanvas, "click", function(e) {
// Firefox and IE access the target element different. e.target, and event.srcElement, respectively.
var target = e ? e.target : window.event.srcElement;
if ( target.nodeName.toLowerCase() === 'img' ) {
alert("clicked");
return false;
}
});
As for making the the image look like an anchor (i.e. the pointer mouse icon), that can be set with css by setting the cursor property:
#map_canvas img { cursor: pointer }

Related

Get coordinates out of click to work with

So, I've been trying to render some div instead of the context menu once the use user right-click anywhere on the page, and for this, I need to receive the coordinates of the click. Currently, I'm doing it like this
function printMousePos(event) {
let coordinates = [event.clientX, event.clientY];
//console.log(coordinates);
return coordinates;
}
document.addEventListener("click", printMousePos);
In the console, I got an array with x and y, but I can't work with them outside the function. I've been trying something like
let a = function (event){...}
but it doesn't seem to return the array in any case, so how could I refer to x and y? The problem is that those are dynamic and change only when the event occurs. Should I just render the menu inside of the printMousePos(event)
? Or is there any other way to get x and y?
EDIT
Thanks a lot for your answers, works for me now. I did the following - rendered the menu outside everything, hide it using CSS, and on click it changes class to visible and appears in the coordinates of the click. Goes something like
rendering the menu in window =>
rootNode.addEventListener('contextmenu', event => {
event.preventDefault();
//console.log('123');
menu.classList.add('active');
menu.style.top = `${event.clientY}px`;
menu.style.left = `${event.clientX}px`;
});
and it shows on click. So, no need to get the coordinates outside.
As Teemu said "You can't return anything from an event listener". And you don't need to.
You can either declare the coordinates array outside the event listener and fill it with data once the event fired OR (and I'd prefer that) write the function that is supposed to work with the coordinates and then call it inside the event listener (which is pretty much what you suggested yourself):
function handleClick(x,y) {
// do stuff with x and y here, like drawing a div...
}
document.addEventListener("click", function(event) {
handleClick(event.clientX, event.clientY);
});

Customize dynamically created elements adding an option choosed via popup

I have a little code that creates elements (rectangles) and when I pass the mouse over them, a "customize yellow button appears on it". When I click this button, a popup with colors let us choose a colour to add in the selected rectangle.
Basically, I have 3 elements... click on 1 of them and choose a colour. This action, clones de tag and set it into the selected item. This works fine.
The problem appears when I click in the second item (or third)... I choose a new different colour but the action changes the selected rectangle and the sibling -applies to all elements that already have a cloned - (like propagation)...
I need to customize every single rectangle with its own colour and not all of them with the same. I pasted a little code here and a working (wrong) link in jsfiddle.
The action executes "on" cause the items are created dynamically (in this example I set them manually.
Can anybody help me? I don't understand what I'm doing wrong.
https://jsfiddle.net/martiniglesias/20Laxn84/2/
$(document).on("click","a.person",function (e)
{
e.preventDefault();
e.stopPropagation();
var elrel=$(this).attr('rel');
var elem=$("#ch_dndBoard1 span[data-id="+elrel+"]");
var elemrel=elem.attr("rel");
if (elemrel=="f1E")
{
$("body").append ("<div class='overlay'></div>").show();
$(".persE").fadeIn("fast");
$(".persE li").click(function(f)
{
f.preventDefault();
f.stopPropagation();
var ese=$(this).closest("li");
if ($(this).hasClass("nope"))
{
elem.find('b').fadeOut("slow",function() { elem.find('b').remove(); });
}
else
{
elem.find('b').remove();
var added=ese.find("b").clone();
added.css({"left":0+"px","top":+5.48+"px","position":"absolute"});
$(added).insertAfter(elem.find('em'));
}
$('.persE').fadeOut("fast",function(){ $(".overlay").remove(); });
});
}
return false;
});
I expect that every single rectangle can choose its own colour cloning it from the popup. For example, I want, rect1 blue, rect2 without color, rect3 red...
Thank you!
PS: Please, forgive my poor english :(
You have this issue because you are adding a click event listener to .persE li each time you click on a a.person.
You need to remove that listener when all your logic is over:
$(".persE li").click(function(f) {
// Your code
$(".persE li").off('click');
});
Be aware that if you listen an other click event with a different logic, that one will be destroyed too.
In order to avoid this, you need to reference your different logics in function:
const changeColorEvent = (e) => {
// Your code
$(this).off('click', changeColorEvent); // Here, "otherEvent" will still exist.
};
const otherEvent = (e) => {
// Different logic here
}
$(".persE li").click(changeColorEvent);
$(".persE li").click(otherEvent);

Is it possible to make hyperlinks inside nodes in Cytoscape.js?

I want users to be able to click on some text inside the node and do some action, like show some dialog or open some other window. Is this possible?
In the documentation there is something like :
text-events : Whether events should occur on an element if the label receives an event; may be yes or no. You may want a style applied to the text on :active so you know the text is activatable.
it seems like the thing but there is no example how to use it on the label level..
EDIT: example
on the diagram
how I imagine it could be in the code:
label_element.on('tap', function(event){
// cyTarget holds a reference to the label
var evtTarget = event.cyTarget;
//...
});
or
cy.on('tap', function(event){
var evtTarget = event.cyTarget;
//evtTarget holds element but I can somehow get the text which got tap event??
});
According Cytoscape.js documentation, you may try do this using
cy.on('tap')
, like this:
Examples
Bind to events that bubble up from elements matching the specified node selector:
cy.on('tap', 'node', { foo: 'bar' }, function(evt){
console.log( evt.data.foo ); // 'bar'
var node = evt.cyTarget;
console.log( 'tapped ' + node.id() );
});
Bind to all tap events that the core receives:
cy.on('tap', function(event){
// cyTarget holds a reference to the originator
// of the event (core or element)
var evtTarget = event.cyTarget;
if( evtTarget === cy ){
console.log('tap on background');
} else {
console.log('tap on some element');
}
});
At http://js.cytoscape.org/#cy.on
If text-events: yes, tapping a node's label will trigger tap on the node.
If you want to have arbitrary UIs on top of nodes that can be independently interacted with, then you should create a separate layer in the DOM.
Rationale : The labels are relatively simple in Cytoscape.js, because supporting complex ones would be on the same order of complexity as the DOM. In that case, it's better to use the DOM as a layer on top of the graph rather than to reimplement it in Cytoscape.js.

How can I prevent a popup to show when clicking on a marker in Leaflet?

I want a popup that doesn't show itself when I click on the Leaflet marker. I cannot use clickable : false because it will make the markers "act as a part of the underlying map" and this is unacceptable for me. I tried the following code:
marker.on('click', function(event) {
event.originalEvent.preventDefault();
});
without any results. What is the right way to prevent a popup from showing without using the clickable : false property of the marker object?
All I need is to open all the popups on the map by clicking on one custom button, but I don't want the popups to show themselves after I click on a particular marker.
Just don't bind a popup to the marker. Here's a fiddle with 2 markers. One has a popup and the other does not.
L.marker([51, 0]).bindPopup("this is a popup").addTo(map);
L.marker([51, 1.5]).addTo(map);
EDIT:
I've edited the fiddle and think it might be what you are asking. Here's the important part of the code:
function onClick(event) {
event.target.closePopup();
}
Try this workaround:
marker.bindPopup('my popup content');
// remove openPopup click handler (actually all click handlers)
marker.off('click');
// Do nothing on click. This is not necessary, but now marker
// doesn't act like part of underlying map
marker.on('click', function() {return;});
See plunker for details.
Juste remove openPopup from the click event of the marker.
marker.bindPopup('My popup!');
marker.off('click', this.openPopup);
None of the other answers worked for me (possibly because of a newer version of Leaflet). I ended up skipping marker.bindPopup() and just creating the popups separately using L.popup() then calling map.openPopup(thePopup) when I needed them to appear.
Something like this:
var map = L.map(),
popup = L.popup().setContent("Stuff"),
marker = L.marker();
popup.setLatLng(marker.getLatLng());
// In my event handler
map.openPopup(popup);
There's no need to remove the event listener yourself, you can just call .unbindPopup() to remove the previously set popup as soon as the marker transitions to your "disabled" state:
marker.bindPopup('My popup!');
marker.unbindPopup();
add return false . it should work. though i am not very sure.
marker.on('click', function(event) {
event.originalEvent.preventDefault();
return false;
});

jquery qTip mouseover browser crash

I am trying to show a tooltip in a mouseover event. The reason I am creating the tooltip on the fly rather than as a precursor (i.e. creating the qtip in document.ready) is that I have generated a list of items that map to a list of objects and I store the hash key for each object in the object list in a hidden element in the "li", so I grab that every time there is a mouseover on an li element.
What is important though is that I can't seem to get the tooltip to display in the mouseover, and I notice that adding the qtip is generating a lot of mouseover events that crash the browser:
$('.result-company-name').mouseover(function() {
var key = $(this).parent().parent().parent().find('.result-company-key').text();
var group = thisview.objGroup.getGroupFromKey(key);
var contacts = group.spotlight().fields.contacts;
if(!contacts)
return;
var qt = $(this).qtip(
{
content: contacts.length,
});
qt.qtip("show");
}
Any thoughts? Thanks.
Maybe you are generating an infinite loop somewhere?
Fixed by using show: { ready: true } to show the tooltip right away when I created it. Seems to be working fine.

Categories