diff.ui.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. var iframeHeight = 0;
  2. var sidebarHeight = 0;
  3. var tabTemp;
  4. var diffAppose = $.cookie.get('renderSideBySide') == 'true';
  5. var distance = 0;
  6. /**
  7. * 左右切换关联信息。
  8. * Aarrow tabs area.
  9. *
  10. * @param string domID
  11. * @param number shift 1|-1
  12. * @param bool hideRightBtn
  13. * @access public
  14. * @return void
  15. */
  16. function arrowTabs(domID, shift, hideRightBtn)
  17. {
  18. if($('#' + domID).html() == '') return;
  19. var hasParent = $('#' + domID + ' .btn-left').length;
  20. var $leftBtn = hasParent ? $('#' + domID + ' .btn-left') : $('.btn-left');
  21. var $rightBtn = hasParent ? $('#' + domID + ' .btn-right') : $('.btn-right');
  22. $leftBtn.show();
  23. $rightBtn.show();
  24. if(hideRightBtn) $rightBtn.hide();
  25. var tabItemWidth = 0;
  26. if($('#' + domID + ' > .nav-tabs')[0]) tabItemWidth = $('#' + domID + ' > .nav-tabs')[0].clientWidth;
  27. var tabsWidth = $('#' + domID)[0].clientWidth;
  28. if($('#' + domID + ' .close-bugs').length) tabsWidth = tabsWidth * 0.7;
  29. if(tabItemWidth <= tabsWidth)
  30. {
  31. $leftBtn.hide();
  32. $rightBtn.hide();
  33. if($('#' + domID + ' > .nav-tabs').length) $('#' + domID + ' > .nav-tabs')[0].style.transform = 'translateX(0px)';
  34. return;
  35. }
  36. distance += tabsWidth * shift * 0.2;
  37. if(distance > 0) distance = 0;
  38. if(distance == 0)
  39. {
  40. $leftBtn.hide();
  41. }
  42. if((tabItemWidth + distance) <= tabsWidth * 0.75)
  43. {
  44. $rightBtn.hide();
  45. return arrowTabs(domID, 1, true);
  46. }
  47. if(domID == 'monacoTabs' && distance < -60) distance = distance + 60;
  48. $('#' + domID + ' > .nav-tabs')[0].style.transform = 'translateX('+ distance +'px)';
  49. }
  50. /**
  51. * 关闭关联信息tab。
  52. * Close commit relations.
  53. *
  54. * @access public
  55. * @return void
  56. */
  57. function closeRelation()
  58. {
  59. $('#relationTabs ul li').remove();
  60. $('#relationTabs .tab-content .tab-pane').remove();
  61. $('.history').html('');
  62. $('#log').data('line', 0);
  63. $('#log').hide();
  64. $('#codeContainer').css('height', codeHeight);
  65. $('#related').css('height', 0);
  66. };
  67. /**
  68. * 获取tabs内容高度。
  69. * Get tab-content height.
  70. *
  71. * @access public
  72. * @return void
  73. */
  74. function getIframeHeight()
  75. {
  76. if(iframeHeight) return iframeHeight;
  77. var windowHeight = $(window).height();
  78. var headerHeight = parseInt($('#header').height());
  79. var mainNavbar = parseInt($('#navbar').height());
  80. var tabsbar = parseInt($('.nav-tabs').height());
  81. var mainMenuHeight = parseInt($('#mainContent').css('padding-top')) + parseInt($('#mainContent').css('padding-bottom'));
  82. var detailHeaderHeight = parseInt($('.detail-header').height());
  83. var mrMenuHeight = parseInt($('#mrMenu').height());
  84. var appTabsHeight = parseInt($('#appTabs').height());
  85. var appsBarHeight = parseInt($('#appsBar').height());
  86. appsBarHeight = appsBarHeight ? appsBarHeight : 0;
  87. appTabsHeight = appTabsHeight ? appTabsHeight : 0;
  88. mainMenuHeight = mainMenuHeight ? mainMenuHeight : 0;
  89. mainNavbar = mainNavbar ? mainNavbar : 0;
  90. iframeHeight = windowHeight - headerHeight - appsBarHeight - appTabsHeight - mainMenuHeight - mainNavbar - tabsbar - detailHeaderHeight - mrMenuHeight - 28;
  91. return iframeHeight;
  92. }
  93. /**
  94. * 获取左侧边栏高度。
  95. * Get sidebar height.
  96. *
  97. * @access public
  98. * @return void
  99. */
  100. function getSidebarHeight()
  101. {
  102. if(sidebarHeight) return sidebarHeight;
  103. var windowHeight = $(window).height();
  104. var headerHeight = parseInt($('#header').height());
  105. var mainNavbar = parseInt($('#navbar').height());
  106. var mainMenuHeight = parseInt($('#mainContent').css('padding-top')) + parseInt($('#mainContent').css('padding-bottom'));
  107. var appTabsHeight = parseInt($('#appTabs').height());
  108. var appsBarHeight = parseInt($('#appsBar').height());
  109. var detailHeaderHeight = parseInt($('.detail-header').height());
  110. var mrMenuHeight = parseInt($('#mrMenu').height());
  111. appsBarHeight = appsBarHeight ? appsBarHeight : 0;
  112. appTabsHeight = appTabsHeight ? appTabsHeight : 0;
  113. mainMenuHeight = mainMenuHeight ? mainMenuHeight : 0;
  114. mainNavbar = mainNavbar ? mainNavbar : 0;
  115. sidebarHeight = windowHeight - headerHeight - appsBarHeight - appTabsHeight - mainMenuHeight - mainNavbar - detailHeaderHeight - mrMenuHeight - 20;
  116. return sidebarHeight;
  117. }
  118. /**
  119. * 查找选中元素所有的父元素及选中元素的id。
  120. * Find parent nodes and item id of selected tree item.
  121. *
  122. * @access public
  123. * @return string
  124. */
  125. function findItemInTreeItems(list, key, level) {
  126. for (const item of list) {
  127. if(level === 0)
  128. {
  129. parentTree = [item.key];
  130. }
  131. if (item.id === key) return item;
  132. if (item.children && item.children.length > 0)
  133. {
  134. const findedItem = findItemInTreeItems(item.children, key);
  135. if (findedItem)
  136. {
  137. parentTree.push(item.key);
  138. return findedItem;
  139. }
  140. }
  141. }
  142. }
  143. /**
  144. * 展开树状结构。
  145. * Expand tree node.
  146. *
  147. * @access public
  148. * @return void
  149. */
  150. function expandTree()
  151. {
  152. const treeObj = $('#monacoTree').parent().data('zui.Tree');
  153. if(treeObj == undefined || treeObj.$ == undefined) return;
  154. for (const key of parentTree) treeObj.$.expand(key);
  155. }
  156. /* Close tab. */
  157. window.closeTab = function(obj)
  158. {
  159. var eleId = $(obj).parent().attr('href');
  160. var tabsEle = $(obj).parent().parent().parent();
  161. var isActive = $(obj).parent().hasClass('active');
  162. $(obj).parent().parent().remove();
  163. $(eleId).remove();
  164. $('#' + eleId.substring(5)).parent().removeClass('selected');
  165. if(isActive) tabsEle.children().last().find('a').trigger('click');
  166. if(!tabsEle.children().length) $('.monaco-dropmenu').addClass('hidden');
  167. const fileKey = eleId.substring(5).replace(/-/g, '=');
  168. $('li[z-key="' + fileKey + '"] .listitem').removeClass('selected');
  169. }
  170. window.afterPageUpdate = function()
  171. {
  172. setTimeout(function()
  173. {
  174. var fileAsId = file.replace(/=/g, '-');
  175. /* Resize moaco height. */
  176. $('#monacoTree').css('height', getSidebarHeight() - 8 + 'px');
  177. /* Init tab template. */
  178. if(!tabTemp) tabTemp = $('#monacoTabs ul li').first().clone();
  179. /* Load default tab content. */
  180. var height = getIframeHeight();
  181. $.cookie.set('repoCodePath', file, {expires:config.cookieLife, path:config.webRoot});
  182. $('#tab-' + fileAsId).html("<iframe class='repo-iframe' src='" + $.createLink('repo', 'ajaxGetDiffEditorContent', urlParams.replace('%s', '')) + "' width='100%' height='" + height + "' scrolling='no'></iframe>")
  183. /* Select default tree item. */
  184. const currentElement = findItemInTreeItems(tree, fileAsId, 0);
  185. if(currentElement != undefined) $('#' + currentElement.id).parent().addClass('selected');
  186. expandTree();
  187. $('.btn-left').on('click', function() {arrowTabs('monacoTabs', 1);});
  188. $('.btn-right').on('click', function() {arrowTabs('monacoTabs', -2);});
  189. }, 200);
  190. };
  191. /**
  192. * 点击左侧菜单打开详情tab。
  193. * Open new tab when click tree item.
  194. *
  195. * @access public
  196. * @return void
  197. */
  198. window.treeClick = function(info)
  199. {
  200. if (info.item.items && info.item.items.length > 0) return;
  201. $('li[z-key="' + info.item.id + '"] .listitem').addClass('selected');
  202. openTab(info.item.id, info.item.text);
  203. arrowTabs('monacoTabs', -2);
  204. }
  205. /**
  206. * Change code encoding.
  207. *
  208. * @param string encoding
  209. * @access public
  210. * @return void
  211. */
  212. function changeEncoding(encoding)
  213. {
  214. $('#encoding').val(encoding);
  215. $('#encoding').parents('form').submit();
  216. }
  217. /**
  218. * Html code decode.
  219. *
  220. * @param string str
  221. * @access public
  222. * @return string
  223. */
  224. function htmlspecialchars_decode(str){
  225. str = str.replace(/&amp;/g, '&');
  226. str = str.replace(/&lt;/g, '<');
  227. str = str.replace(/&gt;/g, '>');
  228. str = str.replace(/&quot;/g, "''");
  229. str = str.replace(/&#039;/g, "'");
  230. return str;
  231. }
  232. /**
  233. * Get diffs by file name.
  234. *
  235. * @param string fileName
  236. * @access public
  237. * @return object
  238. */
  239. window.getDiffs = function(fileName)
  240. {
  241. if(fileName.indexOf('./') === 0) fileName = fileName.substring(2);
  242. var result = {
  243. 'code': {'new': '', 'old': ''},
  244. 'line': {'new': [], 'old': []}
  245. };
  246. const newContent = [];
  247. const oldContent = [];
  248. $.each(diffs, function(i, diff)
  249. {
  250. if(diff.fileName == fileName)
  251. {
  252. if(!diff.contents || typeof diff.contents[0].lines != 'object') return result;
  253. $.each(diff.contents, function(k, content)
  254. {
  255. var lines = content.lines;
  256. $.each(lines, function(l, code)
  257. {
  258. if(code.type == 'all' || code.type == 'new')
  259. {
  260. newContent.push(htmlspecialchars_decode(code.line.substring(1)));
  261. result.line.new.push(parseInt(code.newlc));
  262. }
  263. if(code.type == 'all' || code.type == 'old')
  264. {
  265. oldContent.push(htmlspecialchars_decode(code.line.substring(1)));
  266. result.line.old.push(parseInt(code.oldlc));
  267. }
  268. })
  269. })
  270. result.code.new = newContent.join('\n');
  271. result.code.old = oldContent.join('\n');
  272. return result;
  273. }
  274. });
  275. return result;
  276. }
  277. /**
  278. * 打开新tab。
  279. * Open new tab.
  280. *
  281. * @access public
  282. * @return void
  283. */
  284. function openTab(entry, name)
  285. {
  286. var eleId = 'tab-' + entry.replace(/=/g, '-');
  287. var element = document.getElementById(eleId);
  288. if (element)
  289. {
  290. $("a[href='" + '#' + eleId + "']").trigger('click');
  291. return;
  292. }
  293. var newTab = tabTemp.clone();
  294. newTab.find('a').attr('href', '#' + eleId);
  295. newTab.find('span').text(name);
  296. $('#monacoTabs .nav-tabs').append(newTab);
  297. var height = getIframeHeight();
  298. $.cookie.set('repoCodePath', entry, {expires:config.cookieLife, path:config.webRoot});
  299. $('#monacoTabs .tab-content').append("<div id='" + eleId + "' class='tab-pane active in'><iframe class='repo-iframe' src='" + $.createLink('repo', 'ajaxGetDiffEditorContent', urlParams.replace('%s', '')) + "' width='100%' height='" + height + "' scrolling='no'></iframe></div>")
  300. if($('.monaco-dropmenu').attr('class').indexOf('hidden')) $('.monaco-dropmenu').removeClass('hidden');
  301. setTimeout(() => {
  302. $("a[href='" + '#' + eleId + "']").trigger('click');
  303. updateEditorInline('#' + eleId);
  304. }, 100);
  305. }
  306. window.updateEditorInline = function(eleId)
  307. {
  308. $.cookie.set('renderSideBySide', diffAppose, {expires:config.cookieLife, path:config.webRoot});
  309. if(typeof $(eleId + ' iframe')[0].contentWindow.updateEditorInline == 'function')
  310. {
  311. $(eleId + ' iframe')[0].contentWindow.updateEditorInline(diffAppose);
  312. }
  313. }
  314. window.changeDiffType = function(obj)
  315. {
  316. const eleId = $(obj).attr('href');
  317. if(eleId) $(eleId + ' iframe')[0].contentWindow.updateEditorInline(diffAppose);
  318. }
  319. $(document).ready(function()
  320. {
  321. if(diffAppose)
  322. {
  323. $('.dropdown-menu #inline').show();
  324. $('.dropdown-menu #appose').hide();
  325. }
  326. else
  327. {
  328. $('.dropdown-menu #appose').show();
  329. $('.dropdown-menu #inline').hide();
  330. }
  331. $('.btn-left').on('click', function() {arrowTabs('monacoTabs', 1);});
  332. $('.btn-right').on('click', function() {arrowTabs('monacoTabs', -2);});
  333. });
  334. window.inlineAppose = function()
  335. {
  336. $('.inline-appose').hide();
  337. diffAppose = !diffAppose;
  338. if(diffAppose)
  339. {
  340. $('.dropdown-menu #inline').show();
  341. }
  342. else
  343. {
  344. $('.dropdown-menu #appose').show();
  345. }
  346. var tabID = $('#monacoTabs .nav-item .active').attr('href');
  347. updateEditorInline(tabID);
  348. return;
  349. }
  350. /**
  351. * 在当前页面用modal加载链接。
  352. * Load link object page.
  353. *
  354. * @param string $link
  355. * @access public
  356. * @return void
  357. */
  358. window.loadLinkPage = function(link)
  359. {
  360. $('#linkObject').attr('href', link);
  361. $('#linkObject').trigger('click');
  362. }