/** * Copyright JS Foundation and other contributors, http://js.foundation * * 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. **/ (function($) { var contextParse = function(v,defaultStore) { var parts = RED.utils.parseContextKey(v, defaultStore&&defaultStore.value); return { option: parts.store, value: parts.key } } var contextExport = function(v,opt) { if (!opt) { return v; } var store = ((typeof opt === "string")?opt:opt.value) if (store !== RED.settings.context.default) { return "#:("+store+")::"+v; } else { return v; } } var contextLabel = function(container,value) { var that = this; container.css("pointer-events","none"); container.css("flex-grow",0); container.css("position",'relative'); container.css("overflow",'visible'); $('
').text(value).css({ position: "absolute", bottom:"-2px", right: "5px", "font-size": "0.7em", opacity: 0.3 }).appendTo(container); this.elementDiv.show(); } var mapDeprecatedIcon = function(icon) { if (/^red\/images\/typedInput\/.+\.png$/.test(icon)) { icon = icon.replace(/.png$/,".svg"); } return icon; } 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($('').text(match.pre)); } if(match.match) { els.push($('',{style:"font-weight: bold; color: var(--red-ui-text-color-link);"}).text(match.match)); } if(match.post) { els.push($('').text(match.post)); } return els; } return function(val) { var matches = []; options.forEach(opt => { const optVal = opt.value; const optSrc = (opt.source||[]).join(","); const valMatch = getMatch(optVal, val); const srcMatch = getMatch(optSrc, val); if (valMatch.found || srcMatch.found) { const element = $('
',{style: "display: flex"}); const valEl = $('
',{style:"font-family: var(--red-ui-monospace-font); white-space:nowrap; overflow: hidden; flex-grow:1"}); valEl.append(generateSpans(valMatch)); valEl.appendTo(element); if (optSrc) { const optEl = $('
').css({ "font-size": "0.8em" }); optEl.append(generateSpans(srcMatch)); optEl.appendTo(element); } matches.push({ value: optVal, label: element, i: (valMatch.found ? valMatch.index : srcMatch.index) }); } }) matches.sort(function(A,B){return A.i-B.i}) return matches; } } // This is a hand-generated list of completions for the core nodes (based on the node help html). var msgCompletions = [ { 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.body", source: ["http in"]}, { value: "req.headers", source: ["http in"]}, { value: "req.query", source: ["http in"]}, { value: "req.params", source: ["http in"]}, { value: "req.cookies", source: ["http in"]}, { value: "req.files", source: ["http in"]}, { value: "requestTimeout", source: ["http request"] }, { value: "reset", source: ["delay","trigger","join","rbe"] }, { value: "responseCookies", source: ["http request"] }, { value: "responseTopic", source: ["mqtt"] }, { value: "responseUrl", source: ["http request"] }, { value: "restartTimeout", source: ["join"] }, { value: "retain", source: ["mqtt"] }, { value: "schema", source: ["json"] }, { value: "select", source: ["html"] }, { 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: "toFront", source: ["delay"] }, { value: "url", source: ["http request"] }, { value: "userProperties", source: ["mqtt"] }, { value: "_session", source: ["websocket out","tcp out"] }, ] var allOptions = { msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression, autoComplete: autoComplete(msgCompletions)}, flow: {value:"flow",label:"flow.",hasValue:true, options:[], validate:RED.utils.validatePropertyExpression, parse: contextParse, export: contextExport, valueLabel: contextLabel }, global: {value:"global",label:"global.",hasValue:true, options:[], validate:RED.utils.validatePropertyExpression, parse: contextParse, export: contextExport, valueLabel: contextLabel }, str: {value:"str",label:"string",icon:"red/images/typedInput/az.svg"}, num: {value:"num",label:"number",icon:"red/images/typedInput/09.svg",validate:/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/}, bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.svg",options:["true","false"]}, json: { value:"json", label:"JSON", icon:"red/images/typedInput/json.svg", validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}}, expand: function() { var that = this; var value = this.value(); try { value = JSON.stringify(JSON.parse(value),null,4); } catch(err) { } RED.editor.editJSON({ value: value, stateId: RED.editor.generateViewStateId("typedInput", that, "json"), focus: true, complete: function(v) { var value = v; try { value = JSON.stringify(JSON.parse(v)); } catch(err) { } that.value(value); } }) } }, re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.svg"}, date: {value:"date",label:"timestamp",icon:"fa fa-clock-o",hasValue:false}, jsonata: { value: "jsonata", label: "expression", icon: "red/images/typedInput/expr.svg", validate: function(v) { try{jsonata(v);return true;}catch(e){return false;}}, expand:function() { var that = this; RED.editor.editExpression({ value: this.value().replace(/\t/g,"\n"), stateId: RED.editor.generateViewStateId("typedInput", that, "jsonata"), focus: true, complete: function(v) { that.value(v.replace(/\n/g,"\t")); } }) } }, bin: { value: "bin", label: "buffer", icon: "red/images/typedInput/bin.svg", expand: function() { var that = this; RED.editor.editBuffer({ value: this.value(), stateId: RED.editor.generateViewStateId("typedInput", that, "bin"), focus: true, complete: function(v) { that.value(v); } }) } }, env: { value: "env", label: "env variable", icon: "red/images/typedInput/env.svg" }, node: { value: "node", label: "node", icon: "red/images/typedInput/target.svg", valueLabel: function(container,value) { var node = RED.nodes.node(value); var nodeDiv = $('
',{class:"red-ui-search-result-node"}).css({ "margin-top": "2px", "margin-left": "3px" }).appendTo(container); var nodeLabel = $('').css({ "line-height": "32px", "margin-left": "6px" }).appendTo(container); if (node) { var colour = RED.utils.getNodeColor(node.type,node._def); var icon_url = RED.utils.getNodeIcon(node._def,node); if (node.type === 'tab') { colour = "#C0DEED"; } nodeDiv.css('backgroundColor',colour); var iconContainer = $('
',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv); RED.utils.createIconElement(icon_url, iconContainer, true); var l = RED.utils.getNodeLabel(node,node.id); nodeLabel.text(l); } else { nodeDiv.css({ 'backgroundColor': '#eee', 'border-style' : 'dashed' }); } }, expand: function() { var that = this; RED.tray.hide(); RED.view.selectNodes({ single: true, selected: [that.value()], onselect: function(selection) { that.value(selection.id); RED.tray.show(); }, oncancel: function() { RED.tray.show(); } }) } }, cred:{ value:"cred", label:"credential", icon:"fa fa-lock", inputType: "password", valueLabel: function(container,value) { var that = this; container.css("pointer-events","none"); container.css("flex-grow",0); this.elementDiv.hide(); var buttons = $('
').css({ position: "absolute", right:"6px", top: "6px", "pointer-events":"all" }).appendTo(container); var eyeButton = $('').css({ width:"20px" }).appendTo(buttons).on("click", function(evt) { evt.preventDefault(); var cursorPosition = that.input[0].selectionStart; var currentType = that.input.attr("type"); if (currentType === "text") { that.input.attr("type","password"); eyeCon.removeClass("fa-eye-slash").addClass("fa-eye"); setTimeout(function() { that.input.focus(); that.input[0].setSelectionRange(cursorPosition, cursorPosition); },50); } else { that.input.attr("type","text"); eyeCon.removeClass("fa-eye").addClass("fa-eye-slash"); setTimeout(function() { that.input.focus(); that.input[0].setSelectionRange(cursorPosition, cursorPosition); },50); } }).hide(); var eyeCon = $('').css("margin-left","-2px").appendTo(eyeButton); if (value === "__PWRD__") { var innerContainer = $('
').css({ padding:"6px 6px", borderRadius:"4px" }).addClass("red-ui-typedInput-value-label-inactive").appendTo(container); var editButton = $('').appendTo(buttons).on("click", function(evt) { evt.preventDefault(); innerContainer.hide(); container.css("background","none"); container.css("pointer-events","none"); that.input.val(""); that.element.val(""); that.elementDiv.show(); editButton.hide(); cancelButton.show(); eyeButton.show(); setTimeout(function() { that.input.focus(); },50); }); var cancelButton = $('').css("margin-left","3px").appendTo(buttons).on("click", function(evt) { evt.preventDefault(); innerContainer.show(); container.css("background",""); that.input.val("__PWRD__"); that.element.val("__PWRD__"); that.elementDiv.hide(); editButton.show(); cancelButton.hide(); eyeButton.hide(); that.input.attr("type","password"); eyeCon.removeClass("fa-eye-slash").addClass("fa-eye"); }).hide(); } else { container.css("background","none"); container.css("pointer-events","none"); this.elementDiv.show(); eyeButton.show(); } } } }; // For a type with options, check value is a valid selection // If !opt.multiple, returns the valid option object // if opt.multiple, returns an array of valid option objects // If not valid, returns null; function isOptionValueValid(opt, currentVal) { if (!opt.multiple) { for (var i=0;i'} }).sort(function(A,B) { if (A.value === RED.settings.context.default) { return -1; } else if (B.value === RED.settings.context.default) { return 1; } else { return A.value.localeCompare(B.value); } }) if (contextOptions.length < 2) { allOptions.flow.options = []; allOptions.global.options = []; } else { allOptions.flow.options = contextOptions; allOptions.global.options = contextOptions; } } nlsd = true; var that = this; this.identifier = this.element.attr('id') || "TypedInput-"+Math.floor(Math.random()*100); if (this.options.debug) { console.log(this.identifier,"Create",{defaultType:this.options.default, value:this.element.val()}) } this.disarmClick = false; this.input = $(''); this.input.insertAfter(this.element); this.input.val(this.element.val()); this.element.addClass('red-ui-typedInput'); this.uiWidth = this.element.outerWidth(); this.elementDiv = this.input.wrap("
").parent().addClass('red-ui-typedInput-input-wrap'); this.uiSelect = this.elementDiv.wrap( "
" ).parent(); var attrStyle = this.element.attr('style'); var m; if ((m = /width\s*:\s*(calc\s*\(.*\)|\d+(%|px))/i.exec(attrStyle)) !== null) { this.input.css('width','100%'); this.uiSelect.width(m[1]); this.uiWidth = null; } else if (this.uiWidth !== 0){ this.uiSelect.width(this.uiWidth); } ["Right","Left"].forEach(function(d) { var m = that.element.css("margin"+d); that.uiSelect.css("margin"+d,m); that.input.css("margin"+d,0); }); ["type","placeholder","autocomplete","data-i18n"].forEach(function(d) { var m = that.element.attr(d); that.input.attr(d,m); }); this.defaultInputType = this.input.attr('type'); // Used to remember selections per-type to restore them when switching between types this.oldValues = {}; this.uiSelect.addClass("red-ui-typedInput-container"); this.element.attr('type','hidden'); if (!this.options.types && this.options.type) { this.options.types = [this.options.type] } else { this.options.types = this.options.types||Object.keys(allOptions); } this.selectTrigger = $('').prependTo(this.uiSelect); $('').toggle(this.options.types.length > 1).appendTo(this.selectTrigger); this.selectLabel = $('').appendTo(this.selectTrigger); this.valueLabelContainer = $('
').appendTo(this.uiSelect) this.types(this.options.types); if (this.options.typeField) { this.typeField = $(this.options.typeField).hide(); var t = this.typeField.val(); if (t && this.typeMap[t]) { this.options.default = t; } } else { this.typeField = $("",{type:'hidden'}).appendTo(this.uiSelect); } this.input.on('focus', function() { that.uiSelect.addClass('red-ui-typedInput-focus'); }); this.input.on('blur', function() { that.uiSelect.removeClass('red-ui-typedInput-focus'); }); this.input.on('change', function() { that.validate(); that.element.val(that.value()); that.element.trigger('change',[that.propertyType,that.value()]); }); this.input.on('keyup', function(evt) { that.validate(); that.element.val(that.value()); that.element.trigger('keyup',evt); }); this.input.on('paste', function(evt) { that.validate(); that.element.val(that.value()); that.element.trigger('paste',evt); }); this.input.on('keydown', function(evt) { if (that.typeMap[that.propertyType].autoComplete) { return } if (evt.keyCode >= 37 && evt.keyCode <= 40) { evt.stopPropagation(); } }) this.selectTrigger.on("click", function(event) { event.preventDefault(); event.stopPropagation(); that._showTypeMenu(); }); this.selectTrigger.on('keydown',function(evt) { if (evt.keyCode === 40) { // Down that._showTypeMenu(); } evt.stopPropagation(); }).on('focus', function() { that.uiSelect.addClass('red-ui-typedInput-focus'); }).on('blur', function() { var opt = that.typeMap[that.propertyType]; if (opt.hasValue === false) { that.uiSelect.removeClass('red-ui-typedInput-focus'); } }) // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline' this.optionSelectTrigger = $('').appendTo(this.uiSelect); this.optionSelectLabel = $('').prependTo(this.optionSelectTrigger); // RED.popover.tooltip(this.optionSelectLabel,function() { // return that.optionValue; // }); this.optionSelectTrigger.on("click", function(event) { event.preventDefault(); event.stopPropagation(); that._showOptionSelectMenu(); }).on('keydown', function(evt) { if (evt.keyCode === 40) { // Down that._showOptionSelectMenu(); } evt.stopPropagation(); }).on('blur', function() { that.uiSelect.removeClass('red-ui-typedInput-focus'); }).on('focus', function() { that.uiSelect.addClass('red-ui-typedInput-focus'); }); this.optionExpandButton = $('').appendTo(this.uiSelect); this.optionExpandButtonIcon = $('').appendTo(this.optionExpandButton); this.type(this.typeField.val() || this.options.default||this.typeList[0].value); this.typeChanged = !!this.options.default; }catch(err) { console.log(err.stack); } }, _showTypeMenu: function() { if (this.typeList.length > 1) { this._showMenu(this.menu,this.selectTrigger); var selected = this.menu.find("[value='"+this.propertyType+"']"); setTimeout(function() { selected.trigger("focus"); },120); } else { this.input.trigger("focus"); } }, _showOptionSelectMenu: function() { if (this.optionMenu) { this.optionMenu.css({ minWidth:this.optionSelectLabel.width() }); this._showMenu(this.optionMenu,this.optionSelectTrigger); var targetValue = this.optionValue; if (this.optionValue === null || this.optionValue === undefined) { targetValue = this.value(); } var selectedOption = this.optionMenu.find("[value='"+targetValue+"']"); if (selectedOption.length === 0) { selectedOption = this.optionMenu.children(":first"); } selectedOption.trigger("focus"); } }, _hideMenu: function(menu) { $(document).off("mousedown.red-ui-typedInput-close-property-select"); menu.hide(); menu.css({ height: "auto" }); if (menu.opts.multiple) { var selected = []; menu.find('input[type="checkbox"]').each(function() { if ($(this).prop("checked")) { selected.push($(this).data('value')) } }) menu.callback(selected); } if (this.elementDiv.is(":visible")) { this.input.trigger("focus"); } else if (this.optionSelectTrigger.is(":visible")){ this.optionSelectTrigger.trigger("focus"); } else { this.selectTrigger.trigger("focus"); } }, _createMenu: function(menuOptions,opts,callback) { var that = this; var menu = $("
").addClass("red-ui-typedInput-options red-ui-editor-dialog"); menu.opts = opts; menu.callback = callback; menuOptions.forEach(function(opt) { if (typeof opt === 'string') { opt = {value:opt,label:opt}; } var op = $('').attr("value",opt.value).appendTo(menu); if (opt.label) { op.text(opt.label); } if (opt.title) { op.prop('title', opt.title) } if (opt.icon) { if (opt.icon.indexOf("<") === 0) { $(opt.icon).prependTo(op); } else if (opt.icon.indexOf("/") !== -1) { $('',{class:"red-ui-typedInput-icon", style:"mask-image: url("+opt.icon+"); -webkit-mask-image: url("+opt.icon+");"}).prependTo(op); } else { $('',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(op); } } else { op.css({paddingLeft: "18px"}); } if (!opt.icon && !opt.label) { op.text(opt.value); } var cb; if (opts.multiple) { cb = $('').css("pointer-events","none").data('value',opt.value).prependTo(op).on("mousedown", function(evt) { evt.preventDefault() }); } op.on("click", function(event) { event.preventDefault(); event.stopPropagation(); if (!opts.multiple) { callback(opt.value); that._hideMenu(menu); } else { cb.prop("checked",!cb.prop("checked")); } }); }); menu.css({ display: "none" }); menu.appendTo(document.body); menu.on('keydown', function(evt) { if (evt.keyCode === 40) { evt.preventDefault(); // DOWN $(this).children(":focus").next().trigger("focus"); } else if (evt.keyCode === 38) { evt.preventDefault(); // UP $(this).children(":focus").prev().trigger("focus"); } else if (evt.keyCode === 27) { // ESCAPE evt.preventDefault(); that._hideMenu(menu); } evt.stopPropagation(); }) return menu; }, _showMenu: function(menu,relativeTo) { if (this.disarmClick) { this.disarmClick = false; return } if (menu.opts.multiple) { var selected = {}; this.value().split(",").forEach(function(f) { selected[f] = true; }) menu.find('input[type="checkbox"]').each(function() { $(this).prop("checked",selected[$(this).data('value')]) }) } var that = this; var pos = relativeTo.offset(); var height = relativeTo.height(); var menuHeight = menu.height(); var top = (height+pos.top); if (top+menuHeight-$(document).scrollTop() > $(window).height()) { top -= (top+menuHeight)-$(window).height()+5; } if (top < 0) { menu.height(menuHeight+top) top = 0; } menu.css({ top: top+"px", left: (pos.left)+"px", }); menu.slideDown(100); this._delay(function() { that.uiSelect.addClass('red-ui-typedInput-focus'); $(document).on("mousedown.red-ui-typedInput-close-property-select", function(event) { if(!$(event.target).closest(menu).length) { that._hideMenu(menu); } if ($(event.target).closest(relativeTo).length) { that.disarmClick = true; event.preventDefault(); } }) }); }, _getLabelWidth: function(label, done) { var labelWidth = label.outerWidth(); if (labelWidth === 0) { var wrapper = $('
').css({ position:"absolute", "white-space": "nowrap", top:-2000 }).appendTo(document.body); var container = $('
').appendTo(wrapper); var newTrigger = label.clone().appendTo(container); setTimeout(function() { labelWidth = newTrigger.outerWidth(); wrapper.remove(); done(labelWidth); },50) } else { done(labelWidth); } }, _updateOptionSelectLabel: function(o) { var opt = this.typeMap[this.propertyType]; this.optionSelectLabel.empty(); if (opt.hasValue) { this.valueLabelContainer.empty(); this.valueLabelContainer.show(); } else { this.valueLabelContainer.hide(); } if (this.typeMap[this.propertyType].valueLabel) { if (opt.multiple) { this.typeMap[this.propertyType].valueLabel.call(this,opt.hasValue?this.valueLabelContainer:this.optionSelectLabel,o); } else { this.typeMap[this.propertyType].valueLabel.call(this,opt.hasValue?this.valueLabelContainer:this.optionSelectLabel,o.value); } } if (!this.typeMap[this.propertyType].valueLabel || opt.hasValue) { if (!opt.multiple) { if (o.icon) { if (o.icon.indexOf("<") === 0) { $(o.icon).prependTo(this.optionSelectLabel); } else if (o.icon.indexOf("/") !== -1) { // url $('',{src:mapDeprecatedIcon(o.icon),style:"height: 18px;"}).prependTo(this.optionSelectLabel); } else { // icon class $('',{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.input.trigger('change',[this.propertyType,this.value()]); } } else { this.optionSelectLabel.text(o.length+" selected"); } } }, _destroy: function() { if (this.optionMenu) { this.optionMenu.remove(); } this.menu.remove(); this.uiSelect.remove(); }, types: function(types) { var that = this; var currentType = this.type(); this.typeMap = {}; var firstCall = (this.typeList === undefined); this.typeList = types.map(function(opt) { var result; if (typeof opt === 'string') { result = allOptions[opt]; } else { result = opt; } that.typeMap[result.value] = result; return result; }); if (this.typeList.length < 2) { this.selectTrigger.attr("tabindex", -1) this.selectTrigger.on("mousedown.red-ui-typedInput-focus-block", function(evt) { evt.preventDefault(); }) } else { this.selectTrigger.attr("tabindex", 0) this.selectTrigger.off("mousedown.red-ui-typedInput-focus-block") } this.selectTrigger.toggleClass("disabled", this.typeList.length === 1); this.selectTrigger.find(".fa-caret-down").toggle(this.typeList.length > 1) if (this.menu) { this.menu.remove(); } this.menu = this._createMenu(this.typeList,{},function(v) { that.type(v) }); if (currentType && !this.typeMap.hasOwnProperty(currentType)) { if (!firstCall) { this.type(this.typeList[0].value); } } else { this.propertyType = null; if (!firstCall) { this.type(currentType); } } if (this.typeList.length === 1 && !this.typeList[0].icon && (!this.typeList[0].label || this.typeList[0].showLabel === false)) { this.selectTrigger.hide() } else { this.selectTrigger.show() } }, width: function(desiredWidth) { this.uiWidth = desiredWidth; if (this.uiWidth !== null) { this.uiSelect.width(this.uiWidth); } }, value: function(value) { var that = this; // If the default type has been set to an invalid type, then on first // creation, the current propertyType will not exist. Default to an // empty object on the assumption the corrent type will be set shortly var opt = this.typeMap[this.propertyType] || {}; if (!arguments.length) { var v = this.input.val(); if (opt.export) { v = opt.export(v,this.optionValue) } return v; } else { if (this.options.debug) { console.log(this.identifier,"----- SET VALUE ------",value) } var selectedOption = []; var valueToCheck = value; if (opt.options) { if (opt.hasValue && opt.parse) { var parts = opt.parse(value); if (this.options.debug) { console.log(this.identifier,"new parse",parts) } value = parts.value; valueToCheck = parts.option || parts.value; } var checkValues = [valueToCheck]; if (opt.multiple) { selectedOption = []; checkValues = valueToCheck.split(","); } checkValues.forEach(function(valueToCheck) { for (var i=0;i',{class:"red-ui-typedInput-icon", style:"mask-image: url("+opt.icon+"); -webkit-mask-image: url("+opt.icon+"); margin-right: 4px;height: 18px;width:13px"}).prependTo(this.selectLabel); } else { $('',{class:"red-ui-typedInput-icon "+opt.icon,style:"min-width: 13px; margin-right: 4px;"}).prependTo(this.selectLabel); } } if (opt.hasValue === false || (opt.showLabel !== false && !opt.icon)) { this.selectLabel.text(opt.label); } if (opt.label) { this.selectTrigger.attr("title",opt.label); } else { this.selectTrigger.attr("title",""); } if (opt.hasValue === false) { this.selectTrigger.addClass("red-ui-typedInput-full-width"); } else { this.selectTrigger.removeClass("red-ui-typedInput-full-width"); } if (this.optionMenu) { this.optionMenu.remove(); this.optionMenu = null; } if (opt.options) { if (this.optionExpandButton) { this.optionExpandButton.hide(); this.optionExpandButton.shown = false; } if (this.optionSelectTrigger) { this.optionSelectTrigger.css({"display":"inline-flex"}); if (!opt.hasValue) { this.optionSelectTrigger.css({"flex-grow":1}) this.elementDiv.hide(); this.valueLabelContainer.hide(); } else { this.optionSelectTrigger.css({"flex-grow":0}) this.elementDiv.show(); this.valueLabelContainer.hide(); } this.activeOptions = {}; opt.options.forEach(function(o) { if (typeof o === 'string') { that.activeOptions[o] = {label:o,value:o}; } else { that.activeOptions[o.value] = o; } }); if (!that.activeOptions.hasOwnProperty(that.optionValue)) { that.optionValue = null; } var op; if (!opt.hasValue) { // Check the value is valid for the available options var validValues = isOptionValueValid(opt,this.input.val()); if (!opt.multiple) { if (validValues) { that._updateOptionSelectLabel(validValues) } else { op = opt.options[0]; if (typeof op === "string") { this.value(op); that._updateOptionSelectLabel({value:op}); } else { this.value(op.value); that._updateOptionSelectLabel(op); } } } else { if (!validValues) { validValues = (opt.default || []).map(function(v) { return typeof v === "string"?v:v.value }); this.value(validValues.join(",")); } that._updateOptionSelectLabel(validValues); } } else { var selectedOption = this.optionValue||opt.options[0]; if (opt.parse) { var selectedOptionObj = typeof selectedOption === "string"?{value:selectedOption}:selectedOption var parts = opt.parse(this.input.val(),selectedOptionObj); if (parts.option) { selectedOption = parts.option; if (!this.activeOptions.hasOwnProperty(selectedOption)) { parts.option = Object.keys(this.activeOptions)[0]; 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; if (!this.activeOptions.hasOwnProperty(selectedOption)) { selectedOption = Object.keys(this.activeOptions)[0]; } if (!selectedOption) { this.optionSelectTrigger.hide(); } else { this._updateOptionSelectLabel(this.activeOptions[selectedOption]); } } else if (selectedOption) { if (this.options.debug) { console.log(this.identifier,"HERE",{optionValue:selectedOption.value}) } this.optionValue = selectedOption.value; this._updateOptionSelectLabel(selectedOption); } else { this.optionSelectTrigger.hide(); } } this.optionMenu = this._createMenu(opt.options,opt,function(v){ if (!opt.multiple) { that._updateOptionSelectLabel(that.activeOptions[v]); if (!opt.hasValue) { that.value(that.activeOptions[v].value) } } else { that._updateOptionSelectLabel(v); if (!opt.hasValue) { that.value(v.join(",")) } } }); } this._trigger("typechange",null,this.propertyType); this.input.trigger('change',[this.propertyType,this.value()]); } else { if (this.optionSelectTrigger) { this.optionSelectTrigger.hide(); } if (opt.inputType) { this.input.attr('type',opt.inputType) } else { this.input.attr('type',this.defaultInputType) } if (opt.hasValue === false) { this.elementDiv.hide(); this.valueLabelContainer.hide(); } else if (opt.valueLabel) { // Reset any CSS the custom label may have set this.valueLabelContainer.css("pointer-events",""); this.valueLabelContainer.css("flex-grow",1); this.valueLabelContainer.css("overflow","hidden"); this.valueLabelContainer.show(); this.valueLabelContainer.empty(); this.elementDiv.hide(); opt.valueLabel.call(this,this.valueLabelContainer,this.input.val()); } else { this.valueLabelContainer.hide(); this.elementDiv.show(); if (opt.autoComplete) { this.input.autoComplete({ search: opt.autoComplete, minLength: 0 }) } } if (this.optionExpandButton) { if (opt.expand) { if (opt.expand.icon) { this.optionExpandButtonIcon.removeClass().addClass("red-ui-typedInput-icon fa "+opt.expand.icon) } else { this.optionExpandButtonIcon.removeClass().addClass("red-ui-typedInput-icon fa fa-ellipsis-h") } this.optionExpandButton.shown = true; this.optionExpandButton.show(); this.optionExpandButton.off('click'); this.optionExpandButton.on('click',function(evt) { evt.preventDefault(); if (typeof opt.expand === 'function') { opt.expand.call(that); } else { var container = $('
'); var content = opt.expand.content.call(that,container); var panel = RED.popover.panel(container); panel.container.css({ width:that.valueLabelContainer.width() }); if (opt.expand.minWidth) { panel.container.css({ minWidth: opt.expand.minWidth+"px" }); } panel.show({ target:that.optionExpandButton, onclose:content.onclose, align: "left" }); } }) } else { this.optionExpandButton.shown = false; this.optionExpandButton.hide(); } } this._trigger("typechange",null,this.propertyType); this.input.trigger('change',[this.propertyType,this.value()]); } } } }, validate: function() { var result; var value = this.value(); var type = this.type(); if (this.typeMap[type] && this.typeMap[type].validate) { var val = this.typeMap[type].validate; if (typeof val === 'function') { result = val(value); } else { result = val.test(value); } } else { result = true; } if (result) { this.uiSelect.removeClass('input-error'); } else { this.uiSelect.addClass('input-error'); } return result; }, show: function() { this.uiSelect.show(); }, hide: function() { this.uiSelect.hide(); }, disable: function(val) { if(val === undefined || !!val ) { this.uiSelect.attr("disabled", "disabled"); } else { this.uiSelect.attr("disabled", null); //remove attr } }, enable: function() { this.uiSelect.attr("disabled", null); //remove attr }, disabled: function() { return this.uiSelect.attr("disabled") === "disabled"; }, focus: function() { this.input.focus(); } }); })(jQuery);