Mouseover d3.js map with different layers - javascript

I made my TopoJSON with 3 different administrative levels. During mouseover, I would like the object from Level 2 to be highlighted. However, due to layering, the object could only detect the mouse event if there is no object above it (from, let's say, Level 3). It's a javascript issue, I could simply change the z-index of each levels (either by CSS or in the script). I also tried reordering the calls for each level. However, I read somewhere that d3.js has it's own way of processing the objects, so the approaches I mentioned didn't seem to work.
How do I make sure that the object that I want stays on top?

For some reason, what worked for me is FIRST adding the object with the event listener. AND make sure that the object's fill color exists (not set to none).

Related

Aframe - Raycast class filter doesn't update at runtime

I have a scene, that has a set of objects that I want to be selectable at a particular time.
Some of these objects are visible and an some invisible when the application starts.
The visible objects will have the class .clickable, so that I can click on them with the mouse to perform an operation and .nonclickable for the invisible ones.
However, the when i change the class of the objects from .nonclickable to .clickable, the objects remain unchanged and are still clickable.
Even though the objects are now invisible, there are still registering an event if the mouse enters that area.
So is there a way to have the raycast not interact with the objects once the class type has been changed?
__
PS. I had a work around using
evt.originalTarget.setAttribute("[raycaster]", "objects: .nonclickable")
but this only works with firefox, but breaks with chrome.
Thanks for any help inregards to this.
The provided syntax is incorrect. It is:
evt.target.setAttribute(‘raycaster’, ‘objects: .nonclickable’)
Name of component is not right and originalTarget is a non standard Firefox only feature

XPages client side: listen to and trigger an event (pure CSJS)

I'll try to describe what I'd like to have.
At the moment, I have custom control Desk with:
an Accordion Container (dojo)
several Accordion Panes, of which
one contains custom control Agenda
In custom control Agenda, there's nothing really special, expect for
custom control Tiles
In custom control Tiles, I display meeting info in a nice way, as tiles. There can be multiple tiles on one row. In order to make things looking perfect, I have to spread these tiles over the full line, justified, using CSS (that part works, 99%). What doesn't work is that when the accordion is hidden when the page loads, I have no details on the size of each tile so I can't do my calculations (i.e. offsetWidth==0).
So I have to delay the calculations to when the accordion is activated and onShow is triggered. But how to pass this on downwards, all the way to the custom control Tiles?
Tiles is used in other places too, so it cannot be a fixed reference. It doesn't even know that it's inside an accordion...
Question:
How can I call/trigger a function that's inside the Tiles custom control from the top custom control, Desk, in a transparent way?
NB A code example, even an illustrative one, would be very complicated to make (I think).
Could someone give me a push into the right direction? Events and triggers maybe? Pass accordion id down to the Tiles cc and then do something brilliant?
Thanks!!
I have a solution right now, but it isn't exactly a beautiful and transparent one.
I gave the Tiles a styleClass="Tiles", and then I can find these Tiles using getElementsByClassName. It's not the proper way, but it's a way, the pragmatic one.

New SVG elements in DOM, added through JavaScript, not rendered until mouseup

Pure JavaScript (no JQuery, D3, or other external libraries). I'm dragging SVG objects that look like columns of rectangles around. They have connecting lines between the rectangles, and when I drag one rectangle across another, I remove all elements from the DOM, check whether each rectangle in a column corresponds to a rectangle in neighboring column, and draw a new connecting line between them if that condition is true. In the console I can see that the elements are created immediately, but they aren't rendered until I release the mouse and stop the drag. Because I may drag across more than one column and need to compare the results at each position before deciding where to drop, I need to force the new elements not just to be created immediately, but also to be rendered immediately, without being blocked until I release the mouse.
[Edit: In response for downvote for "not showing research," note the following (original) paragraph. Tried all suggestions I could find, mentioning the most common ones explicitly. Perhaps my research methods are unsophisticated; can you advise so that I could do a better job next time?]
Following suggestions on this site and elsewhere, I've tried adding and deleting an element from the DOM and toggling the display property of various elements, but without success.
Sample files are at https://github.com/obdurodon/drag. To run, clone and then open textual_correspondence_static_sample/test.xhtml in a browser (from the file system, so that it can find the CSS and JavaScript files to which it's linked). Grab a drag icon at the top of a column and pull left or right. Connecting lines repaint only on drop, but I need them to repaint immediately after every crossing (I'll worry about stretching them on mousemove later).
I think the reason is because you are giving the lines a stroke colour in endMove() (after your drawLines() call). But you are not doing that in the swapColumns() function. New elements in SVG have no stroke by default.

Setting the Location of Groups

A newbie question. As I've explained in a prior post, I'm coming to SVG Land from Flash loaded with ActionScript expectations and misconceptions.
I've built an interactive graphic using D3 and I'm nearly finished except that I want to add a little pop-up box that displays when a user mouses over a state. Right now it appears as a static object labeled "West Virginia" on the left side of the stage:
http://www.50laboratories.com/miscellany/demographicclout2.html
The pop-up is a group with its own distinct ID. I need to be able to set its x and y location depending on the state being hovered over, but so far can't figure out how. It seems to me that I should be able to address a group in my JavaScript as I would a named movie clip in Flash, but visiting API references like this one, https://github.com/mbostock/d3/wiki/API-Reference, I see no references to methods and properties of group objects. Thanks in advance for your help.
Unlike actionscript, svg elements are dom nodes and manipulating them involves either setting their attributes or style properties. You could manipulate these by calling certain attribute/style setters of the dom nodes, but since you're using d3, you set those attributes/styles using d3's setters.
The way to position a element with d3 is to
1. select it, by the id you assigned it
2. set its transform attribute to translate([some-x], [some-y])
d3.select("#statepopup").attr("transform", "translate(50,100)");
P.S.
The transform attribute is also how you can scale and rotate the group.

Restrict an object to stay within another object

This is related to SVG, I have a large SVG object made of paths which stays static. With a press of a button, I can create another SVG object inside the larger object. The second object can be dragged with the mousedown.
PROBLEM:
Now I want to add a restriction so that the second object created cannot venture outside of the main object.
I tried using 'mouseup' for restriction but that does not work because the restriction is applied according to the cursor point on the second object, rather than the border of the second object.
Hope someone can help.
UPDATE:
#Phrogz : We have been trying to get Kevin's code to work but are struggling to get any results. We have a function attached to onmouseup to find out the intersected points of the object on the underneath path.
The function is suppose to give the results of the intersection & give an alert that the function has been exected. Its not giving anything in response, leading us to wonder whether the function is being executed at all.
Here is the main code:
var path=svgDoc.getElementById("path");
var str=intersectPathShape(path,DragTarget);
alert(str)
Phrogz, any thoughts on this?
You will need to use an intersection library like this one by Kevin Lindsey to detect when the paths overlap and prevent it. (He also provides demos of his code.)
Depending on how you implement your dragging, you may also need to check the bounding box of the two items to ensure that one is contained in the other (since dragging the child completely outside the parent would cause them not to intersect, but also not be a legal position).
The simplest code would be to store the last position of the child and return it to that position when an intersection is detected. Under fast dragging, though, this might cause the child to stop being dragged at a spot that is not actually touching. For a better user experience, you may want to try a binary search of intermediary offsets between the last known-good position and the current position to find the closest point along that path that is legal.
Kayote,
I think I answered this in another question. The short version is have a look at this github project:
https://github.com/thelonious/js-intersections
In particular, the loadShapes function in this file:
https://github.com/thelonious/js-intersections/blob/master/samples/IntersectionUtilities.js
You will need to instantiate a specific object per node type then pass those to Intersection.intersectShapes.
HTH,
Kevin

Categories

Resources