2016-11-07 22:25:09 +01:00
|
|
|
RED.typeSearch = (function() {
|
|
|
|
|
|
|
|
var shade;
|
|
|
|
|
|
|
|
var disabled = false;
|
|
|
|
var dialog = null;
|
|
|
|
var searchInput;
|
|
|
|
var searchResults;
|
|
|
|
var searchResultsDiv;
|
|
|
|
var selected = -1;
|
|
|
|
var visible = false;
|
|
|
|
|
|
|
|
var activeFilter = "";
|
|
|
|
var addCallback;
|
2018-01-14 00:46:16 +01:00
|
|
|
var cancelCallback;
|
2016-11-07 22:25:09 +01:00
|
|
|
|
2016-11-22 23:57:05 +01:00
|
|
|
var typesUsed = {};
|
|
|
|
|
2016-11-07 22:25:09 +01:00
|
|
|
function search(val) {
|
|
|
|
activeFilter = val.toLowerCase();
|
|
|
|
var visible = searchResults.editableList('filter');
|
2018-01-23 16:40:41 +01:00
|
|
|
searchResults.editableList('sort');
|
2016-11-07 22:25:09 +01:00
|
|
|
setTimeout(function() {
|
|
|
|
selected = 0;
|
|
|
|
searchResults.children().removeClass('selected');
|
|
|
|
searchResults.children(":visible:first").addClass('selected');
|
|
|
|
},100);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function ensureSelectedIsVisible() {
|
|
|
|
var selectedEntry = searchResults.find("li.selected");
|
|
|
|
if (selectedEntry.length === 1) {
|
|
|
|
var scrollWindow = searchResults.parent();
|
|
|
|
var scrollHeight = scrollWindow.height();
|
|
|
|
var scrollOffset = scrollWindow.scrollTop();
|
|
|
|
var y = selectedEntry.position().top;
|
|
|
|
var h = selectedEntry.height();
|
|
|
|
if (y+h > scrollHeight) {
|
|
|
|
scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-10)},50);
|
|
|
|
} else if (y<0) {
|
|
|
|
scrollWindow.animate({scrollTop: '+='+(y-10)},50);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function createDialog() {
|
|
|
|
//shade = $('<div>',{class:"red-ui-type-search-shade"}).appendTo("#main-container");
|
|
|
|
dialog = $("<div>",{id:"red-ui-type-search",class:"red-ui-search red-ui-type-search"}).appendTo("#main-container");
|
|
|
|
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
|
2017-01-01 23:14:33 +01:00
|
|
|
searchInput = $('<input type="text">').attr("placeholder",RED._("search.addNode")).appendTo(searchDiv).searchBox({
|
2016-11-07 22:25:09 +01:00
|
|
|
delay: 50,
|
|
|
|
change: function() {
|
|
|
|
search($(this).val());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
searchInput.on('keydown',function(evt) {
|
|
|
|
var children = searchResults.children(":visible");
|
|
|
|
if (children.length > 0) {
|
|
|
|
if (evt.keyCode === 40) {
|
|
|
|
// Down
|
|
|
|
if (selected < children.length-1) {
|
|
|
|
if (selected > -1) {
|
|
|
|
$(children[selected]).removeClass('selected');
|
|
|
|
}
|
|
|
|
selected++;
|
|
|
|
}
|
|
|
|
$(children[selected]).addClass('selected');
|
|
|
|
ensureSelectedIsVisible();
|
|
|
|
evt.preventDefault();
|
|
|
|
} else if (evt.keyCode === 38) {
|
|
|
|
// Up
|
|
|
|
if (selected > 0) {
|
|
|
|
if (selected < children.length) {
|
|
|
|
$(children[selected]).removeClass('selected');
|
|
|
|
}
|
|
|
|
selected--;
|
|
|
|
}
|
|
|
|
$(children[selected]).addClass('selected');
|
|
|
|
ensureSelectedIsVisible();
|
|
|
|
evt.preventDefault();
|
|
|
|
} else if (evt.keyCode === 13) {
|
|
|
|
// Enter
|
|
|
|
var index = Math.max(0,selected);
|
|
|
|
if (index < children.length) {
|
|
|
|
// TODO: dips into editableList impl details
|
|
|
|
confirm($(children[index]).find(".red-ui-editableList-item-content").data('data'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
searchResultsDiv = $("<div>",{class:"red-ui-search-results-container"}).appendTo(dialog);
|
|
|
|
searchResults = $('<ol>',{id:"search-result-list", style:"position: absolute;top: 0;bottom: 0;left: 0;right: 0;"}).appendTo(searchResultsDiv).editableList({
|
|
|
|
addButton: false,
|
|
|
|
filter: function(data) {
|
|
|
|
if (activeFilter === "" ) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-01-01 22:59:09 +01:00
|
|
|
if (data.recent || data.common) {
|
2016-11-22 23:57:05 +01:00
|
|
|
return false;
|
|
|
|
}
|
2016-11-07 22:25:09 +01:00
|
|
|
return (activeFilter==="")||(data.index.indexOf(activeFilter) > -1);
|
|
|
|
},
|
2018-01-23 16:40:41 +01:00
|
|
|
sort: function(A,B) {
|
|
|
|
if (activeFilter === "") {
|
|
|
|
return A.i - B.i;
|
|
|
|
}
|
|
|
|
var Ai = A.index.indexOf(activeFilter);
|
|
|
|
var Bi = B.index.indexOf(activeFilter);
|
|
|
|
if (Ai === -1) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (Bi === -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (Ai === Bi) {
|
|
|
|
return sortTypeLabels(A,B);
|
|
|
|
}
|
|
|
|
return Ai-Bi;
|
|
|
|
},
|
2016-11-07 22:25:09 +01:00
|
|
|
addItem: function(container,i,object) {
|
|
|
|
var def = object.def;
|
|
|
|
object.index = object.type.toLowerCase();
|
2016-11-22 23:57:05 +01:00
|
|
|
if (object.separator) {
|
|
|
|
container.addClass("red-ui-search-result-separator")
|
|
|
|
}
|
2016-11-07 22:25:09 +01:00
|
|
|
var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
|
|
|
|
|
|
|
|
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
|
2018-07-27 23:05:28 +02:00
|
|
|
var colour = RED.utils.getNodeColor(object.type,def);
|
2017-01-18 14:06:22 +01:00
|
|
|
var icon_url = RED.utils.getNodeIcon(def);
|
2016-11-07 22:25:09 +01:00
|
|
|
nodeDiv.css('backgroundColor',colour);
|
|
|
|
|
|
|
|
var iconContainer = $('<div/>',{class:"palette_icon_container"}).appendTo(nodeDiv);
|
2017-01-18 14:06:22 +01:00
|
|
|
$('<div/>',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
|
2016-11-07 22:25:09 +01:00
|
|
|
|
2016-11-22 23:57:05 +01:00
|
|
|
if (def.inputs > 0) {
|
|
|
|
$('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
|
2016-11-07 22:25:09 +01:00
|
|
|
}
|
2016-11-22 23:57:05 +01:00
|
|
|
if (def.outputs > 0) {
|
|
|
|
$('<div/>',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
|
|
|
|
}
|
|
|
|
|
|
|
|
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
|
2016-11-07 22:25:09 +01:00
|
|
|
|
2016-11-22 23:57:05 +01:00
|
|
|
var label = object.label;
|
|
|
|
object.index += "|"+label.toLowerCase();
|
2016-11-07 22:25:09 +01:00
|
|
|
|
2018-05-11 15:05:52 +02:00
|
|
|
$('<div>',{class:"red-ui-search-result-node-label"}).text(label).appendTo(contentDiv);
|
2016-11-07 22:25:09 +01:00
|
|
|
|
|
|
|
div.click(function(evt) {
|
|
|
|
evt.preventDefault();
|
|
|
|
confirm(object);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
scrollOnAdd: false
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
function confirm(def) {
|
|
|
|
hide();
|
2016-11-22 23:57:05 +01:00
|
|
|
typesUsed[def.type] = Date.now();
|
2016-11-07 22:25:09 +01:00
|
|
|
addCallback(def.type);
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleMouseActivity(evt) {
|
|
|
|
if (visible) {
|
|
|
|
var t = $(evt.target);
|
|
|
|
while (t.prop('nodeName').toLowerCase() !== 'body') {
|
|
|
|
if (t.attr('id') === 'red-ui-type-search') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
t = t.parent();
|
|
|
|
}
|
|
|
|
hide(true);
|
2018-01-14 00:46:16 +01:00
|
|
|
if (cancelCallback) {
|
|
|
|
cancelCallback();
|
|
|
|
}
|
2016-11-07 22:25:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
function show(opts) {
|
|
|
|
if (!visible) {
|
2018-01-14 00:46:16 +01:00
|
|
|
RED.keyboard.add("*","escape",function(){
|
|
|
|
hide();
|
|
|
|
if (cancelCallback) {
|
|
|
|
cancelCallback();
|
|
|
|
}
|
|
|
|
});
|
2016-11-07 22:25:09 +01:00
|
|
|
if (dialog === null) {
|
|
|
|
createDialog();
|
|
|
|
}
|
|
|
|
visible = true;
|
|
|
|
setTimeout(function() {
|
|
|
|
$(document).on('mousedown.type-search',handleMouseActivity);
|
|
|
|
$(document).on('mouseup.type-search',handleMouseActivity);
|
|
|
|
$(document).on('click.type-search',handleMouseActivity);
|
|
|
|
},200);
|
|
|
|
} else {
|
|
|
|
dialog.hide();
|
|
|
|
searchResultsDiv.hide();
|
|
|
|
}
|
|
|
|
refreshTypeList();
|
|
|
|
addCallback = opts.add;
|
2018-01-14 00:46:16 +01:00
|
|
|
closeCallback = opts.close;
|
2016-11-07 22:25:09 +01:00
|
|
|
RED.events.emit("type-search:open");
|
|
|
|
//shade.show();
|
|
|
|
dialog.css({left:opts.x+"px",top:opts.y+"px"}).show();
|
2017-01-09 23:08:54 +01:00
|
|
|
searchResultsDiv.slideDown(300);
|
2016-11-07 22:25:09 +01:00
|
|
|
setTimeout(function() {
|
2016-11-08 22:18:34 +01:00
|
|
|
searchResultsDiv.find(".red-ui-editableList-container").scrollTop(0);
|
2016-11-07 22:25:09 +01:00
|
|
|
searchInput.focus();
|
|
|
|
},100);
|
|
|
|
}
|
|
|
|
function hide(fast) {
|
|
|
|
if (visible) {
|
2016-12-04 23:59:43 +01:00
|
|
|
RED.keyboard.remove("escape");
|
2016-11-07 22:25:09 +01:00
|
|
|
visible = false;
|
|
|
|
if (dialog !== null) {
|
|
|
|
searchResultsDiv.slideUp(fast?50:200,function() {
|
|
|
|
dialog.hide();
|
|
|
|
searchInput.searchBox('value','');
|
|
|
|
});
|
|
|
|
//shade.hide();
|
|
|
|
}
|
|
|
|
RED.events.emit("type-search:close");
|
|
|
|
RED.view.focus();
|
|
|
|
$(document).off('mousedown.type-search');
|
|
|
|
$(document).off('mouseup.type-search');
|
|
|
|
$(document).off('click.type-search');
|
|
|
|
}
|
|
|
|
}
|
2016-11-22 23:57:05 +01:00
|
|
|
|
|
|
|
function getTypeLabel(type, def) {
|
|
|
|
var label = type;
|
|
|
|
if (typeof def.paletteLabel !== "undefined") {
|
|
|
|
try {
|
|
|
|
label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||"";
|
|
|
|
label += " ("+type+")";
|
|
|
|
} catch(err) {
|
|
|
|
console.log("Definition error: "+type+".paletteLabel",err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return label;
|
|
|
|
}
|
2018-01-23 16:40:41 +01:00
|
|
|
function sortTypeLabels(a,b) {
|
|
|
|
var al = a.label.toLowerCase();
|
|
|
|
var bl = b.label.toLowerCase();
|
|
|
|
if (al < bl) {
|
|
|
|
return -1;
|
|
|
|
} else if (al === bl) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2016-11-07 22:25:09 +01:00
|
|
|
function refreshTypeList() {
|
2016-11-22 23:57:05 +01:00
|
|
|
var i;
|
2016-11-07 22:25:09 +01:00
|
|
|
searchResults.editableList('empty');
|
|
|
|
searchInput.searchBox('value','');
|
|
|
|
selected = -1;
|
2016-11-22 23:57:05 +01:00
|
|
|
var common = [
|
2017-01-09 17:41:16 +01:00
|
|
|
'inject','debug','function','change','switch'
|
2016-11-22 23:57:05 +01:00
|
|
|
];
|
2016-11-07 22:25:09 +01:00
|
|
|
|
2016-11-22 23:57:05 +01:00
|
|
|
var recentlyUsed = Object.keys(typesUsed);
|
|
|
|
recentlyUsed.sort(function(a,b) {
|
|
|
|
return typesUsed[b]-typesUsed[a];
|
|
|
|
});
|
|
|
|
recentlyUsed = recentlyUsed.filter(function(t) {
|
|
|
|
return common.indexOf(t) === -1;
|
|
|
|
});
|
2016-11-07 22:25:09 +01:00
|
|
|
|
2016-11-22 23:57:05 +01:00
|
|
|
var items = [];
|
|
|
|
RED.nodes.registry.getNodeTypes().forEach(function(t) {
|
2016-11-07 22:25:09 +01:00
|
|
|
var def = RED.nodes.getType(t);
|
2017-08-02 22:54:58 +02:00
|
|
|
if (def.category !== 'config' && t !== 'unknown' && t !== 'tab') {
|
2016-11-22 23:57:05 +01:00
|
|
|
items.push({type:t,def: def, label:getTypeLabel(t,def)});
|
2016-11-07 22:25:09 +01:00
|
|
|
}
|
2016-11-22 23:57:05 +01:00
|
|
|
});
|
2018-01-23 16:40:41 +01:00
|
|
|
items.sort(sortTypeLabels);
|
2016-11-22 23:57:05 +01:00
|
|
|
|
|
|
|
var commonCount = 0;
|
|
|
|
var item;
|
2018-01-23 16:40:41 +01:00
|
|
|
var index = 0;
|
2016-11-22 23:57:05 +01:00
|
|
|
for(i=0;i<common.length;i++) {
|
2017-10-19 14:52:25 +02:00
|
|
|
var itemDef = RED.nodes.getType(common[i]);
|
|
|
|
if (itemDef) {
|
|
|
|
item = {
|
|
|
|
type: common[i],
|
|
|
|
common: true,
|
2018-01-23 16:40:41 +01:00
|
|
|
def: itemDef,
|
|
|
|
i: index++
|
2017-10-19 14:52:25 +02:00
|
|
|
};
|
|
|
|
item.label = getTypeLabel(item.type,item.def);
|
|
|
|
if (i === common.length-1) {
|
|
|
|
item.separator = true;
|
|
|
|
}
|
|
|
|
searchResults.editableList('addItem', item);
|
2016-11-22 23:57:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for(i=0;i<Math.min(5,recentlyUsed.length);i++) {
|
|
|
|
item = {
|
|
|
|
type:recentlyUsed[i],
|
|
|
|
def: RED.nodes.getType(recentlyUsed[i]),
|
2018-01-23 16:40:41 +01:00
|
|
|
recent: true,
|
|
|
|
i: index++
|
2016-11-22 23:57:05 +01:00
|
|
|
};
|
|
|
|
item.label = getTypeLabel(item.type,item.def);
|
|
|
|
if (i === recentlyUsed.length-1) {
|
|
|
|
item.separator = true;
|
|
|
|
}
|
|
|
|
searchResults.editableList('addItem', item);
|
|
|
|
}
|
|
|
|
for (i=0;i<items.length;i++) {
|
2018-01-23 16:40:41 +01:00
|
|
|
items[i].i = index++;
|
2016-11-22 23:57:05 +01:00
|
|
|
searchResults.editableList('addItem', items[i]);
|
2016-11-07 22:25:09 +01:00
|
|
|
}
|
|
|
|
setTimeout(function() {
|
|
|
|
selected = 0;
|
|
|
|
searchResults.children(":first").addClass('selected');
|
|
|
|
},100);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
show: show,
|
|
|
|
hide: hide
|
|
|
|
};
|
|
|
|
|
|
|
|
})();
|