Strokes broken or shape going underneath others once clicked - Raphael.js - javascript

I made this map, following the demo on Raphaël website.
I want each shape (département) to be clickable and lead to a page.
I put a link, for example, on a yellow shape, more or less in the center of the map.
Here it's how it goes:
Not clicked, the shape looks great, I click it, it leads the page, perfect!
I click the previous arrow on my browser to go back and hover again that same shape, and it behaves really weird. The strokes seem broken or the shape going underneath the other ones (details here). Do you know what's happening?
Also, I would like to have your opinion and feedback about your experience with the map (usability and compatibility with browsers (IE?) mostly).
Thank you in advance for your help.

The reason it looks weird is because by adding a link to the element, Raphael wraps the <path> element (that defines the département shape) inside an <a href="">. But its toFront() method still works on the <path>, so that now just pushes it to the front of the <a>, instead of to the front of the entire set of départements. In other words, .toFront() doesn't work anymore.
That looks like a bug in Raphael to me, actually. I'm not sure how to fix it, other than replacing each occurrence of .toFront() you're using by a function that checks if the node has an <a> parent, and if it does, move that to the front instead (by reinserting it into the DOM).
Also,
It's broken in IE in a different way.
I think whoever made that demo already knew about it, because the if(current) block in the mouseover fixes it on the Australia example. But the scaling and stroke-width animation you added basically also need to be reset there.
If you replace that if(current) block by the following it should work:
if (current && current != departement) {
fra[current].animate({
fill: "#333",
stroke: "#666",
"stroke-width": 1
}, 500);
fra[current].scale(1,1)
document.getElementById(current).style.display = "";
}

Related

Animated timeline with javascript

I am trying to create some time line effect. It will have couple of points for each time with designated picture inside a circle.
I want them to be clickable. When I click, I want another picture(plane) to move from its current location to where it is clicked within 1 second and shrink and disappear. Something similar to following GIF.
I have found couple of examples but I couldn't put them together to achieve what I want. I really searched a lot but couldn't solve it on my own. I am an iOS developer and no background on web development.
I will appreciate if you can help me on this.
Give a relative position to the timeline. Then you can get the position of a clicked circle, and assign it to the movable one. Add CSS transitions to have a better visual result.
Example using jQuery:
$(document).on("click", ".point", function () {
var $this = $(this);
var $abs = $(".is-absolute");
$abs.css("top", $this.position().top);
$abs.css("left", $this.position().left);
});
http://jsfiddle.net/dsr4esn3/

JS toggleClass right way

I've this project where when I click on the plant the scale changes and show some texts.
http://www.gaianet.com.br/Nissin-teste/
I've this project where I should click on a planet and scale's it and show another div by opacity.
Right now i've been trying to do by js using toggle class but I need some help to make it work right.
If I click on first planet it works fine, but when this planet is 'selected'and I click on another all the classes start to toogle and the scale and opacity goes crazy.I don't know how to make a 'reset' to the original css if I click on another planet when one has already changed the class.
$(".layer.planeta1").click(function(){
$(".institucional").toggleClass("escala-planeta repo1-1");
$(".planet-info1").toggleClass("opacidade-planeta ");
$(".educacao").toggleClass("escala-menor-planeta repo1-2");
$(".pdv").toggleClass("escala-menor-planeta repo1-3");
});
$(".layer.planeta2").click(function(){
$(".educacao").toggleClass("escala-planeta repo-2-1");
$(".planet-info2").toggleClass("opacidade-planeta ");
$(".institucional").toggleClass("escala-menor-planeta repo-2-2");
$(".pdv").toggleClass("escala-menor-planeta repo-2-3");
});
$(".layer.planeta3").click(function(){
$(".pdv").toggleClass("escala-planeta");
$(".planet-info3").toggleClass("opacidade-planeta ");
$(".educacao").toggleClass("escala-menor-planeta");
$(".institucional").toggleClass("escala-menor-planeta");
});
I'm sure there should a way better way to do that but I have no idea how.
Thanks a lot
I think I am clear on the acceptance criteria, but just to be sure, here is what I am going with:
When I click on a planet, I want it to scale.
If I click on a planet that is already scaled, I want it to reset to original scale.
When I click on a planet, I want to 'reset' any other planets to their original scale, and scale the planet I clicked on if it is not already scaled.
Given that, you might try being more explicit about what needs to happen when you click on a 'planet':
$('.planet').on('click', function(event){
$('.planet').removeClass('scale'); // Explicitly remove the scale class from other planets
$(this).toggleClass('scale'); // Scale the one I am clicking on, or if it's already scaled, revert it
});
A simplified example demonstrating this: http://codepen.io/anon/pen/xbMJRd
If it is creating so much of hassle using then I would use jQuery addClass and removeClass instead of toggleClass.
Another suggestion, I would save jQuery dom elements in a variable so that I dont search on entire dom again and again.

Canvas onmousedown causes text cursor no matter what CSS I use

Interesting glitch. It turns out that if you try to use CSS to style the cursor (as in to hide or use a crosshair cursor), when you fire an onmousedown event, the cursor is changed to a text cursor.
Here's a code snippet from the Experiment where I noticed this:
mouse=[[0,0],false];
snap_mouse_by=10;
canvas.onmousedown=function(evt){
var X=evt.clientX,Y=evt.clientY;
mouse[0]=[X-X%snap_mouse_by,Y%Y-snap_mouse_by];
//set mouse coordinates
mouse[1]=true;
//set mouse is down to true
}
Along with this, a self-executing function runs and checks for the mouse coordinates and whether the mouse is down or not. Based on this data, it draws a box.
Of course, when I hit the mouse button, the cursor's style goes to text instead of doing nothing.
No need to answer this question, answer is below.
I did a quick google search to see if I was doing the CSS wrong, or if there's a documented bug.
I found nothing, but then got an idea that should seem pretty obvious.
canvas.onmousedown=function(evt){
...
evt.preventDefault();
return false;
}
I tested that out to see if it was a browser function causing the CSS inconsistency, and it worked like a charm, I now have full control of the cursor's style.
Here's the link, if anyone's curious.
Just thought I'd share this in case anyone else runs into this glitch.

Placing elements in div with jQuery

I'm trying to draw in a div that is a droppable element.
To be more precise, I'm drawing arrows using images in a div element.
You can see it here:
http://ekstrakt.selfip.com/coach/?cmp=articleedit
I tried every other way I could think of for drawing with Javascript, even used some libraries made for drawing (ex. draw2d.js), but this is the way it suits me most.
Now, the problem is, I'm placing them in a 900px wide div. When the total width of the added divs/images exceeds 900px, the browser is placing them in wrong places.
Part of the code:
el=document.createElement("div");
eli=document.createElement("img");
$(eli).attr("src", "docs/temp/"+data);
$(el).append(eli);
$(el).draggable();
$(el).draggable('destroy');
$(el).css("position", "relative");
$("#frame").append(el);
$(el).css("float", "left");
$(el).css("width", Math.abs(dot1.x-dot2.x));
$(el).css("height", Math.abs(dot1.y-dot2.y));
$(el).css("left", dot1.x-negativeDistance);
var tempPos=$(el).position();
console.log("position| "+tempPos.left+":"+tempPos.top);
$(el).css("top", dot1.y);
negativeDistance=negativeDistance+Math.abs(dot1.x-dot2.x);
if(negativeDistance>900){
negativeDistance=negativeDistance-900;
}
When you see the example, you'll see the problem. Just click on the green field twice on different places.
Or, if anyone has a solution for drawing in a div, please share.
Have you considered positioning the drawn divs inside div#frame absolutely as opposed to relatively? You may need to rework the math in your code a bit, but you should be able to avoid relatively-positioned floating elements affecting each other's positioning within the parent div (which seems to be the source of your problem) this way. Just a thought.

HTML "overlay" which allows clicks to fall through to elements behind it [duplicate]

This question already has answers here:
HTML/CSS: Make a div "invisible" to clicks?
(5 answers)
Closed 7 years ago.
I'm trying to overlay a element on top of a webpage (to draw arbitrary graphics), and I've come to the point where I can stack it inside of a element on top of everything, but this prevents the user from clicking on any links/buttons/etc.
Is there a way to have its content float on top of everything (it's semi-transparent, so you can still see what is behind) and have the user interact with the layer below it?
I've found a lot of information on the DOM event model, but none of it addresses the problem where the buttons and other "native" controls never seem to get the clicks in the first place.
A silly hack I did was to set the height of the element to zero but overflow:visible; combining this with pointer-events:none; seems to cover all the bases.
.overlay {
height:0px;
overflow:visible;
pointer-events:none;
background:none !important;
}
Add pointer-events: none; to the overlay.
Original answer: My suggestion would be that you could capture the click event with the overlay, hide the overlay, then refire the click event, then display the overlay again. I'm not sure if you'd get a flicker effect though.
[Update] Exactly this problem and exactly my solution just appeared in this post: "Forwarding Mouse Events Through Layers". I know its probably a little late for the OP, but for the sake of somebody having this problem in the future, I though I would include it.
For the record an alternative approach might be to make the clickable layer the overlay: you make it semi-transparent and then place the "overlay" image behind it (somewhat counterintuitively, the "overlay" image could then be opaque). Depending on what you're trying to do, you might well be able to get the exact same visual effect (of an image and a clickable layer semi-transparently superimposed on top of each other), while avoiding clickability problems (because the "overlay" is in fact in the background).
In case anyone else is running in to the same problem, the only solution I could find that satisfied me was to have the canvas cover everything and then to raise the Z-index of all clickable elements. You can't draw on them, but at least they are clickable...
My team ran into this issue and resolved it very nicely.
add a class "passthrough" or something to each element you want clickable and which is under the overlay.
for each ".passthrough" element append a div and position it exactly on top of its parent. add class "element-overlay" to this new div.
The ".element-overlay" css should have a high z-index (above the page's overlay), and the elements should be transparent.
This should resolve your problem as the events on the ".element-overlay" should bubble up to ".passthrough". If you still have problems (we did not see any so far) you can play around with the binding.
This is an enhancement to #jvenema's solution.
The nice thing about this is that
you don't pass through ALL events to ALL elements. Just the ones you want. (resolved #jvenema's argument)
All events will work properly. (hover for example).
If you have any problems please let me know so I can elaborate.
You can use an overlay with opacity set in order to the buttons/anchors in the back stay visible, but once you have that overlay over an element, you can't click it.
Generally, this isn't a great idea. Taking your scenario, if you had evil intentions, you could hide everything underneath your "overlay". Then, when a user clicks on a link they think should take them to bankofamerica.com, instead it triggers the hidden link which takes them to myevilsite.com.
That said, event bubbling works, and if it's within an application, it's not a big deal. The following code is an example. Clicking the blue area pops up an alert, even though the alert is set on the red area. Note that the orange area does NOT work, because the event will propagate through the PARENT elements, so your overlay needs to be inside whatever element you're observing the clicks on. In your scenario, you may be out of luck.
<html>
<head>
</head>
<body>
<div id="outer" style="position:absolute;height:50px;width:60px;z-index:1;background-color:red;top:5px;left:5px;" onclick="alert('outer')">
<div id="nested" style="position:absolute;height:50px;width:60px;z-index:2;background-color:blue;top:15px;left:15px;">
</div>
</div>
<div id="separate" style="position:absolute;height:50px;width:60px;z-index:3;background-color:orange;top:25px;left:25px;">
</div>
</body>
</html>
How about this for IE?:
onmousedown: Hide all elements which could overlay the event. Because display:none visibility:hidden not realy works, push the overlaying div out of the screen for a fixed number of pixels. After a delay push back the overlaying div with the same number of pixels.
onmouseup: Meanwhile this is the event you like to fire.
//script
var allclickthrough=[];
function hidedivover(){
if(allclickthrough.length==0){
allclickthrough=getElementsByClassName(document.body,"clickthrough");// if so .parentNode
}
for(var i=0;i<allclickthrough.length;i++){
allclickthrough[i].style.left=parseInt(allclickthrough[i].style.left)+2000+"px";
}
setTimeout(function(){showdivover()},1000);
}
function showdivover(){
for(var i=0;i<allclickthrough.length;i++){
allclickthrough[i].style.left=parseInt(allclickthrough[i].style.left)-2000+"px";
}
}
//html
<span onmouseup="Dreck_he_got_me()">Click me if you can.</span>
<div onmousedown="hidedivover()" style="position:absolute" class="clickthrough">You'll don't get through!</div>
I was having this issue when viewing my website on a phone. While I was trying to close the overlay, I was pretty much clicking on anything under the overlay. A solution that I found working for myself is to just add a tag around the entire overlay

Categories