diff --git a/nodes/core/logic/15-change.html b/nodes/core/logic/15-change.html index 1ed79b687..9018b0e42 100644 --- a/nodes/core/logic/15-change.html +++ b/nodes/core/logic/15-change.html @@ -128,21 +128,37 @@ selectField.append($("").val(selectOptions[i].v).text(selectOptions[i].l)); } - var propertyName = $('',{style:"width: 250px",class:"node-input-rule-property-name",type:"text"}).appendTo(row1).typedInput({types:['msg','flow','global']}); - var finalspan = $('',{style:"float: right; margin-right: 10px;"}).appendTo(row1); - var deleteButton = $('',{href:"#",class:"editor-button editor-button-small", style:"margin-top: 7px; margin-left: 5px;"}).appendTo(finalspan); + var propertyName = $('',{style:"width: 250px",class:"node-input-rule-property-name",type:"text"}) + .appendTo(row1) + .typedInput({types:['msg','flow','global']}); + var finalspan = $('',{style:"float: right; margin-right: 10px;"}) + .appendTo(row1); + var deleteButton = $('',{href:"#",class:"editor-button editor-button-small", style:"margin-top: 7px; margin-left: 5px;"}) + .appendTo(finalspan); $('',{class:"fa fa-remove"}).appendTo(deleteButton); - $('
',{style:"display: inline-block;text-align:right; width:120px;padding-right: 10px; box-sizing: border-box;"}).text(to).appendTo(row2); - var propertyValue = $('',{style:"width: 250px",class:"node-input-rule-property-value",type:"text"}).appendTo(row2).typedInput({default:'str',types:['msg','flow','global','str','num','bool','json']}); + $('
',{style:"display: inline-block;text-align:right; width:120px;padding-right: 10px; box-sizing: border-box;"}) + .text(to) + .appendTo(row2); + var propertyValue = $('',{style:"width: 250px",class:"node-input-rule-property-value",type:"text"}) + .appendTo(row2) + .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json']}); var row3_1 = $('
').appendTo(row3); - $('
',{style:"display: inline-block;text-align:right; width:120px;padding-right: 10px; box-sizing: border-box;"}).text(search).appendTo(row3_1); - var fromValue = $('',{style:"width: 250px",class:"node-input-rule-property-search-value",type:"text"}).appendTo(row3_1).typedInput({default:'str',types:['msg','flow','global','str','re']}); + $('
',{style:"display: inline-block;text-align:right; width:120px;padding-right: 10px; box-sizing: border-box;"}) + .text(search) + .appendTo(row3_1); + var fromValue = $('',{style:"width: 250px",class:"node-input-rule-property-search-value",type:"text"}) + .appendTo(row3_1) + .typedInput({default:'str',types:['msg','flow','global','str','re','num','bool']}); var row3_2 = $('
',{style:"margin-top:8px;"}).appendTo(row3); - $('
',{style:"display: inline-block;text-align:right; width:120px;padding-right: 10px; box-sizing: border-box;"}).text(replace).appendTo(row3_2); - var toValue = $('',{style:"width: 250px",class:"node-input-rule-property-replace-value",type:"text"}).appendTo(row3_2).typedInput({default:'str',types:['msg','flow','global','str','num','json']}); + $('
',{style:"display: inline-block;text-align:right; width:120px;padding-right: 10px; box-sizing: border-box;"}) + .text(replace) + .appendTo(row3_2); + var toValue = $('',{style:"width: 250px",class:"node-input-rule-property-replace-value",type:"text"}) + .appendTo(row3_2) + .typedInput({default:'str',types:['msg','flow','global','str','num','bool','json']}); selectField.change(function() { var width = $("#node-input-rule-container").width(); diff --git a/nodes/core/logic/15-change.js b/nodes/core/logic/15-change.js index ba0a0ba1b..10f5e677e 100644 --- a/nodes/core/logic/15-change.js +++ b/nodes/core/logic/15-change.js @@ -64,12 +64,13 @@ module.exports = function(RED) { if (!rule.fromt) { rule.fromt = "str"; } - if (rule.t === "change") { + if (rule.t === "change" && rule.fromt !== 'msg' && rule.fromt !== 'flow' && rule.fromt !== 'global') { + rule.fromRE = rule.from; if (rule.fromt !== 're') { - rule.from = rule.from.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + rule.fromRE = rule.fromRE.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); } try { - rule.from = new RegExp(rule.from, "g"); + rule.fromRE = new RegExp(rule.fromRE, "g"); } catch (e) { valid = false; this.error(RED._("change.errors.invalid-from",{error:e.message})); @@ -93,6 +94,10 @@ module.exports = function(RED) { try { var property = rule.p; var value = rule.to; + var current; + var fromValue; + var fromType; + var fromRE; if (rule.tot === "msg") { value = RED.util.getMessageProperty(msg,rule.to); } else if (rule.tot === 'flow') { @@ -100,16 +105,68 @@ module.exports = function(RED) { } else if (rule.tot === 'global') { value = node.context().global.get(rule.to); } + + if (rule.t === 'change') { + if (rule.fromt === 'msg' || rule.fromt === 'flow' || rule.fromt === 'global') { + if (rule.fromt === "msg") { + fromValue = RED.util.getMessageProperty(msg,rule.from); + } else if (rule.tot === 'flow') { + fromValue = node.context().flow.get(rule.from); + } else if (rule.tot === 'global') { + fromValue = node.context().global.get(rule.from); + } + if (typeof fromValue === 'number' || fromValue instanceof Number) { + fromType = 'num'; + } else if (typeof fromValue === 'boolean') { + fromType = 'bool' + } else if (fromValue instanceof RegExp) { + fromType = 're'; + fromRE = fromValue; + } else if (typeof fromValue === 'string') { + fromType = 'str'; + fromRE = fromValue.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + try { + fromRE = new RegExp(fromRE, "g"); + } catch (e) { + valid = false; + node.error(RED._("change.errors.invalid-from",{error:e.message})); + return + } + + } else { + node.error(RED._("change.errors.invalid-from",{error:"unsupported type: "+(typeof fromValue)})); + return + } + } else { + fromType = rule.fromt; + fromValue = rule.from; + fromRE = rule.fromRE; + } + } if (rule.pt === 'msg') { if (rule.t === 'delete') { RED.util.setMessageProperty(msg,property,undefined); } else if (rule.t === 'set') { RED.util.setMessageProperty(msg,property,value); } else if (rule.t === 'change') { - var current = RED.util.getMessageProperty(msg,property); + current = RED.util.getMessageProperty(msg,property); if (typeof current === 'string') { - current = current.replace(rule.from,value); - RED.util.setMessageProperty(msg,property,current); + if ((fromType === 'num' || fromType === 'bool') && current === fromValue) { + // str representation of exact from number/boolean + // only replace if they match exactly + RED.util.setMessageProperty(msg,property,value); + } else { + current = current.replace(fromRE,value); + RED.util.setMessageProperty(msg,property,current); + } + } else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') { + if (current == Number(fromValue)) { + RED.util.setMessageProperty(msg,property,value); + } + } else if (typeof current === 'boolean' && fromType === 'bool') { + if (current.toString() === fromValue) { + RED.util.setMessageProperty(msg,property,value); + } } } } else { @@ -125,16 +182,30 @@ module.exports = function(RED) { } else if (rule.t === 'set') { target.set(property,value); } else if (rule.t === 'change') { - var current = target.get(msg,property); + current = target.get(msg,property); if (typeof current === 'string') { - current = current.replace(rule.from,value); - target.set(property,current); + if ((fromType === 'num' || fromType === 'bool') && current === fromValue) { + // str representation of exact from number/boolean + // only replace if they match exactly + target.set(property,value); + } else { + current = current.replace(fromRE,value); + target.set(property,current); + } + } else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') { + if (current == Number(fromValue)) { + target.set(property,value); + } + } else if (typeof current === 'boolean' && fromType === 'bool') { + if (current.toString() === fromValue) { + target.set(property,value); + } } } } } - } catch(err) {console.log(err.stack)} + } catch(err) {/*console.log(err.stack)*/} return msg; } if (valid) { @@ -142,6 +213,9 @@ module.exports = function(RED) { this.on('input', function(msg) { for (var i=0;i