From 73574d62939fe05b4d52014b8532f864c35f4582 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 7 Nov 2016 21:25:09 +0000 Subject: [PATCH] Add quick-add node mode with cmd/ctrl-click --- Gruntfile.js | 1 + editor/js/nodes.js | 3 + editor/js/ui/palette-editor.js | 2 + editor/js/ui/search.js | 2 + editor/js/ui/typeSearch.js | 271 ++++++++++++++++++++++++++++++++ editor/js/ui/view.js | 217 +++++++++++++++---------- editor/sass/editor.scss | 7 +- editor/sass/flow.scss | 12 ++ editor/sass/mixins.scss | 9 ++ editor/sass/palette-editor.scss | 7 +- editor/sass/search.scss | 63 ++++++++ editor/sass/sidebar.scss | 7 +- 12 files changed, 501 insertions(+), 100 deletions(-) create mode 100644 editor/js/ui/typeSearch.js diff --git a/Gruntfile.js b/Gruntfile.js index abe69aadd..ffb1df3c3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -132,6 +132,7 @@ module.exports = function(grunt) { "editor/js/ui/library.js", "editor/js/ui/notifications.js", "editor/js/ui/search.js", + "editor/js/ui/typeSearch.js", "editor/js/ui/subflow.js", "editor/js/ui/touch/radialMenu.js" ], diff --git a/editor/js/nodes.js b/editor/js/nodes.js index 732c339de..49bd29860 100644 --- a/editor/js/nodes.js +++ b/editor/js/nodes.js @@ -62,6 +62,9 @@ RED.nodes = (function() { getNodeList: function() { return nodeList; }, + getNodeTypes: function() { + return Object.keys(nodeDefinitions); + }, setNodeList: function(list) { nodeList = []; for(var i=0;i scrollHeight) { + scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-10)},50); + } else if (y<0) { + scrollWindow.animate({scrollTop: '+='+(y-10)},50); + } + } + } + + function createDialog() { + //shade = $('
',{class:"red-ui-type-search-shade"}).appendTo("#main-container"); + dialog = $("
",{id:"red-ui-type-search",class:"red-ui-search red-ui-type-search"}).appendTo("#main-container"); + var searchDiv = $("
",{class:"red-ui-search-container"}).appendTo(dialog); + searchInput = $('').appendTo(searchDiv).searchBox({ + 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 = $("
",{class:"red-ui-search-results-container"}).appendTo(dialog); + searchResults = $('
    ',{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; + } + + return (activeFilter==="")||(data.index.indexOf(activeFilter) > -1); + }, + addItem: function(container,i,object) { + var def = object.def; + object.index = object.type.toLowerCase(); + var div = $('',{href:'#',class:"red-ui-search-result"}).appendTo(container); + + var nodeDiv = $('
    ',{class:"red-ui-search-result-node"}).appendTo(div); + var colour = def.color; + var icon_url = "arrow-in.png"; + if (def.category === 'config') { + icon_url = "cog.png"; + } else { + try { + icon_url = (typeof def.icon === "function" ? def.icon.call({}) : def.icon); + } catch(err) { + console.log("Definition error: "+object.type+".icon",err); + } + } + nodeDiv.css('backgroundColor',colour); + + var iconContainer = $('
    ',{class:"palette_icon_container"}).appendTo(nodeDiv); + $('
    ',{class:"palette_icon",style:"background-image: url(icons/"+icon_url+")"}).appendTo(iconContainer); + + var contentDiv = $('
    ',{class:"red-ui-search-result-description"}).appendTo(div); + + var label = object.type; + if (typeof def.paletteLabel !== "undefined") { + try { + label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||""; + label += " ("+object.type+")"; + object.index += "|"+label.toLowerCase(); + } catch(err) { + console.log("Definition error: "+object.type+".paletteLabel",err); + } + } + + + $('
    ',{class:"red-ui-search-result-node-label"}).html(label).appendTo(contentDiv); + + div.click(function(evt) { + evt.preventDefault(); + confirm(object); + }); + }, + scrollOnAdd: false + }); + + } + function confirm(def) { + hide(); + 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); + } + } + function show(opts) { + if (!visible) { + RED.keyboard.add("*",/* ESCAPE */ 27,function(){hide();d3.event.preventDefault();}); + 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; + RED.events.emit("type-search:open"); + //shade.show(); + dialog.css({left:opts.x+"px",top:opts.y+"px"}).show(); + searchResultsDiv.slideDown(); + setTimeout(function() { + searchInput.focus(); + },100); + } + function hide(fast) { + if (visible) { + RED.keyboard.remove(/* ESCAPE */ 27); + 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'); + } + } + function refreshTypeList() { + searchResults.editableList('empty'); + searchInput.searchBox('value',''); + selected = -1; + searchResults.parent().scrollTop(0); + var common = { + "debug" : false, + "inject" : false, + "function": false + }; + var nodeTypes = RED.nodes.registry.getNodeTypes().filter(function(n) { + if (common.hasOwnProperty(n)) { + common[n] = true; + return false; + } + return true; + }); + // Just in case a core node has been disabled + if (common["function"]) { + nodeTypes.unshift("function"); + } + if (common["inject"]) { + nodeTypes.unshift("inject"); + } + if (common["debug"]) { + nodeTypes.unshift("debug"); + } + + + var i; + for (i=0;i