Wrox Programmer Forums
|
Javascript General Javascript discussions.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the Javascript section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old September 26th, 2003, 01:58 AM
richard.york's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 1,706
Thanks: 0
Thanked 6 Times in 6 Posts
Default Dynamic Link Menus

Hello,
    I am pretty *green* when it comes to JavaScript. I have been working on the dynamic link menu example in chapter 12 of the Beginning JavaScript book. I understand programming concepts really well.. I'm a PHP programmer by trade.
    What I am trying to do with the code is convert the example that takes an image object and takes the image's position and adds its width and then repositions a <div> element that onload is positioned off screen to the right of the image creating that dynamic link menu effect. I want to take this code and rewrite it so that the source element doesn't have to be an image, but rather plain text or a div.
    I would like to do something that doesn't rely on the source element as being absolutely positioned while maintaining the ambiguity of the code so that it can be reused in other projects. For now cross-browser compatibility doesn't matter to me. I use IE6.
    For the sake of learning I would grately appreciate someone walking me through the js objects and code required to create this ambiguity... rather than simply fixing my code.
     Thanks in advance!

: )
Rich

Code:
<html>
    <head>
        <style type='text/css'>

            .divMenu {
                position: absolute; 
                left: -200px; 
                top: -1000px; 
                width: 180px;
                z-index: 100;
                background-color: blue;
                border: 1px solid black;
            }

            .tdMenu {
                color: white;
                font-family: sans;
                font-size: 12pt;
                width: 100%;
                cursor: default;
            }

        </style>    
        <script language='JavaScript' type='text/javascript'>

            /*
             * Example using image elements as source object
             *
            */

            function show_menu(menu)
            {

                var srcElement  = event.srcElement;
                var x             = parseInt(srcElement.offsetLeft);
                var y            = parseInt(srcElement.offsetTop);

                menu.style.left = x + (srcElement.width);
                menu.style.top    = y;

            }

            function hide_menu(menu)
            {
                if (event.toElement != menu && menu.contains(event.toElement) == false)
                {

                    menu.style.left = -200;
                    menu.style.top    = -1000;

                }                

            }

            /*
             * Example using div or text elements as source object
             *
            */

            function show_menu_(menu)
            {

                var srcElement  = event.srcElement;
                var x             = parseInt(srcElement.style.left);
                var y            = parseInt(srcElement.style.top);

                                // This code does not work as expected! menu.style.left appears 2000 or 3000 pixels to the right!

                menu.style.left = x + (srcElement.style.width);
                menu.style.top    = y;

            }

            function hide_menu_(menu)
            {
                if (event.toElement != menu && menu.contains(event.toElement) == false)
                {

                    menu.style.left = -200;
                    menu.style.top    = -1000;

                }                

            }

            function goto_page(url)
            {

                window.location.href = url;

            }

        </script>
    </head>    
    <body>        



        <div id='divText' class='divMenu' onmouseout='return hide_menu(this)'>        
            <table>
                <tr>
                    <td id='tdText' RollOver='' RollOut='' class='tdMenu'>
                        some text<br />
                        some more text
                    </td>
                </tr>
            </table>                            
        </div>


        <img src='images/blue_background.jpg' id='thisImage' style='position: absolute; left: 10px; top: 75px; z-index: 1;' onmouseover='show_menu(divText)' onmouseout='hide_menu(divText)' />

        <div style='position: absolute; left: 10px; top: 100px; z-index: 1; width: 100px;'  onmouseover='show_menu_(divText)' onmouseout='hide_menu_(divText)'>
            test        
        </div>

    </body>    
</html>
:::::::::::::::::::::::::::::::::
Smiling Souls
http://www.smilingsouls.net
:::::::::::::::::::::::::::::::::
 
Old September 26th, 2003, 03:27 AM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,212
Thanks: 0
Thanked 1 Time in 1 Post
Default

Hi Rich,

I don't see anything there that is specific to an image.

The reason your code isn't working is coz in this line:
// This code does not work as expected! menu.style.left appears 2000 or 3000 pixels to the right!
menu.style.left = x + (srcElement.style.width);

the expression srcElement.style.width return the string 100px, so you think you're adding 10 to 100,
but actually you're getting string concatenation, i.e. menu.style.left gets the value 10100px !

The original show_menu uses the offsetLeft property, not the style.left property.
However, there is a problem with relying on offsetLeft because you'll find that it
represents the offset from its parent - so if you put the element in a table it all screws up.

Take a look at this previous post regarding exactly that subject:
http://p2p.wrox.com/topic.asp?TOPIC_ID=3419

hth
Phil
 
Old September 26th, 2003, 02:27 PM
richard.york's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 1,706
Thanks: 0
Thanked 6 Times in 6 Posts
Default

Thanks Phil,
    That post was very helpful. I still can't get it to work with a div that calls an onmouseover event (instead of an image).

I used the example in the post:

Code:
            function show_menu(menu)
            {

                var srcElement = event.srcElement;
                var x;
                var y;

                if (srcElement)
                {
                    x = srcElement.width;
                    y = 0;

                }

                while (srcElement)
                {

                    x            += srcElement.offsetLeft;
                    y            += srcElement.offsetTop;
                    srcElement  = srcElement.offsetParent;

                }

                menu.style.top    = y;
                menu.style.left = x;
            }



<img src='images/blue_background.jpg' id='thisImage' style='position: absolute; left: 10px; top: 75px; z-index: 1;' onmouseover='show_menu(divText)' onmouseout='hide_menu(divText)' />


        <div style='position: absolute; left: 10px; top: 100px; z-index: 1; width: 100px;' onmouseover='show_menu(divText)' onmouseout='hide_menu(divText)'>
            test        
        </div>
Would I need to include the parseInt() function? How would I add a number and a string in JavaScript? In PHP, PHP automatically extracts the integer from the string and treats it as an integer with respect to mathematical operations - ignoring everything but the integer content of the string. Is there a method in JavaScript that will do the same? I use the 'px' for standards compliance. Mostly because Navigator has no default measurement mechanism and when the unit of measurement is left off it causes the browser to not display or render certain CSS elements.

Thanks Again,
Rich

:::::::::::::::::::::::::::::::::
Smiling Souls
http://www.smilingsouls.net
:::::::::::::::::::::::::::::::::
 
Old September 26th, 2003, 05:23 PM
richard.york's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 1,706
Thanks: 0
Thanked 6 Times in 6 Posts
Default

Hello again,
    I was able to answer many of my own questions with a bit of research. The culprit it seems was the call to x = srcElement.width; when the value of 'x' was output it contained a 'NaN' value. The following is what I did to get around it.


Code:
            function show_menu(menu)
            {

                // parseInt() - Extract only the integer value
                // If the srcElement.width object does not contain a numeric value
                // Use the srcElement.style.width object, which must be defined

                var srcElement = event.srcElement;
                var x;
                var y;

                if (srcElement)
                {
                    x = parseInt(srcElement.width);

                    if (isNaN(x))
                    {

                        x = parseInt(srcElement.style.width);

                    }

                    y = 0;

                }

                while (srcElement)
                {

                    x            += parseInt(srcElement.offsetLeft);
                    y            += parseInt(srcElement.offsetTop);
                    srcElement  = srcElement.offsetParent;

                }

                if (isNaN(x))
                {

                    output(x);

                }

                menu.style.top    = y + 'px';
                menu.style.left = x + 'px';

            }

            function output(object)
            {

                document.write('<br />' + object + '<br />');                

            }
Is there any other object that I could use, besides the 'srcElement.style.width' that would give me that value? Am I correct in deducing that value must be explicitly defined in the HTML source?

Thanks again for your insight!
: )
Rich

:::::::::::::::::::::::::::::::::
Smiling Souls
http://www.smilingsouls.net
:::::::::::::::::::::::::::::::::
 
Old September 29th, 2003, 03:33 AM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,212
Thanks: 0
Thanked 1 Time in 1 Post
Default

Quote:
quote:Originally posted by quesadilla5
 Hello again,
    I was able to answer many of my own questions with a bit of research. The culprit it seems was the call to x = srcElement.width; when the value of 'x' was output it contained a 'NaN' value. The following is what I did to get around it.
...
Is there any other object that I could use, besides the 'srcElement.style.width' that would give me that value? Am I correct in deducing that value must be explicitly defined in the HTML source?

Thanks again for your insight!
: )
Rich

:::::::::::::::::::::::::::::::::
Smiling Souls
http://www.smilingsouls.net
:::::::::::::::::::::::::::::::::
Ah, of course, now I see your problem on using divs instead of images - images (nearly) always have a width attribute defined, but divs do not. Sorry, that should have clicked before.

Ok, the style property exposes inline style statements, e.g. width, so if you don't specify the width then all you get is an empty string.
(You've already noticed, no doubt, that div element does not have an HTML width attribute defined). Also, I'm pretty sure that the style property only exposes inline styles, so any inherited styles, or styles from external CSS don't get picked up. IE exposes a currentStyle property which picks up a lot more of these.

For a div I think the most reliable property to use would be the offsetWidth (that's divName.offsetWidth, not divName.style.offsetWidth) because that will give you the width whether or not it has been explicitly specified by a CSS style (although, for your example, you would always want to specify the width otherwise the div takes up the entire browser width since it is a block element).

hth
Phil
 
Old September 29th, 2003, 03:55 AM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,212
Thanks: 0
Thanked 1 Time in 1 Post
Default

Hi Rich,

Just had another thought on this. There was a recent post that talked about getting the width of the actual text in a div or span object, and I thought that you might get you a nicer looking result if you didn't specify the actual width of the div, but instead just used the width of the actual text to position the menu. The topic link is here http://p2p.wrox.com/topic.asp?TOPIC_ID=3794, however, it doesn't work nicely for divs (presumably because they are block elements), but it does work well for <span> elements (presumably because they are in-line elements). So maybe you might ant to try using <span> instead of <div>.

rgds
Phil
 
Old September 29th, 2003, 11:58 PM
richard.york's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 1,706
Thanks: 0
Thanked 6 Times in 6 Posts
Default

Hi Phil!
    The offsetWidth did the trick. Although it ended up being:

document.getElementById(tdid).offsetWidth;

and not

srcElement.offsetWidth;

As mentioned in the second post you directed me to. Works beautifully! Thanks for the insight.

For anyone interested, the following is what I ended up with, which works for images or inlines. I have yet to write compatibility code for NS/Mozilla so this only works in IE.

Code:
        /*
         * Dynamically reposition an element
         * void show_menu(string id to reposition, string id of source element)
        */

        function show_menu(menu, tdid)
        {

            // parseInt() - Extract only the integer value
            // If the srcElement.width object does not contain a numeric value
            // Use the offsetWidth property instead
            // if the offestWidth property does not contain a numeric value
            // Use the srcElement.style.width property instead, which must be defined explicitly

            var srcElement = event.srcElement;
            var x;
            var y = 0;

            if (srcElement)
            {
                x = parseInt(srcElement.width);

                if (isNaN(x))
                {

                    x = parseInt(document.getElementById(tdid).offsetWidth);

                    if (isNaN(x))
                    {

                        x = parseInt(srcElement.style.width);

                    }

                }

            }

            if (isNaN(x))
            {

                alert('Error: x is NaN');     

            }

            while (srcElement)
            {

                x            += parseInt(srcElement.offsetLeft);
                y            += parseInt(srcElement.offsetTop);
                srcElement  = srcElement.offsetParent;

            }

            // shift x slightly to the left    
            x = x - 5;

            document.getElementById(menu).style.top     = y + 'px';
                document.getElementById(menu).style.left = x + 'px';

        }
: )
Rich



:::::::::::::::::::::::::::::::::
Smiling Souls
http://www.smilingsouls.net
:::::::::::::::::::::::::::::::::
 
Old July 7th, 2004, 02:25 PM
Authorized User
 
Join Date: Jun 2003
Posts: 83
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via ICQ to natmaster Send a message via AIM to natmaster Send a message via MSN to natmaster
Default

of course, there are simpler ways to make a popup menu.

http://www.meyerweb.com/eric/css/edge/menus/demo.html

describes a way to make css popup menus that work with non-IE browsers. now if you want IE compatibility, you can easily add some simple java scripts to change the style.display from none to block so everything functions properly.

There methods are much more simple, which provides faster loadtime for the page, easier updates, and faster run-time efficiency, not to mention forwards compatibility.

----------------------------
Aeon of Darkness MUD - Free Online Roleplaying Game
http://aeonofdarkness.com
 
Old July 7th, 2004, 05:23 PM
richard.york's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 1,706
Thanks: 0
Thanked 6 Times in 6 Posts
Default

This thread is pretty *old*.. but I'll answer myself for new people that find it ;).

It is possible to do menus with no javascript at all in all of the major browsers, IE, Gecko, Opera, Safari.. etc. with pure CSS.

See: http://dean.edwards.name/IE7

This URL offers a collection of IE behaviours that make meyer's pure CSS menus example work flawlessly in IE 6.

Regards,
Rich

::::::::::::::::::::::::::::::::::::::::::
The Spicy Peanut Project
http://www.spicypeanut.net
::::::::::::::::::::::::::::::::::::::::::





Similar Threads
Thread Thread Starter Forum Replies Last Post
Dynamic menus and content? gabster XSLT 6 October 16th, 2007 10:05 AM
Dynamic Menus - Using multiple dropdown boxes Sebastiaan ASP.NET 1.0 and 1.1 Basics 1 April 18th, 2007 06:25 AM
Code Announcement: Ch3, Dynamic Drop Down Menus richard.york BOOK: CSS Instant Results 0 November 14th, 2006 10:57 AM
Dynamic Link Section beetle_jaipur Classic ASP Databases 0 May 3rd, 2006 12:42 AM
dynamic menus off odbc database sionsolo42069 ASP.NET 2.0 Professional 5 March 21st, 2006 12:33 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.