From 2f154bbed4d715267da428cc9c835c09c6eed008 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Fri, 13 Feb 2015 13:24:13 +0000 Subject: [PATCH] The previous commit inadvertently added parts of the browser treeview implementation. This adds the rest (which still requires further work to make it do anything useful). --- .../static/css/aciTree/css/aciTree.css | 549 ++++ .../css/aciTree/image/drag-drop-rtl.png | Bin 0 -> 982 bytes .../static/css/aciTree/image/drag-drop.png | Bin 0 -> 908 bytes .../browser/static/css/aciTree/image/eyes.png | Bin 0 -> 10753 bytes .../static/css/aciTree/image/load-node.gif | Bin 0 -> 1728 bytes .../static/css/aciTree/image/load-root.gif | Bin 0 -> 8778 bytes .../css/aciTree/image/tree-arrow-big-rtl.png | Bin 0 -> 3939 bytes .../css/aciTree/image/tree-arrow-big.png | Bin 0 -> 3797 bytes .../aciTree/image/tree-arrow-small-rtl.png | Bin 0 -> 2797 bytes .../css/aciTree/image/tree-arrow-small.png | Bin 0 -> 2548 bytes .../static/css/aciTree/image/tree-big-rtl.png | Bin 0 -> 3821 bytes .../static/css/aciTree/image/tree-big.png | Bin 0 -> 3644 bytes .../static/css/aciTree/image/tree-branch.png | Bin 0 -> 235 bytes .../css/aciTree/image/tree-check-big-rtl.png | Bin 0 -> 8134 bytes .../css/aciTree/image/tree-check-big.png | Bin 0 -> 7816 bytes .../aciTree/image/tree-check-small-rtl.png | Bin 0 -> 4044 bytes .../css/aciTree/image/tree-check-small.png | Bin 0 -> 3687 bytes .../css/aciTree/image/tree-small-rtl.png | Bin 0 -> 2351 bytes .../static/css/aciTree/image/tree-small.png | Bin 0 -> 2320 bytes .../js/aciTree/jquery.aciFragment.min.js | 15 + .../static/js/aciTree/jquery.aciPlugin.min.js | 12 + .../js/aciTree/jquery.aciSortable.min.js | 13 + .../js/aciTree/jquery.aciTree.checkbox.js | 483 ++++ .../js/aciTree/jquery.aciTree.column.js | 250 ++ .../static/js/aciTree/jquery.aciTree.core.js | 2544 +++++++++++++++++ .../static/js/aciTree/jquery.aciTree.debug.js | 87 + .../static/js/aciTree/jquery.aciTree.dom.js | 660 +++++ .../js/aciTree/jquery.aciTree.editable.js | 294 ++ .../static/js/aciTree/jquery.aciTree.hash.js | 170 ++ .../static/js/aciTree/jquery.aciTree.min.js | 44 + .../js/aciTree/jquery.aciTree.persist.js | 290 ++ .../static/js/aciTree/jquery.aciTree.radio.js | 471 +++ .../js/aciTree/jquery.aciTree.selectable.js | 739 +++++ .../js/aciTree/jquery.aciTree.sortable.js | 339 +++ .../static/js/aciTree/jquery.aciTree.utils.js | 746 +++++ web/pgadmin/static/css/overrides.css | 9 + 36 files changed, 7715 insertions(+) create mode 100755 web/pgadmin/browser/static/css/aciTree/css/aciTree.css create mode 100755 web/pgadmin/browser/static/css/aciTree/image/drag-drop-rtl.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/drag-drop.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/eyes.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/load-node.gif create mode 100755 web/pgadmin/browser/static/css/aciTree/image/load-root.gif create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-arrow-big-rtl.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-arrow-big.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-arrow-small-rtl.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-arrow-small.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-big-rtl.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-big.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-branch.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-check-big-rtl.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-check-big.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-check-small-rtl.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-check-small.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-small-rtl.png create mode 100755 web/pgadmin/browser/static/css/aciTree/image/tree-small.png create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciFragment.min.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciPlugin.min.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciSortable.min.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.checkbox.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.column.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.core.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.debug.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.dom.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.editable.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.hash.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.min.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.persist.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.radio.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.selectable.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.sortable.js create mode 100755 web/pgadmin/browser/static/js/aciTree/jquery.aciTree.utils.js diff --git a/web/pgadmin/browser/static/css/aciTree/css/aciTree.css b/web/pgadmin/browser/static/css/aciTree/css/aciTree.css new file mode 100755 index 000000000..716c70cb3 --- /dev/null +++ b/web/pgadmin/browser/static/css/aciTree/css/aciTree.css @@ -0,0 +1,549 @@ +@charset "utf-8"; + +/* + * aciTree jQuery Plugin + * http://acoderinsights.ro + * + */ + +.aciTree { + outline: none; +} + +/* the big loader */ +.aciTree.aciTreeLoad { + background:url(../image/load-root.gif) center center no-repeat; +} + +.aciTree .aciTreeUl { + list-style:none; + margin:0; + padding:0; +} +.aciTree .aciTreeLi { + display:block; + clear:both; + white-space:nowrap; +} +.aciTree .aciTreeLine:focus { + outline:none; +} + +.aciTree .aciTreeLi.aciTreeHidden { + display:none; +} + +/* the branch line */ +.aciTree .aciTreeBranch { + padding-left:20px; /* branch indent */ + background:url(../image/tree-branch.png) left 1px repeat-y; +} +.aciTree[dir=rtl] .aciTreeBranch { + padding-left:0; + padding-right:20px; /* branch indent */ + background:url(../image/tree-branch.png) right 1px repeat-y; +} +/* if the parent is the last child on his level (this is level based; added for #8 levels, if you need more ... add them as needed) */ +.aciTree .aciTreeLi.aciTreeLevel0.aciTreeLast .aciTreeBranch.aciTreeLevel0, +.aciTree .aciTreeLi.aciTreeLevel1.aciTreeLast .aciTreeBranch.aciTreeLevel1, +.aciTree .aciTreeLi.aciTreeLevel2.aciTreeLast .aciTreeBranch.aciTreeLevel2, +.aciTree .aciTreeLi.aciTreeLevel3.aciTreeLast .aciTreeBranch.aciTreeLevel3, +.aciTree .aciTreeLi.aciTreeLevel4.aciTreeLast .aciTreeBranch.aciTreeLevel4, +.aciTree .aciTreeLi.aciTreeLevel5.aciTreeLast .aciTreeBranch.aciTreeLevel5, +.aciTree .aciTreeLi.aciTreeLevel6.aciTreeLast .aciTreeBranch.aciTreeLevel6, +.aciTree .aciTreeLi.aciTreeLevel7.aciTreeLast .aciTreeBranch.aciTreeLevel7, +.aciTree .aciTreeLi.aciTreeLevel8.aciTreeLast .aciTreeBranch.aciTreeLevel8, +.aciTree.aciTreeNoBranches .aciTreeBranch { + background:none; +} +/* the branch line behind the button (for the siblings) */ +.aciTree .aciTreeEntry { + overflow:hidden; + background:url(../image/tree-branch.png) left 1px repeat-y; +} +.aciTree[dir=rtl] .aciTreeEntry { + background:url(../image/tree-branch.png) right 1px repeat-y; +} +.aciTree .aciTreeLi.aciTreeLast>.aciTreeLine .aciTreeEntry, +.aciTree.aciTreeNoBranches .aciTreeEntry { + background:none; +} + +.aciTree.aciTreeBig .aciTreeEntry { + padding:0 0 2px 0; +} + +.aciTree .aciTreeButton, .aciTree .aciTreePush, .aciTree .aciTreeItem, .aciTree .aciTreeIcon, .aciTree .aciTreeText, .aciTree .aciTreeColumn { + display:inline-block; + height:20px; + line-height:20px; + font-family:Verdana, Geneva, sans-serif; + font-size:11px; + color:#000; + vertical-align:top; +} +.aciTree.aciTreeBig .aciTreeText, .aciTree.aciTreeBig .aciTreeColumn { + font-size:12px; +} + +.aciTree .aciTreeDisabled>.aciTreeLine .aciTreeText, .aciTree .aciTreeDisabled>.aciTreeLine .aciTreeColumn { + color:#888; +} + +.aciTree .aciTreeItem { + padding:0 2px 0 2px; + border:1px solid transparent; + height:auto; + white-space:normal; + cursor:pointer; + /* margin-right need to be set to icon width [.aciTree .aciTreeIcon = 20] + + item padding [.aciTree .aciTreeItem = 4] (+ the width of all columns, if any) */ + margin-right:24px; +} +.aciTree[dir=rtl] .aciTreeItem{ + margin-right:0; + /* margin-left need to be set to icon width [.aciTree .aciTreeIcon = 20] + + item padding [.aciTree .aciTreeItem = 4] (+ the width of all columns, if any) */ + margin-left:24px; +} +.aciTree .aciTreeText { + display:inline; + height:auto; +} +.aciTree .aciTreeColumn { + float:right; + height:auto; + white-space:normal; + cursor:default; +} +.aciTree[dir=rtl] .aciTreeColumn { + float:left; +} + +/* columns width/style (left to right, if any) */ + +.aciTree .aciTreeColumn0 { + width:80px; +} +.aciTree .aciTreeColumn1 { + width:60px; +} + +/* item selection */ + +.aciTree .aciTreeLine.aciTreeHover .aciTreeItem { + background-color:#EFF5FD; + border:1px dashed #D9D9D9; + -webkit-border-radius:3px; + -moz-border-radius:3px; + border-radius:3px; +} +.aciTree .aciTreeFocus>.aciTreeLine .aciTreeItem { + /* not selected but with focus */ + border:1px solid #D9D9D9; + -webkit-border-radius:3px; + -moz-border-radius:3px; + border-radius:3px; +} +.aciTree .aciTreeSelected>.aciTreeLine .aciTreeItem { + background-color:#E8E8E8; + border:1px dashed #D9D9D9; + -webkit-border-radius:3px; + -moz-border-radius:3px; + border-radius:3px; +} +.aciTree.aciTreeFocus .aciTreeSelected>.aciTreeLine .aciTreeItem { + background-color:#d0e5fe; +} +.aciTree.aciTreeFocus .aciTreeFocus>.aciTreeLine .aciTreeItem { + /* not selected but with focus */ + border:1px solid #84acdd; +} +.aciTree.aciTreeFocus .aciTreeSelected.aciTreeFocus>.aciTreeLine .aciTreeItem { + border:1px dashed #84acdd; +} + +/* full row selection */ + +.aciTree.aciTreeFullRow>.aciTreeUl { + margin:2px; +} + +.aciTree.aciTreeFullRow .aciTreeLine { + margin:-2px; + border:1px solid transparent; +} + +.aciTree.aciTreeFullRow .aciTreeLine.aciTreeHover .aciTreeItem { + background:none; + border:1px solid transparent; +} +.aciTree.aciTreeFullRow .aciTreeFocus>.aciTreeLine { + /* not selected but with focus */ + border:1px solid #D9D9D9; +} +.aciTree.aciTreeFullRow .aciTreeSelected>.aciTreeLine .aciTreeItem, +.aciTree.aciTreeFullRow .aciTreeFocus>.aciTreeLine .aciTreeItem { + background:none; + border:1px solid transparent; +} +.aciTree.aciTreeFullRow.aciTreeFocus .aciTreeSelected>.aciTreeLine .aciTreeItem { + background:none; + border:1px solid transparent; +} + +.aciTree.aciTreeFullRow .aciTreeLine.aciTreeHover { + background: #e3edf9; + background: -moz-linear-gradient(top, #e3edf9 0%, #9cb7d8 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#e3edf9), color-stop(100%,#9cb7d8)); + background: -webkit-linear-gradient(top, #e3edf9 0%,#9cb7d8 100%); + background: -o-linear-gradient(top, #e3edf9 0%,#9cb7d8 100%); + background: -ms-linear-gradient(top, #e3edf9 0%,#9cb7d8 100%); + background: linear-gradient(to bottom, #e3edf9 0%,#9cb7d8 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e3edf9', endColorstr='#9cb7d8',GradientType=0 ); +} +.aciTree.aciTreeFullRow .aciTreeSelected>.aciTreeLine { + background: #f4f4f4; + background: -moz-linear-gradient(top, #f4f4f4 0%, #c6c6c6 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f4f4f4), color-stop(100%,#c6c6c6)); + background: -webkit-linear-gradient(top, #f4f4f4 0%,#c6c6c6 100%); + background: -o-linear-gradient(top, #f4f4f4 0%,#c6c6c6 100%); + background: -ms-linear-gradient(top, #f4f4f4 0%,#c6c6c6 100%); + background: linear-gradient(to bottom, #f4f4f4 0%,#c6c6c6 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#c6c6c6',GradientType=0 ); +} +.aciTree.aciTreeFullRow.aciTreeFocus .aciTreeFocus>.aciTreeLine { + /* not selected but with focus */ + border:1px solid #84acdd; +} +.aciTree.aciTreeFullRow.aciTreeFocus .aciTreeSelected>.aciTreeLine { + border:1px solid transparent; + background: #d0e5fe; + background: -moz-linear-gradient(top, #d0e5fe 0%, #84acdd 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#d0e5fe), color-stop(100%,#84acdd)); + background: -webkit-linear-gradient(top, #d0e5fe 0%,#84acdd 100%); + background: -o-linear-gradient(top, #d0e5fe 0%,#84acdd 100%); + background: -ms-linear-gradient(top, #d0e5fe 0%,#84acdd 100%); + background: linear-gradient(to bottom, #d0e5fe 0%,#84acdd 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d0e5fe', endColorstr='#84acdd',GradientType=0 ); +} +.aciTree.aciTreeFullRow.aciTreeFocus .aciTreeSelected>.aciTreeLine.aciTreeHover, +.aciTree.aciTreeFullRow .aciTreeSelected>.aciTreeLine.aciTreeHover { + background: #c3dbf7; + background: -moz-linear-gradient(top, #c3dbf7 0%, #84a9d6 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#c3dbf7), color-stop(100%,#84a9d6)); + background: -webkit-linear-gradient(top, #c3dbf7 0%,#84a9d6 100%); + background: -o-linear-gradient(top, #c3dbf7 0%,#84a9d6 100%); + background: -ms-linear-gradient(top, #c3dbf7 0%,#84a9d6 100%); + background: linear-gradient(to bottom, #c3dbf7 0%,#84a9d6 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c3dbf7', endColorstr='#84a9d6',GradientType=0 ); +} + +/* checkbox/radio tree */ + +.aciTree .aciTreeCheckbox label, .aciTree .aciTreeRadio label { + cursor:pointer; +} +.aciTree .aciTreeCheck { + width:20px; + height:20px; + display:inline-block; + margin:0 2px 0 2px; + padding:0; + vertical-align:text-bottom; + background:url(../image/tree-check-small.png) 0 0 no-repeat; +} +.aciTree.aciTreeBig .aciTreeCheck { + background:url(../image/tree-check-big.png) 0 0 no-repeat; +} + +.aciTree[dir=rtl] .aciTreeCheck { + background:url(../image/tree-check-small-rtl.png) 0 0 no-repeat; +} +.aciTree.aciTreeBig[dir=rtl] .aciTreeCheck { + background:url(../image/tree-check-big-rtl.png) 0 0 no-repeat; +} + +.aciTree .aciTreeCheckbox>.aciTreeLine .aciTreeCheck { background-position:-5px -65px; } +.aciTree .aciTreeCheckbox.aciTreeChecked>.aciTreeLine .aciTreeCheck { background-position:-5px -5px; } +.aciTree .aciTreeCheckbox.aciTreeChecked.aciTreeTristate>.aciTreeLine .aciTreeCheck { background-position:-5px -35px; } + +.aciTree .aciTreeCheckbox>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-35px -65px; } +.aciTree .aciTreeCheckbox.aciTreeChecked>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-35px -5px; } +.aciTree .aciTreeCheckbox.aciTreeChecked.aciTreeTristate>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-35px -35px; } + +.aciTree .aciTreeCheckbox.aciTreeDisabled>.aciTreeLine .aciTreeCheck { background-position:-65px -65px; } +.aciTree .aciTreeCheckbox.aciTreeDisabled.aciTreeChecked>.aciTreeLine .aciTreeCheck { background-position:-65px -5px; } +.aciTree .aciTreeCheckbox.aciTreeDisabled.aciTreeChecked.aciTreeTristate>.aciTreeLine .aciTreeCheck { background-position:-65px -35px; } + +.aciTree .aciTreeRadio>.aciTreeLine .aciTreeCheck { background-position:-95px -65px; } +.aciTree .aciTreeRadio.aciTreeChecked>.aciTreeLine .aciTreeCheck { background-position:-95px -5px; } +.aciTree .aciTreeRadio.aciTreeChecked.aciTreeTristate>.aciTreeLine .aciTreeCheck { background-position:-95px -35px; } + +.aciTree .aciTreeRadio>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-125px -65px; } +.aciTree .aciTreeRadio.aciTreeChecked>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-125px -5px; } +.aciTree .aciTreeRadio.aciTreeChecked.aciTreeTristate>.aciTreeLine.aciTreeHover .aciTreeCheck { background-position:-125px -35px; } + +.aciTree .aciTreeRadio.aciTreeDisabled>.aciTreeLine .aciTreeCheck { background-position:-155px -65px; } +.aciTree .aciTreeRadio.aciTreeDisabled.aciTreeChecked>.aciTreeLine .aciTreeCheck { background-position:-155px -5px; } +.aciTree .aciTreeRadio.aciTreeDisabled.aciTreeChecked.aciTreeTristate>.aciTreeLine .aciTreeCheck { background-position:-155px -35px; } + +/* inplace editable */ + +.aciTree .aciTreeEdited input[type=text] { + outline: none; + border:1px solid #000; + padding:0; + margin:0; + line-height:18px; + height:18px; + display:inline-block; + font-family:Verdana, Geneva, sans-serif; + font-size:11px; + color:#000; + vertical-align:top; +} +.aciTree.aciTreeBig .aciTreeEdited input[type=text] { + font-size:12px; +} + +/* sortable items */ + +.aciTree .aciTreeChild { + height:0; + line-height:0; +} + +.aciTree .aciTreePlaceholder { + height:0; + line-height:0; + overflow:visible; + position:relative; +} + +.aciTree .aciTreePlaceholder div { + position:absolute; + left:0; + width:16px; + height:16px; + margin-left:20px; + background:#fff url(../image/drag-drop.png) -7px -37px no-repeat; + border:1px solid #999; +} + +.aciTree[dir=rtl] .aciTreePlaceholder div { + background:#fff url(../image/drag-drop-rtl.png) -7px -37px no-repeat; +} + +.aciTree .aciTreeChild .aciTreePlaceholder div { + top:-20px; + left:-20px; +} +.aciTree.aciTreeBig .aciTreeChild .aciTreePlaceholder div { + top:-22px; +} + +.aciTree .aciTreePlaceholder.aciTreeBefore div { + top:2px; + background-position:-7px -7px !important; +} + +.aciTree .aciTreePlaceholder.aciTreeAfter div { + top:-20px; + background-position:-7px -67px !important; +} +.aciTree.aciTreeBig .aciTreePlaceholder.aciTreeAfter div { + top:-22px; +} + +.aciTree.aciTreeDragDrop .aciTreeItem, .aciTree.aciTreeDragDrop .aciTreeColumn, +.aciTree.aciTreeDragDrop .aciTreeCheckbox label, .aciTree.aciTreeDragDrop .aciTreeRadio label { + cursor:inherit !important; +} + +/* this is level based; added for #8 levels, if you need more ... add them as needed */ +.aciTree .aciTreeLi.aciTreeLevel0 .aciTreePlaceholder div { margin-left:40px; } +.aciTree .aciTreeLi.aciTreeLevel1 .aciTreePlaceholder div { margin-left:60px; } +.aciTree .aciTreeLi.aciTreeLevel2 .aciTreePlaceholder div { margin-left:80px; } +.aciTree .aciTreeLi.aciTreeLevel3 .aciTreePlaceholder div { margin-left:100px; } +.aciTree .aciTreeLi.aciTreeLevel4 .aciTreePlaceholder div { margin-left:120px; } +.aciTree .aciTreeLi.aciTreeLevel5 .aciTreePlaceholder div { margin-left:140px; } +.aciTree .aciTreeLi.aciTreeLevel6 .aciTreePlaceholder div { margin-left:160px; } +.aciTree .aciTreeLi.aciTreeLevel7 .aciTreePlaceholder div { margin-left:180px; } +.aciTree .aciTreeLi.aciTreeLevel8 .aciTreePlaceholder div { margin-left:200px; } + +.aciTree[dir=rtl] .aciTreePlaceholder div { + left:auto; + right:0; + margin-left:0; + margin-right:20px; +} + +.aciTree .aciTreeChild .aciTreePlaceholder div { + right:-20px; +} + +/* this is level based; added for #8 levels, if you need more ... add them as needed */ +.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel0 .aciTreePlaceholder div { margin-right:40px; } +.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel1 .aciTreePlaceholder div { margin-right:60px; } +.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel2 .aciTreePlaceholder div { margin-right:80px; } +.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel3 .aciTreePlaceholder div { margin-right:100px; } +.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel4 .aciTreePlaceholder div { margin-right:120px; } +.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel5 .aciTreePlaceholder div { margin-right:140px; } +.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel6 .aciTreePlaceholder div { margin-right:160px; } +.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel7 .aciTreePlaceholder div { margin-right:180px; } +.aciTree[dir=rtl] .aciTreeLi.aciTreeLevel8 .aciTreePlaceholder div { margin-right:200px; } + +.aciTreeHelper { + position:absolute; + max-width:300px; + color:#000; + background-color:#d0e5fe; + border:1px dashed #84acdd; + -webkit-border-radius:3px; + -moz-border-radius:3px; + border-radius:3px; + padding:4px; + margin:20px 0 0 20px; +} + +/* default - item in the middle (comment the hover part to keep the same button image) */ + +.aciTree .aciTreeButton, .aciTree .aciTreePush { + width:18px; + background:url(../image/tree-small.png) -7px -35px no-repeat; +} +.aciTree.aciTreeBig .aciTreeButton, .aciTree.aciTreeBig .aciTreePush { + background:url(../image/tree-big.png) -7px -35px no-repeat; +} + +.aciTree[dir=rtl] .aciTreeButton, .aciTree[dir=rtl] .aciTreePush { + background:url(../image/tree-small-rtl.png) -7px -35px no-repeat; +} +.aciTree.aciTreeBig[dir=rtl] .aciTreeButton, .aciTree.aciTreeBig[dir=rtl] .aciTreePush { + background:url(../image/tree-big-rtl.png) -7px -35px no-repeat; +} + +.aciTree.aciTreeArrow .aciTreeButton, .aciTree.aciTreeArrow .aciTreePush { + background:url(../image/tree-arrow-small.png) -7px -35px no-repeat; +} +.aciTree.aciTreeBig.aciTreeArrow .aciTreeButton, .aciTree.aciTreeBig.aciTreeArrow .aciTreePush { + background:url(../image/tree-arrow-big.png) -7px -35px no-repeat; +} + +.aciTree.aciTreeArrow[dir=rtl] .aciTreeButton, .aciTree.aciTreeArrow[dir=rtl] .aciTreePush { + background:url(../image/tree-arrow-small-rtl.png) -7px -35px no-repeat; +} +.aciTree.aciTreeBig.aciTreeArrow[dir=rtl] .aciTreeButton, .aciTree.aciTreeBig.aciTreeArrow[dir=rtl] .aciTreePush { + background:url(../image/tree-arrow-big-rtl.png) -7px -35px no-repeat; +} + +.aciTree.aciTreeNoBranches .aciTreeButton, +.aciTree .aciTreeLeaf>.aciTreeLine .aciTreePush { background:none !important; } + +.aciTree .aciTreeInodeMaybe>.aciTreeLine .aciTreePush { background-position:-67px -5px !important; } +.aciTree .aciTreeInodeMaybe>.aciTreeLine .aciTreePush.aciTreeHover { background-position:-67px -35px !important; } +.aciTree .aciTreeInode>.aciTreeLine .aciTreePush { background-position:-97px -5px !important; } +.aciTree .aciTreeInode>.aciTreeLine .aciTreePush.aciTreeHover { background-position:-97px -35px !important; } +.aciTree .aciTreeOpen>.aciTreeLine .aciTreePush { background-position:-127px -5px !important; } +.aciTree .aciTreeOpen>.aciTreeLine .aciTreePush.aciTreeHover { background-position:-127px -35px !important; } + +/* if it's the last item in list */ + +.aciTree .aciTreeLi.aciTreeLast>.aciTreeLine .aciTreeButton { background-position:-37px -5px !important; } + +/* the item loader */ + +.aciTree .aciTreePush>span { + display:none; + position:absolute; + width:18px; + height:18px; + left:0; + top:2px; + background:url(../image/load-node.gif) 0 0 no-repeat; +} +.aciTree .aciTreeLoad>.aciTreeLine .aciTreePush { + position:relative; + /* uncomment next line to hide the button while loading */ + /*background:none !important;*/ +} +.aciTree .aciTreeLoad>.aciTreeLine .aciTreePush>span { + display:inline-block; +} + +/* tree item icon */ + +.aciTree .aciTreeIcon { + width:20px; + background:url(../image/tree-small.png) 0 0 no-repeat; +} +.aciTree.aciTreeBig .aciTreeIcon { + background:url(../image/tree-big.png) 0 0 no-repeat; +} + +.aciTree[dir=rtl] .aciTreeIcon { + width:16px; + margin-left:4px; + background:url(../image/tree-small-rtl.png) 0 0 no-repeat; +} +.aciTree.aciTreeBig[dir=rtl] .aciTreeIcon { + background:url(../image/tree-big-rtl.png) 0 0 no-repeat; +} + +.aciTree.aciTreeArrow .aciTreeIcon { background:url(../image/tree-arrow-small.png) 0 0 no-repeat; } +.aciTree.aciTreeBig.aciTreeArrow .aciTreeIcon { background:url(../image/tree-arrow-big.png) 0 0 no-repeat; } + +.aciTree.aciTreeArrow[dir=rtl] .aciTreeIcon { background:url(../image/tree-arrow-small-rtl.png) 0 0 no-repeat; } +.aciTree.aciTreeBig.aciTreeArrow[dir=rtl] .aciTreeIcon { background:url(../image/tree-arrow-big-rtl.png) 0 0 no-repeat; } + +/* demo file/folder icon class */ + +.aciTree .aciTreeIcon.folder { + background-position:-157px -5px !important; +} +.aciTree .aciTreeLine.aciTreeHover .aciTreeIcon.folder { + /* comment next line to keep the same icon on hover */ + background-position:-157px -35px !important; +} +.aciTree .aciTreeIcon.file { + background-position:-187px -5px !important; +} +.aciTree .aciTreeLine.aciTreeHover .aciTreeIcon.file { + /* comment next line to keep the same icon on hover */ + background-position:-187px -35px !important; +} + +/* demo row colors */ + +.aciTree.aciTreeColors .aciTreeOdd>.aciTreeLine { + /* odd rows */ + background-color:#FFFFC4; +} +.aciTree.aciTreeColors .aciTreeEven>.aciTreeLine { + /* even rows */ + background-color:#CAFFCA; +} +.aciTree.aciTreeColors .aciTreeFirst>.aciTreeLine { + /* first item on each level */ + /*background-color:#B0DFFF;*/ +} +.aciTree.aciTreeColors .aciTreeLast>.aciTreeLine { + /* last item on each level */ + /*background-color:#FFCEFF;*/ +} + +/* uncomment below to keep the item in one line and scroll the tree horizontally when needed */ + +/* + +.aciTree .aciTreeEntry { + overflow:visible; +} + +.aciTree .aciTreeItem { + white-space:nowrap; + margin-right:12px; +} + +*/ diff --git a/web/pgadmin/browser/static/css/aciTree/image/drag-drop-rtl.png b/web/pgadmin/browser/static/css/aciTree/image/drag-drop-rtl.png new file mode 100755 index 0000000000000000000000000000000000000000..21e11f04f031683e49e4fd6f5a9f7d24b10c3195 GIT binary patch literal 982 zcmV;{11bE8P)$Qmh00S;b zL_t(&f$iDfOOsI;2k`HC=hE0aL1AiQqPT=XVci5-Mroik@FFOvpkEZ-h+PGi7b4hI ze}ITdL3!Cl;zlv(*vgtO*oVxev!kkl)_q?x8G0p>rz1#bq^EvN! zc6Oc}Mnu?;koH9tuz&@e8PQmLM-zY{*gF-Ws)m>F1eXlsOz+I)Q^HhxZ!rD*Y>HFb?>UZ?cbAy?wV zxdvCMc>$6vLy~3mUn@=@OR|jqj=J=5WQnJ>)!=@sz1{##PR^pa`2;KL98XvJ)m6>h zeo&mSwJaAs_Vjf64Sx^vjrlqpH+vY1>p)P(Mt zYq#Ry{W=L)zycPqfCVhzgAeOo?2S$n1E7|g7szI_8tyn(MV}G|fVIW5+H&S89F9&l zHWo}}4fZKv*eePF024}>E}w3P-ycRO6vyP`tl>N6TxBx&ln`CG@(RBLQ7{0m*Eh)7 zP@O%PF$Rw^Pc?U4SYA;xx&jcep>oHq|W6P51*>!trD42^>Dx;GGY);i$>kD{H033s>tnjd!bI4@!JgGu)MKMrh11qw@ z-DW3xZfA@^`q$1{;R@~)#utU85>n>}fnWk)3~)6AZO;$gJi?9Yg4gi+f#{akKR8!luPDsUR{dId=Ri%a_5VVK&&}&b0q~`% zo6FBYlFA2&Jjy)nd72uH#VOxvF*IEQVmDR50{$Q1zrd5s;jeQEK>z>%07*qoM6N<$ Eg87BIDF6Tf literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/drag-drop.png b/web/pgadmin/browser/static/css/aciTree/image/drag-drop.png new file mode 100755 index 0000000000000000000000000000000000000000..02cabb94a5a1c32f88a3ca5d729d2d9eefaa5933 GIT binary patch literal 908 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 literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/tree-arrow-big-rtl.png b/web/pgadmin/browser/static/css/aciTree/image/tree-arrow-big-rtl.png new file mode 100755 index 0000000000000000000000000000000000000000..cb88a70615122d417d6fdad99c1c39b34677b5ea GIT binary patch literal 3939 zcmV-p51jCcP)}36P`^A*8&D!CDa_B%(kCe5-ERt*_PHRn~J9Ikt7z zmoA%bb=PxLy0liQ7EhI~?7Dj(^;p~hHi6Xw>naeHz#t+CfxM8AnM`KpzCHU#LRqW{ z%De>P^Orj~-S6{q@BIoXB?^TiF|@(nfU}{hs!CPA;+#S#M^Y#fM>� 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 literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/tree-arrow-big.png b/web/pgadmin/browser/static/css/aciTree/image/tree-arrow-big.png new file mode 100755 index 0000000000000000000000000000000000000000..682683f48de2800214f1ef4c5bcd323deea1ff33 GIT binary patch literal 3797 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 KMNUMnLSTY()Yd}) literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/tree-big-rtl.png b/web/pgadmin/browser/static/css/aciTree/image/tree-big-rtl.png new file mode 100755 index 0000000000000000000000000000000000000000..c4e91c1751dfdfeffa908c253eaa87cdbc7deb4d GIT binary patch literal 3821 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 literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/tree-big.png b/web/pgadmin/browser/static/css/aciTree/image/tree-big.png new file mode 100755 index 0000000000000000000000000000000000000000..bcf58ed4f8f501bb034f0e1c0d7433b578209848 GIT binary patch literal 3644 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 KT-G@yGywpm+)Nz+ literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/tree-check-big-rtl.png b/web/pgadmin/browser/static/css/aciTree/image/tree-check-big-rtl.png new file mode 100755 index 0000000000000000000000000000000000000000..e05709086401857ef7f72479f035f1a5cddf2430 GIT binary patch literal 8134 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 Lck)%TR#E>4awPMb literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/tree-check-big.png b/web/pgadmin/browser/static/css/aciTree/image/tree-check-big.png new file mode 100755 index 0000000000000000000000000000000000000000..470689c99ebed4f34e8f7c80a972228bab4590d1 GIT binary patch literal 7816 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 literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/tree-check-small-rtl.png b/web/pgadmin/browser/static/css/aciTree/image/tree-check-small-rtl.png new file mode 100755 index 0000000000000000000000000000000000000000..554e20220dabced0cdc5c67a896d8270e0a5dab3 GIT binary patch literal 4044 zcmbtXXHe7Kv;Gl!ml8s6qM($}n-CC!Q~?DkA_3_=N=XQaprQn%=!=R55CjpFW}!*~ zq5(vL6lns6CZWbq0tlhpym#)$`@diAnc1_?IlFUaXP=!pyXnr3*8Dt@JOBXj+uFb{ zGIbqOE^~1(ccD8sJ~0(rjD@W$7jxa<3cxbY+}CV8V*r3x_+Mce{B?7mc_|%hW>%WD7s*8ec#yOmcQXw{{k>E((<5VR{#5SQ(O^TO$9lUzpe$h=Yu15IS4`?B}P<11X^H#)JE*UFPi?|N4)bOp1 zSza{8UfyVm!Knc9QVu)8Kxl$sl3C@3v-tNj5FtZz@sSCg2^j#D`0 zQ7rM#?f)I@-@Dw;M`Sary7^)g;u2+5YwQ_D*gv#Mk&0F4^u3?aNa{J|!qPA%+``_4AS z(7hSe`jY9-M|=G9Hw5K&iEc&$~X~`i@ScRzcx|~jriXX!nW7q#&|T{D0mEz z?7Kb`JNrvHVJ=4mlI(EoL_ew}$a&>iN6pR6kMi>w zM9j+aatM+3GEdN1%uLV;?i+h`hQ&FJ`ai;SGkCFC4?!n~4uG zT1scxaai9EKYv3st`uix@{JP`8_nT&61t^swbs?BXlrNH2&u=si~3w&XOnRSosLz3 z^C5fxG+UX-S-;|NC*R|KW%&GWbIa>Hx8*xI)__u4YPG}q>2P;ojJ#49wRf4?x>ImTiKonJ^6D_NiNsfzz% zp(LWy4`*xn1tT;yH6be)efD$?p>8akzivPOr6#VCreM^DqWO*#1*cu`7>n53Y)=eQ z#F@k4f;$8Fw@Q2WLaG}TxhhGb? z)Yscvwy_ai?tUz_O6CmeLA!79%4n?_E)R>Mj$8fi#B20L-?+#d<)t3TfYel}kTNZN zS2Z4avi&g&A_TL2uU>k8$LVWXCw6qW4BdFp0G^zd6HDv)HaG1iQyy{TEd&mBRFc<3 zDSuNV9#FD&G8@7tM(RK}ss<)2;!R6*k;9eM(>VBg$wHF}W1Bhw9vB#i-|RKGesq}h z=R+S%2jsz;Qd?V#99r2bo1dSr7Q1hy22Gi8sYP(;#(<=Ay!^J0ZrX=kIs?>|hV{_E z46l9w;Cjl+uQ9hANup0CewoRNHqprF7N71_iHtTCwf412?yHPS6$YihfB(vl-Ej4$#cfH;wWbMLO2jK{MteTbr%>qr8VH zJv!k|JrmMhyF?<9>qC7G+g@Mno1q)mf0R$s-Z?8!oWB9?INX)7(~SX@J$A9FV(Z}h-T zdd|WN4loEr; zo~uF#z1DFV1n=5h@eTnMO9!y$d>-ac-{lc+u!>@HR=uYmu&Zo}s2&Jt5TMj=1eG>) zwdh>;$J&tB=eo+-*x41JP+I!t$mpm6GcwE4fhL36%DSCaOQc(>@W7FpFqz~;O%gw;~z^8xS>@q_3AHZUdXRn`esXY zioaUchku!b<5iV@xH3lu-5RM*HdPQA*--G2mhMtez41~{zg$gP7QyrVjqpgdyER`= zOGA}5--E>1rF`rN_2&oW&GtK-QJ61ZzEn$QbSbKf<3w+xmyB>(D z_4C=bgL?npz_K9+#C6I`E)?O}uMrcTqs5?zMpX2#C+YS zWiGA;+-`qg#-RJ-3=@7?8S`L-K%HW8tIp8+9f$1ZRRIdt(*(p3kc78?q89qx1QTuV=;*ld=2GR&RH;pY9Wy1KPl*5`&O{9O3tHq@ z>!EbwGOqq{5=C}A4xWodA|az*4TrhsFCk}s432@Bq1^&TN)|elfTm}mUrmn1PHS$IwV6cRrpWnR#bdwxUGWWC0c#)tljQy5Y5CKY z<{gmu!Wd|vi!t5KszunCU5$ycR<3Txt*r?IJuGS`7lW870w8F>5UXOK0pZ){wJ*c~`BiBHTKNRR`qF@JpFfr;9r*pn%mfd5y8}&VWwrT)x zwP?8#QN>4sDW8lEUqB0HW`Wo&NxeZYOEVW}|Bru&rps*-sb zIx*(TDapWJS@n(>{19w;+-r6%V+yuR-^Lt1ggl*#Vk}-`O_DI@PPr^lF_$7KP{Fyz znv&sj*C9lTa(Gi80mK1e{asR`qDrqC6C7tJV`LJ|tWX$?cnTlj6K%TSTMPUZ{ zCr85{E|GtyUFgx`H2l--h9ESJPMB*DIAzEk(OUQl0bbrS=!3nu#aQEV2rJ&Wux4|A zce7hTK_TVe`VwC|LoYDCP`uEUI{kOg5(sP;K`uoUpccdg+vtC?Vb7LLhaN6^UQM!Nd|F)s7l$`q&`q4_Lx$$`DY(AlA@JaOyH5R;@z=Nud4pYkG{wmG0}XqFazMU;T~0 zJOO`-!C$Y4Nu02TsCldrG0Nw0^pYzY))y{3^xAxHZf3@extxX5yDFUS##nsMU4s{q zBn-nc6ewFk43#h8^l-VjtetUd?>WNuz>BpoW>(iHKZ6b?`)iYi^vM5XP5T^9E#;%l zM92{Y)R?X9?Z$CyLH&;#`i^UE43&FN(T3Dgwf;VlWzwTqE10l51P7>adbXEdi?jT< z0wNU~b53tOtkA=eM%wXi|GTWna5@tJc>4nH3g4SrVt8f>e)69J(@eOZ87U8LdgTvq&fuV<*`u*)%L zZr?(AZVtPQ>r%s?V9!_E7-Pa(u*odE0Et&jtv?op`W&Er357A1<`kvqUo!>dX^ZEYqz2`i4dEMvS``r6H&%Mv{#M;uBlTDZn002%? z69Zd%TTdsalPBmkZvw1?-Y|#gncAJC7ud-M$@KB5M<$LT0Km@ohZx3YVh`w`XsF?x z&|86?p%L!E9>9$Uf%iNljC_JUA_9XShDhk&QVnWYP^0q+{^8RP_HYmN2@H_1^YQlp zlrJk?QBzV@;ryKXo-Rhaslg4q$bz*(xOH~KtG-!{AkYkn)6Vug#@TaoI`Vrr3#0nu z8^+IVwWYp?%O#)WkUn$t zGpZd(ddA0fRa)WNNLuBbu1Z}z)6hq@{|iXzcIR27FWZP|teuW8yAfaIR@~rM7Q6SM zs^+x>C7I28YpryKu;XG^a%}^zzmFHY?e5yv6mu>%Va!-b4L>mvQIEw&?<66SR(`W> z&fF3l9VcN`5#kSz-43aK3oXyTkg-U+aKH?Ip5|I2-W;$`8|wAY&3{}KnD^V)e`=2^ zxa)absO*cG11Z&f4ZwQ2wni#bIulsmE-(93I=<@_7ZHg*Y?yFS>B@&b@qUJhc6e>1 zpEzTXnkGY0GD;$kVysI7C)hAGXBKPHA(GhXKv>XfC>t|Do6o7;u_r{Cp&<`}Oo2^yN* zC%X>YvY%_MONg}z%RbSUoZRdE%TwU+UZ29blfIwcZsZcoclP^0@SBT^i&r%?G_Y>I z-rlIwvX&z|JN4exp>gY%E@n=6o1jOnVFaRq0Xas&?kKhy7i=c}!Yf=F zSy)(DG&D4{v$ob%R8-{qVlE-&ukXpx^FWP<*XK;63o7Ym%9H+*6UBE=!QSP6c&kcg z<_q<#(-hp&WUg>Djz>wq!%G(Cnm`~B^M-~7D-0Hk%{4PKOE&nbV1Y6|MoU=8dgPhf zp=ih3MQow*CGLVEr1)%ED>E_Ak#v0vW#zrleD6$TkR*2dzTDCXr&RG}`PP}TM%7b# zR~+}RN73{z_A{QEvb4b(5aQzE&ZqY1)tlgkhK54-wmfVoDLljM^;zN;y*xI_w7nNr zAv5maFM2BM?c*?xoxCk7MojrIq?M~eV?u1H`7?J^S`q88TT0JJ zK7|er8qf@XQ0f>NGXC%l2m$yG#zNrT(_n^jKC9QYCfr~ChGbGuU-B2Ao`8VRN-b!a zf=SYY95YMY{6-kaC?aE~*+o<9Jnc+~Vb?@SB+^-x7dJ66F){BbjFU1lGE2{%@pkw0 zNM5?cMF;J5**0=T0vec}K$r??=uI!UZNaz?E1;#B3NO~sN{Iz@=j_iFi(%Ugnl=b6 zmVuQa?ecAN%7Hhs$3@6Hgq*HaPHqtRu@O3Gtq;C4YOH}qqw`+9GP1BpKk*34Q0dgb z)-ms*?4U7yFo#rPYRcS|KJ~lw(`v^v(faQUrEO=^4WV))39jNktl-XwR*fnzMq(88 z`Z{Ks8)F>@fBLNjwinFI%E|;>y4!^K>o5L33VA|VTRV+J@}?hy0dRsqc!h;8xZ~24 zA}JzHwK%^X&UajlNp7ZANDpr{J4_j$ngYOrXwN#5VH;UG3U?2@wd+ZD>5V#%0UlxD z=6lrjnY@=TyI4Umgi_mY#?jGH6BCnf9R1`NNpJ2-ay zy*iH)17MVI!!6e3+M_s&6Dc4F5@TWG!{XaV7YWP$K~Qy*A3ZZDltgHFc=K*P0k%Cf z-_fDV%*^c8mmyY&7-x6$^W#9A+?Wq3l(l3_d|@^IJye);c?=vjSftX@_nZdqgC3NO zNZuK0R%4L3;T8UG*laFlzQmfew&ovAEQ}~`Z2Wp-n>biiYa5Bvlu!HUD+A?{O-w$V zAO_n;E|1CBP{8J>o-~R+$}pW`Oz-8KAAwD-KY`+KetqV%=IoHJ<+t5~#!(}(L`MaX z1PH-~;EQxCA2bgqZHr63TiMxUMp<8}Ks7Ad4@1!tLX~@X>=ts>njw5~1mmmU=3XeR zxxss-;%z3;mu0yXp(rme9|VJm3a0jGs;cI2N8m1BRa4XS_4R%F>Q$_$6!|ufBGl@2 zd1;_}JXepuhsLRn=;B@-fgtnQ?N%{=jmdl%B?Yn{zS+gDG`EJG{Tw$;`J9m3Rur@h zxrq{5f-qTWoOSGs^L)U<`tq58sJD^*Bb3m814#a@WPE4p$Jr?eCA_p;`oif=@^A_v zh4B+C+UL5vN1!)u`}-waj`&i=8F%_y()j$jpba6{HCD*S$0x9p2qku6-4x^2(Q_?r zrQe!p<*8oF;Fa6N5;@GS05Apk0X1WkSHLeFpsIfIb5xjiZKbuGHWYMF4R1Z4-H)E| zzG}9HS6iQTbgkQ$yD%(E%955gzS&Xa-uT91_=hwS>4d#2hToVjYG|bFIAqQ2U3VWB z6fPjFwBu!}xnsJb?+@TdNrg$34eGJ9oW~Kd56LSlD-Kn6pU{1zu>XN@r)Z#=*{6|x z3fXwz)2F)KwJEBA!58ux_c_519mYufdmSb>A%r|I3lb(BO%E)X&L18uZEt>G3-`hK zBWH)nFs44I(_?h8CV-EHGT8lIt@J=&={@vDqo8_eYP5@*#nrF#rQ2qkWd zUr^-s1 zRLmwLiDe{RgD^MeCXaK5s5Cn7HUB(orllzb@B_cCm7_U#&m*`Q4)(ViQZ}{v%<9B@ z*L&`MHT5fHcxo{rjeui$m0w=)JNIgt2Hb-NGlJv|E4__yDJJ?x8 zI<&N^U&$~DN@N0DV4FP&bff#)+^m^8>YaA^#m((jRxZ)At7NhW-9ftAVrbp?mft=~3uNy&`Hd;kTx%fKI{*%{pb)R})fNoT(6QvtO9*F|=PdoNYD#;~lB z%MiXMn%swr%*PF4{~>Jse{t+T15Gqi_AkXdv-6M|gXzeR>isEa2WE_mVzTRLa#kA8 z1=rWnm>gquSvWUaM?;L&Ggy7FA$b%pH~C(tg7;(2pk^73l)k<)w3qZK(d-lp%C5YN zGv#1qT|hmf%BbH`-~P3~p5{iuI{M9y=ZWw>Qb$w?Wv#!lHO(QCCT9dd66tk*J*}^2>obdR_8Wt0dFW3OL1Zh2llE z=?xqtgI9!(!$6d@(E$m0OnLL-T}{R#c( zOF#oUvLhtAU1yAIO>l%z5PdV5;uJ1%{9V1?BO`WTjZvEU>iWiTQ%T&O178G)jwihy zxtD+Eqn6}1HqLhhcy=pIj{Zi{g?4pyg*!N$;X8fW5I+#-;`EKr(m}=({3!vfG3>Ml z>;ZPbUmZ;P9xiqIMbwioZkJ`6?}BOo-I4FX6<)YeGRN10708}`csbA#OtNo~oUQrH zTlj|&-zRgxeFtzerw6#AAP}tPO3y9+Uz_k9(f|Me literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/tree-small-rtl.png b/web/pgadmin/browser/static/css/aciTree/image/tree-small-rtl.png new file mode 100755 index 0000000000000000000000000000000000000000..9489def9ed5cc61f127209fe5edfbb9bc3824975 GIT binary patch literal 2351 zcmaKucTf{r7RG}H%%dn0gczv-C7?j)Qlyszqe6%jkzVrv1B4zx1p@}9J`AjM1Oy^Y zBnXP&L*UT@1f&RvN>`~;10);wznz`gd*=Mke0RQ?J9B5wxtDBp-9msD$_oGh1W-s* z45uqF7Gh=}VuSY% z33m(j0vLJX-MysDalu~U_+USRl!=W-P{XVy$0zdJXA4dJ)k=8NY& zpCSvQpSBPJiVFS)BsfKwpXbTt48-_<^tv$dIFBU)g1zTtXZJj*MKO**XZsZ#`#z(? z(kTzN@@_6Nl+P?$XY#+50GH09vzgp~mi4hHHq%$voNv;u9aTzRF_E(3qL?vWE(KhQ zWg`z|ENWF=Yf=}|E|xSm>j)rEKLK@}dUp?#L>$vIVtTXym^$#|2r0%%@g$SGO(|Kn zO8NSx{h1Rfq4-x}BlwwytSgiG^P~Xf`pxv3?TH(H{aUS!`isnj+tOs2CnA)*AW5_@ zQ|5zkIVbu>F>iw^<5gIQf?R7<`FT^1$rECJnocdFgS7;$fvUU0>bb;47+deIcq#f) z@Asibnm7N~Knr^4$tGik5*hK!d&KDoCbqTr`Sl$7ly<$-48^UKs+w3B!w*BPpM7=v zzKqW|Y?R~PHzyl-!Cow)(2K2W+AiOfF%x+xA9fUV{B#@ki$+UkBs$YAP4%Zl%oT}2 zdFtAk(6z+~Dlb}Ed>K89d)E>jSrUd?2ZNT? zGq3M=%@)yUJOLBgW#o#elb*yu*_Ejd-8tThw3LyfPPLKK^LHTh5Yz7{_8Jg19T;t< zZf`eZUo&^eJOLCF7!U2jS=z9id};09nmW}g{CqEb7v|;~n%RX`;441ENe z+qpsVw+xFaqSQ~Nq0a|b4=?G#@!K1=LFJCMV8im3WGmu1N`T7luua7GA(GSDe9i%- zr6;D>+3TBleRKX|jup`{%XXKNdejoO5z?MMHdYt7-!8aj=r?Ft%6H*Oo27#+1{H#R zHVKBe=TYyO!pM^4m6auxl^NEt2KqJRiZ+k(d;#Qnf@lW%A8)tevTIS@86AMzO`ke< z3qE)32&9H6&eVCxQEjV&kDxVgl-hjWZOY<*GL7Dc5@%_v_eJeA`(k|c5vQP%COKTN zAwh#!)_}h~+sk+i_C*bG4NiqzBg|T}!h*#3B%&EZdW<|i5v{}JaNWo^+PU@kfNkXJ z?b>V;qKi^hWQj4DY{~_Cys1Lyc~Ct@Vyvu%7KQvGFH;|kyA(xBjH@7yk5d+QHn`Ry znNQ@u(K=J^&nLTPuikzr3&tfjImG|?S&%FpnTka=pHk>M__jlD{;Ha~23Lx4OXw2MT_z z8&Z2zqxahp!1mhpY*$F39?wc0VqU+a+osB1WpQ__yRT6+TFU{2q5|bSNepQToI@C! z(af~l3GnDUfIVop{zeAcTOYe$H%<wlVUuMuA)$ zCs34g*#AKw7PT_-=p*2EnZt0MV{x#R!dM>gAM-nD7F5}9qn>3)Uh3%c zsMysTkSp4uDOIg1x*WXmnVpUr>PbwDhLVOH_!~EuKBO}pmD%ClEQx;i%U=_F{bM)p zoTcKgBIr4H_c=|UD3_?Mr=6EQxc^p=d#d7N%Y1xH>#a)BYG>{#?v0aH%U`_(1h2W9 zDZVJ_e5v>|Gps7jeItTNrWsAb)f0{lTdm;$8>XuVFO9-eGf{KBJH9q;*k7y5{2w7` zX|ycH-f2C{6Kdwr5%Ex*w7K7|n_LW`3-a@bYZrkR_GdfN=G#uxoZ++$5^9#<{`k`w zRTElGNCLQpB5K*VyNMa(Tq}P^wuORc<$fTF1gBJ&SbM@lErd3&>M`6ux4xo7U7@7e zbEQUE=GNa+WaqLzE$@!|q`n>Tal4IcF2U4!Q|+Lniv>+3)}ZzTG?X;0nEZDG*yl$> z8JFbN&5s`S-*pvagJg}6GMoop3Bj4VNfj4CN7BEQ)PG~$VCH7kKUdaO!JJPE0A+UF JwA$D;?%zcFXL0}l literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/css/aciTree/image/tree-small.png b/web/pgadmin/browser/static/css/aciTree/image/tree-small.png new file mode 100755 index 0000000000000000000000000000000000000000..ed13e084cc7f34e9341c48e5879e6d6845a42cd0 GIT binary patch literal 2320 zcmZ`*XHXN`5)Mc&Qi2p|K@cJqO3+XZ#e@U_1Lo2(ND(1GD3KDHf*^^8ULGLQ3{0{}?M{}zFf$&?-br5XY5K{$`U zM2Nc>9R#om#QO(<5Fyb)arkIl49M>M$*4B=DZZcLZ$G=}po@eMd;|y+5*`FFGBz-V z7#Kksb3$tX0I|!cGd7s`+nkEzFyIe$25hK;V=a}SC5))@u3}Tghn>ALOlBLzM--h1 zg>4Nc^)DQ$%~fPVs9gDnQko#i0TV#Oggl6yoHa2KaXtGNrNn`jPFgkAVuIQQsnw3M zVxO{sos(9)9+U#a-(q6id4y$8oLaZasa&qu*;$IqSsuhv+Yqus!OCyGUbU#MuSeBj zl`-I6WZK_qzd0z|p6QgFT*~mCtXQZ_K!jX(IlP(i+;hr5L z+g#U4xujqwS4u~`=35uF*zPhUH4KVC#wf>ZUz+w!A_t zqUF5yBpb)ReHVTjEoRsfww1k|hZG%?k6cSi^fJ3*^bQ8Y|CmrJ0espR@hW5SAnp$@ z;0BrZ0`E#K!XnX?A=|AiZX#~sKGu-+Gkm*YHWr@$+P*u>b88)~er5w)8 zwu(lBu1@u+2+tHedfbyR(!C&D2~Bplth?6Ug(H##P<~(f4c1J=a&Y`_+}!f?Zup8bSj%9^toN@t9S)e#mEhUU$r_j zbY<=PTlFxUm(uWe-``6^*9o2 z%VkE{F-}mGbN+%Nb3I6bzG0eAyF&P3L#gz#-mT$Z-E>-VpV|@oQ=R_^SZpSBe}47c zrz2W>nb^*JIUT!vLsWvQ;Nh#BnUNhr%aYb_J1y7J#gxsd8OZZ_8Lz+Kb682f*Hpv0 zRKKz6m7!&!yPF}sMk3Yo@O04yI{lC*kD!LMN+(t|Ig1GiHlXR>(7BOdkM;`k>*>qnh}40rYbVJ3LWnX_6FQ<_19lXa6)YFVlag+E-smxSqvaQgQU>0 zn6i_@W7TyQZI>(;pvyH;a4X>3B8xeFz3ysIXChVOYQnjQ@Ay=1!ZJ5$wANd!u)4Y6 zV1Ik_F;Ik^$u*HyX8n4jhp1r=Tv~2(FV^B`e<~XZVX7nCk8o~ zCxHqMc3)oe4cKw4v^){+t3|+Xb)f0nZw;ksm-S*X>7ot}3jZSGF(m<>lj-Bxbr))H z7@fVX`C5K8-ob)lhdak}M1rKR+H25`l9xK-Dhf{)Sj86TJ7{TK@??ze ztZ_OYbAwX}wDRU-fFv`7>z}H`;cU^Nj+XgdsA?I^GBOV?scTERrY;k;3F8Q*yT4LH zk%n%tVELO1;g&zy0Cs2x=hxehE-5fT5cR7-+t78Pd^ASG`&sf|{dpAwnu|QE$91A8 z#Ft;+*7baz^*@I_Z1t_JnMq0OLNnW^r-LwsB|+hO*K`yrJ}+Cg%`fp3p_QLh{fLus z>ks4R1GbtNz3It(mb6<_)Ur_yLxO(uqb!JzEIeGR-y z82)$~Br{hP&Wt*ta%7*?l9cz82u@Rq$5UH{v+fgMy2?_FPE;+@ege$3Hy#0)Dl#26 zY_6a##wE_Q2<;I;Pf}l~I7q#w2r8YUidLw?^Jb83@ZrFi2LsthPvM5feX^%hpS+Ow<$rSivdq{%+tb0aX`(ySv zKUP|iTih3Cw?Yr3O-zD282N9-G+(yZ8YFG1+q0&tVrs!mwfbCoNQ8p2qn>SWaHh=;7K2>bRL6ia&TTk6g#gg7NZ>Xf9R~8o~68Dh8$74V9ERGc_k^68^b= zOs@#&@Ts0wID?RjrHzkK4tdXgIStIuGmi9zlD+38sfoDV$l(J}as>H`dOe!XZ|?5o zo7^VVls6Rr*=H{ACRt|aS!=HT>ObYuTtuSkO-0ARfBy;e@Zk^(o5&hy2zP(5@kU#;9KaRd_YUB0zsM>c6apf{liC$!P6-bRV z2Ta_T^qxqf8Z5rUfrOi|>MKba9ZJ0smJ5K*62QJhb&o`wxmfJ^KIv literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciFragment.min.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciFragment.min.js new file mode 100755 index 000000000..85bd48d4b --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciFragment.min.js @@ -0,0 +1,15 @@ + +/* + * aciFragment jQuery Plugin v1.1.0 + * http://acoderinsights.ro + * + * Copyright (c) 2013 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.7.1 http://jquery.com + * + aciPlugin >= v1.1.1 https://github.com/dragosu/jquery-aciPlugin + * + * Date: Apr Fri 26 18:00 2013 +0200 + */ + +(function(e,t,n){var r={anchor:"anchor",poolDelay:250,scroll:{duration:"medium",easing:"linear"}};var i={__extend:function(){e.extend(this._instance,{lastHash:null,lastParsed:null,parsed:{},anchor:true,timeOut:null,"native":"onhashchange"in t&&(t.document.documentMode===n||t.document.documentMode>7)})},init:function(){var n=this;if(this.wasInit()){return}if(this._instance.native){e(t).bind("hashchange"+this._instance.nameSpace,function(){n._trigger()})}else{this._change()}this._instance.anchor=true;this._trigger();this._super()},_trigger:function(){this._instance.jQuery.trigger("acifragment",[this,this._instance.anchor]);this._instance.anchor=false},_change:function(){var e=this;var n=t.location.hash;if(n!=this._instance.lastHash){this._trigger();this._instance.lastHash=n}this._instance.timeOut=t.setTimeout(function(){e._change()},this._instance.options.poolDelay)},scroll:function(){var n=this.get(this._instance.options.anchor);if(n&&n.length){var r=e("#"+n+":first");if(!r.length){r=e('[name="'+n+'"]:first')}if(r.length){var i=r.get(0).getBoundingClientRect();var s=e(t).scrollLeft()+i.left,o=e(t).scrollTop()+i.top;if(this._instance.options.scroll){e("html,body").stop(true).animate({scrollLeft:s,scrollTop:o},this._instance.options.scroll)}else{t.scrollTo(s,o)}}}},click:function(e,t){var n=e.attr("href");if(n){var r=this.parse(n);this.update(r);if(t&&this.hasAnchor(r)){this.scroll()}}},parse:function(e){var n=e.indexOf("#"),r={};if(n!=-1){e=e.substr(n+1);var i=e.split("&"),s;for(var o in i){s=i[o].split("=");if(s.length>1){r[t.decodeURIComponent(s[0])]=t.decodeURIComponent(s[1])}else{r[this._instance.options.anchor]=t.decodeURIComponent(s[0])}}}return r},hasAnchor:function(e){return e[this._instance.options.anchor]&&e[this._instance.options.anchor].length>0},setAnchor:function(e){this.set(this._instance.options.anchor,e)},getAnchor:function(e){return this.get(this._instance.options.anchor,e)},parseHash:function(){var e=t.location.hash;if(e==this._instance.lastParsed){return this._instance.parsed}var n=this.parse(e);this._instance.parsed=n;this._instance.lastParsed=e;return n},get:function(e,r){var i=this.parseHash();if(i[e]!==null&&i[e]!==n&&t.String(i[e]).length){return i[e]}else{return r}},replace:function(e,r){var i=[];for(var s in e){if(e[s]!==null&&e[s]!==n&&t.String(e[s]).length){i[i.length]=t.encodeURIComponent(s)+"="+t.encodeURIComponent(e[s])}}if(!r&&this.hasAnchor(e)){this._instance.anchor=true}var o=t.location.hash;if(i.length){t.location.hash="#"+i.join("&")}else if(t.history&&t.history.pushState){t.history.pushState("",t.document.title,t.location.pathname+t.location.search)}else{t.location.hash=""}if(t.location.hash==o){this._trigger()}},update:function(e){var t=this.parseHash();for(var n in e){t[n]=e[n]}if(this.hasAnchor(e)){this._instance.anchor=true}this.replace(t,true)},set:function(e,t){var n=this.parseHash();n[e]=t;if(e==this._instance.options.anchor){this._instance.anchor=true}this.replace(n,true)},destroy:function(){if(!this.wasInit()){return}if(this._instance.native){e(t).unbind(this._instance.nameSpace)}t.clearTimeout(this._instance.timeOut);this._super()}};aciPluginClass.plugins.aciFragment=aciPluginClass.aciPluginUi.extend(i,"aciFragment");aciPluginClass.publish("aciFragment",r)})(jQuery,this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciPlugin.min.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciPlugin.min.js new file mode 100755 index 000000000..b315a857b --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciPlugin.min.js @@ -0,0 +1,12 @@ + +/* + * aciPlugin little jQuery plugin helper v1.5.1 + * http://acoderinsights.ro + * + * Copyright (c) 2013 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.2.3 http://jquery.com + */ + +(function(d,c,e){if(typeof aciPluginClass!=="undefined"){return}var a;this.aciPluginClass=function(){};aciPluginClass.extend=function(g,j){i.extend=arguments.callee;function i(){if(a){this._instance={};return this.__construct.apply(this,arguments)}}a=false;i.prototype=new this();a=true;var h=this.prototype;for(var f in g){i.prototype[f]=((typeof g[f]=="function")&&(f!="proxy"))?(function(k){return function(){var p=this._parent;this._parent=h;var n=this._super;this._super=h[k];var o=this._private;if(this._instance&&j){var m=this._instance._private;if(m[j]===e){m[j]={nameSpace:"."+j}}this._private=m[j]}var l=g[k].apply(this,arguments);this._parent=p;this._super=n;this._private=o;return l}})(f):g[f]}return i};var b=0;aciPluginClass.aciPluginUi=aciPluginClass.extend({__construct:function(k,l,i,h,j){var f="."+k;var g=l.data(f);if(g){this._instance=g._instance;return g.__request(i,h,j)}l.data(f,this);d.extend(true,this._instance,{_private:{},nameSpace:f,jQuery:l,options:d.extend(true,{},d.fn[k].defaults,(typeof i=="object")?i:{}),index:b++,wasInit:false});this.__extend();return this.__request(i,h,j)},__extend:function(){},__request:function(g,f,h){if((g===e)||(typeof g=="object")){if(this._instance.options.autoInit){this.init()}}else{if(typeof g=="string"){switch(g){case"init":this.init();break;case"api":return{object:this};case"options":if(f===e){return{object:this.options()}}else{if(typeof f=="string"){return{object:this.options(f)}}else{this.options(f)}}break;case"option":this.option(f,h);break;case"destroy":this.destroy();break}}}return this._instance.jQuery},proxy:function(j,h){var m=c.Array.prototype.slice;var f=m.call(arguments,2);var i=this,g=i._parent,l=i._super,k=i._private;return function(){i._parent=g;i._super=l;i._private=k;return j.apply(i,h?f.concat([this],m.call(arguments)):f.concat(m.call(arguments)))}},init:function(){if(!this._instance.wasInit){this._instance.wasInit=true;return true}return false},wasInit:function(){return this._instance.wasInit},__parent:function(h,f,l){var m=f.split(".");if(m.length>1){var j=h,k;for(var g in m){k=j;j=j[m[g]]}l.name=m[g];return k}l.name=f;return h},options:function(f){if(f){var i={name:null};var h;if(typeof f=="string"){h=this.__parent(this._instance.options,f,i);return h[i.name]}else{for(var g in f){h=this.__parent(this._instance.options,g,i);h[i.name]=f[g]}}}else{return this._instance.options}},option:function(g,i){var h={name:null};var f=this.__parent(this._instance.options,g,h);f[h.name]=i},destroy:function(){if(this._instance.wasInit){this._instance.wasInit=false;this._instance.jQuery.removeData(this._instance.nameSpace);return true}return false}});aciPluginClass.plugins={};aciPluginClass.publish=function(f,g){d.fn[f]=function(j,m,n){var h=null;for(var l=0,k=this.length;l= v1.7.1 http://jquery.com + * + aciPlugin >= v1.4.0 https://github.com/dragosu/jquery-aciPlugin + */ + +(function(d,c,e){var b={container:"ul",item:"li",distance:4,handle:"*",disable:"a,input,textarea,select,option,button",child:null,childHolder:'

    ',childHolderSelector:".aciSortableChild",exclude:null,vertical:true,placeholder:'
  • ',placeholderSelector:".aciSortablePlaceholder",helper:'
    ',helperSelector:".aciSortableHelper",relative:false,draggable:true,gluedPlaceholder:false,connectDrop:null,dropPosition:null,simpleDrop:null,scroll:80,scrollParent:"window",before:function(g){if(this._instance.options.exclude){var f=this.containerFrom(g);return !f.is(this._instance.options.exclude)&&!g.is(this._instance.options.exclude)}return true},start:function(g,h,f){var i=g.clone();i.children(this._instance.options.container).remove();f.html(i.text())},valid:function(j,h,k,g,l,i){if(this._instance.options.exclude){if(g){return !h.is(this._instance.options.exclude)}else{var f=this.containerFrom(h);return !f.is(this._instance.options.exclude)}}return true},drag:function(g,i,h,f){},create:function(g,f){f.append(this._instance.options.childHolder);return true},remove:function(g,f){f.children(this._instance.options.childHolderSelector).remove()},end:function(h,f,i,g){if(i.parent().length){i.after(h).detach()}g.detach()}};var a={__extend:function(){d.extend(this._instance,{sorting:false,item:null,hoverItem:null,isContainer:false,pointStart:null,pointNow:null,placeholder:null,helper:null,relative:null,children:null,scroll:false,lastCheck:{}})},init:function(){if(this.wasInit()){return}this._instance.jQuery.on("mousedown"+this._instance.nameSpace,this._instance.options.item,this.proxy(function(f){var g=d(f.target);if(!g.is(this._instance.options.handle)||g.is(this._instance.options.disable)){return}if(!g.is(this._instance.options.disable)){f.preventDefault()}if(g.is(this._instance.options.container)){d(c.document.body).css("cursor","no-drop")}else{this._delayStart(f)}})).on("mousemove"+this._instance.nameSpace,this._instance.options.item,this.proxy(function(h){if(this._instance.sorting){h.stopPropagation();this._instance.isContainer=false;var g=this.itemFrom(h.target);if(this._instance.item.has(g).length){this._instance.hoverItem=null}else{if(this._instance.options.dropPosition===null){this._instance.hoverItem=g}else{var f=this.containerFrom(h.target);this._dropPosition(f)}}}this._drag(h)})).on("mousemove"+this._instance.nameSpace,this._instance.options.container,this.proxy(function(g){if(this._instance.sorting){g.stopPropagation();var f=this.containerFrom(g.target);if(!this._instance.item.has(f).length){if(this.isEmpty(f)){this._instance.hoverItem=f;this._instance.isContainer=true}else{this._instance.isContainer=false;if(this._instance.options.dropPosition===null){this._instance.hoverItem=this._closestFrom(g)}else{this._dropPosition(f)}}}}this._drag(g)}));this._initConnect();this._initSimple();d(c.document).bind("mousemove"+this._instance.nameSpace+this._instance.index,this.proxy(function(f){if(this._instance.sorting){this._instance.hoverItem=null;this._drag(f)}})).on("mousemove"+this._instance.nameSpace+this._instance.index,this._instance.options.helperSelector,this.proxy(function(g){if(this._instance.sorting){var f=this._fromCursor(g);if(f){this._instance.jQuery.trigger(d.Event("mousemove",{target:f,pageX:g.pageX,pageY:g.pageY}));g.stopPropagation()}}})).bind("selectstart"+this._instance.nameSpace+this._instance.index,this.proxy(function(f){if(this._instance.sorting){f.preventDefault()}})).bind("mouseup"+this._instance.nameSpace+this._instance.index,this.proxy(function(){if(this._instance.sorting){this._end()}else{this._instance.item=null;d(c.document.body).css("cursor","default")}}));this._super()},_dropPosition:function(f){if(this._instance.options.dropPosition==-1){this._instance.hoverItem=this._firstItem(f)}else{this._instance.hoverItem=this._lastItem(f)}if(!this._instance.hoverItem.length){this._instance.hoverItem=f;this._instance.isContainer=true}},_firstItem:function(f){return f.children(this._instance.options.item).not(this._instance.options.placeholderSelector).first()},_lastItem:function(f){return f.children(this._instance.options.item).not(this._instance.options.placeholderSelector).last()},_closestFrom:function(j){var i=null;var h=d(j.target);if(this._instance.options.vertical){var f=d(c).scrollTop();var g=h.height();h.find(this._instance.options.item).not(this._instance.options.placeholderSelector).each(function(){var k=this.getBoundingClientRect();var l=c.Math.abs(f+k.top+(k.bottom-k.top)/2-j.pageY);if(l');d(c.document.body).append(g);this._instance.item=g;this._instance.placeholder.detach();this._instance.helper.detach();this._end();g.remove();h._start()}},hasItem:function(f){return this._instance.jQuery.has(f).length>0},sortableFrom:function(f){if(this._instance.jQuery.has(f).length){return this._instance.jQuery}if(this._instance.options.connectDrop){return d(f).closest(this._instance.options.connectDrop)}return d()},itemFrom:function(f){return d(f).closest(this._instance.options.item)},containerFrom:function(f){return d(f).closest(this._instance.options.container)},hasChildrens:function(f){return f.children(this._instance.options.container).children(this._instance.options.item).not(this._instance.options.placeholderSelector).length>0},hasContainer:function(f){return f.children(this._instance.options.container).length>0},isEmpty:function(f){return !f.children(this._instance.options.item).not(this._instance.options.placeholderSelector).length},_delayStart:function(h){var g=this.itemFrom(h.target);if(this._call("before",{item:g})){this._instance.item=g;this._instance.pointStart={x:h.pageX,y:h.pageY};if(this._instance.options.relative){var j=d(c).scrollTop();var i=d(c).scrollLeft();var f=this._instance.item.get(0).getBoundingClientRect();this._instance.relative={x:f.left+i-h.pageX,y:f.top+j-h.pageY}}else{this._instance.relative={x:0,y:0}}this._drag(h)}else{d(c.document.body).css("cursor","no-drop")}},_start:function(){this._instance.sorting=true;if(!this._instance.placeholder){this._instance.placeholder=d(this._instance.options.placeholder)}if(!this._instance.helper){this._instance.helper=d(this._instance.options.helper)}this._call("start",{item:this._instance.item,placeholder:this._instance.placeholder,helper:this._instance.helper});if(this._instance.options.gluedPlaceholder){this._instance.item.after(this._instance.placeholder)}d(c.document.body).append(this._instance.helper);d(c.document.body).css("cursor","move")},_minDistance:function(){return(c.Math.abs(this._instance.pointStart.x-this._instance.pointNow.x)>this._instance.options.distance)||(c.Math.abs(this._instance.pointStart.y-this._instance.pointNow.y)>this._instance.options.distance)},_drag:function(f){this._instance.pointNow={x:f.pageX,y:f.pageY};if(this._instance.sorting){this._helper();this._placeholder()}else{if(this._instance.item){if(this._minDistance()){this._start()}}}},_onDrag:function(f){this._call("drag",{item:this._instance.item,placeholder:this._instance.placeholder,isValid:f,helper:this._instance.helper})},_isValid:function(g,f){if(!this._instance.options.draggable&&this.hasItem(this._instance.item)&&(this._instance.isContainer||(this.containerFrom(this._instance.item).get(0)!=this.containerFrom(this._instance.hoverItem).get(0)))){return false}if(this._call("valid",{item:this._instance.item,hover:this._instance.hoverItem,before:f?null:((g===null)?false:g),isContainer:f?true:this._instance.isContainer,placeholder:this._instance.placeholder,helper:this._instance.helper})){d(c.document.body).css("cursor","move");return true}return false},_onCreate:function(){this._onRemove();if(this._instance.hoverItem.is(this._instance.options.exclude)){return false}if(this._isSimple()){return false}if(this._call("create",{item:this._instance.item,hover:this._instance.hoverItem})){this._instance.childItem=this._instance.hoverItem;this._instance.hoverItem=this._instance.hoverItem.children(this._instance.options.childHolderSelector);this._instance.isContainer=true;this._placeholder();return true}return false},_onRemove:function(f){if(this._instance.childItem&&(!f||(f.get(0)!=this._instance.childItem.get(0)))){if(this._instance.placeholder){this._instance.placeholder.detach()}if(!this.hasChildrens(this._instance.childItem)){this._call("remove",{item:this._instance.item,hover:this._instance.childItem})}this._instance.childItem=null}},_wasValid:function(j,h,g){if(this._instance.lastCheck){var i=g?this._instance.lastCheck.check:this._instance.lastCheck.normal;var f=i&&(i.hoverItem.get(0)==this._instance.hoverItem.get(0))&&(i.before===j)&&(i.create===h)&&(i.isContainer==this._instance.isContainer)}this._instance.lastCheck[g?"check":"normal"]={hoverItem:this._instance.hoverItem,before:j,create:h,isContainer:this._instance.isContainer};return f},_isSimple:function(){return this._instance.options.simpleDrop&&this._instance.hoverItem&&this._instance.hoverItem.is(this._instance.options.simpleDrop)},_placeholder:function(){this._instance.pointStart=this._instance.pointNow;if(this._instance.hoverItem){if(this._instance.hoverItem.is(this._instance.options.placeholderSelector)){return}if(this._instance.isContainer){if(this._wasValid(null,false)){return}if(this._isValid(null)){this._instance.hoverItem.append(this._instance.placeholder);this._onDrag(true);return}}else{if(this._instance.hoverItem.get(0)!=this._instance.item.get(0)){var m=false,j=false;var k=this._instance.hoverItem.get(0).getBoundingClientRect();var i=this._instance.hoverItem.children(this._instance.options.container);if(this._instance.options.vertical){var n=d(c).scrollTop();var g=k.bottom-((i.length&&i.is(":visible"))?i.outerHeight(true):0);if(this._instance.options.child&&(this._instance.options.draggable||!this.hasItem(this._instance.item))&&!this.hasChildrens(this._instance.hoverItem)){var h=(g-k.top)*(0.5-this._instance.options.child/200);if((this._instance.pointNow.y>n+k.top+h)&&(this._instance.pointNow.yn+k.left+h)||(this._instance.pointNow.xq)&&(this._instance.pointNow.x>k+o.left)&&(this._instance.pointNow.x0){var f=p+o.top+l-this._instance.pointNow.y;g.scrollTop(c.Math.max(h-this._amount(l,f),0));n=true}}else{if(this._instance.pointNow.y>p+o.bottom-l){if(h+qi)&&(this._instance.pointNow.y>p+o.top)&&(this._instance.pointNow.y0){var f=k+o.left+l-this._instance.pointNow.x;g.scrollLeft(c.Math.max(h-this._amount(l,f),0));n=true}}else{if(this._instance.pointNow.x>k+o.right-l){if(h+i= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * This extension adds checkbox support to aciTree, + * should be used with the selectable extension. + * + * The are a few extra properties for the item data: + * + * { + * ... + * checkbox: true, // TRUE (default) means the item will have a checkbox (can be omitted if the `radio` extension is not used) + * checked: false, // if should be checked or not + * ... + * } + * + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + checkbox: false, // if TRUE then each item will have a checkbox + checkboxChain: true, + // if TRUE the selection will propagate to the parents/children + // if -1 the selection will propagate only to parents + // if +1 the selection will propagate only to children + // if FALSE the selection will not propagate in any way + checkboxBreak: true, // if TRUE then a missing checkbox will break the chaining + checkboxClick: false // if TRUE then a click will trigger a state change only when made over the checkbox itself + }; + + // aciTree checkbox extension + + var aciTree_checkbox = { + // init checkbox + _checkboxInit: function() { + this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) { + switch (eventName) { + case 'loaded': + // check/update on item load + api._checkboxLoad(item); + break; + } + }).bind('keydown' + this._private.nameSpace, this.proxy(function(e) { + switch (e.which) { + case 32: // space + // support `selectable` extension + if (this.extSelectable && this.extSelectable() && !e.ctrlKey) { + var item = this.focused(); + if (this.hasCheckbox(item) && this.isEnabled(item)) { + if (this.isChecked(item)) { + this.uncheck(item); + } else { + this.check(item); + } + e.stopImmediatePropagation(); + // prevent page scroll + e.preventDefault(); + } + } + break; + } + })).on('click' + this._private.nameSpace, '.aciTreeItem', this.proxy(function(e) { + if (!this._instance.options.checkboxClick || $(e.target).is('.aciTreeCheck')) { + var item = this.itemFrom(e.target); + if (this.hasCheckbox(item) && this.isEnabled(item) && (!this.extSelectable || !this.extSelectable() || (!e.ctrlKey && !e.shiftKey))) { + // change state on click + if (this.isChecked(item)) { + this.uncheck(item); + } else { + this.check(item); + } + e.preventDefault(); + } + } + })); + }, + // override `_initHook` + _initHook: function() { + if (this.extCheckbox()) { + this._checkboxInit(); + } + // call the parent + this._super(); + }, + // override `_itemHook` + _itemHook: function(parent, item, itemData, level) { + if (this.extCheckbox()) { + // support `radio` extension + var radio = this.extRadio && this.hasRadio(item); + if (!radio && (itemData.checkbox || ((itemData.checkbox === undefined) && (!this.extRadio || !this.extRadio())))) { + this._checkboxDOM.add(item, itemData); + } + } + // call the parent + this._super(parent, item, itemData, level); + }, + // low level DOM functions + _checkboxDOM: { + // add item checkbox + add: function(item, itemData) { + domApi.addClass(item[0], itemData.checked ? ['aciTreeCheckbox', 'aciTreeChecked'] : 'aciTreeCheckbox'); + var text = domApi.childrenByClass(item[0].firstChild, 'aciTreeText'); + var parent = text.parentNode; + var label = window.document.createElement('LABEL'); + var check = window.document.createElement('SPAN'); + check.className = 'aciTreeCheck'; + label.appendChild(check); + label.appendChild(text); + parent.appendChild(label); + item[0].firstChild.setAttribute('aria-checked', !!itemData.checked); + }, + // remove item checkbox + remove: function(item) { + domApi.removeClass(item[0], ['aciTreeCheckbox', 'aciTreeChecked', 'aciTreeTristate']); + var text = domApi.childrenByClass(item[0].firstChild, 'aciTreeText'); + var label = text.parentNode; + var parent = label.parentNode; + parent.replaceChild(text, label) + item[0].firstChild.removeAttribute('aria-checked'); + }, + // (un)check items + check: function(items, state) { + domApi.toggleListClass(items.toArray(), 'aciTreeChecked', state, function(node) { + node.firstChild.setAttribute('aria-checked', state); + }); + }, + // (un)set tristate items + tristate: function(items, state) { + domApi.toggleListClass(items.toArray(), 'aciTreeTristate', state); + } + }, + // update items on load, starting from the loaded node + _checkboxLoad: function(item) { + if (this._instance.options.checkboxChain === false) { + // do not update on load + return; + } + var state = undefined; + if (this.hasCheckbox(item)) { + if (this.isChecked(item)) { + if (!this.checkboxes(this.children(item, false, true), true).length) { + // the item is checked but no children are, check them all + state = true; + } + } else { + // the item is not checked, uncheck all children + state = false; + } + } + this._checkboxUpdate(item, state); + }, + // get children list + _checkboxChildren: function(item) { + if (this._instance.options.checkboxBreak) { + var list = []; + var process = this.proxy(function(item) { + var children = this.children(item, false, true); + children.each(this.proxy(function(element) { + var item = $(element); + // break on missing checkbox + if (this.hasCheckbox(item)) { + list.push(element); + process(item); + } + }, true)); + }); + process(item); + return $(list); + } else { + var children = this.children(item, true, true); + return this.checkboxes(children); + } + }, + // update checkbox state + _checkboxUpdate: function(item, state) { + // update children + var checkDown = this.proxy(function(item, count, state) { + var children = this.children(item, false, true); + var total = 0; + var checked = 0; + children.each(this.proxy(function(element) { + var item = $(element); + var subCount = { + total: 0, + checked: 0 + }; + if (this.hasCheckbox(item)) { + if ((state !== undefined) && (this._instance.options.checkboxChain !== -1)) { + this._checkboxDOM.check(item, state); + } + total++; + if (this.isChecked(item)) { + checked++; + } + checkDown(item, subCount, state); + } else { + if (this._instance.options.checkboxBreak) { + var reCount = { + total: 0, + checked: 0 + }; + checkDown(item, reCount); + } else { + checkDown(item, subCount, state); + } + } + total += subCount.total; + checked += subCount.checked; + }, true)); + if (item) { + this._checkboxDOM.tristate(item, (checked > 0) && (checked != total)); + count.total += total; + count.checked += checked; + } + }); + var count = { + total: 0, + checked: 0 + }; + checkDown(item, count, state); + // update parents + var checkUp = this.proxy(function(item, tristate, state) { + var parent = this.parent(item); + if (parent.length) { + if (!tristate) { + var children = this._checkboxChildren(parent); + var checked = this.checkboxes(children, true).length; + var tristate = (checked > 0) && (checked != children.length); + } + if (this.hasCheckbox(parent)) { + if ((state !== undefined) && (this._instance.options.checkboxChain !== 1)) { + this._checkboxDOM.check(parent, tristate ? true : state); + } + this._checkboxDOM.tristate(parent, tristate); + checkUp(parent, tristate, state); + } else { + if (this._instance.options.checkboxBreak) { + checkUp(parent); + } else { + checkUp(parent, tristate, state); + } + } + } + }); + checkUp(item, undefined, state); + }, + // test if item have a checkbox + hasCheckbox: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeCheckbox'); + }, + // add checkbox + addCheckbox: function(item, options) { + options = this._options(options, 'checkboxadded', 'addcheckboxfail', 'wascheckbox', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeaddcheckbox', options)) { + this._fail(item, options); + return; + } + if (this.hasCheckbox(item)) { + this._notify(item, options); + } else { + var process = function() { + this._checkboxDOM.add(item, { + }); + this._success(item, options); + }; + // support `radio` extension + if (this.extRadio && this.hasRadio(item)) { + // remove radio first + this.removeRadio(item, this._inner(options, { + success: process, + fail: options.fail + })); + } else { + process.apply(this); + } + } + } else { + this._fail(item, options); + } + }, + // remove checkbox + removeCheckbox: function(item, options) { + options = this._options(options, 'checkboxremoved', 'removecheckboxfail', 'notcheckbox', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeremovecheckbox', options)) { + this._fail(item, options); + return; + } + if (this.hasCheckbox(item)) { + this._checkboxDOM.remove(item); + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // test if it's checked + isChecked: function(item) { + if (this.hasCheckbox(item)) { + return domApi.hasClass(item[0], 'aciTreeChecked'); + } + // support `radio` extension + if (this._super) { + // call the parent + return this._super(item); + } + return false; + }, + // check checkbox + check: function(item, options) { + if (this.extCheckbox && this.hasCheckbox(item)) { + options = this._options(options, 'checked', 'checkfail', 'waschecked', item); + // a way to cancel the operation + if (!this._trigger(item, 'beforecheck', options)) { + this._fail(item, options); + return; + } + if (this.isChecked(item)) { + this._notify(item, options); + } else { + this._checkboxDOM.check(item, true); + if (this._instance.options.checkboxChain !== false) { + // chain them + this._checkboxUpdate(item, true); + } + this._success(item, options); + } + } else { + // support `radio` extension + if (this._super) { + // call the parent + this._super(item, options); + } else { + this._trigger(item, 'checkfail', options); + this._fail(item, options); + } + } + }, + // uncheck checkbox + uncheck: function(item, options) { + if (this.extCheckbox && this.hasCheckbox(item)) { + options = this._options(options, 'unchecked', 'uncheckfail', 'notchecked', item); + // a way to cancel the operation + if (!this._trigger(item, 'beforeuncheck', options)) { + this._fail(item, options); + return; + } + if (this.isChecked(item)) { + this._checkboxDOM.check(item, false); + if (this._instance.options.checkboxChain !== false) { + // chain them + this._checkboxUpdate(item, false); + } + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + // support `radio` extension + if (this._super) { + // call the parent + this._super(item, options); + } else { + this._trigger(item, 'uncheckfail', options); + this._fail(item, options); + } + } + }, + // filter items with checkbox by state (if set) + checkboxes: function(items, state) { + if (state !== undefined) { + return $(domApi.withClass(items.toArray(), state ? ['aciTreeCheckbox', 'aciTreeChecked'] : 'aciTreeCheckbox', state ? null : 'aciTreeChecked')); + } + return $(domApi.withClass(items.toArray(), 'aciTreeCheckbox')); + }, + // override `_serialize` + _serialize: function(item, callback) { + var data = this._super(item, callback); + if (data && this.extCheckbox()) { + if (data.hasOwnProperty('checkbox')) { + data.checkbox = this.hasCheckbox(item); + data.checked = this.isChecked(item); + } else if (this.hasCheckbox(item)) { + if (this.extRadio && this.extRadio()) { + data.checkbox = true; + } + data.checked = this.isChecked(item); + } + } + return data; + }, + // override `serialize` + serialize: function(item, what, callback) { + if (what == 'checkbox') { + var serialized = ''; + var children = this.children(item, true, true); + this.checkboxes(children, true).each(this.proxy(function(element) { + var item = $(element); + if (callback) { + serialized += callback.call(this, item, what, this.getId(item)); + } else { + serialized += this._instance.options.serialize.call(this, item, what, this.getId(item)); + } + }, true)); + return serialized; + } + return this._super(item, what, callback); + }, + // test if item is in tristate + isTristate: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeTristate'); + }, + // filter tristate items + tristate: function(items) { + return $(domApi.withClass(items.toArray(), 'aciTreeTristate')); + }, + // test if checkbox is enabled + extCheckbox: function() { + return this._instance.options.checkbox; + }, + // override set `option` + option: function(option, value) { + if (this.wasInit() && !this.isLocked()) { + if ((option == 'checkbox') && (value != this.extCheckbox())) { + if (value) { + this._checkboxInit(); + } else { + this._checkboxDone(); + } + } + } + // call the parent + this._super(option, value); + }, + // done checkbox + _checkboxDone: function(destroy) { + this._instance.jQuery.unbind(this._private.nameSpace); + this._instance.jQuery.off(this._private.nameSpace, '.aciTreeItem'); + if (!destroy) { + // remove checkboxes + this.checkboxes(this.children(null, true, true)).each(this.proxy(function(element) { + this.removeCheckbox($(element)); + }, true)); + } + }, + // override `_destroyHook` + _destroyHook: function(unloaded) { + if (unloaded) { + this._checkboxDone(true); + } + // call the parent + this._super(unloaded); + } + + }; + + // extend the base aciTree class and add the checkbox stuff + aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_checkbox, 'aciTreeCheckbox'); + + // add extra default options + aciPluginClass.defaults('aciTree', options); + + // for internal access + var domApi = aciPluginClass.plugins.aciTree_dom; + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.column.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.column.js new file mode 100755 index 000000000..aa5bf7114 --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.column.js @@ -0,0 +1,250 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * This extension adds multiple column support to aciTree. + * + * The `columnData` option is used to tell what are the columns and show one or + * more values that will be read from the item data object. + * + * Column data is an array of column definitions, each column definition is + * an object: + * + * { + * width: 100, + * props: 'column_x', + * value: 'default' + * } + * + * where the `width` is the column width in [px], if undefined - then the value + * from the CSS will be used; the `props` is the property name that will be + * read from the item data, if undefined (or the `item-data[column.props]` + * is undefined) then a default value will be set for the column: the `value`. + * + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + columnData: [] // column definitions list + }; + + // aciTree columns extension + // adds item columns, set width with CSS or using the API + + var aciTree_column = { + __extend: function() { + // add extra data + $.extend(this._private, { + propsIndex: { // column index cache + } + }); + // call the parent + this._super(); + }, + // override `_initHook` + _initHook: function() { + if (this._instance.options.columnData.length) { + // check column width + var found = false, data; + for (var i in this._instance.options.columnData) { + data = this._instance.options.columnData[i]; + if (data.width !== undefined) { + // update column width + this._updateCss('.aciTree.aciTree' + this._instance.index + ' .aciTreeColumn' + i, 'width:' + data.width + 'px;'); + found = true; + } + this._private.propsIndex[data.props] = i; + } + if (found) { + // at least a column width set + this._updateWidth(); + } + } + // call the parent + this._super(); + }, + // read property value from a CSS class name + _getCss: function(className, property, numeric) { + var id = '_getCss_' + window.String(className).replace(/[^a-z0-9_-]/ig, '_'); + var test = $('body').find('#' + id); + if (!test.length) { + if (className instanceof Array) { + var style = '', end = ''; + for (var i in className) { + style += '
    '; + end += '
    '; + } + style += end; + } else { + var style = '
    '; + } + $('body').append('
    ' + style + '
    '); + test = $('body').find('#' + id); + } + var value = test.find('*:last').css(property); + if (numeric) { + value = parseInt(value); + if (isNaN(value)) { + value = null; + } + } + return value; + }, + // dynamically change a CSS class definition + _updateCss: function(className, definition) { + var id = '_updateCss_' + window.String(className).replace('>', '_gt_').replace(/[^a-z0-9_-]/ig, '_'); + var style = ''; + var test = $('body').find('#' + id); + if (test.length) { + test.replaceWith(style); + } else { + $('body').prepend(style); + } + }, + // get column width + // `index` is the #0 based column index + getWidth: function(index) { + if ((index >= 0) && (index < this.columns())) { + return this._getCss(['aciTree aciTree' + this._instance.index, 'aciTreeColumn' + index], 'width', true); + } + return null; + }, + // set column width + // `index` is the #0 based column index + setWidth: function(index, width) { + if ((index >= 0) && (index < this.columns())) { + this._updateCss('.aciTree.aciTree' + this._instance.index + ' .aciTreeColumn' + index, 'width:' + width + 'px;'); + this._updateWidth(); + } + }, + // update item margins + _updateWidth: function() { + var width = 0; + for (var i in this._instance.options.columnData) { + if (this.isColumn(i)) { + width += this.getWidth(i); + } + } + var icon = this._getCss(['aciTree', 'aciTreeIcon'], 'width', true); + // add item padding + width += this._getCss(['aciTree', 'aciTreeItem'], 'padding-left', true) + this._getCss(['aciTree', 'aciTreeItem'], 'padding-right', true); + this._updateCss('.aciTree.aciTree' + this._instance.index + ' .aciTreeItem', 'margin-right:' + (icon + width) + 'px;'); + this._updateCss('.aciTree[dir=rtl].aciTree' + this._instance.index + ' .aciTreeItem', 'margin-right:0;margin-left:' + (icon + width) + 'px;'); + }, + // test if column is visible + // `index` is the #0 based column index + isColumn: function(index) { + if ((index >= 0) && (index < this.columns())) { + return this._getCss(['aciTree aciTree' + this._instance.index, 'aciTreeColumn' + index], 'display') != 'none'; + } + return false; + }, + // get column index by `props` + // return -1 if the column does not exists + columnIndex: function(props) { + if (this._private.propsIndex[props] !== undefined) { + return this._private.propsIndex[props]; + } + return -1; + }, + // get the column count + columns: function() { + return this._instance.options.columnData.length; + }, + // set column to be visible or hidden + // `index` is the #0 based column index + // if `show` is undefined then the column visibility will be toggled + toggleColumn: function(index, show) { + if ((index >= 0) && (index < this.columns())) { + if (show === undefined) { + var show = !this.isColumn(index); + } + this._updateCss('.aciTree.aciTree' + this._instance.index + ' .aciTreeColumn' + index, 'display:' + (show ? 'inherit' : 'none') + ';'); + this._updateWidth(); + } + }, + // override `_itemHook` + _itemHook: function(parent, item, itemData, level) { + if (this.columns()) { + var position = domApi.childrenByClass(item[0].firstChild, 'aciTreeEntry'), data, column; + for (var i in this._instance.options.columnData) { + data = this._instance.options.columnData[i]; + column = this._createColumn(itemData, data, i); + position.insertBefore(column, position.firstChild); + } + } + // call the parent + this._super(parent, item, itemData, level); + }, + // create column markup + // `itemData` item data object + // `columnData` column data definition + // `index` is the #0 based column index + _createColumn: function(itemData, columnData, index) { + var value = columnData.props && (itemData[columnData.props] !== undefined) ? itemData[columnData.props] : + ((columnData.value === undefined) ? '' : columnData.value); + var column = window.document.createElement('DIV'); + column.className = 'aciTreeColumn aciTreeColumn' + index; + column.innerHTML = value.length ? value : ' '; + return column; + }, + // set column content + // `options.index` the #0 based column index + // `options.value` is the new content + // `options.oldValue` will keep the old content + setColumn: function(item, options) { + options = this._options(options, 'columnset', 'columnfail', 'wascolumn', item); + if (this.isItem(item) && (options.index >= 0) && (options.index < this.columns())) { + // a way to cancel the operation + if (!this._trigger(item, 'beforecolumn', options)) { + this._fail(item, options); + return; + } + var data = this.itemData(item); + // keep the old one + options.oldValue = data[this._instance.options.columnData[options.index].props]; + if (options.value == options.oldValue) { + this._notify(item, options); + } else { + // set the column + item.children('.aciTreeLine').find('.aciTreeColumn' + options.index).html(options.value); + // remember this one + data[this._instance.options.columnData[options.index].props] = options.value; + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // get column content + getColumn: function(item, index) { + if ((index >= 0) && (index < this.columns())) { + var data = this.itemData(item); + return data ? data[this._instance.options.columnData[index].props] : null; + } + return null; + } + }; + + // extend the base aciTree class and add the columns stuff + aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_column, 'aciTreeColumn'); + + // add extra default options + aciPluginClass.defaults('aciTree', options); + + // for internal access + var domApi = aciPluginClass.plugins.aciTree_dom; + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.core.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.core.js new file mode 100755 index 000000000..24e766b62 --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.core.js @@ -0,0 +1,2544 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * The aciTree core. + * + * A few words about how item data looks like: + * + * for a leaf node (a node that does not have any children): + * + * { + * id: 'some_file_ID', // should be unique item ID + * label: 'This is a File Item', // the item label (text value) + * inode: false, // FALSE means is a leaf node (can be omitted) + * icon: 'fileIcon', // CSS class name for the icon (if any), can also be an Array ['CSS class name', background-position-x, background-position-y] + * disabled: false, // TRUE means the item is disabled (can be omitted) + * random_prop: 'random 1' // sample user defined property (you can have any number defined) + * } + * + * for a inner node (a node that have at least a children under it): + * + * { + * id: 'some_folder_ID', // should be unique item ID + * label: 'This is a Folder Item', // the item label (text value) + * inode: true, // can also be NULL to find at runtime if its an inode (on load will be transformed in a leaf node if there aren't any children) + * open: false, // if TRUE then the node will be opened when the tree is loaded (can be omitted) + * icon: 'folderIcon', // CSS class name for the icon (if any), can also be an Array ['CSS class name', background-position-x, background-position-y] + * disabled: false, // TRUE means the item is disabled (can be omitted) + * source: 'myDataSource', // the data source name (if any) to read the children from, by default `aciTree.options.ajax` is used + * branch: [ // a list of children + * { ... item data ... }, + * { ... item data ... }, + * ... + * ], + * random_prop: 'random 2' // sample user defined property (you can have any number defined) + * } + * + * The `branch` array can be empty, in this case the children will be loaded when the node will be opened for the first time. + * + * Please note that the item data should be valid (in the expected format). No checking is done and errors can appear on invalid data. + * + * One note about a item: a item is always the LI element with the class 'aciTreeLi'. + * The children of a node are all added under a UL element with the class 'aciTreeUl'. + * + * Almost all API functions expect only one item. If you need to process more at once then you'll need to loop between all of them yourself. + * + * The `options` parameter for all API methods (when there is one) is a object with the properties (not all are required or used): + * + * { + * uid: string -> operation UID (defaults to `ui`) + * success: function (item, options) -> callback to be called on success (you can access plugin API with `this` keyword inside the callback) + * fail: function (item, options) -> callback to be called on fail (you can access plugin API with `this` keyword inside the callback) + * notify: function (item, options) -> notify callback (internal use for when already in the requested state, will call `success` by default) + * expand: true/false -> propagate on open/toggle + * collapse: true/false -> propagate on close/toggle + * unique: true/false -> should other branches be closed (on open/toggle) ? + * unanimated: true/false -> if it's TRUE then no animations are to be run (used on open/close/toggle) + * itemData: object[item data]/array[item data] -> used when adding/updating items + * } + * + * Note: when using the API methods that support the `options` parameter, you will need to use the success/fail callbacks if you need to do + * any processing after the API call. This because there can be async operations that will complete at a later time and the API methods will + * exit before the job is actually completed. This will happen when items are loaded with AJAX, on animations and other delayed operations (see _queue). + * + */ + +(function($, window, undefined) { + + // default options + + var options = { + // the AJAX options (see jQuery.ajax) where the `success` and `error` are overridden by aciTree + ajax: { + url: null, // URL from where to take the data, something like `path/script?nodeId=` (the node ID value will be added for each request) + dataType: 'json' + }, + dataSource: null, // a list of data sources to be used (each entry in `aciTree.options.ajax` format) + rootData: null, // initial ROOT data for the Tree (if NULL then one initial AJAX request is made on init) + queue: { + async: 4, // the number of simultaneous async (AJAX) tasks + interval: 50, // interval [ms] after which to insert a `delay` + delay: 20 // how many [ms] delay between tasks (after `interval` expiration) + }, + loaderDelay: 500, // how many msec to wait before showing the main loader ? (on lengthy operations) + expand: false, // if TRUE then all children of a node are expanded when the node is opened + collapse: false, // if TRUE then all children of a node are collapsed when the node is closed + unique: false, // if TRUE then a single tree branch will stay open, the oters are closed when a node is opened + empty: false, // if TRUE then all children of a node are removed when the node is closed + show: {// show node/ROOT animation (default is slideDown) + props: { + 'height': 'show' + }, + duration: 'medium', + easing: 'linear' + }, + animateRoot: true, // if the ROOT should be animated on init + hide: {// hide node animation (default is slideUp) + props: { + 'height': 'hide' + }, + duration: 'medium', + easing: 'linear' + }, + view: {// scroll item into view animation + duration: 'medium', + easing: 'linear' + }, + // called for each AJAX request when a node needs to be loaded + // `item` is the item who will be loaded + // `settings` is the `aciTree.options.ajax` object or an entry from `aciTree.options.dataSource` + ajaxHook: function(item, settings) { + // the default implementation changes the URL by adding the item ID at the end + settings.url += (item ? this.getId(item) : ''); + }, + // called after each item is created but before is inserted into the DOM + // `parent` is the parent item (can be empty) + // `item` is the new created item + // `itemData` is the object used to create the item + // `level` is the #0 based item level + itemHook: function(parent, item, itemData, level) { + // there is no default implementation + }, + // called for each item to serialize its value + // `item` is the tree item to be serialized + // `what` is the option telling what is being serialized + // `value` is the current serialized value (from the `item`, value type depending of `what`) + serialize: function(item, what, value) { + if (typeof what == 'object') { + return value; + } else { + // the default implementation uses a `|` (pipe) character to separate values + return '|' + value; + } + } + }; + + // aciTree plugin core + + var aciTree_core = { + // add extra data + __extend: function() { + $.extend(this._instance, { + queue: new this._queue(this, this._instance.options.queue) // the global tree queue + }); + $.extend(this._private, { + locked: false, // to tell the tree state + itemClone: {// keep a clone of the LI for faster tree item creation + }, + // timeouts for the loader + loaderHide: null, + loaderInterval: null, + // busy delay counter + delayBusy: 0 + }); + }, + // init the treeview + init: function(options) { + options = this._options(options); + // check if was init already + if (this.wasInit()) { + this._trigger(null, 'wasinit', options); + this._fail(null, options); + return; + } + // check if is locked + if (this.isLocked()) { + this._trigger(null, 'locked', options); + this._fail(null, options); + return; + } + // a way to cancel the operation + if (!this._trigger(null, 'beforeinit', options)) { + this._trigger(null, 'initfail', options); + this._fail(null, options); + return; + } + this._private.locked = true; + this._instance.jQuery.addClass('aciTree' + this._instance.index).attr('role', 'tree').on('click' + this._instance.nameSpace, '.aciTreeButton', this.proxy(function(e) { + // process click on button + var item = this.itemFrom(e.target); + // skip when busy + if (!this.isBusy(item)) { + // tree button pressed + this.toggle(item, { + collapse: this._instance.options.collapse, + expand: this._instance.options.expand, + unique: this._instance.options.unique + }); + } + })).on('mouseenter' + this._instance.nameSpace + ' mouseleave' + this._instance.nameSpace, '.aciTreePush', function(e) { + // handle the aciTreeHover class + var element = e.target; + if (!domApi.hasClass(element, 'aciTreePush')) { + element = domApi.parentByClass(element, 'aciTreePush'); + } + domApi.toggleClass(element, 'aciTreeHover', e.type == 'mouseenter'); + }).on('mouseenter' + this._instance.nameSpace + ' mouseleave' + this._instance.nameSpace, '.aciTreeLine', function(e) { + // handle the aciTreeHover class + var element = e.target; + if (!domApi.hasClass(element, 'aciTreeLine')) { + element = domApi.parentByClass(element, 'aciTreeLine'); + } + domApi.toggleClass(element, 'aciTreeHover', e.type == 'mouseenter'); + }); + this._initHook(); + // call on success + var success = this.proxy(function() { + // call the parent + this._super(); + this._private.locked = false; + this._trigger(null, 'init', options); + this._success(null, options); + }); + // call on fail + var fail = this.proxy(function() { + // call the parent + this._super(); + this._private.locked = false; + this._trigger(null, 'initfail', options); + this._fail(null, options); + }); + if (this._instance.options.rootData) { + // the rootData was set, use it to init the tree + this.loadFrom(null, this._inner(options, { + success: success, + fail: fail, + itemData: this._instance.options.rootData + })); + } else if (this._instance.options.ajax.url) { + // the AJAX url was set, init with AJAX + this.ajaxLoad(null, this._inner(options, { + success: success, + fail: fail + })); + } else { + success.apply(this); + } + }, + _initHook: function() { + // override this to do extra init + }, + // check locked state + isLocked: function() { + return this._private.locked; + }, + // get a formatted message + // `raw` is the raw message text (can contain %NUMBER sequences, replaced with values from `params`) + // `params` is a list of values to be replaced into the message (by #0 based index) + _format: function(raw, params) { + if (!(params instanceof Array)) { + return raw; + } + var parts = raw.split(/(%[0-9]+)/gm); + var compile = '', part, index, last = false, len; + var test = new window.RegExp('^%[0-9]+$'); + for (var i = 0; i < parts.length; i++) { + part = parts[i]; + len = part.length; + if (len) { + if (!last && test.test(part)) { + index = window.parseInt(part.substr(1)) - 1; + if ((index >= 0) && (index < params.length)) { + compile += params[index]; + continue; + } + } else { + last = false; + if (part.substr(len - 1) == '%') { + if (part.substr(len - 2) != '%%') { + last = true; + } + part = part.substr(0, len - 1); + } + } + compile += part; + } + } + return compile; + }, + // low level DOM functions + _coreDOM: { + // set as leaf node + leaf: function(items) { + domApi.addRemoveListClass(items.toArray(), 'aciTreeLeaf', ['aciTreeInode', 'aciTreeInodeMaybe', 'aciTreeOpen'], function(node) { + node.firstChild.removeAttribute('aria-expanded'); + }); + }, + // set as inner node + inode: function(items, branch) { + domApi.addRemoveListClass(items.toArray(), branch ? 'aciTreeInode' : 'aciTreeInodeMaybe', 'aciTreeLeaf', function(node) { + node.firstChild.setAttribute('aria-expanded', false); + }); + }, + // set as open/closed + toggle: function(items, state) { + domApi.toggleListClass(items.toArray(), 'aciTreeOpen', state, function(node) { + node.firstChild.setAttribute('aria-expanded', state); + }); + }, + // set odd/even classes + oddEven: function(items, odd) { + var list = items.toArray(); + for (var i = 0; i < list.length; i++) { + domApi.addRemoveClass(list[i], odd ? 'aciTreeOdd' : 'aciTreeEven', odd ? 'aciTreeEven' : 'aciTreeOdd'); + odd = !odd; + } + } + }, + // a small queue implementation + // `context` the context to be used with `callback.call` + // `options` are the queue options + _queue: function(context, options) { + var locked = false; + var fifo = [], fifoAsync = []; + var load = 0, loadAsync = 0, schedule = 0, stack = 0; + // run the queue + var run = function() { + if (locked) { + stack--; + return; + } + var now = new window.Date().getTime(); + if (schedule > now) { + stack--; + return; + } + var callback, async = false; + if (load < options.async * 2) { + // get the next synchronous callback + callback = fifo.shift(); + } + if (!callback && (loadAsync < options.async)) { + // get the next async callback + callback = fifoAsync.shift(); + async = true; + } + if (callback) { + // run the callback + if (async) { + loadAsync++; + callback.call(context, function() { + loadAsync--; + }); + if (stack < 40) { + stack++; + run(); + } + } else { + load++; + callback.call(context, function() { + if (now - schedule > options.interval) { + schedule = now + options.delay; + } + load--; + if (stack < 40) { + stack++; + run(); + } + }); + } + } + stack--; + }; + var interval = []; + // start the queue + var start = function() { + for (var i = 0; i < 4; i++) { + interval[i] = window.setInterval(function() { + if (stack < 20) { + stack++; + run(); + } + }, 10); + } + }; + // stop the queue + var stop = function() { + for (var i = 0; i < interval.length; i++) { + window.clearInterval(interval[i]); + } + }; + start(); + // init the queue + this.init = function() { + this.destroy(); + start(); + return this; + }; + // push `callback` function (complete) for later call + // `async` tells if is async callback + this.push = function(callback, async) { + if (!locked) { + if (async) { + fifoAsync.push(callback); + } else { + fifo.push(callback); + } + } + return this; + }; + // test if busy + this.busy = function() { + return (load != 0) || (loadAsync != 0) || (fifo.length != 0) || (fifoAsync.length != 0); + }; + // destroy queue + this.destroy = function() { + locked = true; + stop(); + fifo = []; + fifoAsync = []; + load = 0; + loadAsync = 0; + schedule = 0; + stack = 0; + locked = false; + return this; + }; + }, + // used with a `queue` to execute something at the end + // `endCallback` function (complete) is the callback called at the end + _task: function(queue, endCallback) { + var counter = 0, finish = false; + // push a `callback` function (complete) for later call + this.push = function(callback, async) { + counter++; + queue.push(function(complete) { + var context = this; + callback.call(this, function() { + counter--; + if ((counter < 1) && !finish) { + finish = true; + endCallback.call(context, complete); + } else { + complete(); + } + }); + }, async); + }; + }, + // helper function to extend the `options` object + // `object` the initial options object + // _success, _fail, _notify are callbacks or string (the event name to be triggered) + // `item` is the item to trigger events for + _options: function(object, _success, _fail, _notify, item) { + // options object (need to be in this form for all API functions + // that have the `options` parameter, not all properties are required) + var options = $.extend({ + uid: 'ui', + success: null, // success callback + fail: null, // fail callback + notify: null, // notify callback (internal use for when already in the requested state) + expand: this._instance.options.expand, // propagate (on open) + collapse: this._instance.options.collapse, // propagate (on close) + unique: this._instance.options.unique, // keep a single branch open (on open) + unanimated: false, // unanimated (open/close/toggle) + itemData: { + } // items data (object) or a list (array) of them (used when creating branches) + }, + object); + var success = _success ? ((typeof _success == 'string') ? function() { + this._trigger(item, _success, options); + } : _success) : null; + var fail = _fail ? ((typeof _fail == 'string') ? function() { + this._trigger(item, _fail, options); + } : _fail) : null; + var notify = _notify ? ((typeof _notify == 'string') ? function() { + this._trigger(item, _notify, options); + } : _notify) : null; + if (success) { + // success callback + if (object && object.success) { + options.success = function() { + success.apply(this, arguments); + object.success.apply(this, arguments); + }; + } else { + options.success = success; + } + } + if (fail) { + // fail callback + if (object && object.fail) { + options.fail = function() { + fail.apply(this, arguments); + object.fail.apply(this, arguments); + }; + } else { + options.fail = fail; + } + } + if (notify) { + // notify callback + if (object && object.notify) { + options.notify = function() { + notify.apply(this, arguments); + object.notify.apply(this, arguments); + }; + } else if (!options.notify && object && object.success) { + options.notify = function() { + notify.apply(this, arguments); + object.success.apply(this, arguments); + }; + } else { + options.notify = notify; + } + } else if (!options.notify && object && object.success) { + // by default, run success callback + options.notify = object.success; + } + return options; + }, + // helper for passing `options` object to inner methods + // the callbacks are removed and `override` can be used to update properties + _inner: function(options, override) { + // removing success/fail/notify from options + return $.extend({ + }, options, { + success: null, + fail: null, + notify: null + }, + override); + }, + // trigger the aciTree events on the tree container + _trigger: function(item, eventName, options) { + var event = $.Event('acitree'); + if (!options) { + options = this._options(); + } + this._instance.jQuery.trigger(event, [this, item, eventName, options]); + return !event.isDefaultPrevented(); + }, + // call on success + _success: function(item, options) { + if (options && options.success) { + options.success.call(this, item, options); + } + }, + // call on fail + _fail: function(item, options) { + if (options && options.fail) { + options.fail.call(this, item, options); + } + }, + // call on notify (should be same as `success` but called when already in the requested state) + _notify: function(item, options) { + if (options && options.notify) { + options.notify.call(this, item, options); + } + }, + // delay callback on busy item + _delayBusy: function(item, callback) { + if ((this._private.delayBusy < 10) && this.isBusy(item)) { + this._private.delayBusy++; + window.setTimeout(this.proxy(function() { + this._delayBusy.call(this, item, callback); + this._private.delayBusy--; + }), 10); + return; + } + callback.apply(this); + }, + // return the data source for item + // defaults to `aciTree.options.ajax` if not set on the item/his parents + _dataSource: function(item) { + var dataSource = this._instance.options.dataSource; + if (dataSource) { + var data = this.itemData(item); + if (data && data.source && dataSource[data.source]) { + return dataSource[data.source]; + } + var parent; + do { + parent = this.parent(item); + data = this.itemData(parent); + if (data && data.source && dataSource[data.source]) { + return dataSource[data.source]; + } + } while (parent.length); + } + return this._instance.options.ajax; + }, + // process item loading with AJAX + // `item` can be NULL to load the ROOT + // loaded data need to be array of item objects + // each item can have children (defined as `itemData.branch` - array of item data objects) + ajaxLoad: function(item, options) { + if (item && this.isBusy(item)) { + // delay the load if busy + this._delayBusy(item, function() { + this.ajaxLoad(item, options); + }); + return; + } + options = this._options(options, function() { + this._loading(item); + this._trigger(item, 'loaded', options); + }, function() { + this._loading(item); + this._trigger(item, 'loadfail', options); + }, function() { + this._loading(item); + this._trigger(item, 'wasloaded', options); + }); + if (!item || this.isInode(item)) { + // add the task to the queue + this._instance.queue.push(function(complete) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeload', options)) { + this._fail(item, options); + complete(); + return; + } + this._loading(item, true); + if (this.wasLoad(item)) { + // was load already + this._notify(item, options); + complete(); + return; + } + // ensure we work on a copy of the dataSource object + var settings = $.extend({ + }, this._dataSource(item)); + // call the `aciTree.options.ajaxHook` + this._instance.options.ajaxHook.call(this, item, settings); + // loaded data need to be array of item objects + settings.success = this.proxy(function(itemList) { + if (itemList && (itemList instanceof Array) && itemList.length) { + // the AJAX returned some items + var process = function() { + if (this.wasLoad(item)) { + this._notify(item, options); + complete(); + } else { + // create a branch from `itemList` + this._createBranch(item, this._inner(options, { + success: function() { + this._success(item, options); + complete(); + }, + fail: function() { + this._fail(item, options); + complete(); + }, + itemData: itemList + })); + } + }; + if (!item || this.isInode(item)) { + process.apply(this); + } else { + // change the item to inode, then load + this.setInode(item, this._inner(options, { + success: process, + fail: options.fail + })); + } + } else { + // the AJAX response was not just right (or not a inode) + var process = function() { + this._fail(item, options); + complete(); + }; + if (!item || this.isLeaf(item)) { + process.apply(this); + } else { + // change the item to leaf + this.setLeaf(item, this._inner(options, { + success: process, + fail: process + })); + } + } + }); + settings.error = this.proxy(function() { + // AJAX failed + this._fail(item, options); + complete(); + }); + $.ajax(settings); + }, true); + } else { + this._fail(item, options); + } + }, + // process item loading + // `item` can be NULL to load the ROOT + // `options.itemData` need to be array of item objects + // each item can have children (defined as `itemData.branch` - array of item data objects) + loadFrom: function(item, options) { + if (item && this.isBusy(item)) { + // delay the load if busy + this._delayBusy(item, function() { + this.loadFrom(item, options); + }); + return; + } + options = this._options(options, function() { + this._loading(item); + this._trigger(item, 'loaded', options); + }, function() { + this._loading(item); + this._trigger(item, 'loadfail', options); + }, function() { + this._loading(item); + this._trigger(item, 'wasloaded', options); + }); + if (!item || this.isInode(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeload', options)) { + this._fail(item, options); + return; + } + this._loading(item, true); + if (this.wasLoad(item)) { + // was load already + this._notify(item, options); + return; + } + // data need to be array of item objects + if (options.itemData && (options.itemData instanceof Array) && options.itemData.length) { + // create the branch from `options.itemData` + var process = function() { + if (this.wasLoad(item)) { + this._notify(item, options); + } else { + this._createBranch(item, options); + } + }; + if (!item || this.isInode(item)) { + process.apply(this); + } else { + // change the item to inode, then create children + this.setInode(item, this._inner(options, { + success: process, + fail: options.fail + })); + } + } else { + // this is not a inode + if (!item || this.isLeaf(item)) { + this._fail(item, options); + } else { + // change the item to leaf + this.setLeaf(item, this._inner(options, { + success: options.fail, + fail: options.fail + })); + } + } + } else { + this._fail(item, options); + } + }, + // unload item + // `item` can be NULL to unload the entire tree + unload: function(item, options) { + options = this._options(options, function() { + this._loading(item); + this._trigger(item, 'unloaded', options); + }, function() { + this._loading(item); + this._trigger(item, 'unloadfail', options); + }, function() { + this._loading(item); + this._trigger(item, 'notloaded', options); + }); + if (!item || this.isInode(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeunload', options)) { + this._fail(item, options); + return; + } + this._loading(item, true); + if (!this.wasLoad(item)) { + // if was not loaded + this._notify(item, options); + return; + } + // first check each children + var cancel = false; + var children = this.children(item, true, true); + children.each(this.proxy(function(element) { + var item = $(element); + if (this.isInode(item)) { + if (this.isOpen(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeclose', options)) { + cancel = true; + return false; + } + } + if (this.wasLoad(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeunload', options)) { + cancel = true; + return false; + } + } + } + // a way to cancel the operation + if (!this._trigger(item, 'beforeremove', options)) { + cancel = true; + return false; + } + }, true)); + if (cancel) { + // it was canceled + this._fail(item, options); + return; + } + var process = function() { + children.each(this.proxy(function(element) { + // trigger the events before DOM changes + var item = $(element); + if (this.isInode(item)) { + if (this.isOpen(item)) { + this._trigger(item, 'closed', options); + } + if (this.wasLoad(item)) { + this._trigger(item, 'unloaded', options); + } + } + this._trigger(item, 'removed', options); + }, true)); + }; + // process the child remove + if (item) { + if (this.isOpen(item)) { + // first close the item, then remove children + this.close(item, this._inner(options, { + success: function() { + process.call(this); + this._removeContainer(item); + this._success(item, options); + }, + fail: options.fail + })); + } else { + process.call(this); + this._removeContainer(item); + this._success(item, options); + } + } else { + // unload the ROOT + this._animate(item, false, !this._instance.options.animateRoot || options.unanimated, function() { + process.call(this); + this._removeContainer(); + this._success(item, options); + }); + } + } else { + this._fail(item, options); + } + }, + // remove item + remove: function(item, options) { + if (this.isItem(item)) { + if (this.hasSiblings(item, true)) { + options = this._options(options, function() { + if (this.isOpenPath(item)) { + // if the parents are opened (visible) update the item states + domApi.removeClass(item[0], 'aciTreeVisible'); + this._setOddEven(item); + } + this._trigger(item, 'removed', options); + }, 'removefail', null, item); + // a way to cancel the operation + if (!this._trigger(item, 'beforeremove', options)) { + this._fail(item, options); + return; + } + if (this.wasLoad(item)) { + // unload the inode then remove + this.unload(item, this._inner(options, { + success: function() { + this._success(item, options); + this._removeItem(item); + }, + fail: options.fail + })); + } else { + // just remove the item + this._success(item, options); + this._removeItem(item); + } + } else { + var parent = this.parent(item); + if (parent.length) { + this.setLeaf(parent, options); + } else { + this.unload(null, options); + } + } + } else { + this._trigger(item, 'removefail', options) + this._fail(item, options); + } + }, + // open item children + _openChildren: function(item, options) { + if (options.expand) { + var queue = this._instance.queue; + // process the children inodes + this.inodes(this.children(item)).each(function() { + var item = $(this); + // queue node opening + queue.push(function(complete) { + this.open(item, this._inner(options)); + complete(); + }); + }); + queue.push(function(complete) { + this._success(item, options); + complete(); + }); + } else { + this._success(item, options); + } + }, + // process item open + _openItem: function(item, options) { + if (!options.unanimated && !this.isVisible(item)) { + options.unanimated = true; + } + if (options.unique) { + // close other opened nodes + this.closeOthers(item); + options.unique = false; + } + // open the node + this._coreDOM.toggle(item, true); + // (temporarily) update children states + this._setOddEvenChildren(item); + this._animate(item, true, options.unanimated, function() { + this._openChildren(item, options); + }); + }, + // open item and his children if requested + open: function(item, options) { + options = this._options(options, function() { + if (this.isOpenPath(item)) { + // if all parents are open, update the items after + this._updateVisible(item); + this._setOddEven(item); + } + this._trigger(item, 'opened', options); + }, 'openfail', 'wasopened', item); + if (this.isInode(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeopen', options)) { + this._fail(item, options); + return; + } + if (this.isOpen(item)) { + options.success = options.notify; + // propagate/open children (if required) + this._openChildren(item, options); + } else { + if (this.wasLoad(item)) { + this._openItem(item, options); + } else { + // try to load the node, then open + this.ajaxLoad(item, this._inner(options, { + success: function() { + this._openItem(item, options); + }, + fail: options.fail + })); + } + } + } else { + this._fail(item, options); + } + }, + // close item children + _closeChildren: function(item, options) { + if (this._instance.options.empty) { + // unload on close + options.unanimated = true; + this.unload(item, options); + } else if (options.collapse) { + var queue = this._instance.queue; + // process the children inodes + this.inodes(this.children(item)).each(function() { + var item = $(this); + // queue node close + queue.push(function(complete) { + this.close(item, this._inner(options, { + unanimated: true + })); + complete(); + }); + }); + queue.push(function(complete) { + this._success(item, options); + complete(); + }); + } else { + this._success(item, options); + } + }, + // process item close + _closeItem: function(item, options) { + if (!options.unanimated && !this.isVisible(item)) { + options.unanimated = true; + } + // close the item + this._coreDOM.toggle(item, false); + this._animate(item, false, options.unanimated, function() { + this._closeChildren(item, options); + }); + }, + // close item and his children if requested + close: function(item, options) { + options = this._options(options, function() { + if (this.isOpenPath(item)) { + // if all parents are open, update the items after + this._updateVisible(item); + this._setOddEven(item); + } + this._trigger(item, 'closed', options); + }, 'closefail', 'wasclosed', item); + if (this.isInode(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeclose', options)) { + this._fail(item, options); + return; + } + if (this.isOpen(item)) { + this._closeItem(item, options); + } else if (this.wasLoad(item)) { + options.success = options.notify; + // propagate/close/empty children (if required) + this._closeChildren(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // update visible state + _updateVisible: function(item) { + if (this.isOpenPath(item)) { + if (!this.isHidden(item)) { + // if open parents and not hidden + domApi.addClass(item[0], 'aciTreeVisible'); + if (this.isOpen(item)) { + // process children + domApi.children(item[0], false, this.proxy(function(node) { + if (!domApi.hasClass(node, 'aciTreeVisible')) { + this._updateVisible($(node)); + } + })); + } else { + // children are not visible + domApi.children(item[0], true, function(node) { + return domApi.removeClass(node, 'aciTreeVisible') ? true : null; + }); + } + } + } else if (domApi.removeClass(item[0], 'aciTreeVisible')) { + domApi.children(item[0], true, function(node) { + return domApi.removeClass(node, 'aciTreeVisible') ? true : null; + }); + } + }, + // keep just one branch open + closeOthers: function(item, options) { + options = this._options(options); + if (this.isItem(item)) { + var queue = this._instance.queue; + // exclude the item and his parents + var exclude = item.add(this.path(item)).add(this.children(item, true)); + // close all other open nodes + this.inodes(this.children(null, true, true), true).not(exclude).each(function() { + var item = $(this); + // add node to close queue + queue.push(function(complete) { + this.close(item, this._inner(options)); + complete(); + }); + }); + queue.push(function(complete) { + this._success(item, options); + complete(); + }); + } else { + this._fail(item, options); + } + }, + // toggle item + toggle: function(item, options) { + options = this._options(options, 'toggled', 'togglefail', null, item); + if (this.isInode(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforetoggle', options)) { + this._fail(item, options); + return; + } + if (this.isOpen(item)) { + this.close(item, options); + } else { + this.open(item, options); + } + } else { + this._fail(item, options); + } + }, + // get item path starting from the top parent (ROOT) + // when `reverse` is TRUE returns the path in reverse order + path: function(item, reverse) { + if (item) { + var parent = item[0], list = []; + while (parent = domApi.parent(parent)) { + list.push(parent); + } + return reverse ? $(list) : $(list.reverse()); + } + return $([]); + }, + // test if item is in view + // when `center` is TRUE will test if is centered in view + isVisible: function(item, center) { + if (item && domApi.hasClass(item[0], 'aciTreeVisible')) { + // the item path need to be open + var rect = this._instance.jQuery[0].getBoundingClientRect(); + var size = item[0].firstChild; + var test = size.getBoundingClientRect(); + var height = size.offsetHeight; + var offset = center ? (rect.bottom - rect.top) / 2 : 0; + if ((test.bottom - height < rect.top + offset) || (test.top + height > rect.bottom - offset)) { + // is out of view + return false; + } + return true; + } + return false; + }, + // open path to item + openPath: function(item, options) { + options = this._options(options); + if (this.isItem(item)) { + var queue = this._instance.queue; + // process closed inodes + this.inodes(this.path(item), false).each(function() { + var item = $(this); + // add node to open queue + queue.push(function(complete) { + this.open(item, this._inner(options)); + complete(); + }); + }); + queue.push(function(complete) { + this._success(item, options); + complete(); + }); + } else { + this._fail(item, options); + } + }, + // test if path to item is open + isOpenPath: function(item) { + var parent = this.parent(item); + return parent[0] ? this.isOpen(parent) && domApi.hasClass(parent[0], 'aciTreeVisible') : true; + }, + // get animation speed vs. offset size + // `speed` is the raw speed + // `totalSize` is the available size + // `required` is the offset used for calculations + _speedFraction: function(speed, totalSize, required) { + if ((required < totalSize) && totalSize) { + var numeric = parseInt(speed); + if (isNaN(numeric)) { + // predefined string values + switch (speed) { + case 'slow': + numeric = 600; + break; + case 'medium': + numeric = 400; + break; + case 'fast': + numeric = 200; + break; + default: + return speed; + } + } + return numeric * required / totalSize; + } + return speed; + }, + // bring item in view + // `options.center` says if should be centered in view + setVisible: function(item, options) { + options = this._options(options, 'visible', 'visiblefail', 'wasvisible', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforevisible', options)) { + this._fail(item, options); + return; + } + if (this.isVisible(item)) { + // is visible already + this._notify(item, options); + return; + } + var process = function() { + // compute position with getBoundingClientRect + var rect = this._instance.jQuery[0].getBoundingClientRect(); + var size = item[0].firstChild; + var test = size.getBoundingClientRect(); + var height = size.offsetHeight; + var offset = options.center ? (rect.bottom - rect.top) / 2 : 0; + if (test.bottom - height < rect.top + offset) { + // item somewhere before the first visible + var diff = rect.top + offset - test.bottom + height; + if (!options.unanimated && this._instance.options.view) { + this._instance.jQuery.stop(true).animate({ + scrollTop: this._instance.jQuery.scrollTop() - diff + }, + { + duration: this._speedFraction(this._instance.options.view.duration, rect.bottom - rect.top, diff), + easing: this._instance.options.view.easing, + complete: this.proxy(function() { + this._success(item, options); + }) + }); + } else { + this._instance.jQuery.stop(true)[0].scrollTop = this._instance.jQuery.scrollTop() - diff; + this._success(item, options); + } + } else if (test.top + height > rect.bottom - offset) { + // item somewhere after the last visible + var diff = test.top - rect.bottom + offset + height; + if (!options.unanimated && this._instance.options.view) { + this._instance.jQuery.stop(true).animate({ + scrollTop: this._instance.jQuery.scrollTop() + diff + }, + { + duration: this._speedFraction(this._instance.options.view.duration, rect.bottom - rect.top, diff), + easing: this._instance.options.view.easing, + complete: this.proxy(function() { + this._success(item, options); + }) + }); + } else { + this._instance.jQuery.stop(true)[0].scrollTop = this._instance.jQuery.scrollTop() + diff; + this._success(item, options); + } + } else { + this._success(item, options); + } + }; + if (this.hasParent(item)) { + // first we need to open the path to item + this.openPath(item, this._inner(options, { + success: process, + fail: options.fail + })); + } else { + process.apply(this); + } + } else { + this._fail(item, options); + } + }, + // test if item has parent + hasParent: function(item) { + return this.parent(item).length > 0; + }, + // get item parent + parent: function(item) { + return item ? $(domApi.parent(item[0])) : $([]); + }, + // get item top (ROOT) parent + topParent: function(item) { + return this.path(item).eq(0); + }, + // create tree branch + // `options.itemData` need to be in the same format as for .append + _createBranch: function(item, options) { + var total = 0; + var count = function(itemList) { + var itemData; + for (var i = 0; i < itemList.length; i++) { + itemData = itemList[i]; + if (itemData.branch && (itemData.branch instanceof Array) && itemData.branch.length) { + count(itemData.branch); + } + } + total++; + }; + count(options.itemData); + var index = 0; + var complete = this.proxy(function() { + index++; + if (index >= total) { + this._success(item, options); + } + }); + var process = this.proxy(function(node, itemList) { + if (node) { + // set it as a inode + domApi.addRemoveClass(node[0], 'aciTreeInode', 'aciTreeInodeMaybe'); + } + // use .append to add new items + this.append(node, this._inner(options, { + success: function(item, options) { + var itemData; + for (var i = 0; i < options.itemData.length; i++) { + itemData = options.itemData[i]; + // children need to be array of item objects + if (itemData.branch && (itemData.branch instanceof Array) && itemData.branch.length) { + process(options.items.eq(i), itemData.branch); + } + if (itemData.open) { + // open the item is requuested + this.open(options.items.eq(i), this._inner(options, { + itemData: null, + items: null + })); + } + } + complete(); + }, + fail: options.fail, + itemData: itemList + })); + }); + process(item, options.itemData); + }, + // get first/last items + _getFirstLast: function(parent) { + if (!parent) { + parent = this._instance.jQuery; + } + return $(domApi.withAnyClass(domApi.children(parent[0]), ['aciTreeFirst', 'aciTreeLast'])); + }, + // update first/last items + _setFirstLast: function(parent, clear) { + if (clear) { + domApi.removeListClass(clear.toArray(), ['aciTreeFirst', 'aciTreeLast']); + } + var first = this.first(parent); + if (first[0]) { + domApi.addClass(first[0], 'aciTreeFirst'); + domApi.addClass(this.last(parent)[0], 'aciTreeLast'); + } + }, + // update odd/even state + _setOddEven: function(items) { + // consider only visible items + var visible; + if (this._instance.jQuery[0].getElementsByClassName) { + visible = this._instance.jQuery[0].getElementsByClassName('aciTreeVisible'); + visible = visible ? window.Array.prototype.slice.call(visible) : []; + } else { + visible = $(domApi.children(this._instance.jQuery[0], true, function(node) { + return this.hasClass(node, 'aciTreeVisible') ? true : null; + })); + } + var odd = true; + if (visible.length) { + var index = 0; + if (items) { + // search the item to start with (by index) + items.each(function() { + if (visible.indexOf) { + var found = visible.indexOf(this); + if (found != -1) { + index = window.Math.min(found, index); + } + } else { + for (var i = 0; i < visible.length; i++) { + if (visible[i] === this) { + index = window.Math.min(i, index); + break; + } + } + } + }); + index = window.Math.max(index - 1, 0); + } + if (index > 0) { + // determine with what to start with (odd/even) + var first = visible[index]; + if (domApi.hasClass(first, 'aciTreOdd')) { + odd = false; + } + // process only after index + visible = visible.slice(index + 1); + } + } + this._coreDOM.oddEven($(visible), odd); + }, + // update odd/even state for direct children + _setOddEvenChildren: function(item) { + var odd = domApi.hasClass(item[0], 'aciTreeOdd'); + var children = this.children(item); + this._coreDOM.oddEven(children, !odd); + }, + // process item before inserting into the DOM + _itemHook: function(parent, item, itemData, level) { + if (this._instance.options.itemHook) { + this._instance.options.itemHook.apply(this, arguments); + } + }, + // create item by `itemData` + // `level` is the #0 based item level + _createItem: function(itemData, level) { + if (this._private.itemClone[level]) { + var li = this._private.itemClone[level].cloneNode(true); + var line = li.firstChild; + var icon = line; + for (var i = 0; i < level; i++) { + icon = icon.firstChild; + } + icon = icon.firstChild.lastChild.firstChild; + var text = icon.nextSibling; + } else { + var li = window.document.createElement('LI'); + li.setAttribute('role', 'presentation'); + var line = window.document.createElement('DIV'); + li.appendChild(line); + line.setAttribute('tabindex', -1); + line.setAttribute('role', 'treeitem'); + line.setAttribute('aria-selected', false); + line.className = 'aciTreeLine'; + var last = line, branch; + for (var i = 0; i < level; i++) { + branch = window.document.createElement('DIV'); + last.appendChild(branch); + branch.className = 'aciTreeBranch aciTreeLevel' + i; + last = branch; + } + var entry = window.document.createElement('DIV'); + last.appendChild(entry); + entry.className = 'aciTreeEntry'; + var button = window.document.createElement('SPAN'); + entry.appendChild(button); + button.className = 'aciTreeButton'; + var push = window.document.createElement('SPAN'); + button.appendChild(push); + push.className = 'aciTreePush'; + push.appendChild(window.document.createElement('SPAN')); + var item = window.document.createElement('SPAN'); + entry.appendChild(item); + item.className = 'aciTreeItem'; + var icon = window.document.createElement('SPAN'); + item.appendChild(icon); + var text = window.document.createElement('SPAN'); + item.appendChild(text); + text.className = 'aciTreeText'; + this._private.itemClone[level] = li.cloneNode(true); + } + li.className = 'aciTreeLi' + (itemData.inode || (itemData.inode === null) ? (itemData.inode || (itemData.branch && itemData.branch.length) ? ' aciTreeInode' : ' aciTreeInodeMaybe') : ' aciTreeLeaf') + ' aciTreeLevel' + level + (itemData.disabled ? ' aciTreeDisabled' : ''); + line.setAttribute('aria-level', level + 1); + if (itemData.inode || (itemData.inode === null)) { + line.setAttribute('aria-expanded', false); + } + if (itemData.icon) { + if (itemData.icon instanceof Array) { + icon.className = 'aciTreeIcon ' + itemData.icon[0]; + icon.style.backgroundPosition = itemData.icon[1] + 'px ' + itemData.icon[2] + 'px'; + } else { + icon.className = 'aciTreeIcon ' + itemData.icon; + } + } else { + icon.parentNode.removeChild(icon); + } + text.innerHTML = itemData.label; + var $li = $(li); + $li.data('itemData' + this._instance.nameSpace, $.extend({ + }, itemData, { + branch: itemData.branch && itemData.branch.length + })); + return $li; + }, + // remove item + _removeItem: function(item) { + var parent = this.parent(item); + item.remove(); + // update sibling state + this._setFirstLast(parent.length ? parent : null); + }, + // create & add one or more items + // `ul`, `before` and `after` are set depending on the caller + // `itemData` need to be array of objects or just an object (one item) + // `level` is the #0 based level + // `callback` function (items) is called at the end of the operation + _createItems: function(ul, before, after, itemData, level, callback) { + var items = [], fragment = window.document.createDocumentFragment(); + var task = new this._task(this._instance.queue, function(complete) { + items = $(items); + if (items.length) { + // add the new items + if (ul) { + ul[0].appendChild(fragment); + } else if (before) { + before[0].parentNode.insertBefore(fragment, before[0]); + } else if (after) { + after[0].parentNode.insertBefore(fragment, after[0].nextSibling); + } + } + callback.call(this, items); + complete(); + }); + if (itemData) { + this._loader(true); + var parent; + if (ul) { + parent = this.itemFrom(ul); + } else if (before) { + parent = this.parent(before); + } else if (after) { + parent = this.parent(after); + } + if (itemData instanceof Array) { + // this is a list of items + for (var i = 0; i < itemData.length; i++) { + (function(itemData) { + task.push(function(complete) { + var item = this._createItem(itemData, level); + this._itemHook(parent, item, itemData, level); + fragment.appendChild(item[0]); + items.push(item[0]); + complete(); + }); + })(itemData[i]); + } + } else { + task.push(function(complete) { + // only one item + var item = this._createItem(itemData, level); + this._itemHook(parent, item, itemData, level); + fragment.appendChild(item[0]); + items.push(item[0]); + complete(); + }); + } + } + // run at least once + task.push(function(complete) { + complete(); + }); + }, + // create children container + _createContainer: function(item) { + if (!item) { + item = this._instance.jQuery; + } + // ensure we have a UL in place + var ul = domApi.container(item[0]); + if (!ul) { + var ul = window.document.createElement('UL'); + ul.setAttribute('role', 'group'); + ul.className = 'aciTreeUl'; + ul.style.display = 'none'; + item[0].appendChild(ul); + } + return $(ul); + }, + // remove children container + _removeContainer: function(item) { + if (!item) { + item = this._instance.jQuery; + } + var ul = domApi.container(item[0]); + ul.parentNode.removeChild(ul); + }, + // append one or more items to item + // `options.itemData` can be a item object or array of item objects + // `options.items` will keep a list of added items + append: function(item, options) { + options = this._options(options, 'appended', 'appendfail', null, item); + if (item) { + if (this.isInode(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeappend', options)) { + this._fail(item, options); + return; + } + var container = this._createContainer(item); + var last = this.last(item); + this._createItems(container, null, null, options.itemData, this.level(item) + 1, function(list) { + if (list.length) { + // some items created, update states + domApi.addRemoveClass(item[0], 'aciTreeInode', 'aciTreeInodeMaybe'); + this._setFirstLast(item, last); + if (this.isHidden(item)) { + domApi.addListClass(list.toArray(), 'aciTreeHidden'); + } else if (this.isOpenPath(item) && this.isOpen(item)) { + domApi.addListClass(list.toArray(), 'aciTreeVisible'); + this._setOddEven(list.first()); + } + // trigger `added` for each item + list.each(this.proxy(function(element) { + this._trigger($(element), 'added', options); + }, true)); + } else if (!this.hasChildren(item, true)) { + container.remove(); + } + options.items = list; + this._success(item, options); + }); + } else { + this._fail(item, options); + } + } else { + // a way to cancel the operation + if (!this._trigger(item, 'beforeappend', options)) { + this._fail(item, options); + return; + } + var container = this._createContainer(); + var last = this.last(); + this._createItems(container, null, null, options.itemData, 0, function(list) { + if (list.length) { + // some items created, update states + this._setFirstLast(null, last); + domApi.addListClass(list.toArray(), 'aciTreeVisible'); + this._setOddEven(); + // trigger `added` for each item + list.each(this.proxy(function(element) { + this._trigger($(element), 'added', options); + }, true)); + this._animate(null, true, !this._instance.options.animateRoot || options.unanimated); + } else if (!this.hasChildren(null, true)) { + // remove the children container + container.remove(); + } + options.items = list; + this._success(item, options); + }); + } + }, + // insert one or more items before item + // `options.itemData` can be a item object or array of item objects + // `options.items` will keep a list of added items + before: function(item, options) { + options = this._options(options, 'before', 'beforefail', null, item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforebefore', options)) { + this._fail(item, options); + return; + } + var prev = this.prev(item); + this._createItems(null, item, null, options.itemData, this.level(item), function(list) { + if (list.length) { + // some items created, update states + if (!prev.length) { + domApi.removeClass(item[0], 'aciTreeFirst'); + domApi.addClass(list.first()[0], 'aciTreeFirst'); + } + var parent = this.parent(item); + if (parent.length && this.isHidden(parent)) { + domApi.addListClass(list.toArray(), 'aciTreeHidden'); + } else if (this.isOpenPath(item)) { + domApi.addListClass(list.toArray(), 'aciTreeVisible'); + this._setOddEven(list.first()); + } + // trigger `added` for each item + list.each(this.proxy(function(element) { + this._trigger($(element), 'added', options); + }, true)); + } + options.items = list; + this._success(item, options); + }); + } else { + this._fail(item, options); + } + }, + // insert one or more items after item + // `options.itemData` can be a item object or array of item objects + // `options.items` will keep a list of added items + after: function(item, options) { + options = this._options(options, 'after', 'afterfail', null, item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeafter', options)) { + this._fail(item, options); + return; + } + var next = this.next(item); + this._createItems(null, null, item, options.itemData, this.level(item), function(list) { + if (list.length) { + // some items created, update states + if (!next.length) { + domApi.removeClass(item[0], 'aciTreeLast'); + domApi.addClass(list.last()[0], 'aciTreeLast'); + } + var parent = this.parent(item); + if (parent.length && this.isHidden(parent)) { + domApi.addListClass(list.toArray(), 'aciTreeHidden'); + } else if (this.isOpenPath(item)) { + domApi.addListClass(list.toArray(), 'aciTreeVisible'); + this._setOddEven(list.first()); + } + // trigger `added` for each item + list.each(this.proxy(function(element) { + this._trigger($(element), 'added', options); + }, true)); + } + options.items = list; + this._success(item, options); + }); + } else { + this._fail(item, options); + } + }, + // get item having the element + itemFrom: function(element) { + if (element) { + var item = $(element); + if (item[0] === this._instance.jQuery[0]) { + return $([]); + } else { + return $(domApi.parentFrom(item[0])); + } + } + return $([]); + }, + // get item children + // if `branch` is TRUE then all children are returned + // if `hidden` is TRUE then the hidden items will be considered too + children: function(item, branch, hidden) { + return $(domApi.children(item && item[0] ? item[0] : this._instance.jQuery[0], branch, hidden ? null : function(node) { + return this.hasClass(node, 'aciTreeHidden') ? null : true; + })); + }, + // filter only the visible items (items with all parents opened) + // if `view` is TRUE then only the items in view are returned + visible: function(items, view) { + var list = domApi.withClass(items.toArray(), 'aciTreeVisible'); + if (view) { + var filter = []; + for (var i = 0; i < list.length; i++) { + if (this.isVisible($(list[i]))) { + filter.push(list[i]); + } + } + return $(filter); + } + return $(list); + }, + // filter only inner nodes from items + // if `state` is set then filter only open/closed ones + inodes: function(items, state) { + if (state !== undefined) { + if (state) { + return $(domApi.withClass(items.toArray(), 'aciTreeOpen')); + } else { + return $(domApi.withAnyClass(items.toArray(), ['aciTreeInode', 'aciTreeInodeMaybe'], 'aciTreeOpen')); + } + } + return $(domApi.withAnyClass(items.toArray(), ['aciTreeInode', 'aciTreeInodeMaybe'])); + }, + // filter only leaf nodes from items + leaves: function(items) { + return $(domApi.withClass(items.toArray(), 'aciTreeLeaf')); + }, + // test if is a inner node + isInode: function(item) { + return item && domApi.hasAnyClass(item[0], ['aciTreeInode', 'aciTreeInodeMaybe']); + }, + // test if is a leaf node + isLeaf: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeLeaf'); + }, + // test if item was loaded + wasLoad: function(item) { + if (item) { + return domApi.container(item[0]) !== null; + } + return domApi.container(this._instance.jQuery[0]) !== null; + }, + // set item as inner node + setInode: function(item, options) { + options = this._options(options, 'inodeset', 'inodefail', 'wasinode', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeinode', options)) { + this._fail(item, options); + return; + } + if (this.isLeaf(item)) { + this._coreDOM.inode(item, true); + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // set item as leaf node + setLeaf: function(item, options) { + options = this._options(options, 'leafset', 'leaffail', 'wasleaf', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeleaf', options)) { + this._fail(item, options); + return; + } + if (this.isInode(item)) { + var process = function() { + this._coreDOM.leaf(item); + this._success(item, options); + }; + if (this.wasLoad(item)) { + // first unload the node + this.unload(item, this._inner(options, { + success: process, + fail: options.fail + })); + } else { + process.apply(this); + } + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // add/update item icon + // `options.icon` can be the CSS class name or array['CSS class name', background-position-x, background-position-y] + // `options.oldIcon` will keep the old icon + addIcon: function(item, options) { + options = this._options(options, 'iconadded', 'addiconfail', 'wasicon', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeaddicon', options)) { + this._fail(item, options); + return; + } + var data = this.itemData(item); + // keep the old one + options.oldIcon = data.icon; + var parent = domApi.childrenByClass(item[0].firstChild, 'aciTreeItem'); + var found = domApi.childrenByClass(parent, 'aciTreeIcon'); + if (found && data.icon && (options.icon.toString() == data.icon.toString())) { + this._notify(item, options); + } else { + if (!found) { + found = window.document.createElement('DIV'); + parent.insertBefore(found, parent.firstChild); + } + if (options.icon instanceof Array) { + // icon with background-position + found.className = 'aciTreeIcon ' + options.icon[0]; + found.style.backgroundPosition = options.icon[1] + 'px ' + options.icon[2] + 'px'; + } else { + // only the CSS class name + found.className = 'aciTreeIcon ' + options.icon; + } + // remember this one + data.icon = options.icon; + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // remove item icon + // options.oldIcon will keep the old icon + removeIcon: function(item, options) { + options = this._options(options, 'iconremoved', 'removeiconfail', 'noticon', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeremoveicon', options)) { + this._fail(item, options); + return; + } + var data = this.itemData(item); + // keep the old one + options.oldIcon = data.icon; + var parent = domApi.childrenByClass(item[0].firstChild, 'aciTreeItem'); + var found = domApi.childrenByClass(parent, 'aciTreeIcon'); + if (found) { + parent.removeChild(found); + // remember was removed + data.icon = null; + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // test if item has icon + hasIcon: function(item) { + return !!this.getIcon(item); + }, + // get item icon + getIcon: function(item) { + var data = this.itemData(item); + return data ? data.icon : null; + }, + // set item label + // `options.label` is the new label + // `options.oldLabel` will keep the old label + setLabel: function(item, options) { + options = this._options(options, 'labelset', 'labelfail', 'waslabel', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforelabel', options)) { + this._fail(item, options); + return; + } + var data = this.itemData(item); + // keep the old one + options.oldLabel = data.label; + if (options.label == options.oldLabel) { + this._notify(item, options); + } else { + // set the label + domApi.childrenByClass(item[0].firstChild, 'aciTreeText').innerHTML = options.label; + // remember this one + data.label = options.label; + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // disable item + disable: function(item, options) { + options = this._options(options, 'disabled', 'disablefail', 'wasdisabled', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforedisable', options)) { + this._fail(item, options); + return; + } + if (this.isDisabled(item)) { + this._notify(item, options); + } else { + domApi.addClass(item[0], 'aciTreeDisabled'); + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // test if item is disabled + isDisabled: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeDisabled'); + }, + // test if any of parents are disabled + isDisabledPath: function(item) { + return domApi.withClass(this.path(item).toArray(), 'aciTreeDisabled').length > 0; + }, + // filter only the disabled items + disabled: function(items) { + return $(domApi.withClass(items.toArray(), 'aciTreeDisabled')); + }, + // enable item + enable: function(item, options) { + options = this._options(options, 'enabled', 'enablefail', 'wasenabled', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeenable', options)) { + this._fail(item, options); + return; + } + if (this.isDisabled(item)) { + domApi.removeClass(item[0], 'aciTreeDisabled'); + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // test if item is enabled + isEnabled: function(item) { + return item && !domApi.hasClass(item[0], 'aciTreeDisabled'); + }, + // test if all parents are enabled + isEnabledPath: function(item) { + return domApi.withClass(this.path(item).toArray(), 'aciTreeDisabled').length == 0; + }, + // filter only the enabled items + enabled: function(items) { + return $(domApi.withClass(items.toArray(), null, 'aciTreeDisabled')); + }, + // set item as hidden + hide: function(item, options) { + options = this._options(options, 'hidden', 'hidefail', 'washidden', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforehide', options)) { + this._fail(item, options); + return; + } + if (this.isHidden(item)) { + this._notify(item, options); + } else { + domApi.addRemoveClass(item[0], 'aciTreeHidden', 'aciTreeVisible'); + // process children + domApi.addRemoveClass(this.children(item, true).toArray(), 'aciTreeHidden', 'aciTreeVisible'); + // update item states + var parent = this.parent(item); + this._setFirstLast(parent.length ? parent : null, item); + this._setOddEven(item); + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // test if item is hidden + isHidden: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeHidden'); + }, + // test if any of parents are hidden + isHiddenPath: function(item) { + var parent = this.parent(item); + return parent[0] && domApi.hasClass(parent[0], 'aciTreeHidden'); + }, + // update hidden state + _updateHidden: function(item) { + if (this.isHiddenPath(item)) { + if (!this.isHidden(item)) { + domApi.addClass(item[0], 'aciTreeHidden'); + this._updateVisible(item); + } + } else { + this._updateVisible(item); + } + }, + // filter only the hidden items + hidden: function(items) { + return $(domApi.withClass(items.toArray(), 'aciTreeHidden')); + }, + // show hidden item + _showHidden: function(item) { + var parent = null; + this.path(item).add(item).each(this.proxy(function(element) { + var item = $(element); + if (this.isHidden(item)) { + domApi.removeClass(item[0], 'aciTreeHidden'); + if (this.isOpenPath(item) && (!parent || this.isOpen(parent))) { + domApi.addClass(item[0], 'aciTreeVisible'); + } + // update item states + this._setFirstLast(parent, this._getFirstLast(parent)); + } + parent = item; + }, true)); + }, + // show hidden item + show: function(item, options) { + options = this._options(options, 'shown', 'showfail', 'wasshown', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeshow', options)) { + this._fail(item, options); + return; + } + if (this.isHidden(item)) { + this._showHidden(item); + var parent = this.topParent(item); + // update item states + this._setOddEven(parent.length ? parent : item); + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // test if item is open + isOpen: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeOpen'); + }, + // test if item is closed + isClosed: function(item) { + return item && !domApi.hasClass(item[0], 'aciTreeOpen'); + }, + // test if item has children + // if `hidden` is TRUE then the hidden items will be considered too + hasChildren: function(item, hidden) { + return this.children(item, false, hidden).length > 0; + }, + // test if item has siblings + // if `hidden` is TRUE then the hidden items will be considered too + hasSiblings: function(item, hidden) { + return this.siblings(item, hidden).length > 0; + }, + // test if item has another before + // if `hidden` is TRUE then the hidden items will be considered too + hasPrev: function(item, hidden) { + return this.prev(item, hidden).length > 0; + }, + // test if item has another after + // if `hidden` is TRUE then the hidden items will be considered too + hasNext: function(item, hidden) { + return this.next(item, hidden).length > 0; + }, + // get item siblings + // if `hidden` is TRUE then the hidden items will be considered too + siblings: function(item, hidden) { + return item ? $(domApi.children(item[0].parentNode.parentNode, false, function(node) { + return (node != item[0]) && (hidden || !this.hasClass(node, 'aciTreeHidden')); + })) : $([]); + }, + // get previous item + // if `hidden` is TRUE then the hidden items will be considered too + prev: function(item, hidden) { + return item ? $(domApi.prev(item[0], hidden ? null : function(node) { + return !this.hasClass(node, 'aciTreeHidden'); + })) : $([]); + }, + // get next item + // if `hidden` is TRUE then the hidden items will be considered too + next: function(item, hidden) { + return item ? $(domApi.next(item[0], hidden ? null : function(node) { + return !this.hasClass(node, 'aciTreeHidden'); + })) : $([]); + }, + // get item level - starting from 0 + // return -1 for invalid items + level: function(item) { + var level = -1; + if (item) { + var node = item[0]; + while (domApi.hasClass(node, 'aciTreeLi')) { + node = node.parentNode.parentNode; + level++; + } + } + return level; + }, + // get item ID + getId: function(item) { + var data = this.itemData(item); + return data ? data.id : null; + }, + // get item data + itemData: function(item) { + return item ? item.data('itemData' + this._instance.nameSpace) : null; + }, + // set item ID + // `options.id` is the new item ID + // `options.oldId` will keep the old ID + setId: function(item, options) { + options = this._options(options, 'idset', 'idfail', 'wasid', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeid', options)) { + this._fail(item, options); + return; + } + var data = this.itemData(item); + // keep the old one + options.oldId = data.id; + if (options.id == options.oldId) { + this._notify(item, options); + } else { + // remember this one + data.id = options.id; + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // get item index - starting from #0 + getIndex: function(item) { + if (item && item[0]) { + if (window.Array.prototype.indexOf) { + return window.Array.prototype.indexOf.call(item[0].parentNode.childNodes, item[0]); + } else { + var children = item[0].parentNode.childNodes; + for (var i = 0; i < children.length; i++) { + if (children[i] == item[0]) { + return i; + } + } + } + } + return null; + }, + // set item index - #0 based + // `options.index` is the new index + // `options.oldIndex` will keep the old index + setIndex: function(item, options) { + options = this._options(options, 'indexset', 'indexfail', 'wasindex', item); + if (this.isItem(item)) { + var oldIndex = this.getIndex(item); + var siblings = this.siblings(item); + if ((options.index != oldIndex) && !siblings.length) { + this._fail(item, options); + return; + } + // a way to cancel the operation + if (!this._trigger(item, 'beforeindex', options)) { + this._fail(item, options); + return; + } + // keep the old one + options.oldIndex = oldIndex; + if (options.index == oldIndex) { + this._notify(item, options); + } else { + // set the new index + if (options.index < 1) { + siblings.first().before(item); + } else if (options.index >= siblings.length) { + siblings.last().after(item); + } else { + siblings.eq(options.index).before(item); + } + var parent = this.parent(item); + // update item states + this._setFirstLast(parent.length ? parent : null, item.add([siblings[0], siblings.get(-1)])); + this._setOddEven(parent); + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // get item label + getLabel: function(item) { + var data = this.itemData(item); + return data ? data.label : null; + }, + // test if is valid item + isItem: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeLi'); + }, + // item animation + // `state` if TRUE then show, FALSE then hide + // `unanimated` if TRUE then don't use animations + // `callback` function () to call at the end + _animate: function(item, state, unanimated, callback) { + if (!item) { + item = this._instance.jQuery; + } + if (!unanimated) { + // use the defined animation props + var setting = state ? this._instance.options.show : this._instance.options.hide; + if (setting) { + var ul = domApi.container(item[0]); + if (ul) { + // animate children container + $(ul).stop(true, true).animate(setting.props, { + duration: setting.duration, + easing: setting.easing, + complete: callback ? this.proxy(callback) : null + }); + } else if (callback) { + callback.apply(this); + } + return; + } + } + // use no animation + $(domApi.container(item[0])).stop(true, true).toggle(state); + if (callback) { + callback.apply(this); + } + }, + // get first children of item + // if `hidden` is TRUE then the hidden items will be considered too + first: function(item, hidden) { + if (!item) { + item = this._instance.jQuery; + } + return $(domApi.firstChild(item[0], hidden ? null : function(node) { + return !this.hasClass(node, 'aciTreeHidden'); + })); + }, + // test if item is the first one for his parent + // if `hidden` is TRUE then the hidden items will be considered too + isFirst: function(item, hidden) { + if (item) { + var parent = domApi.parent(item[0]); + return this.first(parent ? $(parent) : null, hidden)[0] == item[0]; + } + return false; + }, + // get last children of item + // if `hidden` is TRUE then the hidden items will be considered too + last: function(item, hidden) { + if (!item) { + item = this._instance.jQuery; + } + return $(domApi.lastChild(item[0], hidden ? null : function(node) { + return !this.hasClass(node, 'aciTreeHidden'); + })); + }, + // test if item is the last one for his parent + // if `hidden` is TRUE then the hidden items will be considered too + isLast: function(item, hidden) { + if (item) { + var parent = domApi.parent(item[0]); + return this.last(parent ? $(parent) : null, hidden)[0] == item[0]; + } + return false; + }, + // test if item is busy/loading + isBusy: function(item) { + if (item) { + return domApi.hasClass(item[0], 'aciTreeLoad'); + } else { + return this._instance.queue.busy(); + } + }, + // set loading state + _loading: function(item, state) { + if (item) { + domApi.toggleClass(item[0], 'aciTreeLoad', state); + if (state) { + item[0].firstChild.setAttribute('aria-busy', true); + } else { + item[0].firstChild.removeAttribute('aria-busy'); + } + } else if (state) { + this._loader(state); + } + }, + // show loader image + _loader: function(show) { + if (show || this.isBusy()) { + if (!this._private.loaderInterval) { + this._private.loaderInterval = window.setInterval(this.proxy(function() { + this._loader(); + }), this._instance.options.loaderDelay); + } + domApi.addClass(this._instance.jQuery[0], 'aciTreeLoad'); + window.clearTimeout(this._private.loaderHide); + this._private.loaderHide = window.setTimeout(this.proxy(function() { + domApi.removeClass(this._instance.jQuery[0], 'aciTreeLoad'); + }), this._instance.options.loaderDelay * 2); + } + }, + // test if parent has children + isChildren: function(parent, children) { + if (!parent) { + parent = this._instance.jQuery; + } + return children && (parent.has(children).length > 0); + }, + // test if parent has immediate children + isImmediateChildren: function(parent, children) { + if (!parent) { + parent = this._instance.jQuery; + } + return children && parent.children('.aciTreeUl').children('.aciTreeLi').is(children); + }, + // test if items share the same parent + sameParent: function(item1, item2) { + if (item1 && item2) { + var parent1 = this.parent(item1); + var parent2 = this.parent(item2); + return (!parent1.length && !parent2.length) || (parent1[0] == parent2[0]); + } + return false; + }, + // test if items share the same top parent + sameTopParent: function(item1, item2) { + if (item1 && item2) { + var parent1 = this.topParent(item1); + var parent2 = this.topParent(item2); + return (!parent1.length && !parent2.length) || (parent1[0] == parent2[0]); + } + return false; + }, + // return the updated item data + // `callback` function (item) called for each item + _serialize: function(item, callback) { + var data = this.itemData(item); + if (this.isInode(item)) { + data.inode = true; + if (this.wasLoad(item)) { + if (data.hasOwnProperty('open')) { + data.open = this.isOpen(item); + } else if (this.isOpen(item)) { + data.open = true; + } + data.branch = []; + this.children(item, false, true).each(this.proxy(function(element) { + var entry = this._serialize($(element), callback); + if (callback) { + entry = callback.call(this, $(element), { + }, entry); + } else { + entry = this._instance.options.serialize.call(this, $(element), { + }, entry); + } + if (entry) { + data.branch.push(entry); + } + }, true)); + if (!data.branch.length) { + data.branch = null; + } + } else { + if (data.hasOwnProperty('open')) { + data.open = false; + } + if (data.hasOwnProperty('branch')) { + data.branch = null; + } + } + } else { + if (data.hasOwnProperty('inode')) { + data.inode = false; + } + if (data.hasOwnProperty('open')) { + data.open = null; + } + if (data.hasOwnProperty('branch')) { + data.branch = null; + } + } + if (data.hasOwnProperty('disabled')) { + data.disabled = this.isDisabled(item); + } else if (this.isDisabled(item)) { + data.disabled = true; + } + return data; + }, + // return serialized data + // `callback` function (item, what, value) - see `aciTree.options.serialize` + serialize: function(item, what, callback) { + // override this to provide serialized data + if (typeof what == 'object') { + if (item) { + var data = this._serialize(item, callback); + if (callback) { + data = callback.call(this, item, { + }, data); + } else { + data = this._instance.options.serialize.call(this, item, { + }, data); + } + return data; + } else { + var list = []; + this.children(null, false, true).each(this.proxy(function(element) { + var data = this._serialize($(element), callback); + if (callback) { + data = callback.call(this, $(element), { + }, data); + } else { + data = this._instance.options.serialize.call(this, $(element), { + }, data); + } + if (data) { + list.push(data); + } + }, true)); + return list; + } + } + return ''; + }, + // destroy the control + destroy: function(options) { + options = this._options(options); + // check if was init + if (!this.wasInit()) { + this._trigger(null, 'notinit', options); + this._fail(null, options); + return; + } + // check if is locked + if (this.isLocked()) { + this._trigger(null, 'locked', options); + this._fail(null, options); + return; + } + // a way to cancel the operation + if (!this._trigger(null, 'beforedestroy', options)) { + this._trigger(null, 'destroyfail', options); + this._fail(null, options); + return; + } + this._private.locked = true; + this._instance.jQuery.addClass('aciTreeLoad').attr('aria-busy', true); + this._instance.queue.destroy(); + this._destroyHook(false); + // unload the entire treeview + this.unload(null, this._inner(options, { + success: this.proxy(function() { + window.clearTimeout(this._private.loaderHide); + window.clearInterval(this._private.loaderInterval); + this._private.itemClone = { + }; + this._destroyHook(true); + this._instance.jQuery.unbind(this._instance.nameSpace).off(this._instance.nameSpace, '.aciTreeButton').off(this._instance.nameSpace, '.aciTreeLine'); + this._instance.jQuery.removeClass('aciTree' + this._instance.index + ' aciTreeLoad').removeAttr('role aria-busy'); + this._private.locked = false; + // call the parent + this._super(); + this._trigger(null, 'destroyed', options); + this._success(null, options); + }), + fail: function() { + this._instance.jQuery.removeClass('aciTreeLoad'); + this._private.locked = false; + this._trigger(null, 'destroyfail', options); + this._fail(null, options); + } + })); + }, + _destroyHook: function(unloaded) { + // override this to do extra destroy before/after unload + } + + }; + + // extend the base aciPluginUi class and store into aciPluginClass.plugins + aciPluginClass.plugins.aciTree = aciPluginClass.aciPluginUi.extend(aciTree_core, 'aciTreeCore'); + + // publish the plugin & the default options + aciPluginClass.publish('aciTree', options); + + // for internal access + var domApi = aciPluginClass.plugins.aciTree_dom; + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.debug.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.debug.js new file mode 100755 index 000000000..50564475f --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.debug.js @@ -0,0 +1,87 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * This extension adds debug capabilities, for now it's just a log of the aciTree events. + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + logTo: null // selector for the element where to log the errors to + }; + + // aciTree debug extension + + var aciTree_debug = { + __extend: function() { + $.extend(this._private, { + logTo: null + }); + // call the parent + this._super(); + }, + // init debug + _debugInit: function() { + if (this._instance.options.logTo) { + this._private.logTo = $(this._instance.options.logTo); + } + this._instance.jQuery.bind('acitree' + this._private.nameSpace, this.proxy(function(event, api, item, eventName, options) { + var message = 'aciTree event:' + eventName + ' for:' + (item ? api.getId(item) : 'ROOT') + ' uid:' + options.uid + + ' success:' + (options.success ? 'Y' : 'N') + ' fail:' + (options.fail ? 'Y' : 'N') + ' expand:' + (options.expand ? 'Y' : 'N') + + ' collapse:' + (options.collapse ? 'Y' : 'N') + ' unique:' + (options.unique ? 'Y' : 'N') + ' animated:' + (options.unanimated ? 'N' : 'Y'); + if (this._private.logTo) { + this._private.logTo.prepend(message.replace(/([^\s]+:)/g, '$1') + '
    '); + } else if (console && console.log) { + console.log(message); + } else { + throw new Error(message); + } + })); + }, + // override `_initHook` + _initHook: function() { + this._debugInit(); + // call the parent + this._super(); + }, + // override set `option` + option: function(option, value) { + if (option == 'logTo') { + this._private.logTo = value ? $(value) : null; + } + // call the parent + this._super(option, value); + }, + // done debug + _debugDone: function() { + this._instance.jQuery.unbind(this._private.nameSpace); + }, + // override _destroyHook + _destroyHook: function(unloaded) { + if (unloaded) { + this._debugDone(); + } + // call the parent + this._super(unloaded); + } + }; + + // extend the base aciTree class and add the hash stuff + aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_debug, 'aciTreeDebug'); + + // add extra default options + aciPluginClass.defaults('aciTree', options); + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.dom.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.dom.js new file mode 100755 index 000000000..ffafc7206 --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.dom.js @@ -0,0 +1,660 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * The aciTree low-level DOM functions. + * + * A collection of functions optimised for aciTree DOM structure. + * + * Need to be included before the aciTree core and after aciPlugin. + */ + +aciPluginClass.plugins.aciTree_dom = { + // get the UL container from a LI + // `node` must be valid LI DOM node + // can return NULL + container: function(node) { + var container = node.lastChild; + if (container && (container.nodeName == 'UL')) { + return container; + } + return null; + }, + // get the first children from a LI (with filtering) + // `node` must be valid LI DOM node + // `callback` can return FALSE to skip a node + // can return NULL + firstChild: function(node, callback) { + var container = this.container(node); + if (container) { + var firstChild = container.firstChild; + if (callback) { + while (firstChild && !callback.call(this, firstChild)) { + firstChild = firstChild.nextSibling; + } + } + return firstChild; + } + return null; + }, + // get the last children from a LI (with filtering) + // `node` must be valid LI DOM node + // `callback` can return FALSE to skip a node + // can return NULL + lastChild: function(node, callback) { + var container = this.container(node); + if (container) { + var lastChild = container.lastChild; + if (callback) { + while (lastChild && !callback.call(this, lastChild)) { + lastChild = lastChild.previousSibling; + } + } + return lastChild; + } + return null; + }, + // get the previous LI sibling (with filtering) + // `node` must be valid LI DOM node + // `callback` can return FALSE to skip a node + // can return NULL + prev: function(node, callback) { + var previous = node.previousSibling; + if (callback) { + while (previous && !callback.call(this, previous)) { + previous = previous.previousSibling; + } + } + return previous; + }, + // get the next LI sibling (with filtering) + // `node` must be valid LI DOM node + // `callback` can return FALSE to skip a node + // can return NULL + next: function(node, callback) { + var next = node.nextSibling; + if (callback) { + while (next && !callback.call(this, next)) { + next = next.nextSibling; + } + } + return next; + }, + // get the previous LI in tree order (with filtering) + // `node` must be valid LI DOM node + // `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node + // can return NULL + prevAll: function(node, callback) { + var previous, lastChild, drillDown, match, prev, parent; + while (true) { + previous = this.prev(node); + if (previous) { + if (callback) { + match = callback.call(this, previous); + if (match === null) { + node = previous; + continue; + } + } + lastChild = this.lastChild(previous); + if (lastChild) { + if (callback && (callback.call(this, lastChild) === null)) { + node = lastChild; + continue; + } + prev = false; + while (drillDown = this.lastChild(lastChild)) { + lastChild = drillDown; + if (callback) { + match = callback.call(this, lastChild); + if (match === null) { + node = lastChild; + prev = true; + break; + } + } + } + if (prev) { + continue; + } + if (callback) { + match = callback.call(this, lastChild); + if (match) { + return lastChild; + } else if (match !== null) { + node = lastChild; + continue; + } + } else { + return lastChild; + } + } else { + if (!callback || match) { + return previous; + } else { + node = previous; + continue; + } + } + } + parent = this.parent(node); + if (parent) { + if (callback) { + match = callback.call(this, parent); + if (match) { + return parent; + } else { + node = parent; + } + } else { + return parent; + } + } else { + return null; + } + } + return null; + }, + // get the next LI in tree order (with filtering) + // `node` must be valid LI DOM node + // `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node + // can return NULL + nextAll: function(node, callback) { + var firstChild, match, next, parent, child; + while (true) { + firstChild = this.firstChild(node); + if (firstChild) { + if (callback) { + match = callback.call(this, firstChild); + if (match) { + return firstChild; + } else { + node = firstChild; + if (match !== null) { + continue; + } + } + } else { + return firstChild; + } + } + while (true) { + next = this.next(node); + if (next) { + if (callback) { + match = callback.call(this, next); + if (match) { + return next; + } else { + node = next; + if (match !== null) { + break; + } else { + continue; + } + } + } else { + return next; + } + } else { + parent = node; + child = null; + while (parent = this.parent(parent)) { + next = this.next(parent); + if (next) { + if (callback) { + match = callback.call(this, next); + if (match) { + return next; + } else { + node = next; + if (match !== null) { + child = true; + } else { + child = false; + } + break; + } + } else { + return next; + } + } + } + if (child !== null) { + if (child) { + break; + } else { + continue; + } + } + return null; + } + } + } + return null; + }, + // get the first LI in tree order (with filtering) + // `node` must be valid LI DOM node + // `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node + // can return NULL + first: function(node, callback) { + var container = this.container(node); + if (container) { + var firstChild = container.firstChild; + if (firstChild) { + if (callback && !callback.call(this, firstChild)) { + return this.nextAll(firstChild, callback); + } + return firstChild; + } + } + return null; + }, + // get the last LI in tree order (with filtering) + // `node` must be valid LI DOM node + // `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node + // can return NULL + last: function(node, callback) { + var container = this.container(node); + if (container) { + var lastChild = container.lastChild; + if (lastChild) { + if (callback && (callback.call(this, lastChild) === null)) { + return this.prevAll(lastChild, callback); + } else { + var drillDown; + while (drillDown = this.lastChild(lastChild)) { + lastChild = drillDown; + } + if (callback && !callback.call(this, lastChild)) { + return this.prevAll(lastChild, callback); + } + return lastChild; + } + } + } + return null; + }, + // get the children LI from the node + // `node` must be valid LI DOM node + // `drillDown` if TRUE all children are returned + // `callback` can return FALSE to skip a node or NULL to prevent drill down/skip the node + children: function(node, drillDown, callback) { + var children = [], levels = [], match, next, skip; + var firstChild = this.firstChild(node); + if (firstChild) { + while (true) { + skip = false; + do { + if (callback) { + match = callback.call(this, firstChild); + if (match) { + children.push(firstChild); + } + if (drillDown && (match !== null)) { + next = this.firstChild(firstChild); + if (next) { + levels.push(firstChild); + firstChild = next; + skip = true; + break; + } + } + } else { + children.push(firstChild); + if (drillDown) { + next = this.firstChild(firstChild); + if (next) { + levels.push(firstChild); + firstChild = next; + skip = true; + break; + } + } + } + } while (firstChild = firstChild.nextSibling); + if (!skip) { + while (firstChild = levels.pop()) { + firstChild = firstChild.nextSibling; + if (firstChild) { + break; + } + } + if (!firstChild) { + break; + } + } + } + } + return children; + }, + // get a children from the node + // `node` must be valid DOM node + // `callback` can return FALSE to skip a node or NULL to stop the search + // can return NULL + childrenTill: function(node, callback) { + var levels = [], match, next, skip; + var firstChild = node.firstChild; + if (firstChild) { + while (true) { + skip = false; + do { + match = callback.call(this, firstChild); + if (match) { + return firstChild; + } else if (match === null) { + return null; + } + next = firstChild.firstChild; + if (next) { + levels.push(firstChild); + firstChild = next; + skip = true; + break; + } + } while (firstChild = firstChild.nextSibling); + if (!skip) { + while (firstChild = levels.pop()) { + firstChild = firstChild.nextSibling; + if (firstChild) { + break; + } + } + if (!firstChild) { + break; + } + } + } + } + return null; + }, + // get a children from the node having a class + // `node` must be valid DOM node + // `className` String or Array to check for + // can return NULL + childrenByClass: function(node, className) { + if (node.getElementsByClassName) { + var list = node.getElementsByClassName(className instanceof Array ? className.join(' ') : className); + return list ? list[0] : null; + } else { + return this.childrenTill(node, function(node) { + return this.hasClass(node, className); + }); + } + }, + // get the parent LI from the children LI + // `node` must be valid LI DOM node + // can return NULL + parent: function(node) { + var parent = node.parentNode.parentNode; + if (parent && (parent.nodeName == 'LI')) { + return parent; + } + return null; + }, + // get the parent LI from any children + // `node` must be valid children of a LI DOM node + // can return NULL + parentFrom: function(node) { + while (node.nodeName != 'LI') { + node = node.parentNode; + if (!node) { + return null; + } + } + return node; + }, + // get a parent from the node + // `node` must be valid DOM node + // `callback` can return FALSE to skip a node or NULL to stop the search + // can return NULL + parentTill: function(node, callback) { + var match; + while (node = node.parentNode) { + match = callback.call(this, node); + if (match) { + return node; + } else if (match === null) { + return null; + } + } + return null; + }, + // get a parent from the node having a class + // `node` must be valid DOM node + // `className` String or Array to check for + // can return NULL + parentByClass: function(node, className) { + return this.parentTill(node, function(node) { + return this.hasClass(node, className); + }); + }, + // test if node has class(es) + // `className` String or Array to check for + // `withOut` String or Array to exclude with + hasClass: function(node, className, withOut) { + var oldClass = ' ' + node.className + ' '; + if (withOut instanceof Array) { + for (var i = 0; i < withOut.length; i++) { + if (oldClass.indexOf(' ' + withOut[i] + ' ') != -1) { + return false; + } + } + } else { + if (withOut && oldClass.indexOf(' ' + withOut + ' ') != -1) { + return false; + } + } + if (className instanceof Array) { + for (var i = 0; i < className.length; i++) { + if (oldClass.indexOf(' ' + className[i] + ' ') == -1) { + return false; + } + } + } else { + if (className && oldClass.indexOf(' ' + className + ' ') == -1) { + return false; + } + } + return true; + }, + // filter nodes with class(es) + // `nodes` Array of DOM nodes + // @see `hasClass` + withClass: function(nodes, className, withOut) { + var filter = []; + for (var i = 0; i < nodes.length; i++) { + if (this.hasClass(nodes[i], className, withOut)) { + filter.push(nodes[i]); + } + } + return filter; + }, + // test if node has any class(es) + // `className` String or Array to check for (any class) + // `withOut` String or Array to exclude with + hasAnyClass: function(node, className, withOut) { + var oldClass = ' ' + node.className + ' '; + if (withOut instanceof Array) { + for (var i = 0; i < withOut.length; i++) { + if (oldClass.indexOf(' ' + withOut[i] + ' ') != -1) { + return false; + } + } + } else { + if (withOut && oldClass.indexOf(' ' + withOut + ' ') != -1) { + return false; + } + } + if (className instanceof Array) { + for (var i = 0; i < className.length; i++) { + if (oldClass.indexOf(' ' + className[i] + ' ') != -1) { + return true; + } + } + } else { + if (className && oldClass.indexOf(' ' + className + ' ') != -1) { + return true; + } + } + return false; + }, + // filter nodes with any class(es) + // `nodes` Array of DOM nodes + // @see `hasAnyClass` + withAnyClass: function(nodes, className, withOut) { + var filter = []; + for (var i = 0; i < nodes.length; i++) { + if (this.hasAnyClass(nodes[i], className, withOut)) { + filter.push(nodes[i]); + } + } + return filter; + }, + // add class(es) to node + // `node` must be valid DOM node + // `className` String or Array to add + // return TRUE if className changed + addClass: function(node, className) { + var oldClass = ' ' + node.className + ' ', append = ''; + if (className instanceof Array) { + for (var i = 0; i < className.length; i++) { + if (oldClass.indexOf(' ' + className[i] + ' ') == -1) { + append += ' ' + className[i]; + } + } + } else { + if (oldClass.indexOf(' ' + className + ' ') == -1) { + append += ' ' + className; + } + } + if (append) { + node.className = node.className + append; + return true; + } + return false; + }, + // add class(es) to nodes + // `nodes` Array of DOM nodes + // @see `addClass` + addListClass: function(nodes, className, callback) { + for (var i = 0; i < nodes.length; i++) { + this.addClass(nodes[i], className); + if (callback) { + callback.call(this, nodes[i]); + } + } + }, + // remove class(es) from node + // `node` must be valid DOM node + // `className` String or Array to remove + // return TRUE if className changed + removeClass: function(node, className) { + var oldClass = ' ' + node.className + ' '; + if (className instanceof Array) { + for (var i = 0; i < className.length; i++) { + oldClass = oldClass.replace(' ' + className[i] + ' ', ' '); + } + } else { + oldClass = oldClass.replace(' ' + className + ' ', ' '); + } + oldClass = oldClass.substr(1, oldClass.length - 2); + if (node.className != oldClass) { + node.className = oldClass; + return true; + } + return false; + }, + // remove class(es) from nodes + // `nodes` Array of DOM nodes + // @see `removeClass` + removeListClass: function(nodes, className, callback) { + for (var i = 0; i < nodes.length; i++) { + this.removeClass(nodes[i], className); + if (callback) { + callback.call(this, nodes[i]); + } + } + }, + // toggle node class(es) + // `node` must be valid DOM node + // `className` String or Array to toggle + // `add` TRUE to add them + // return TRUE if className changed + toggleClass: function(node, className, add) { + if (add) { + return this.addClass(node, className); + } else { + return this.removeClass(node, className); + } + }, + // toggle nodes class(es) + // `nodes` Array of DOM nodes + // @see `toggleClass` + toggleListClass: function(nodes, className, add, callback) { + for (var i = 0; i < nodes.length; i++) { + this.toggleClass(nodes[i], className, add); + if (callback) { + callback.call(this, nodes[i]); + } + } + }, + // add/remove and keep old class(es) + // `node` must be valid DOM node + // `addClass` String or Array to add + // `removeClass` String or Array to remove + // return TRUE if className changed + addRemoveClass: function(node, addClass, removeClass) { + var oldClass = ' ' + node.className + ' '; + if (removeClass) { + if (removeClass instanceof Array) { + for (var i = 0; i < removeClass.length; i++) { + oldClass = oldClass.replace(' ' + removeClass[i] + ' ', ' '); + } + } else { + oldClass = oldClass.replace(' ' + removeClass + ' ', ' '); + } + } + if (addClass) { + var append = ''; + if (addClass instanceof Array) { + for (var i = 0; i < addClass.length; i++) { + if (oldClass.indexOf(' ' + addClass[i] + ' ') == -1) { + append += addClass[i] + ' '; + } + } + } else { + if (oldClass.indexOf(' ' + addClass + ' ') == -1) { + append += addClass + ' '; + } + } + oldClass += append; + } + oldClass = oldClass.substr(1, oldClass.length - 2); + if (node.className != oldClass) { + node.className = oldClass; + return true; + } + return false; + }, + // add/remove and keep old class(es) + // `nodes` Array of DOM nodes + // @see `addRemoveClass` + addRemoveListClass: function(nodes, addClass, removeClass, callback) { + for (var i = 0; i < nodes.length; i++) { + this.addRemoveClass(nodes[i], addClass, removeClass); + if (callback) { + callback.call(this, nodes[i]); + } + } + } +}; diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.editable.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.editable.js new file mode 100755 index 000000000..c184dcb26 --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.editable.js @@ -0,0 +1,294 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * This extension adds inplace edit support to aciTree, + * should be used with the selectable extension. + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + editable: false, // if TRUE then each item will be inplace editable + editDelay: 250 // how many [ms] to wait (with mouse down) before starting the edit (on mouse release) + }; + + // aciTree editable extension + // add inplace item editing by pressing F2 key or mouse click (to enter edit mode) + // press enter/escape to save/cancel the text edit + + var aciTree_editable = { + __extend: function() { + // add extra data + $.extend(this._private, { + editTimestamp: null + }); + // call the parent + this._super(); + }, + // init editable + _editableInit: function() { + this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) { + switch (eventName) { + case 'blurred': + // support `selectable` extension + var item = api.edited(); + if (item.length) { + // cancel edit/save the changes + api.endEdit(); + } + break; + case 'deselected': + // support `selectable` extension + if (api.isEdited(item)) { + // cancel edit/save the changes + api.endEdit(); + } + break; + } + }).bind('click' + this._private.nameSpace, this.proxy(function() { + // click on the tree + var item = this.edited(); + if (item.length) { + // cancel edit/save the changes + this.endEdit(); + } + })).bind('keydown' + this._private.nameSpace, this.proxy(function(e) { + switch (e.which) { + case 113: // F2 + // support `selectable` extension + if (this.extSelectable && this.extSelectable()) { + var item = this.focused(); + if (item.length && !this.isEdited(item) && this.isEnabled(item)) { + // enable edit on F2 key + this.edit(item); + // prevent default F2 key function + e.preventDefault(); + } + } + break; + } + })).on('mousedown' + this._private.nameSpace, '.aciTreeItem', this.proxy(function(e) { + if ($(e.target).is('.aciTreeItem,.aciTreeText')) { + this._private.editTimestamp = $.now(); + } + })).on('mouseup' + this._private.nameSpace, '.aciTreeItem', this.proxy(function(e) { + if ($(e.target).is('.aciTreeItem,.aciTreeText')) { + var passed = $.now() - this._private.editTimestamp; + // start edit only after N [ms] but before N * 4 [ms] have passed + if ((passed > this._instance.options.editDelay) && (passed < this._instance.options.editDelay * 4)) { + var item = this.itemFrom(e.target); + if ((!this.extSelectable || !this.extSelectable() || (this.isFocused(item) && (this.selected().length == 1))) && this.isEnabled(item)) { + // edit on mouseup + this.edit(item); + } + } + } + })).on('keydown' + this._private.nameSpace, 'input[type=text]', this.proxy(function(e) { + // key handling + switch (e.which) { + case 13: // enter + this.itemFrom(e.target).focus(); + this.endEdit(); + e.stopPropagation(); + break; + case 27: // escape + this.itemFrom(e.target).focus(); + this.endEdit({ + save: false + }); + e.stopPropagation(); + // prevent default action on ESC + e.preventDefault(); + break; + case 38: // up + case 40: // down + case 37: // left + case 39: // right + case 33: // pgup + case 34: // pgdown + case 36: // home + case 35: // end + case 32: // space + case 107: // numpad [+] + case 109: // numpad [-] + case 106: // numpad [*] + e.stopPropagation(); + break; + } + })).on('blur' + this._private.nameSpace, 'input[type=text]', this.proxy(function() { + if (!this.extSelectable || !this.extSelectable()) { + // cancel edit/save the changes + this.endEdit(); + } + })).on('click' + this._private.nameSpace + ' dblclick' + this._private.nameSpace, 'input[type=text]', function(e) { + e.stopPropagation(); + }); + }, + // override `_initHook` + _initHook: function() { + if (this.extEditable()) { + this._editableInit(); + } + // call the parent + this._super(); + }, + // low level DOM functions + _editableDOM: { + // add edit field + add: function(item) { + var line = item.addClass('aciTreeEdited').children('.aciTreeLine'); + line.find('.aciTreeText').html(''); + line.find('label').attr('for', 'aciTree-editable-tree-item'); + this._editableDOM.get(item).val(this.getLabel(item)); + }, + // remove edit field + remove: function(item, label) { + var line = item.removeClass('aciTreeEdited').children('.aciTreeLine'); + line.find('.aciTreeText').html(this.getLabel(item)); + line.find('label').removeAttr('for'); + }, + // return edit field + get: function(item) { + return item ? item.children('.aciTreeLine').find('input[type=text]') : $([]); + } + }, + // get edited item + edited: function() { + return this._instance.jQuery.find('.aciTreeEdited'); + }, + // test if item is edited + isEdited: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeEdited'); + }, + // set focus to the input + _focusEdit: function(item) { + var field = this._editableDOM.get(item).focus().trigger('click')[0]; + if (field) { + if (typeof field.selectionStart == 'number') { + field.selectionStart = field.selectionEnd = field.value.length; + } else if (field.createTextRange !== undefined) { + var range = field.createTextRange(); + range.collapse(false); + range.select(); + } + } + }, + // override `setLabel` + setLabel: function(item, options) { + if (!this.extEditable() || !this.isEdited(item)) { + // call the parent + this._super(item, options); + } + }, + // edit item inplace + edit: function(item, options) { + options = this._options(options, 'edit', 'editfail', 'wasedit', item); + if (this.extEditable() && this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeedit', options)) { + this._fail(item, options); + return; + } + var edited = this.edited(); + if (edited.length) { + if (edited[0] == item[0]) { + this._notify(item, options); + return; + } else { + this._editableDOM.remove.call(this, edited); + this._trigger(edited, 'endedit', options); + } + } + this._editableDOM.add.call(this, item); + this._focusEdit(item); + this._success(item, options); + } else { + this._fail(item, options); + } + }, + // end edit + // `options.save` when set to FALSE will not save the changes + endEdit: function(options) { + var item = this.edited(); + options = this._options(options, 'edited', 'endeditfail', 'endedit', item); + if (this.extEditable() && this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeendedit', options)) { + this._fail(item, options); + return; + } + var text = this._editableDOM.get(item).val(); + this._editableDOM.remove.call(this, item); + if ((options.save === undefined) || options.save) { + this.setLabel(item, { + label: text + }); + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // test if editable is enabled + extEditable: function() { + return this._instance.options.editable; + }, + // override set `option` + option: function(option, value) { + if (this.wasInit() && !this.isLocked()) { + if ((option == 'editable') && (value != this.extEditable())) { + if (value) { + this._editableInit(); + } else { + this._editableDone(); + } + } + } + // call the parent + this._super(option, value); + }, + // done editable + _editableDone: function() { + this._instance.jQuery.unbind(this._private.nameSpace); + this._instance.jQuery.off(this._private.nameSpace, '.aciTreeItem'); + this._instance.jQuery.off(this._private.nameSpace, 'input[type=text]'); + var edited = this.edited(); + if (edited.length) { + this.endEdit(); + } + }, + // override `_destroyHook` + _destroyHook: function(unloaded) { + if (unloaded) { + this._editableDone(); + } + // call the parent + this._super(unloaded); + } + + }; + + // extend the base aciTree class and add the editable stuff + aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_editable, 'aciTreeEditable'); + + // add extra default options + aciPluginClass.defaults('aciTree', options); + + // for internal access + var domApi = aciPluginClass.plugins.aciTree_dom; + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.hash.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.hash.js new file mode 100755 index 000000000..7cadd0bca --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.hash.js @@ -0,0 +1,170 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * This extension adds hash/fragment support using aciFragment, it opens/select item(s) based on variables stored in the fragment part of the URL. + * The states are loaded from the URL fragment and set on treeview init. Multiple item IDs separated with ";" are supported for + * opening/selecting deep items (if loading nodes is required). + * Require aciFragment https://github.com/dragosu/jquery-aciFragment and the utils extension for finding items by ID. + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + selectHash: null, // hash key name to select a item (item path IDs as key value, multiple item IDs separated with a ";") + openHash: null // hash key name to open item(s) (item path IDs as key value, multiple item IDs separated with a ";") + }; + + // aciTree hash extension + // select/open items based on IDs stored in the fragment of the current URL + + var aciTree_hash = { + __extend: function() { + $.extend(this._private, { + lastSelect: null, + lastOpen: null, + // store `aciFragment` api + hashApi: null + }); + // call the parent + this._super(); + }, + // init hash + _hashInit: function() { + // init `aciFragment` + this._instance.jQuery.aciFragment(); + this._private.hashApi = this._instance.jQuery.aciFragment('api'); + this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) { + switch (eventName) { + case 'init': + api._hashRestore(); + break; + } + }).bind('acifragment' + this._private.nameSpace, this.proxy(function(event, api, anchorChanged) { + event.stopPropagation(); + this._hashRestore(); + })); + }, + // override `_initHook` + _initHook: function() { + if (this.extHast()) { + this._hashInit(); + } + // call the parent + this._super(); + }, + // restore item states from hash + _hashRestore: function() { + var queue = this._instance.queue; + var process = function(opened) { + // open all hash items + for (var i in opened) { + (function(id) { + // add item to queue + queue.push(function(complete) { + this.search(null, { + success: function(item) { + this.open(item, { + uid: 'ui.hash', + success: complete, + fail: complete + }); + }, + fail: complete, + search: id + }); + }); + })(opened[i]); + } + }; + if (this._instance.options.openHash) { + var hash = this._private.hashApi.get(this._instance.options.openHash, ''); + if (hash.length && (hash != this._private.lastOpen)) { + this._private.lastOpen = hash; + var opened = hash.split(';'); + process(opened); + } + } + // support `selectable` extension + if (this._instance.options.selectHash && this.extSelectable && this.extSelectable()) { + var hash = this._private.hashApi.get(this._instance.options.selectHash, ''); + if (hash.length && (hash != this._private.lastSelect)) { + this._private.lastSelect = hash; + var opened = hash.split(';'); + var selected = opened.pop(); + process(opened); + if (selected) { + // select item + queue.push(function(complete) { + this.search(null, { + success: function(item) { + this.select(item, { + uid: 'ui.hash', + success: function(item) { + this.setVisible(item, { + center: true + }); + complete(); + }, + fail: complete + }); + }, + fail: complete, + search: selected + }); + }); + } + } + } + }, + // test if hash is enabled + extHast: function() { + return this._instance.options.selectHash || this._instance.options.openHash; + }, + // override set option + option: function(option, value) { + var hash = this.extHast(); + // call the parent + this._super(option, value); + if (this.extHast() != hash) { + if (hash) { + this._hashDone(); + } else { + this._hashInit(); + } + } + }, + // done hash + _hashDone: function() { + this._instance.jQuery.unbind(this._private.nameSpace); + this._private.hashApi = null; + this._instance.jQuery.aciFragment('destroy'); + }, + // override `_destroyHook` + _destroyHook: function(unloaded) { + if (unloaded) { + this._hashDone(); + } + // call the parent + this._super(unloaded); + } + }; + + // extend the base aciTree class and add the hash stuff + aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_hash, 'aciTreeHash'); + + // add extra default options + aciPluginClass.defaults('aciTree', options); + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.min.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.min.js new file mode 100755 index 000000000..b00b953b4 --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.min.js @@ -0,0 +1,44 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +// DOM +aciPluginClass.plugins.aciTree_dom={container:function(b){var a=b.lastChild;if(a&&(a.nodeName=="UL")){return a}return null},firstChild:function(b,d){var a=this.container(b);if(a){var c=a.firstChild;if(d){while(c&&!d.call(this,c)){c=c.nextSibling}}return c}return null},lastChild:function(c,d){var a=this.container(c);if(a){var b=a.lastChild;if(d){while(b&&!d.call(this,b)){b=b.previousSibling}}return b}return null},prev:function(b,c){var a=b.previousSibling;if(c){while(a&&!c.call(this,a)){a=a.previousSibling}}return a},next:function(b,c){var a=b.nextSibling;if(c){while(a&&!c.call(this,a)){a=a.nextSibling}}return a},prevAll:function(f,h){var e,d,g,a,c,b;while(true){e=this.prev(f);if(e){if(h){a=h.call(this,e);if(a===null){f=e;continue}}d=this.lastChild(e);if(d){if(h&&(h.call(this,d)===null)){f=d;continue}c=false;while(g=this.lastChild(d)){d=g;if(h){a=h.call(this,d);if(a===null){f=d;c=true;break}}}if(c){continue}if(h){a=h.call(this,d);if(a){return d}else{if(a!==null){f=d;continue}}}else{return d}}else{if(!h||a){return e}else{f=e;continue}}}b=this.parent(f);if(b){if(h){a=h.call(this,b);if(a){return b}else{f=b}}else{return b}}else{return null}}return null},nextAll:function(d,g){var e,a,c,b,f;while(true){e=this.firstChild(d);if(e){if(g){a=g.call(this,e);if(a){return e}else{d=e;if(a!==null){continue}}}else{return e}}while(true){c=this.next(d);if(c){if(g){a=g.call(this,c);if(a){return c}else{d=c;if(a!==null){break}else{continue}}}else{return c}}else{b=d;f=null;while(b=this.parent(b)){c=this.next(b);if(c){if(g){a=g.call(this,c);if(a){return c}else{d=c;if(a!==null){f=true}else{f=false}break}}else{return c}}}if(f!==null){if(f){break}else{continue}}return null}}}return null},first:function(b,d){var a=this.container(b);if(a){var c=a.firstChild;if(c){if(d&&!d.call(this,c)){return this.nextAll(c,d)}return c}}return null},last:function(c,e){var a=this.container(c);if(a){var b=a.lastChild;if(b){if(e&&(e.call(this,b)===null)){return this.prevAll(b,e)}else{var d;while(d=this.lastChild(b)){b=d}if(e&&!e.call(this,b)){return this.prevAll(b,e)}return b}}}return null},children:function(b,f,h){var a=[],i=[],d,c,g;var e=this.firstChild(b);if(e){while(true){g=false;do{if(h){d=h.call(this,e);if(d){a.push(e)}if(f&&(d!==null)){c=this.firstChild(e);if(c){i.push(e);e=c;g=true;break}}}else{a.push(e);if(f){c=this.firstChild(e);if(c){i.push(e);e=c;g=true;break}}}}while(e=e.nextSibling);if(!g){while(e=i.pop()){e=e.nextSibling;if(e){break}}if(!e){break}}}}return a},childrenTill:function(d,g){var e=[],a,b,c;var f=d.firstChild;if(f){while(true){c=false;do{a=g.call(this,f);if(a){return f}else{if(a===null){return null}}b=f.firstChild;if(b){e.push(f);f=b;c=true;break}}while(f=f.nextSibling);if(!c){while(f=e.pop()){f=f.nextSibling;if(f){break}}if(!f){break}}}}return null},childrenByClass:function(b,a){if(b.getElementsByClassName){var c=b.getElementsByClassName(a instanceof Array?a.join(" "):a);return c?c[0]:null}else{return this.childrenTill(b,function(d){return this.hasClass(d,a)})}},parent:function(b){var a=b.parentNode.parentNode;if(a&&(a.nodeName=="LI")){return a}return null},parentFrom:function(a){while(a.nodeName!="LI"){a=a.parentNode;if(!a){return null}}return a},parentTill:function(b,c){var a;while(b=b.parentNode){a=c.call(this,b);if(a){return b}else{if(a===null){return null}}}return null},parentByClass:function(b,a){return this.parentTill(b,function(c){return this.hasClass(c,a)})},hasClass:function(e,d,a){var b=" "+e.className+" ";if(a instanceof Array){for(var c=0;c=0)&&(lt){o--;return}var v,u=false;if(ps.interval){m=t+s.delay}p--;if(o<40){o++;k()}})}}o--};var j=[];var g=function(){for(var t=0;t<4;t++){j[t]=c.setInterval(function(){if(o<20){o++;k()}},10)}};var n=function(){for(var t=0;tj.bottom-l)){return false}return true}return false},openPath:function(i,h){h=this._options(h);if(this.isItem(i)){var g=this._instance.queue;this.inodes(this.path(i),false).each(function(){var j=d(this);g.push(function(k){this.open(j,this._inner(h));k()})});g.push(function(j){this._success(i,h);j()})}else{this._fail(i,h)}},isOpenPath:function(h){var g=this.parent(h);return g[0]?this.isOpen(g)&&a.hasClass(g[0],"aciTreeVisible"):true},_speedFraction:function(i,g,j){if((jl.bottom-n){var m=o.top-l.bottom+n+j;if(!g.unanimated&&this._instance.options.view){this._instance.jQuery.stop(true).animate({scrollTop:this._instance.jQuery.scrollTop()+m},{duration:this._speedFraction(this._instance.options.view.duration,l.bottom-l.top,m),easing:this._instance.options.view.easing,complete:this.proxy(function(){this._success(h,g)})})}else{this._instance.jQuery.stop(true)[0].scrollTop=this._instance.jQuery.scrollTop()+m;this._success(h,g)}}else{this._success(h,g)}}};if(this.hasParent(h)){this.openPath(h,this._inner(g,{success:i,fail:g.fail}))}else{i.apply(this)}}else{this._fail(h,g)}},hasParent:function(g){return this.parent(g).length>0},parent:function(g){return g?d(a.parent(g[0])):d([])},topParent:function(g){return this.path(g).eq(0)},_createBranch:function(l,i){var k=0;var j=function(o){var n;for(var p=0;p=k){this._success(l,i)}});var m=this.proxy(function(o,n){if(o){a.addRemoveClass(o[0],"aciTreeInode","aciTreeInodeMaybe")}this.append(o,this._inner(i,{success:function(s,q){var p;for(var r=0;r0){var j=k[h];if(a.hasClass(j,"aciTreOdd")){i=false}k=k.slice(h+1)}}this._coreDOM.oddEven(d(k),i)},_setOddEvenChildren:function(h){var i=a.hasClass(h[0],"aciTreeOdd");var g=this.children(h);this._coreDOM.oddEven(g,!i)},_itemHook:function(h,i,g,j){if(this._instance.options.itemHook){this._instance.options.itemHook.apply(this,arguments)}},_createItem:function(h,g){if(this._private.itemClone[g]){var r=this._private.itemClone[g].cloneNode(true);var u=r.firstChild;var n=u;for(var j=0;j0},disabled:function(g){return d(a.withClass(g.toArray(),"aciTreeDisabled"))},enable:function(h,g){g=this._options(g,"enabled","enablefail","wasenabled",h);if(this.isItem(h)){if(!this._trigger(h,"beforeenable",g)){this._fail(h,g);return}if(this.isDisabled(h)){a.removeClass(h[0],"aciTreeDisabled");this._success(h,g)}else{this._notify(h,g)}}else{this._fail(h,g)}},isEnabled:function(g){return g&&!a.hasClass(g[0],"aciTreeDisabled")},isEnabledPath:function(g){return a.withClass(this.path(g).toArray(),"aciTreeDisabled").length==0},enabled:function(g){return d(a.withClass(g.toArray(),null,"aciTreeDisabled"))},hide:function(i,g){g=this._options(g,"hidden","hidefail","washidden",i);if(this.isItem(i)){if(!this._trigger(i,"beforehide",g)){this._fail(i,g);return}if(this.isHidden(i)){this._notify(i,g)}else{a.addRemoveClass(i[0],"aciTreeHidden","aciTreeVisible");a.addRemoveClass(this.children(i,true).toArray(),"aciTreeHidden","aciTreeVisible");var h=this.parent(i);this._setFirstLast(h.length?h:null,i);this._setOddEven(i);this._success(i,g)}}else{this._fail(i,g)}},isHidden:function(g){return g&&a.hasClass(g[0],"aciTreeHidden")},isHiddenPath:function(h){var g=this.parent(h);return g[0]&&a.hasClass(g[0],"aciTreeHidden")},_updateHidden:function(g){if(this.isHiddenPath(g)){if(!this.isHidden(g)){a.addClass(g[0],"aciTreeHidden");this._updateVisible(g)}}else{this._updateVisible(g)}},hidden:function(g){return d(a.withClass(g.toArray(),"aciTreeHidden"))},_showHidden:function(h){var g=null;this.path(h).add(h).each(this.proxy(function(i){var j=d(i);if(this.isHidden(j)){a.removeClass(j[0],"aciTreeHidden");if(this.isOpenPath(j)&&(!g||this.isOpen(g))){a.addClass(j[0],"aciTreeVisible")}this._setFirstLast(g,this._getFirstLast(g))}g=j},true))},show:function(i,g){g=this._options(g,"shown","showfail","wasshown",i);if(this.isItem(i)){if(!this._trigger(i,"beforeshow",g)){this._fail(i,g);return}if(this.isHidden(i)){this._showHidden(i);var h=this.topParent(i);this._setOddEven(h.length?h:i);this._success(i,g)}else{this._notify(i,g)}}else{this._fail(i,g)}},isOpen:function(g){return g&&a.hasClass(g[0],"aciTreeOpen")},isClosed:function(g){return g&&!a.hasClass(g[0],"aciTreeOpen")},hasChildren:function(g,h){return this.children(g,false,h).length>0},hasSiblings:function(g,h){return this.siblings(g,h).length>0},hasPrev:function(g,h){return this.prev(g,h).length>0},hasNext:function(g,h){return this.next(g,h).length>0},siblings:function(g,h){return g?d(a.children(g[0].parentNode.parentNode,false,function(i){return(i!=g[0])&&(h||!this.hasClass(i,"aciTreeHidden"))})):d([])},prev:function(g,h){return g?d(a.prev(g[0],h?null:function(i){return !this.hasClass(i,"aciTreeHidden")})):d([])},next:function(g,h){return g?d(a.next(g[0],h?null:function(i){return !this.hasClass(i,"aciTreeHidden")})):d([])},level:function(h){var i=-1;if(h){var g=h[0];while(a.hasClass(g,"aciTreeLi")){g=g.parentNode.parentNode;i++}}return i},getId:function(g){var h=this.itemData(g);return h?h.id:null},itemData:function(g){return g?g.data("itemData"+this._instance.nameSpace):null},setId:function(h,g){g=this._options(g,"idset","idfail","wasid",h);if(this.isItem(h)){if(!this._trigger(h,"beforeid",g)){this._fail(h,g);return}var i=this.itemData(h);g.oldId=i.id;if(g.id==g.oldId){this._notify(h,g)}else{i.id=g.id;this._success(h,g)}}else{this._fail(h,g)}},getIndex:function(j){if(j&&j[0]){if(c.Array.prototype.indexOf){return c.Array.prototype.indexOf.call(j[0].parentNode.childNodes,j[0])}else{var h=j[0].parentNode.childNodes;for(var g=0;g=j.length){j.last().after(i)}else{j.eq(g.index).before(i)}}var h=this.parent(i);this._setFirstLast(h.length?h:null,i.add([j[0],j.get(-1)]));this._setOddEven(h);this._success(i,g)}}else{this._fail(i,g)}},getLabel:function(g){var h=this.itemData(g);return h?h.label:null},isItem:function(g){return g&&a.hasClass(g[0],"aciTreeLi")},_animate:function(j,k,i,l){if(!j){j=this._instance.jQuery}if(!i){var h=k?this._instance.options.show:this._instance.options.hide;if(h){var g=a.container(j[0]);if(g){d(g).stop(true,true).animate(h.props,{duration:h.duration,easing:h.easing,complete:l?this.proxy(l):null})}else{if(l){l.apply(this)}}return}}d(a.container(j[0])).stop(true,true).toggle(k);if(l){l.apply(this)}},first:function(g,h){if(!g){g=this._instance.jQuery}return d(a.firstChild(g[0],h?null:function(i){return !this.hasClass(i,"aciTreeHidden")}))},isFirst:function(h,i){if(h){var g=a.parent(h[0]);return this.first(g?d(g):null,i)[0]==h[0]}return false},last:function(g,h){if(!g){g=this._instance.jQuery}return d(a.lastChild(g[0],h?null:function(i){return !this.hasClass(i,"aciTreeHidden")}))},isLast:function(h,i){if(h){var g=a.parent(h[0]);return this.last(g?d(g):null,i)[0]==h[0]}return false},isBusy:function(g){if(g){return a.hasClass(g[0],"aciTreeLoad")}else{return this._instance.queue.busy()}},_loading:function(g,h){if(g){a.toggleClass(g[0],"aciTreeLoad",h);if(h){g[0].firstChild.setAttribute("aria-busy",true)}else{g[0].firstChild.removeAttribute("aria-busy")}}else{if(h){this._loader(h)}}},_loader:function(g){if(g||this.isBusy()){if(!this._private.loaderInterval){this._private.loaderInterval=c.setInterval(this.proxy(function(){this._loader()}),this._instance.options.loaderDelay)}a.addClass(this._instance.jQuery[0],"aciTreeLoad");c.clearTimeout(this._private.loaderHide);this._private.loaderHide=c.setTimeout(this.proxy(function(){a.removeClass(this._instance.jQuery[0],"aciTreeLoad")}),this._instance.options.loaderDelay*2)}},isChildren:function(h,g){if(!h){h=this._instance.jQuery}return g&&(h.has(g).length>0)},isImmediateChildren:function(h,g){if(!h){h=this._instance.jQuery}return g&&h.children(".aciTreeUl").children(".aciTreeLi").is(g)},sameParent:function(i,g){if(i&&g){var j=this.parent(i);var h=this.parent(g);return(!j.length&&!h.length)||(j[0]==h[0])}return false},sameTopParent:function(i,g){if(i&&g){var j=this.topParent(i);var h=this.topParent(g);return(!j.length&&!h.length)||(j[0]==h[0])}return false},_serialize:function(g,i){var h=this.itemData(g);if(this.isInode(g)){h.inode=true;if(this.wasLoad(g)){if(h.hasOwnProperty("open")){h.open=this.isOpen(g)}else{if(this.isOpen(g)){h.open=true}}h.branch=[];this.children(g,false,true).each(this.proxy(function(j){var k=this._serialize(d(j),i);if(i){k=i.call(this,d(j),{},k)}else{k=this._instance.options.serialize.call(this,d(j),{},k)}if(k){h.branch.push(k)}},true));if(!h.branch.length){h.branch=null}}else{if(h.hasOwnProperty("open")){h.open=false}if(h.hasOwnProperty("branch")){h.branch=null}}}else{if(h.hasOwnProperty("inode")){h.inode=false}if(h.hasOwnProperty("open")){h.open=null}if(h.hasOwnProperty("branch")){h.branch=null}}if(h.hasOwnProperty("disabled")){h.disabled=this.isDisabled(g)}else{if(this.isDisabled(g)){h.disabled=true}}return h},serialize:function(g,j,k){if(typeof j=="object"){if(g){var i=this._serialize(g,k);if(k){i=k.call(this,g,{},i)}else{i=this._instance.options.serialize.call(this,g,{},i)}return i}else{var h=[];this.children(null,false,true).each(this.proxy(function(l){var m=this._serialize(d(l),k);if(k){m=k.call(this,d(l),{},m)}else{m=this._instance.options.serialize.call(this,d(l),{},m)}if(m){h.push(m)}},true));return h}}return""},destroy:function(g){g=this._options(g);if(!this.wasInit()){this._trigger(null,"notinit",g);this._fail(null,g);return}if(this.isLocked()){this._trigger(null,"locked",g);this._fail(null,g);return}if(!this._trigger(null,"beforedestroy",g)){this._trigger(null,"destroyfail",g);this._fail(null,g);return}this._private.locked=true;this._instance.jQuery.addClass("aciTreeLoad").attr("aria-busy",true);this._instance.queue.destroy();this._destroyHook(false);this.unload(null,this._inner(g,{success:this.proxy(function(){c.clearTimeout(this._private.loaderHide);c.clearInterval(this._private.loaderInterval);this._private.itemClone={};this._destroyHook(true);this._instance.jQuery.unbind(this._instance.nameSpace).off(this._instance.nameSpace,".aciTreeButton").off(this._instance.nameSpace,".aciTreeLine");this._instance.jQuery.removeClass("aciTree"+this._instance.index+" aciTreeLoad").removeAttr("role aria-busy");this._private.locked=false;this._super();this._trigger(null,"destroyed",g);this._success(null,g)}),fail:function(){this._instance.jQuery.removeClass("aciTreeLoad");this._private.locked=false;this._trigger(null,"destroyfail",g);this._fail(null,g)}}))},_destroyHook:function(g){}};aciPluginClass.plugins.aciTree=aciPluginClass.aciPluginUi.extend(e,"aciTreeCore");aciPluginClass.publish("aciTree",b);var a=aciPluginClass.plugins.aciTree_dom})(jQuery,this); + +// utils +(function(e,d,f){var b={filterHook:function(h,g,i){return g.length?i.test(d.String(this.getLabel(h))):true}};var c={__extend:function(){e.extend(this._instance,{filter:new this._queue(this,this._instance.options.queue)});this._instance.filter.destroy();this._super()},branch:function(h,k,i){var g=this._instance.queue;var j=this.proxy(function(m,o,l){var n=l?this.next(m):this.first(m);if(n.length){if(this.isInode(n)){if(this.wasLoad(n)){g.push(function(p){o.call(this,n);j(n,o);j(n,o,true);p()})}else{if(i){this.ajaxLoad(n,{success:function(){o.call(this,n);j(n,o);j(n,o,true)},fail:function(){j(n,o,true)}})}else{g.push(function(p){o.call(this,n);j(n,o,true);p()})}}}else{g.push(function(p){o.call(this,n);j(n,o,true);p()})}}});j(h,k)},swap:function(i){i=this._options(i,null,"swapfail",null,null);var h=i.item1;var g=i.item2;if(this.isItem(h)&&this.isItem(g)&&!this.isChildren(h,g)&&!this.isChildren(g,h)&&(h[0]!=g[0])){if(!this._trigger(null,"beforeswap",i)){this._fail(null,i);return}var l=this.prev(h);if(l.length){if(g[0]==l[0]){g.before(h)}else{h.insertAfter(g);g.insertAfter(l)}}else{var k=this.next(h);if(k.length){if(g[0]==k[0]){g.after(h)}else{h.insertAfter(g);g.insertBefore(k)}}else{var j=h.parent();h.insertAfter(g);j.append(g)}}this._updateLevel(h);var j=this.parent(h);this._setFirstLast(j.length?j:null,h);this._updateHidden(h);this._updateLevel(g);j=this.parent(g);this._setFirstLast(j.length?j:null,g);this._updateHidden(g);this._setOddEven(h.add(g));this._trigger(null,"swapped",i);this._success(null,i)}else{this._fail(null,i)}},_updateItemLevel:function(n,h,k){a.addRemoveClass(n[0],"aciTreeLevel"+k,"aciTreeLevel"+h);var g=n[0].firstChild;g.setAttribute("aria-level",k+1);var m=a.childrenByClass(g,"aciTreeEntry");if(h0)&&(m!=n));o.total+=n;o.checked+=m}});var i={total:0,checked:0};g(j,i,k);var h=this.proxy(function(p,o,q){var m=this.parent(p);if(m.length){if(!o){var l=this._checkboxChildren(m);var n=this.checkboxes(l,true).length;var o=(n>0)&&(n!=l.length)}if(this.hasCheckbox(m)){if((q!==f)&&(this._instance.options.checkboxChain!==1)){this._checkboxDOM.check(m,o?true:q)}this._checkboxDOM.tristate(m,o);h(m,o,q)}else{if(this._instance.options.checkboxBreak){h(m)}else{h(m,o,q)}}}});h(j,f,k)},hasCheckbox:function(g){return g&&a.hasClass(g[0],"aciTreeCheckbox")},addCheckbox:function(h,g){g=this._options(g,"checkboxadded","addcheckboxfail","wascheckbox",h);if(this.isItem(h)){if(!this._trigger(h,"beforeaddcheckbox",g)){this._fail(h,g);return}if(this.hasCheckbox(h)){this._notify(h,g)}else{var i=function(){this._checkboxDOM.add(h,{});this._success(h,g)};if(this.extRadio&&this.hasRadio(h)){this.removeRadio(h,this._inner(g,{success:i,fail:g.fail}))}else{i.apply(this)}}}else{this._fail(h,g)}},removeCheckbox:function(h,g){g=this._options(g,"checkboxremoved","removecheckboxfail","notcheckbox",h);if(this.isItem(h)){if(!this._trigger(h,"beforeremovecheckbox",g)){this._fail(h,g);return}if(this.hasCheckbox(h)){this._checkboxDOM.remove(h);this._success(h,g)}else{this._notify(h,g)}}else{this._fail(h,g)}},isChecked:function(g){if(this.hasCheckbox(g)){return a.hasClass(g[0],"aciTreeChecked")}if(this._super){return this._super(g)}return false},check:function(h,g){if(this.extCheckbox&&this.hasCheckbox(h)){g=this._options(g,"checked","checkfail","waschecked",h);if(!this._trigger(h,"beforecheck",g)){this._fail(h,g);return}if(this.isChecked(h)){this._notify(h,g)}else{this._checkboxDOM.check(h,true);if(this._instance.options.checkboxChain!==false){this._checkboxUpdate(h,true)}this._success(h,g)}}else{if(this._super){this._super(h,g)}else{this._trigger(h,"checkfail",g);this._fail(h,g)}}},uncheck:function(h,g){if(this.extCheckbox&&this.hasCheckbox(h)){g=this._options(g,"unchecked","uncheckfail","notchecked",h);if(!this._trigger(h,"beforeuncheck",g)){this._fail(h,g);return}if(this.isChecked(h)){this._checkboxDOM.check(h,false);if(this._instance.options.checkboxChain!==false){this._checkboxUpdate(h,false)}this._success(h,g)}else{this._notify(h,g)}}else{if(this._super){this._super(h,g)}else{this._trigger(h,"uncheckfail",g);this._fail(h,g)}}},checkboxes:function(g,h){if(h!==f){return e(a.withClass(g.toArray(),h?["aciTreeCheckbox","aciTreeChecked"]:"aciTreeCheckbox",h?null:"aciTreeChecked"))}return e(a.withClass(g.toArray(),"aciTreeCheckbox"))},_serialize:function(g,i){var h=this._super(g,i);if(h&&this.extCheckbox()){if(h.hasOwnProperty("checkbox")){h.checkbox=this.hasCheckbox(g);h.checked=this.isChecked(g)}else{if(this.hasCheckbox(g)){if(this.extRadio&&this.extRadio()){h.checkbox=true}h.checked=this.isChecked(g)}}}return h},serialize:function(h,j,k){if(j=="checkbox"){var i="";var g=this.children(h,true,true);this.checkboxes(g,true).each(this.proxy(function(l){var m=e(l);if(k){i+=k.call(this,m,j,this.getId(m))}else{i+=this._instance.options.serialize.call(this,m,j,this.getId(m))}},true));return i}return this._super(h,j,k)},isTristate:function(g){return g&&a.hasClass(g[0],"aciTreeTristate")},tristate:function(g){return e(a.withClass(g.toArray(),"aciTreeTristate"))},extCheckbox:function(){return this._instance.options.checkbox},option:function(g,h){if(this.wasInit()&&!this.isLocked()){if((g=="checkbox")&&(h!=this.extCheckbox())){if(h){this._checkboxInit()}else{this._checkboxDone()}}}this._super(g,h)},_checkboxDone:function(g){this._instance.jQuery.unbind(this._private.nameSpace);this._instance.jQuery.off(this._private.nameSpace,".aciTreeItem");if(!g){this.checkboxes(this.children(null,true,true)).each(this.proxy(function(h){this.removeCheckbox(e(h))},true))}},_destroyHook:function(g){if(g){this._checkboxDone(true)}this._super(g)}};aciPluginClass.plugins.aciTree=aciPluginClass.plugins.aciTree.extend(b,"aciTreeCheckbox");aciPluginClass.defaults("aciTree",c);var a=aciPluginClass.plugins.aciTree_dom})(jQuery,this); + +// radio (works best with selectable) +(function(e,c,f){var b={radio:false,radioChain:true,radioBreak:true,radioClick:false};var d={_radioInit:function(){this._instance.jQuery.bind("acitree"+this._private.nameSpace,function(k,i,j,g,h){switch(g){case"loaded":if(j){i._radioLoad(j)}break}}).bind("keydown"+this._private.nameSpace,this.proxy(function(h){switch(h.which){case 32:if(this.extSelectable&&this.extSelectable()&&!h.ctrlKey){var g=this.focused();if(this.hasRadio(g)&&this.isEnabled(g)){if(!this.isChecked(g)){this.check(g)}h.stopImmediatePropagation();h.preventDefault()}}break}})).on("click"+this._private.nameSpace,".aciTreeItem",this.proxy(function(h){if(!this._instance.options.radioClick||e(h.target).is(".aciTreeCheck")){var g=this.itemFrom(h.target);if(this.hasRadio(g)&&this.isEnabled(g)&&(!this.extSelectable||!this.extSelectable()||(!h.ctrlKey&&!h.shiftKey))){if(!this.isChecked(g)){this.check(g)}h.preventDefault()}}}))},_initHook:function(){if(this.extRadio()){this._radioInit()}this._super()},_itemHook:function(h,i,g,k){if(this.extRadio()){var j=this.extCheckbox&&this.hasCheckbox(i);if(!j&&(g.radio||((g.radio===f)&&(!this.extCheckbox||!this.extCheckbox())))){this._radioDOM.add(i,g)}}this._super(h,i,g,k)},_radioDOM:{add:function(k,g){a.addClass(k[0],g.checked?["aciTreeRadio","aciTreeChecked"]:"aciTreeRadio");var l=a.childrenByClass(k[0].firstChild,"aciTreeText");var j=l.parentNode;var i=c.document.createElement("LABEL");var h=c.document.createElement("SPAN");h.className="aciTreeCheck";i.appendChild(h);i.appendChild(l);j.appendChild(i);k[0].firstChild.setAttribute("aria-checked",!!g.checked)},remove:function(i){a.removeClass(i[0],["aciTreeRadio","aciTreeChecked"]);var j=a.childrenByClass(i[0].firstChild,"aciTreeText");var g=j.parentNode;var h=g.parentNode;h.replaceChild(j,g);i[0].firstChild.removeAttribute("aria-checked")},check:function(g,h){a.toggleListClass(g.toArray(),"aciTreeChecked",h,function(i){i.firstChild.setAttribute("aria-checked",h)})}},_radioLoad:function(g){if(!this._instance.options.radioChain){return}if(this.hasRadio(g)){if(this.isChecked(g)){if(!this.radios(this.children(g,false,true),true).length){this._radioUpdate(g,true)}}else{this._radioUpdate(g)}}},_radioChildren:function(h){if(this._instance.options.radioBreak){var i=[];var j=this.proxy(function(l){var k=this.children(l,false,true);k.each(this.proxy(function(m){var n=e(m);if(this.hasRadio(n)){i.push(m);j(n)}},true))});j(h);return e(i)}else{var g=this.children(h,true,true);return this.radios(g)}},_radioLevel:function(g){var h=[];g.each(this.proxy(function(j){var k=e(j);var i=this.children(k,false,true);i.each(this.proxy(function(l){var m=e(l);if(!this._instance.options.radioBreak||this.hasRadio(m)){h.push(l)}},true))},true));return e(h)},_radioUpdate:function(i,j){var k=this.proxy(function(l){var m=this.siblings(l,true);this._radioDOM.check(this.radios(m),false);m.each(this.proxy(function(n){var o=e(n);if(!this._instance.options.radioBreak||this.hasRadio(o)){this._radioDOM.check(this._radioChildren(o),false)}},true))});if(j){k(i)}var g=this.proxy(function(n){var l=this._radioLevel(n);var o=this.radios(l);if(o.length){var m=this.radios(l,true);if(m.length){m=m.first();this._radioDOM.check(m,true);k(m);g(m)}else{m=o.first();this._radioDOM.check(m,true);k(m);g(m)}}else{if(l.length){g(l)}}});if(j){g(i)}else{this._radioDOM.check(this._radioChildren(i),false)}var h=this.proxy(function(m){var l=this.parent(m);if(l.length){if(this.hasRadio(l)){if(j){k(l)}this._radioDOM.check(l,j);h(l)}else{if(!this._instance.options.radioBreak){if(j){k(l)}h(l)}}}});if(j!==f){h(i)}},hasRadio:function(g){return g&&a.hasClass(g[0],"aciTreeRadio")},addRadio:function(h,g){g=this._options(g,"radioadded","addradiofail","wasradio",h);if(this.isItem(h)){if(!this._trigger(h,"beforeaddradio",g)){this._fail(h,g);return}if(this.hasRadio(h)){this._notify(h,g)}else{var i=function(){this._radioDOM.add(h,{});this._success(h,g)};if(this.extCheckbox&&this.hasCheckbox(h)){this.removeCheckbox(h,this._inner(g,{success:i,fail:g.fail}))}else{i.apply(this)}}}else{this._fail(h,g)}},removeRadio:function(h,g){g=this._options(g,"radioremoved","removeradiofail","notradio",h);if(this.isItem(h)){if(!this._trigger(h,"beforeremoveradio",g)){this._fail(h,g);return}if(this.hasRadio(h)){this._radioDOM.remove(h);this._success(h,g)}else{this._notify(h,g)}}else{this._fail(h,g)}},isChecked:function(g){if(this.hasRadio(g)){return a.hasClass(g[0],"aciTreeChecked")}if(this._super){return this._super(g)}return false},check:function(h,g){if(this.extRadio&&this.hasRadio(h)){g=this._options(g,"checked","checkfail","waschecked",h);if(!this._trigger(h,"beforecheck",g)){this._fail(h,g);return}if(this.isChecked(h)){this._notify(h,g)}else{this._radioDOM.check(h,true);if(this._instance.options.radioChain){this._radioUpdate(h,true)}this._success(h,g)}}else{if(this._super){this._super(h,g)}else{this._trigger(h,"checkfail",g);this._fail(h,g)}}},uncheck:function(h,g){if(this.extRadio&&this.hasRadio(h)){g=this._options(g,"unchecked","uncheckfail","notchecked",h);if(!this._trigger(h,"beforeuncheck",g)){this._fail(h,g);return}if(this.isChecked(h)){this._radioDOM.check(h,false);if(this._instance.options.radioChain){this._radioUpdate(h,false)}this._success(h,g)}else{this._notify(h,g)}}else{if(this._super){this._super(h,g)}else{this._trigger(h,"uncheckfail",g);this._fail(h,g)}}},radios:function(g,h){if(h!==f){return e(a.withClass(g.toArray(),h?["aciTreeRadio","aciTreeChecked"]:"aciTreeRadio",h?null:"aciTreeChecked"))}return e(a.withClass(g.toArray(),"aciTreeRadio"))},_serialize:function(g,i){var h=this._super(g,i);if(h&&this.extRadio()){if(h.hasOwnProperty("radio")){h.radio=this.hasRadio(g);h.checked=this.isChecked(g)}else{if(this.hasRadio(g)){if(this.extCheckbox&&this.extCheckbox()){h.radio=true}h.checked=this.isChecked(g)}}}return h},serialize:function(h,j,k){if(j=="radio"){var i="";var g=this.children(h,true,true);this.radios(g,true).each(this.proxy(function(l){var m=e(l);if(k){i+=k.call(this,m,j,this.getId(m))}else{i+=this._instance.options.serialize.call(this,m,j,this.getId(m))}},true));return i}return this._super(h,j,k)},extRadio:function(){return this._instance.options.radio},option:function(g,h){if(this.wasInit()&&!this.isLocked()){if((g=="radio")&&(h!=this.extRadio())){if(h){this._radioInit()}else{this._radioDone()}}}this._super(g,h)},_radioDone:function(g){this._instance.jQuery.unbind(this._private.nameSpace);this._instance.jQuery.off(this._private.nameSpace,".aciTreeItem");if(!g){this.radios(this.children(null,true,true)).each(this.proxy(function(h){this.removeRadio(e(h))},true))}},_destroyHook:function(g){if(g){this._radioDone(true)}this._super(g)}};aciPluginClass.plugins.aciTree=aciPluginClass.plugins.aciTree.extend(d,"aciTreeRadio");aciPluginClass.defaults("aciTree",b);var a=aciPluginClass.plugins.aciTree_dom})(jQuery,this); + +// column +(function(e,c,f){var b={columnData:[]};var d={__extend:function(){e.extend(this._private,{propsIndex:{}});this._super()},_initHook:function(){if(this._instance.options.columnData.length){var j=false,h;for(var g in this._instance.options.columnData){h=this._instance.options.columnData[g];if(h.width!==f){this._updateCss(".aciTree.aciTree"+this._instance.index+" .aciTreeColumn"+g,"width:"+h.width+"px;");j=true}this._private.propsIndex[h.props]=g}if(j){this._updateWidth()}}this._super()},_getCss:function(m,p,o){var h="_getCss_"+c.String(m).replace(/[^a-z0-9_-]/ig,"_");var l=e("body").find("#"+h);if(!l.length){if(m instanceof Array){var g="",j="";for(var k in m){g+='
    ';j+="
    "}g+=j}else{var g='
    '}e("body").append('
    '+g+"
    ");l=e("body").find("#"+h)}var n=l.find("*:last").css(p);if(o){n=parseInt(n);if(isNaN(n)){n=null}}return n},_updateCss:function(i,g){var k="_updateCss_"+c.String(i).replace(">","_gt_").replace(/[^a-z0-9_-]/ig,"_");var h='";var j=e("body").find("#"+k);if(j.length){j.replaceWith(h)}else{e("body").prepend(h)}},getWidth:function(g){if((g>=0)&&(g=0)&&(g=0)&&(g=0)&&(h=0)&&(g.index=0)&&(gthis._instance.options.editDelay)&&(i');g.find("label").attr("for","aciTree-editable-tree-item");this._editableDOM.get(h).val(this.getLabel(h))},remove:function(i,h){var g=i.removeClass("aciTreeEdited").children(".aciTreeLine");g.find(".aciTreeText").html(this.getLabel(i));g.find("label").removeAttr("for")},get:function(g){return g?g.children(".aciTreeLine").find("input[type=text]"):d([])}},edited:function(){return this._instance.jQuery.find(".aciTreeEdited")},isEdited:function(g){return g&&a.hasClass(g[0],"aciTreeEdited")},_focusEdit:function(h){var i=this._editableDOM.get(h).focus().trigger("click")[0];if(i){if(typeof i.selectionStart=="number"){i.selectionStart=i.selectionEnd=i.value.length}else{if(i.createTextRange!==f){var g=i.createTextRange();g.collapse(false);g.select()}}}},setLabel:function(h,g){if(!this.extEditable()||!this.isEdited(h)){this._super(h,g)}},edit:function(h,g){g=this._options(g,"edit","editfail","wasedit",h);if(this.extEditable()&&this.isItem(h)){if(!this._trigger(h,"beforeedit",g)){this._fail(h,g);return}var i=this.edited();if(i.length){if(i[0]==h[0]){this._notify(h,g);return}else{this._editableDOM.remove.call(this,i);this._trigger(i,"endedit",g)}}this._editableDOM.add.call(this,h);this._focusEdit(h);this._success(h,g)}else{this._fail(h,g)}},endEdit:function(g){var h=this.edited();g=this._options(g,"edited","endeditfail","endedit",h);if(this.extEditable()&&this.isItem(h)){if(!this._trigger(h,"beforeendedit",g)){this._fail(h,g);return}var i=this._editableDOM.get(h).val();this._editableDOM.remove.call(this,h);if((g.save===f)||g.save){this.setLabel(h,{label:i});this._success(h,g)}else{this._notify(h,g)}}else{this._fail(h,g)}},extEditable:function(){return this._instance.options.editable},option:function(g,h){if(this.wasInit()&&!this.isLocked()){if((g=="editable")&&(h!=this.extEditable())){if(h){this._editableInit()}else{this._editableDone()}}}this._super(g,h)},_editableDone:function(){this._instance.jQuery.unbind(this._private.nameSpace);this._instance.jQuery.off(this._private.nameSpace,".aciTreeItem");this._instance.jQuery.off(this._private.nameSpace,"input[type=text]");var g=this.edited();if(g.length){this.endEdit()}},_destroyHook:function(g){if(g){this._editableDone()}this._super(g)}};aciPluginClass.plugins.aciTree=aciPluginClass.plugins.aciTree.extend(e,"aciTreeEditable");aciPluginClass.defaults("aciTree",b);var a=aciPluginClass.plugins.aciTree_dom})(jQuery,this); + +// persist (require utils extension & jStorage plugin) +(function(c,b,e){var a={persist:null};var d={__extend:function(){c.extend(this._private,{selectTimeout:null,focusTimeout:null,openTimeout:null});this._super()},_initPersist:function(){this._instance.jQuery.bind("acitree"+this._private.nameSpace,function(j,h,i,f,g){if(g.uid=="ui.persist"){return}switch(f){case"init":h._persistRestore();break;case"selected":case"deselected":h._persistLater("selected");break;case"focus":case"blur":h._persistLater("focused");break;case"opened":case"closed":h._persistLater("opened");break}})},_initHook:function(){if(this.extPersist()){this._initPersist()}this._super()},_persistLater:function(f){switch(f){case"selected":b.clearTimeout(this._private.selectTimeout);this._private.selectTimeout=b.setTimeout(this.proxy(function(){this._persistSelected()}),250);break;case"focused":b.clearTimeout(this._private.focusTimeout);this._private.focusTimeout=b.setTimeout(this.proxy(function(){this._persistFocused()}),250);break;case"opened":b.clearTimeout(this._private.openTimeout);this._private.openTimeout=b.setTimeout(this.proxy(function(){this._persistOpened()}),250);break}},_persistRestore:function(){var f=new this._queue(this,this._instance.options.queue);var g=new this._task(f,function(k){if(this.extSelectable&&this.extSelectable()){var m=c.jStorage.get("aciTree_"+this._instance.options.persist+"_selected");if(m instanceof Array){for(var l in m){(function(i){f.push(function(o){this.searchPath(null,{success:function(p){this.select(p,{uid:"ui.persist",success:function(){o()},fail:o,focus:false})},fail:o,path:i.split(";")})})})(m[l]);if(!this._instance.options.multiSelectable){break}}}var n=c.jStorage.get("aciTree_"+this._instance.options.persist+"_focused");if(n instanceof Array){for(var l in n){(function(i){f.push(function(o){this.searchPath(null,{success:function(p){this.focus(p,{uid:"ui.persist",success:function(q){this.setVisible(q,{center:true});o()},fail:o})},fail:o,path:i.split(";")})})})(n[l])}}}k()});var j=c.jStorage.get("aciTree_"+this._instance.options.persist+"_opened");if(j instanceof Array){for(var h in j){(function(i){g.push(function(k){this.searchPath(null,{success:function(l){this.open(l,{uid:"ui.persist",success:k,fail:k})},fail:k,path:i.split(";"),load:true})})})(j[h])}}},_persistSelected:function(){if(this.extSelectable&&this.extSelectable()){var f=[];this.selected().each(this.proxy(function(g){var h=c(g);var i=this.pathId(h);i.push(this.getId(h));f.push(i.join(";"))},true));c.jStorage.set("aciTree_"+this._instance.options.persist+"_selected",f)}},_persistFocused:function(){if(this.extSelectable&&this.extSelectable()){var f=[];this.focused().each(this.proxy(function(g){var h=c(g);var i=this.pathId(h);i.push(this.getId(h));f.push(i.join(";"))},true));c.jStorage.set("aciTree_"+this._instance.options.persist+"_focused",f)}},_persistOpened:function(){var f=[];this.inodes(this.children(null,true),true).each(this.proxy(function(g){var h=c(g);if(this.isOpenPath(h)){var i=this.pathId(h);i.push(this.getId(h));f.push(i.join(";"))}},true));c.jStorage.set("aciTree_"+this._instance.options.persist+"_opened",f)},isPersist:function(){if(this.extPersist()){var f=c.jStorage.get("aciTree_"+this._instance.options.persist+"_selected");if(f instanceof Array){return true}var g=c.jStorage.get("aciTree_"+this._instance.options.persist+"_focused");if(g instanceof Array){return true}var h=c.jStorage.get("aciTree_"+this._instance.options.persist+"_opened");if(h instanceof Array){return true}}return false},unpersist:function(){if(this.extPersist()){c.jStorage.deleteKey("aciTree_"+this._instance.options.persist+"_selected");c.jStorage.deleteKey("aciTree_"+this._instance.options.persist+"_focused");c.jStorage.deleteKey("aciTree_"+this._instance.options.persist+"_opened")}},extPersist:function(){return this._instance.options.persist},option:function(f,h){var g=this.extPersist();this._super(f,h);if(this.extPersist()!=g){if(g){this._donePersist()}else{this._initPersist()}}},_donePersist:function(){this._instance.jQuery.unbind(this._private.nameSpace)},_destroyHook:function(f){if(f){this._donePersist()}this._super(f)}};aciPluginClass.plugins.aciTree=aciPluginClass.plugins.aciTree.extend(d,"aciTreePersist");aciPluginClass.defaults("aciTree",a)})(jQuery,this); + +// hash (require utils extension & aciFragment plugin) +(function(d,c,e){var a={selectHash:null,openHash:null};var b={__extend:function(){d.extend(this._private,{lastSelect:null,lastOpen:null,hashApi:null});this._super()},_hashInit:function(){this._instance.jQuery.aciFragment();this._private.hashApi=this._instance.jQuery.aciFragment("api");this._instance.jQuery.bind("acitree"+this._private.nameSpace,function(j,h,i,f,g){switch(f){case"init":h._hashRestore();break}}).bind("acifragment"+this._private.nameSpace,this.proxy(function(h,g,f){h.stopPropagation();this._hashRestore()}))},_initHook:function(){if(this.extHast()){this._hashInit()}this._super()},_hashRestore:function(){var f=this._instance.queue;var i=function(l){for(var k in l){(function(m){f.push(function(n){this.search(null,{success:function(o){this.open(o,{uid:"ui.hash",success:n,fail:n})},fail:n,search:m})})})(l[k])}};if(this._instance.options.openHash){var h=this._private.hashApi.get(this._instance.options.openHash,"");if(h.length&&(h!=this._private.lastOpen)){this._private.lastOpen=h;var j=h.split(";");i(j)}}if(this._instance.options.selectHash&&this.extSelectable&&this.extSelectable()){var h=this._private.hashApi.get(this._instance.options.selectHash,"");if(h.length&&(h!=this._private.lastSelect)){this._private.lastSelect=h;var j=h.split(";");var g=j.pop();i(j);if(g){f.push(function(k){this.search(null,{success:function(l){this.select(l,{uid:"ui.hash",success:function(m){this.setVisible(m,{center:true});k()},fail:k})},fail:k,search:g})})}}}},extHast:function(){return this._instance.options.selectHash||this._instance.options.openHash},option:function(f,g){var h=this.extHast();this._super(f,g);if(this.extHast()!=h){if(h){this._hashDone()}else{this._hashInit()}}},_hashDone:function(){this._instance.jQuery.unbind(this._private.nameSpace);this._private.hashApi=null;this._instance.jQuery.aciFragment("destroy")},_destroyHook:function(f){if(f){this._hashDone()}this._super(f)}};aciPluginClass.plugins.aciTree=aciPluginClass.plugins.aciTree.extend(b,"aciTreeHash");aciPluginClass.defaults("aciTree",a)})(jQuery,this); + +// sortable (require utils extension & aciSortable plugin) +(function(d,c,e){var a={sortable:false,sortDelay:750,sortDrag:function(h,j,i,g){if(!i){var f=this.getLabel(h);if(this._private.dragDrop&&(this._private.dragDrop.length>1)){f+=" and #"+(this._private.dragDrop.length-1)+" more"}g.html(f)}},sortValid:function(j,h,k,g,l,i){var f=this.getLabel(j);if(this._private.dragDrop.length>1){f+=" and #"+(this._private.dragDrop.length-1)+" more"}if(g){i.html("move "+f+" to "+this.getLabel(this.itemFrom(h)));l.removeClass("aciTreeAfter aciTreeBefore")}else{if(k!==null){if(k){i.html("move "+f+" before "+this.getLabel(h));l.removeClass("aciTreeAfter").addClass("aciTreeBefore")}else{i.html("move "+f+" after "+this.getLabel(h));l.removeClass("aciTreeBefore").addClass("aciTreeAfter")}}}}};var b={__extend:function(){d.extend(this._private,{openTimeout:null,dragDrop:null});this._super()},_sortableInit:function(){this._instance.jQuery.aciSortable({container:".aciTreeUl",item:".aciTreeLi",child:50,childHolder:'
      ',childHolderSelector:".aciTreeChild",placeholder:'
    • ',placeholderSelector:".aciTreePlaceholder",helper:'
      ',helperSelector:".aciTreeHelper",before:this.proxy(function(f){if(!this._initDrag(f)){return false}if(!this._trigger(f,"beforedrag")){this._trigger(f,"dragfail");return false}return true}),start:this.proxy(function(g,h,f){this._instance.jQuery.addClass("aciTreeDragDrop");f.css({opacity:1}).html(this.getLabel(g))}),drag:this.proxy(function(g,i,h,f){if(!h){c.clearTimeout(this._private.openTimeout)}if(this._instance.options.sortDrag){this._instance.options.sortDrag.apply(this,arguments)}}),valid:this.proxy(function(j,h,k,g,l,i){c.clearTimeout(this._private.openTimeout);if(!this._checkDrop(j,h,k,g,l,i)){return false}var f=this._options({hover:h,before:k,isContainer:g,placeholder:l,helper:i});if(!this._trigger(j,"checkdrop",f)){return false}if(this.isInode(h)&&!this.isOpen(h)){this._private.openTimeout=c.setTimeout(this.proxy(function(){this.open(h)}),this._instance.options.sortDelay)}if(this._instance.options.sortValid){this._instance.options.sortValid.apply(this,arguments)}return true}),create:this.proxy(function(g,h,f){if(this.isLeaf(f)){f.append(g._instance.options.childHolder);return true}return false},true),end:this.proxy(function(q,k,p,g){c.clearTimeout(this._private.openTimeout);var r={placeholder:p,helper:g};r=this._options(r,"sorted","dropfail",null,q);if(p.parent().length){var i=this.prev(p,true);if(i.length){p.detach();var l=d(this._private.dragDrop.get().reverse());this._private.dragDrop=null;l.each(this.proxy(function(s){this.moveAfter(d(s),this._inner(r,{success:r.success,fail:r.fail,after:i}))},true))}else{var j=this.next(p,true);if(j.length){p.detach();var l=d(this._private.dragDrop.get().reverse());this._private.dragDrop=null;l.each(this.proxy(function(s){this.moveBefore(d(s),this._inner(r,{success:r.success,fail:r.fail,before:j}))},true))}else{var o=this.parent(p);var f=p.parent();p.detach();f.remove();if(this.isLeaf(o)){var l=this._private.dragDrop;this.asChild(l.eq(0),this._inner(r,{success:function(){this._success(q,r);this.open(o);l.filter(":gt(0)").each(this.proxy(function(s){this.moveAfter(d(s),this._inner(r,{success:r.success,fail:r.fail,after:this.last(o)}))},true))},fail:r.fail,parent:o}))}else{this._fail(q,r)}}}}else{this._fail(q,r)}this._private.dragDrop=null;if(g.parent().length){var n=d(c).scrollTop();var h=d(c).scrollLeft();var m=q[0].getBoundingClientRect();g.animate({top:m.top+n,left:m.left+h,opacity:0},{complete:function(){g.detach()}})}this._instance.jQuery.removeClass("aciTreeDragDrop")})})},_initHook:function(){if(this.extSortable()){this._sortableInit()}this._super()},_parents:function(l){var h=l.length,k,g,f=[];for(var n=0;n= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * This extension adds save/restore support for item states (open/selected) using local storage. + * The states are saved on item select/open and restored on treeview init. + * Require jStorage https://github.com/andris9/jStorage and the utils extension for finding items by ID. + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + persist: null // the storage key name to keep the states (should be unique/treeview) + }; + + // aciTree persist extension + // save/restore item state in/from local storage + + var aciTree_persist = { + __extend: function() { + $.extend(this._private, { + // timeouts for the save operation + selectTimeout: null, + focusTimeout: null, + openTimeout: null + }); + // call the parent + this._super(); + }, + // init persist + _initPersist: function() { + this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) { + if (options.uid == 'ui.persist') { + // skip processing itself + return; + } + switch (eventName) { + case 'init': + api._persistRestore(); + break; + case 'selected': + case 'deselected': + // support `selectable` extension + api._persistLater('selected'); + break; + case 'focus': + case 'blur': + // support `selectable` extension + api._persistLater('focused'); + break; + case 'opened': + case 'closed': + api._persistLater('opened'); + break; + } + }); + }, + // override `_initHook` + _initHook: function() { + if (this.extPersist()) { + this._initPersist(); + } + // call the parent + this._super(); + }, + // persist states + _persistLater: function(type) { + switch (type) { + case 'selected': + window.clearTimeout(this._private.selectTimeout); + this._private.selectTimeout = window.setTimeout(this.proxy(function() { + this._persistSelected(); + }), 250); + break; + case 'focused': + window.clearTimeout(this._private.focusTimeout); + this._private.focusTimeout = window.setTimeout(this.proxy(function() { + this._persistFocused(); + }), 250); + break; + case 'opened': + window.clearTimeout(this._private.openTimeout); + this._private.openTimeout = window.setTimeout(this.proxy(function() { + this._persistOpened(); + }), 250); + break; + } + }, + // restore item states + _persistRestore: function() { + var queue = new this._queue(this, this._instance.options.queue); + var task = new this._task(queue, function(complete) { + // support `selectable` extension + if (this.extSelectable && this.extSelectable()) { + var selected = $.jStorage.get('aciTree_' + this._instance.options.persist + '_selected'); + if (selected instanceof Array) { + // select all saved items + for (var i in selected) { + (function(path) { + queue.push(function(complete) { + this.searchPath(null, { + success: function(item) { + this.select(item, { + uid: 'ui.persist', + success: function() { + complete(); + }, + fail: complete, + focus: false + }); + }, + fail: complete, + path: path.split(';') + }); + }); + })(selected[i]); + if (!this._instance.options.multiSelectable) { + break; + } + } + } + var focused = $.jStorage.get('aciTree_' + this._instance.options.persist + '_focused'); + if (focused instanceof Array) { + // focus all saved items + for (var i in focused) { + (function(path) { + queue.push(function(complete) { + this.searchPath(null, { + success: function(item) { + this.focus(item, { + uid: 'ui.persist', + success: function(item) { + this.setVisible(item, { + center: true + }); + complete(); + }, + fail: complete + }); + }, + fail: complete, + path: path.split(';') + }); + }); + })(focused[i]); + } + } + } + complete(); + }); + var opened = $.jStorage.get('aciTree_' + this._instance.options.persist + '_opened'); + if (opened instanceof Array) { + // open all saved items + for (var i in opened) { + (function(path) { + // add item to queue + task.push(function(complete) { + this.searchPath(null, { + success: function(item) { + this.open(item, { + uid: 'ui.persist', + success: complete, + fail: complete + }); + }, + fail: complete, + path: path.split(';'), + load: true + }); + }); + })(opened[i]); + } + } + }, + // persist selected items + _persistSelected: function() { + // support `selectable` extension + if (this.extSelectable && this.extSelectable()) { + var selected = []; + this.selected().each(this.proxy(function(element) { + var item = $(element); + var path = this.pathId(item); + path.push(this.getId(item)); + selected.push(path.join(';')); + }, true)); + $.jStorage.set('aciTree_' + this._instance.options.persist + '_selected', selected); + } + }, + // persist focused item + _persistFocused: function() { + // support `selectable` extension + if (this.extSelectable && this.extSelectable()) { + var focused = []; + this.focused().each(this.proxy(function(element) { + var item = $(element); + var path = this.pathId(item); + path.push(this.getId(item)); + focused.push(path.join(';')); + }, true)); + $.jStorage.set('aciTree_' + this._instance.options.persist + '_focused', focused); + } + }, + // persist opened items + _persistOpened: function() { + var opened = []; + this.inodes(this.children(null, true), true).each(this.proxy(function(element) { + var item = $(element); + if (this.isOpenPath(item)) { + var path = this.pathId(item); + path.push(this.getId(item)); + opened.push(path.join(';')); + } + }, true)); + $.jStorage.set('aciTree_' + this._instance.options.persist + '_opened', opened); + }, + // test if there is any saved data + isPersist: function() { + if (this.extPersist()) { + var selected = $.jStorage.get('aciTree_' + this._instance.options.persist + '_selected'); + if (selected instanceof Array) { + return true; + } + var focused = $.jStorage.get('aciTree_' + this._instance.options.persist + '_focused'); + if (focused instanceof Array) { + return true; + } + var opened = $.jStorage.get('aciTree_' + this._instance.options.persist + '_opened'); + if (opened instanceof Array) { + return true; + } + } + return false; + }, + // remove any saved states + unpersist: function() { + if (this.extPersist()) { + $.jStorage.deleteKey('aciTree_' + this._instance.options.persist + '_selected'); + $.jStorage.deleteKey('aciTree_' + this._instance.options.persist + '_focused'); + $.jStorage.deleteKey('aciTree_' + this._instance.options.persist + '_opened'); + } + }, + // test if persist is enabled + extPersist: function() { + return this._instance.options.persist; + }, + // override set `option` + option: function(option, value) { + var persist = this.extPersist(); + // call the parent + this._super(option, value); + if (this.extPersist() != persist) { + if (persist) { + this._donePersist(); + } else { + this._initPersist(); + } + } + }, + // done persist + _donePersist: function() { + this._instance.jQuery.unbind(this._private.nameSpace); + }, + // override `_destroyHook` + _destroyHook: function(unloaded) { + if (unloaded) { + this._donePersist(); + } + // call the parent + this._super(unloaded); + } + }; + + // extend the base aciTree class and add the persist stuff + aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_persist, 'aciTreePersist'); + + // add extra default options + aciPluginClass.defaults('aciTree', options); + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.radio.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.radio.js new file mode 100755 index 000000000..03aa30396 --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.radio.js @@ -0,0 +1,471 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * This extension adds radio-button support to aciTree, + * should be used with the selectable extension. + * + * The are a few extra properties for the item data: + * + * { + * ... + * radio: true, // TRUE (default) means the item will have a radio button (can be omitted if the `checkbox` extension is not used) + * checked: false, // if should be checked or not + * ... + * } + * + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + radio: false, // if TRUE then each item will have a radio button + radioChain: true, // if TRUE the selection will propagate to the parents/children + radioBreak: true, // if TRUE then a missing radio button will break the chaining + radioClick: false // if TRUE then a click will trigger a state change only when made over the radio-button itself + }; + + // aciTree radio extension + + var aciTree_radio = { + // init radio + _radioInit: function() { + this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) { + switch (eventName) { + case 'loaded': + if (item) { + // check/update on item load + api._radioLoad(item); + } + break; + } + }).bind('keydown' + this._private.nameSpace, this.proxy(function(e) { + switch (e.which) { + case 32: // space + // support `selectable` extension + if (this.extSelectable && this.extSelectable() && !e.ctrlKey) { + var item = this.focused(); + if (this.hasRadio(item) && this.isEnabled(item)) { + if (!this.isChecked(item)) { + this.check(item); + } + e.stopImmediatePropagation(); + // prevent page scroll + e.preventDefault(); + } + } + break; + } + })).on('click' + this._private.nameSpace, '.aciTreeItem', this.proxy(function(e) { + if (!this._instance.options.radioClick || $(e.target).is('.aciTreeCheck')) { + var item = this.itemFrom(e.target); + if (this.hasRadio(item) && this.isEnabled(item) && (!this.extSelectable || !this.extSelectable() || (!e.ctrlKey && !e.shiftKey))) { + // change state on click + if (!this.isChecked(item)) { + this.check(item); + } + e.preventDefault(); + } + } + })); + }, + // override `_initHook` + _initHook: function() { + if (this.extRadio()) { + this._radioInit(); + } + // call the parent + this._super(); + }, + // override `_itemHook` + _itemHook: function(parent, item, itemData, level) { + if (this.extRadio()) { + // support `checkbox` extension + var checkbox = this.extCheckbox && this.hasCheckbox(item); + if (!checkbox && (itemData.radio || ((itemData.radio === undefined) && (!this.extCheckbox || !this.extCheckbox())))) { + this._radioDOM.add(item, itemData); + } + } + // call the parent + this._super(parent, item, itemData, level); + }, + // low level DOM functions + _radioDOM: { + // add item radio + add: function(item, itemData) { + domApi.addClass(item[0], itemData.checked ? ['aciTreeRadio', 'aciTreeChecked'] : 'aciTreeRadio'); + var text = domApi.childrenByClass(item[0].firstChild, 'aciTreeText'); + var parent = text.parentNode; + var label = window.document.createElement('LABEL'); + var check = window.document.createElement('SPAN'); + check.className = 'aciTreeCheck'; + label.appendChild(check); + label.appendChild(text); + parent.appendChild(label); + item[0].firstChild.setAttribute('aria-checked', !!itemData.checked); + }, + // remove item radio + remove: function(item) { + domApi.removeClass(item[0], ['aciTreeRadio', 'aciTreeChecked']); + var text = domApi.childrenByClass(item[0].firstChild, 'aciTreeText'); + var label = text.parentNode; + var parent = label.parentNode; + parent.replaceChild(text, label) + item[0].firstChild.removeAttribute('aria-checked'); + }, + // (un)check items + check: function(items, state) { + domApi.toggleListClass(items.toArray(), 'aciTreeChecked', state, function(node) { + node.firstChild.setAttribute('aria-checked', state); + }); + } + }, + // update item on load + _radioLoad: function(item) { + if (!this._instance.options.radioChain) { + // do not update on load + return; + } + if (this.hasRadio(item)) { + if (this.isChecked(item)) { + if (!this.radios(this.children(item, false, true), true).length) { + // the item is checked but no children are, check the children + this._radioUpdate(item, true); + } + } else { + // the item is not checked, uncheck children + this._radioUpdate(item); + } + } + }, + // get children list + _radioChildren: function(item) { + if (this._instance.options.radioBreak) { + var list = []; + var process = this.proxy(function(item) { + var children = this.children(item, false, true); + children.each(this.proxy(function(element) { + var item = $(element); + // break on missing radio + if (this.hasRadio(item)) { + list.push(element); + process(item); + } + }, true)); + }); + process(item); + return $(list); + } else { + var children = this.children(item, true, true); + return this.radios(children); + } + }, + // get children across items + _radioLevel: function(items) { + var list = []; + items.each(this.proxy(function(element) { + var item = $(element); + var children = this.children(item, false, true); + children.each(this.proxy(function(element) { + var item = $(element); + if (!this._instance.options.radioBreak || this.hasRadio(item)) { + list.push(element); + } + }, true)); + }, true)); + return $(list); + }, + // update radio state + _radioUpdate: function(item, state) { + // update siblings + var siblings = this.proxy(function(item) { + var siblings = this.siblings(item, true); + this._radioDOM.check(this.radios(siblings), false); + siblings.each(this.proxy(function(element) { + var item = $(element); + if (!this._instance.options.radioBreak || this.hasRadio(item)) { + this._radioDOM.check(this._radioChildren(item), false); + } + }, true)); + }); + if (state) { + siblings(item); + } + // update children + var checkDown = this.proxy(function(item) { + var children = this._radioLevel(item); + var radios = this.radios(children); + if (radios.length) { + var checked = this.radios(children, true); + if (checked.length) { + checked = checked.first(); + this._radioDOM.check(checked, true); + siblings(checked); + checkDown(checked); + } else { + checked = radios.first(); + this._radioDOM.check(checked, true); + siblings(checked); + checkDown(checked); + } + } else if (children.length) { + checkDown(children); + } + }); + if (state) { + checkDown(item); + } else { + this._radioDOM.check(this._radioChildren(item), false); + } + // update parents + var checkUp = this.proxy(function(item) { + var parent = this.parent(item); + if (parent.length) { + if (this.hasRadio(parent)) { + if (state) { + siblings(parent); + } + this._radioDOM.check(parent, state); + checkUp(parent); + } else { + if (!this._instance.options.radioBreak) { + if (state) { + siblings(parent); + } + checkUp(parent); + } + } + } + }); + if (state !== undefined) { + checkUp(item); + } + }, + // test if item have a radio + hasRadio: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeRadio'); + }, + // add radio button + addRadio: function(item, options) { + options = this._options(options, 'radioadded', 'addradiofail', 'wasradio', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeaddradio', options)) { + this._fail(item, options); + return; + } + if (this.hasRadio(item)) { + this._notify(item, options); + } else { + var process = function() { + this._radioDOM.add(item, { + }); + this._success(item, options); + }; + // support `checkbox` extension + if (this.extCheckbox && this.hasCheckbox(item)) { + // remove checkbox first + this.removeCheckbox(item, this._inner(options, { + success: process, + fail: options.fail + })); + } else { + process.apply(this); + } + } + } else { + this._fail(item, options); + } + }, + // remove radio button + removeRadio: function(item, options) { + options = this._options(options, 'radioremoved', 'removeradiofail', 'notradio', item); + if (this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeremoveradio', options)) { + this._fail(item, options); + return; + } + if (this.hasRadio(item)) { + this._radioDOM.remove(item); + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // test if it's checked + isChecked: function(item) { + if (this.hasRadio(item)) { + return domApi.hasClass(item[0], 'aciTreeChecked'); + } + // support `checkbox` extension + if (this._super) { + // call the parent + return this._super(item); + } + return false; + }, + // check radio button + check: function(item, options) { + if (this.extRadio && this.hasRadio(item)) { + options = this._options(options, 'checked', 'checkfail', 'waschecked', item); + // a way to cancel the operation + if (!this._trigger(item, 'beforecheck', options)) { + this._fail(item, options); + return; + } + if (this.isChecked(item)) { + this._notify(item, options); + } else { + this._radioDOM.check(item, true); + if (this._instance.options.radioChain) { + // chain them + this._radioUpdate(item, true); + } + this._success(item, options); + } + } else { + // support `checkbox` extension + if (this._super) { + // call the parent + this._super(item, options); + } else { + this._trigger(item, 'checkfail', options); + this._fail(item, options); + } + } + }, + // uncheck radio button + uncheck: function(item, options) { + if (this.extRadio && this.hasRadio(item)) { + options = this._options(options, 'unchecked', 'uncheckfail', 'notchecked', item); + // a way to cancel the operation + if (!this._trigger(item, 'beforeuncheck', options)) { + this._fail(item, options); + return; + } + if (this.isChecked(item)) { + this._radioDOM.check(item, false); + if (this._instance.options.radioChain) { + // chain them + this._radioUpdate(item, false); + } + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + // support `checkbox` extension + if (this._super) { + // call the parent + this._super(item, options); + } else { + this._trigger(item, 'uncheckfail', options); + this._fail(item, options); + } + } + }, + // filter items with radio by state (if set) + radios: function(items, state) { + if (state !== undefined) { + return $(domApi.withClass(items.toArray(), state ? ['aciTreeRadio', 'aciTreeChecked'] : 'aciTreeRadio', state ? null : 'aciTreeChecked')); + } + return $(domApi.withClass(items.toArray(), 'aciTreeRadio')); + }, + // override `_serialize` + _serialize: function(item, callback) { + var data = this._super(item, callback); + if (data && this.extRadio()) { + if (data.hasOwnProperty('radio')) { + data.radio = this.hasRadio(item); + data.checked = this.isChecked(item); + } else if (this.hasRadio(item)) { + if (this.extCheckbox && this.extCheckbox()) { + data.radio = true; + } + data.checked = this.isChecked(item); + } + } + return data; + }, + // override `serialize` + serialize: function(item, what, callback) { + if (what == 'radio') { + var serialized = ''; + var children = this.children(item, true, true); + this.radios(children, true).each(this.proxy(function(element) { + var item = $(element); + if (callback) { + serialized += callback.call(this, item, what, this.getId(item)); + } else { + serialized += this._instance.options.serialize.call(this, item, what, this.getId(item)); + } + }, true)); + return serialized; + } + return this._super(item, what, callback); + }, + // test if radio is enabled + extRadio: function() { + return this._instance.options.radio; + }, + // override set `option` + option: function(option, value) { + if (this.wasInit() && !this.isLocked()) { + if ((option == 'radio') && (value != this.extRadio())) { + if (value) { + this._radioInit(); + } else { + this._radioDone(); + } + } + } + // call the parent + this._super(option, value); + }, + // done radio + _radioDone: function(destroy) { + this._instance.jQuery.unbind(this._private.nameSpace); + this._instance.jQuery.off(this._private.nameSpace, '.aciTreeItem'); + if (!destroy) { + // remove radios + this.radios(this.children(null, true, true)).each(this.proxy(function(element) { + this.removeRadio($(element)); + }, true)); + } + }, + // override `_destroyHook` + _destroyHook: function(unloaded) { + if (unloaded) { + this._radioDone(true); + } + // call the parent + this._super(unloaded); + } + + }; + + // extend the base aciTree class and add the radio stuff + aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_radio, 'aciTreeRadio'); + + // add extra default options + aciPluginClass.defaults('aciTree', options); + + // for internal access + var domApi = aciPluginClass.plugins.aciTree_dom; + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.selectable.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.selectable.js new file mode 100755 index 000000000..e4cea7e77 --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.selectable.js @@ -0,0 +1,739 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * This extension adds item selection/keyboard navigation to aciTree and need to + * be always included if you care about accessibility. + * + * There is an extra property for the item data: + * + * { + * ... + * selected: false, // TRUE means the item will be selected + * ... + * } + * + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + selectable: true, // if TRUE then one item can be selected (and the tree navigation with the keyboard will be enabled) + multiSelectable: false, // if TRUE then multiple items can be selected at a time + // the 'tabIndex' attribute need to be >= 0 set on the tree container (by default will be set to 0) + fullRow: false, // if TRUE then the selection will be made on the entire row (the CSS should reflect this) + textSelection: false // if FALSE then the item text can't be selected + }; + + // aciTree selectable extension + // adds item selection & keyboard navigation (left/right, up/down, pageup/pagedown, home/end, space, enter, escape) + // dblclick also toggles the item + + var aciTree_selectable = { + __extend: function() { + // add extra data + $.extend(this._instance, { + focus: false + }); + $.extend(this._private, { + blurTimeout: null, + spinPoint: null // the selected item to operate against when using the shift key with selection + }); + // call the parent + this._super(); + }, + // test if has focus + hasFocus: function() { + return this._instance.focus; + }, + // init selectable + _selectableInit: function() { + if (this._instance.jQuery.attr('tabindex') === undefined) { + // ensure the tree can get focus + this._instance.jQuery.attr('tabindex', 0); + } + if (!this._instance.options.textSelection) { + // disable text selection + this._selectable(false); + } + this._instance.jQuery.bind('acitree' + this._private.nameSpace, function(event, api, item, eventName, options) { + switch (eventName) { + case 'closed': + var focused = api.focused(); + if (api.isChildren(item, focused)) { + // move focus to parent on close + api._focusOne(item); + } + // deselect children on parent close + api.children(item, true).each(api.proxy(function(element) { + var item = $(element); + if (this.isSelected(item)) { + this.deselect(item); + } + }, true)); + break; + } + }).bind('focusin' + this._private.nameSpace, this.proxy(function() { + // handle tree focus + window.clearTimeout(this._private.blurTimeout); + if (!this.hasFocus()) { + this._instance.focus = true; + domApi.addClass(this._instance.jQuery[0], 'aciTreeFocus'); + this._trigger(null, 'focused'); + } + })).bind('focusout' + this._private.nameSpace, this.proxy(function() { + // handle tree focus + window.clearTimeout(this._private.blurTimeout); + this._private.blurTimeout = window.setTimeout(this.proxy(function() { + if (this.hasFocus()) { + this._instance.focus = false; + domApi.removeClass(this._instance.jQuery[0], 'aciTreeFocus'); + this._trigger(null, 'blurred'); + } + }), 10); + })).bind('keydown' + this._private.nameSpace, this.proxy(function(e) { + if (!this.hasFocus()) { + // do not handle if we do not have focus + return; + } + var focused = this.focused(); + if (focused.length && this.isBusy(focused)) { + // skip when busy + return false; + } + var item = $([]); + switch (e.which) { + case 65: // aA + if (this._instance.options.multiSelectable && e.ctrlKey) { + // select all visible items + var select = this.visible(this.enabled(this.children(null, true))).not(this.selected()); + select.each(this.proxy(function(element) { + this.select($(element), { + focus: false + }); + }, true)); + if (!this.focused().length) { + // ensure one item has focus + this._focusOne(this.visible(select, true).first()); + } + // prevent default action + e.preventDefault(); + } + break; + case 38: // up + item = focused.length ? this._prev(focused) : this.first(); + break; + case 40: // down + item = focused.length ? this._next(focused) : this.first(); + break; + case 37: // left + if (focused.length) { + if (this.isOpen(focused)) { + item = focused; + // close the item + this.close(focused, { + collapse: this._instance.options.collapse, + expand: this._instance.options.expand, + unique: this._instance.options.unique + }); + } else { + item = this.parent(focused); + } + } else { + item = this._first(); + } + break; + case 39: // right + if (focused.length) { + if (this.isInode(focused) && this.isClosed(focused)) { + item = focused; + // open the item + this.open(focused, { + collapse: this._instance.options.collapse, + expand: this._instance.options.expand, + unique: this._instance.options.unique + }); + } else { + item = this.first(focused); + } + } else { + item = this._first(); + } + break; + case 33: // pgup + item = focused.length ? this._prevPage(focused) : this._first(); + break; + case 34: // pgdown + item = focused.length ? this._nextPage(focused) : this._first(); + break; + case 36: // home + item = this._first(); + break; + case 35: // end + item = this._last(); + break; + case 13: // enter + case 107: // numpad [+] + item = focused; + if (this.isInode(focused) && this.isClosed(focused)) { + // open the item + this.open(focused, { + collapse: this._instance.options.collapse, + expand: this._instance.options.expand, + unique: this._instance.options.unique + }); + } + break; + case 27: // escape + case 109: // numpad [-] + item = focused; + if (this.isOpen(focused)) { + // close the item + this.close(focused, { + collapse: this._instance.options.collapse, + expand: this._instance.options.expand, + unique: this._instance.options.unique + }); + } + if (e.which == 27) { + // prevent default action on ESC + e.preventDefault(); + } + break; + case 32: // space + item = focused; + if (this.isInode(focused) && !e.ctrlKey) { + // toggle the item + this.toggle(focused, { + collapse: this._instance.options.collapse, + expand: this._instance.options.expand, + unique: this._instance.options.unique + }); + } + // prevent page scroll + e.preventDefault(); + break; + case 106: // numpad [*] + item = focused; + if (this.isInode(focused)) { + // open all children + this.open(focused, { + collapse: this._instance.options.collapse, + expand: true, + unique: this._instance.options.unique + }); + } + break; + } + if (item.length) { + if (this._instance.options.multiSelectable && !e.ctrlKey && !e.shiftKey) { + // unselect others + this._unselect(this.selected().not(item)); + } + if (!this.isVisible(item)) { + // bring it into view + this.setVisible(item); + } + if (e.ctrlKey) { + if ((e.which == 32) && this.isEnabled(item)) { // space + if (this.isSelected(item)) { + this.deselect(item); + } else { + this.select(item); + } + // remember for later + this._private.spinPoint = item; + } else { + this._focusOne(item); + } + } else if (e.shiftKey) { + this._shiftSelect(item); + } else { + if (!this.isSelected(item) && this.isEnabled(item)) { + this.select(item); + } else { + this._focusOne(item); + } + // remember for later + this._private.spinPoint = item; + } + return false; + } + })); + this._fullRow(this._instance.options.fullRow); + this._multiSelectable(this._instance.options.multiSelectable); + }, + // change full row mode + _fullRow: function(state) { + this._instance.jQuery.off(this._private.nameSpace, '.aciTreeLine,.aciTreeItem').off(this._private.nameSpace, '.aciTreeItem'); + this._instance.jQuery.on('mousedown' + this._private.nameSpace + ' click' + this._private.nameSpace, state ? '.aciTreeLine,.aciTreeItem' : '.aciTreeItem', this.proxy(function(e) { + var item = this.itemFrom(e.target); + if (!this.isVisible(item)) { + this.setVisible(item); + } + if (e.ctrlKey) { + if (e.type == 'click') { + if (this.isEnabled(item)) { + // (de)select item + if (this.isSelected(item)) { + this.deselect(item); + this._focusOne(item); + } else { + this.select(item); + } + } else { + this._focusOne(item); + } + } + } else if (this._instance.options.multiSelectable && e.shiftKey) { + this._shiftSelect(item); + } else { + if (this._instance.options.multiSelectable && (!this.isSelected(item) || (e.type == 'click'))) { + // deselect all other (keep the old focus) + this._unselect(this.selected().not(item)); + } + this._selectOne(item); + } + if (!e.shiftKey) { + this._private.spinPoint = item; + } + })).on('dblclick' + this._private.nameSpace, state ? '.aciTreeLine,.aciTreeItem' : '.aciTreeItem', this.proxy(function(e) { + var item = this.itemFrom(e.target); + if (this.isInode(item)) { + // toggle the item + this.toggle(item, { + collapse: this._instance.options.collapse, + expand: this._instance.options.expand, + unique: this._instance.options.unique + }); + return false; + } + })); + if (state) { + domApi.addClass(this._instance.jQuery[0], 'aciTreeFullRow'); + } else { + domApi.removeClass(this._instance.jQuery[0], 'aciTreeFullRow'); + } + }, + // change selection mode + _multiSelectable: function(state) { + if (state) { + this._instance.jQuery.attr('aria-multiselectable', true); + } else { + var focused = this.focused(); + this._unselect(this.selected().not(focused)); + this._instance.jQuery.removeAttr('aria-multiselectable'); + } + }, + // process `shift` key selection + _shiftSelect: function(item) { + var spinPoint = this._private.spinPoint; + if (!spinPoint || !$.contains(this._instance.jQuery[0], spinPoint[0]) || !this.isOpenPath(spinPoint)) { + spinPoint = this.focused(); + } + if (spinPoint.length) { + // select a range of items + var select = [item[0]], start = spinPoint[0], found = false, stop = item[0]; + var visible = this.visible(this.children(null, true)); + visible.each(this.proxy(function(element) { + // find what items to select + if (found) { + if (this.isEnabled($(element))) { + select.push(element); + } + if ((element == start) || (element == stop)) { + return false; + } + } else if ((element == start) || (element == stop)) { + if (this.isEnabled($(element))) { + select.push(element); + } + if ((element == start) && (element == stop)) { + return false; + } + found = true; + } + }, true)); + this._unselect(this.selected().not(select)); + // select the items + $(select).not(item).each(this.proxy(function(element) { + var item = $(element); + if (!this.isSelected(item)) { + // select item (keep the old focus) + this.select(item, { + focus: false + }); + } + }, true)); + } + this._selectOne(item); + }, + // override `_initHook` + _initHook: function() { + if (this.extSelectable()) { + this._selectableInit(); + } + // call the parent + this._super(); + }, + // override `_itemHook` + _itemHook: function(parent, item, itemData, level) { + if (this.extSelectable() && itemData.selected) { + this._selectableDOM.select(item, true); + } + // call the parent + this._super(parent, item, itemData, level); + }, + // low level DOM functions + _selectableDOM: { + // (de)select one or more items + select: function(items, state) { + if (state) { + domApi.addListClass(items.toArray(), 'aciTreeSelected', function(node) { + node.firstChild.setAttribute('aria-selected', true); + }); + } else { + domApi.removeListClass(items.toArray(), 'aciTreeSelected', function(node) { + node.firstChild.setAttribute('aria-selected', false); + }); + } + }, + // focus one item, unfocus one or more items + focus: function(items, state) { + if (state) { + domApi.addClass(items[0], 'aciTreeFocus'); + items[0].firstChild.focus(); + } else { + domApi.removeListClass(items.toArray(), 'aciTreeFocus'); + } + } + }, + // make element (un)selectable + _selectable: function(state) { + if (state) { + this._instance.jQuery.css({ + '-webkit-user-select': 'text', + '-moz-user-select': 'text', + '-ms-user-select': 'text', + '-o-user-select': 'text', + 'user-select': 'text' + }).attr({ + 'unselectable': null, + 'onselectstart': null + }).unbind('selectstart' + this._private.nameSpace); + } else { + this._instance.jQuery.css({ + '-webkit-user-select': 'none', + '-moz-user-select': '-moz-none', + '-ms-user-select': 'none', + '-o-user-select': 'none', + 'user-select': 'none' + }).attr({ + 'unselectable': 'on', + 'onselectstart': 'return false' + }).bind('selectstart' + this._private.nameSpace, function(e) { + if (!$(e.target).is('input,textarea')) { + return false; + } + }); + } + }, + // get first visible item + _first: function() { + return $(domApi.first(this._instance.jQuery[0], function(node) { + return this.hasClass(node, 'aciTreeVisible') ? true : null; + })); + }, + // get last visible item + _last: function() { + return $(domApi.last(this._instance.jQuery[0], function(node) { + return this.hasClass(node, 'aciTreeVisible') ? true : null; + })); + }, + // get previous visible starting with item + _prev: function(item) { + return $(domApi.prevAll(item[0], function(node) { + return this.hasClass(node, 'aciTreeVisible') ? true : null; + })); + }, + // get next visible starting with item + _next: function(item) { + return $(domApi.nextAll(item[0], function(node) { + return this.hasClass(node, 'aciTreeVisible') ? true : null; + })); + }, + // get previous page starting with item + _prevPage: function(item) { + var space = this._instance.jQuery.height(); + var now = item[0].firstChild.offsetHeight; + var prev = item, last = $(); + while (now < space) { + prev = this._prev(prev); + if (prev[0]) { + now += prev[0].firstChild.offsetHeight; + last = prev; + } else { + break; + } + } + return last; + }, + // get next page starting with item + _nextPage: function(item) { + var space = this._instance.jQuery.height(); + var now = item[0].firstChild.offsetHeight; + var next = item, last = $(); + while (now < space) { + next = this._next(next); + if (next[0]) { + now += next[0].firstChild.offsetHeight; + last = next; + } else { + break; + } + } + return last; + }, + // select one item + _selectOne: function(item) { + if (this.isSelected(item)) { + this._focusOne(item); + } else { + if (this.isEnabled(item)) { + // select the item + this.select(item); + } else { + this._focusOne(item); + } + } + }, + // unselect the items + _unselect: function(items) { + items.each(this.proxy(function(element) { + this.deselect($(element)); + }, true)); + }, + // focus one item + _focusOne: function(item) { + if (!this._instance.options.multiSelectable) { + this._unselect(this.selected().not(item)); + } + if (!this.isFocused(item)) { + this.focus(item); + } + }, + // select item + // `options.focus` when set to FALSE will not set the focus + // `options.oldSelected` will keep the old selected items + select: function(item, options) { + options = this._options(options, 'selected', 'selectfail', 'wasselected', item); + if (this.extSelectable() && this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeselect', options)) { + this._fail(item, options); + return; + } + // keep the old ones + options.oldSelected = this.selected(); + if (!this._instance.options.multiSelectable) { + // deselect all other + var unselect = options.oldSelected.not(item); + this._selectableDOM.select(unselect, false); + unselect.each(this.proxy(function(element) { + this._trigger($(element), 'deselected', options); + }, true)); + } + if (this.isSelected(item)) { + this._notify(item, options); + } else { + this._selectableDOM.select(item, true); + this._success(item, options); + } + // process focus + if ((options.focus === undefined) || options.focus) { + if (!this.isFocused(item) || options.focus) { + this.focus(item, this._inner(options)); + } + } + } else { + this._fail(item, options); + } + }, + // deselect item + deselect: function(item, options) { + options = this._options(options, 'deselected', 'deselectfail', 'notselected', item); + if (this.extSelectable() && this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforedeselect', options)) { + this._fail(item, options); + return; + } + if (this.isSelected(item)) { + this._selectableDOM.select(item, false); + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // set `virtual` focus + // `options.oldFocused` will keep the old focused item + focus: function(item, options) { + options = this._options(options, 'focus', 'focusfail', 'wasfocused', item); + if (this.extSelectable() && this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforefocus', options)) { + this._fail(item, options); + return; + } + // keep the old ones + options.oldFocused = this.focused(); + // blur all other + var unfocus = options.oldFocused.not(item); + this._selectableDOM.focus(unfocus, false); + // unfocus all others + unfocus.each(this.proxy(function(element) { + this._trigger($(element), 'blur', options); + }, true)); + if (this.isFocused(item)) { + this._notify(item, options); + } else { + this._selectableDOM.focus(item, true); + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // remove `virtual` focus + blur: function(item, options) { + options = this._options(options, 'blur', 'blurfail', 'notfocused', item); + if (this.extSelectable() && this.isItem(item)) { + // a way to cancel the operation + if (!this._trigger(item, 'beforeblur', options)) { + this._fail(item, options); + return; + } + if (this.isFocused(item)) { + this._selectableDOM.focus(item, false); + this._success(item, options); + } else { + this._notify(item, options); + } + } else { + this._fail(item, options); + } + }, + // get selected items + selected: function() { + return this._instance.jQuery.find('.aciTreeSelected'); + }, + // override `_serialize` + _serialize: function(item, callback) { + // call the parent + var data = this._super(item, callback); + if (data && this.extSelectable()) { + if (data.hasOwnProperty('selected')) { + data.selected = this.isSelected(item); + } else if (this.isSelected(item)) { + data.selected = true; + } + } + return data; + }, + // test if item is selected + isSelected: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeSelected'); + }, + // return the focused item + focused: function() { + return this._instance.jQuery.find('.aciTreeFocus'); + }, + // test if item is focused + isFocused: function(item) { + return item && domApi.hasClass(item[0], 'aciTreeFocus'); + }, + // test if selectable is enabled + extSelectable: function() { + return this._instance.options.selectable; + }, + // override set `option` + option: function(option, value) { + if (this.wasInit() && !this.isLocked()) { + if ((option == 'selectable') && (value != this.extSelectable())) { + if (value) { + this._selectableInit(); + } else { + this._selectableDone(); + } + } + if ((option == 'multiSelectable') && (value != this._instance.options.multiSelectable)) { + this._multiSelectable(value); + } + if ((option == 'fullRow') && (value != this._instance.options.fullRow)) { + this._fullRow(value); + } + if ((option == 'textSelection') && (value != this._instance.options.textSelection)) { + this._selectable(value); + } + } + // call the parent + this._super(option, value); + }, + // done selectable + _selectableDone: function(destroy) { + if (this._instance.jQuery.attr('tabindex') == 0) { + this._instance.jQuery.removeAttr('tabindex'); + } + if (!this._instance.options.textSelection) { + this._selectable(true); + } + this._instance.jQuery.unbind(this._private.nameSpace); + this._instance.jQuery.off(this._private.nameSpace, '.aciTreeLine,.aciTreeItem').off(this._private.nameSpace, '.aciTreeItem'); + domApi.removeClass(this._instance.jQuery[0], ['aciTreeFocus', 'aciTreeFullRow']); + this._instance.jQuery.removeAttr('aria-multiselectable'); + this._instance.focus = false; + this._private.spinPoint = null; + if (!destroy) { + // remove selection + this._unselect(this.selected()); + var focused = this.focused(); + if (focused.length) { + this.blur(focused); + } + } + }, + // override `_destroyHook` + _destroyHook: function(unloaded) { + if (unloaded) { + this._selectableDone(true); + } + // call the parent + this._super(unloaded); + } + + }; + + // extend the base aciTree class and add the selectable stuff + aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_selectable, 'aciTreeSelectable'); + + // add extra default options + aciPluginClass.defaults('aciTree', options); + + // for internal access + var domApi = aciPluginClass.plugins.aciTree_dom; + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.sortable.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.sortable.js new file mode 100755 index 000000000..09a80697e --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.sortable.js @@ -0,0 +1,339 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * This extension adds the possibility to sort the tree items. + * Require aciSortable https://github.com/dragosu/jquery-aciSortable and the utils extension for reordering items. + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + sortable: false, // if TRUE then the tree items can be sorted + sortDelay: 750, // how many [ms] before opening a inode on hovering when in drag + // called by the `aciSortable` inside the `drag` callback + sortDrag: function(item, placeholder, isValid, helper) { + if (!isValid) { + var move = this.getLabel(item); + if (this._private.dragDrop && (this._private.dragDrop.length > 1)) { + move += ' and #' + (this._private.dragDrop.length - 1) + ' more'; + } + helper.html(move); + } + }, + // called by the `aciSortable` inside the `valid` callback + sortValid: function(item, hover, before, isContainer, placeholder, helper) { + var move = this.getLabel(item); + if (this._private.dragDrop.length > 1) { + move += ' and #' + (this._private.dragDrop.length - 1) + ' more'; + } + if (isContainer) { + helper.html('move ' + move + ' to ' + this.getLabel(this.itemFrom(hover))); + placeholder.removeClass('aciTreeAfter aciTreeBefore'); + } else if (before !== null) { + if (before) { + helper.html('move ' + move + ' before ' + this.getLabel(hover)); + placeholder.removeClass('aciTreeAfter').addClass('aciTreeBefore'); + } else { + helper.html('move ' + move + ' after ' + this.getLabel(hover)); + placeholder.removeClass('aciTreeBefore').addClass('aciTreeAfter'); + } + } + } + }; + + // aciTree sortable extension + + var aciTree_sortable = { + __extend: function() { + // add extra data + $.extend(this._private, { + openTimeout: null, + dragDrop: null // the items used in drag & drop + }); + // call the parent + this._super(); + }, + // init sortable + _sortableInit: function() { + this._instance.jQuery.aciSortable({ + container: '.aciTreeUl', + item: '.aciTreeLi', + child: 50, + childHolder: '
        ', + childHolderSelector: '.aciTreeChild', + placeholder: '
      • ', + placeholderSelector: '.aciTreePlaceholder', + helper: '
        ', + helperSelector: '.aciTreeHelper', + // just before drag start + before: this.proxy(function(item) { + // init before drag + if (!this._initDrag(item)) { + return false; + } + // a way to cancel the operation + if (!this._trigger(item, 'beforedrag')) { + this._trigger(item, 'dragfail'); + return false; + } + return true; + }), + // just after drag start, before dragging + start: this.proxy(function(item, placeholder, helper) { + this._instance.jQuery.addClass('aciTreeDragDrop'); + helper.stop(true).css('opacity', 1); + }), + // when in drag + drag: this.proxy(function(item, placeholder, isValid, helper) { + if (!isValid) { + window.clearTimeout(this._private.openTimeout); + } + if (this._instance.options.sortDrag) { + this._instance.options.sortDrag.apply(this, arguments); + } + }), + // to check the drop target (when the placeholder is repositioned) + valid: this.proxy(function(item, hover, before, isContainer, placeholder, helper) { + window.clearTimeout(this._private.openTimeout); + if (!this._checkDrop(item, hover, before, isContainer, placeholder, helper)) { + return false; + } + var options = this._options({ + hover: hover, + before: before, + isContainer: isContainer, + placeholder: placeholder, + helper: helper + }); + // a way to cancel the operation + if (!this._trigger(item, 'checkdrop', options)) { + return false; + } + if (this.isInode(hover) && !this.isOpen(hover)) { + this._private.openTimeout = window.setTimeout(this.proxy(function() { + this.open(hover); + }), this._instance.options.sortDelay); + } + if (this._instance.options.sortValid) { + this._instance.options.sortValid.apply(this, arguments); + } + return true; + }), + // when dragged as child + create: this.proxy(function(api, item, hover) { + if (this.isLeaf(hover)) { + hover.append(api._instance.options.childHolder); + return true; + } + return false; + }, true), + // on drag end + end: this.proxy(function(item, hover, placeholder, helper) { + window.clearTimeout(this._private.openTimeout); + var options = { + placeholder: placeholder, + helper: helper + }; + options = this._options(options, 'sorted', 'dropfail', null, item); + if (placeholder.parent().length) { + var prev = this.prev(placeholder, true); + if (prev.length) { + // add after a item + placeholder.detach(); + var items = $(this._private.dragDrop.get().reverse()); + this._private.dragDrop = null; + items.each(this.proxy(function(element) { + this.moveAfter($(element), this._inner(options, { + success: options.success, + fail: options.fail, + after: prev + })); + }, true)); + } else { + var next = this.next(placeholder, true); + if (next.length) { + // add before a item + placeholder.detach(); + var items = $(this._private.dragDrop.get().reverse()); + this._private.dragDrop = null; + items.each(this.proxy(function(element) { + this.moveBefore($(element), this._inner(options, { + success: options.success, + fail: options.fail, + before: next + })); + }, true)); + } else { + // add as a child + var parent = this.parent(placeholder); + var container = placeholder.parent(); + placeholder.detach(); + container.remove(); + if (this.isLeaf(parent)) { + // we can set asChild only for leaves + var items = this._private.dragDrop; + this.asChild(items.eq(0), this._inner(options, { + success: function() { + this._success(item, options); + this.open(parent); + items.filter(':gt(0)').each(this.proxy(function(element) { + this.moveAfter($(element), this._inner(options, { + success: options.success, + fail: options.fail, + after: this.last(parent) + })); + }, true)); + }, + fail: options.fail, + parent: parent + })); + } else { + this._fail(item, options); + } + } + } + } else { + this._fail(item, options); + } + this._private.dragDrop = null; + if (helper.parent().length) { + // the helper is inserted in the DOM + var top = $(window).scrollTop(); + var left = $(window).scrollLeft(); + var rect = item[0].getBoundingClientRect(); + // animate helper to item position + helper.animate({ + top: rect.top + top, + left: rect.left + left, + opacity: 0 + }, + { + complete: function() { + // detach the helper when completed + helper.detach(); + } + }); + } + this._instance.jQuery.removeClass('aciTreeDragDrop'); + }) + }); + }, + // override `_initHook` + _initHook: function() { + if (this.extSortable()) { + this._sortableInit(); + } + // call the parent + this._super(); + }, + // reduce items by removing the childrens + _parents: function(items) { + var len = items.length, a, b, remove = []; + for (var i = 0; i < len - 1; i++) { + a = items.eq(i); + for (var j = i + 1; j < len; j++) { + b = items.eq(j); + if (this.isChildren(a, b)) { + remove.push(items[j]); + } else if (this.isChildren(b, a)) { + remove.push(items[i]); + } + } + } + return items.not(remove); + }, + // called before drag start + _initDrag: function(item) { + // support `selectable` extension + if (this.extSelectable && this.extSelectable()) { + if (!this.hasFocus()) { + this._instance.jQuery.focus(); + } + if (!this.isEnabled(item)) { + return false; + } + var drag = this.selected(); + if (drag.length) { + if (!this.isSelected(item)) { + return false; + } + } else { + drag = item; + } + this._private.dragDrop = this._parents(drag); + } else { + this._instance.jQuery.focus(); + this._private.dragDrop = item; + } + return true; + }, + // check the drop target + _checkDrop: function(item, hover, before, isContainer, placeholder, helper) { + var items = this._private.dragDrop; + if (!items) { + return false; + } + var test = this.itemFrom(hover); + if (items.is(test) || items.has(test[0]).length) { + return false; + } + if (!isContainer) { + test = before ? this.prev(hover) : this.next(hover); + if (items.is(test)) { + return false; + } + } + return true; + }, + // test if sortable is enabled + extSortable: function() { + return this._instance.options.sortable; + }, + // override set `option` + option: function(option, value) { + if (this.wasInit() && !this.isLocked()) { + if ((option == 'sortable') && (value != this.extSortable())) { + if (value) { + this._sortableInit(); + } else { + this._sortableDone(); + } + } + } + // call the parent + this._super(option, value); + }, + // done sortable + _sortableDone: function() { + this._instance.jQuery.unbind(this._private.nameSpace); + this._instance.jQuery.aciSortable('destroy'); + }, + // override `_destroyHook` + _destroyHook: function(unloaded) { + if (unloaded) { + this._sortableDone(); + } + // call the parent + this._super(unloaded); + } + }; + + // extend the base aciTree class and add the sortable stuff + aciPluginClass.plugins.aciTree = aciPluginClass.plugins.aciTree.extend(aciTree_sortable, 'aciTreeSortable'); + + // add extra default options + aciPluginClass.defaults('aciTree', options); + +})(jQuery, this); diff --git a/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.utils.js b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.utils.js new file mode 100755 index 000000000..a903add27 --- /dev/null +++ b/web/pgadmin/browser/static/js/aciTree/jquery.aciTree.utils.js @@ -0,0 +1,746 @@ + +/* + * aciTree jQuery Plugin v4.5.0-rc.7 + * http://acoderinsights.ro + * + * Copyright (c) 2014 Dragos Ursu + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Require jQuery Library >= v1.9.0 http://jquery.com + * + aciPlugin >= v1.5.1 https://github.com/dragosu/jquery-aciPlugin + */ + +/* + * A few utility functions for aciTree. + */ + +(function($, window, undefined) { + + // extra default options + + var options = { + // called when items need to be filtered, for each tree item + // return TRUE/FALSE to include/exclude items on filtering + filterHook: function(item, search, regexp) { + return search.length ? regexp.test(window.String(this.getLabel(item))) : true; + } + }; + + // aciTree utils extension + // adds item update option, branch processing, moving items & item swapping, item search by ID + + var aciTree_utils = { + __extend: function() { + // add extra data + $.extend(this._instance, { + filter: new this._queue(this, this._instance.options.queue) + }); + // stop queue until needed + this._instance.filter.destroy(); + // call the parent + this._super(); + }, + // call the `callback` function (item) for each children of item + // when `load` is TRUE will also try to load nodes + branch: function(item, callback, load) { + var queue = this._instance.queue; + var process = this.proxy(function(item, callback, next) { + var child = next ? this.next(item) : this.first(item); + if (child.length) { + if (this.isInode(child)) { + if (this.wasLoad(child)) { + queue.push(function(complete) { + callback.call(this, child); + process(child, callback); + process(child, callback, true); + complete(); + }); + } else if (load) { + // load the item first + this.ajaxLoad(child, { + success: function() { + callback.call(this, child); + process(child, callback); + process(child, callback, true); + }, + fail: function() { + process(child, callback, true); + } + }); + } else { + queue.push(function(complete) { + callback.call(this, child); + process(child, callback, true); + complete(); + }); + } + } else { + queue.push(function(complete) { + callback.call(this, child); + process(child, callback, true); + complete(); + }); + } + } + }); + process(item, callback); + }, + // swap two items (they can't be parent & children) + // `options.item1` & `options.item2` are the swapped items + swap: function(options) { + options = this._options(options, null, 'swapfail', null, null); + var item1 = options.item1; + var item2 = options.item2; + if (this.isItem(item1) && this.isItem(item2) && !this.isChildren(item1, item2) && !this.isChildren(item2, item1) && (item1[0] != item2[0])) { + // a way to cancel the operation + if (!this._trigger(null, 'beforeswap', options)) { + this._fail(null, options); + return; + } + var prev = this.prev(item1); + if (prev.length) { + if (item2[0] == prev[0]) { + item2.before(item1); + } else { + item1.insertAfter(item2); + item2.insertAfter(prev); + } + } else { + var next = this.next(item1); + if (next.length) { + if (item2[0] == next[0]) { + item2.after(item1); + } else { + item1.insertAfter(item2); + item2.insertBefore(next); + } + } else { + var parent = item1.parent(); + item1.insertAfter(item2); + parent.append(item2); + } + } + // update item states + this._updateLevel(item1); + var parent = this.parent(item1); + this._setFirstLast(parent.length ? parent : null, item1); + this._updateHidden(item1); + this._updateLevel(item2); + parent = this.parent(item2); + this._setFirstLast(parent.length ? parent : null, item2); + this._updateHidden(item2); + this._setOddEven(item1.add(item2)); + this._trigger(null, 'swapped', options); + this._success(null, options); + } else { + this._fail(null, options); + } + }, + // update item level + _updateItemLevel: function(item, fromLevel, toLevel) { + domApi.addRemoveClass(item[0], 'aciTreeLevel' + toLevel, 'aciTreeLevel' + fromLevel); + var line = item[0].firstChild; + line.setAttribute('aria-level', toLevel + 1); + var entry = domApi.childrenByClass(line, 'aciTreeEntry'); + if (fromLevel < toLevel) { + line = entry.parentNode; + var branch; + for (var i = fromLevel; i < toLevel; i++) { + branch = window.document.createElement('DIV'); + line.appendChild(branch); + branch.className = 'aciTreeBranch aciTreeLevel' + i; + line = branch; + } + line.appendChild(entry); + } else { + var branch = entry; + for (var i = toLevel; i <= fromLevel; i++) { + branch = branch.parentNode; + } + branch.removeChild(branch.firstChild); + branch.appendChild(entry); + } + }, + // update child level + _updateChildLevel: function(item, fromLevel, toLevel) { + this.children(item, false, true).each(this.proxy(function(element) { + var item = $(element); + this._updateItemLevel(item, fromLevel, toLevel); + if (this.isInode(item)) { + this._updateChildLevel(item, fromLevel + 1, toLevel + 1); + } + }, true)); + }, + // update item level + _updateLevel: function(item) { + var level = this.level(item); + var found = window.parseInt(item.attr('class').match(/aciTreeLevel[0-9]+/)[0].match(/[0-9]+/)); + if (level != found) { + this._updateItemLevel(item, found, level); + this._updateChildLevel(item, found + 1, level + 1); + } + }, + // move item up + moveUp: function(item, options) { + options = this._options(options); + options.index = window.Math.max(this.getIndex(item) - 1, 0); + this.setIndex(item, options); + }, + // move item down + moveDown: function(item, options) { + options = this._options(options); + options.index = window.Math.min(this.getIndex(item) + 1, this.siblings(item).length); + this.setIndex(item, options); + }, + // move item in first position + moveFirst: function(item, options) { + options = this._options(options); + options.index = 0; + this.setIndex(item, options); + }, + // move item in last position + moveLast: function(item, options) { + options = this._options(options); + options.index = this.siblings(item).length; + this.setIndex(item, options); + }, + // move item before another (they can't be parent & children) + // `options.before` is the element before which the item will be moved + moveBefore: function(item, options) { + options = this._options(options, null, 'movefail', 'wasbefore', item); + var before = options.before; + if (this.isItem(item) && this.isItem(before) && !this.isChildren(item, before) && (item[0] != before[0])) { + // a way to cancel the operation + if (!this._trigger(item, 'beforemove', options)) { + this._fail(item, options); + return; + } + if (this.prev(before, true)[0] == item[0]) { + this._notify(item, options); + } else { + var parent = this.parent(item); + var prev = this.prev(item, true); + if (!prev.length) { + prev = parent.length ? parent : this.first(); + } + item.insertBefore(before); + if (parent.length && !this.hasChildren(parent, true)) { + this.setLeaf(parent); + } + this._updateLevel(item); + // update item states + this._setFirstLast(parent.length ? parent : null); + parent = this.parent(item); + this._setFirstLast(parent.length ? parent : null, item.add(before)); + this._updateHidden(item); + this._setOddEven(item.add(before).add(prev)); + this._trigger(item, 'moved', options); + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // move item after another (they can't be parent & children) + // `options.after` is the element after which the item will be moved + moveAfter: function(item, options) { + options = this._options(options, null, 'movefail', 'wasafter', item); + var after = options.after; + if (this.isItem(item) && this.isItem(after) && !this.isChildren(item, after) && (item[0] != after[0])) { + // a way to cancel the operation + if (!this._trigger(item, 'beforemove', options)) { + this._fail(item, options); + return; + } + if (this.next(after, true)[0] == item[0]) { + this._notify(item, options); + } else { + var parent = this.parent(item); + var prev = this.prev(item, true); + if (!prev.length) { + prev = parent.length ? parent : this.first(); + } + item.insertAfter(after); + if (parent.length && !this.hasChildren(parent, true)) { + this.setLeaf(parent); + } + this._updateLevel(item); + this._setFirstLast(parent.length ? parent : null); + parent = this.parent(item); + this._setFirstLast(parent.length ? parent : null, item.add(after)); + this._updateHidden(item); + this._setOddEven(item.add(after).add(prev)); + this._trigger(item, 'moved', options); + this._success(item, options); + } + } else { + this._fail(item, options); + } + }, + // move item to be a child of another (they can't be parent & children and the targeted parent item must be empty) + // `options.parent` is the parent element on which the item will be added + asChild: function(item, options) { + options = this._options(options, null, 'childfail', null, item); + var parent = options.parent; + if (this.isItem(item) && this.isItem(parent) && !this.isChildren(item, parent) && !this.hasChildren(parent, true) && (item[0] != parent[0])) { + // a way to cancel the operation + if (!this._trigger(item, 'beforechild', options)) { + this._fail(item, options); + return; + } + var process = function() { + var oldParent = this.parent(item); + var prev = this.prev(item); + if (!prev.length) { + prev = oldParent.length ? oldParent : this.first(); + } + var container = this._createContainer(parent); + container.append(item); + if (oldParent.length && !this.hasChildren(oldParent, true)) { + // no more children + this.setLeaf(oldParent); + } + // update item states + this._updateLevel(item); + this._setFirstLast(oldParent.length ? oldParent : null); + this._setFirstLast(parent.length ? parent : null, item); + this._updateHidden(item); + this._setOddEven(item.add(prev)); + this._trigger(item, 'childset', options); + this._success(item, options); + }; + if (this.isInode(parent)) { + process.apply(this); + } else { + // set as inode first + this.setInode(parent, this._inner(options, { + success: process, + fail: options.fail + })); + } + } else { + this._fail(item, options); + } + }, + // search a `path` ID from a parent + _search: function(parent, pathId) { + var items = this.children(parent); + var item, id, length, found, exact = false; + for (var i = 0, size = items.length; i < size; i++) { + item = items.eq(i); + id = window.String(this.getId(item)); + length = id.length; + if (length) { + if (id == pathId.substr(0, length)) { + found = item; + exact = pathId.length == length; + break; + } + } + } + if (found) { + if (!exact) { + // try to search children + var child = this._search(found, pathId); + if (child) { + return child; + } + } + return { + item: found, + exact: exact + }; + } else { + return null; + } + }, + // search items by ID + // `options.id` is the ID to search for + // if `path` is TRUE then the search will be more optimized + // and reduced to the first branch that matches the ID + // but the ID must be set like a path otherwise will not work + // if `load` is TRUE will also try to load nodes (works only when `path` is TRUE) + searchId: function(path, load, options) { + options = this._options(options); + var id = options.id; + if (path) { + if (load) { + var process = this.proxy(function(item) { + var found = this._search(item, id); + if (found) { + if (found.exact) { + this._success(found.item, options); + } else { + if (this.wasLoad(found.item)) { + this._fail(item, options); + } else { + // load the item + this.ajaxLoad(found.item, this._inner(options, { + success: function() { + process(found.item); + }, + fail: options.fail + })); + } + } + } else { + this._fail(item, options); + } + }); + process(); + } else { + var found = this._search(null, id); + if (found && found.exact) { + this._success(found.item, options); + } else { + this._fail(null, options); + } + } + } else { + var found = $(); + this._instance.jQuery.find('.aciTreeLi').each(this.proxy(function(element) { + if (id == this.getId($(element))) { + found = $(element); + return false; + } + }, true)); + if (found.length) { + this._success(found, options); + } else { + this._fail(null, options); + } + } + }, + // search nodes by ID or custom property starting from item + // `options.search` is the value to be searched + // `options.load` if TRUE will try to load nodes + // `options.callback` function (item, search) return TRUE for the custom match + // `options.results` will keep the search results + search: function(item, options) { + var results = []; + options = this._options(options); + var task = new this._task(new this._queue(this, this._instance.options.queue), function(complete) { + // run this at the end + if (results.length) { + options.results = $(results); + this._success($(results[0]), options); + } else { + this._fail(item, options); + } + complete(); + }); + var children = this.proxy(function(item) { + this.children(item, false, true).each(this.proxy(function(element) { + if (options.callback) { + // custom search + var match = options.callback.call(this, $(element), options.search); + if (match) { + results.push(element); + } else if (match === null) { + // skip childrens + return; + } + } else if (this.getId($(element)) == options.search) { + // default ID match + results.push(element); + } + if (this.isInode($(element))) { + // process children + task.push(function(complete) { + search($(element)); + complete(); + }); + } + }, true)); + }); + var search = this.proxy(function(item) { + if (this.wasLoad(item)) { + // process children + task.push(function(complete) { + children(item); + complete(); + }); + } else if (options.load) { + task.push(function(complete) { + // load the item first + this.ajaxLoad(item, { + success: function() { + children(item); + complete(); + }, + fail: complete + }); + }); + } + }); + // run the search + task.push(function(complete) { + search(item); + complete(); + }); + }, + // search node by a list of IDs starting from item + // `options.path` is a list of IDs to be searched - the path to the node + // `options.load` if TRUE will try to load nodes + searchPath: function(item, options) { + options = this._options(options); + var path = options.path; + var search = this.proxy(function(item, id) { + this.search(item, { + success: function(item) { + if (path.length) { + search(item, path.shift()); + } else { + this._success(item, options); + } + }, + fail: function() { + this._fail(item, options); + }, + search: id, + load: options.load, + callback: function(item, search) { + // prevent drill-down + return (this.getId(item) == search) ? true : null; + } + }); + }); + search(item, path.shift()); + }, + // get item path IDs starting from the top parent (ROOT) + // when `reverse` is TRUE returns the IDs in reverse order + pathId: function(item, reverse) { + var path = this.path(item, reverse), id = []; + path.each(this.proxy(function(element) { + id.push(this.getId($(element))); + }, true)); + return id; + }, + // escape string and return RegExp + _regexp: function(search) { + return new window.RegExp(window.String(search).replace(/([-()\[\]{}+?*.$\^|,:#