home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2004 March / PCWMAR04.iso / Sponsors / Xara / Tutorial / xaramenu.js < prev   
Encoding:
JavaScript  |  2002-05-21  |  11.4 KB  |  402 lines

  1. // ⌐Xara Ltd 2002
  2. // variables used to store info on each menu that is visible
  3. var ma = new Array();
  4. var mx = new Array();
  5. var my = new Array();
  6. var mc = new Array();
  7. var mal = 0;
  8.  
  9. var main = 0;
  10. var menuw = 200;
  11. var psrc = 0;
  12. var pname = "";
  13. var al="";
  14.  
  15. // browser sniffer function
  16. var NS6 = (!document.all && document.getElementById);
  17. var NS4 = (!document.getElementById);
  18. var IE5 = (!NS4 && !NS6 && navigator.userAgent.indexOf('MSIE 5.0')!=-1);
  19. // Opera misbehaves so treat it like NS4
  20. if (navigator.userAgent.indexOf('Opera')!=-1) NS4=1;
  21.  
  22. // must be called to start a navbar menu
  23. // file = the top/left navbar end
  24. // dir = direction of the navbar 1 for vertical, 2 for horizontal, 3 for nontable vertical and 4 for nontable horizontal
  25. // space = the spacing between buttons
  26. // align = 1 right justify the graphics in the table, 2 = center the graphics, anything else and left justify them
  27. function startMainMenu(file, h, w, dir, space, align)
  28. {
  29. if (w>0) menuw = w;
  30. main = dir;
  31. if (main == 1 || main == 2) document.write("<table border=\"0\" cellspacing=\"" + space + "\" cellpadding=\"0\">");
  32. if (file != "")
  33.     {
  34.     al="";
  35.     if (align==1) al=" align=\"right\"";
  36.     if (align==2) al=" align=\"center\"";
  37.     if (main == 1 || main == 2) document.write("<tr><td" + al + ">");
  38.     document.write("<img src=\"" + loc + file + "\" border=\"0\"");
  39.     if (h>0) document.write(" height=\"" + h + "\"");
  40.     if (w>0) document.write(" width=\"" + w + "\"");    
  41.     document.write(" />");
  42.     if (main == 1 || main == 2) document.write("</td>");
  43.     if (main == 1) document.write("</tr>");
  44.     if (main == 3) document.write("<br></br>");
  45.     }
  46. }
  47.  
  48. // must be called to end a navbar menu
  49. // file = the graphic of the bottom/right end bar
  50. // h = height of the end bar graphic if applicable, zero to ignore
  51. // w = width of the end bar graphic if applicable, zero to ignore
  52. function endMainMenu(file, h, w)
  53. {
  54. if (file != "")
  55.     {
  56.     if (main == 1) document.write("<tr>");
  57.     if (main == 1 || main == 2) document.write("<td" + al + ">");
  58.     document.write("<img src=\"" + loc + file + "\" border=\"0\"");
  59.     if (h>0) document.write(" height=\"" + h + "\"");
  60.     if (w>0) document.write(" width=\"" + w + "\"");    
  61.     document.write(" />");
  62.     if (main == 1 || main == 2) document.write("</td></tr>");
  63.     }
  64. if (main == 1 || main == 2) document.write("</table>");
  65. main = 0;
  66. }
  67.  
  68. // called for each graphic element and source of a menu in the navbar menu
  69. // name = the unique name of the submenu to create. Also the name of graphic if the ext is ".gif" etc.
  70. //    if so graphics are required for name.ext and possibly name_over.ext
  71. // ext = the graphic file extention eg ".gif", if it doesnt start with a . is assumed to be a text element in the menu
  72. // url = the url this item links to
  73. // tar = the target
  74. // dir = the direction of the submenu 1 to the right, 2 down, 3 to the left
  75. // state = number of button states 1 for static graphics, 2 for showing over states
  76. // s = the css class which controls what this entry looks like in terms of font, colour, rollover, triangle graphics etc
  77. function mainMenuItem(name, ext, h, w, url, tar, alt, dir, state, s)
  78. {
  79.     if (NS4 && main==0) return;
  80.     var isgraphic = ext.charAt(0)==".";
  81.  
  82.     if (main == 1) document.write("<tr>");
  83.     if (main == 1 || main == 2) document.write("<td" + al + ">");
  84.  
  85.     document.write("<a ");
  86.     if (url != "" || !isgraphic) document.write("href=\"" + url + "\" ");
  87.     if (tar != "") document.write("target=\"" + tar + "\" ");
  88.     document.write ("onmouseout=\"");
  89.     if (dir > 0) document.write("tidyMenu(event);");
  90.     document.write("\" onmouseover=\"");
  91.     if (dir > 0) document.write("openMenu(event, '" + name + "'," + dir + "," + bc + "," + fc + ");");
  92.     if (state > 1 && isgraphic)
  93.         {
  94.         // cache the over state if required
  95.         document[name+"_over"] = new Image();
  96.         document[name+"_over"].src = loc + name+"_over"+ext;
  97.         // if there is an over state make it select it
  98.         document.write("setGraphic(event, '" + loc + name + "_over" + ext + "');");
  99.         }
  100.     document.write("return false;\"");
  101.     
  102.     if (!isgraphic) document.write(" class=\""+s+"\" style=\"width:" + (w>0?w:menuw) + "px\"");
  103.     
  104.     document.write(">");
  105.     if (isgraphic)
  106.     {    
  107.         document.write("<img src=\"" + loc + name + ext + "\" border=\"0\"");
  108.         if (h>0) document.write(" height=\"" + h + "\"");
  109.         if (w>0) document.write(" width=\"" + w + "\"");
  110.         if (alt!="") document.write(" alt=\"" + alt + "\"");
  111.         document.write(" />");
  112.     }
  113.     else
  114.     {
  115.         document.write(" " + ext + " ");
  116.     }
  117.         
  118.     document.write("</a>");
  119.     if (main == 1 || main == 2) document.write("</td>");
  120.     if (main == 1) document.write("</tr>");
  121.     if (main == 3) document.write("<br></br>");
  122. }
  123.  
  124. // called first when defining a submenu
  125. // name = unique name of the submenu
  126. function startSubmenu(name, style, sw)
  127. {
  128.     if (NS4) return;
  129.     if (sw>0) menuw = sw;
  130.     document.write("<div id=\"" + name + "\" class=\""+ style + "\"  style=\"width:" + (menuw+(NS6?bd*2:0)) + "px\">");
  131. }
  132.  
  133. // called to mark the end of a submenu definition
  134. // name = unique name of the submenu
  135. function endSubmenu(name)
  136. {
  137.     if (NS4) return;
  138.     document.write("</div>");
  139.     // register the mouseout from this div
  140.     if (!NS6) document.getElementById(name).onmouseout = tidyMenu;
  141. }
  142.  
  143. // called to define each element on the submenu
  144. // text = the menu items text
  145. // url = its url
  146. // tar = its target
  147. // s = css class name
  148. function submenuItem(text, url, tar, s)
  149. {
  150.     if (NS4) return;
  151.     if (text.charAt(0) == '<')
  152.         document.write(text);
  153.     else
  154.     {
  155.         document.write("<a ");
  156.         if (url != "") document.write("href=\"" + url + "\" ");
  157.         if (tar != "") document.write("target=\"" + tar + "\" ");
  158.         document.write("class=\""+s+"\" style=\"width:" + menuw + "px\"> " + text + " </a>");
  159.     }
  160. }
  161.  
  162. // change the image that spawned the event to show the graphic 'file'
  163. function setGraphic(event, name)
  164. {
  165.     if (NS4) return;
  166.     psrc = (NS6) ? event.target : event.srcElement;
  167.     pname = psrc.src;
  168.  
  169.     if (NS6)
  170.         event.target.src = name;
  171.     else
  172.         event.srcElement.src = name;
  173.         
  174. }
  175.  
  176. // open the submenu
  177. // id = the name of the submenu
  178. // pos = the relative position of the submenu 1 to right, 2 down, 3 to left
  179. function openMenu(event, id, pos, bc, fc)
  180. {
  181.     if (NS4) return;
  182.     var el, x, y;
  183.     //if the menu is still opening up snap it to fully open first then see what we have
  184.     if (mal>0)
  185.     {
  186.         el = document.getElementById(ma[mal-1]);
  187.         if (mx[mal-1] != el.offsetLeft || my[mal-1] != el.offsetTop)
  188.         {
  189.             el.style.left = mx[mal-1];
  190.             el.style.top = my[mal-1];
  191.         }
  192.  
  193.     tidyMenu(event);
  194.     }
  195.         
  196.     if (NS6)
  197.     {
  198.         if (mal == 0)
  199.         {
  200.             x = event.target.x - bd;
  201.             y = event.target.y;
  202.             dx = event.target.offsetWidth;
  203.             dy = event.target.offsetHeight;
  204.         }
  205.         else
  206.         {
  207.             var p = event.target;
  208.             if (p.nodeName != "A" && p.parentNode.nodeName == "A")
  209.                 p = p.parentNode;
  210.  
  211.             dx = p.offsetWidth;
  212.             dy = p.offsetHeight;
  213.             el = document.getElementById(ma[mal-1]);
  214.             x = el.offsetLeft - bd;
  215.             y = el.offsetTop + p.offsetTop;
  216.         }
  217.  
  218.     }
  219.     else
  220.     {
  221.         x = event.clientX - event.offsetX + document.body.scrollLeft - document.body.clientLeft;
  222.         y = event.clientY - event.offsetY + document.body.scrollTop - document.body.clientTop - bd;
  223.         dx = event.srcElement.offsetWidth;
  224.         dy = event.srcElement.offsetHeight;
  225.         if (mal>0) x-=2*bd;
  226.  
  227.     }
  228.             
  229.     el = document.getElementById(id);
  230.     if (el && el.style.visibility != "visible")
  231.     {
  232.         if (pos == 1)
  233.         {
  234.             x += dx;
  235.             el.style.left = x-el.offsetWidth;
  236.             el.style.top  = y;
  237.             nspeed = el.offsetWidth / frames;
  238.         }
  239.         else if (pos == 2)
  240.         {
  241.             y += dy;
  242.             el.style.left = x;
  243.             el.style.top  = y-el.offsetHeight;
  244.             nspeed = el.offsetHeight / frames;
  245.         }
  246.         else if (pos == 3)
  247.         {
  248.             x -= el.offsetWidth;
  249.             el.style.left = x+el.offsetWidth;
  250.             el.style.top  = y;
  251.             nspeed = el.offsetWidth / frames;
  252.         }
  253.  
  254.         mx[mal] = x;
  255.         my[mal] = y;        
  256.  
  257.         if (NS6 || IE5 || frames==0)
  258.         {
  259.             el.style.left = x;
  260.             el.style.top = y;
  261.         }
  262.                 
  263.         if (!IE5) clipMenu(mal, el);
  264.         el.style.visibility = "visible";
  265.         ma[mal] = id;
  266.         
  267.         if (NS6)
  268.         {
  269.             var p = event.target;
  270.             if (p.nodeName != "A" && p.parentNode.nodeName == "A")
  271.                 p = p.parentNode;
  272.             mc[mal] = p.style;
  273.             // format the NS6 likes its colours to be in
  274.             //mc[mal].backgroundColor = "#ffffff";
  275.             //mc[mal].color = "#ff0000";
  276.             
  277.             el.onmouseout = tidyMenu;
  278.         }
  279.         else
  280.         {
  281.             mc[mal] = event.srcElement.style;
  282.             if (mal>0)
  283.             {
  284.                 mc[mal].backgroundColor = bc;
  285.                 mc[mal].color = fc;
  286.             }
  287.         }
  288.         mal++;
  289.     }
  290. }
  291.  
  292. // return the name of the menu which contains x,y
  293. function overMenu(x,y)
  294. {
  295.     for (i=0; i < mal; i++)
  296.     {
  297.         var el = document.getElementById(ma[i]);
  298.         if (el.offsetLeft + el.offsetWidth > x && el.offsetLeft <= x
  299.         && el.offsetTop + el.offsetHeight > y && el.offsetTop <= y)
  300.         {
  301.             return ma[i];
  302.         }
  303.     }
  304.     return "";
  305. }
  306.  
  307. // the cursor has left a menu or a button
  308. // tidy away menus that the cursor isnt over or arnt parents of a menu the cursor is over
  309. // the parents are identified by having a name that starts the same as the child
  310. // eg if the child is called menu2_3_1 the parent would be called menu2_3
  311. function tidyMenu(e)
  312. {
  313.     if (NS4) return;
  314.  
  315.     if (NS6)
  316.     {
  317.         t = overMenu(e.pageX, e.pageY);
  318.     
  319.         // remove NS flicker since it defines events when moving between different parts of the same object
  320.         if (t!="" && (e.target.firstChild == e.relatedTarget || e.target == e.relatedTarget.firstChild))
  321.             return;
  322.         
  323.     }
  324.     else
  325.         t = overMenu(event.clientX + document.body.scrollLeft-document.body.clientLeft, event.clientY + document.body.scrollTop-document.body.clientTop);
  326.         
  327.     om = 0;
  328.     for (i=0; i < mal; i++)
  329.     {
  330.         var mail = ma[i].length;
  331.         if (mail > t.length || t.substring(0, mail) != ma[i])
  332.         {
  333.             var el = document.getElementById(ma[i]);
  334.             el.style.visibility = "hidden";
  335.             mc[i].backgroundColor = "";
  336.             mc[i].color = "";
  337.         }
  338.         else
  339.         {
  340.             ma[om] = ma[i];
  341.             mx[om] = mx[i];
  342.             my[om] = my[i];
  343.             om++;
  344.         }
  345.     }
  346.     mal = om;
  347.     
  348.     // replace the button graphic
  349.     if (mal == 0 && psrc) psrc.src = pname;
  350. }
  351.  
  352. // function called every 50 millisecs to make the menus slide out
  353. function animate()
  354. {
  355.     for (i=0; i < mal; i++)
  356.     {
  357.         var el = document.getElementById(ma[i]);
  358.         if (el.style.visibility == "visible")
  359.         {
  360.             if (el.offsetLeft < mx[i]) el.style.left = Math.min(el.offsetLeft + nspeed,  mx[i]) + "px";
  361.             if (el.offsetLeft > mx[i]) el.style.left = Math.max(el.offsetLeft - nspeed, mx[i]) + "px";        
  362.             if (el.offsetTop < my[i]) el.style.top = Math.min(el.offsetTop + nspeed, my[i]) + "px";
  363.             clipMenu(i, el);
  364.         }
  365.     }
  366.     
  367.     if (mal!=0 || frames!=0)
  368.         setTimeout("animate()", 50);
  369. }
  370.  
  371. // clip the menus while they slide out
  372. function clipMenu(i, el)
  373. {
  374.     if (el.offsetLeft > mx[i]) el.style.clip = "rect(" + (my[i]-el.offsetTop) + "px "+ (el.offsetWidth+(mx[i]-el.offsetLeft)) + "px " + el.offsetHeight + "px " + 0 + "px)";
  375.     else el.style.clip = "rect(" + (my[i]-el.offsetTop) + "px "+ el.offsetWidth + "px " + el.offsetHeight + "px " + (mx[i]-el.offsetLeft) + "px)";
  376. }
  377.  
  378. // debug function only - not part of the menus at all. Used to probe the DOM.
  379. // object = enumerate the properties of this object
  380. function showpropsign(object)
  381. {
  382.     t = 0;
  383.     str=""
  384.     for (var i in object)
  385.     {
  386.         if (i != "innerHTML" && i != "innerText" && i != "outerText" && i != "outerHTML" && i != "preventBubble"
  387.          && i != "preventCapture" && i != "initEvent" && i != "view")
  388.          {
  389.             str += i + " = " + object[i] + "\n";
  390.             t++;
  391.             if (t > 10)
  392.             {
  393.             alert(str);
  394.             str = "";
  395.             t = 0;
  396.             }
  397.          }
  398.     }
  399.     if (t > 0) alert(str)
  400. }
  401.  
  402.