Hover on <p> element to highlight geographic boundary, D3 Choropleth - html

I made a choropleth map of Chicago's 77 neighborhoods in D3.
The only challenge is, it's hard to know which neighborhood is which.
So, what I did was make divs with p elements (containing the neighborhood names) in the body of my HTML file and positioned them into a blank spot in my svg/canvas.
See a visual here.
What I'm trying to do is make it so when you hover over the name, the geographic boundary of the neighborhood highlights. Somehow I need to relate the geography to the text, but I have no idea how.

For a more robust solution, you would ideally want to add an id field to your data. This assumes that your data is some format (such as JSON). You may already have a unique identifier that you can use instead, but if not the following should work.
var i = 0;
for (var x in dataSet)
dataSet[x].id = ++i; //Or i++ for zero-based indexing
Now it depends on how you are generating the svg elements, but ideally you are using the enter function of d3. In that case, just create the result of enter as a variable and use it to append both the path (map portion) as well as the text.
var dataSelect = svg.selectAll(".item").data(data.items);
var dataEnter = dataSelect.enter();
dataEnter.append("path").....
dataEnter.append("text").....text(function(d){return d.label;}) //Using text because this is drawn inside the SVG.
With using the data and enter functions, the created objects automatically have the id data bound to them.
This makes it a simple case of text.id == path.id in your mouseover function.
svg.selectAll(".itemText").on("mouseover", function(textItem){
svg.selectAll(".item").each(function (cityItem){
if (cityItem.id == textItem.id)
d3.select(this).style("fill", "green");
else
d3.select(this).style("fill", function(d){return d.color;});
})
});
I've done this in a fiddle which you can see here
Note that this does not use p elements because ideally, if you're using SVG then you probably should use text elements. If you have to use p elements, then you can still use this general technique, but instead using p.text() as the matching factor on mouseover instead of id, assuming that the name is bound to your path data somewhere.

Related

Inserting tags by clicking on the objet

I have a question about the coordinates of the model.
Would it be possible to register a problem with a tag in the model, defining the exact location by clicking on the model?
enter image description here
PS.: on this example, only it is possible to use central coordinates of the object
To get the exact x,y,z value, use this 'ALT-key pivot point' technique, to get the surface point of a model, instead of it's centroid:
https://github.com/wallabyway/markupExt/issues/2
Second part:
Once you have the x,y,z value, you can replace 'centroid' position calulation, in this post:
https://forge.autodesk.com/blog/placing-custom-markup-dbid
// get the center of the dbId (based on its fragIds bounding boxes)
const pos = this.viewer.worldToClient(this.getModifiedWorldBoundingBox(id).center());
Does that help?

Is there a way to automatically have text move into certain sections in Google Docs depending on what color I highlight it?

So let's see if I can explain this correctly.
I use a Google Doc to track my to-do list at work. When I add something that needs immediate attention, I will highlight that bullet point and the description of the task with a bright yellow color. Lesser tasks, get a different color, etc. I break up my tasks into different lists under different headings depending on what type of project it's for (so I have a heading for "Website" then a bulleted list under it for all the tasks I need to do that pertain to updating the website, I have a "Videos" heading and a list beneath with all the tasks I need to do for videos, and so on). Within each section, I then highlight based on priority.
My list is long with many sections and I would love it if it were possible that when I highlight a task in a given section as "top priority" with the bright yellow color, that it would - automatically - be copied and moved to a section at the very top of my doc under a heading of "Priorities" that way I can see all in one place all the high priority tasks I want to accomplish across all my projects without having to scan through each section in my document and potentially missing something.
Is this possible to do? I've heard of Google Apps Script but I've never really dived into it. I have basic coding knowledge and can usually find my way around HTML, Javascript, and so on.
Is something like this possible? And how would I go about it?
Brenda.
You'll probably start with this:
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var lists = body.getListItems();
var childIndex = 0;
for (var i = 0; i < doc.getNumChildren(); i++) {
var child = doc.getChild(i);
if (child.getType() == DocumentApp.ElementType.LIST_ITEM){
while(child.getType() == DocumentApp.ElementType.LIST_ITEM){
child = doc.getChild(i)
childIndex = body.getChildIndex(child);
Logger.log(childIndex)
i++
}
child = doc.getChild(i-2)
var listId = child.getListId();
Logger.log(childIndex)
// You'll want to do something like...
// if child.getBackgroundColor() == "Yellow"...
// Here you can add an element to your "Priorities" list as well:
// var newElement = child.getParent().insertListItem(childIndex, elementContent);
// newElement.setListId(child);
break;
}
}
Here's a good reference: https://stackoverflow.com/a/20729760/5415398
And another: https://stackoverflow.com/a/26419644/5415398
Here you are getting the document, its body, and any lists contained therein. You can either use the "lists" variable directly, or you can instead loop through all of the document's children and for any that are LIST_ITEMs, they can be processed as needed.
You'll try to capture the highlighting of the list item with the ".getBackgroundColor()" function, and if it meets your conditions, then add the item to your priorities list.
(Note: This answer can and should be improved to be complete.)

D3.js: How to combine 2 datasets in order to create a map and show values on.mouseover?

I would like to combine two datasets on a map in D3.js.
For example:
1st dataset: spatial data in .json.
2nd dataset: Data to the areas in .csv
--> When you hover on the map a tooltip should show a sentences with some data from the 2nd dataset.
I am able to make the map and show a tooltip with data within the .json-file, but how do I insert the 2nd dataset?
A new function within my function that creates the map?
Do I have to take a completely new way?
Should I merge the .json-file with my 2nd dataset before using d3.js?
I appreciate any thoughts! :)
So, I think what you're asking is how to take spatial data from json and join it with some csv data that is loaded separately?
I did something similar with a choropleth map I was drawing and basically I just created a map of topology element ids to data objects and then I did a lookup using the topology element id to get whatever I wanted to associate with the actual drawn map element (I was using this method to set the color for the choropleth based on the fips country code).
So basically, draw the map so that you have an id associated with each map element that you want to be able to hover over. Then, in your mouseover/mouseout handlers, you will use that id to lookup the data you want to show in the tooltip and either use the svg title element or tipsy or manually draw an svg text element or whatever to show the tooltip.
Here's a couple useful references for drawing tooltips:
https://gist.github.com/biovisualize/1016860
http://jsfiddle.net/reblace/6FkBd/2/
From the fiddle:
function mouseover(d) {
d3.select(this).append("text")
.attr("class", "hover")
.attr('transform', function(d){
return 'translate(5, -10)';
})
.text(d.name + ": " + d.id);
}
// Toggle children on click.
function mouseout(d) {
d3.select(this).select("text.hover").remove();
}
Basically, it's appending an SVG text element and offsetting it from the position of the element being hovered over.
And here's a sample of how I look up data in an external map:
// Update the bound data
data.svg.selectAll("g.map path").transition().duration(750)
.style("fill", function(d) {
// Get the feature data from the mapData using the feature code
var val = mapData[d.properties.code];
// Return the colorScale value for the state's value
return (val !== undefined)? data.settings.colorScale(val) : undefined;
});
If your data is static, you can join it into your topojson file (if that's what you're using). https://github.com/mbostock/topojson/wiki/Command-Line-Reference
The client could change my data, so I kept it separate and redrew the map each time the data changed so that the colors would update. Since my data was topojson, I could access the feature id from the map data using d.properties.code (because I had joined the codes into the topojson file using the topojson tool I reference above... but you could use whatever unique id is in the spatial data file you have).

In Matlab, I need a function/script that reads the element ij in two different images and outputs a new image which is the output of a function

Pretty simple:
I need a script that reads the element ij of TWO images (same size). These two elements will be the input of a function that I have (actually a fuzzy logic system). I want the output of this function to form a new image, this one is made with the output of my function for every ij element of the TWO images opened before.
Thanks very much!
Rodrigo
The naive approach:
sz = size(img1);
out = zeros(sz,class(img1));
for i=1:sz(1)
for j=1:sz(2)
out(i,j) = myFunc(img1(i,j), img2(i,j));
end
end
If your function is properly vectorized, you can just do:
out = myFunc(img1,img2);

Get page selection including HTML?

I'm writing a Chrome Extension, and I was wondering if it was possible to get the selected text of a particular tab, including the underlying HTML? So if I select a link, it should also return the <a> tag.
I tried looking at the context menu event objects (yes, I'm using a context menu for this), and this is all that comes with the callback:
editable : false
menuItemId : 1
pageUrl : <the URL>
selectionText : <the selected text in plaintext formatting, not HTML>
It also returns a Tab object, but nothing in there was very useful, either.
So I'm kind of at a loss here. Is this even possible? If so, any ideas you might have would be great. Thanks! :)
Getting the selected text of a page is fairly easy, you can do something like
var text = window.getSelection().toString();
and you'll get a text representation of the currently selected text that you can pass from a content script to a background page or a popup.
Getting HTML content is a lot more difficult, mostly because the selection isn't always at a clean HTML boundary in the document (what if you only select a small part of a long link, or a few cells of a table for example). The most direct way to get all of the html associated with a selection is to reference commonAncestorContainer, which is a property on a selection range that corresponds with the deepest node which contains both the start and end of the selection. To get this, you'd do something like:
var selection = window.getSelection();
// Only works with a single range - add extra logic to
// iterate over more ranges if needed
var range = selection.getRangeAt(0);
var container = range.commonAncestorContainer;
var html = container.innerHTML
Of course, this will likely contain a lot of HTML that wasn't actually selected. It's possible that you could iterate through the children of the common ancestor and prune out anything that wasn't in the selection, but that's going to be a bit more involved and may not be necessary depending on what you're trying to do.
To show how to wrap this all up into an extension, I've written a short sample which you can reference:
http://github.com/kurrik/chrome-extensions/tree/master/contentscript-selection/
If you don't want all of the siblings, just the selected HTML, use range's other methods like .cloneContents() (to copy) or .extractContents() (to cut).
Here I use .cloneContents():
function getSelectedHTML() {
var range = window.getSelection().getRangeAt(0); // Get the selected range
var div = document.createElement("div");
div.appendChild(range.cloneContents()); // Get the document fragment from selected range
return div.innerHTML; // Return the actual HTML
}