Chapter 10  Scripting the DOM

Extract

Touching Elements

Since we can look at the computer mouse as the elongated arm of the user, mouse events play a big role in design for interactivity.


Figure 10-8. Rectangles with events

While focusing on events I chose a simple SVG document.
1.      The following code defines our five rectangles

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/SVG/DTD/svg10.dtd">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" onload="Init(evt);">
 
<script type="text/ecmascript" xlink:href="RemoveWhiteSpace.js"/>

 
<script type="text/ecmascript">
 
<![CDATA[
   
function Init(evt)
   
{
      
RemoveWhiteSpaceChildNodesOf(evt.target.ownerDocument.documentElement);
    }
  ]]>
  </script>
  <g>
     <rect x="10"  y="100" width="90" height="40" fill="blue" opacity="0.4" />
     <rect x="110" y="100" width="90" height="40" fill="green" opacity="0.4" />
     <rect x="210" y="100" width="90" height="40" fill="yellowgreen" opacity="0.4"
/>
     <rect x="310" y="100" width="90" height="40" fill="orange" opacity="0.4" />
     <rect x="410" y="100" width="90" height="40" fill="red" opacity="0.4" />
  </g>
  <text x="55"  y="160" text-anchor="middle">highlight</text>
  <text x="155" y="160" text-anchor="middle">magical</text>
  <text x="255" y="160" text-anchor="middle">changing color</text>
  <text x="355" y="160" text-anchor="middle">mutate</text>
  <text x="455" y="160" text-anchor="middle">click</text>
</svg>

All of these rectangles are child elements of a common group and have the opacity style attribute defined with a value of 0.4. We want to exploit this for a highlighting effect by setting the opacity to 1.0, when the user moves the mouse pointer over it.

Highlighting

So let’s start with the leftmost blue rectangle, labelled highlight, adding appropriate event properties.
1.      Add the event handler attribute to the first rectangle
2.      Then we need to implement the ECMAScript functions
Highlight and Unhighlight.

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/SVG/DTD/svg10.dtd">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" onload="Init(evt);">
  <script type="text/ecmascript" xlink:href="RemoveWhiteSpace.js"/>
  <script type="text/ecmascript">
  <![CDATA[
    function Init(evt)
    {
       RemoveWhiteSpaceChildNodesOf(evt.target.ownerDocument.documentElement);
    }
    function Highlight(evt)
    {
       evt.target.
setAttribute("opacity", "1.0");
    }
    function Unhighlight(evt)
    {
      
evt.target.
setAttribute("opacity", "0.4");
    }
  ]]>
  </script>
  <g>
    <rect x="10"  y="100" width="90" height="40" fill="blue" opacity="0.4"
         
onmouseover="Highlight(evt);" onmouseout="Unhighlight(evt);"/>
<!-- other elements here -->
</svg>

Thanks to the Event object’s target property we get access to <rect> element that received the event. With this we can set the rectangles opacity to 1.0, when the mouse enters its area and reset it to 0.4 when the mouse pointer leaves.


Figure 10-9. Highlight a rectangle

( test this svg )

Now, if we want to give the other rectangles the same behaviour, we must add these onmouseover and onmouseout event properties to them also.

 4.      But there seems to be a simpler solution. Remembering the event flows towards the parent element – called event bubbling. We could add the onmouseover and onmouseout event properties to the <g> element instead and leave it at that.

  <g onmouseover="Highlight(evt);" onmouseout="Unhighlight(evt);">
    
<rect x="10"  y="100" width="90" height="40" fill="blue" opacity="0.4" />
    
<rect x="110" y="100" width="90" height="40" fill="green" opacity="0.4" />
     <rect x="210" y="100" width="90" height="40" fill="yellowgreen" opacity="0.4"/>
     <rect x="310" y="100" width="90" height="40" fill="orange" opacity="0.4" />
    
<rect x="410" y="100" width="90" height="40" fill="red" opacity="0.4" />
 
</g>

Trying this out verifies that our considerations were correct. If we needed access to the <g> element inside the Highlight and Unhighlight functions, we would have used evt.currentTarget instead of evt.target.

Changing Color

We’ll come back to the ‘magical’ rectangle shortly but for now we want the third yellowgreen rectangle to change its color to black whenever the mouse is clicked on it.
5.      To achieve this effect, we have to register the <rect> element as an event listener for the onmousedown and onmouseup events.

    <rect x="210" y="100" width="90" height="40" fill="yellowgreen" opacity="0.4"
          
onmousedown="ChangeColor(evt);" onmouseup="ChangeColor(evt);"/>

6.      Next we must again implement the affiliated ECMAScript function. Now we intend to use a single function instead of one for onmousedown and another for onmouseup event. Here is the complete code.

    function ChangeColor(evt)
   
{
      
if (evt.type == "mousedown")
          
evt.target.setAttribute("fill", "black");
      
else if (evt.type == "mouseup")
         
evt.target.setAttribute("fill", "yellowgreen");

   
}



Figure 10-10. Change color of rectangle

( test this svg )

Now when we move the mouse pointer onto the yellowgreen rectangle, it is highlighted due to the parents event handler. Then when we press the mouse button the colour changes to black. Releasing the button turns the colour back to yellowgreen. — still highlighted.

 On the other hand, if we keep the mouse button pressed, move the mouse pointer away from the rectangle and then release the mouse button, the color remains black, though unhighlighted now.

Getting Invisible

For our next trick we’ll use the 2nd rectangle that we skipped over a moment ago. The goal here is for the fourth rectangle to disappear when the mouse is over this ‘magical’ rectangle. On the side we also want to suppress the highlighting effect.

7.      Adjust the code accordingly

 <rect x="110" y="100" width="90" height="40" fill="green" opacity="0.4"
     
onmouseover="Magical(evt);" onmouseout="Magical(evt);"/>

8.      The Magical function is similar to ChangeColor.

function Magical(evt)
{
   if (evt.type == "mouseover")
      evt.target.nextSibling.nextSibling.setAttribute("visibility", "hidden");
   else
      evt.target.nextSibling.nextSibling.removeAttribute("visibility");
   evt.stopPropagation ();
}


Figure 10-11. Hide rectangle

( test this svg )

As I am illustrating here, we can use the evt.target element as a start to navigate through the DOM tree and affect other elements by that particular event too. We also tested the interruption of the event flow via a call to evt.stopPropagation().

Mutating Elements

The next task is to change the fourth rectangle when clicking with the mouse on it, so that it becomes an ellipse. As we learned so far, we know that we cannot change an element’s type, we have to remove the element from the DOM tree and insert a new one instead. But I also told you, before using create and remove operations we should consider attribute manipulation in the first place. So here is one possible and simple solution. We add an <ellipse> element statically to our document and hide it with the display="none" attribute.

 9.      Enter the following code to the fourth rectangle

 <rect x="310" y="100" width="90" height="40" fill="orange" opacity="0.4"
        
onclick="Mutate(evt);" />
<ellipse cx="355" cy="120" rx="45" ry="20" fill="orange" display="none"
         onclick="Mutate(evt);" />

10.  Then we need only to move the display="none" attribute to the <rect> element and back to the <ellipse> element with each mouse click.

function Mutate(evt)
{
   var elem = evt.target;
   elem.setAttribute("display", "none"); // hide the displayed element ..
   if (elem.nodeName == "rect") // rectangle was displayed ..
      elem.nextSibling.removeAttribute("display"); // .. show ellipse
   else                       // ellipse was be displayed ..
      elem.previousSibling.removeAttribute("display");  // show rectangle
}
 }


Figure 10-12. Change shape

( test this svg )

Since the <ellipse> element is also a child of the same parent group, highlighting works automatically here too. You might be urged to ask here what the difference between the display attribute and the visibility attribute is, as you cannot see the elements then either. Regarding the mouse event sensibility there is indeed a significant difference:

·        Elements with visibility="hidden" attribute set are invisible and can receive mouse events, if they additionally define the attribute pointer-events="all".

·        Elements with display="none" attribute set are invisible and cannot receive mouse events.

 And that last behaviour was exactly what we wanted here.

Double Clicks

Sometimes we’ll want to differentiate between single and double mouse clicks. If you’ve read the MouseEvent’s properties, you’ll probably have noticed the detail property. This is a very commonly used property and its value varies with the event type. With the onclick event it stores the count of clicks the user performed.

11.  Just to test this we’ll register the last red rectangle as an onclick event listener.

   <rect x="410" y="100" width="90" height="40" fill="red" opacity="0.4"
        
onclick="ClickCounter(evt);"/>

12.  With the implementation of the ClickCounter function we need to display the number of current click counts. We’ll use the rectangles caption for this.

function ClickCounter(evt)
{

  
var clickText = evt.target.parentNode.parentNode.lastChild.firstChild;
  
clickText.nodeValue = evt.detail + ". click"
}

 
Figure 10-13. Click counter

( test this svg )

It obviously works. The first click always writes 1. click under the rectangle. The second click will produce different results based on several factors.

       ·        If the time between the first and the second click is too long we get 1. click again.

·        If the time between the first and the second click is short enough, but we displaced the mouse pointer slightly we get 1. click too.

·        If the time between the first and the second click is short enough and we didn’t displace the mouse pointer we get 2. click.



chapters: intro toc intro sample svg elements toc svg elements sample


To see SVG examples in HTML you need the SVG plugin:
Adobe SVG Viewer or Corel Viewer
You can also use Batik viewer to open SVG files.




SVG Tutorials
SVG Books
SVG Graphics
MapPoint
SVG Links


Compaq Nx7000 Battery

Motorcycle and Bike Repair Manuals smart file hosting

Direct Link Ads UK
Buy Direct Link Ads from the UKs top Offline Optimisation Company

Internet Marketing
Need help putting together a solid internet marketing strategy? Working with your budget, we will help you set up the best possible campaign. We currently have 700 clients with a 99% retention rate.

NLP Business and management training
Business and Leadership NLP. Using Business & Leadership skills 'NLP Practitioner Certification' is the most cutting-edge, personal development training now available to those working in business, sales and management who want to get ahead.

XML Elves
XML and SVG Discussion
- OSCON for FREE!
- Several updates from The Mozilla Project today.

| Rainbow Seeker | SVG PHP


Map Visitors Learn SVG: Contact Learn SVG
©2002-2008 Learn SVG. All Rights Reserved.
Questions and comments to: learnsvg@gmail.com