Explorar o código

优化程序。

yangzhijie %!s(int64=4) %!d(string=hai) anos
pai
achega
382dfc9e1a

+ 8 - 2
index.html

@@ -8,6 +8,9 @@
 
   <link rel="stylesheet" type="text/css" href="./static/bootstrap/css/bootstrap.min.css">
   <link rel="stylesheet" type="text/css" href="./static/bootstrap/css/bootstrap-dialog.min.css">
+  <link rel="stylesheet" type="text/css" href="./static/bootstrap-treeview/bootstrap-treeview.css">
+  <!-- <link rel="stylesheet" type="text/css" href="./static/summernote-0.8.18/summernote.css"> -->
+
 
   <script src="./static/bootstrap/js/jquery.min.js"></script>
   <script src="./static/bootstrap/js/jquery.cookie.js"></script>
@@ -18,8 +21,11 @@
   <script src="./static/bootstrap/js/bootstrap.js"></script>
   <script src="./static/bootstrap/js/bootstrap-dialog.min.js"></script>
 
-  <script src="../static/js/table-fixer.jquery.js"></script>
-  <script src="../static/js/colResizable-1.6.js"></script>
+  <script src="./static/bootstrap-treeview/bootstrap-treeview.js"></script>
+  <script src="./static/summernote-0.8.18/summernote.min.js"></script>
+  <script src="./static/summernote-0.8.18/lang/summernote-zh-CN.min.js"></script>
+
+  
 </head>
 
 <body>

+ 3 - 8
package-lock.json

@@ -7304,9 +7304,9 @@
       }
     },
     "pc-client-component": {
-      "version": "0.0.22",
-      "resolved": "https://registry.nlark.com/pc-client-component/download/pc-client-component-0.0.22.tgz?cache=0&sync_timestamp=1627371629641&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpc-client-component%2Fdownload%2Fpc-client-component-0.0.22.tgz",
-      "integrity": "sha1-JQUBdZHYRfEncS8HjfMoR+5ghIw="
+      "version": "0.0.24",
+      "resolved": "https://registry.nlark.com/pc-client-component/download/pc-client-component-0.0.24.tgz?cache=0&sync_timestamp=1627395498678&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpc-client-component%2Fdownload%2Fpc-client-component-0.0.24.tgz",
+      "integrity": "sha1-oz/Verxq9q4fwpq7jfUoOYAYr6g="
     },
     "picomatch": {
       "version": "2.3.0",
@@ -11891,11 +11891,6 @@
       "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
       "dev": true
     },
-    "vue-treeselect": {
-      "version": "1.0.7",
-      "resolved": "https://registry.nlark.com/vue-treeselect/download/vue-treeselect-1.0.7.tgz",
-      "integrity": "sha1-WJ9okBm2yR0bO7qUbb22NWWxPwU="
-    },
     "vuedraggable": {
       "version": "2.24.3",
       "resolved": "https://registry.nlark.com/vuedraggable/download/vuedraggable-2.24.3.tgz?cache=0&sync_timestamp=1623379410842&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvuedraggable%2Fdownload%2Fvuedraggable-2.24.3.tgz",

+ 1 - 1
package.json

@@ -12,7 +12,7 @@
   },
   "dependencies": {
     "@riophae/vue-treeselect": "^0.4.0",
-    "pc-client-component": "0.0.22",
+    "pc-client-component": "0.0.24",
     "vue": "^2.5.2",
     "vue-bootstrap-pagination": "^2.10.3",
     "vue-i18n": "^8.24.5",

+ 1 - 1
src/App.vue

@@ -1,5 +1,5 @@
 <template>
-  <div id="app">
+  <div id="app" style="padding: 10px">
     <router-view/>
   </div>
 </template>

BIN=BIN
src/assets/font/summernote.eot


BIN=BIN
src/assets/font/summernote.ttf


BIN=BIN
src/assets/font/summernote.woff


BIN=BIN
src/assets/font/summernote.woff2


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 12 - 0
src/assets/summernote.css


+ 9 - 9
src/common/DynamicJsLoader.js

@@ -42,20 +42,20 @@ module.exports = {
 	},
 
 
+
 	/**
-	 * 动态加载summernote
+	 * 动态加载loadBootstrapTree
 	 * @param {Object} success
 	 */
-	 loadSummernote: function (success) {
-		if (jQuery().summernote) {
+	loadBootstrapTree: function (success) {
+		if (jQuery().loadBootstrapTree) {
 			success();
 		} else {
-			this.addCSS("../../static/summernote-0.8.18/summernote.css");
-			$.getScript("../../static/summernote-0.8.18/summernote.min.js", function (data, textStatus, jqxhr) {
-				$.getScript("../../static/summernote-0.8.18/lang/summernote-zh-CN.min.js", function (data, textStatus, jaxhr) {
-					success();
-				})
-			});
+			this.addCSS("../../static/bootstrap-treeview/bootstrap-treeview.css");
+			$.getScript("../../static/bootstrap-treeview/bootstrap-treeview.js", function (data, textStatus, jaxhr) {
+				success();
+			})
 		}
 	},
+
 }

+ 6 - 0
src/main.js

@@ -9,6 +9,12 @@ import VueI18n from 'vue-i18n'
 import routes from './router/index.js'
 import PcClientComponent from 'pc-client-component';
 
+// bug fixed by jack 
+// 在加载 css 的时候 font 不能被正确的加载
+import './assets/summernote.css';
+
+
+
 Vue.config.productionTip = false
 
 Vue.use(Router)

+ 2 - 2
src/trace/CompleteProjectList.vue

@@ -131,7 +131,7 @@ export default {
          * 显示归档/未归档的项目
          */
         isTheArchive: function () {
-            let routeData  = this.$router.push({path: '/desktop/projectList'});
+            let routeData  = this.$router.push({path: '/trace/projectList'});
 			window.open(routeData.href, '_blank');
         },
         /**
@@ -142,7 +142,7 @@ export default {
             var _self = this;
             this.$router.push(
                 {
-                    path: '/desktop/notFinishedProjectTraces/' + obj.id,
+                    path: '/trace/notFinishedProjectTraces/' + obj.id,
                     query:
                     {
                         projectName: obj.name

+ 1 - 1
src/trace/Finished.vue

@@ -126,7 +126,7 @@ export default {
          */
         openLine: function (obj) {
             this.$router.push({
-                path: '/desktop/trace/' + obj.id
+                path: '/trace/trace/' + obj.id
             });
         },
         /**

+ 6 - 6
src/trace/FinishedProjectTraces.vue

@@ -160,7 +160,7 @@ export default {
          */
         edit: function (trace) {
             var _self = this;
-            this.$router.push("/desktop/traceUpdate/" + trace.id);
+            this.$router.push("/trace/traceUpdate/" + trace.id);
         },
 
         /**
@@ -222,7 +222,7 @@ export default {
          */
         openLine: function (obj) {
             this.$router.push({
-                path: '/desktop/trace/' + obj.id
+                path: '/trace/trace/' + obj.id
             });
         },
 
@@ -231,7 +231,7 @@ export default {
          * @author ZhangTeng 20190201
          */
         addTrace: function (projectId) {
-            this.$router.push("/desktop/traceCreate/" + projectId);
+            this.$router.push("/trace/traceCreate/" + projectId);
         },
 
 		/**
@@ -242,7 +242,7 @@ export default {
         projectArchive: function (projectId) {
             var _self = this;
             this.$router.push({
-                path: '/desktop/projectArchive/' + projectId,
+                path: '/trace/projectArchive/' + projectId,
                 query:
                 {
                     projectName: _self.projectName
@@ -257,7 +257,7 @@ export default {
 		projectManagement: function (projectId) {
 			var _self = this;
             this.$router.push({
-                    path: '/desktop/projectManagement/' + projectId,
+                    path: '/trace/projectManagement/' + projectId,
                     query:
                     {
                         projectName: _self.projectName
@@ -271,7 +271,7 @@ export default {
         goPersonList: function () {
             var _self = this;
             this.$router.push({
-                path: "/desktop/projectUserList/" + _self.projectId,
+                path: "/trace/projectUserList/" + _self.projectId,
                 query: {
                     projectName: _self.projectName,
                 },

+ 9 - 9
src/trace/NotFinishedProjectTraces.vue

@@ -154,7 +154,7 @@
 			 */
 			edit: function(trace) {
 				var _self = this;
-				this.$router.push("/desktop/traceUpdate/" + trace.id);
+				this.$router.push("/trace/traceUpdate/" + trace.id);
 			},
 
 			/**
@@ -162,7 +162,7 @@
 			 */
 			openFinishedProjectTraces: function() {
 				var _self = this;
-				this.$router.push("/desktop/finishedProjectTraces/" + _self.projectId + "?projectName=" + _self.projectName);
+				this.$router.push("/trace/finishedProjectTraces/" + _self.projectId + "?projectName=" + _self.projectName);
 			},
 
 			listNotFinishedTask: function() {
@@ -305,7 +305,7 @@
 			 */
 			openLine: function(obj) {
 				this.$router.push({
-					path: '/desktop/trace/' + obj.id
+					path: '/trace/trace/' + obj.id
 				});
 			},
 
@@ -314,7 +314,7 @@
 			 * @author ZhangTeng 20190201
 			 */
 			addTrace: function(projectId) {
-				this.$router.push("/desktop/traceCreate/" + projectId);
+				this.$router.push("/trace/traceCreate/" + projectId);
 			},
 
 			/**
@@ -325,7 +325,7 @@
 			projectArchive: function(projectId) {
 				var _self = this;
 				this.$router.push({
-					path: '/desktop/projectArchive/' + projectId,
+					path: '/trace/projectArchive/' + projectId,
 					query: {
 						projectName: _self.projectName
 					}
@@ -339,7 +339,7 @@
 			projectManagement: function(projectId) {
 				var _self = this;
 				this.$router.push({
-					path: '/desktop/projectManagement/' + projectId,
+					path: '/trace/projectManagement/' + projectId,
 					query: {
 						projectName: _self.projectName
 					}
@@ -352,7 +352,7 @@
 			goPersonList: function() {
 				var _self = this;
 				this.$router.push({
-					path: "/desktop/projectUserList/" + _self.projectId,
+					path: "/trace/projectUserList/" + _self.projectId,
 					query: {
 						projectName: _self.projectName,
 					},
@@ -366,7 +366,7 @@
 			goAdminPersonList: function() {
 				var _self = this;
 				this.$router.push({
-					path: "/desktop/projectAdminUserList/" + _self.projectId,
+					path: "/trace/projectAdminUserList/" + _self.projectId,
 					query: {
 						projectName: _self.projectName,
 					},
@@ -394,7 +394,7 @@
 			projectManagement: function(projectId) {
 				var _self = this;
 				this.$router.push({
-					path: '/desktop/projectManagement/' + projectId,
+					path: '/trace/projectManagement/' + projectId,
 					query: {
 						projectName: _self.projectName
 					}

+ 2 - 2
src/trace/Personage.vue

@@ -110,7 +110,7 @@ export default {
          */
         openLine: function (obj) {
             this.$router.push({ 
-                path: '/desktop/trace/' + obj.id 
+                path: '/trace/trace/' + obj.id 
             });
         },
         /**
@@ -170,7 +170,7 @@ export default {
                 userName: this.userName
             }
             localStorage.setItem(this.uuid, JSON.stringify(obj))
-            this.$router.push("/desktop/finished/" + this.uuid);
+            this.$router.push("/trace/finished/" + this.uuid);
         },
 	},
 	

+ 1 - 1
src/trace/ProjectAdminUserList.vue

@@ -121,7 +121,7 @@ export default {
                 userName:user.userName
             }
             localStorage.setItem(uuid, JSON.stringify(obj));
-            this.$router.push("/desktop/userNotFinishedTrace/" + uuid);
+            this.$router.push("/trace/userNotFinishedTrace/" + uuid);
         },
 
         /**

+ 2 - 2
src/trace/ProjectList.vue

@@ -153,7 +153,7 @@ export default {
          * 显示归档/未归档的项目
          */
         isTheArchive: function () {
-           this.$router.push("/desktop/completeProjectList");
+           this.$router.push("/trace/completeProjectList");
         },
         /**
          * 打开明细
@@ -163,7 +163,7 @@ export default {
             var _self = this;
             this.$router.push(
                 {
-                    path: '/desktop/notFinishedProjectTraces/' + obj.id,
+                    path: '/trace/notFinishedProjectTraces/' + obj.id,
                     query:
                     {
                         projectName: obj.name

+ 1 - 1
src/trace/ProjectUserList.vue

@@ -122,7 +122,7 @@ export default {
                 userName:user.userName
             }
             localStorage.setItem(uuid, JSON.stringify(obj));
-            this.$router.push("/desktop/userNotFinishedTrace/" + uuid);
+            this.$router.push("/trace/userNotFinishedTrace/" + uuid);
         },
 
         /**

+ 1 - 1
src/trace/TeamList.vue

@@ -66,7 +66,7 @@ export default {
          */
         openUserNotFinishedTrace: function (user) {
             this.$router.push({
-                path: '/desktop/userNotFinishedTrace/' + user.id,
+                path: '/trace/userNotFinishedTrace/' + user.id,
                 query: {
                     userName : user.name
                 }

+ 2 - 2
src/trace/Trace.vue

@@ -254,7 +254,7 @@ export default {
          */
         openTraceComment: function () {
             var _self = this;
-            this.$router.push("/desktop/traceCommentCreate/" + _self.trace.id);
+            this.$router.push("/trace/traceCommentCreate/" + _self.trace.id);
         },
 
         /**
@@ -278,7 +278,7 @@ export default {
          */
         edit: function () {
             var _self = this;
-            _self.$router.push("/desktop/traceUpdate/" + _self.traceId);
+            _self.$router.push("/trace/traceUpdate/" + _self.traceId);
         },
 
         /**

+ 1 - 1
src/trace/TraceComment.vue

@@ -111,7 +111,7 @@
 			 * @author GuoZhiBo 20171201
 			 */
 			edit: function(item) {
-				this.$router.push("/desktop/traceCommentEdit/" + item.id);
+				this.$router.push("/trace/traceCommentEdit/" + item.id);
 			}
 		},
 		

+ 20 - 22
src/trace/TraceCommentCreate.vue

@@ -390,28 +390,26 @@ export default {
         });
         this.initData();
         this.getTraceConfig();
-		DynamicJsLoader.loadSummernote(function () {
-		    $('#summernote').summernote({
-		    	toolbar:[
-			        ['insert', ['link', 'picture', 'video', 'audio', 'hr', 'table', //插件
-			        'fontname', 'fontsize', 'color', 'bold', 'italic', 'underline', 'strikethrough', 'clear',//字体样式
-			        'style', 'ol', 'ul', 'paragraph', 'height',//段落样式
-			        'fullscreen', 'codeview', 'undo', 'redo', 'help'//Misc
-			        ]],
-			    ],
-		        height: 400,
-		        minHeight: 300,
-		        maxHeight: 500,
-		        focus: true,
-		        lang: 'zh-CN',
-		        callbacks: {
-		            onImageUpload: function (files, editor, $editable) {
-		                _self.sendFile(files[0], editor, $editable);
-		            }
-		        }
-		    });
-		    _self.summernoteInitSuccess = true;
-		})
+        $('#summernote').summernote({
+            toolbar:[
+                ['insert', ['link', 'picture', 'video', 'audio', 'hr', 'table', //插件
+                'fontname', 'fontsize', 'color', 'bold', 'italic', 'underline', 'strikethrough', 'clear',//字体样式
+                'style', 'ol', 'ul', 'paragraph', 'height',//段落样式
+                'fullscreen', 'codeview', 'undo', 'redo', 'help'//Misc
+                ]],
+            ],
+            height: 400,
+            minHeight: 300,
+            maxHeight: 500,
+            focus: true,
+            lang: 'zh-CN',
+            callbacks: {
+                onImageUpload: function (files, editor, $editable) {
+                    _self.sendFile(files[0], editor, $editable);
+                }
+            }
+        });
+        _self.summernoteInitSuccess = true;
 		
     },
 	destroyed: function(){

+ 21 - 23
src/trace/TraceCommentEdit.vue

@@ -95,31 +95,29 @@
 						if(successData.attachments != null && successData.attachments != ''){
 							_self.files=(successData.attachments.split(','));
 						}
-						DynamicJsLoader.loadSummernote(function() {
-							$('#summernote').summernote({
-								toolbar:[
-							        ['insert', ['link', 'picture', 'video', 'audio', 'hr', 'table', //插件
-							        'fontname', 'fontsize', 'color', 'bold', 'italic', 'underline', 'strikethrough', 'clear',//字体样式
-							        'style', 'ol', 'ul', 'paragraph', 'height',//段落样式
-							        'fullscreen', 'codeview', 'undo', 'redo', 'help'//Misc
-							        ]],
-							    ],
-								height: 400,
-								minHeight: 300,
-								maxHeight: 500,
-								focus: true,
-								lang: 'zh-CN',
-								callbacks: {
-									onImageUpload: function(files, editor, $editable) {
-										_self.sendFile(files[0], editor, $editable);
-									}
+						$('#summernote').summernote({
+							toolbar:[
+								['insert', ['link', 'picture', 'video', 'audio', 'hr', 'table', //插件
+								'fontname', 'fontsize', 'color', 'bold', 'italic', 'underline', 'strikethrough', 'clear',//字体样式
+								'style', 'ol', 'ul', 'paragraph', 'height',//段落样式
+								'fullscreen', 'codeview', 'undo', 'redo', 'help'//Misc
+								]],
+							],
+							height: 400,
+							minHeight: 300,
+							maxHeight: 500,
+							focus: true,
+							lang: 'zh-CN',
+							callbacks: {
+								onImageUpload: function(files, editor, $editable) {
+									_self.sendFile(files[0], editor, $editable);
 								}
-							});
-							if (_self.traceComment != null) {
-								$('#summernote').summernote('code', _self.traceComment.content);
 							}
-							_self.summernoteInitSuccess = true;
-						})
+						});
+						if (_self.traceComment != null) {
+							$('#summernote').summernote('code', _self.traceComment.content);
+						}
+						_self.summernoteInitSuccess = true;
 					}, errorData => {
 						Common.processException(errorData);
 					});

+ 20 - 22
src/trace/TraceCreate.vue

@@ -295,28 +295,26 @@ export default {
         this.projectId = this.$route.params.projectId;
         this.initProject();
         this.initData();
-        DynamicJsLoader.loadSummernote(function () {
-            $('#summernote').summernote({
-            	toolbar:[
-			        ['insert', ['link', 'picture', 'video', 'audio', 'hr', 'table', //插件
-			        'fontname', 'fontsize', 'color', 'bold', 'italic', 'underline', 'strikethrough', 'clear',//字体样式
-			        'style', 'ol', 'ul', 'paragraph', 'height',//段落样式
-			        'fullscreen', 'codeview', 'undo', 'redo', 'help'//Misc
-			        ]],
-			    ],
-                height: 400,
-                minHeight: 300,
-                maxHeight: 500,
-                focus: true,
-                lang: 'zh-CN',
-                callbacks: {
-                    onImageUpload: function (files, editor, $editable) {
-                        _self.sendFile(files[0], editor, $editable);
-                    },
-                }
-            });
-            _self.summernoteInitSuccess = true;
-        })
+        $('#summernote').summernote({
+            toolbar:[
+                ['insert', ['link', 'picture', 'video', 'audio', 'hr', 'table', //插件
+                'fontname', 'fontsize', 'color', 'bold', 'italic', 'underline', 'strikethrough', 'clear',//字体样式
+                'style', 'ol', 'ul', 'paragraph', 'height',//段落样式
+                'fullscreen', 'codeview', 'undo', 'redo', 'help'//Misc
+                ]],
+            ],
+            height: 400,
+            minHeight: 300,
+            maxHeight: 500,
+            focus: true,
+            lang: 'zh-CN',
+            callbacks: {
+                onImageUpload: function (files, editor, $editable) {
+                    _self.sendFile(files[0], editor, $editable);
+                },
+            }
+        });
+        _self.summernoteInitSuccess = true;
     },
 
     destroyed: function(){

+ 1 - 1
src/trace/TraceDynamic.vue

@@ -193,7 +193,7 @@ export default {
             var _self = this;
             if (traceId != null && traceId != undefined) {
                 this.$router.push({
-                    path: '/desktop/trace/' + traceId
+                    path: '/trace/trace/' + traceId
                 });
             } else {
                 Notify.error("提示", "找不到这个任务了!");

+ 6 - 6
src/trace/TraceHeader.vue

@@ -18,7 +18,7 @@
 
                    
                 <span class="glyphicon glyphicon-circle-arrow-left m-image"
-                    @click="goBack"></span>
+                    @click="goBack" style="font-size: 36px; color: black;"></span>
 
                 </a>
             </div>
@@ -80,7 +80,7 @@ export default {
          */
         openProject() {
             var _self = this;
-            this.$router.push("/desktop/projectList");
+            this.$router.push("/trace/projectList");
         },
 
         /**
@@ -88,21 +88,21 @@ export default {
          */
         openDynamic() {
             var _self = this;
-            this.$router.push("/desktop/traceDynamic");
+            this.$router.push("/trace/traceDynamic");
         },
 
         /**
          * 打开我自己界面
          */
         openSelf() {
-            this.$router.push("/desktop/traceList/I_LAUNCH");
+            this.$router.push("/trace/traceList/I_LAUNCH");
         },
 
         /**
          * 打开团队界面
          */
         team() {
-            this.$router.push("/desktop/teamList");
+            this.$router.push("/trace/teamList");
         },
 
         goBack() {
@@ -114,7 +114,7 @@ export default {
         },
         
         traceSetting(){
-        	this.$router.push("/desktop/traceConfig");
+        	this.$router.push("/trace/traceConfig");
         },
         /**
          * 查询配置信息

+ 4 - 4
src/trace/TraceList.vue

@@ -51,7 +51,7 @@
 			</div>
 		</div>
 
-		<div class="row">
+		<div >
 			<div class="pull-left">
 				<span>第{{(pagination.current_page-1)*pagination.per_page+1}}-{{pagination.current_page*pagination.per_page}}条,共计{{pagination.total}}条,每页显示</span>
 				<PageSizeSelect  v-on:pageSizeChanged="gridSizeSelect"></PageSizeSelect>
@@ -192,7 +192,7 @@
 			 */
 			openLine: function(obj) {
 				this.$router.push({
-					path: '/desktop/trace/' + obj.id
+					path: '/trace/trace/' + obj.id
 				});
 			},
 
@@ -202,7 +202,7 @@
 			 */
 			edit: function(item) {
 				var _self = this;
-				this.$router.push("/desktop/traceUpdate/" + item.id);
+				this.$router.push("/trace/traceUpdate/" + item.id);
 			},
 
 			/**
@@ -233,7 +233,7 @@
 				this.getDatas();
 			},
 			"param.traceUserStatus": function(val) {
-				this.$router.push("/desktop/traceList/" + val);
+				this.$router.push("/trace/traceList/" + val);
 				this.param.traceUserStatus = this.$route.params.traceState;
 				this.pagination.total = 0;
 				this.pagination.per_page = Common.pageSize;

+ 2 - 2
src/trace/TraceTimeLine.vue

@@ -227,7 +227,7 @@ export default {
         editTraceTimeLine: function (traceTimeLine) {
             var _self = this;
             this.$router.push({
-                path: "/desktop/traceTimeLineEdit/" + traceTimeLine.id,
+                path: "/trace/traceTimeLineEdit/" + traceTimeLine.id,
                 query: {
                     projectId: _self.trace.projectId
                 }
@@ -240,7 +240,7 @@ export default {
         createTraceTimeLine: function(){
             var _self = this;
             this.$router.push({
-                path: "/desktop/traceTimeLineCreate/" + this.trace.id,
+                path: "/trace/traceTimeLineCreate/" + this.trace.id,
                 query: {
                     projectId: _self.trace.projectId
                 }

+ 21 - 23
src/trace/TraceUpdate.vue

@@ -294,31 +294,29 @@ export default {
                     	_self.srcArray = JSON.parse(successData.audioSrcs); 
                     }
                     _self.changeProjectSelected();
-                    DynamicJsLoader.loadSummernote(function () {
-                        $('#summernote').summernote({
-                        	toolbar:[
-						        ['insert', ['link', 'picture', 'video', 'audio', 'hr', 'table', //插件
-						        'fontname', 'fontsize', 'color', 'bold', 'italic', 'underline', 'strikethrough', 'clear',//字体样式
-						        'style', 'ol', 'ul', 'paragraph', 'height',//段落样式
-						        'fullscreen', 'codeview', 'undo', 'redo', 'help'//Misc
-						        ]],
-						    ],
-                            height: 400,
-                            minHeight: 300,
-                            maxHeight: 500,
-                            focus: true,
-                            lang: 'zh-CN',
-                            callbacks: {
-                                onImageUpload: function (files, editor, $editable) {
-                                    _self.sendFile(files[0], editor, $editable);
-                                }
+                    $('#summernote').summernote({
+                        toolbar:[
+                            ['insert', ['link', 'picture', 'video', 'audio', 'hr', 'table', //插件
+                            'fontname', 'fontsize', 'color', 'bold', 'italic', 'underline', 'strikethrough', 'clear',//字体样式
+                            'style', 'ol', 'ul', 'paragraph', 'height',//段落样式
+                            'fullscreen', 'codeview', 'undo', 'redo', 'help'//Misc
+                            ]],
+                        ],
+                        height: 400,
+                        minHeight: 300,
+                        maxHeight: 500,
+                        focus: true,
+                        lang: 'zh-CN',
+                        callbacks: {
+                            onImageUpload: function (files, editor, $editable) {
+                                _self.sendFile(files[0], editor, $editable);
                             }
-                        });
-                        if (_self.traceDto != null) {
-                            $('#summernote').summernote('code', _self.traceDto.detail);
                         }
-                        _self.summernoteInitSuccess = true;
-                    })
+                    });
+                    if (_self.traceDto != null) {
+                        $('#summernote').summernote('code', _self.traceDto.detail);
+                    }
+                    _self.summernoteInitSuccess = true;
                 }, errorData => {
                     Common.processException(errorData);
                 });

+ 1 - 1
src/trace/UseFinishedTrace.vue

@@ -122,7 +122,7 @@ export default {
          */
         openLine: function (obj) {
             this.$router.push({ 
-                path: '/desktop/trace/' + obj.id 
+                path: '/trace/trace/' + obj.id 
             });
         },
         /**

+ 2 - 2
src/trace/UserNotFinishedTrace.vue

@@ -103,7 +103,7 @@ export default {
          */
         openLine: function (obj) {
             this.$router.push({ 
-                path: '/desktop/trace/' + obj.id 
+                path: '/trace/trace/' + obj.id 
             });
         },
         
@@ -152,7 +152,7 @@ export default {
         finished: function () {
             var _self = this;
             this.$router.push({
-                path: '/desktop/useFinishedTrace/' + _self.userId,
+                path: '/trace/useFinishedTrace/' + _self.userId,
                 query: {
                     userName: _self.userName,
                 }

+ 37 - 0
static/bootstrap-treeview/bootstrap-treeview.css

@@ -0,0 +1,37 @@
+/* =========================================================
+ * bootstrap-treeview.css v1.2.0
+ * =========================================================
+ * Copyright 2013 Jonathan Miles 
+ * Project URL : http://www.jondmiles.com/bootstrap-treeview
+ *	
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+.treeview .list-group-item {
+	cursor: pointer;
+}
+
+.treeview span.indent {
+	margin-left: 10px;
+	margin-right: 10px;
+}
+
+.treeview span.icon {
+	width: 12px;
+	margin-right: 5px;
+}
+
+.treeview .node-disabled {
+	color: silver;
+	cursor: not-allowed;
+}

+ 1249 - 0
static/bootstrap-treeview/bootstrap-treeview.js

@@ -0,0 +1,1249 @@
+/* =========================================================
+ * bootstrap-treeview.js v1.2.0
+ * =========================================================
+ * Copyright 2013 Jonathan Miles
+ * Project URL : http://www.jondmiles.com/bootstrap-treeview
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+;(function ($, window, document, undefined) {
+
+	/*global jQuery, console*/
+
+	'use strict';
+
+	var pluginName = 'treeview';
+
+	var _default = {};
+
+	_default.settings = {
+
+		injectStyle: true,
+
+		levels: 2,
+
+		expandIcon: 'glyphicon glyphicon-plus',
+		collapseIcon: 'glyphicon glyphicon-minus',
+		emptyIcon: 'glyphicon',
+		nodeIcon: '',
+		selectedIcon: '',
+		checkedIcon: 'glyphicon glyphicon-check',
+		uncheckedIcon: 'glyphicon glyphicon-unchecked',
+
+		color: undefined, // '#000000',
+		backColor: undefined, // '#FFFFFF',
+		borderColor: undefined, // '#dddddd',
+		onhoverColor: '#F5F5F5',
+		selectedColor: '#FFFFFF',
+		selectedBackColor: '#428bca',
+		searchResultColor: '#D9534F',
+		searchResultBackColor: undefined, //'#FFFFFF',
+
+		enableLinks: false,
+		highlightSelected: true,
+		highlightSearchResults: true,
+		showBorder: true,
+		showIcon: true,
+		showCheckbox: false,
+		showTags: false,
+		multiSelect: false,
+
+		// Event handlers
+		onNodeChecked: undefined,
+		onNodeCollapsed: undefined,
+		onNodeDisabled: undefined,
+		onNodeEnabled: undefined,
+		onNodeExpanded: undefined,
+		onNodeSelected: undefined,
+		onNodeUnchecked: undefined,
+		onNodeUnselected: undefined,
+		onSearchComplete: undefined,
+		onSearchCleared: undefined
+	};
+
+	_default.options = {
+		silent: false,
+		ignoreChildren: false
+	};
+
+	_default.searchOptions = {
+		ignoreCase: true,
+		exactMatch: false,
+		revealResults: true
+	};
+
+	var Tree = function (element, options) {
+
+		this.$element = $(element);
+		this.elementId = element.id;
+		this.styleId = this.elementId + '-style';
+
+		this.init(options);
+
+		return {
+
+			// Options (public access)
+			options: this.options,
+
+			// Initialize / destroy methods
+			init: $.proxy(this.init, this),
+			remove: $.proxy(this.remove, this),
+
+			// Get methods
+			getNode: $.proxy(this.getNode, this),
+			getParent: $.proxy(this.getParent, this),
+			getSiblings: $.proxy(this.getSiblings, this),
+			getSelected: $.proxy(this.getSelected, this),
+			getUnselected: $.proxy(this.getUnselected, this),
+			getExpanded: $.proxy(this.getExpanded, this),
+			getCollapsed: $.proxy(this.getCollapsed, this),
+			getChecked: $.proxy(this.getChecked, this),
+			getUnchecked: $.proxy(this.getUnchecked, this),
+			getDisabled: $.proxy(this.getDisabled, this),
+			getEnabled: $.proxy(this.getEnabled, this),
+
+			// Select methods
+			selectNode: $.proxy(this.selectNode, this),
+			unselectNode: $.proxy(this.unselectNode, this),
+			toggleNodeSelected: $.proxy(this.toggleNodeSelected, this),
+
+			// Expand / collapse methods
+			collapseAll: $.proxy(this.collapseAll, this),
+			collapseNode: $.proxy(this.collapseNode, this),
+			expandAll: $.proxy(this.expandAll, this),
+			expandNode: $.proxy(this.expandNode, this),
+			toggleNodeExpanded: $.proxy(this.toggleNodeExpanded, this),
+			revealNode: $.proxy(this.revealNode, this),
+
+			// Expand / collapse methods
+			checkAll: $.proxy(this.checkAll, this),
+			checkNode: $.proxy(this.checkNode, this),
+			uncheckAll: $.proxy(this.uncheckAll, this),
+			uncheckNode: $.proxy(this.uncheckNode, this),
+			toggleNodeChecked: $.proxy(this.toggleNodeChecked, this),
+
+			// Disable / enable methods
+			disableAll: $.proxy(this.disableAll, this),
+			disableNode: $.proxy(this.disableNode, this),
+			enableAll: $.proxy(this.enableAll, this),
+			enableNode: $.proxy(this.enableNode, this),
+			toggleNodeDisabled: $.proxy(this.toggleNodeDisabled, this),
+
+			// Search methods
+			search: $.proxy(this.search, this),
+			clearSearch: $.proxy(this.clearSearch, this)
+		};
+	};
+
+	Tree.prototype.init = function (options) {
+
+		this.tree = [];
+		this.nodes = [];
+
+		if (options.data) {
+			if (typeof options.data === 'string') {
+				options.data = $.parseJSON(options.data);
+			}
+			this.tree = $.extend(true, [], options.data);
+			delete options.data;
+		}
+		this.options = $.extend({}, _default.settings, options);
+
+		this.destroy();
+		this.subscribeEvents();
+		this.setInitialStates({ nodes: this.tree }, 0);
+		this.render();
+	};
+
+	Tree.prototype.remove = function () {
+		this.destroy();
+		$.removeData(this, pluginName);
+		$('#' + this.styleId).remove();
+	};
+
+	Tree.prototype.destroy = function () {
+
+		if (!this.initialized) return;
+
+		this.$wrapper.remove();
+		this.$wrapper = null;
+
+		// Switch off events
+		this.unsubscribeEvents();
+
+		// Reset this.initialized flag
+		this.initialized = false;
+	};
+
+	Tree.prototype.unsubscribeEvents = function () {
+
+		this.$element.off('click');
+		this.$element.off('nodeChecked');
+		this.$element.off('nodeCollapsed');
+		this.$element.off('nodeDisabled');
+		this.$element.off('nodeEnabled');
+		this.$element.off('nodeExpanded');
+		this.$element.off('nodeSelected');
+		this.$element.off('nodeUnchecked');
+		this.$element.off('nodeUnselected');
+		this.$element.off('searchComplete');
+		this.$element.off('searchCleared');
+	};
+
+	Tree.prototype.subscribeEvents = function () {
+
+		this.unsubscribeEvents();
+
+		this.$element.on('click', $.proxy(this.clickHandler, this));
+
+		if (typeof (this.options.onNodeChecked) === 'function') {
+			this.$element.on('nodeChecked', this.options.onNodeChecked);
+		}
+
+		if (typeof (this.options.onNodeCollapsed) === 'function') {
+			this.$element.on('nodeCollapsed', this.options.onNodeCollapsed);
+		}
+
+		if (typeof (this.options.onNodeDisabled) === 'function') {
+			this.$element.on('nodeDisabled', this.options.onNodeDisabled);
+		}
+
+		if (typeof (this.options.onNodeEnabled) === 'function') {
+			this.$element.on('nodeEnabled', this.options.onNodeEnabled);
+		}
+
+		if (typeof (this.options.onNodeExpanded) === 'function') {
+			this.$element.on('nodeExpanded', this.options.onNodeExpanded);
+		}
+
+		if (typeof (this.options.onNodeSelected) === 'function') {
+			this.$element.on('nodeSelected', this.options.onNodeSelected);
+		}
+
+		if (typeof (this.options.onNodeUnchecked) === 'function') {
+			this.$element.on('nodeUnchecked', this.options.onNodeUnchecked);
+		}
+
+		if (typeof (this.options.onNodeUnselected) === 'function') {
+			this.$element.on('nodeUnselected', this.options.onNodeUnselected);
+		}
+
+		if (typeof (this.options.onSearchComplete) === 'function') {
+			this.$element.on('searchComplete', this.options.onSearchComplete);
+		}
+
+		if (typeof (this.options.onSearchCleared) === 'function') {
+			this.$element.on('searchCleared', this.options.onSearchCleared);
+		}
+	};
+
+	/*
+		Recurse the tree structure and ensure all nodes have
+		valid initial states.  User defined states will be preserved.
+		For performance we also take this opportunity to
+		index nodes in a flattened structure
+	*/
+	Tree.prototype.setInitialStates = function (node, level) {
+
+		if (!node.nodes) return;
+		level += 1;
+
+		var parent = node;
+		var _this = this;
+		$.each(node.nodes, function checkStates(index, node) {
+
+			// nodeId : unique, incremental identifier
+			node.nodeId = _this.nodes.length;
+
+			// parentId : transversing up the tree
+			node.parentId = parent.nodeId;
+
+			// if not provided set selectable default value
+			if (!node.hasOwnProperty('selectable')) {
+				node.selectable = true;
+			}
+
+			// where provided we should preserve states
+			node.state = node.state || {};
+
+			// set checked state; unless set always false
+			if (!node.state.hasOwnProperty('checked')) {
+				node.state.checked = false;
+			}
+
+			// set enabled state; unless set always false
+			if (!node.state.hasOwnProperty('disabled')) {
+				node.state.disabled = false;
+			}
+
+			// set expanded state; if not provided based on levels
+			if (!node.state.hasOwnProperty('expanded')) {
+				if (!node.state.disabled &&
+						(level < _this.options.levels) &&
+						(node.nodes && node.nodes.length > 0)) {
+					node.state.expanded = true;
+				}
+				else {
+					node.state.expanded = false;
+				}
+			}
+
+			// set selected state; unless set always false
+			if (!node.state.hasOwnProperty('selected')) {
+				node.state.selected = false;
+			}
+
+			// index nodes in a flattened structure for use later
+			_this.nodes.push(node);
+
+			// recurse child nodes and transverse the tree
+			if (node.nodes) {
+				_this.setInitialStates(node, level);
+			}
+		});
+	};
+
+	Tree.prototype.clickHandler = function (event) {
+
+		if (!this.options.enableLinks) event.preventDefault();
+
+		var target = $(event.target);
+		var node = this.findNode(target);
+		if (!node || node.state.disabled) return;
+		
+		var classList = target.attr('class') ? target.attr('class').split(' ') : [];
+		if ((classList.indexOf('expand-icon') !== -1)) {
+
+			this.toggleExpandedState(node, _default.options);
+			this.render();
+		}
+		else if ((classList.indexOf('check-icon') !== -1)) {
+			
+			this.toggleCheckedState(node, _default.options);
+			this.render();
+		}
+		else {
+			
+			if (node.selectable) {
+				this.toggleSelectedState(node, _default.options);
+			} else {
+				this.toggleExpandedState(node, _default.options);
+			}
+
+			this.render();
+		}
+	};
+
+	// Looks up the DOM for the closest parent list item to retrieve the
+	// data attribute nodeid, which is used to lookup the node in the flattened structure.
+	Tree.prototype.findNode = function (target) {
+
+		var nodeId = target.closest('li.list-group-item').attr('data-nodeid');
+		var node = this.nodes[nodeId];
+
+		if (!node) {
+			console.log('Error: node does not exist');
+		}
+		return node;
+	};
+
+	Tree.prototype.toggleExpandedState = function (node, options) {
+		if (!node) return;
+		this.setExpandedState(node, !node.state.expanded, options);
+	};
+
+	Tree.prototype.setExpandedState = function (node, state, options) {
+
+		if (state === node.state.expanded) return;
+
+		if (state && node.nodes) {
+
+			// Expand a node
+			node.state.expanded = true;
+			if (!options.silent) {
+				this.$element.trigger('nodeExpanded', $.extend(true, {}, node));
+			}
+		}
+		else if (!state) {
+
+			// Collapse a node
+			node.state.expanded = false;
+			if (!options.silent) {
+				this.$element.trigger('nodeCollapsed', $.extend(true, {}, node));
+			}
+
+			// Collapse child nodes
+			if (node.nodes && !options.ignoreChildren) {
+				$.each(node.nodes, $.proxy(function (index, node) {
+					this.setExpandedState(node, false, options);
+				}, this));
+			}
+		}
+	};
+
+	Tree.prototype.toggleSelectedState = function (node, options) {
+		if (!node) return;
+		this.setSelectedState(node, !node.state.selected, options);
+	};
+
+	Tree.prototype.setSelectedState = function (node, state, options) {
+
+		if (state === node.state.selected) return;
+
+		if (state) {
+
+			// If multiSelect false, unselect previously selected
+			if (!this.options.multiSelect) {
+				$.each(this.findNodes('true', 'g', 'state.selected'), $.proxy(function (index, node) {
+					this.setSelectedState(node, false, options);
+				}, this));
+			}
+
+			// Continue selecting node
+			node.state.selected = true;
+			if (!options.silent) {
+				this.$element.trigger('nodeSelected', $.extend(true, {}, node));
+			}
+		}
+		else {
+
+			// Unselect node
+			node.state.selected = false;
+			if (!options.silent) {
+				this.$element.trigger('nodeUnselected', $.extend(true, {}, node));
+			}
+		}
+	};
+
+	Tree.prototype.toggleCheckedState = function (node, options) {
+		if (!node) return;
+		this.setCheckedState(node, !node.state.checked, options);
+	};
+
+	Tree.prototype.setCheckedState = function (node, state, options) {
+
+		if (state === node.state.checked) return;
+
+		if (state) {
+
+			// Check node
+			node.state.checked = true;
+
+			if (!options.silent) {
+				this.$element.trigger('nodeChecked', $.extend(true, {}, node));
+			}
+		}
+		else {
+
+			// Uncheck node
+			node.state.checked = false;
+			if (!options.silent) {
+				this.$element.trigger('nodeUnchecked', $.extend(true, {}, node));
+			}
+		}
+	};
+
+	Tree.prototype.setDisabledState = function (node, state, options) {
+
+		if (state === node.state.disabled) return;
+
+		if (state) {
+
+			// Disable node
+			node.state.disabled = true;
+
+			// Disable all other states
+			this.setExpandedState(node, false, options);
+			this.setSelectedState(node, false, options);
+			this.setCheckedState(node, false, options);
+
+			if (!options.silent) {
+				this.$element.trigger('nodeDisabled', $.extend(true, {}, node));
+			}
+		}
+		else {
+
+			// Enabled node
+			node.state.disabled = false;
+			if (!options.silent) {
+				this.$element.trigger('nodeEnabled', $.extend(true, {}, node));
+			}
+		}
+	};
+
+	Tree.prototype.render = function () {
+
+		if (!this.initialized) {
+
+			// Setup first time only components
+			this.$element.addClass(pluginName);
+			this.$wrapper = $(this.template.list);
+
+			this.injectStyle();
+
+			this.initialized = true;
+		}
+
+		this.$element.empty().append(this.$wrapper.empty());
+
+		// Build tree
+		this.buildTree(this.tree, 0);
+	};
+
+	// Starting from the root node, and recursing down the
+	// structure we build the tree one node at a time
+	Tree.prototype.buildTree = function (nodes, level) {
+
+		if (!nodes) return;
+		level += 1;
+
+		var _this = this;
+		$.each(nodes, function addNodes(id, node) {
+
+			var treeItem = $(_this.template.item)
+				.addClass('node-' + _this.elementId)
+				.addClass(node.state.checked ? 'node-checked' : '')
+				.addClass(node.state.disabled ? 'node-disabled': '')
+				.addClass(node.state.selected ? 'node-selected' : '')
+				.addClass(node.searchResult ? 'search-result' : '') 
+				.attr('data-nodeid', node.nodeId)
+				.attr('style', _this.buildStyleOverride(node));
+
+			// Add indent/spacer to mimic tree structure
+			for (var i = 0; i < (level - 1); i++) {
+				treeItem.append(_this.template.indent);
+			}
+
+			// Add expand, collapse or empty spacer icons
+			var classList = [];
+			if (node.nodes) {
+				classList.push('expand-icon');
+				if (node.state.expanded) {
+					classList.push(_this.options.collapseIcon);
+				}
+				else {
+					classList.push(_this.options.expandIcon);
+				}
+			}
+			else {
+				classList.push(_this.options.emptyIcon);
+			}
+
+			treeItem
+				.append($(_this.template.icon)
+					.addClass(classList.join(' '))
+				);
+
+
+			// Add node icon
+			if (_this.options.showIcon) {
+				
+				var classList = ['node-icon'];
+
+				classList.push(node.icon || _this.options.nodeIcon);
+				if (node.state.selected) {
+					classList.pop();
+					classList.push(node.selectedIcon || _this.options.selectedIcon || 
+									node.icon || _this.options.nodeIcon);
+				}
+
+				treeItem
+					.append($(_this.template.icon)
+						.addClass(classList.join(' '))
+					);
+			}
+
+			// Add check / unchecked icon
+			if (_this.options.showCheckbox) {
+
+				var classList = ['check-icon'];
+				if (node.state.checked) {
+					classList.push(_this.options.checkedIcon); 
+				}
+				else {
+					classList.push(_this.options.uncheckedIcon);
+				}
+
+				treeItem
+					.append($(_this.template.icon)
+						.addClass(classList.join(' '))
+					);
+			}
+
+			// Add text
+			if (_this.options.enableLinks) {
+				// Add hyperlink
+				treeItem
+					.append($(_this.template.link)
+						.attr('href', node.href)
+						.append(node.text)
+					);
+			}
+			else {
+				// otherwise just text
+				treeItem
+					.append(node.text);
+			}
+
+			// Add tags as badges
+			if (_this.options.showTags && node.tags) {
+				$.each(node.tags, function addTag(id, tag) {
+					treeItem
+						.append($(_this.template.badge)
+							.append(tag)
+						);
+				});
+			}
+
+			// Add item to the tree
+			_this.$wrapper.append(treeItem);
+
+			// Recursively add child ndoes
+			if (node.nodes && node.state.expanded && !node.state.disabled) {
+				return _this.buildTree(node.nodes, level);
+			}
+		});
+	};
+
+	// Define any node level style override for
+	// 1. selectedNode
+	// 2. node|data assigned color overrides
+	Tree.prototype.buildStyleOverride = function (node) {
+
+		if (node.state.disabled) return '';
+
+		var color = node.color;
+		var backColor = node.backColor;
+
+		if (this.options.highlightSelected && node.state.selected) {
+			if (this.options.selectedColor) {
+				color = this.options.selectedColor;
+			}
+			if (this.options.selectedBackColor) {
+				backColor = this.options.selectedBackColor;
+			}
+		}
+
+		if (this.options.highlightSearchResults && node.searchResult && !node.state.disabled) {
+			if (this.options.searchResultColor) {
+				color = this.options.searchResultColor;
+			}
+			if (this.options.searchResultBackColor) {
+				backColor = this.options.searchResultBackColor;
+			}
+		}
+
+		return 'color:' + color +
+			';background-color:' + backColor + ';';
+	};
+
+	// Add inline style into head
+	Tree.prototype.injectStyle = function () {
+
+		if (this.options.injectStyle && !document.getElementById(this.styleId)) {
+			$('<style type="text/css" id="' + this.styleId + '"> ' + this.buildStyle() + ' </style>').appendTo('head');
+		}
+	};
+
+	// Construct trees style based on user options
+	Tree.prototype.buildStyle = function () {
+
+		var style = '.node-' + this.elementId + '{';
+
+		if (this.options.color) {
+			style += 'color:' + this.options.color + ';';
+		}
+
+		if (this.options.backColor) {
+			style += 'background-color:' + this.options.backColor + ';';
+		}
+
+		if (!this.options.showBorder) {
+			style += 'border:none;';
+		}
+		else if (this.options.borderColor) {
+			style += 'border:1px solid ' + this.options.borderColor + ';';
+		}
+		style += '}';
+
+		if (this.options.onhoverColor) {
+			style += '.node-' + this.elementId + ':not(.node-disabled):hover{' +
+				'background-color:' + this.options.onhoverColor + ';' +
+			'}';
+		}
+
+		return this.css + style;
+	};
+
+	Tree.prototype.template = {
+		list: '<ul class="list-group"></ul>',
+		item: '<li class="list-group-item"></li>',
+		indent: '<span class="indent"></span>',
+		icon: '<span class="icon"></span>',
+		link: '<a href="#" style="color:inherit;"></a>',
+		badge: '<span class="badge"></span>'
+	};
+
+	Tree.prototype.css = '.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}'
+
+
+	/**
+		Returns a single node object that matches the given node id.
+		@param {Number} nodeId - A node's unique identifier
+		@return {Object} node - Matching node
+	*/
+	Tree.prototype.getNode = function (nodeId) {
+		return this.nodes[nodeId];
+	};
+
+	/**
+		Returns the parent node of a given node, if valid otherwise returns undefined.
+		@param {Object|Number} identifier - A valid node or node id
+		@returns {Object} node - The parent node
+	*/
+	Tree.prototype.getParent = function (identifier) {
+		var node = this.identifyNode(identifier);
+		return this.nodes[node.parentId];
+	};
+
+	/**
+		Returns an array of sibling nodes for a given node, if valid otherwise returns undefined.
+		@param {Object|Number} identifier - A valid node or node id
+		@returns {Array} nodes - Sibling nodes
+	*/
+	Tree.prototype.getSiblings = function (identifier) {
+		var node = this.identifyNode(identifier);
+		var parent = this.getParent(node);
+		var nodes = parent ? parent.nodes : this.tree;
+		return nodes.filter(function (obj) {
+				return obj.nodeId !== node.nodeId;
+			});
+	};
+
+	/**
+		Returns an array of selected nodes.
+		@returns {Array} nodes - Selected nodes
+	*/
+	Tree.prototype.getSelected = function () {
+		return this.findNodes('true', 'g', 'state.selected');
+	};
+
+	/**
+		Returns an array of unselected nodes.
+		@returns {Array} nodes - Unselected nodes
+	*/
+	Tree.prototype.getUnselected = function () {
+		return this.findNodes('false', 'g', 'state.selected');
+	};
+
+	/**
+		Returns an array of expanded nodes.
+		@returns {Array} nodes - Expanded nodes
+	*/
+	Tree.prototype.getExpanded = function () {
+		return this.findNodes('true', 'g', 'state.expanded');
+	};
+
+	/**
+		Returns an array of collapsed nodes.
+		@returns {Array} nodes - Collapsed nodes
+	*/
+	Tree.prototype.getCollapsed = function () {
+		return this.findNodes('false', 'g', 'state.expanded');
+	};
+
+	/**
+		Returns an array of checked nodes.
+		@returns {Array} nodes - Checked nodes
+	*/
+	Tree.prototype.getChecked = function () {
+		return this.findNodes('true', 'g', 'state.checked');
+	};
+
+	/**
+		Returns an array of unchecked nodes.
+		@returns {Array} nodes - Unchecked nodes
+	*/
+	Tree.prototype.getUnchecked = function () {
+		return this.findNodes('false', 'g', 'state.checked');
+	};
+
+	/**
+		Returns an array of disabled nodes.
+		@returns {Array} nodes - Disabled nodes
+	*/
+	Tree.prototype.getDisabled = function () {
+		return this.findNodes('true', 'g', 'state.disabled');
+	};
+
+	/**
+		Returns an array of enabled nodes.
+		@returns {Array} nodes - Enabled nodes
+	*/
+	Tree.prototype.getEnabled = function () {
+		return this.findNodes('false', 'g', 'state.disabled');
+	};
+
+
+	/**
+		Set a node state to selected
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.selectNode = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setSelectedState(node, true, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Set a node state to unselected
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.unselectNode = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setSelectedState(node, false, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Toggles a node selected state; selecting if unselected, unselecting if selected.
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.toggleNodeSelected = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.toggleSelectedState(node, options);
+		}, this));
+
+		this.render();
+	};
+
+
+	/**
+		Collapse all tree nodes
+		@param {optional Object} options
+	*/
+	Tree.prototype.collapseAll = function (options) {
+		var identifiers = this.findNodes('true', 'g', 'state.expanded');
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setExpandedState(node, false, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Collapse a given tree node
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.collapseNode = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setExpandedState(node, false, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Expand all tree nodes
+		@param {optional Object} options
+	*/
+	Tree.prototype.expandAll = function (options) {
+		options = $.extend({}, _default.options, options);
+
+		if (options && options.levels) {
+			this.expandLevels(this.tree, options.levels, options);
+		}
+		else {
+			var identifiers = this.findNodes('false', 'g', 'state.expanded');
+			this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+				this.setExpandedState(node, true, options);
+			}, this));
+		}
+
+		this.render();
+	};
+
+	/**
+		Expand a given tree node
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.expandNode = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setExpandedState(node, true, options);
+			if (node.nodes && (options && options.levels)) {
+				this.expandLevels(node.nodes, options.levels-1, options);
+			}
+		}, this));
+
+		this.render();
+	};
+
+	Tree.prototype.expandLevels = function (nodes, level, options) {
+		options = $.extend({}, _default.options, options);
+
+		$.each(nodes, $.proxy(function (index, node) {
+			this.setExpandedState(node, (level > 0) ? true : false, options);
+			if (node.nodes) {
+				this.expandLevels(node.nodes, level-1, options);
+			}
+		}, this));
+	};
+
+	/**
+		Reveals a given tree node, expanding the tree from node to root.
+		@param {Object|Number|Array} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.revealNode = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			var parentNode = this.getParent(node);
+			while (parentNode) {
+				this.setExpandedState(parentNode, true, options);
+				parentNode = this.getParent(parentNode);
+			};
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Toggles a nodes expanded state; collapsing if expanded, expanding if collapsed.
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.toggleNodeExpanded = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.toggleExpandedState(node, options);
+		}, this));
+		
+		this.render();
+	};
+
+
+	/**
+		Check all tree nodes
+		@param {optional Object} options
+	*/
+	Tree.prototype.checkAll = function (options) {
+		var identifiers = this.findNodes('false', 'g', 'state.checked');
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setCheckedState(node, true, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Check a given tree node
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.checkNode = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setCheckedState(node, true, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Uncheck all tree nodes
+		@param {optional Object} options
+	*/
+	Tree.prototype.uncheckAll = function (options) {
+		var identifiers = this.findNodes('true', 'g', 'state.checked');
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setCheckedState(node, false, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Uncheck a given tree node
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.uncheckNode = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setCheckedState(node, false, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Toggles a nodes checked state; checking if unchecked, unchecking if checked.
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.toggleNodeChecked = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.toggleCheckedState(node, options);
+		}, this));
+
+		this.render();
+	};
+
+
+	/**
+		Disable all tree nodes
+		@param {optional Object} options
+	*/
+	Tree.prototype.disableAll = function (options) {
+		var identifiers = this.findNodes('false', 'g', 'state.disabled');
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setDisabledState(node, true, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Disable a given tree node
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.disableNode = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setDisabledState(node, true, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Enable all tree nodes
+		@param {optional Object} options
+	*/
+	Tree.prototype.enableAll = function (options) {
+		var identifiers = this.findNodes('true', 'g', 'state.disabled');
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setDisabledState(node, false, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Enable a given tree node
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.enableNode = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setDisabledState(node, false, options);
+		}, this));
+
+		this.render();
+	};
+
+	/**
+		Toggles a nodes disabled state; disabling is enabled, enabling if disabled.
+		@param {Object|Number} identifiers - A valid node, node id or array of node identifiers
+		@param {optional Object} options
+	*/
+	Tree.prototype.toggleNodeDisabled = function (identifiers, options) {
+		this.forEachIdentifier(identifiers, options, $.proxy(function (node, options) {
+			this.setDisabledState(node, !node.state.disabled, options);
+		}, this));
+
+		this.render();
+	};
+
+
+	/**
+		Common code for processing multiple identifiers
+	*/
+	Tree.prototype.forEachIdentifier = function (identifiers, options, callback) {
+
+		options = $.extend({}, _default.options, options);
+
+		if (!(identifiers instanceof Array)) {
+			identifiers = [identifiers];
+		}
+
+		$.each(identifiers, $.proxy(function (index, identifier) {
+			callback(this.identifyNode(identifier), options);
+		}, this));	
+	};
+
+	/*
+		Identifies a node from either a node id or object
+	*/
+	Tree.prototype.identifyNode = function (identifier) {
+		return ((typeof identifier) === 'number') ?
+						this.nodes[identifier] :
+						identifier;
+	};
+
+	/**
+		Searches the tree for nodes (text) that match given criteria
+		@param {String} pattern - A given string to match against
+		@param {optional Object} options - Search criteria options
+		@return {Array} nodes - Matching nodes
+	*/
+	Tree.prototype.search = function (pattern, options) {
+		options = $.extend({}, _default.searchOptions, options);
+
+		this.clearSearch({ render: false });
+
+		var results = [];
+		if (pattern && pattern.length > 0) {
+
+			if (options.exactMatch) {
+				pattern = '^' + pattern + '$';
+			}
+
+			var modifier = 'g';
+			if (options.ignoreCase) {
+				modifier += 'i';
+			}
+
+			results = this.findNodes(pattern, modifier);
+
+			// Add searchResult property to all matching nodes
+			// This will be used to apply custom styles
+			// and when identifying result to be cleared
+			$.each(results, function (index, node) {
+				node.searchResult = true;
+			})
+		}
+
+		// If revealResults, then render is triggered from revealNode
+		// otherwise we just call render.
+		if (options.revealResults) {
+			this.revealNode(results);
+		}
+		else {
+			this.render();
+		}
+
+		this.$element.trigger('searchComplete', $.extend(true, {}, results));
+
+		return results;
+	};
+
+	/**
+		Clears previous search results
+	*/
+	Tree.prototype.clearSearch = function (options) {
+
+		options = $.extend({}, { render: true }, options);
+
+		var results = $.each(this.findNodes('true', 'g', 'searchResult'), function (index, node) {
+			node.searchResult = false;
+		});
+
+		if (options.render) {
+			this.render();	
+		}
+		
+		this.$element.trigger('searchCleared', $.extend(true, {}, results));
+	};
+
+	/**
+		Find nodes that match a given criteria
+		@param {String} pattern - A given string to match against
+		@param {optional String} modifier - Valid RegEx modifiers
+		@param {optional String} attribute - Attribute to compare pattern against
+		@return {Array} nodes - Nodes that match your criteria
+	*/
+	Tree.prototype.findNodes = function (pattern, modifier, attribute) {
+
+		modifier = modifier || 'g';
+		attribute = attribute || 'text';
+
+		var _this = this;
+		return $.grep(this.nodes, function (node) {
+			var val = _this.getNodeValue(node, attribute);
+			if (typeof val === 'string') {
+				return val.match(new RegExp(pattern, modifier));
+			}
+		});
+	};
+
+	/**
+		Recursive find for retrieving nested attributes values
+		All values are return as strings, unless invalid
+		@param {Object} obj - Typically a node, could be any object
+		@param {String} attr - Identifies an object property using dot notation
+		@return {String} value - Matching attributes string representation
+	*/
+	Tree.prototype.getNodeValue = function (obj, attr) {
+		var index = attr.indexOf('.');
+		if (index > 0) {
+			var _obj = obj[attr.substring(0, index)];
+			var _attr = attr.substring(index + 1, attr.length);
+			return this.getNodeValue(_obj, _attr);
+		}
+		else {
+			if (obj.hasOwnProperty(attr)) {
+				return obj[attr].toString();
+			}
+			else {
+				return undefined;
+			}
+		}
+	};
+
+	var logError = function (message) {
+		if (window.console) {
+			window.console.error(message);
+		}
+	};
+
+	// Prevent against multiple instantiations,
+	// handle updates and method calls
+	$.fn[pluginName] = function (options, args) {
+
+		var result;
+
+		this.each(function () {
+			var _this = $.data(this, pluginName);
+			if (typeof options === 'string') {
+				if (!_this) {
+					logError('Not initialized, can not call method : ' + options);
+				}
+				else if (!$.isFunction(_this[options]) || options.charAt(0) === '_') {
+					logError('No such method : ' + options);
+				}
+				else {
+					if (!(args instanceof Array)) {
+						args = [ args ];
+					}
+					result = _this[options].apply(_this, args);
+				}
+			}
+			else if (typeof options === 'boolean') {
+				result = _this;
+			}
+			else {
+				$.data(this, pluginName, new Tree(this, $.extend(true, {}, options)));
+			}
+		});
+
+		return result || this;
+	};
+
+})(jQuery, window, document);

+ 0 - 427
static/js/colResizable-1.6.js

@@ -1,427 +0,0 @@
-/**
-               _ _____           _          _     _      
-              | |  __ \         (_)        | |   | |     
-      ___ ___ | | |__) |___  ___ _ ______ _| |__ | | ___ 
-     / __/ _ \| |  _  // _ \/ __| |_  / _` | '_ \| |/ _ \
-    | (_| (_) | | | \ \  __/\__ \ |/ / (_| | |_) | |  __/
-     \___\___/|_|_|  \_\___||___/_/___\__,_|_.__/|_|\___|
-	 
-	v1.7 - jQuery plugin created by Alvaro Prieto Lauroba
-	
-	Licences: MIT & GPL
-	Feel free to use or modify this plugin as far as my full name is kept	
-*/
-
-(function($){ 	
-	
-	//IE8 Polyfill
-	if(!Array.indexOf) { Array.prototype.indexOf = function(obj) { for(var i=0; i<this.length;i++){if(this[i]==obj){return i;}} return -1; }}
-	
-	var d = $(document); 		//window object
-	var h = $("head");			//head object
-	var drag = null;			//reference to the current grip that is being dragged
-	var tables = {};			//object of the already processed tables (table.id as key)
-	var	count = 0;				//internal count to create unique IDs when needed.	
-	
-	//common strings for packing
-	var ID = "id";	
-	var PX = "px";
-	var SIGNATURE ="JColResizer";
-    var FLEX = "JCLRFlex";
-	
-	//short-cuts
-	var I = parseInt;
-	var M = Math;
-	var ie = navigator.userAgent.indexOf('Trident/4.0')>0;
-	var S;
-    var pad = ""
-    
-	
-	//append required CSS rules  
-    h.append("<style type='text/css'>  .JColResizer{table-layout:fixed;} .JColResizer > tbody > tr > td, .JColResizer > tbody > tr > th{overflow:hidden}  .JPadding > tbody > tr > td, .JPadding > tbody > tr > th{padding-left:0!important; padding-right:0!important;} .JCLRgrips{ height:0px; position:relative;} .JCLRgrip{margin-left:-5px; position:absolute; z-index:5; } .JCLRgrip .JColResizer{position:absolute;background-color:red;filter:alpha(opacity=1);opacity:0;width:10px;height:100%;cursor: col-resize;top:0px} .JCLRLastGrip{position:absolute; width:1px; } .JCLRgripDrag{ border-left:1px dotted black;	} .JCLRFlex{width:auto!important;} .JCLRgrip.JCLRdisabledGrip .JColResizer{cursor:default; display:none;}</style>");
-
-	
-	/**
-	 * Function to allow column resizing for table objects. It is the starting point to apply the plugin.
-	 * @param {DOM node} tb - reference to the DOM table object to be enhanced
-	 * @param {Object} options	- some customization values
-	 */
-	var init = function( tb, options){	
-		var t = $(tb);				    //the table object is wrapped
-        t.opt = options;                //each table has its own options available at anytime
-        t.mode = options.resizeMode;    //shortcuts
-        t.dc = t.opt.disabledColumns;
-        if(t.opt.removePadding) t.addClass("JPadding");
-
-		try {
-			if (t.opt.useLocalStorage) {
-				S = localStorage;
-			} else {
-				S = sessionStorage;
-			}
-		} catch(e) {}	//Firefox crashes when executed as local file system
-
-		if(t.opt.disable) return destroy(t);				//the user is asking to destroy a previously colResized table
-		var	id = t.id = t.attr(ID) || SIGNATURE+count++;	//its id is obtained, if null new one is generated		
-		t.p = t.opt.postbackSafe; 							//short-cut to detect postback safe 		
-		if(!t.is("table") || tables[id] && !t.opt.partialRefresh) return; 		//if the object is not a table or if it was already processed then it is ignored.
-		if (t.opt.hoverCursor !== 'col-resize') h.append("<style type='text/css'>.JCLRgrip .JColResizer:hover{cursor:"+ t.opt.hoverCursor +"!important}</style>");  //if hoverCursor has been set, append the style
-        t.addClass(SIGNATURE).attr(ID, id).before('<div class="JCLRgrips"/>');	//the grips container object is added. Signature class forces table rendering in fixed-layout mode to prevent column's min-width
-		t.g = []; t.c = []; t.w = t.width(); t.gc = t.prev(); t.f=t.opt.fixed;	//t.c and t.g are arrays of columns and grips respectively				
-		if(options.marginLeft) t.gc.css("marginLeft", options.marginLeft);  	//if the table contains margins, it must be specified
-		if(options.marginRight) t.gc.css("marginRight", options.marginRight);  	//since there is no (direct) way to obtain margin values in its original units (%, em, ...)
-		t.cs = I(ie? tb.cellSpacing || tb.currentStyle.borderSpacing :t.css('border-spacing'))||2;	//table cellspacing (not even jQuery is fully cross-browser)
-		t.b  = I(ie? tb.border || tb.currentStyle.borderLeftWidth :t.css('border-left-width'))||1;	//outer border width (again cross-browser issues)
-		// if(!(tb.style.width || tb.width)) t.width(t.width()); //I am not an IE fan at all, but it is a pity that only IE has the currentStyle attribute working as expected. For this reason I can not check easily if the table has an explicit width or if it is rendered as "auto"
-		tables[id] = t; 	//the table object is stored using its id as key	
-		createGrips(t);		//grips are created 
-	
-	};
-
-
-	/**
-	 * This function allows to remove any enhancements performed by this plugin on a previously processed table.
-	 * @param {jQuery ref} t - table object
-	 */
-	var destroy = function(t){
-		var id=t.attr(ID), t=tables[id];		//its table object is found
-		if(!t||!t.is("table")) return;			//if none, then it wasn't processed	 
-		t.removeClass(SIGNATURE+" "+FLEX).gc.remove();	//class and grips are removed
-		delete tables[id];						//clean up data
-	};
-
-
-	/**
-	 * Function to create all the grips associated with the table given by parameters 
-	 * @param {jQuery ref} t - table object
-	 */
-	var createGrips = function(t){	
-	
-        var th = t.find(">thead>tr:first>th,>thead>tr:first>td"); //table headers are obtained
-		if(!th.length) th = t.find(">tbody>tr:first>th,>tr:first>th,>tbody>tr:first>td, >tr:first>td");	 //but headers can also be included in different ways
-		th = th.filter(":visible");					//filter invisible columns
-		t.cg = t.find("col"); 						//a table can also contain a colgroup with col elements		
-		t.ln = th.length;							//table length is stored	
-		if(t.p && S && S[t.id])memento(t,th);		//if 'postbackSafe' is enabled and there is data for the current table, its coloumn layout is restored
-		th.each(function(i){						//iterate through the table column headers			
-			var c = $(this); 						//jquery wrap for the current column		
-            var dc = t.dc.indexOf(i)!=-1;           //is this a disabled column?
-			var g = $(t.gc.append('<div class="JCLRgrip"></div>')[0].lastChild); //add the visual node to be used as grip
-            g.append(dc ? "": t.opt.gripInnerHtml).append('<div class="'+SIGNATURE+'"></div>');
-            if(i == t.ln-1){                        //if the current grip is the las one 
-                g.addClass("JCLRLastGrip");         //add a different css class to stlye it in a different way if needed
-                if(t.f) g.html("");                 //if the table resizing mode is set to fixed, the last grip is removed since table with can not change
-            }
-            g.bind('touchstart mousedown', onGripMouseDown); //bind the mousedown event to start dragging 
-            
-            if (!dc){ 
-                //if normal column bind the mousedown event to start dragging, if disabled then apply its css class
-                g.removeClass('JCLRdisabledGrip').bind('touchstart mousedown', onGripMouseDown);      
-            }else{
-                g.addClass('JCLRdisabledGrip'); 
-            }
-
-			g.t = t; g.i = i; g.c = c;	c.w =c.width();		//some values are stored in the grip's node data as shortcut
-			t.g.push(g); t.c.push(c);						//the current grip and column are added to its table object
-			c.width(c.w).removeAttr("width");				//the width of the column is converted into pixel-based measurements
-			g.data(SIGNATURE, {i:i, t:t.attr(ID), last: i == t.ln-1});	 //grip index and its table name are stored in the HTML 												
-		}); 	
-		t.cg.removeAttr("width");	//remove the width attribute from elements in the colgroup 
-
-		t.find('td, th').not(th).not('table th, table td').each(function(){  
-			$(this).removeAttr('width');	//the width attribute is removed from all table cells which are not nested in other tables and dont belong to the header
-		});		
-        if(!t.f){
-            t.removeAttr('width').addClass(FLEX); //if not fixed, let the table grow as needed
-        }
-        syncGrips(t); 				//the grips are positioned according to the current table layout			
-        //there is a small problem, some cells in the table could contain dimension values interfering with the 
-        //width value set by this plugin. Those values are removed
-		
-	};
-	
-    
-	/**
-	 * Function to allow the persistence of columns dimensions after a browser postback. It is based in
-	 * the HTML5 sessionStorage object, which can be emulated for older browsers using sessionstorage.js
-	 * @param {jQuery ref} t - table object
-	 * @param {jQuery ref} th - reference to the first row elements (only set in deserialization)
-	 */
-	var memento = function(t, th){ 
-		var w,m=0,i=0,aux =[],tw;
-		if(th){										//in deserialization mode (after a postback)
-			t.cg.removeAttr("width");
-			if(t.opt.flush){ S[t.id] =""; return;} 	//if flush is activated, stored data is removed
-			w = S[t.id].split(";");					//column widths is obtained
-			tw = w[t.ln+1];
-            if(!t.f && tw){							//if not fixed and table width data available its size is restored
-                t.width(tw*=1);
-                if(t.opt.overflow) {				//if overfolw flag is set, restore table width also as table min-width
-                    t.css('min-width', tw + PX);
-                    t.w = tw;
-                }
-            }
-			for(;i<t.ln;i++){						//for each column
-				aux.push(100*w[i]/w[t.ln]+"%"); 	//width is stored in an array since it will be required again a couple of lines ahead
-				th.eq(i).css("width", aux[i] ); 	//each column width in % is restored
-			}			
-			for(i=0;i<t.ln;i++)
-				t.cg.eq(i).css("width", aux[i]);	//this code is required in order to create an inline CSS rule with higher precedence than an existing CSS class in the "col" elements
-		}else{							//in serialization mode (after resizing a column)
-			S[t.id] ="";				//clean up previous data
-			for(;i < t.c.length; i++){	//iterate through columns
-				w = t.c[i].width();		//width is obtained
-				S[t.id] += w+";";		//width is appended to the sessionStorage object using ID as key
-				m+=w;					//carriage is updated to obtain the full size used by columns
-			}
-			S[t.id]+=m;							//the last item of the serialized string is the table's active area (width), 
-												//to be able to obtain % width value of each columns while deserializing
-			if(!t.f) S[t.id] += ";"+t.width(); 	//if not fixed, table width is stored
-		}	
-	};
-	
-	
-	/**
-	 * Function that places each grip in the correct position according to the current table layout	 
-	 * @param {jQuery ref} t - table object
-	 */
-	var syncGrips = function (t){	
-		t.gc.width(t.w);			//the grip's container width is updated				
-		for(var i=0; i<t.ln; i++){	//for each column
-			var c = t.c[i]; 			
-			t.g[i].css({			//height and position of the grip is updated according to the table layout
-				left: c.offset().left - t.offset().left + c.outerWidth(false) + t.cs / 2 + PX,
-				height: t.opt.headerOnly? t.c[0].outerHeight(false) : t.outerHeight(false)				
-			});			
-		} 	
-	};
-	
-	
-	
-	/**
-	* This function updates column's width according to the horizontal position increment of the grip being
-	* dragged. The function can be called while dragging if liveDragging is enabled and also from the onGripDragOver
-	* event handler to synchronize grip's position with their related columns.
-	* @param {jQuery ref} t - table object
-	* @param {number} i - index of the grip being dragged
-	* @param {bool} isOver - to identify when the function is being called from the onGripDragOver event	
-	*/
-	var syncCols = function(t,i,isOver){
-		var inc = drag.x-drag.l, c = t.c[i], c2 = t.c[i+1]; 			
-		var w = c.w + inc;	var w2= c2.w- inc;	//their new width is obtained					
-		c.width( w + PX);			
-		t.cg.eq(i).width( w + PX); 
-        if(t.f){ //if fixed mode
-            c2.width(w2 + PX);
-            t.cg.eq(i+1).width( w2 + PX);
-        }else if(t.opt.overflow) {				//if overflow is set, incriment min-width to force overflow
-            t.css('min-width', t.w + inc);
-        }
-		if(isOver){
-            c.w=w; 
-            c2.w= t.f ? w2 : c2.w;
-        }
-	};
-
-	
-	/**
-	* This function updates all columns width according to its real width. It must be taken into account that the 
-	* sum of all columns can exceed the table width in some cases (if fixed is set to false and table has some kind 
-	* of max-width).
-	* @param {jQuery ref} t - table object	
-	*/
-	var applyBounds = function(t){
-        var w = $.map(t.c, function(c){			//obtain real widths
-            return c.width();
-        });
-        t.width(t.w = t.width()).removeClass(FLEX);	//prevent table width changes
-        $.each(t.c, function(i,c){
-            c.width(w[i]).w = w[i];				//set column widths applying bounds (table's max-width)
-        });
-		t.addClass(FLEX);						//allow table width changes
-	};
-	
-	
-	/**
-	 * Event handler used while dragging a grip. It checks if the next grip's position is valid and updates it. 
-	 * @param {event} e - mousemove event binded to the window object
-	 */
-	var onGripDrag = function(e){	
-		if(!drag) return; 
-        var t = drag.t;		//table object reference 
-        var oe = e.originalEvent.touches;
-        var ox = oe ? oe[0].pageX : e.pageX;    //original position (touch or mouse)
-        var x =  ox - drag.ox + drag.l;	        //next position according to horizontal mouse position increment
-		var mw = t.opt.minWidth, i = drag.i ;	//cell's min width
-		var l = t.cs*1.5 + mw + t.b;
-        var last = i == t.ln-1;                 			//check if it is the last column's grip (usually hidden)
-        var min = i? t.g[i-1].position().left+t.cs+mw: l;	//min position according to the contiguous cells
-		var max = t.f ? 	//fixed mode?
-			i == t.ln-1? 
-				t.w-l: 
-				t.g[i+1].position().left-t.cs-mw:
-			Infinity; 								//max position according to the contiguous cells 
-		x = M.max(min, M.min(max, x));				//apply bounding		
-		drag.x = x;	 drag.css("left",  x + PX); 	//apply position increment	
-        if(last){									//if it is the last grip
-            var c = t.c[drag.i];					//width of the last column is obtained
-			drag.w = c.w + x- drag.l;         
-        }              
-		if(t.opt.liveDrag){ 			//if liveDrag is enabled
-			if(last){
-			    c.width(drag.w);
-                if(!t.f && t.opt.overflow){			//if overflow is set, incriment min-width to force overflow
-                   t.css('min-width', t.w + x - drag.l);
-                }else {
-                    t.w = t.width();
-                }
-			}else{
-				syncCols(t,i); 			//columns are synchronized
-			}
-			syncGrips(t);
-			var cb = t.opt.onDrag;							//check if there is an onDrag callback
-			if (cb) { e.currentTarget = t[0]; cb(e); }		//if any, it is fired			
-		}
-		return false; 	//prevent text selection while dragging				
-	};
-	
-
-	/**
-	 * Event handler fired when the dragging is over, updating table layout
-     * @param {event} e - grip's drag over event
-	 */
-	var onGripDragOver = function(e){	
-		
-		d.unbind('touchend.'+SIGNATURE+' mouseup.'+SIGNATURE).unbind('touchmove.'+SIGNATURE+' mousemove.'+SIGNATURE);
-		$("head :last-child").remove(); 				//remove the dragging cursor style	
-		if(!drag) return;
-		drag.removeClass(drag.t.opt.draggingClass);		//remove the grip's dragging css-class
-        if (!(drag.x - drag.l == 0)) {
-            var t = drag.t;
-            var cb = t.opt.onResize; 	    //get some values	
-            var i = drag.i;                 //column index
-            var last = i == t.ln-1;         //check if it is the last column's grip (usually hidden)
-            var c = t.g[i].c;               //the column being dragged
-            if(last){
-                c.width(drag.w);
-                c.w = drag.w;
-            }else{
-                syncCols(t, i, true);	//the columns are updated
-            }
-            if(!t.f) applyBounds(t);	//if not fixed mode, then apply bounds to obtain real width values
-            syncGrips(t);				//the grips are updated
-            if (cb) { e.currentTarget = t[0]; cb(e); }	//if there is a callback function, it is fired
-            if(t.p && S) memento(t); 	//if postbackSafe is enabled and there is sessionStorage support, the new layout is serialized and stored
-        }
-		drag = null;   //since the grip's dragging is over									
-	};	
-	
-	
-	/**
-	 * Event handler fired when the grip's dragging is about to start. Its main goal is to set up events 
-	 * and store some values used while dragging.
-     * @param {event} e - grip's mousedown event
-	 */
-	var onGripMouseDown = function(e){
-		var o = $(this).data(SIGNATURE);			//retrieve grip's data
-		var t = tables[o.t],  g = t.g[o.i];			//shortcuts for the table and grip objects
-        var oe = e.originalEvent.touches;           //touch or mouse event?
-        g.ox = oe? oe[0].pageX: e.pageX;            //the initial position is kept
-		g.l = g.position().left;
-        g.x = g.l;
-        
-		d.bind('touchmove.'+SIGNATURE+' mousemove.'+SIGNATURE, onGripDrag ).bind('touchend.'+SIGNATURE+' mouseup.'+SIGNATURE, onGripDragOver);	//mousemove and mouseup events are bound
-		h.append("<style type='text/css'>*{cursor:"+ t.opt.dragCursor +"!important}</style>"); 	//change the mouse cursor
-		g.addClass(t.opt.draggingClass); 	//add the dragging class (to allow some visual feedback)				
-		drag = g;							//the current grip is stored as the current dragging object
-		if(t.c[o.i].l) for(var i=0,c; i<t.ln; i++){ c=t.c[i]; c.l = false; c.w= c.width(); } 	//if the colum is locked (after browser resize), then c.w must be updated		
-		return false; 	//prevent text selection
-	};
-    
-    
-	/**
-	 * Event handler fired when the browser is resized. The main purpose of this function is to update
-	 * table layout according to the browser's size synchronizing related grips 
-	 */
-	var onResize = function(){
-		for(var t in tables){
-            if( tables.hasOwnProperty( t ) ) {
-                t = tables[t];
-                var i, mw=0;
-                t.removeClass(SIGNATURE);   //firefox doesn't like layout-fixed in some cases
-                if (t.f) {                  //in fixed mode
-                    t.w = t.width();        //its new width is kept
-                    for(i=0; i<t.ln; i++) mw+= t.c[i].w;		
-                    //cell rendering is not as trivial as it might seem, and it is slightly different for
-                    //each browser. In the beginning i had a big switch for each browser, but since the code
-                    //was extremely ugly now I use a different approach with several re-flows. This works 
-                    //pretty well but it's a bit slower. For now, lets keep things simple...   
-                    for(i=0; i<t.ln; i++) t.c[i].css("width", M.round(1000*t.c[i].w/mw)/10 + "%").l=true; 
-                    //c.l locks the column, telling us that its c.w is outdated									
-                }else{     //in non fixed-sized tables
-                    applyBounds(t);         //apply the new bounds 
-                    if(t.mode == 'flex' && t.p && S){   //if postbackSafe is enabled and there is sessionStorage support,
-                        memento(t);                     //the new layout is serialized and stored for 'flex' tables
-                    }
-                }
-                syncGrips(t.addClass(SIGNATURE));
-            }
-		} 
-		
-	};		
-
-
-	//bind resize event, to update grips position 
-	$(window).bind('resize.'+SIGNATURE, onResize); 
-
-
-	/**
-	 * The plugin is added to the jQuery library
-	 * @param {Object} options -  an object that holds some basic customization values 
-	 */
-    $.fn.extend({  
-        colResizable: function(options) {           
-            var defaults = {
-			
-				//attributes:
-                
-                resizeMode: 'fit',                    //mode can be 'fit', 'flex' or 'overflow'
-                draggingClass: 'JCLRgripDrag',	//css-class used when a grip is being dragged (for visual feedback purposes)
-				gripInnerHtml: '',				//if it is required to use a custom grip it can be done using some custom HTML				
-				liveDrag: false,				//enables table-layout updating while dragging	
-				minWidth: 15, 					//minimum width value in pixels allowed for a column 
-				headerOnly: false,				//specifies that the size of the the column resizing anchors will be bounded to the size of the first row 
-				hoverCursor: "col-resize",  		//cursor to be used on grip hover
-				dragCursor: "col-resize",  		//cursor to be used while dragging
-				postbackSafe: false, 			//when it is enabled, table layout can persist after postback or page refresh. It requires browsers with sessionStorage support (it can be emulated with sessionStorage.js). 
-				flush: false, 					//when postbakSafe is enabled, and it is required to prevent layout restoration after postback, 'flush' will remove its associated layout data 
-				marginLeft: null,				//in case the table contains any margins, colResizable needs to know the values used, e.g. "10%", "15em", "5px" ...
-				marginRight: null, 				//in case the table contains any margins, colResizable needs to know the values used, e.g. "10%", "15em", "5px" ...
-				disable: false,					//disables all the enhancements performed in a previously colResized table	
-				partialRefresh: false,			//can be used in combination with postbackSafe when the table is inside of an updatePanel,
-				useLocalStorage: false,	 	 	//use localStorage to save table layout instead of sessionStorage
-                disabledColumns: [],            //column indexes to be excluded
-                removePadding: true,           //for some uses (such as multiple range slider), it is advised to set this modifier to true, it will remove padding from the header cells.
-
-				//events:
-				onDrag: null, 					//callback function to be fired during the column resizing process if liveDrag is enabled
-				onResize: null					//callback function fired when the dragging process is over
-            }			
-			var options =  $.extend(defaults, options);		
-            
-            //since now there are 3 different ways of resizing columns, I changed the external interface to make it clear
-            //calling it 'resizeMode' but also to remove the "fixed" attribute which was confusing for many people
-            options.fixed = true;
-            options.overflow = false;
-            switch(options.resizeMode){
-                case 'flex': options.fixed = false; break;
-                case 'overflow': options.fixed = false; options.overflow = true; break;
-            }
-
-            return this.each(function() {				
-             	init( this, options);             
-            });
-        }
-    });
-})(jQuery);
-

+ 0 - 338
static/js/table-fixer.jquery.js

@@ -1,338 +0,0 @@
-(function ($) {
-
-  $.fn.tableFixer = function (param) {
-
-    return this.each(function () {
-      table.call(this);
-    });
-
-    function table() {
-      /**
-       * This function solver z-index problem in corner cell
-       * where fix row and column at the same time,
-       * set corner cells z-index 1 more then other fixed cells
-       */
-      function setCorner() {
-        var table = $(settings.table);
-
-        if (settings.head) {
-          var tr;
-          if (settings.left > 0) {
-            tr = table.find("> thead > tr");
-
-            tr.each(function (k, row) {
-              solveLeftColspan(row, function (cell) {
-                $(cell).css("z-index", settings['z-index'] + 1);
-              });
-            });
-          }
-
-          if (settings.right > 0) {
-            tr = table.find("> thead > tr");
-
-            tr.each(function (k, row) {
-              solveRightColspan(row, function (cell) {
-                $(cell).css("z-index", settings['z-index'] + 1);
-              });
-            });
-          }
-        }
-
-        if (settings.foot) {
-          if (settings.left > 0) {
-            tr = table.find("> tfoot > tr");
-
-            tr.each(function (k, row) {
-              solveLeftColspan(row, function (cell) {
-                $(cell).css("z-index", settings['z-index'] + 1);
-              });
-            });
-          }
-
-          if (settings.right > 0) {
-            tr = table.find("> tfoot > tr");
-
-            tr.each(function (k, row) {
-              solveRightColspan(row, function (cell) {
-                $(cell).css("z-index", settings['z-index'] + 1);
-              });
-            });
-          }
-        }
-      }
-
-      // Set style of table parent
-      function setParent() {
-        var parent = $(settings.parent);
-        var table = $(settings.table);
-
-        parent.append(table).css({
-          'overflow-x': 'auto',
-          'overflow-y': 'auto',
-          'position': 'relative', // for cells position computation
-        });
-
-        parent.on('scroll', $.proxy(function () {
-          var scrollWidth = parent[0].scrollWidth;
-          var clientWidth = parent[0].clientWidth;
-          var scrollHeight = parent[0].scrollHeight;
-          var clientHeight = parent[0].clientHeight;
-          var scroll_top = parent.scrollTop();
-          var scroll_left = parent.scrollLeft();
-          var table_position = {
-            left: table[0].offsetLeft,
-            top: table[0].offsetTop,
-          };
-          table_position.right = scrollWidth - table_position.left - table.width();
-          table_position.bottom = scrollHeight - table_position.top - table.height();
-
-          if (settings.head) {
-            var top = scroll_top - table_position.top;
-            this.find("> thead > tr > *").css("top", top < 0 ? 0 : top);
-          }
-
-          if (settings.foot) {
-            var bottom = scrollHeight - clientHeight - scroll_top - table_position.bottom;
-            this.find("> tfoot > tr > *").css("bottom", bottom < 0 ? 0 : bottom);
-          }
-
-          if (settings.left > 0) {
-            var left = scroll_left - table_position.left;
-            settings.leftColumns.css("left", left < 0 ? 0 : left);
-          }
-
-          if (settings.right > 0) {
-            var right = scrollWidth - clientWidth - scroll_left - table_position.right;
-            settings.rightColumns.css("right", right < 0 ? 0 : right);
-          }
-        }, table));
-      }
-
-      // Set table head fixed
-      function fixHead() {
-        var thead = $(settings.table).find("> thead");
-        var cells = thead.find("> tr > *");
-
-        setBackground(cells);
-        cells.css({
-          'position': 'relative',
-          'z-index': settings['z-index'],
-        });
-      }
-
-      // Set table foot fixed
-      function fixFoot() {
-        var tfoot = $(settings.table).find("> tfoot");
-        var cells = tfoot.find("> tr > *");
-
-        setBackground(cells);
-        cells.css({
-          'position': 'relative',
-          'z-index': settings['z-index'],
-        });
-      }
-
-      // Set table left column fixed
-      function fixLeft() {
-        var table = $(settings.table);
-
-        settings.leftColumns = $();
-
-        var tr = table.find("> thead > tr, > tbody > tr, > tfoot > tr");
-        tr.each(function (k, row) {
-
-          solveLeftColspan(row, function (cell) {
-            settings.leftColumns = settings.leftColumns.add(cell);
-          });
-        });
-
-        var column = settings.leftColumns;
-
-        column.each(function (k, cell) {
-          cell = $(cell);
-
-          setBackground(cell);
-          cell.css({
-            'position': 'relative',
-            'z-index': settings['z-index'],
-          });
-        });
-      }
-
-      // Set table right column fixed
-      function fixRight() {
-        var table = $(settings.table);
-
-        settings.rightColumns = $();
-
-        var tr = table.find("> thead > tr, > tbody > tr, > tfoot > tr");
-        tr.each(function (k, row) {
-          solveRightColspan(row, function (cell) {
-            settings.rightColumns = settings.rightColumns.add(cell);
-          });
-        });
-
-        var column = settings.rightColumns;
-
-        column.each(function (k, cell) {
-          cell = $(cell);
-
-          setBackground(cell);
-          cell.css({
-            'position': 'relative',
-            'z-index': settings['z-index'],
-          });
-        });
-
-      }
-
-      // Set fixed cells backgrounds
-      function setBackground(elements) {
-        elements.each(function (k, element) {
-          element = $(element);
-          var parent = $(element).parent();
-
-          var elementBackground = element.css("background-color");
-          elementBackground = (elementBackground === "transparent" || elementBackground === "rgba(0, 0, 0, 0)")
-            ? null
-            : elementBackground;
-
-          var parentBackground = parent.css("background-color");
-          parentBackground = (parentBackground === "transparent" || parentBackground === "rgba(0, 0, 0, 0)")
-            ? null
-            : parentBackground;
-
-          var background = parentBackground ? parentBackground : "white";
-          background = elementBackground ? elementBackground : background;
-
-          element.css("background-color", background);
-        });
-      }
-
-      function solveLeftColspan(row, action) {
-        var fixColumn = settings.left;
-        var inc = 1;
-
-        for (var i = 1; i <= fixColumn; i = i + inc) {
-          var nth = inc > 1 ? i - 1 : i;
-
-          var cell = $(row).find("> *:nth-child(" + nth + ")");
-          var colspan = cell.prop("colspan");
-
-          if (typeof cell.cellPos() !== 'undefined' && cell.cellPos().left < fixColumn) {
-            action(cell);
-          }
-
-          inc = colspan;
-        }
-      }
-
-      function solveRightColspan(row, action) {
-        var fixColumn = settings.right;
-        var inc = 1;
-        for (var i = 1; i <= fixColumn; i = i + inc) {
-          var nth = inc > 1 ? i - 1 : i;
-
-          var cell = $(row).find("> *:nth-last-child(" + nth + ")");
-          var colspan = cell.prop("colspan");
-          action(cell);
-          inc = colspan;
-        }
-      }
-
-      var defaults = {
-        head: true,
-        foot: false,
-        left: 0,
-        right: 0,
-        'z-index': 1,
-      };
-
-      var settings = $.extend({}, defaults, param);
-      settings.head = Boolean(settings.head);
-      settings.foot = Boolean(settings.foot);
-      settings.table = this;
-      settings.parent = $(settings.table).parent();
-      setParent();
-
-      if (settings.head === true) {
-        fixHead();
-      }
-
-      if (settings.foot === true) {
-        fixFoot();
-      }
-
-      if (settings.left > 0) {
-        fixLeft();
-      }
-
-      if (settings.right > 0) {
-        fixRight();
-      }
-
-      setCorner();
-
-      $(settings.parent).trigger("scroll");
-
-      $(window).resize(function () {
-        $(settings.parent).trigger("scroll");
-      });
-    }
-  };
-
-})(jQuery);
-
-/**
- * cellPos jQuery plugin
- * ---------------------
- * Get visual position of cell in HTML table (or its block like thead).
- * Return value is object with "top" and "left" properties set to row
- * and column index of top-left cell corner.
- * Example of use:
- * $("#myTable tbody td").each(function(){
- *   $(this).text( $(this).cellPos().top +", "+ $(this).cellPos().left );
- * });
- */
-(function ($) {
-  /* scan individual table and set "cellPos" data in the form { left: x-coord, top: y-coord } */
-  function scanTable($table) {
-    var m = [];
-    $table.children("tr").each(function (y, row) {
-      $(row).children("td, th").each(function (x, cell) {
-        var $cell = $(cell),
-          colspan = $cell.attr("colspan") | 0,
-          rowspan = $cell.attr("rowspan") | 0,
-          tx, ty;
-        colspan = colspan ? colspan : 1;
-        rowspan = rowspan ? rowspan : 1;
-
-        // noinspection StatementWithEmptyBodyJS
-        for (; m[y] && m[y][x]; ++x); //skip already occupied cells in current row
-
-        for (tx = x; tx < x + colspan; ++tx) {  //mark matrix elements occupied by current cell with true
-          for (ty = y; ty < y + rowspan; ++ty) {
-            if (!m[ty]) {  //fill missing rows
-              m[ty] = [];
-            }
-            m[ty][tx] = true;
-          }
-        }
-        var pos = {top: y, left: x};
-        $cell.data("cellPos", pos);
-      });
-    });
-  }
-
-  /* plugin */
-  $.fn.cellPos = function (rescan) {
-    var $cell = this.first(),
-      pos = $cell.data("cellPos");
-    if (!pos || rescan) {
-      var $table = $cell.closest("table, thead, tbody, tfoot");
-      scanTable($table);
-    }
-    pos = $cell.data("cellPos");
-    return pos;
-  }
-})(jQuery);

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio