diff --git a/Gruntfile.js b/Gruntfile.js index 3ddab44f5..4600d031b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -135,6 +135,7 @@ module.exports = function(grunt) { "packages/node_modules/@node-red/editor-client/src/js/validators.js", "packages/node_modules/@node-red/editor-client/src/js/ui/utils.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js", + "packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/checkboxSet.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js", diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js new file mode 100644 index 000000000..e139257f7 --- /dev/null +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js @@ -0,0 +1,177 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +(function($) { + +/** + * options: + * - data : array - initial items to display in tree + * + * methods: + * - data(items) - clears existing items and replaces with new data + * + * events: + * - treelistselect : function(event, item) {} + * + * + * data: + * [ + * { + * label: 'Local', // label for the item + * icon: 'fa fa-rocket', // (optional) icon for the item + * selected: true/false, // (optional) if present, display checkbox accordingly + * children: [] | function(done) // (optional) an array of child items, or a function + * // that will call the `done` callback with an array + * // of child items + * } + * ] + * + * + * + * var treeList = $("
").css({width: "100%", height: "100%"}).treeList({data:[...]}) + * treeList.on('treelistselect', function(e,item) { console.log(item)}) + * treeList.treeList('data',[ ... ] ) + * + */ + + $.widget( "nodered.treeList", { + _create: function() { + var that = this; + + this.element.addClass('red-ui-treeList'); + var wrapper = $('
',{class:'red-ui-treeList-container'}).appendTo(this.element); + + this._data = []; + + this._topList = $('
    ').css({ + position:'absolute', + top: 0, + left:0, + right:0, + bottom:0 + }).appendTo(wrapper).editableList({ + addButton: false, + scrollOnAdd: false, + height: '100%', + addItem: function(container,i,item) { + that._addSubtree(container,item,0); + } + }); + if (this.options.data) { + this.data(this.options.data); + } + }, + _addChildren: function(container,children,depth) { + var that = this; + var subtree = $('
      ').appendTo(container).editableList({ + addButton: false, + scrollOnAdd: false, + height: 'auto', + addItem: function(container,i,item) { + that._addSubtree(container,item,depth+1); + } + }); + for (var i=0;i').appendTo(label); + // $('').appendTo(label); + label.click(function(e) { + if (!container.hasClass("built") && typeof item.children === 'function') { + container.addClass('built'); + var childrenAdded = false; + var spinner; + item.children(function(children) { + childrenAdded = true; + that._addChildren(container,children,depth); + if (spinner) { + spinner.remove(); + } + }); + if (!childrenAdded) { + spinner = $('
      ').css({ + "background-position": (35+depth*15)+'px 50%' + }).appendTo(container); + } + + } + container.toggleClass("expanded"); + }) + } else { + $('').appendTo(label); + } + if (item.hasOwnProperty('selected')) { + var selectWrapper = $('').appendTo(label); + var cb = $('').prop('checked',item.selected).appendTo(selectWrapper); + cb.on('click', function(e) { + e.stopPropagation(); + }); + cb.on('change', function(e) { + item.selected = this.checked; + that._trigger("select",e,item); + }) + } else if (!item.children) { + label.click(function(e) { + that._trigger("select",e,item) + }) + } + if (item.icon) { + $('').appendTo(label); + } + $('').html(item.label).appendTo(label); + if (item.children) { + if (Array.isArray(item.children)) { + that._addChildren(container,item.children,depth); + } + if (item.expanded) { + label.click(); + } + } + }, + empty: function() { + this._topList.editableList('empty'); + }, + data: function(items) { + if (items !== undefined) { + this._data = items; + this._topList.editableList('empty'); + for (var i=0; i i { position: absolute; diff --git a/packages/node_modules/@node-red/editor-client/src/sass/style.scss b/packages/node_modules/@node-red/editor-client/src/sass/style.scss index b160959c8..ccf09f9cb 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/style.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/style.scss @@ -58,6 +58,7 @@ @import "ui/common/nodeList"; @import "ui/common/checkboxSet"; @import "ui/common/stack"; +@import "ui/common/treeList"; @import "dragdrop"; diff --git a/packages/node_modules/@node-red/editor-client/src/sass/ui/common/treeList.scss b/packages/node_modules/@node-red/editor-client/src/sass/ui/common/treeList.scss new file mode 100644 index 000000000..2d090ae72 --- /dev/null +++ b/packages/node_modules/@node-red/editor-client/src/sass/ui/common/treeList.scss @@ -0,0 +1,108 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +.red-ui-treeList { + +} + +.red-ui-treeList-container { + width: 100%; + height: 100%; + position: relative; + background: #f9f9f9; + + border: 1px solid $form-input-border-color; + border-radius: 4px; + + box-sizing: border-box; + + .red-ui-editableList-border { + border: none; + } + + .red-ui-editableList-container { + padding: 0px; + } + + .red-ui-editableList-container li { + padding: 0; + border-bottom: none; + .red-ui-editableList-container { + // margin-left: 15px; + } + } + .red-ui-editableList-item-content { + & > .red-ui-treeList-label .fa-angle-right { + transition: transform 0.1s ease-in-out; + } + .red-ui-editableList { + display: none; + } + &.expanded { + & > .red-ui-treeList-label .fa-angle-right { + transform: rotate(90deg) + } + & > .red-ui-editableList { + display: block + } + & > .red-ui-treeList-spinner { + display: block; + } + } + } +} +label.red-ui-treeList-label { + display: block; + width: auto; +} +.red-ui-treeList-label { + @include disable-selection; + padding: 6px 0; + display: block; + color: $form-text-color; + text-decoration: none; + cursor: pointer; + vertical-align: middle; + margin: 0; + + &:hover { + background: #f9f9f9; + color: $form-text-color; + text-decoration: none; + } + &:focus { + outline: none; + color: $form-text-color; + text-decoration: none; + } + input { + margin: 0; + } +} +.red-ui-treeList-label-text { + margin-left: 4px; +} +.red-ui-treeList-icon { + display: inline-block; + width: 20px; + text-align: center; +} +.red-ui-treeList-spinner { + display: none; + height: 32px; + background: url(images/spin.svg) 50% 50% no-repeat; + background-size: auto 20px; +}