You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

394 lines
9.8 KiB

  1. // Copyright © 2009-2011, Rob Chandler.
  2. // Please don't use this file without purchasing FAR. http://helpware.net/FAR/
  3. // This effectively licenses you to use my code. This code (before modification) was
  4. // first written by Jean-Claude Manoli.
  5. // Changes
  6. // RWC: 2005-04-01 - Fix image pre-load section. Last line had typo causing some images not to load
  7. // RWC: 2005-05-21 - Some work fixing TOC Sync
  8. // RWC: 2008-01-30 - Change resizeTree() to be compatible with non-MS browsers
  9. // RWC: 2009-06-10 - All files now saved in UTF-8 file format.
  10. // RWC: 2009-09-26 - Allow Opera browser to scroll the tree when syncing TOC.
  11. // RWC: 2011-09-10 - Fix Sync for \\server\ UNC paths.
  12. // RWC: 2011-09-11 - Fix Sync for CJK paths.
  13. // RWC: 2012-09-04 - Added selectNext(fwd) & findLinkNode()
  14. /* Original Copyright © 2002 Jean-Claude Manoli [jc@manoli.net]
  15. *
  16. * This software is provided 'as-is', without any express or implied warranty.
  17. * In no event will the author(s) be held liable for any damages arising from
  18. * the use of this software.
  19. *
  20. * Permission is granted to anyone to use this software for any purpose,
  21. * including commercial applications, and to alter it and redistribute it
  22. * freely, subject to the following restrictions:
  23. *
  24. * 1. The origin of this software must not be misrepresented; you must not
  25. * claim that you wrote the original software. If you use this software
  26. * in a product, an acknowledgment in the product documentation would be
  27. * appreciated but is not required.
  28. *
  29. * 2. Altered source versions must be plainly marked as such, and must not
  30. * be misrepresented as being the original software.
  31. *
  32. * 3. This notice may not be removed or altered from any source distribution.
  33. */
  34. var treeSelected = null; //last treeNode clicked
  35. //pre-load tree nodes images
  36. var imgPlus = new Image();
  37. imgPlus.src="treenodeplus.gif";
  38. var imgMinus = new Image();
  39. imgMinus.src="treenodeminus.gif";
  40. var imgDot = new Image();
  41. imgDot.src="treenodedot.gif"; //rwc - fixed. Was... imgPlus.src="treenodedot.gif";
  42. function findNode(el)
  43. {
  44. // Takes element and determines if it is a treeNode.
  45. // If not, seeks a treeNode in its parents.
  46. while (el != null)
  47. {
  48. if (el.className == "treeNode")
  49. {
  50. break;
  51. }
  52. else
  53. {
  54. el = el.parentNode;
  55. }
  56. }
  57. return el;
  58. }
  59. function clickAnchor(el)
  60. {
  61. // handles click on a TOC link
  62. //
  63. expandNode(el.parentNode);
  64. selectNode(el.parentNode);
  65. el.blur();
  66. }
  67. function findLinkNode(node)
  68. {
  69. if (node == null || node == undefined)
  70. node = treeSelected;
  71. node = findNode(node);
  72. if (node == null)
  73. return null;
  74. var anchors = node.getElementsByTagName('A');
  75. if (anchors.length > 0)
  76. return anchors[0];
  77. return null;
  78. }
  79. function selectNext(fwd)
  80. {
  81. // Sync forward or back from current selected. Return href of newly selected node.
  82. //
  83. var el;
  84. var aref = "";
  85. var node = document.getElementById('treeRoot');
  86. var anchors = node.getElementsByTagName('A');
  87. //nothing selected? - Select the first node
  88. if (treeSelected == null)
  89. {
  90. if (anchors.length > 0 && anchors[0] != null && anchors[0] != undefined)
  91. {
  92. el = anchors[0];
  93. selectAndShowNode(el);
  94. aref = el.getAttribute('href');
  95. }
  96. }
  97. else //select the next node
  98. {
  99. for(var i = 0; i < anchors.length; i++)
  100. {
  101. el = anchors[i];
  102. if (findNode(el) == treeSelected) // find the current selected node & walk fwd or back
  103. {
  104. if (fwd) el = anchors[i+1];
  105. else el = anchors[i-1];
  106. if (el != null && el != undefined)
  107. {
  108. selectAndShowNode(el);
  109. aref = el.getAttribute('href');
  110. }
  111. break;
  112. }
  113. }
  114. }
  115. return aref;
  116. }
  117. function selectNode(el)
  118. {
  119. // Un-selects currently selected node, if any, and selects the specified node
  120. //
  121. if (treeSelected != null)
  122. {
  123. setSubNodeClass(treeSelected, 'A', 'treeUnselected');
  124. }
  125. setSubNodeClass(el, 'A', 'treeSelected');
  126. treeSelected = el;
  127. }
  128. function setSubNodeClass(el, nodeName, className)
  129. {
  130. // Sets the specified class name on el's first child that is a nodeName element
  131. //
  132. var child;
  133. for (var i=0; i < el.childNodes.length; i++)
  134. {
  135. child = el.childNodes[i];
  136. if (child.nodeName == nodeName)
  137. {
  138. child.className = className;
  139. break;
  140. }
  141. }
  142. }
  143. function expandCollapse(el)
  144. {
  145. // If source treeNode has child nodes, expand or collapse view of treeNode
  146. //
  147. if (el == null)
  148. return; //Do nothing if it isn't a treeNode
  149. var child;
  150. var imgEl;
  151. for(var i=0; i < el.childNodes.length; i++)
  152. {
  153. child = el.childNodes[i];
  154. if (child.src)
  155. {
  156. imgEl = child;
  157. }
  158. else if (child.className == "treeSubnodesHidden")
  159. {
  160. child.className = "treeSubnodes";
  161. imgEl.src = "treenodeminus.gif";
  162. break;
  163. }
  164. else if (child.className == "treeSubnodes")
  165. {
  166. child.className = "treeSubnodesHidden";
  167. imgEl.src = "treenodeplus.gif";
  168. break;
  169. }
  170. }
  171. }
  172. function expandNode(el)
  173. {
  174. // If source treeNode has child nodes, expand it
  175. //
  176. var child;
  177. var imgEl;
  178. for(var i=0; i < el.childNodes.length; i++)
  179. {
  180. child = el.childNodes[i];
  181. if (child.src)
  182. {
  183. imgEl = child;
  184. }
  185. if (child.className == "treeSubnodesHidden")
  186. {
  187. child.className = "treeSubnodes";
  188. imgEl.src = "treenodeminus.gif";
  189. break;
  190. }
  191. }
  192. }
  193. function GetUnixPath(url)
  194. {
  195. var path = url.replace(/\\/g, '/'); // DOS to Unix slash
  196. path = path.replace(/\/\/\//, "//"); // Force 2 slashes xxx://xxx
  197. path = path.replace(/\/\/\//, "//");
  198. path = path.replace(/\/\/\//, "//");
  199. path = path.replace(/\/\/\//, "//");
  200. return path;
  201. }
  202. function syncTree(href)
  203. {
  204. // Selects and scrolls into view the node that references the specified URL
  205. //
  206. //RWC 2005-05-21 - This is the real URL base of the TOC
  207. var gbase = GetUnixPath(location.href);
  208. gbase = decodeURI(gbase);
  209. gbase = gbase.substr(0, gbase.lastIndexOf('/') + 1); //trim off file name. Leave trailing /
  210. var loc = new String();
  211. loc = GetUnixPath(href);
  212. loc = encodeURI(loc); //encode as valid URI
  213. //RWC 2005-05-21 - properly Scrub URL of encoding
  214. loc = decodeURI(loc); //Converts %2520 -> %20 (under FireFox)
  215. loc = decodeURI(loc); //Converts %20 = ' '
  216. var tocEl = findHref(document.getElementById('treeRoot'), loc, gbase);
  217. if (tocEl != null)
  218. {
  219. selectAndShowNode(tocEl);
  220. }
  221. }
  222. function findHref(node, href, base)
  223. {
  224. // find the <a> element with the specified href value
  225. //
  226. //RWC 24/3/2006: Consider any bookmark on the URL to test
  227. var href_BaseURL = '';
  228. var iBookmark = href.indexOf('#');
  229. if (iBookmark > 0)
  230. href_BaseURL = href.substr(0, iBookmark);
  231. var el;
  232. var anchors = node.getElementsByTagName('A');
  233. for (var i = 0; i < anchors.length; i++)
  234. {
  235. el = anchors[i];
  236. var aref = new String();
  237. aref = el.getAttribute('href');
  238. if ((aref.substring(0, 7) != 'http://')
  239. && (aref.substring(0, 8) != 'https://')
  240. && (aref.substring(0, 7) != 'file://'))
  241. {
  242. aref = base + aref;
  243. }
  244. aref = GetUnixPath(decodeURI(aref));
  245. //if (i < 5)
  246. // alert('aref=' + aref + ', href=' + href + ', base=' + base);
  247. //RWC: If href has #bookmark and aref does not then compare without bookmarks
  248. if ((href_BaseURL.length > 0) && (aref.indexOf('#') < 0))
  249. if (aref == href_BaseURL)
  250. return el;
  251. if (aref == href)
  252. {
  253. return el;
  254. }
  255. }
  256. return null;
  257. }
  258. function selectAndShowNode(node)
  259. {
  260. // Selects and scrolls into view the specified node
  261. //
  262. var el = findNode(node);
  263. if (el != null)
  264. {
  265. selectNode(el);
  266. do
  267. {
  268. expandNode(el);
  269. el = findNode(el.parentNode);
  270. } while ((el != null))
  271. //vertical scroll element into view
  272. var windowTop;
  273. var windowBottom;
  274. var treeDiv = document.getElementById('tree');
  275. var ua = window.navigator.userAgent.toLowerCase();
  276. if ((i = ua.indexOf('msie')) != -1)
  277. {
  278. windowTop = node.offsetTop - treeDiv.scrollTop;
  279. windowBottom = treeDiv.clientHeight - windowTop - node.offsetHeight;
  280. }
  281. else if (ua.indexOf('gecko') != -1)
  282. {
  283. windowTop = node.offsetTop - treeDiv.offsetTop - treeDiv.scrollTop;
  284. windowBottom = treeDiv.clientHeight - windowTop - node.offsetHeight;
  285. }
  286. else if (ua.indexOf('opera') != -1)
  287. {
  288. windowTop = node.offsetTop - treeDiv.offsetTop - treeDiv.scrollTop;
  289. windowBottom = treeDiv.clientHeight - windowTop - node.offsetHeight;
  290. }
  291. else
  292. {
  293. return;
  294. }
  295. if (windowTop < 0)
  296. {
  297. treeDiv.scrollTop += windowTop - 18;
  298. return;
  299. }
  300. if (windowBottom < 0)
  301. {
  302. treeDiv.scrollTop -= windowBottom - 18;
  303. return;
  304. }
  305. }
  306. }
  307. function GetFrameWidth()
  308. {
  309. var x = 300;
  310. if (self.innerHeight) // all except Explorer
  311. x = self.innerWidth;
  312. else if (document.documentElement && document.documentElement.clientHeight) // Explorer 6 Strict Mode
  313. x = document.documentElement.clientWidth;
  314. else if (document.body) // other Explorers
  315. x = document.body.clientWidth;
  316. return(x);
  317. }
  318. function GetFrameHeight()
  319. {
  320. var y = 400;
  321. if (self.innerHeight) // all except Explorer
  322. y = self.innerHeight;
  323. else if (document.documentElement && document.documentElement.clientWidth) // Explorer 6 Strict Mode
  324. y = document.documentElement.clientHeight;
  325. else if (document.body) // other Explorers
  326. y = document.body.clientHeight;
  327. return(y);
  328. }
  329. function resizeTree()
  330. {
  331. var treeDiv = document.getElementById("tree");
  332. var DivFooter = document.getElementById("DivFooter");
  333. var xTop = treeDiv.offsetTop;
  334. if ((DivFooter != null) && (DivFooter != undefined))
  335. xTop = xTop + DivFooter.offsetHeight;
  336. treeDiv.style.width = GetFrameWidth();
  337. var HH = GetFrameHeight();
  338. if (HH - xTop > 0)
  339. treeDiv.style.height = HH - xTop;
  340. }
  341. // old original func
  342. //function resizeTree()
  343. //{
  344. // var treeDiv = document.getElementById('tree');
  345. // //treeDiv.setAttribute('style', 'width: ' + document.body.offsetWidth + 'px; height: ' + (document.body.offsetHeight - 27) + 'px;');
  346. // treeDiv.style.width = document.documentElement.offsetWidth;
  347. // treeDiv.style.height = document.documentElement.offsetHeight - 27;
  348. //}