From da818cf420d249c3bcc0fd20d7ffa951ced0acc7 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 27 Jul 2016 22:25:18 +0100 Subject: [PATCH 01/12] Add initial palette sidebar --- Gruntfile.js | 1 + editor/js/ui/sidebar.js | 1 + red/api/locales/en-US/editor.json | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/Gruntfile.js b/Gruntfile.js index 95c8d6989..597337ae5 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -119,6 +119,7 @@ module.exports = function(grunt) { "editor/js/ui/palette.js", "editor/js/ui/tab-info.js", "editor/js/ui/tab-config.js", + "editor/js/ui/tab-palette.js", "editor/js/ui/editor.js", "editor/js/ui/tray.js", "editor/js/ui/clipboard.js", diff --git a/editor/js/ui/sidebar.js b/editor/js/ui/sidebar.js index 9a3e75dae..56d9e8b46 100644 --- a/editor/js/ui/sidebar.js +++ b/editor/js/ui/sidebar.js @@ -206,6 +206,7 @@ RED.sidebar = (function() { showSidebar(); RED.sidebar.info.init(); RED.sidebar.config.init(); + RED.sidebar.palette.init(); // hide info bar at start if screen rather narrow... if ($(window).width() < 600) { toggleSidebar(); } } diff --git a/red/api/locales/en-US/editor.json b/red/api/locales/en-US/editor.json index 75d1dc8ce..cff8f3e43 100644 --- a/red/api/locales/en-US/editor.json +++ b/red/api/locales/en-US/editor.json @@ -225,6 +225,10 @@ "filterUnused":"unused", "filterAll":"all", "filtered": "__count__ hidden" + }, + "palette": { + "name": "Palette management", + "label": "palette" } }, "typedInput": { From 7220af3ef02e89969522268ba99844486f97a52e Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 4 Aug 2016 16:49:36 +0100 Subject: [PATCH 02/12] Move palette editor to left hand side --- Gruntfile.js | 2 +- editor/js/main.js | 6 +- editor/js/nodes.js | 65 ++-- editor/js/ui/editableList.js | 32 +- editor/js/ui/palette-editor.js | 317 ++++++++++++++++++ editor/js/ui/palette.js | 45 +++ editor/js/ui/sidebar.js | 1 - editor/js/ui/tray.js | 2 + editor/sass/editor.scss | 2 +- editor/sass/mixins.scss | 15 +- editor/sass/palette-editor.scss | 158 +++++++++ editor/sass/palette.scss | 21 +- editor/sass/style.scss | 2 + editor/sass/workspace.scss | 2 + editor/templates/index.mst | 34 +- red/runtime/nodes/registry/loader.js | 3 +- red/runtime/nodes/registry/localfilesystem.js | 5 +- red/runtime/nodes/registry/registry.js | 6 +- 18 files changed, 657 insertions(+), 61 deletions(-) create mode 100644 editor/js/ui/palette-editor.js create mode 100644 editor/sass/palette-editor.scss diff --git a/Gruntfile.js b/Gruntfile.js index 597337ae5..ca01292f8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -119,7 +119,7 @@ module.exports = function(grunt) { "editor/js/ui/palette.js", "editor/js/ui/tab-info.js", "editor/js/ui/tab-config.js", - "editor/js/ui/tab-palette.js", + "editor/js/ui/palette-editor.js", "editor/js/ui/editor.js", "editor/js/ui/tray.js", "editor/js/ui/clipboard.js", diff --git a/editor/js/main.js b/editor/js/main.js index 3e1b55761..06fd8cf9f 100644 --- a/editor/js/main.js +++ b/editor/js/main.js @@ -56,11 +56,9 @@ var RED = (function() { success: function(data) { $("body").append(data); $("body").i18n(); - - $(".palette-spinner").hide(); - $(".palette-scroll").show(); - $("#palette-search").show(); + $(".palette-scroll").removeClass("hide"); + $("#palette-search").removeClass("hide"); loadFlows(); } }); diff --git a/editor/js/nodes.js b/editor/js/nodes.js index 32085802c..8a6a50c03 100644 --- a/editor/js/nodes.js +++ b/editor/js/nodes.js @@ -32,12 +32,22 @@ RED.nodes = (function() { } var registry = (function() { + var moduleList = {}; var nodeList = []; var nodeSets = {}; var typeToId = {}; var nodeDefinitions = {}; var exports = { + getModule: function(module) { + return moduleList[module]; + }, + getNodeSetForType: function(nodeType) { + return exports.getNodeSet(typeToId[nodeType]); + }, + getModuleList: function() { + return moduleList; + }, getNodeList: function() { return nodeList; }, @@ -55,27 +65,38 @@ RED.nodes = (function() { typeToId[ns.types[j]] = ns.id; } nodeList.push(ns); + + moduleList[ns.module] = moduleList[ns.module] || { + name:ns.module, + version:ns.version, + local:ns.local, + sets:{} + }; + moduleList[ns.module].sets[ns.name] = ns; + RED.events.emit("registry:node-set-added",ns); }, removeNodeSet: function(id) { var ns = nodeSets[id]; for (var j=0;j').appendTo(this.element); + var li = $('
  • '); + var added = false; + if (this.options.sort) { + var items = this.items(); + var skip = false; + items.each(function(i,el) { + if (added) { return } + var itemData = el.data('data'); + if (that.options.sort(data,itemData) < 0) { + li.insertBefore(el.closest("li")); + added = true; + } + }); + } + if (!added) { + li.appendTo(this.element); + } var row = $('
    ').addClass("red-ui-editableList-item-content").appendTo(li); row.data('data',data); if (this.options.sortable === true) { diff --git a/editor/js/ui/palette-editor.js b/editor/js/ui/palette-editor.js new file mode 100644 index 000000000..310e07539 --- /dev/null +++ b/editor/js/ui/palette-editor.js @@ -0,0 +1,317 @@ +/** + * Copyright 2016 IBM Corp. + * + * 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.palette.editor = (function() { + + var nodeList; + var typesInUse = {}; + + var nodeEntries = {}; + + var eventTimers = {}; + + function changeNodeState(id,state,callback) { + $.ajax({ + url:"nodes/"+id, + type: "PUT", + data: JSON.stringify({ + enabled: state + }), + contentType: "application/json; charset=utf-8" + }).done(function(data,textStatus,xhr) { + callback(); + }).fail(function(xhr,textStatus,err) { + callback(xhr); + }) + } + function refreshNodeModule(module) { + if (!eventTimers.hasOwnProperty(module)) { + eventTimers[module] = setTimeout(function() { + delete eventTimers[module]; + _refreshNodeModule(module); + },100); + } + } + + + function getContrastingBorder(rgbColor){ + var parts = /^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)[,)]/.exec(rgbColor); + if (parts) { + var r = parseInt(parts[1]); + var g = parseInt(parts[2]); + var b = parseInt(parts[3]); + var yiq = ((r*299)+(g*587)+(b*114))/1000; + if (yiq > 160) { + r = Math.floor(r*0.8); + g = Math.floor(g*0.8); + b = Math.floor(b*0.8); + return "rgb("+r+","+g+","+b+")"; + } + } + return rgbColor; + } + + + function _refreshNodeModule(module) { + if (!nodeEntries.hasOwnProperty(module)) { + nodeEntries[module] = {info:RED.nodes.registry.getModule(module)}; + nodeList.editableList('addItem', nodeEntries[module]); + //console.log(nodeList.editableList('items')); + + } else { + var moduleInfo = nodeEntries[module].info; + var nodeEntry = nodeEntries[module].elements; + if (nodeEntry) { + var activeTypeCount = 0; + var typeCount = 0; + nodeEntries[module].totalUseCount = 0; + nodeEntries[module].setUseCount = {}; + + for (var setName in moduleInfo.sets) { + if (moduleInfo.sets.hasOwnProperty(setName)) { + var inUseCount = 0; + var set = moduleInfo.sets[setName]; + var setElements = nodeEntry.sets[setName]; + + if (set.enabled) { + activeTypeCount += set.types.length; + } + typeCount += set.types.length; + for (var i=0;i 0) { + setElements.enableButton.html('in use'); + setElements.enableButton.addClass('disabled'); + } else { + setElements.enableButton.removeClass('disabled'); + if (set.enabled) { + setElements.enableButton.html('disable'); + } else { + setElements.enableButton.html('enable'); + } + } + setElements.setRow.toggleClass("palette-module-set-disabled",!set.enabled); + } + } + var nodeCount = (activeTypeCount === typeCount)?typeCount:activeTypeCount+" / "+typeCount; + nodeEntry.setCount.html(nodeCount+" node"+(typeCount>1?"s":"")); + + if (nodeEntries[module].totalUseCount > 0) { + nodeEntry.enableButton.html("in use"); + nodeEntry.enableButton.addClass('disabled'); + nodeEntry.removeButton.hide(); + } else { + nodeEntry.enableButton.removeClass('disabled'); + nodeEntry.removeButton.show(); + if (activeTypeCount === 0) { + nodeEntry.enableButton.html("enable all"); + } else { + nodeEntry.enableButton.html("disable all"); + } + nodeEntry.container.toggleClass("disabled",(activeTypeCount === 0)); + } + } + } + + } + function showPaletteEditor() { + $("#header-shade").show(); + $("#editor-shade").show(); + $("#sidebar-shade").show(); + $("#main-container").addClass("palette-expanded"); + } + function hidePaletteEditor() { + $("#main-container").removeClass("palette-expanded"); + $("#header-shade").hide(); + $("#editor-shade").hide(); + $("#sidebar-shade").hide(); + } + + function init() { + $("#editor-shade").click(function() { + if ($("#main-container").hasClass("palette-expanded")) { + hidePaletteEditor(); + } + }); + $("#palette-edit").on("click",function(e) { + if ($("#main-container").hasClass("palette-expanded")) { + hidePaletteEditor(); + } else { + showPaletteEditor(); + } + }); + $("#palette-editor-close").on("click", function(e) { + hidePaletteEditor(); + }) + + var divTabs = $('
    ',{style:"position:absolute;top:80px;left:0;right:0;bottom:0"}).appendTo("#palette-editor"); + + nodeList = $('
      ',{id:"palette-module-list", style:"position: absolute;top: 0;bottom: 0;left: 0;right: 0px;"}).appendTo(divTabs).editableList({ + addButton: false, + sort: function(A,B) { + return A.info.name.localeCompare(B.info.name); + }, + addItem: function(container,i,object) { + var entry = object.info; + + var headerRow = $('
      ',{class:"palette-module-header"}).appendTo(container); + + var titleRow = $('
      ',{class:"palette-module-meta"}).appendTo(headerRow); + var chevron = $('').appendTo(titleRow); + var title = $('',{class:"palette-module-name"}).html(entry.name).appendTo(titleRow); + + var metaRow = $('
      ',{class:"palette-module-meta"}).appendTo(headerRow); + var version = $('').appendTo(metaRow); + $('').html(entry.version).appendTo(version); + + + var buttonRow = $('
      ',{class:"palette-module-meta"}).appendTo(headerRow); + + var setButton = $(' ').appendTo(buttonRow); + var setCount = $('').appendTo(setButton); + + var buttonGroup = $('
      ',{class:"palette-module-button-group"}).appendTo(buttonRow); + var removeButton = $('').html('remove').appendTo(buttonGroup); + if (!entry.local) { + removeButton.hide(); + } + var enableButton = $('').html('disable all').appendTo(buttonGroup); + + var contentRow = $('
      ',{class:"palette-module-content"}).appendTo(container); + + object.elements = { + removeButton: removeButton, + enableButton: enableButton, + setCount: setCount, + container: container, + sets: {} + } + setButton.click(function() { + if (container.hasClass('expanded')) { + container.removeClass('expanded'); + contentRow.slideUp(); + } else { + container.addClass('expanded'); + contentRow.slideDown(); + } + }) + + var setList = Object.keys(entry.sets) + setList.sort(function(A,B) { + return A.toLowerCase().localeCompare(B.toLowerCase()); + }); + setList.forEach(function(setName) { + var set = entry.sets[setName]; + var setRow = $('
      ',{class:"palette-module-set"}).appendTo(contentRow); + var buttonGroup = $('
      ',{class:"palette-module-set-button-group"}).appendTo(setRow); + var typeSwatches = {}; + set.types.forEach(function(t) { + var typeDiv = $('
      ',{class:"palette-module-type"}).appendTo(setRow); + typeSwatches[t] = $('',{class:"palette-module-type-swatch"}).appendTo(typeDiv); + $('',{class:"palette-module-type-node"}).html(t).appendTo(typeDiv); + }) + + var enableButton = $('').appendTo(buttonGroup); + enableButton.click(function(evt) { + if (object.setUseCount[setName] === 0) { + var currentSet = RED.nodes.registry.getNodeSet(set.id); + changeNodeState(set.id,!currentSet.enabled,function(xhr){ + console.log(xhr) + }); + } + evt.preventDefault(); + }) + + object.elements.sets[set.name] = { + setRow: setRow, + enableButton: enableButton, + swatches: typeSwatches + }; + }); + enableButton.click(function(evt) { + if (object.totalUseCount === 0) { + changeNodeState(entry.name,(container.hasClass('disabled')),function(xhr){ + console.log(xhr) + }); + } + evt.preventDefault(); + }) + refreshNodeModule(entry.name); + } + }); + + RED.events.on('registry:node-set-enabled', function(ns) { + refreshNodeModule(ns.module); + }); + RED.events.on('registry:node-set-disabled', function(ns) { + refreshNodeModule(ns.module); + }); + RED.events.on('registry:node-type-added', function(nodeType) { + var ns = RED.nodes.registry.getNodeSetForType(nodeType); + refreshNodeModule(ns.module); + }); + RED.events.on('registry:node-type-removed', function(nodeType) { + var ns = RED.nodes.registry.getNodeSetForType(nodeType); + refreshNodeModule(ns.module); + }); + RED.events.on('registry:node-set-added', function(ns) { + refreshNodeModule(ns.module); + }); + RED.events.on('registry:node-set-removed', function(ns) { + refreshNodeModule(ns.module); + }); + RED.events.on('nodes:add', function(n) { + typesInUse[n.type] = (typesInUse[n.type]||0)+1; + if (typesInUse[n.type] === 1) { + var ns = RED.nodes.registry.getNodeSetForType(n.type); + refreshNodeModule(ns.module); + } + }) + RED.events.on('nodes:remove', function(n) { + if (typesInUse.hasOwnProperty(n.type)) { + typesInUse[n.type]--; + if (typesInUse[n.type] === 0) { + delete typesInUse[n.type]; + var ns = RED.nodes.registry.getNodeSetForType(n.type); + refreshNodeModule(ns.module); + } + } + }) + + + } + + return { + init: init, + } +})(); diff --git a/editor/js/ui/palette.js b/editor/js/ui/palette.js index f17889ded..86e9b8c45 100644 --- a/editor/js/ui/palette.js +++ b/editor/js/ui/palette.js @@ -393,6 +393,49 @@ RED.palette = (function() { } function init() { + + RED.events.on('registry:node-type-added', function(nodeType) { + var def = RED.nodes.getType(nodeType); + addNodeType(nodeType,def); + if (def.onpaletteadd && typeof def.onpaletteadd === "function") { + def.onpaletteadd.call(def); + } + }); + RED.events.on('registry:node-type-removed', function(nodeType) { + removeNodeType(nodeType); + }); + + RED.events.on('registry:node-set-enabled', function(nodeSet) { + for (var j=0;j
      -
      +
      + + +
      +
      • Manage palette
      +
      +
      + +
      +
      diff --git a/red/runtime/nodes/registry/loader.js b/red/runtime/nodes/registry/loader.js index 9e5897593..d51b427e9 100644 --- a/red/runtime/nodes/registry/loader.js +++ b/red/runtime/nodes/registry/loader.js @@ -188,7 +188,8 @@ function loadNodeConfig(fileInfo) { template: file.replace(/\.js$/,".html"), enabled: isEnabled, loaded:false, - version: version + version: version, + local: fileInfo.local }; if (fileInfo.hasOwnProperty("types")) { node.types = fileInfo.types; diff --git a/red/runtime/nodes/registry/localfilesystem.js b/red/runtime/nodes/registry/localfilesystem.js index 112ed72ee..9ca1307e3 100644 --- a/red/runtime/nodes/registry/localfilesystem.js +++ b/red/runtime/nodes/registry/localfilesystem.js @@ -141,7 +141,8 @@ function scanTreeForNodesModules(moduleName) { if (settings.userDir) { userDir = path.join(settings.userDir,"node_modules"); - results = results.concat(scanDirForNodesModules(userDir,moduleName)); + results = scanDirForNodesModules(userDir,moduleName); + results.forEach(function(r) { r.local = true; }); } if (dir) { @@ -240,12 +241,14 @@ function getNodeFiles(disableNodePathScan) { nodeList[moduleFile.package.name] = { name: moduleFile.package.name, version: moduleFile.package.version, + local: moduleFile.local||false, nodes: {} }; if (moduleFile.package['node-red'].version) { nodeList[moduleFile.package.name].redVersion = moduleFile.package['node-red'].version; } nodeModuleFiles.forEach(function(node) { + node.local = moduleFile.local||false; nodeList[moduleFile.package.name].nodes[node.name] = node; }); nodeFiles = nodeFiles.concat(nodeModuleFiles); diff --git a/red/runtime/nodes/registry/registry.js b/red/runtime/nodes/registry/registry.js index 74606853e..02a3b304d 100644 --- a/red/runtime/nodes/registry/registry.js +++ b/red/runtime/nodes/registry/registry.js @@ -56,7 +56,8 @@ function filterNodeInfo(n) { id: n.id||n.module+"/"+n.name, name: n.name, types: n.types, - enabled: n.enabled + enabled: n.enabled, + local: n.local||false }; if (n.hasOwnProperty("module")) { r.module = n.module; @@ -90,6 +91,7 @@ function saveNodeList() { moduleList[module] = { name: module, version: moduleConfigs[module].version, + local: moduleConfigs[module].local||false, nodes: {} }; } @@ -179,6 +181,7 @@ function addNodeSet(id,set,version) { if (version) { moduleConfigs[set.module].version = version; } + moduleConfigs[set.module].local = set.local; moduleConfigs[set.module].nodes[set.name] = set; nodeList.push(id); @@ -306,6 +309,7 @@ function getModuleInfo(module) { var m = { name: module, version: moduleConfigs[module].version, + local: moduleConfigs[module].local, nodes: [] }; for (var i = 0; i < nodes.length; ++i) { From 12e302c10af45097795ec782b12bc67b7a1220c9 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 4 Aug 2016 22:28:56 +0100 Subject: [PATCH 03/12] Collapse palette modules when palette-editor closed --- editor/js/ui/palette-editor.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/editor/js/ui/palette-editor.js b/editor/js/ui/palette-editor.js index 310e07539..2e67ea7ab 100644 --- a/editor/js/ui/palette-editor.js +++ b/editor/js/ui/palette-editor.js @@ -155,6 +155,10 @@ RED.palette.editor = (function() { $("#header-shade").hide(); $("#editor-shade").hide(); $("#sidebar-shade").hide(); + $("#palette-editor").find('.expanded').each(function(i,el) { + $(el).find(".palette-module-content").slideUp(); + $(el).removeClass('expanded'); + }); } function init() { From 521e669879297a56b7996f1695c2194e890f2b70 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Fri, 5 Aug 2016 13:39:14 +0100 Subject: [PATCH 04/12] Enable palette-editor remove buttons --- editor/js/nodes.js | 9 ++---- editor/js/ui/editableList.js | 8 +++-- editor/js/ui/palette-editor.js | 56 ++++++++++++++++++++++++++++++--- editor/sass/palette-editor.scss | 9 ++++++ 4 files changed, 68 insertions(+), 14 deletions(-) diff --git a/editor/js/nodes.js b/editor/js/nodes.js index 8a6a50c03..7507798b0 100644 --- a/editor/js/nodes.js +++ b/editor/js/nodes.js @@ -87,13 +87,8 @@ RED.nodes = (function() { break; } } - for (i=0;i').html('remove').appendTo(buttonGroup); if (!entry.local) { removeButton.hide(); + } else { + removeButton.click(function() { + shade.show(); + removeNodeModule(entry.name, function(xhr) { + console.log(xhr); + }) + }) } var enableButton = $('').html('disable all').appendTo(buttonGroup); var contentRow = $('
      ',{class:"palette-module-content"}).appendTo(container); + var shade = $('
      ',{class:"palette-module-shade hide"}).appendTo(container); + $('').appendTo(shade); + object.elements = { removeButton: removeButton, enableButton: enableButton, setCount: setCount, container: container, + shade: shade, sets: {} } setButton.click(function() { @@ -249,7 +289,8 @@ RED.palette.editor = (function() { enableButton.click(function(evt) { if (object.setUseCount[setName] === 0) { var currentSet = RED.nodes.registry.getNodeSet(set.id); - changeNodeState(set.id,!currentSet.enabled,function(xhr){ + shade.show(); + changeNodeState(set.id,!currentSet.enabled,shade,function(xhr){ console.log(xhr) }); } @@ -264,7 +305,7 @@ RED.palette.editor = (function() { }); enableButton.click(function(evt) { if (object.totalUseCount === 0) { - changeNodeState(entry.name,(container.hasClass('disabled')),function(xhr){ + changeNodeState(entry.name,(container.hasClass('disabled')),shade,function(xhr){ console.log(xhr) }); } @@ -292,7 +333,14 @@ RED.palette.editor = (function() { refreshNodeModule(ns.module); }); RED.events.on('registry:node-set-removed', function(ns) { - refreshNodeModule(ns.module); + var module = RED.nodes.registry.getModule(ns.module); + if (!module) { + var entry = nodeEntries[ns.module]; + if (entry) { + nodeList.editableList('removeItem', entry); + delete nodeEntries[ns.module]; + } + } }); RED.events.on('nodes:add', function(n) { typesInUse[n.type] = (typesInUse[n.type]||0)+1; diff --git a/editor/sass/palette-editor.scss b/editor/sass/palette-editor.scss index a5e96881f..5e8330c17 100644 --- a/editor/sass/palette-editor.scss +++ b/editor/sass/palette-editor.scss @@ -58,6 +58,15 @@ margin-left: 5px; } } + .palette-module-shade { + position: absolute; + top: 0; + bottom:0; + left:0; + right:0; + background: rgba(255,255,255,0.8); + text-align: center; + } .palette-module-meta { overflow: hidden; color: #666; From ba37db275cc23363f673133d7a025dc96ef18a8c Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Fri, 5 Aug 2016 16:39:41 +0100 Subject: [PATCH 05/12] Add node filter to palette-editor --- editor/js/ui/editableList.js | 37 +++++++++++++++ editor/js/ui/palette-editor.js | 56 +++++++++++++++++++++-- editor/js/ui/palette.js | 25 +++++------ editor/sass/palette.scss | 82 +++++++++++++++++----------------- editor/templates/index.mst | 4 +- 5 files changed, 145 insertions(+), 59 deletions(-) diff --git a/editor/js/ui/editableList.js b/editor/js/ui/editableList.js index 3446c46ee..5b3c12125 100644 --- a/editor/js/ui/editableList.js +++ b/editor/js/ui/editableList.js @@ -85,6 +85,8 @@ this.uiHeight = this.element.height(); + this.activeFilter = this.options.filter||null; + var minHeight = this.element.css("minHeight"); if (minHeight !== '0px') { this.uiContainer.css("minHeight",minHeight); @@ -155,6 +157,26 @@ }, _destroy: function() { }, + _refreshFilter: function() { + var that = this; + if (!this.activeFilter) { + this.element.children().show(); + } + var items = this.items(); + items.each(function (i,el) { + var data = el.data('data'); + try { + if (that.activeFilter(data)) { + el.parent().show(); + } else { + el.parent().hide(); + } + } catch(err) { + console.log(err); + el.parent().show(); + } + }); + }, width: function(desiredWidth) { this.uiWidth = desiredWidth; this._resize(); @@ -207,6 +229,15 @@ var index = that.element.children().length-1; setTimeout(function() { that.options.addItem(row,index,data); + if (that.activeFilter) { + try { + if (!that.activeFilter(data)) { + li.hide(); + } + } catch(err) { + } + } + if (!that.options.sort) { setTimeout(function() { that.uiContainer.scrollTop(that.element.height()); @@ -229,6 +260,12 @@ }, empty: function() { this.element.empty(); + }, + filter: function(filter) { + if (filter !== undefined) { + this.activeFilter = filter; + } + this._refreshFilter(); } }); })(jQuery); diff --git a/editor/js/ui/palette-editor.js b/editor/js/ui/palette-editor.js index fceb574c0..f2fc57a02 100644 --- a/editor/js/ui/palette-editor.js +++ b/editor/js/ui/palette-editor.js @@ -17,11 +17,11 @@ RED.palette.editor = (function() { var nodeList; var typesInUse = {}; - var nodeEntries = {}; - var eventTimers = {}; + var activeFilter = ""; + function delayCallback(start,callback) { var delta = Date.now() - start; if (delta < 300) { @@ -96,6 +96,15 @@ RED.palette.editor = (function() { function _refreshNodeModule(module) { if (!nodeEntries.hasOwnProperty(module)) { nodeEntries[module] = {info:RED.nodes.registry.getModule(module)}; + var index = [module]; + for (var s in nodeEntries[module].info.sets) { + if (nodeEntries[module].info.sets.hasOwnProperty(s)) { + index.push(s); + index = index.concat(nodeEntries[module].info.sets[s].types) + } + } + nodeEntries[module].index = index.join(",").toLowerCase(); + nodeList.editableList('addItem', nodeEntries[module]); //console.log(nodeList.editableList('items')); @@ -188,6 +197,19 @@ RED.palette.editor = (function() { $(el).find(".palette-module-content").slideUp(); $(el).removeClass('expanded'); }); + $("#palette-editor-search input").val(""); + filterChange(""); + } + + function filterChange(val) { + if (val === "") { + $("#palette-editor-search a").hide(); + activeFilter = val; + } else { + $("#palette-editor-search a").show(); + activeFilter = val.toLowerCase(); + } + nodeList.editableList('filter'); } function init() { @@ -209,11 +231,39 @@ RED.palette.editor = (function() { var divTabs = $('
      ',{style:"position:absolute;top:80px;left:0;right:0;bottom:0"}).appendTo("#palette-editor"); - nodeList = $('
        ',{id:"palette-module-list", style:"position: absolute;top: 0;bottom: 0;left: 0;right: 0px;"}).appendTo(divTabs).editableList({ + var searchDiv = $('
        ',{id:"palette-editor-search",class:"palette-search"}).appendTo(divTabs); + $('').appendTo(searchDiv) + + $("#palette-editor-search a").on("click",function(e) { + e.preventDefault(); + $("#palette-editor-search input").val(""); + filterChange(""); + $("#palette-editor-search input").focus(); + }); + + $("#palette-editor-search input").val(""); + $("#palette-editor-search input").on("keyup",function() { + filterChange($(this).val()); + }); + + $("#palette-editor-search input").on("focus",function() { + $("body").one("mousedown",function() { + $("#palette-editor-search input").blur(); + }); + }); + + nodeList = $('
          ',{id:"palette-module-list", style:"position: absolute;top: 35px;bottom: 0;left: 0;right: 0px;"}).appendTo(divTabs).editableList({ addButton: false, sort: function(A,B) { return A.info.name.localeCompare(B.info.name); }, + filter: function(data) { + if (activeFilter === "" ) { + return true; + } + + return (activeFilter==="")||(data.index.indexOf(activeFilter) > -1); + }, addItem: function(container,i,object) { var entry = object.info; diff --git a/editor/js/ui/palette.js b/editor/js/ui/palette.js index 86e9b8c45..645867fae 100644 --- a/editor/js/ui/palette.js +++ b/editor/js/ui/palette.js @@ -361,12 +361,11 @@ RED.palette = (function() { }); } - function filterChange() { - var val = $("#palette-search-input").val(); + function filterChange(val) { if (val === "") { - $("#palette-search-clear").hide(); + $("#palette-search a").hide(); } else { - $("#palette-search-clear").show(); + $("#palette-search a").show(); } var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i'); @@ -447,21 +446,21 @@ RED.palette = (function() { }); } - $("#palette-search-clear").on("click",function(e) { + $("#palette-search a").on("click",function(e) { e.preventDefault(); - $("#palette-search-input").val(""); - filterChange(); - $("#palette-search-input").focus(); + $("#palette-search input").val(""); + filterChange(""); + $("#palette-search input").focus(); }); - $("#palette-search-input").val(""); - $("#palette-search-input").on("keyup",function() { - filterChange(); + $("#palette-search input").val(""); + $("#palette-search input").on("keyup",function() { + filterChange($(this).val()); }); - $("#palette-search-input").on("focus",function() { + $("#palette-search input").on("focus",function() { $("body").one("mousedown",function() { - $("#palette-search-input").blur(); + $("#palette-search input").blur(); }); }); diff --git a/editor/sass/palette.scss b/editor/sass/palette.scss index bc4c8fde1..18ba0b59c 100644 --- a/editor/sass/palette.scss +++ b/editor/sass/palette.scss @@ -57,7 +57,7 @@ padding-top: 40px; } -#palette-search { +.palette-search { position: absolute; top: 0; left:0; @@ -69,49 +69,49 @@ padding: 3px; border-bottom: 1px solid $primary-border-color; box-sizing:border-box; -} -#palette-search i { - font-size: 10px; - color: #666; -} -#palette-search i.fa-search { - position: absolute; - pointer-events: none; - left: 12px; - top: 12px; -} -#palette-search i.fa-times { - position: absolute; - right: 7px; - top: 12px; + i { + font-size: 10px; + color: #666; + } + i.fa-search { + position: absolute; + pointer-events: none; + left: 12px; + top: 12px; + } + i.fa-times { + position: absolute; + right: 7px; + top: 12px; + } + input { + border-radius: 0; + border: none; + width: 100%; + box-shadow: none; + -webkit-box-shadow: none; + padding: 3px 17px 3px 22px; + margin: 0px; + height: 30px; + box-sizing:border-box; + + &:focus { + border: none; + box-shadow: none; + -webkit-box-shadow: none; + } + } + .palette-search-clear { + position: absolute; + right: 0; + top: 0; + bottom: 0; + width: 20px; + display: none; + } } -#palette-search-clear { - position: absolute; - right: 0; - top: 0; - bottom: 0; - width: 20px; - display: none; -} -#palette-search input { - border-radius: 0; - border: none; - width: 100%; - box-shadow: none; - -webkit-box-shadow: none; - padding: 3px 17px 3px 22px; - margin: 0px; - height: 30px; - box-sizing:border-box; -} - -#palette-search input:focus { - border: none; - box-shadow: none; - -webkit-box-shadow: none; -} #palette-footer { @include component-footer; } diff --git a/editor/templates/index.mst b/editor/templates/index.mst index 239f68a6e..bd23b55e5 100644 --- a/editor/templates/index.mst +++ b/editor/templates/index.mst @@ -58,8 +58,8 @@
          -