On Mon, 8 May 2017 11:24:57 +0100 Mark Crutch <markc@...2744...> wrote:
Steve,
On Mon, May 8, 2017 at 4:02 AM, Steve Litt <slitt@...2357...> wrote:
So to ease the path of those who follow me, I put up a map of the landmines one's likely to run into while learning/using SVG clickmaps. Once a person knows these landmines exist, he/she can go about his/her business, and if something goes wrong, a simple reference to the landmines page substitutes for hours of web search and experimentation. Here's the URL of the SVG clickmaps landmines page:
http://troubleshooters.com/codecorn/svg_clickmaps/landmines.htm
I have a few suggestions with regard to some of your "landmines" that might make things a little easier...
- "Use alert() commands"
Actually don't do this. Not for general logging of position or values in the script, at least. Alerts are intrusive and can only show you a text string. Get familiar with the developer console in all modern browsers, and especially the console.log() function. It's non-modal, and you can log out rich objects and data structures, then interrogate their properties, attributes and values interactively in the console. It's a much better experience for most cases when you might want to log via alert().
Yes. I'll need to add an exhortation to use console.log(), as well as to reiterate that alert() is only for situations so unknown that only immediate feedback with stoppage of action will sufice.
- getElementsByTagName(), getElementsByClassName(), getElementById()
These work, but are somewhat out of fashion now. document.querySelector() and document.querySelectorAll() are the preferred approach these days. They take a CSS selector as a parameter, which allows for much richer ways to select objects:
document.querySelectorAll(".myclass"); // Gets all the elements with a class of "myclass" document.querySelector(".myclass"); // The same, but only gets the first one
document.querySelector("#myID"); // Select by ID
document.querySelectorAll("circle"); // All the circles
document.querySelector("circle.myclass"); // The first circle with a class of "myclass"
document.querySelectorAll("g.myclass > circle"); // All the circles that are immediate children of a group with a class of "myclass"
CSS selectors are powerful things these days (though still with some limitations), and a well crafted querySelector() can save a lot of DOM traversal in code.
How about browser support? What are the limitations you mention? These CSS type queries certainly seem more intuitive to someone knowing CSS, but before I switch to them I'd like to check for any downsides.
- "Group Clicking Gotchas"
"Let me start with this piece of advice: You'll probably *never* want to put events on the group itself."
I disagree with this advice. There's nothing wrong with putting event handlers on the group, or on the items within it, or on both. You just need to understand how events propagate within browsers; it's a slightly odd process, borne of a need to combine the old Internet Explorer way of handling them with the W3C standard way. In short, the things you need to know are these:
- "evt" will be the name of the event in the handler.
- "evt.target" will be the object that fired the event (i.e. the
object that was clicked on), not necessarily the one the handler is on.
- "this" will be the name of the object the handler is attached to.
Thanks. I missed that one and was using evt.currentTarget, which seemed iffy, before I decided not to put events in groups at all.
- The handler can call another function, passing the event, but also
passing other parameters.
- If a child object wants to consume an event and not pass it up to
its ancestors, you must call evt.stopPropagation()
Thanks. I didn't know about that one either.
I've put an example file up on my site which shows some of this at work:
http://peppertop.com/interactive_groups.svg
The whole file is a single group, but there are four onclick handlers (one on the group, one on each circle). Clicking a circle will change its colour randomly; clicking on the group (i.e. either lozenge shape) will change all three circles. There are also onmouseover and onmouseout handlers on the circles to thicken their borders when the mouse moves over them.
By putting a click handler on the group, and passing both "evt" and "this" you can get a reference to the object that was clicked ("evt.target") and the group itself ("this").
Other than demonstrating "this" and "if (e) e.stopPropagation();", is there a benefit to putting "onclick=change_all_colours();" on the group rather than on each losenge? I think the behavior would be identical, it would have simplified change_fill(), and would have required only one argument for change_fill().
I can see a benefit for my screw group, namely, that I wouldn't need to include the transparent cover. My screw group is somewhat atypical in that it should perform the identical action no matter what part of the group is clicked, hovered or unhovered, and there are no "blank" places in the group the way there are in your peppertop page in the area between the two losenges.
Let me give this some more thought, and thanks for another supremely instructive interactive SVG.
P.S. Did you see the message I posted a couple of weeks ago about making AJAX calls from SVG? I saw no feedback on it, so I'm not sure if it made it to the mailing list or not.
Yes. I had so much momentum on the stuff I was doing, that instead of exploring it I put it on my "later" pile. When I start making a back end for my apps, I'll study your AJAX methodology. Thanks for cluing me in about AJAX.
SteveT
Steve Litt May 2017 featured book: Twenty Eight Tales of Troubleshooting http://www.troubleshooters.com/28