mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #3521 from Steve-Mcl/autocomplete-improvements
autocomplete improvements...
This commit is contained in:
commit
1be6e4565f
@ -9,12 +9,14 @@
|
|||||||
*
|
*
|
||||||
* options:
|
* options:
|
||||||
*
|
*
|
||||||
* search : function(value, [done])
|
* search: function(value, [done])
|
||||||
* A function that is passed the current contents of the input whenever
|
* A function that is passed the current contents of the input whenever
|
||||||
* it changes.
|
* it changes.
|
||||||
* The function must either return auto-complete options, or pass them
|
* The function must either return auto-complete options, or pass them
|
||||||
* to the optional 'done' parameter.
|
* to the optional 'done' parameter.
|
||||||
* If the function signature includes 'done', it must be used
|
* If the function signature includes 'done', it must be used
|
||||||
|
* minLength: number
|
||||||
|
* If `minLength` is 0, pressing down arrow will show the list
|
||||||
*
|
*
|
||||||
* The auto-complete options should be an array of objects in the form:
|
* The auto-complete options should be an array of objects in the form:
|
||||||
* {
|
* {
|
||||||
@ -26,10 +28,11 @@
|
|||||||
|
|
||||||
$.widget( "nodered.autoComplete", {
|
$.widget( "nodered.autoComplete", {
|
||||||
_create: function() {
|
_create: function() {
|
||||||
var that = this;
|
const that = this;
|
||||||
this.completionMenuShown = false;
|
this.completionMenuShown = false;
|
||||||
this.options.search = this.options.search || function() { return [] }
|
this.options.minLength = parseInteger(this.options.minLength, 1, 0);
|
||||||
this.element.addClass("red-ui-autoComplete")
|
this.options.search = this.options.search || function() { return [] };
|
||||||
|
this.element.addClass("red-ui-autoComplete");
|
||||||
this.element.on("keydown.red-ui-autoComplete", function(evt) {
|
this.element.on("keydown.red-ui-autoComplete", function(evt) {
|
||||||
if ((evt.keyCode === 13 || evt.keyCode === 9) && that.completionMenuShown) {
|
if ((evt.keyCode === 13 || evt.keyCode === 9) && that.completionMenuShown) {
|
||||||
var opts = that.menu.options();
|
var opts = that.menu.options();
|
||||||
@ -71,8 +74,8 @@
|
|||||||
this.completionMenuShown = true;
|
this.completionMenuShown = true;
|
||||||
},
|
},
|
||||||
_updateCompletions: function(val) {
|
_updateCompletions: function(val) {
|
||||||
var that = this;
|
const that = this;
|
||||||
if (val.trim() === "") {
|
if (val.trim().length < this.options.minLength) {
|
||||||
if (this.completionMenuShown) {
|
if (this.completionMenuShown) {
|
||||||
this.menu.hide();
|
this.menu.hide();
|
||||||
}
|
}
|
||||||
@ -96,7 +99,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.options.search.length === 2) {
|
if (this.options.search.length === 2) {
|
||||||
var requestId = 1+Math.floor(Math.random()*10000);
|
const requestId = 1+Math.floor(Math.random()*10000);
|
||||||
this.pendingRequest = requestId;
|
this.pendingRequest = requestId;
|
||||||
this.options.search(val,function(completions) { displayResults(completions,requestId);})
|
this.options.search(val,function(completions) { displayResults(completions,requestId);})
|
||||||
} else {
|
} else {
|
||||||
@ -112,4 +115,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
function parseInteger(input, def, min, max) {
|
||||||
|
if(input == null) { return (def || 0); }
|
||||||
|
min = min == null ? Number.NEGATIVE_INFINITY : min;
|
||||||
|
max = max == null ? Number.POSITIVE_INFINITY : max;
|
||||||
|
let n = parseInt(input);
|
||||||
|
if(isNaN(n) || n < min || n > max) { n = def || 0; }
|
||||||
|
return n;
|
||||||
|
}
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
@ -55,34 +55,46 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var autoComplete = function(options) {
|
var autoComplete = function(options) {
|
||||||
|
function getMatch(value, searchValue) {
|
||||||
|
const idx = value.toLowerCase().indexOf(searchValue.toLowerCase());
|
||||||
|
const len = idx > -1 ? searchValue.length : 0;
|
||||||
|
return {
|
||||||
|
index: idx,
|
||||||
|
found: idx > -1,
|
||||||
|
pre: value.substring(0,idx),
|
||||||
|
match: value.substring(idx,idx+len),
|
||||||
|
post: value.substring(idx+len),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function generateSpans(match) {
|
||||||
|
const els = [];
|
||||||
|
if(match.pre) { els.push($('<span/>').text(match.pre)); }
|
||||||
|
if(match.match) { els.push($('<span/>',{style:"font-weight: bold; color: var(--red-ui-text-color-link);"}).text(match.match)); }
|
||||||
|
if(match.post) { els.push($('<span/>').text(match.post)); }
|
||||||
|
return els;
|
||||||
|
}
|
||||||
return function(val) {
|
return function(val) {
|
||||||
var matches = [];
|
var matches = [];
|
||||||
options.forEach(opt => {
|
options.forEach(opt => {
|
||||||
let v = opt.value;
|
const optVal = opt.value;
|
||||||
var i = v.toLowerCase().indexOf(val.toLowerCase());
|
const optSrc = (opt.source||[]).join(",");
|
||||||
if (i > -1) {
|
const valMatch = getMatch(optVal, val);
|
||||||
var pre = v.substring(0,i);
|
const srcMatch = getMatch(optSrc, val);
|
||||||
var matchedVal = v.substring(i,i+val.length);
|
if (valMatch.found || srcMatch.found) {
|
||||||
var post = v.substring(i+val.length)
|
const element = $('<div>',{style: "display: flex"});
|
||||||
|
const valEl = $('<div/>',{style:"font-family: var(--red-ui-monospace-font); white-space:nowrap; overflow: hidden; flex-grow:1"});
|
||||||
var el = $('<div/>',{style:"white-space:nowrap; overflow: hidden; flex-grow:1"});
|
valEl.append(generateSpans(valMatch));
|
||||||
$('<span/>').text(pre).appendTo(el);
|
valEl.appendTo(element);
|
||||||
$('<span/>',{style:"font-weight: bold"}).text(matchedVal).appendTo(el);
|
if (optSrc) {
|
||||||
$('<span/>').text(post).appendTo(el);
|
const optEl = $('<div>').css({ "font-size": "0.8em" });
|
||||||
|
optEl.append(generateSpans(srcMatch));
|
||||||
var element = $('<div>',{style: "display: flex"});
|
optEl.appendTo(element);
|
||||||
el.appendTo(element);
|
|
||||||
if (opt.source) {
|
|
||||||
$('<div>').css({
|
|
||||||
"font-size": "0.8em"
|
|
||||||
}).text(opt.source.join(",")).appendTo(element);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matches.push({
|
matches.push({
|
||||||
value: v,
|
value: optVal,
|
||||||
label: element,
|
label: element,
|
||||||
i:i
|
i: (valMatch.found ? valMatch.index : srcMatch.index)
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
matches.sort(function(A,B){return A.i-B.i})
|
matches.sort(function(A,B){return A.i-B.i})
|
||||||
@ -93,6 +105,36 @@
|
|||||||
// This is a hand-generated list of completions for the core nodes (based on the node help html).
|
// This is a hand-generated list of completions for the core nodes (based on the node help html).
|
||||||
var msgCompletions = [
|
var msgCompletions = [
|
||||||
{ value: "payload" },
|
{ value: "payload" },
|
||||||
|
{ value: "topic", source: ["mqtt","inject","rbe"] },
|
||||||
|
{ value: "action", source: ["mqtt"] },
|
||||||
|
{ value: "complete", source: ["join"] },
|
||||||
|
{ value: "contentType", source: ["mqtt"] },
|
||||||
|
{ value: "cookies", source: ["http request","http response"] },
|
||||||
|
{ value: "correlationData", source: ["mqtt"] },
|
||||||
|
{ value: "delay", source: ["delay","trigger"] },
|
||||||
|
{ value: "encoding", source: ["file"] },
|
||||||
|
{ value: "error", source: ["catch"] },
|
||||||
|
{ value: "error.message", source: ["catch"] },
|
||||||
|
{ value: "error.source", source: ["catch"] },
|
||||||
|
{ value: "error.source.id", source: ["catch"] },
|
||||||
|
{ value: "error.source.type", source: ["catch"] },
|
||||||
|
{ value: "error.source.name", source: ["catch"] },
|
||||||
|
{ value: "filename", source: ["file","file in"] },
|
||||||
|
{ value: "flush", source: ["delay"] },
|
||||||
|
{ value: "followRedirects", source: ["http request"] },
|
||||||
|
{ value: "headers", source: ["http response","http request"] },
|
||||||
|
{ value: "host", source: ["tcp request","http request"] },
|
||||||
|
{ value: "ip", source: ["udp out"] },
|
||||||
|
{ value: "kill", source: ["exec"] },
|
||||||
|
{ value: "messageExpiryInterval", source: ["mqtt"] },
|
||||||
|
{ value: "method", source: ["http request"] },
|
||||||
|
{ value: "options", source: ["xml"] },
|
||||||
|
{ value: "parts", source: ["split","join","batch","sort"] },
|
||||||
|
{ value: "pid", source: ["exec"] },
|
||||||
|
{ value: "port", source: ["tcp request"," udp out"] },
|
||||||
|
{ value: "qos", source: ["mqtt"] },
|
||||||
|
{ value: "rate", source: ["delay"] },
|
||||||
|
{ value: "rejectUnauthorized", source: ["http request"] },
|
||||||
{ value: "req", source: ["http in"]},
|
{ value: "req", source: ["http in"]},
|
||||||
{ value: "req.body", source: ["http in"]},
|
{ value: "req.body", source: ["http in"]},
|
||||||
{ value: "req.headers", source: ["http in"]},
|
{ value: "req.headers", source: ["http in"]},
|
||||||
@ -100,38 +142,28 @@
|
|||||||
{ value: "req.params", source: ["http in"]},
|
{ value: "req.params", source: ["http in"]},
|
||||||
{ value: "req.cookies", source: ["http in"]},
|
{ value: "req.cookies", source: ["http in"]},
|
||||||
{ value: "req.files", source: ["http in"]},
|
{ value: "req.files", source: ["http in"]},
|
||||||
{ value: "complete", source: ["join"] },
|
|
||||||
{ value: "contentType", source: ["mqtt"] },
|
|
||||||
{ value: "cookies", source: ["http in","http request"] },
|
|
||||||
{ value: "correlationData", source: ["mqtt"] },
|
|
||||||
{ value: "delay", source: ["delay","trigger"] },
|
|
||||||
{ value: "encoding", source: ["file"] },
|
|
||||||
{ value: "error", source: ["catch"] },
|
|
||||||
{ value: "filename", source: ["file","file in"] },
|
|
||||||
{ value: "flush", source: ["delay"] },
|
|
||||||
{ value: "followRedirects", source: ["http request"] },
|
|
||||||
{ value: "headers", source: ["http in"," http request"] },
|
|
||||||
{ value: "kill", source: ["exec"] },
|
|
||||||
{ value: "messageExpiryInterval", source: ["mqtt"] },
|
|
||||||
{ value: "method", source: ["http-request"] },
|
|
||||||
{ value: "options", source: ["xml"] },
|
|
||||||
{ value: "parts", source: ["split","join"] },
|
|
||||||
{ value: "pid", source: ["exec"] },
|
|
||||||
{ value: "qos", source: ["mqtt"] },
|
|
||||||
{ value: "rate", source: ["delay"] },
|
|
||||||
{ value: "rejectUnauthorized", source: ["http request"] },
|
|
||||||
{ value: "requestTimeout", source: ["http request"] },
|
{ value: "requestTimeout", source: ["http request"] },
|
||||||
{ value: "reset", source: ["delay","trigger","join","rbe"] },
|
{ value: "reset", source: ["delay","trigger","join","rbe"] },
|
||||||
|
{ value: "responseCookies", source: ["http request"] },
|
||||||
{ value: "responseTopic", source: ["mqtt"] },
|
{ value: "responseTopic", source: ["mqtt"] },
|
||||||
|
{ value: "responseURL", source: ["http request"] },
|
||||||
{ value: "restartTimeout", source: ["join"] },
|
{ value: "restartTimeout", source: ["join"] },
|
||||||
{ value: "retain", source: ["mqtt"] },
|
{ value: "retain", source: ["mqtt"] },
|
||||||
|
{ value: "schema", source: ["json"] },
|
||||||
{ value: "select", source: ["html"] },
|
{ value: "select", source: ["html"] },
|
||||||
{ value: "statusCode", source: ["http in"] },
|
{ value: "statusCode", source: ["http response","http request"] },
|
||||||
|
{ value: "status", source: ["status"] },
|
||||||
|
{ value: "status.text", source: ["status"] },
|
||||||
|
{ value: "status.source", source: ["status"] },
|
||||||
|
{ value: "status.source.type", source: ["status"] },
|
||||||
|
{ value: "status.source.id", source: ["status"] },
|
||||||
|
{ value: "status.source.name", source: ["status"] },
|
||||||
|
{ value: "target", source: ["link call"] },
|
||||||
{ value: "template", source: ["template"] },
|
{ value: "template", source: ["template"] },
|
||||||
{ value: "toFront", source: ["delay"] },
|
{ value: "toFront", source: ["delay"] },
|
||||||
{ value: "topic", source: ["inject","mqtt","rbe"] },
|
|
||||||
{ value: "url", source: ["http request"] },
|
{ value: "url", source: ["http request"] },
|
||||||
{ value: "userProperties", source: ["mqtt"] }
|
{ value: "userProperties", source: ["mqtt"] },
|
||||||
|
{ value: "_session", source: ["websocket out","tcp out"] },
|
||||||
]
|
]
|
||||||
var allOptions = {
|
var allOptions = {
|
||||||
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression, autoComplete: autoComplete(msgCompletions)},
|
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression, autoComplete: autoComplete(msgCompletions)},
|
||||||
@ -1147,7 +1179,8 @@
|
|||||||
this.elementDiv.show();
|
this.elementDiv.show();
|
||||||
if (opt.autoComplete) {
|
if (opt.autoComplete) {
|
||||||
this.input.autoComplete({
|
this.input.autoComplete({
|
||||||
search: opt.autoComplete
|
search: opt.autoComplete,
|
||||||
|
minLength: 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user