diff --git a/README.md b/README.md index 550b4bd..bbbf15d 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,18 @@ Chrome extension to show a code tree on GitLab :) ![](https://ws2.sinaimg.cn/large/006tNc79gy1fhpc4wcad7g30z10hzaqs.gif) + +## Change Log + - v1.2 + - add css loading + - add options setting + - search file + - load entire tree at once + - v1.1 + - basic function + - v1.0 + - initial version + ## More - Email:[linsage@live.com](mailto:linsage@live.com) diff --git a/css/main.css b/css/main.css index 2d5e661..9b552cd 100755 --- a/css/main.css +++ b/css/main.css @@ -293,7 +293,6 @@ } .ztree li span.button.ico_close { - margin-right: 2px; margin-right: 2px; background-image: none; vertical-align: top; @@ -358,9 +357,21 @@ background-position: -168px 0; } +.ztree li span.button.ico_loading:before { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + content: "\f110"; + padding-top: 4px; + padding-left: 4px; +} + .ztree li span.button.ico_loading { margin-right: 2px; - background: url(data:image/gif;base64,R0lGODlhEAAQAKIGAMLY8YSx5HOm4Mjc88/g9Ofw+v///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAGACwAAAAAEAAQAAADMGi6RbUwGjKIXCAA016PgRBElAVlG/RdLOO0X9nK61W39qvqiwz5Ls/rRqrggsdkAgAh+QQFCgAGACwCAAAABwAFAAADD2hqELAmiFBIYY4MAutdCQAh+QQFCgAGACwGAAAABwAFAAADD1hU1kaDOKMYCGAGEeYFCQAh+QQFCgAGACwKAAIABQAHAAADEFhUZjSkKdZqBQG0IELDQAIAIfkEBQoABgAsCgAGAAUABwAAAxBoVlRKgyjmlAIBqCDCzUoCACH5BAUKAAYALAYACgAHAAUAAAMPaGpFtYYMAgJgLogA610JACH5BAUKAAYALAIACgAHAAUAAAMPCAHWFiI4o1ghZZJB5i0JACH5BAUKAAYALAAABgAFAAcAAAMQCAFmIaEp1motpDQySMNFAgA7) no-repeat scroll 0 0 transparent; + background-image: none; vertical-align: top; *vertical-align: middle } @@ -451,7 +462,7 @@ a.gitlabTreeView_toggle { font-size: 13px; font-weight: normal; text-shadow: none; - height: 58px; + height: auto; line-height: 2.8; background: none rgb(250, 251, 252); border-bottom: 1px solid rgb(225, 228, 232); @@ -486,3 +497,67 @@ a.gitlabTreeView_toggle { min-width: 100%; padding-top: 2px; } + +.gitlabTreeView_cog_icon { + float: right; + position: relative; + top: 6px; + right: 6px; + cursor: pointer; +} + +.gitlabTreeView_header_search { + margin-top: 2px; + margin-left: 4px; + width: 100%; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + line-height: 30px; +} + +.gitlabTreeView_search_text { + border: 1px solid #e5e5e5; + font-size: 13px; + padding: 4px 16px 4px 6px; + line-height: 20px; + width: 60%; +} + +.gitlabTreeView_search_icon { + position: relative; + right: 18px; + top: 0; + color: #e7e9ed; +} + +.gitlabTreeView_search_icon.active { + cursor: pointer; + color: rgba(0, 0, 0, 0.85); +} + +.gitlabTreeView_header_setting { + margin-top: 4px; + margin-left: 4px; + width: 100%; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + height: auto; + display: none; +} + +.gitlabTreeView_header_setting * { + font-weight: normal; +} + +.gitlabTreeView_header_setting_save { + cursor: pointer; + line-height: 1.5; + padding: 4px 6px; + font-size: 13px; + vertical-align: middle; + background-color: #fff; + border: 1px solid #e5e5e5; + color: rgba(0, 0, 0, 0.85); +} \ No newline at end of file diff --git a/js/jquery.ztree.exhide.min.js b/js/jquery.ztree.exhide.min.js new file mode 100755 index 0000000..e8af502 --- /dev/null +++ b/js/jquery.ztree.exhide.min.js @@ -0,0 +1,22 @@ +/* + * JQuery zTree exHideNodes v3.5.29 + * http://treejs.cn/ + * + * Copyright (c) 2010 Hunter.z + * + * Licensed same as jquery - MIT License + * http://www.opensource.org/licenses/mit-license.php + * + * email: hunter.z@263.net + * Date: 2017-06-19 + */ +(function(i){i.extend(!0,i.fn.zTree._z,{view:{clearOldFirstNode:function(c,a){for(var b=a.getNextNode();b;){if(b.isFirstNode){b.isFirstNode=!1;d.setNodeLineIcos(c,b);break}if(b.isLastNode)break;b=b.getNextNode()}},clearOldLastNode:function(c,a,b){for(a=a.getPreNode();a;){if(a.isLastNode){a.isLastNode=!1;b&&d.setNodeLineIcos(c,a);break}if(a.isFirstNode)break;a=a.getPreNode()}},makeDOMNodeMainBefore:function(c,a,b){c.push("
  • ")},showNode:function(c,a){a.isHidden=!1;f.initShowForExCheck(c,a);j(a,c).show()},showNodes:function(c,a,b){if(a&&a.length!=0){var e={},g,k;for(g=0,k=a.length;g0&&!a[b][0].isHidden? +a[b][0].isFirstNode=!0:e>0&&d.setFirstNodeForHide(c,a[b])},setLastNode:function(c,a){var b=c.data.key.children,e=a[b].length;e>0&&!a[b][0].isHidden?a[b][e-1].isLastNode=!0:e>0&&d.setLastNodeForHide(c,a[b])},setFirstNodeForHide:function(c,a){var b,e,g;for(e=0,g=a.length;e=0;e--){b=a[e];if(b.isLastNode)break;if(!b.isHidden&&!b.isLastNode){b.isLastNode=!0;d.setNodeLineIcos(c,b);break}else b=null}return b},setLastNodeForShow:function(c,a){var b,e,g,f;for(e=a.length-1;e>=0;e--)if(b=a[e],!g&&!b.isHidden&& +b.isLastNode){g=b;break}else if(!g&&!b.isHidden&&!b.isLastNode)b.isLastNode=!0,g=b,d.setNodeLineIcos(c,b);else if(g&&b.isLastNode){b.isLastNode=!1;f=b;d.setNodeLineIcos(c,b);break}return{"new":g,old:f}}},data:{initHideForExCheck:function(c,a){if(a.isHidden&&c.check&&c.check.enable){if(typeof a._nocheck=="undefined")a._nocheck=!!a.nocheck,a.nocheck=!0;a.check_Child_State=-1;d.repairParentChkClassWithSelf&&d.repairParentChkClassWithSelf(c,a)}},initShowForExCheck:function(c,a){if(!a.isHidden&&c.check&& +c.check.enable){if(typeof a._nocheck!="undefined")a.nocheck=a._nocheck,delete a._nocheck;if(d.setChkClass){var b=j(a,l.id.CHECK,c);d.setChkClass(c,b,a)}d.repairParentChkClassWithSelf&&d.repairParentChkClassWithSelf(c,a)}}}});var i=i.fn.zTree,m=i._z.tools,l=i.consts,d=i._z.view,f=i._z.data,j=m.$;f.addInitNode(function(c,a,b){if(typeof b.isHidden=="string")b.isHidden=m.eqs(b.isHidden,"true");b.isHidden=!!b.isHidden;f.initHideForExCheck(c,b)});f.addBeforeA(function(){});f.addZTreeTools(function(c,a){a.showNodes= +function(a,b){d.showNodes(c,a,b)};a.showNode=function(a,b){a&&d.showNodes(c,[a],b)};a.hideNodes=function(a,b){d.hideNodes(c,a,b)};a.hideNode=function(a,b){a&&d.hideNodes(c,[a],b)};var b=a.checkNode;if(b)a.checkNode=function(c,d,f,h){(!c||!c.isHidden)&&b.apply(a,arguments)}});var n=f.initNode;f.initNode=function(c,a,b,e,g,i,h){var j=(e?e:f.getRoot(c))[c.data.key.children];f.tmpHideFirstNode=d.setFirstNodeForHide(c,j);f.tmpHideLastNode=d.setLastNodeForHide(c,j);h&&(d.setNodeLineIcos(c,f.tmpHideFirstNode), +d.setNodeLineIcos(c,f.tmpHideLastNode));g=f.tmpHideFirstNode===b;i=f.tmpHideLastNode===b;n&&n.apply(f,arguments);h&&i&&d.clearOldLastNode(c,b,h)};var o=f.makeChkFlag;if(o)f.makeChkFlag=function(c,a){(!a||!a.isHidden)&&o.apply(f,arguments)};var p=f.getTreeCheckedNodes;if(p)f.getTreeCheckedNodes=function(c,a,b,e){if(a&&a.length>0){var d=a[0].getParentNode();if(d&&d.isHidden)return[]}return p.apply(f,arguments)};var q=f.getTreeChangeCheckedNodes;if(q)f.getTreeChangeCheckedNodes=function(c,a,b){if(a&& +a.length>0){var d=a[0].getParentNode();if(d&&d.isHidden)return[]}return q.apply(f,arguments)};var r=d.expandCollapseSonNode;if(r)d.expandCollapseSonNode=function(c,a,b,e,f){(!a||!a.isHidden)&&r.apply(d,arguments)};var s=d.setSonNodeCheckBox;if(s)d.setSonNodeCheckBox=function(c,a,b,e){(!a||!a.isHidden)&&s.apply(d,arguments)};var t=d.repairParentChkClassWithSelf;if(t)d.repairParentChkClassWithSelf=function(c,a){(!a||!a.isHidden)&&t.apply(d,arguments)}})(jQuery); diff --git a/main.js b/main.js index 5fe6f1f..a67d44b 100644 --- a/main.js +++ b/main.js @@ -6,6 +6,11 @@ var vm = {     project_id: null, repository_ref: null, shortcuts_project: null, + /* default setting */ + setting: { + toggle: true, + recursive: true + }, /* Detection if we are on GitLab page */ isGitLab: function () { var isGitLab = document.querySelector("meta[content^='GitLab']"); @@ -30,17 +35,55 @@ var vm = {     vm.repository_ref = $('#repository_ref').val(); //console.info(vm) }, - fetchFileTree: function (callback) { + loadNode: function (parentNode) { + if (parentNode && (parentNode.zAsync || parentNode.isAjaxing)) { + return; + } + + if (parentNode) { + parentNode.isAjaxing = true; + vm.getZTree().updateNode(parentNode); + //ztree class update + $("#" + parentNode.tId + "_ico").attr({ + style: "", + "class": "button" + " " + "ico_loading" + }); + } + + $.get(vm.apiRepoTree, { + id: vm.project_id, + path: parentNode ? parentNode.path : null, + ref_name: vm.repository_ref, + private_token: vm.private_token + }, function (result) { + if (parentNode) { + parentNode.isAjaxing = false; + parentNode.zAsync = true; + vm.getZTree().updateNode(parentNode); + } + + var treeArr = []; + + if (result) { + for (var i = 0; i < result.length; i++) { + var node = result[i]; + if (node.type === 'tree') { + node.isParent = true; + } + treeArr.push(node); + } + } + vm.getZTree().addNodes(parentNode, i, treeArr); + }); + }, + loadRecursiveNode: function () { $.get(vm.apiRepoTree, { id: vm.project_id, recursive: true, ref_name: vm.repository_ref, private_token: vm.private_token }, function (result) { - var tree = { - // This array is used in order to meet the structure requirments by ztree. - 'tree_arr': [] - }; + var treeArr = []; if (result) { // Convert the response data to another structure which can be accepted by ztree. @@ -53,11 +96,11 @@ var vm = {     } var path_fragments = node.path.split('/'); - if (path_fragments.length === 1) { // root level - tree[path_fragments[0]] = node; - tree['tree_arr'].push(node); - } else { // sub level - var parent = tree[path_fragments[0]]; + if (path_fragments.length === 1) { // root level + treeArr[path_fragments[0]] = node; + treeArr.push(node); + } else { // sub level + var parent = treeArr[path_fragments[0]]; for (var j = 1; j < path_fragments.length - 1; j++) { parent = parent.children_map[path_fragments[j]]; } @@ -67,13 +110,12 @@ var vm = {     } } - if (callback && typeof callback === "function") { - callback(tree['tree_arr']); - } + vm.getZTree().addNodes(null, i, treeArr); }); }, showTree: function () { - localStorage.setItem('toggle', 'show'); + vm.setting.toggle = true; + vm.saveSetting(); $("html").css("margin-left", "230px"); $(".gitlabTreeView_sidebar").animate({ @@ -83,7 +125,8 @@ var vm = {     }); }, hideTree: function () { - localStorage.setItem('toggle', 'hide'); + vm.setting.toggle = false; + vm.saveSetting(); $("html").css("margin-left", "0px"); $(".gitlabTreeView_sidebar").animate({ @@ -111,13 +154,17 @@ var vm = {     callback: { onClick: function (event, treeId, treeNode) { vm.selectNode(treeNode); + }, + onExpand: function (event, treeId, treeNode) { + if (vm.recursive) { + return; + } + vm.loadNode(treeNode); } } }; - vm.fetchFileTree(function (tree) { - $.fn.zTree.init($("#gitlabTreeView"), setting, tree); - }); + $.fn.zTree.init($("#gitlabTreeView"), setting); }, selectNode: function (treeNode) { if (treeNode.type === 'blob') { @@ -171,6 +218,72 @@ var vm = {     getZTree: function () { return $.fn.zTree.getZTreeObj("gitlabTreeView"); }, + getLocalStorage: function (k) { + try { + return localStorage.getItem(k) ? JSON.parse(localStorage.getItem(k)) : null; + } catch (err) { + //console.info(err); + localStorage.removeItem(k); + return null; + } + }, + setLocalStorage: function (k, v) { + localStorage.setItem(k, JSON.stringify(v)); + }, + getSetting: function () { + return vm.getLocalStorage("setting"); + }, + saveSetting: function () { + return vm.setLocalStorage("setting", vm.setting); + }, + isNull: function (obj) { + if (typeof (obj) == "undefined" || obj == "undefined") { + return true; + } else { + return (obj == null || obj.length <= 0) ? true : false; + } + }, + search: function (searchValue) { + var treeObj = vm.getZTree(); + var allNode = treeObj.transformToArray(treeObj.getNodes()); + + if (!vm.isNull(searchValue)) { + var nodeList = treeObj.getNodesByParamFuzzy("name", searchValue); + if (nodeList.length > 0) { + treeObj.hideNodes(allNode); + vm.showTreeNodes(nodeList, treeObj); + treeObj.expandAll(true); + } else { + treeObj.hideNodes(allNode); + } + } else { + treeObj.showNodes(allNode); + //折叠所有节点 + treeObj.expandAll(false); + } + }, + findParentNodes: [], + findParent: function (node, zTree) { + var pNode = node.getParentNode(); + if (pNode != null) { + vm.findParentNodes.push(pNode); + vm.findParent(pNode, zTree); + } + }, + showTreeNodes: function (nodeList, zTree) { + vm.findParentNodes = []; + for (var i = 0; i < nodeList.length; i++) { + vm.findParent(nodeList[i], zTree); + //显示结果节点的子节点 + if (nodeList[i].children != null) { + zTree.showNodes(zTree.transformToArray(nodeList[i].children)); + } + } + //显示所有对应父节点 + zTree.showNodes(vm.findParentNodes); + //显示搜索结果叶子节点 + zTree.showNodes(nodeList); + }, init: function () { if (!vm.isGitLab() || !vm.isFilePage()) { return; @@ -188,15 +301,25 @@ var vm = {     nav += "
    "; nav += "
    " + shortcuts + "
    "; nav += "
    " + vm.repository_ref + "
    "; + + nav += ""; + + nav += "
    " + nav += "
    "; + nav += "
    "; + nav += "
    "; + nav += "
    "; nav += "
      "; nav += ""; nav += ""; $("body").append($(nav)); - var toggle = localStorage.getItem('toggle') ? localStorage.getItem('toggle') : 'show'; + //setting + vm.setting = vm.getSetting() != null ? vm.getSetting() : vm.setting; + - if (toggle == 'show') { + if (vm.setting.toggle) { vm.showTree(); } else { vm.hideTree(); @@ -209,11 +332,61 @@ var vm = {     vm.showTree(); } }); + /** search */ + $(".gitlabTreeView_search_text").on("keyup", function (event) { + var searchValue = $(".gitlabTreeView_search_text").val(); + + if (vm.isNull(searchValue)) { + $(".gitlabTreeView_search_icon").addClass("fa-search").removeClass("fa-remove active"); + } else { + $(".gitlabTreeView_search_icon").addClass("fa-remove active").removeClass("fa-search"); + } + + if (event.keyCode == 13) { + vm.search(searchValue); + } + }); + + /** clear value and search */ + $(".gitlabTreeView_search_icon").on('click', function () { + $(".gitlabTreeView_search_text").val(''); + var e = $.Event("keyup"); + e.keyCode = 13; + $(".gitlabTreeView_search_text").trigger(e); + }); + + $(".gitlabTreeView_cog_icon").on("click", function () { + $(".gitlabTreeView_header_setting").slideToggle(); + }) + + /** saveSetting */ + $(".gitlabTreeView_header_setting_save").on("click", function () { + $(".gitlabTreeView_header_setting input[type=checkbox]").each(function () { + var name = $(this).attr('name'); + vm.setting[name] = $(this).is(':checked'); + vm.saveSetting(); + }); + + $(".gitlabTreeView_header_setting").slideUp(); + }) + + $(".gitlabTreeView_header_setting input[type=checkbox]").each(function () { + var name = $(this).attr('name'); + var value = vm.setting[name]; + $(this).prop('checked', value); + }); + vm.initTree(); + + if (vm.setting.recursive) { + vm.loadRecursiveNode(); + } else { + vm.loadNode(null); + } } }; $(function () { vm.init(); -}); +}); \ No newline at end of file diff --git a/manifest.json b/manifest.json index 784d55f..edf80de 100755 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name": "Gitlab TreeView", - "version": "1.1", + "version": "1.2", "manifest_version": 2, "author": "linsage", "description": "Code tree for Gitlab", @@ -36,6 +36,7 @@ "js": [ "js/jquery-1.12.4.min.js", "js/jquery.ztree.all.min.js", + "js/jquery.ztree.exhide.min.js", "main.js" ], "run_at": "document_start"