PageRenderTime 29ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/nav-div.js

http://github.com/yinwang0/ydiff
JavaScript | 282 lines | 192 code | 60 blank | 30 comment | 40 complexity | b4b18eb7e7f240f2ec3d87efe340a267 MD5 | raw file
Possible License(s): GPL-3.0
  1. // ydiff - a language-aware tool for comparing programs
  2. // Copyright (C) 2011 Yin Wang (yinwang0@gmail.com)
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. // You should have received a copy of the GNU General Public License
  12. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. // convenience function for document.getElementById().
  14. window['$']=function(a){return document.getElementById(a)};
  15. /////////////////////// debug flag ////////////////////////
  16. var debug = false;
  17. /////////////////////// adjustable parameters //////////////////
  18. var minStep = 10;
  19. var nSteps = 30;
  20. var stepInterval = 10;
  21. var blockRange = 5; // how far consider one page blocked
  22. var nodeHLColor = 'yellow';
  23. var lineHLColor = '#FFFF66';
  24. var lineBlockedColor = '#E9AB17';
  25. var bgColor = '';
  26. var bodyBlockedColor = '#FAF0E6';
  27. ///////////////////////// globals ////////////////////////
  28. var eventCount = { 'left' : 0, 'right' : 0};
  29. var moving = false;
  30. var matchId1 = 'leftstart';
  31. var matchId2 = 'rightstart';
  32. var matchLineId1 = -1;
  33. var matchLineId2 = -1;
  34. var cTimeout;
  35. ///////////////////////// utilities ///////////////////////
  36. // No Math.sign() in JS?
  37. function sign(x) {
  38. if (x > 0) {
  39. return 1;
  40. } else if (x < 0) {
  41. return -1;
  42. } else {
  43. return 0;
  44. }
  45. }
  46. function log(msg) {
  47. if (debug) {
  48. console.log(msg);
  49. }
  50. }
  51. function elementPosition(id) {
  52. obj = $(id);
  53. var curleft = 0, curtop = 0;
  54. if (obj && obj.offsetParent) {
  55. curleft = obj.offsetLeft;
  56. curtop = obj.offsetTop;
  57. while (obj = obj.offsetParent) {
  58. curleft += obj.offsetLeft;
  59. curtop += obj.offsetTop;
  60. }
  61. }
  62. return { x: curleft, y: curtop };
  63. }
  64. /*
  65. * Scroll the window to relative position, detecting blocking positions.
  66. */
  67. function scrollWithBlockCheck(container, distX, distY) {
  68. var oldTop = container.scrollTop;
  69. var oldLeft = container.scrollLeft;
  70. container.scrollTop += distY; // the ONLY place for actual scrolling
  71. container.scrollLeft += distX;
  72. var actualX = container.scrollLeft - oldLeft;
  73. var actualY = container.scrollTop - oldTop;
  74. log("distY=" + distY + ", actualY=" + actualY);
  75. log("distX=" + distX + ", actualX=" + actualX);
  76. // extra leewaw here because Chrome scrolling is horribly inacurate
  77. if ((Math.abs(distX) > blockRange && actualX === 0)
  78. || Math.abs(distY) > blockRange && actualY === 0) {
  79. log("blocked");
  80. container.style.backgroundColor = bodyBlockedColor;
  81. return true;
  82. } else {
  83. eventCount[container.id] += 1;
  84. container.style.backgroundColor = bgColor;
  85. return false;
  86. }
  87. }
  88. function getContainer(elm) {
  89. while (elm && elm.tagName !== 'DIV') {
  90. elm = elm.parentElement || elm.parentNode;
  91. }
  92. return elm;
  93. }
  94. /*
  95. * timed animation function for scrolling the current window
  96. */
  97. function matchWindow(linkId, targetId, n)
  98. {
  99. moving = true;
  100. var link = $(linkId);
  101. var target = $(targetId);
  102. var linkContainer = getContainer(link);
  103. var targetContainer = getContainer(target);
  104. var linkPos = elementPosition(linkId).y - linkContainer.scrollTop;
  105. var targetPos = elementPosition(targetId).y - targetContainer.scrollTop;
  106. var distY = targetPos - linkPos;
  107. var distX = linkContainer.scrollLeft - targetContainer.scrollLeft;
  108. log("matching window... " + n + " distY=" + distY + " distX=" + distX);
  109. if (distY === 0 && distX === 0) {
  110. clearTimeout(cTimeout);
  111. moving = false;
  112. } else if (n <= 1) {
  113. scrollWithBlockCheck(targetContainer, distX, distY);
  114. moving = false;
  115. } else {
  116. var stepSize = Math.floor(Math.abs(distY) / n);
  117. actualMinStep = Math.min(minStep, Math.abs(distY));
  118. if (Math.abs(stepSize) < minStep) {
  119. var step = actualMinStep * sign(distY);
  120. } else {
  121. var step = stepSize * sign(distY);
  122. }
  123. var blocked = scrollWithBlockCheck(targetContainer, distX, step);
  124. var rest = Math.floor(distY / step) - 1;
  125. log("blocked?" + blocked + ", rest steps=" + rest);
  126. if (!blocked) {
  127. cTimeout = setTimeout(function () {
  128. return matchWindow(linkId, targetId, rest);
  129. }, stepInterval);
  130. } else {
  131. clearTimeout(cTimeout);
  132. moving = false;
  133. }
  134. }
  135. }
  136. ////////////////////////// highlighting /////////////////////////////
  137. var highlighted = []
  138. function putHighlight(id, color) {
  139. var elm = $(id);
  140. if (elm !== null) {
  141. elm.style.backgroundColor = color;
  142. if (color !== bgColor) {
  143. highlighted.push(id);
  144. }
  145. }
  146. }
  147. function clearHighlight() {
  148. for (i = 0; i < highlighted.length; i += 1) {
  149. putHighlight(highlighted[i], bgColor);
  150. }
  151. highlighted = [];
  152. }
  153. /*
  154. * Highlight the link, target nodes and their lines,
  155. * then start animation to move the other window to match.
  156. */
  157. function highlight(me, linkId, targetId, linkLineId, targetLineId, doMatch)
  158. {
  159. if (me.id === 'left') {
  160. matchId1 = linkId;
  161. matchId2 = targetId;
  162. } else {
  163. matchId1 = targetId;
  164. matchId2 = linkId;
  165. }
  166. clearHighlight();
  167. putHighlight(linkId, nodeHLColor);
  168. putHighlight(targetId, nodeHLColor);
  169. putHighlight(linkLineId, lineHLColor);
  170. putHighlight(targetLineId, lineHLColor);
  171. if (doMatch) {
  172. matchWindow(linkId, targetId, nSteps);
  173. }
  174. }
  175. function instantMoveOtherWindow (me) {
  176. log("me=" + me.id + ", eventcount=" + eventCount[me.id]);
  177. log("matchId1=" + matchId1 + ", matchId2=" + matchId2);
  178. me.style.backgroundColor = bgColor;
  179. if (!moving && eventCount[me.id] === 0) {
  180. if (me.id === 'left') {
  181. matchWindow(matchId1, matchId2, 1);
  182. } else {
  183. matchWindow(matchId2, matchId1, 1);
  184. }
  185. }
  186. if (eventCount[me.id] > 0) {
  187. eventCount[me.id] -= 1;
  188. }
  189. }
  190. function getTarget(x){
  191. x = x || window.event;
  192. return x.target || x.srcElement;
  193. }
  194. window.onload =
  195. function (e) {
  196. var tags = document.getElementsByTagName("A")
  197. for (var i = 0; i < tags.length; i++) {
  198. tags[i].onmouseover =
  199. function (e) {
  200. var t = getTarget(e)
  201. var lid = t.id
  202. var tid = t.getAttribute('tid')
  203. var container = getContainer(t)
  204. highlight(container, lid, tid, 'ignore', 'ignore', false)
  205. }
  206. tags[i].onclick =
  207. function (e) {
  208. var t = getTarget(e)
  209. var lid = t.id
  210. var tid = t.getAttribute('tid')
  211. var container = getContainer(t)
  212. highlight(container, lid, tid, 'ignore', 'ignore', true)
  213. }
  214. }
  215. tags = document.getElementsByTagName("DIV")
  216. for (var i = 0; i < tags.length; i++) {
  217. tags[i].onscroll =
  218. function (e) {
  219. instantMoveOtherWindow(getTarget(e))
  220. }
  221. }
  222. }