home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2006 April / DPPRO0406DVD.ISO / Essentials / Programming / Eclipse SDK / eclipse-SDK-3.1.1-win32.exe / eclipse / plugins / org.eclipse.help.webapp_3.1.0 / advanced / toc.js < prev    next >
Encoding:
JavaScript  |  2005-09-29  |  12.8 KB  |  608 lines

  1. /*******************************************************************************
  2.  * Copyright (c) 2000, 2004 IBM Corporation and others.
  3.  * All rights reserved. This program and the accompanying materials 
  4.  * are made available under the terms of the Eclipse Public License v1.0
  5.  * which accompanies this distribution, and is available at
  6.  * http://www.eclipse.org/legal/epl-v10.html
  7.  * 
  8.  * Contributors:
  9.  *     IBM Corporation - initial API and implementation
  10.  *******************************************************************************/
  11.  
  12. // Common scripts for IE and Mozilla.
  13.  
  14. var isMozilla = navigator.userAgent.indexOf('Mozilla') != -1 && parseInt(navigator.appVersion.substring(0,1)) >= 5;
  15. var isIE = navigator.userAgent.indexOf('MSIE') != -1;
  16.  
  17. var oldActive;
  18. var oldActiveClass = "";
  19.  
  20.  
  21. // Preload images
  22. // **********************************************************
  23. // Note: code moved into the jsp, for dynamic image preferences
  24.  
  25. /**
  26.  * Returns the target node of an event
  27.  */
  28. function getTarget(e) {
  29.     var target;
  30.       if (isMozilla)
  31.           target = e.target;
  32.       else if (isIE)
  33.            target = window.event.srcElement;
  34.  
  35.     return target;
  36. }
  37.  
  38. /**
  39.  * Returns the next tree node "down" from current one
  40.  */
  41. function getNextDown(node)
  42. {
  43.     var a = getAnchorNode(node);
  44.     if (!a) return null;
  45.         
  46.     // Try visible child first
  47.     var li = a.parentNode;
  48.     var ul = getChildNode(li, "UL");
  49.     if (ul && ul.className == "expanded")
  50.         return getDescendantNode(ul, "A");
  51.     
  52.     // Try next sibling
  53.     var li_sib = getNextSibling(li);
  54.     if (li_sib != null)
  55.         return getDescendantNode(li_sib, "A");
  56.         
  57.     // Try looking to parent's sibling
  58.     while(li_sib == null) {
  59.         var ul = li.parentNode;
  60.         li = ul.parentNode;
  61.         if (li.tagName != "LI") // reached the top, nothing else to do
  62.             return null;
  63.             
  64.         li_sib = getNextSibling(li);        
  65.     }
  66.         
  67.     // found the next down sibling
  68.     return getDescendantNode(li_sib, "A");        
  69. }
  70.  
  71. /**
  72.  * Returns the next tree node "down" from current one
  73.  */
  74. function getNextUp(node)
  75. {
  76.     var a = getAnchorNode(node);
  77.     if (!a) return null;
  78.         
  79.     // Get previous sibling first
  80.     var li = a.parentNode;
  81.     var li_sib = getPrevSibling(li);
  82.     if (li_sib != null) {
  83.         // try to get the deepest node that preceeds this current node
  84.         var candidate = getDescendantNode(li_sib, "A");
  85.         var nextDown = getNextDown(candidate);
  86.         while(nextDown != null && nextDown != node){
  87.             candidate = nextDown;
  88.             nextDown = getNextDown(nextDown);
  89.         }
  90.         return getDescendantNode(candidate, "A");    ;
  91.     } else {
  92.         // get the parent
  93.         var li = li.parentNode.parentNode;
  94.         if (li && li.tagName == "LI")
  95.             return getDescendantNode(li, "A");
  96.         else
  97.             return null;
  98.     }
  99. }
  100.  
  101. /**
  102.  * Returns the next sibling element
  103.  */
  104. function getNextSibling(node) 
  105. {
  106.     var sib = node.nextSibling;
  107.     while (sib && (sib.nodeType == 3 || sib.tagName=="SCRIPT")) // text or script node
  108.         sib = sib.nextSibling;
  109.     return sib;
  110. }
  111.  
  112. /**
  113.  * Returns the next sibling element
  114.  */
  115. function getPrevSibling(node) 
  116. {
  117.     var sib = node.previousSibling;
  118.     while (sib && (sib.nodeType == 3 || sib.tagName=="SCRIPT")) // text or script node
  119.         sib = sib.previousSibling;
  120.     return sib;
  121. }
  122.  
  123.  
  124. /**
  125.  * Returns the child node with specified tag
  126.  */
  127. function getChildNode(parent, childTag)
  128. {
  129.     var list = parent.childNodes;
  130.     if (list == null) return null;
  131.     for (var i=0; i<list.length; i++)
  132.         if (list.item(i).tagName == childTag)
  133.             return list.item(i);
  134.     return null;
  135. }
  136.  
  137. /**
  138.  * Returns the descendat node with specified tag (depth-first searches)
  139.  */
  140. function getDescendantNode(parent, childTag)
  141. {    
  142.     if (parent == null) return null;
  143.     
  144.     if (parent.tagName == childTag)
  145.         return parent;
  146.         
  147.     var list = parent.childNodes;
  148.     if (list == null) return null;
  149.     for (var i=0; i<list.length; i++) {
  150.         var child = list.item(i);
  151.         if(child.tagName == childTag)
  152.             return child;
  153.         
  154.         child = getDescendantNode(child, childTag);
  155.         if (child != null)
  156.             return child;
  157.     }
  158.     return null;
  159. }
  160.  
  161.  
  162. /**
  163.  * Returns the anchor of this click
  164.  * NOTE: MOZILLA BUG WITH A:focus and A:active styles
  165.  */
  166. function getAnchorNode(node) {
  167.   if (node == null) return null;
  168.    
  169.   if (node.nodeType == 3)  //"Node.TEXT_NODE") 
  170.     return node.parentNode;
  171.   else if (node.tagName == "A") 
  172.     return node;
  173.   else if (node.tagName == "IMG")
  174.       return getChildNode(node.parentNode, "A");
  175.   return null;
  176. }
  177.  
  178. /**
  179.  * Returns the plus/minus icon for this tree node
  180.  */
  181. function getPlusMinus(node)
  182. {
  183.     if (isPlusMinus(node))
  184.         return node;
  185.       else if (node.nodeType == 3)  //"Node.TEXT_NODE") 
  186.         return getChildNode(node.parentNode.parentNode, "IMG");
  187.     else if (node.tagName == "IMG")
  188.         return getChildNode(node.parentNode.parentNode, "IMG");
  189.       else if (node.tagName == "A") 
  190.         return getChildNode(node.parentNode, "IMG");
  191.  
  192.      return null;
  193. }
  194.  
  195.  
  196. /**
  197.  * Returns true when the node is the plus or minus icon
  198.  */
  199. function isPlusMinus(node)
  200. {
  201.     return (node.nodeType != 3 && node.tagName == "IMG" && (node.className == "expanded" || node.className == "collapsed"));
  202. }
  203.  
  204. /**
  205.  * Collapses a tree rooted at the specified element
  206.  */
  207. function collapse(node) {
  208.   node.className = "collapsed";
  209.   node.src = plus.src;
  210.   node.alt = altTopicClosed;
  211.   // set the UL as well
  212.   var ul = getChildNode(node.parentNode, "UL");
  213.   if (ul != null) ul.className = "collapsed";
  214. }
  215.  
  216. /**
  217.  * Expands a tree rooted at the specified element
  218.  */
  219. function expand(node) {
  220.       node.className = "expanded";
  221.       node.src = minus.src;
  222.     node.alt = altTopicOpen;
  223.       // set the UL as well
  224.       var ul = getChildNode(node.parentNode, "UL");
  225.       if (ul != null){
  226.           ul.className = "expanded";
  227.           if (ul.id.length > 0){
  228.               if (!frames.dynLoadFrame) {
  229.                   return;
  230.               }
  231.               var ix = window.location.href.indexOf('?');
  232.               if (ix < 0) {
  233.                   return;
  234.               }
  235.               var query = window.location.href.substr(ix);
  236.               frames.dynLoadFrame.location = "tocFragment.jsp" + query + "&path=" + ul.id;
  237.           }
  238.       }
  239. }
  240.  
  241. /**
  242.  * Expands the nodes from root to the specified node
  243.  */
  244. function expandPathTo(node, inclusive)
  245. {
  246.     // when the node is a link, get the plus/minus image
  247.     if (node.tagName == "A") 
  248.     {
  249.         var img = getChildNode(node.parentNode, "IMG")
  250.         if (img == null) return;
  251.         expandPathTo(img, inclusive);
  252.         return;
  253.     }
  254.     
  255.     if (inclusive && isCollapsed(node))
  256.         expand(node);
  257.         
  258.     var li = node.parentNode;
  259.     if (li == null) return;
  260.     var ul = li.parentNode;
  261.     if (ul == null) return;
  262.     li = ul.parentNode;
  263.     if (li == null) return;
  264.     var img = getChildNode(li, "IMG");
  265.     if (img == null) return;
  266.         
  267.     expandPathTo(img, true);
  268. }
  269.  
  270. /**
  271.  * Returns true when this is an expanded tree node
  272.  */
  273. function isExpanded(node) {
  274.   return node.className == "expanded";
  275. }
  276.  
  277. /**
  278.  * Returns true when this is a collapsed tree node
  279.  */
  280. function isCollapsed(node) {
  281.   return  node.className == "collapsed";
  282. }
  283.  
  284. /**
  285.  * Highlights link
  286.  */
  287. function highlightTopic(topic)
  288. {
  289.     if (isMozilla)
  290.         window.getSelection().removeAllRanges();
  291.  
  292.       var a = getAnchorNode(topic); 
  293.       if (a != null)
  294.       {
  295.             parent.parent.parent.setContentToolbarTitle(tocTitle);
  296.             if (oldActive) 
  297.                 oldActive.className = oldActiveClass;
  298.  
  299.           oldActive = a;
  300.           oldActiveClass = a.className;
  301.           a.className = "active";
  302.           // it looks like the onclick event is not handled in mozilla
  303.           // *** TO DO: handle failed synchronization, do not select in that case
  304.           if (isMozilla && a.onclick) 
  305.               a.onclick()
  306.           //if (isIE)
  307.           //    a.hideFocus = "true";
  308.       }
  309. }
  310.  
  311. /**
  312.  * Selects a topic in the tree: expand tree and highlight it
  313.  * returns true if success
  314.  */
  315. function selectTopic(topic)
  316. {
  317.     if (!topic)
  318.         return false;
  319.         
  320.     // remove the query, if any
  321.     var i = topic.indexOf('?');
  322.     if (i != -1)
  323.         topic = topic.substring(0, i);
  324.  
  325.     var links = document.getElementsByTagName("a");
  326.  
  327.     for (var i=0; i<links.length; i++)
  328.     {
  329.         if (topic == links[i].href)
  330.         {
  331.             expandPathTo(links[i], false);
  332.             highlightTopic(links[i]);
  333.             scrollIntoView(links[i]);
  334.             return true;
  335.         }
  336.     }
  337.     return false;
  338. }
  339.  
  340. /**
  341.  * Selects a topic in the tree: expand tree and highlight it
  342.  * returns true if success
  343.  */
  344. function selectTopicById(id)
  345. {
  346.     var topic = document.getElementById(id);
  347.     if (topic)
  348.     {
  349.         expandPathTo(topic, false);
  350.         highlightTopic(topic);
  351.         scrollIntoView(topic);
  352.         return true;
  353.     }
  354.     return false;
  355. }
  356.  
  357. /**
  358.  * Scrolls the page to show the specified element
  359.  */
  360. function scrollIntoView(node)
  361. {
  362.     var scroll = getVerticalScroll(node);
  363.     if (scroll != 0)
  364.         window.scrollBy(0, scroll);
  365. }
  366.  
  367. /**
  368.  * Scrolls the page to show the specified element
  369.  */
  370. function getVerticalScroll(node)
  371. {
  372.     var nodeTop = node.offsetTop;
  373.     var nodeBottom = nodeTop + node.offsetHeight;
  374.     var pageTop = 0;
  375.     var pageBottom = 0;
  376.     
  377.     if (isIE)
  378.     {
  379.         pageTop = document.body.scrollTop; 
  380.         pageBottom = pageTop + document.body.clientHeight;
  381.     
  382.     } 
  383.     else if (isMozilla)
  384.     {
  385.         pageTop = window.pageYOffset;
  386.         pageBottom = pageTop + window.innerHeight - node.offsetHeight;
  387.     }
  388.     
  389.     var scroll = 0;
  390.     if (nodeTop >= pageTop )
  391.     {
  392.         if (nodeBottom <= pageBottom)
  393.             scroll = 0; // already in view
  394.         else
  395.             scroll = nodeBottom - pageBottom;
  396.     }
  397.     else
  398.     {
  399.         scroll = nodeTop - pageTop;
  400.     }
  401.     
  402.     return scroll;
  403. }
  404.  
  405. /*
  406.  * Currently called on IE only
  407.  */
  408. function focusHandler(e)
  409. {
  410.     /*if (isMozilla)
  411.         return;
  412.     */
  413.         
  414.     try{
  415.         if (oldActive){
  416.             // only focus when the element is visible
  417.             var scroll = getVerticalScroll(oldActive);
  418.             if (scroll == 0)
  419.                 oldActive.focus();
  420.         }        
  421.     }
  422.     catch(e){}
  423. }
  424.  
  425.  
  426. /**
  427.  * display topic label in the status line on mouse over topic
  428.  */
  429. function mouseMoveHandler(e) {
  430.     var overNode = getTarget(e);
  431.      if (!overNode) return;
  432.       
  433.     overNode = getAnchorNode(overNode);
  434.       if (overNode == null){
  435.        window.status = "";
  436.        return;
  437.       }
  438.  
  439.     if (isMozilla)
  440.         e.cancelBubble = false;
  441.        
  442.     if (overNode.title == "") {
  443.         if (overNode.innerText)
  444.             overNode.title = overNode.innerText;
  445.         else if (overNode.text)
  446.             overNode.title = overNode.text;
  447.     }
  448.     window.status = overNode.title;
  449. }
  450.  
  451. /**
  452.  * handler for expanding / collapsing topic tree
  453.  */
  454. function mouseClickHandler(e) {
  455.  
  456.       var clickedNode = getTarget(e);
  457.  
  458.       if (isPlusMinus(clickedNode) )
  459.       {    
  460.         if (isCollapsed(clickedNode)) 
  461.                expand(clickedNode);
  462.           else if (isExpanded(clickedNode)) 
  463.                 collapse(clickedNode);
  464.       }
  465.       else
  466.       {
  467.           var plus_minus = getPlusMinus(clickedNode);
  468.           if (plus_minus != null)
  469.               highlightTopic(plus_minus);
  470.       }
  471.       
  472.       if (isMozilla)
  473.           e.cancelBubble = true;
  474.       else if (isIE)
  475.           window.event.cancelBubble = true;
  476. }
  477.  
  478. /**
  479.  * handler for expanding / collapsing topic tree
  480.  */
  481. function mouseDblClickHandler(e) {
  482.  
  483.       var clickedNode = getTarget(e);
  484.       if (!clickedNode) return;
  485.  
  486.       var plus_minus = getPlusMinus(clickedNode);
  487.       if (plus_minus != null)
  488.       {    
  489.         if (isCollapsed(plus_minus)) 
  490.                expand(plus_minus);
  491.           else if (isExpanded(plus_minus)) 
  492.                 collapse(plus_minus);
  493.                             
  494.           highlightTopic(plus_minus);
  495.       }
  496.   
  497.       if (isMozilla)
  498.           e.cancelBubble = true;
  499.       else if (isIE)
  500.           window.event.cancelBubble = true;
  501. }
  502.  
  503. /**
  504.  * Handler for key down (arrows)
  505.  */
  506. function keyDownHandler(e)
  507. {
  508.     var key;
  509.  
  510.     if (isIE) {
  511.         key = window.event.keyCode;
  512.     } else if (isMozilla) {
  513.         key = e.keyCode;
  514.     }
  515.         
  516.     if (key <37 || key > 40) 
  517.         return true;
  518.     
  519.     if (isMozilla)
  520.           e.cancelBubble = true;
  521.       else if (isIE)
  522.           window.event.cancelBubble = true;
  523.           
  524.       if (key == 39) { // Right arrow, expand
  525.         var clickedNode = getTarget(e);
  526.           if (!clickedNode) return;
  527.           if (isIE){
  528.             if(clickedNode.id!=null){
  529.                 if(clickedNode.id.charAt(0)=='b'){
  530.                     if(clickedNode.name!="opened"){
  531.                         loadTOC(clickedNode.name);
  532.                         return true;
  533.                     }
  534.                 }
  535.             }
  536.         }
  537.  
  538.           var plus_minus = getPlusMinus(clickedNode);
  539.           if (plus_minus != null)
  540.           {    
  541.             if (isCollapsed(plus_minus)) 
  542.                    expand(plus_minus);
  543.               
  544.               highlightTopic(plus_minus);
  545.               scrollIntoView(clickedNode);
  546.           }
  547.       } else if (key == 37) { // Left arrow,collapse
  548.         var clickedNode = getTarget(e);
  549.           if (!clickedNode) return;
  550.           
  551.           if(clickedNode.id!=null){
  552.               if(clickedNode.id.charAt(0)=='b'){
  553.                 if(clickedNode.name=="opened"){
  554.                     loadTOC(" ");
  555.                     return true;
  556.                 }
  557.                 else{     
  558.                     return true;
  559.                 }
  560.             }
  561.             
  562.         }
  563.  
  564.           var plus_minus = getPlusMinus(clickedNode);
  565.           if (plus_minus != null)
  566.           {    
  567.             if (isExpanded(plus_minus)) 
  568.                    collapse(plus_minus);
  569.               
  570.               highlightTopic(plus_minus);
  571.               scrollIntoView(clickedNode);
  572.           }
  573.       } else if (key == 40 ) { // down arrow
  574.           var clickedNode = getTarget(e);
  575.           if (!clickedNode) return;
  576.  
  577.         var next = getNextDown(clickedNode);
  578.         if (next)
  579.             next.focus();
  580.  
  581.       } else if (key == 38 ) { // up arrow
  582.           var clickedNode = getTarget(e);
  583.           if (!clickedNode) return;
  584.  
  585.         var next = getNextUp(clickedNode);
  586.         if (next)
  587.             next.focus();
  588.       }
  589.       
  590.                    
  591.       return true;
  592. }
  593.  
  594. if (isMozilla) {
  595.   document.addEventListener('click', mouseClickHandler, true);
  596.   document.addEventListener('dblclick', mouseDblClickHandler, true);
  597.   document.addEventListener('mousemove', mouseMoveHandler, true);
  598.   document.addEventListener('keydown', keyDownHandler, true);
  599. }
  600. else if (isIE){
  601.   document.onclick = mouseClickHandler;
  602.   document.ondblclick = mouseDblClickHandler;
  603.   document.onmousemove = mouseMoveHandler;
  604.   document.onkeydown = keyDownHandler;
  605.   //window.onfocus = focusHandler;
  606. }
  607.  
  608.