SVG Clickmap Landmines

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

SVG Clickmap Landmines

Steve Litt
Hi all,

I think I understand SVG clickmaps now, how to make them, how to
troubleshoot them, and the like. But it took a long time to learn
because I kept running into time consuming problems. There's
documentation about those problems, but it's scattered all over the
web, and much of it's contradictory. I'd still be trying to put it
together if not for the help of several people on this mailing list,
and I thank you for that.

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

SteveT

Steve Litt
May 2017 featured book: Twenty Eight Tales of Troubleshooting
http://www.troubleshooters.com/28



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Inkscape-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/inkscape-user
Reply | Threaded
Open this post in threaded view
|

Re: SVG Clickmap Landmines

Mark Crutch-2
Steve,

On Mon, May 8, 2017 at 4:02 AM, Steve Litt <[hidden email]> 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...

1) "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().


2) 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.


3) "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.
* 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()


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").


Regards,

Mark

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.





------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Inkscape-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/inkscape-user
Reply | Threaded
Open this post in threaded view
|

Re: SVG Clickmap Landmines

Steve Litt
On Mon, 8 May 2017 11:24:57 +0100
Mark Crutch <[hidden email]> wrote:

> Steve,
>
> On Mon, May 8, 2017 at 4:02 AM, Steve Litt <[hidden email]>
> 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...
>
> 1) "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.


>
>
> 2) 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.

>
>
> 3) "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



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Inkscape-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/inkscape-user
Reply | Threaded
Open this post in threaded view
|

Re: SVG Clickmap Landmines

Mark Crutch-2
On Tue, May 9, 2017 at 1:19 AM, Steve Litt <[hidden email]> wrote:

> 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.

Support is excellent - all the way back to IE9 (and IE8, if you limit the choice of selectors).

http://caniuse.com/#search=querySelector

The limitations are purely those inherent in CSS selectors in general - e.g. that you can only select descendants of your chosen node, not its ancestors, and that there's no CSS selector for "the current node itself" ("this", if you will). None if this is likely to affect your use of them, and as a replacement for getElement(s)By... there are no real downsides.
 

> 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().

No, it was purely demonstrative to show that you can put a handler on the <g> and use "this" to get a reference to the group.

Regards,

Mark



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Inkscape-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/inkscape-user
Reply | Threaded
Open this post in threaded view
|

Re: SVG Clickmap Landmines

Steve Litt
On Tue, 9 May 2017 09:45:43 +0100
Mark Crutch <[hidden email]> wrote:

> On Tue, May 9, 2017 at 1:19 AM, Steve Litt <[hidden email]>
> wrote:
>
> >  
> > > 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.
>
> Support is excellent - all the way back to IE9 (and IE8, if you limit
> the choice of selectors).
>
> http://caniuse.com/#search=querySelector

This caniuse.com seems like an excellent resource. Thanks!

It looks like .querySelector() works with major browsers back at least
5 years, and that's good enough. Actually, according to this page, my
user of <embed/> is a bigger problem.

>
> The limitations are purely those inherent in CSS selectors in general
> - e.g. that you can only select descendants of your chosen node, not
> its ancestors,

Sounds pretty good to me. If I wanted to cast a wider net, I'd do
document.querySelector('.whatever') instead of
myElement.querySelector('.whatever').


> and that there's no CSS selector for "the current node
> itself" ("this", if you will). None if this is likely to affect your
> use of them, and as a replacement for getElement(s)By... there are no
> real downsides.

Thanks.

>
>
> > 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().
> >  
>
> No, it was purely demonstrative to show that you can put a handler on
> the <g> and use "this" to get a reference to the group.

After considerable thought, my screwhead and LED objects will have the
methods on the group, use "this" instead of e.currentTarget or a
parent-looping use of e.target to find the group, and
mygroup.querySelector('.screwhead') to find the subcomponent that will
change colors. By doing this, I eliminate the transparent cover, which
could become somewhat important when I'm making over 100 copies of
these group objects.

When you clued me in to 'this', it opened a world of possibilities.

Thanks
 
SteveT

Steve Litt
May 2017 featured book: Twenty Eight Tales of Troubleshooting
http://www.troubleshooters.com/28



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Inkscape-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/inkscape-user
Reply | Threaded
Open this post in threaded view
|

Re: SVG Clickmap Landmines

Mark Crutch-2


On Tue, May 9, 2017 at 7:57 PM, Steve Litt <[hidden email]> wrote:

> The limitations are purely those inherent in CSS selectors in general
> - e.g. that you can only select descendants of your chosen node, not
> its ancestors,

Sounds pretty good to me. If I wanted to cast a wider net, I'd do
document.querySelector('.whatever') instead of
myElement.querySelector('.whatever').


The limitation of not being able to select ancestors can sometimes be a problem if you've got an event handler. Consider this example of a few groups within groups:

<g id="myParent">
  <g onclick="clicked(this);">
    <g class="inner">
      <circle id="circle1" ... />
    </g>
  </g>

  <g onclick="clicked(this);">
    <g class="inner">
      <circle id="circle2"... />
    </g>
  </g>
</g>


In your event handler you get a handle to the clicked group, but if you wanted to get a handle to the parent element ("myParent"), there's no way to use querySelector() to get to it. E.g.

function clicked(oGroup) {
  var c = oGroup.querySelector(".inner > circle");   // Gets the circle - selecting into the tree is fine
  var c = oGroup.querySelector("g > circle");         // Does the same
  var c = oGroup.querySelector("circle");               // So does this (in this case)
  var c = oGroup.querySelector("g circle");            // As does this (in this case), but a little less efficiently

  // If I want to get the parent group, this would be a nice option...
  var g = oGroup.querySelector("this < g");  // There's no "this" in CSS, and no "<" as a parent selector. This will fail.

  // Instead I end up doing this...
  var g = oGroup.parentNode;
}


In this simple example that's not too bad, but when you start getting more complex DOM structures, you can end up having to maintain code that has "this.parentNode.parentNode.nextElementSibling.parentNode" and similarly fragile structures.


So yes, you can use document.querySelector() to select from the entire document, or node.querySelector() to restrict the selection, but depending on your "starting point" it you might not have the luxury of choice. It's generally a lot easier going down into the tree than walking back up it.

 
When you clued me in to 'this', it opened a world of possibilities.

Just be a little careful with "this", as it can change depending on how a function is called. It's often worth logging it out to make sure it actually represents the thing you think it does. This can be a particular problem if you start trying to do anything asynchronously, using setTimeout() or similar.


Regards,

Mark



 


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Inkscape-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/inkscape-user