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; var cancelCallback; var moveCallback; var typesUsed = {}; function search(val) { activeFilter = val.toLowerCase(); var visible = searchResults.editableList('filter'); searchResults.editableList('sort'); 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 moveDialog(dx,dy) { var pos = dialog.position(); pos.top = (pos.top + dy)+"px"; pos.left = (pos.left + dx)+"px"; dialog.css(pos); moveCallback(dx,dy); } function createDialog() { dialog = $("
",{id:"red-ui-type-search",class:"red-ui-search red-ui-type-search"}).appendTo("#red-ui-main-container"); var searchDiv = $("
",{class:"red-ui-search-container"}).appendTo(dialog); searchInput = $('').attr("placeholder",RED._("search.addNode")).appendTo(searchDiv).searchBox({ delay: 50, change: function() { search($(this).val()); } }); searchInput.on('keydown',function(evt) { var children = searchResults.children(":visible"); if (evt.keyCode === 40 && evt.shiftKey) { evt.preventDefault(); moveDialog(0,10); } else if (evt.keyCode === 38 && evt.shiftKey) { evt.preventDefault(); moveDialog(0,-10); } else if (evt.keyCode === 39 && evt.shiftKey) { evt.preventDefault(); moveDialog(10,0); } else if (evt.keyCode === 37 && evt.shiftKey) { evt.preventDefault(); moveDialog(-10,0); } else 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) { if (selected > 0) { if (selected < children.length) { $(children[selected]).removeClass('selected'); } selected--; } $(children[selected]).addClass('selected'); ensureSelectedIsVisible(); evt.preventDefault(); } else if ((evt.metaKey || evt.ctrlKey) && evt.keyCode === 13 ) { evt.preventDefault(); // (ctrl or cmd) and enter var index = Math.max(0,selected); if (index < children.length) { var n = $(children[index]).find(".red-ui-editableList-item-content").data('data'); if (!/^_action_:/.test(n.type)) { typesUsed[n.type] = Date.now(); } if (n.def.outputs === 0) { confirm(n); } else { addCallback(n.type,true); } $("#red-ui-type-search-input").val("").trigger("keyup"); setTimeout(function() { $("#red-ui-type-search-input").focus(); },100); } } else if (evt.keyCode === 13) { evt.preventDefault(); // 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')); } } } else { if (evt.keyCode === 13 ) { // Stop losing focus if [Cmd]-Enter is pressed on an empty list evt.stopPropagation(); evt.preventDefault(); } } }); searchResultsDiv = $("
",{class:"red-ui-search-results-container"}).appendTo(dialog); searchResults = $('
    ',{style:"position: absolute;top: 0;bottom: 0;left: 0;right: 0;"}).appendTo(searchResultsDiv).editableList({ addButton: false, filter: function(data) { if (activeFilter === "" ) { return true; } if (data.recent || data.common) { return false; } return (activeFilter==="")||(data.index.indexOf(activeFilter) > -1); }, 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; }, addItem: function(container,i,object) { var def = object.def; object.index = object.type.toLowerCase(); if (object.separator) { container.addClass("red-ui-search-result-separator") } var div = $('
    ',{class:"red-ui-search-result"}).appendTo(container); var nodeDiv = $('
    ',{class:"red-ui-search-result-node"}).appendTo(div); if (object.type === "junction") { nodeDiv.addClass("red-ui-palette-icon-junction"); } else if (/^_action_:/.test(object.type)) { nodeDiv.addClass("red-ui-palette-icon-junction") } else { var colour = RED.utils.getNodeColor(object.type,def); nodeDiv.css('backgroundColor',colour); } var icon_url = RED.utils.getNodeIcon(def); var iconContainer = $('
    ',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv); RED.utils.createIconElement(icon_url, iconContainer, false); if (!/^_action_:/.test(object.type) && object.type !== "junction") { if (def.inputs > 0) { $('
    ',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv); } if (def.outputs > 0) { $('
    ',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv); } } var contentDiv = $('
    ',{class:"red-ui-search-result-description"}).appendTo(div); var label = object.label; object.index += "|"+label.toLowerCase(); $('
    ',{class:"red-ui-search-result-node-label"}).text(label).appendTo(contentDiv); div.on("click", function(evt) { evt.preventDefault(); confirm(object); }); }, scrollOnAdd: false }); } function confirm(def) { hide(); if (!/^_action_:/.test(def.type)) { typesUsed[def.type] = Date.now(); } 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); if (cancelCallback) { cancelCallback(); } } } function show(opts) { if (!visible) { if (dialog === null) { createDialog(); RED.keyboard.add("red-ui-type-search","escape",function(){ hide(); if (cancelCallback) { cancelCallback(); } }); } visible = true; } else { dialog.hide(); searchResultsDiv.hide(); } $(document).off('mousedown.red-ui-type-search'); $(document).off('mouseup.red-ui-type-search'); $(document).off('click.red-ui-type-search'); $(document).off('touchstart.red-ui-type-search'); $(document).off('mousedown.red-ui-type-search'); setTimeout(function() { $(document).on('mousedown.red-ui-type-search',handleMouseActivity); $(document).on('mouseup.red-ui-type-search',handleMouseActivity); $(document).on('click.red-ui-type-search',handleMouseActivity); $(document).on('touchstart.red-ui-type-search',handleMouseActivity); },200); refreshTypeList(opts); addCallback = opts.add; cancelCallback = opts.cancel; moveCallback = opts.move; RED.events.emit("type-search:open"); //shade.show(); if ($("#red-ui-main-container").height() - opts.y - 195 < 0) { opts.y = opts.y - 275; } dialog.css({left:opts.x+"px",top:opts.y+"px"}).show(); searchResultsDiv.slideDown(300); setTimeout(function() { searchResultsDiv.find(".red-ui-editableList-container").scrollTop(0); if (!opts.disableFocus) { searchInput.trigger("focus"); } },200); } function hide(fast) { if (visible) { 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.red-ui-type-search'); $(document).off('mouseup.red-ui-type-search'); $(document).off('click.red-ui-type-search'); $(document).off('touchstart.red-ui-type-search'); } } 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; } 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; } } function applyFilter(filter,type,def) { return !filter || ( (!filter.spliceMultiple) && (!filter.type || type === filter.type) && (!filter.input || type === 'junction' || def.inputs > 0) && (!filter.output || type === 'junction' || def.outputs > 0) ) } function refreshTypeList(opts) { var i; searchResults.editableList('empty'); searchInput.searchBox('value','').focus(); selected = -1; var common = [ 'inject','debug','function','change','switch','junction' ].filter(function(t) { return applyFilter(opts.filter,t,RED.nodes.getType(t)); }); // if (opts.filter && opts.filter.input && opts.filter.output && !opts.filter.type) { // if (opts.filter.spliceMultiple) { // common.push('_action_:core:split-wires-with-junctions') // } // common.push('_action_:core:split-wire-with-link-nodes') // } var recentlyUsed = Object.keys(typesUsed); recentlyUsed.sort(function(a,b) { return typesUsed[b]-typesUsed[a]; }); recentlyUsed = recentlyUsed.filter(function(t) { return applyFilter(opts.filter,t,RED.nodes.getType(t)) && common.indexOf(t) === -1; }); var items = []; RED.nodes.registry.getNodeTypes().forEach(function(t) { var def = RED.nodes.getType(t); if (def.category !== 'config' && t !== 'unknown' && t !== 'tab') { items.push({type:t,def: def, label:getTypeLabel(t,def)}); } }); items.push({ type: 'junction', def: { inputs:1, outputs: 1, label: 'junction', type: 'junction'}, label: 'junction' }) items.sort(sortTypeLabels); var commonCount = 0; var item; var index = 0; for(i=0;i