1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Allow typedInputs to have options plus value

This commit is contained in:
Nick O'Leary 2018-06-21 10:46:07 +01:00
parent a467fe5ed7
commit 461e6562ca
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
2 changed files with 179 additions and 72 deletions

View File

@ -98,14 +98,17 @@
var that = this; var that = this;
this.disarmClick = false; this.disarmClick = false;
this.input = $('<input type="text"></input>');
this.input.insertAfter(this.element);
this.input.val(this.element.val());
this.element.addClass('red-ui-typedInput'); this.element.addClass('red-ui-typedInput');
this.uiWidth = this.element.outerWidth(); this.uiWidth = this.element.outerWidth();
this.elementDiv = this.element.wrap("<div>").parent().addClass('red-ui-typedInput-input'); this.elementDiv = this.input.wrap("<div>").parent().addClass('red-ui-typedInput-input');
this.uiSelect = this.elementDiv.wrap( "<div>" ).parent(); this.uiSelect = this.elementDiv.wrap( "<div>" ).parent();
var attrStyle = this.element.attr('style'); var attrStyle = this.element.attr('style');
var m; var m;
if ((m = /width\s*:\s*(calc\s*\(.*\)|\d+(%|px))/i.exec(attrStyle)) !== null) { if ((m = /width\s*:\s*(calc\s*\(.*\)|\d+(%|px))/i.exec(attrStyle)) !== null) {
this.element.css('width','100%'); this.input.css('width','100%');
this.uiSelect.width(m[1]); this.uiSelect.width(m[1]);
this.uiWidth = null; this.uiWidth = null;
} else { } else {
@ -114,17 +117,19 @@
["Right","Left"].forEach(function(d) { ["Right","Left"].forEach(function(d) {
var m = that.element.css("margin"+d); var m = that.element.css("margin"+d);
that.uiSelect.css("margin"+d,m); that.uiSelect.css("margin"+d,m);
that.element.css("margin"+d,0); that.input.css("margin"+d,0);
}); });
this.uiSelect.addClass("red-ui-typedInput-container"); this.uiSelect.addClass("red-ui-typedInput-container");
this.element.attr('type','hidden');
this.options.types = this.options.types||Object.keys(allOptions); this.options.types = this.options.types||Object.keys(allOptions);
this.selectTrigger = $('<button tabindex="0"></button>').prependTo(this.uiSelect); this.selectTrigger = $('<button tabindex="0"></button>').prependTo(this.uiSelect);
if (this.options.types.length > 1) { $('<i class="red-ui-typedInput-icon fa fa-sort-desc"></i>').toggle(this.options.types.length > 1).appendTo(this.selectTrigger);
$('<i class="fa fa-sort-desc"></i>').appendTo(this.selectTrigger);
} this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger);
this.selectLabel = $('<span></span>').appendTo(this.selectTrigger);
this.types(this.options.types); this.types(this.options.types);
@ -138,14 +143,16 @@
this.typeField = $("<input>",{type:'hidden'}).appendTo(this.uiSelect); this.typeField = $("<input>",{type:'hidden'}).appendTo(this.uiSelect);
} }
this.element.on('focus', function() { this.input.on('focus', function() {
that.uiSelect.addClass('red-ui-typedInput-focus'); that.uiSelect.addClass('red-ui-typedInput-focus');
}); });
this.element.on('blur', function() { this.input.on('blur', function() {
that.uiSelect.removeClass('red-ui-typedInput-focus'); that.uiSelect.removeClass('red-ui-typedInput-focus');
}); });
this.element.on('change', function() { this.input.on('change', function() {
that.validate(); that.validate();
that.element.val(that.value());
that.element.trigger('change',that.propertyType,that.value());
}) })
this.selectTrigger.click(function(event) { this.selectTrigger.click(function(event) {
event.preventDefault(); event.preventDefault();
@ -161,7 +168,7 @@
}) })
// explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline' // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="fa fa-sort-desc"></i></span></button>').appendTo(this.uiSelect); this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-sort-desc"></i></span></button>').appendTo(this.uiSelect);
this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger); this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
this.optionSelectTrigger.click(function(event) { this.optionSelectTrigger.click(function(event) {
event.preventDefault(); event.preventDefault();
@ -177,9 +184,7 @@
that.uiSelect.addClass('red-ui-typedInput-focus'); that.uiSelect.addClass('red-ui-typedInput-focus');
}); });
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"><i class="fa fa-ellipsis-h"></i></button>').appendTo(this.uiSelect); this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"><i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i></button>').appendTo(this.uiSelect);
this.type(this.options.default||this.typeList[0].value); this.type(this.options.default||this.typeList[0].value);
}, },
_showTypeMenu: function() { _showTypeMenu: function() {
@ -187,7 +192,7 @@
this._showMenu(this.menu,this.selectTrigger); this._showMenu(this.menu,this.selectTrigger);
this.menu.find("[value='"+this.propertyType+"']").focus(); this.menu.find("[value='"+this.propertyType+"']").focus();
} else { } else {
this.element.focus(); this.input.focus();
} }
}, },
_showOptionSelectMenu: function() { _showOptionSelectMenu: function() {
@ -196,8 +201,8 @@
minWidth:this.optionSelectLabel.width() minWidth:this.optionSelectLabel.width()
}); });
this._showMenu(this.optionMenu,this.optionSelectLabel); this._showMenu(this.optionMenu,this.optionSelectTrigger);
var selectedOption = this.optionMenu.find("[value='"+this.value()+"']"); var selectedOption = this.optionMenu.find("[value='"+this.optionValue+"']");
if (selectedOption.length === 0) { if (selectedOption.length === 0) {
selectedOption = this.optionMenu.children(":first"); selectedOption = this.optionMenu.children(":first");
} }
@ -209,7 +214,7 @@
$(document).off("mousedown.close-property-select"); $(document).off("mousedown.close-property-select");
menu.hide(); menu.hide();
if (this.elementDiv.is(":visible")) { if (this.elementDiv.is(":visible")) {
this.element.focus(); this.input.focus();
} else if (this.optionSelectTrigger.is(":visible")){ } else if (this.optionSelectTrigger.is(":visible")){
this.optionSelectTrigger.focus(); this.optionSelectTrigger.focus();
} else { } else {
@ -228,10 +233,19 @@
op.text(opt.label); op.text(opt.label);
} }
if (opt.icon) { if (opt.icon) {
$('<img>',{src:opt.icon,style:"margin-right: 4px; height: 18px;"}).prependTo(op); if (opt.icon.indexOf("<") === 0) {
$(opt.icon).prependTo(op);
} else if (opt.icon.indexOf("/") !== -1) {
$('<img>',{src:opt.icon,style:"margin-right: 4px; height: 18px;"}).prependTo(op);
} else {
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(op);
}
} else { } else {
op.css({paddingLeft: "18px"}); op.css({paddingLeft: "18px"});
} }
if (!opt.icon && !opt.label) {
op.text(opt.value);
}
op.click(function(event) { op.click(function(event) {
event.preventDefault(); event.preventDefault();
@ -310,7 +324,8 @@
if (this.uiWidth !== null) { if (this.uiWidth !== null) {
this.uiSelect.width(this.uiWidth); this.uiSelect.width(this.uiWidth);
} }
if (this.typeMap[this.propertyType] && this.typeMap[this.propertyType].hasValue === false) { var type = this.typeMap[this.propertyType];
if (type && type.hasValue === false) {
this.selectTrigger.addClass("red-ui-typedInput-full-width"); this.selectTrigger.addClass("red-ui-typedInput-full-width");
} else { } else {
this.selectTrigger.removeClass("red-ui-typedInput-full-width"); this.selectTrigger.removeClass("red-ui-typedInput-full-width");
@ -320,12 +335,64 @@
this.elementDiv.css('right',"22px"); this.elementDiv.css('right',"22px");
} else { } else {
this.elementDiv.css('right','0'); this.elementDiv.css('right','0');
this.input.css({
'border-top-right-radius': '4px',
'border-bottom-right-radius': '4px'
});
} }
// if (this.optionSelectTrigger) {
// this.optionSelectTrigger.css({'left':(labelWidth)+"px",'width':'calc( 100% - '+labelWidth+'px )'});
// }
if (this.optionSelectTrigger) { if (this.optionSelectTrigger) {
this.optionSelectTrigger.css({'left':(labelWidth)+"px",'width':'calc( 100% - '+labelWidth+'px )'}); if (type && type.options && type.hasValue === true) {
this.optionSelectLabel.css({'left':'auto'})
var lw = this._getLabelWidth(this.optionSelectLabel);
this.optionSelectTrigger.css({'width':(23+lw)+"px"});
this.elementDiv.css('right',(23+lw)+"px");
this.input.css({
'border-top-right-radius': 0,
'border-bottom-right-radius': 0
});
} else {
this.optionSelectLabel.css({'left':'0'})
this.optionSelectTrigger.css({'width':'calc( 100% - '+labelWidth+'px )'});
if (!this.optionExpandButton.is(":visible")) {
this.elementDiv.css({'right':0});
this.input.css({
'border-top-right-radius': '4px',
'border-bottom-right-radius': '4px'
});
}
}
} }
} }
}, },
_updateOptionSelectLabel: function(o) {
var opt = this.typeMap[this.propertyType];
this.optionSelectLabel.empty();
if (o.icon) {
if (o.icon.indexOf("<") === 0) {
$(o.icon).prependTo(this.optionSelectLabel);
} else if (o.icon.indexOf("/") !== -1) {
// url
$('<img>',{src:o.icon,style:"height: 18px;"}).prependTo(this.optionSelectLabel);
} else {
// icon class
$('<i>',{class:"red-ui-typedInput-icon "+o.icon}).prependTo(this.optionSelectLabel);
}
} else if (o.label) {
this.optionSelectLabel.text(o.label);
} else {
this.optionSelectLabel.text(o.value);
}
if (opt.hasValue) {
this.optionValue = o.value;
this._resize();
this.input.trigger('change',this.propertyType,this.value());
}
},
_destroy: function() { _destroy: function() {
this.menu.remove(); this.menu.remove();
}, },
@ -344,6 +411,7 @@
return result; return result;
}); });
this.selectTrigger.toggleClass("disabled", this.typeList.length === 1); this.selectTrigger.toggleClass("disabled", this.typeList.length === 1);
this.selectTrigger.find(".fa-sort-desc").toggle(this.typeList.length > 1)
if (this.menu) { if (this.menu) {
this.menu.remove(); this.menu.remove();
} }
@ -351,6 +419,7 @@
if (currentType && !this.typeMap.hasOwnProperty(currentType)) { if (currentType && !this.typeMap.hasOwnProperty(currentType)) {
this.type(this.typeList[0].value); this.type(this.typeList[0].value);
} }
setTimeout(function() {that._resize();},0);
}, },
width: function(desiredWidth) { width: function(desiredWidth) {
this.uiWidth = desiredWidth; this.uiWidth = desiredWidth;
@ -358,33 +427,33 @@
}, },
value: function(value) { value: function(value) {
if (!arguments.length) { if (!arguments.length) {
return this.element.val(); var v = this.input.val();
if (this.typeMap[this.propertyType].export) {
v = this.typeMap[this.propertyType].export(v,this.optionValue)
}
return v;
} else { } else {
var selectedOption;
if (this.typeMap[this.propertyType].options) { if (this.typeMap[this.propertyType].options) {
var validValue = false;
var label;
for (var i=0;i<this.typeMap[this.propertyType].options.length;i++) { for (var i=0;i<this.typeMap[this.propertyType].options.length;i++) {
var op = this.typeMap[this.propertyType].options[i]; var op = this.typeMap[this.propertyType].options[i];
if (typeof op === "string") { if (typeof op === "string") {
if (op === value) { if (op === value) {
label = value; selectedOption = this.activeOptions[op];
validValue = true;
break; break;
} }
} else if (op.value === value) { } else if (op.value === value) {
label = op.label||op.value; selectedOption = op;
validValue = true;
break; break;
} }
} }
if (!validValue) { if (!selectedOption) {
value = ""; selectedOption = {value:""}
label = "";
} }
this.optionSelectLabel.text(label); this._updateOptionSelectLabel(selectedOption)
} }
this.element.val(value); this.input.val(value);
this.element.trigger('change',this.type(),value); this.input.trigger('change',this.type(),value);
} }
}, },
type: function(type) { type: function(type) {
@ -412,37 +481,72 @@
} }
if (this.optionSelectTrigger) { if (this.optionSelectTrigger) {
this.optionSelectTrigger.show(); this.optionSelectTrigger.show();
this.elementDiv.hide(); if (!opt.hasValue) {
this.elementDiv.hide();
} else {
this.elementDiv.show();
}
this.activeOptions = {};
opt.options.forEach(function(o) {
if (typeof o === 'string') {
that.activeOptions[o] = {label:o,value:o};
} else {
that.activeOptions[o.value] = o;
}
})
this.optionMenu = this._createMenu(opt.options,function(v){ this.optionMenu = this._createMenu(opt.options,function(v){
that.optionSelectLabel.text(v); that._updateOptionSelectLabel(that.activeOptions[v]);
that.value(v); if (!opt.hasValue) {
that.value(that.activeOptions[v].value)
}
}); });
var currentVal = this.element.val();
var validValue = false;
var op; var op;
for (var i=0;i<opt.options.length;i++) { if (!opt.hasValue) {
op = opt.options[i]; var currentVal = this.input.val();
if (typeof op === "string") { var validValue = false;
if (op === currentVal) { for (var i=0;i<opt.options.length;i++) {
this.optionSelectLabel.text(currentVal); op = opt.options[i];
if (typeof op === "string" && op === currentVal) {
that._updateOptionSelectLabel({value:currentVal});
validValue = true;
break;
} else if (op.value === currentVal) {
that._updateOptionSelectLabel(op);
validValue = true; validValue = true;
break; break;
} }
} else if (op.value === currentVal) {
this.optionSelectLabel.text(op.label||op.value);
validValue = true;
break;
} }
} if (!validValue) {
if (!validValue) { op = opt.options[0];
op = opt.options[0]; if (typeof op === "string") {
if (typeof op === "string") { this.value(op);
this.value(op); that._updateOptionSelectLabel({value:op});
} else {
this.value(op.value);
that._updateOptionSelectLabel(op);
}
}
} else {
var selectedOption = this.optionValue||opt.options[0];
if (opt.parse) {
var parts = opt.parse(this.input.val());
if (parts.option) {
selectedOption = parts.option;
}
this.input.val(parts.value);
if (opt.export) {
this.element.val(opt.export(parts.value,parts.option||selectedOption));
}
}
if (typeof selectedOption === "string") {
this.optionValue = selectedOption;
this._updateOptionSelectLabel(this.activeOptions[selectedOption]);
} else { } else {
this.value(op.value); this.optionValue = selectedOption.value;
this._updateOptionSelectLabel(selectedOption);
} }
} }
console.log(validValue);
} }
} else { } else {
if (this.optionMenu) { if (this.optionMenu) {
@ -453,12 +557,12 @@
this.optionSelectTrigger.hide(); this.optionSelectTrigger.hide();
} }
if (opt.hasValue === false) { if (opt.hasValue === false) {
this.oldValue = this.element.val(); this.oldValue = this.input.val();
this.element.val(""); this.input.val("");
this.elementDiv.hide(); this.elementDiv.hide();
} else { } else {
if (this.oldValue !== undefined) { if (this.oldValue !== undefined) {
this.element.val(this.oldValue); this.input.val(this.oldValue);
delete this.oldValue; delete this.oldValue;
} }
this.elementDiv.show(); this.elementDiv.show();
@ -473,7 +577,7 @@
} else { } else {
this.optionExpandButton.hide(); this.optionExpandButton.hide();
} }
this.element.trigger('change',this.propertyType,this.value()); this.input.trigger('change',this.propertyType,this.value());
} }
if (image) { if (image) {
image.onload = function() { that._resize(); } image.onload = function() { that._resize(); }

View File

@ -23,7 +23,7 @@
margin: 0; margin: 0;
vertical-align: middle; vertical-align: middle;
box-sizing: border-box; box-sizing: border-box;
overflow:hidden; overflow:visible;
position: relative; position: relative;
.red-ui-typedInput-input { .red-ui-typedInput-input {
position: absolute; position: absolute;
@ -43,6 +43,7 @@
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
box-shadow: none; box-shadow: none;
vertical-align: middle; vertical-align: middle;
// backgroun/d: #f0fff0;
} }
&.red-ui-typedInput-focus:not(.input-error) { &.red-ui-typedInput-focus:not(.input-error) {
@ -63,7 +64,7 @@
line-height: 32px; line-height: 32px;
vertical-align: middle; vertical-align: middle;
color: #555; color: #555;
i { i.red-ui-typedInput-icon {
position: relative; position: relative;
top: -3px; top: -3px;
margin-left: 1px; margin-left: 1px;
@ -76,11 +77,11 @@
} }
&.disabled { &.disabled {
cursor: default; cursor: default;
i { i.red-ui-typedInput-icon {
color: #bbb; color: #bbb;
} }
} }
span { .red-ui-typedInput-type-label,.red-ui-typedInput-option-label {
display: inline-block; display: inline-block;
height: 100%; height: 100%;
padding: 0 1px 0 5px; padding: 0 1px 0 5px;
@ -121,26 +122,25 @@
border-bottom-right-radius: 4px; border-bottom-right-radius: 4px;
padding: 0 0 0 0; padding: 0 0 0 0;
position:absolute; position:absolute;
width: calc( 100% ); right: 0;
i {
position:absolute;
right: 4px;
top: 7px;
}
.red-ui-typedInput-option-label { .red-ui-typedInput-option-label {
background:#fff; background:$typedInput-button-background;
position:absolute; position:absolute;
left:0; left:0;
right:23px; right:23px;
top: 0; top: 0;
padding: 0 5px 0 5px; padding: 0 5px 0 8px;
i.red-ui-typedInput-icon {
margin-right: 4px;
margin-top: 4px;
}
} }
.red-ui-typedInput-option-caret { .red-ui-typedInput-option-caret {
top: 0; top: 0;
position: absolute; position: absolute;
right: 0; right: 0;
width: 17px; width: 17px;
padding-left: 6px;
} }
&:focus { &:focus {
box-shadow: none; box-shadow: none;
@ -175,4 +175,7 @@
background: $typedInput-button-background-active; background: $typedInput-button-background-active;
} }
} }
.red-ui-typedInput-icon {
margin-right: 4px;
}
} }