mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
b5da6f9c74
Uses jquery-migrate-3.0.1.min.js to keep things working.
347 lines
14 KiB
JavaScript
347 lines
14 KiB
JavaScript
/**
|
|
* 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(item,done) // (optional) an array of child items, or a function
|
|
* // that will call the `done` callback with an array
|
|
* // of child items
|
|
* }
|
|
* ]
|
|
*
|
|
*
|
|
*
|
|
* var treeList = $("<div>").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');
|
|
this.element.attr("tabIndex",0);
|
|
var wrapper = $('<div>',{class:'red-ui-treeList-container'}).appendTo(this.element);
|
|
this.element.on('keydown', function(evt) {
|
|
var selected = that._topList.find(".selected").parent().data('data');
|
|
if (!selected && (evt.keyCode === 40 || evt.keyCode === 38)) {
|
|
that.select(that._data[0]);
|
|
return;
|
|
}
|
|
var target;
|
|
switch(evt.keyCode) {
|
|
case 37: // LEFT
|
|
if (selected.children&& selected.treeList.container.hasClass("expanded")) {
|
|
selected.treeList.collapse()
|
|
} else if (selected.parent) {
|
|
target = selected.parent;
|
|
}
|
|
break;
|
|
case 38: // UP
|
|
target = that._getPreviousSibling(selected);
|
|
if (target) {
|
|
target = that._getLastDescendant(target);
|
|
}
|
|
if (!target && selected.parent) {
|
|
target = selected.parent;
|
|
}
|
|
break;
|
|
case 39: // RIGHT
|
|
if (selected.children) {
|
|
if (!selected.treeList.container.hasClass("expanded")) {
|
|
selected.treeList.expand()
|
|
}
|
|
}
|
|
break
|
|
case 40: //DOWN
|
|
if (selected.children && Array.isArray(selected.children) && selected.children.length > 0 && selected.treeList.container.hasClass("expanded")) {
|
|
target = selected.children[0];
|
|
} else {
|
|
target = that._getNextSibling(selected);
|
|
while (!target && selected.parent) {
|
|
selected = selected.parent;
|
|
target = that._getNextSibling(selected);
|
|
}
|
|
}
|
|
break
|
|
}
|
|
if (target) {
|
|
that.select(target);
|
|
}
|
|
});
|
|
this._data = [];
|
|
|
|
this._topList = $('<ol>').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(that._topList,container,item,0);
|
|
}
|
|
})
|
|
if (this.options.data) {
|
|
this.data(this.options.data);
|
|
}
|
|
},
|
|
_getLastDescendant: function(item) {
|
|
// Gets the last visible descendant of the item
|
|
if (!item.children || !item.treeList.container.hasClass("expanded") || item.children.length === 0) {
|
|
return item;
|
|
}
|
|
return this._getLastDescendant(item.children[item.children.length-1]);
|
|
},
|
|
_getPreviousSibling: function(item) {
|
|
var candidates;
|
|
if (!item.parent) {
|
|
candidates = this._data;
|
|
} else {
|
|
candidates = item.parent.children;
|
|
}
|
|
var index = candidates.indexOf(item);
|
|
if (index === 0) {
|
|
return null;
|
|
} else {
|
|
return candidates[index-1];
|
|
}
|
|
},
|
|
_getNextSibling: function(item) {
|
|
var candidates;
|
|
if (!item.parent) {
|
|
candidates = this._data;
|
|
} else {
|
|
candidates = item.parent.children;
|
|
}
|
|
var index = candidates.indexOf(item);
|
|
if (index === candidates.length - 1) {
|
|
return null;
|
|
} else {
|
|
return candidates[index+1];
|
|
}
|
|
},
|
|
_addChildren: function(container,parent,children,depth) {
|
|
var that = this;
|
|
var subtree = $('<ol>').appendTo(container).editableList({
|
|
addButton: false,
|
|
scrollOnAdd: false,
|
|
height: 'auto',
|
|
addItem: function(container,i,item) {
|
|
that._addSubtree(subtree,container,item,depth+1);
|
|
}
|
|
});
|
|
for (var i=0;i<children.length;i++) {
|
|
children[i].parent = parent;
|
|
subtree.editableList('addItem',children[i])
|
|
}
|
|
return subtree;
|
|
},
|
|
_addSubtree: function(parentList, container, item, depth) {
|
|
var that = this;
|
|
item.treeList = {};
|
|
item.treeList.container = container;
|
|
|
|
item.treeList.parentList = parentList;
|
|
item.treeList.remove = function() {
|
|
parentList.editableList('removeItem',item);
|
|
if (item.parent) {
|
|
var index = item.parent.children.indexOf(item);
|
|
item.parent.children.splice(index,1)
|
|
}
|
|
}
|
|
var labelNodeType = "<div>";
|
|
// if (item.children && item.hasOwnProperty('selected')) {
|
|
// labelNodeType = "<div>";
|
|
// }
|
|
var label = $(labelNodeType,{class:"red-ui-treeList-label"}).appendTo(container);
|
|
item.treeList.label = label;
|
|
if (item.class) {
|
|
label.addClass(item.class);
|
|
}
|
|
label.css({
|
|
paddingLeft: (depth*15)+'px'
|
|
})
|
|
label.on('mouseover',function(e) { that._trigger('itemmouseover',e,item); })
|
|
label.on('mouseout',function(e) { that._trigger('itemmouseout',e,item); })
|
|
label.on('mouseenter',function(e) { that._trigger('itemmouseenter',e,item); })
|
|
label.on('mouseleave',function(e) { that._trigger('itemmouseleave',e,item); })
|
|
|
|
if (item.children) {
|
|
item.treeList.addChild = function(newItem,select) {
|
|
item.treeList.childList.editableList('addItem',newItem)
|
|
newItem.parent = item;
|
|
item.children.push(newItem);
|
|
if (select) {
|
|
setTimeout(function() {
|
|
that.select(newItem)
|
|
},100);
|
|
}
|
|
}
|
|
item.treeList.expand = function(done) {
|
|
if (container.hasClass("expanded")) {
|
|
done && done();
|
|
return;
|
|
}
|
|
if (!container.hasClass("built") && typeof item.children === 'function') {
|
|
container.addClass('built');
|
|
var childrenAdded = false;
|
|
var spinner;
|
|
var startTime = 0;
|
|
item.children(item,function(children) {
|
|
childrenAdded = true;
|
|
item.treeList.childList = that._addChildren(container,item,children,depth).hide();
|
|
var delta = Date.now() - startTime;
|
|
if (delta < 400) {
|
|
setTimeout(function() {
|
|
item.treeList.childList.slideDown('fast');
|
|
if (spinner) {
|
|
spinner.remove();
|
|
}
|
|
},400-delta);
|
|
} else {
|
|
item.treeList.childList.slideDown('fast');
|
|
if (spinner) {
|
|
spinner.remove();
|
|
}
|
|
}
|
|
done && done();
|
|
that._trigger("childrenloaded",null,item)
|
|
});
|
|
if (!childrenAdded) {
|
|
startTime = Date.now();
|
|
spinner = $('<div class="red-ui-treeList-spinner">').css({
|
|
"background-position": (35+depth*15)+'px 50%'
|
|
}).appendTo(container);
|
|
}
|
|
|
|
} else {
|
|
item.treeList.childList.slideDown('fast');
|
|
done && done();
|
|
}
|
|
container.addClass("expanded");
|
|
}
|
|
item.treeList.collapse = function() {
|
|
item.treeList.childList.slideUp('fast');
|
|
container.removeClass("expanded");
|
|
}
|
|
|
|
$('<span class="red-ui-treeList-icon"><i class="fa fa-angle-right" /></span>').appendTo(label);
|
|
// $('<span class="red-ui-treeList-icon"><i class="fa fa-folder-o" /></span>').appendTo(label);
|
|
label.on("click", function(e) {
|
|
if (container.hasClass("expanded")) {
|
|
if (item.hasOwnProperty('selected') || label.hasClass("selected")) {
|
|
item.treeList.collapse();
|
|
}
|
|
} else {
|
|
item.treeList.expand();
|
|
}
|
|
})
|
|
} else {
|
|
$('<span class="red-ui-treeList-icon"></span>').appendTo(label);
|
|
}
|
|
if (item.hasOwnProperty('selected')) {
|
|
var selectWrapper = $('<span class="red-ui-treeList-icon"></span>').appendTo(label);
|
|
var cb = $('<input type="checkbox">').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 {
|
|
label.on("click", function(e) {
|
|
that._topList.find(".selected").removeClass("selected");
|
|
label.addClass("selected");
|
|
that._trigger("select",e,item)
|
|
})
|
|
}
|
|
if (item.icon) {
|
|
$('<span class="red-ui-treeList-icon"><i class="'+item.icon+'" /></span>').appendTo(label);
|
|
}
|
|
if (item.label) {
|
|
$('<span class="red-ui-treeList-label-text"></span>').text(item.label).appendTo(label);
|
|
} else if (item.element) {
|
|
$(item.element).appendTo(label);
|
|
}
|
|
if (item.children) {
|
|
if (Array.isArray(item.children)) {
|
|
item.treeList.childList = that._addChildren(container,item,item.children,depth).hide();
|
|
}
|
|
if (item.expanded) {
|
|
item.treeList.expand();
|
|
}
|
|
}
|
|
},
|
|
empty: function() {
|
|
this._topList.editableList('empty');
|
|
},
|
|
data: function(items) {
|
|
if (items !== undefined) {
|
|
this._data = items;
|
|
this._topList.editableList('empty');
|
|
for (var i=0; i<items.length;i++) {
|
|
this._topList.editableList('addItem',items[i]);
|
|
}
|
|
this._trigger("select")
|
|
|
|
} else {
|
|
return this._data;
|
|
}
|
|
},
|
|
show: function(id) {
|
|
for (var i=0;i<this._data.length;i++) {
|
|
if (this._data[i].id === id) {
|
|
this._topList.editableList('show',this._data[i]);
|
|
}
|
|
}
|
|
},
|
|
select: function(item) {
|
|
this._topList.find(".selected").removeClass("selected");
|
|
item.treeList.label.addClass("selected");
|
|
this._trigger("select",null,item)
|
|
|
|
},
|
|
selected: function() {
|
|
var s = this._topList.find(".selected").parent().data('data');
|
|
return s;
|
|
}
|
|
});
|
|
|
|
})(jQuery);
|