node/friendlyid.html
<script type="text/javascript">
RED.nodes.registerType("friendly-id", {
category: 'function',
color: '#C0C0C0',
icon: "icon.svg",
inputs: 1,
outputs: 1,
defaults: {
name: {
value: ""
},
mode: {
value: "GENERATE-NANOID",
required: true
},
charlen: {
value: 21,
required: true
},
charset: {
value: "DEFAULT"
},
customs: {
value: "",
validate: function(v) {
var charset = $('#node-input-charset option:selected').val();
if (charset === "CUSTOM") {
if (v.length == 0) {
return false;
}
var duplicateCount = v.split("")
.filter(function(value, index, self) {
return self.indexOf(value) !== index;
}).length;
if (duplicateCount > 0) {
return false;
}
return RED.validators.regex(/[0-9A-Za-z]+/)(v)
}
return true;
}
},
tostatus: {
value: false
},
statusVal: {
value: ""
},
statusType: {
value: "auto"
},
inputFromVal: {
value: ""
},
inputFromType: {
value: "auto"
},
outputToVal: {
value: ""
},
outputToType: {
value: "auto"
}
},
label: function() {
return this.name || "friendly-id";
},
labelStyle: function() {
return this.name ? "node_label_italic" : "";
},
oneditprepare: function() {
var node = this;
var defaultInOutType = {
value: "auto",
label: node._("label.defaultInOutType"),
hasValue: false
}
var inplaceType = {
value: "inplace",
label: node._("label.inplaceType"),
hasValue: false
}
var createTypedOutputTypes = function(inplace = true) {
var dynamicTypes = [defaultInOutType];
if (inplace) {
dynamicTypes.push(inplaceType);
}
dynamicTypes.push("msg");
return dynamicTypes;
};
var defaultStatusType = {
value: "auto",
label: node._("label.defaultStatusType"),
hasValue: false
};
$("#node-input-typed-status").typedInput({
default: "auto",
types: [defaultStatusType, "msg"],
typeField: $("#node-input-statusType")
});
$("#node-input-typed-outputTo").typedInput({
default: "auto",
types: createTypedOutputTypes(true),
typeField: $("#node-input-outputToType")
})
$("#node-input-typed-inputFrom").typedInput({
default: "auto",
types: [defaultInOutType, "msg"],
typeField: $("#node-input-inputFromType")
})
$("#node-input-typed-inputFrom").typedInput('type', node.inputFromType || node._def.defaults.inputFromType.value);
$("#node-input-typed-inputFrom").typedInput('value', node.inputFromVal || node._def.defaults.inputFromVal.value);
$("#node-input-typed-outputTo").typedInput('type', node.outputToType || node._def.defaults.outputToType.value);
$("#node-input-typed-outputTo").typedInput('value', node.outputToVal || node._def.defaults.outputToVal.value);
if (node.statusType === undefined) {
$("#node-input-typed-status").typedInput('type', node._def.defaults.statusType.value);
}
if (node.statusVal === undefined) {
$("#node-input-typed-status").typedInput('value', node._def.defaults.statusVal.value);
}
if (node.charlen === undefined) {
$('#node-input-charlen').val(node._def.defaults.charlen.value);
}
if (node.charset === undefined) {
$('#node-input-charset').val(node._def.defaults.charset.value);
}
$("#node-input-tostatus").change(function(e) {
if ($(this).is(":checked")) {
$("#node-input-typed-status").typedInput('type', node.statusType);
$("#node-input-typed-status").typedInput('value', node.statusVal);
$("#node-tostatus-line").show();
} else {
$("#node-tostatus-line").hide();
node.statusType = node._def.defaults.statusType.value;
node.statusVal = node._def.defaults.statusVal.value;
$("#node-input-typed-status").typedInput('type', node.statusType);
$("#node-input-typed-status").typedInput('value', node.statusVal);
}
});
$('#node-input-mode').change(function(e) {
var inplace = true;
switch ($('option:selected', this).val()) {
case "GENERATE-NANOID":
$('#node-nodeid-customs-line').hide();
$('#node-nodeid-line').show()
inplace = false;
break;
case "GENERATE-SHORTID":
case "GENERATE-UUID4":
inplace = false;
// break;
default:
$('#node-nodeid-line').hide()
node.charset = node._def.defaults.charset.value;
node.charlen = node._def.defaults.charlen.value;
$('#node-input-charset').val(node.charset);
$('#node-input-charlen').val(node.charlen);
break;
}
$("#node-input-typed-outputTo").typedInput('types', createTypedOutputTypes(inplace));
if (inplace) {
$('#node-inputs-line').show()
} else {
$('#node-inputs-line').hide()
node.inputFromType = node._def.defaults.inputFromType.value;
node.inputFromVal = node._def.defaults.inputFromVal.value;
$("#node-input-typed-inputFrom").typedInput('type', node.inputFromType);
$("#node-input-typed-inputFrom").typedInput('value', node.inputFromVal);
}
});
$('#node-input-charset').change(function(e) {
if ($('option:selected', this).val() === "CUSTOM") {
$("#node-input-customs").val(node.customs || node._def.defaults.customs.value);
$('#node-nodeid-customs-line').show();
} else {
$('#node-nodeid-customs-line').hide();
node.customs = node._def.defaults.customs.value;
$("#node-input-customs").val(node.customs);
}
});
},
oneditsave: function() {
$("#node-input-statusVal").val($("#node-input-typed-status").typedInput('value'));
$("#node-input-inputFromVal").val($("#node-input-typed-inputFrom").typedInput('value'));
$("#node-input-outputToVal").val($("#node-input-typed-outputTo").typedInput('value'));
}
});
</script>
<script type="text/x-red" data-template-name="friendly-id">
<div class="form-row">
<label for="node-input-mode"><i class="fa fa-tasks"></i> <span data-i18n="label.mode.title"></span></label>
<select type="text" id="node-input-mode" style="width:70%">
<option value="ENCODE" data-i18n="label.mode._encode"></option>
<option value="DECODE" data-i18n="label.mode._decode"></option>
<option value="GENERATE-UUID4" data-i18n="label.mode._uuid"></option>
<option value="GENERATE-SHORTID" data-i18n="label.mode._shortid"></option>
<option value="GENERATE-NANOID" data-i18n="label.mode._nanoid"></option>
</select>
</div>
<div id="node-nodeid-line">
<div class="form-row">
<label for="node-input-charset"><i class="fa fa-keyboard-o"></i> <span data-i18n="label.charset.title"></span></label>
<select type="text" id="node-input-charset" style="width:70%">
<option value="DEFAULT" data-i18n="label.charset._default"></option>
<option value="NUMERIC" data-i18n="label.charset._numbers" data-restricted="0123456789"></option>
<option value="LOWERCASE" data-i18n="label.charset._lowercase" data-restricted="abcdefghijklmnopqrstuvwxyz"></option>
<option value="UPPERCASE" data-i18n="label.charset._uppercase" data-restricted="ABCDEFGHIJKLMNOPQRSTUVWXYZ"></option>
<option value="ALPHANUMERIC" data-i18n="label.charset._alphanumeric" data-restricted="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"></option>
<option value="NO-LOOKALIKES" data-i18n="label.charset._nolookalikes" data-restricted="346789ABCDEFGHJKLMNPQRTUVWXYabcdefghijkmnpqrtwxyz"></option>
<option value="NO-LOOKALIKES-SAFE" data-i18n="label.charset._nolookalikessafe" data-restricted="6789BCDFGHJKLMNPQRTWbcdfghjkmnpqrtwz"></option>
<option value="CUSTOM" data-i18n="label.charset._custom"></option>
</select>
</div>
<div class="form-row" id="node-nodeid-customs-line">
<label for="node-input-customs"></label>
<input type="text" id="node-input-customs" data-i18n="[placeholder]label.charset.unique">
</div>
<div class="form-row">
<label for="node-input-charlen"><i class="fa fa-puzzle-piece"></i> <span data-i18n="label.charlen.title"></span></label>
<input type="number" min="2" max="32" id="node-input-charlen" style="text-align:end; width:70px !important" oninput="this.value = Math.min(this.max, Math.max(this.min, this.value))">
</div>
</div>
<hr>
<div class="form-row" id="node-inputs-line">
<label for="node-input-typed-inputFrom"><i class="fa fa-sign-in"></i> <span data-i18n="label.inputFrom"></span></label>
<input id="node-input-typed-inputFrom" type="text" style="width: 70%">
<input id="node-input-inputFromVal" type="hidden">
<input id="node-input-inputFromType" type="hidden">
</div>
<div class="form-row" id="node-outputs-line">
<label for="node-input-typed-outputTo"><i class="fa fa-sign-out"></i> <span data-i18n="label.outputTo"></span></label>
<input id="node-input-typed-outputTo" type="text" style="width: 70%">
<input id="node-input-outputToVal" type="hidden">
<input id="node-input-outputToType" type="hidden">
</div>
<hr>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
</div>
<div class="form-row">
<label for="node-input-tostatus"> </label>
<label for="node-input-tostatus" style="width: 70%;">
<input type="checkbox" id="node-input-tostatus" style="display: inline-block; width: auto; vertical-align: top;"> <span data-i18n="label.tostatus"></span>
</label>
</div>
<div class="form-row" id="node-tostatus-line">
<label for="node-input-typed-status"> </label>
<input id="node-input-typed-status" type="text" style="width: 70%">
<input id="node-input-statusVal" type="hidden">
<input id="node-input-statusType" type="hidden">
</div>
</script>