From f1c59faf72e2655fdb1ad220ee166944aac82917 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sun, 3 Jan 2016 22:26:47 +0000 Subject: [PATCH] Rename propertySelect to typedInput and add boolean opt --- Gruntfile.js | 2 +- editor/images/bool.png | Bin 0 -> 367 bytes editor/js/ui/propertySelect.js | 176 ----------- editor/js/ui/typedInput.js | 275 ++++++++++++++++++ editor/sass/colors.scss | 6 +- editor/sass/style.scss | 2 +- .../{propertySelect.scss => typedInput.scss} | 39 ++- nodes/core/logic/10-switch.html | 28 +- nodes/core/logic/15-change.html | 32 +- nodes/core/logic/15-change.js | 2 + red/runtime/util.js | 2 + 11 files changed, 345 insertions(+), 219 deletions(-) create mode 100644 editor/images/bool.png delete mode 100644 editor/js/ui/propertySelect.js create mode 100644 editor/js/ui/typedInput.js rename editor/sass/{propertySelect.scss => typedInput.scss} (70%) diff --git a/Gruntfile.js b/Gruntfile.js index 2871e9d67..c0c31e89b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -125,7 +125,7 @@ module.exports = function(grunt) { "editor/js/ui/notifications.js", "editor/js/ui/subflow.js", "editor/js/ui/touch/radialMenu.js", - "editor/js/ui/propertySelect.js" + "editor/js/ui/typedInput.js" ], dest: "public/red/red.js" }, diff --git a/editor/images/bool.png b/editor/images/bool.png new file mode 100644 index 0000000000000000000000000000000000000000..cd626f3b1e1d799f4d38d82fbf5932747eb49d9b GIT binary patch literal 367 zcmeAS@N?(olHy`uVBq!ia0vp^GC-`x!3HF+zxf>xq*#ibJVQ8upoSx*1IXtr@Q5sC zVBk*#Va65q%QJz3k|nMYCBgY=CFO}lsSM@i<$9TU*~Q6;1*v-ZMd`EO*+>Buz43H$ z42fucJH?ypkb!{1d?h`RgTDL^1^0Bk{&i5eg7e_qXjXHj7pgXs6s|pTioN2Xo9m;- zDEdjEds0eVnvo_8Q)7Oxc1?LhYx;2>i*R4J1BX9%d}?ZYmQwv7WxfDIY(l~&gZYX6 z8jrVbH#xk^IY4mNB&}HoE+yRMv$!R019%qv(fX5|g*?k_djtHDkxA18-#G8dvhq zTzR3}<72S>d(#5JW4YcfwF`Z`17|Q4pYJ" ) - .parent(); - - ["Top","Right","Bottom","Left"].forEach(function(d) { - var m = that.element.css("margin"+d); - that.uiSelect.css("margin"+d,m); - that.element.css("margin"+d,0); - }); - - this.uiSelect.addClass("red-ui-propertySelect-container"); - - this.selectTrigger = $('').prependTo(this.uiSelect); - this.selectLabel = $('msg.').appendTo(this.selectTrigger); - - this.element.on('focus', function() { - that.uiSelect.addClass('red-ui-propertySelect-focus'); - }); - this.element.on('blur', function() { - that.uiSelect.removeClass('red-ui-propertySelect-focus'); - }); - - this.selectTrigger.click(function(event) { - event.preventDefault(); - if (that.disarmClick) { - that.disarmClick = false; - return - } - that._showMenu(); - }); - this.options.options = this.options.options||Object.keys(allOptions); - this._createMenu(this.options.options); - this.type(this.options.default||this.options.options[0]) - this._delay(function() { - //this._resize(); - }); - }, - _hideMenu: function() { - $(document).off("mousedown.close-property-select"); - this.menu.hide(); - this.element.focus(); - }, - _createMenu: function(opts) { - var that = this; - this.menu = $("
").addClass("red-ui-propertySelect-options"); - opts.forEach(function(key) { - var opt = allOptions[key]; - if (opt) { - var op = $('').attr("value",opt.value).appendTo(that.menu); - if (opt.label) { - op.text(opt.label); - } - if (opt.icon) { - $('',{src:opt.icon,style:"margin-right: 4px; height: 18px;"}).prependTo(op); - } else { - op.css({paddingLeft: "18px"}); - } - - op.click(function(event) { - event.preventDefault(); - that.type(key); - that._hideMenu(); - }); - } - }); - this.menu.css({ - display: "none", - }); - this.menu.appendTo(document.body); - - }, - _showMenu: function() { - var that = this; - var pos = this.selectTrigger.offset(); - var height = this.selectTrigger.height(); - this.menu.css({ - top: (height+pos.top)+"px", - left: (2+pos.left)+"px" - }); - this.menu.slideDown(200); - this._delay(function() { - that.uiSelect.addClass('red-ui-propertySelect-focus'); - $(document).on("mousedown.close-property-select", function(event) { - if(!$(event.target).closest(that.menu).length) { - that._hideMenu(); - } - if ($(event.target).closest(that.selectTrigger).length) { - that.disarmClick = true; - event.preventDefault(); - } - }) - }); - }, - _resize: function() { - var labelWidth = this.selectTrigger.width(); - if (labelWidth === 0) { - var newTrigger = this.selectTrigger.clone(); - newTrigger.css({ - position:"absolute", - top:0, - left:-1000 - }).appendTo(document.body); - labelWidth = newTrigger.width()+4; - newTrigger.remove(); - } - this.element.width(this.uiWidth-labelWidth+4); - }, - width: function(desiredWidth) { - this.uiWidth = desiredWidth; - this._resize(); - }, - _destroy: function() { - this.menu.remove(); - }, - type: function(type) { - if (!arguments.length) { - return this.propertyType; - } else { - var opt = allOptions[type]; - if (opt) { - this.propertyType = type; - this.selectLabel.empty(); - if (opt.icon) { - $('',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel); - } else { - this.selectLabel.text(opt.label); - } - this._resize(); - } - } - } - }); -})(jQuery); diff --git a/editor/js/ui/typedInput.js b/editor/js/ui/typedInput.js new file mode 100644 index 000000000..913a91f6e --- /dev/null +++ b/editor/js/ui/typedInput.js @@ -0,0 +1,275 @@ +/** + * Copyright 2015 IBM Corp. + * + * 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 allOptions = { + msg: {value:"msg",label:"msg.",validate:/^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]+)*/i}, + flow: {value:"flow",label:"flow.",validate:/^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]+)*/i}, + global: {value:"global",label:"global.",validate:/^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]+)*/i}, + str: {value:"str",label:"string",icon:"red/images/az.png"}, + num: {value:"num",label:"number",icon:"red/images/09.png",validate:/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/}, + bool: {value:"bool",label:"boolean",icon:"red/images/bool.png",options:["true","false"]}, + json: {value:"json",label:"JSON",icon:"red/images/json.png", validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}}}, + re: {value:"re",label:"regular expression",icon:"red/images/re.png"} + }; + var nlsd = false; + + $.widget( "nodered.typedInput", { + _create: function() { + if (!nlsd && RED && RED._) { + for (var i in allOptions) { + if (allOptions.hasOwnProperty(i)) { + allOptions[i].label = RED._("typedInput.type."+i,{defaultValue:allOptions[i].label}); + } + } + } + nlsd = true; + var that = this; + + this.disarmClick = false; + this.element.addClass('red-ui-typedInput'); + this.uiWidth = this.element.width(); + this.uiSelect = this.element + .wrap( "
" ) + .parent(); + + ["Right","Left"].forEach(function(d) { + var m = that.element.css("margin"+d); + that.uiSelect.css("margin"+d,m); + that.element.css("margin"+d,0); + }); + this.uiSelect.addClass("red-ui-typedInput-container"); + + if (this.options.typeField) { + this.typeField = $(this.options.typeField).hide(); + } else { + this.typeField = $("",{type:'hidden'}).appendTo(this.uiSelect); + } + + this.selectTrigger = $('').prependTo(this.uiSelect); + this.selectLabel = $('').appendTo(this.selectTrigger); + + this.element.on('focus', function() { + that.uiSelect.addClass('red-ui-typedInput-focus'); + }); + this.element.on('blur', function() { + that.uiSelect.removeClass('red-ui-typedInput-focus'); + }); + this.element.on('change', function() { + that.validate(); + }) + + this.selectTrigger.click(function(event) { + event.preventDefault(); + that._showMenu(that.menu,that.selectTrigger); + }); + + this.options.options = this.options.options||Object.keys(allOptions); + + if (this.options.options.filter(function(opt) { return allOptions[opt] && allOptions[opt].hasOwnProperty('options')}).length > 0) { + // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline' + this.optionSelectTrigger = $('').appendTo(this.uiSelect); + this.optionSelectLabel = $('').prependTo(this.optionSelectTrigger); + this.optionSelectTrigger.click(function(event) { + event.preventDefault(); + if (that.optionMenu) { + that.optionMenu.css({ + minWidth:that.optionSelectLabel.width() + }); + + that._showMenu(that.optionMenu,that.optionSelectLabel) + } + }); + } + this.menu = this._createMenu(this.options.options, function(v) { that.type(v) }); + this.type(this.options.default||this.options.options[0]); + }, + _hideMenu: function(menu) { + $(document).off("mousedown.close-property-select"); + menu.hide(); + this.element.focus(); + }, + _createMenu: function(opts,callback) { + var that = this; + var menu = $("
").addClass("red-ui-typedInput-options"); + opts.forEach(function(key) { + var opt = allOptions[key]; + if (!opt) { + opt = {value:key,label:key}; + } + var op = $('').attr("value",opt.value).appendTo(menu); + if (opt.label) { + op.text(opt.label); + } + if (opt.icon) { + $('',{src:opt.icon,style:"margin-right: 4px; height: 18px;"}).prependTo(op); + } else { + op.css({paddingLeft: "18px"}); + } + + op.click(function(event) { + event.preventDefault(); + callback(key); + that._hideMenu(menu); + }); + }); + menu.css({ + display: "none", + }); + menu.appendTo(document.body); + return menu; + + }, + _showMenu: function(menu,relativeTo) { + if (this.disarmClick) { + this.disarmClick = false; + return + } + var that = this; + var pos = relativeTo.offset(); + var height = relativeTo.height(); + menu.css({ + top: (height+pos.top-3)+"px", + left: (2+pos.left)+"px", + }); + menu.slideDown(200); + this._delay(function() { + that.uiSelect.addClass('red-ui-typedInput-focus'); + $(document).on("mousedown.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) { + var labelWidth = label.width(); + if (labelWidth === 0) { + var newTrigger = label.clone(); + newTrigger.css({ + position:"absolute", + top:0, + left:-1000 + }).appendTo(document.body); + labelWidth = newTrigger.width()+4; + newTrigger.remove(); + } + return labelWidth; + }, + _resize: function() { + var labelWidth = this._getLabelWidth(this.selectTrigger); + + var newWidth = this.uiWidth-labelWidth+4; + this.element.width(newWidth); + + if (this.optionSelectTrigger) { + var triggerWidth = this._getLabelWidth(this.optionSelectTrigger); + labelWidth = this._getLabelWidth(this.optionSelectLabel)-4; + this.optionSelectLabel.width(labelWidth+(newWidth-triggerWidth)); + } + }, + _destroy: function() { + this.menu.remove(); + }, + width: function(desiredWidth) { + this.uiWidth = desiredWidth; + this._resize(); + }, + value: function(value) { + if (!arguments.length) { + return this.element.val(); + } else { + if (allOptions[this.propertyType].options) { + if (allOptions[this.propertyType].options.indexOf(value) === -1) { + value = ""; + } + this.optionSelectLabel.text(value); + } + this.element.val(value); + this.element.trigger('change'); + } + }, + type: function(type) { + if (!arguments.length) { + return this.propertyType; + } else { + var opt = allOptions[type]; + if (opt && this.propertyType !== type) { + this.propertyType = type; + this.typeField.val(type); + this.selectLabel.empty(); + if (opt.icon) { + $('',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel); + } else { + this.selectLabel.text(opt.label); + } + if (opt.options) { + if (this.optionSelectTrigger) { + this.optionSelectTrigger.show(); + this.element.hide(); + var that = this; + this.optionMenu = this._createMenu(opt.options,function(v){ + that.optionSelectLabel.text(v); + that.value(v); + }); + var currentVal = this.element.val(); + if (opt.options.indexOf(currentVal) !== -1) { + this.optionSelectLabel.text(currentVal); + } else { + this.value(opt.options[0]); + } + } + } else { + if (this.optionMenu) { + this.optionMenu.remove(); + this.optionMenu = null; + } + if (this.optionSelectTrigger) { + this.optionSelectTrigger.hide(); + } + this.element.show(); + this.element.trigger('change'); + } + this._resize(); + } + } + }, + validate: function() { + var result; + var value = this.value(); + var type = this.type(); + if (allOptions[type] && allOptions[type].validate) { + var val = allOptions[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; + } + }); +})(jQuery); diff --git a/editor/sass/colors.scss b/editor/sass/colors.scss index d95050e77..e8d4d7c9b 100644 --- a/editor/sass/colors.scss +++ b/editor/sass/colors.scss @@ -44,6 +44,6 @@ $workspace-button-color-focus: #999; $workspace-button-color-hover: #666; $workspace-button-color-active: #666; -$propertySelect-button-background: #efefef; -$propertySelect-button-background-hover: #ddd; -$propertySelect-button-background-active: #e3e3e3; +$typedInput-button-background: #efefef; +$typedInput-button-background-hover: #ddd; +$typedInput-button-background-active: #e3e3e3; diff --git a/editor/sass/style.scss b/editor/sass/style.scss index 543a19993..08b90bd4b 100644 --- a/editor/sass/style.scss +++ b/editor/sass/style.scss @@ -41,7 +41,7 @@ @import "popover"; @import "flow"; -@import "propertySelect"; +@import "typedInput"; @import "dragdrop"; diff --git a/editor/sass/propertySelect.scss b/editor/sass/typedInput.scss similarity index 70% rename from editor/sass/propertySelect.scss rename to editor/sass/typedInput.scss index 76617e31e..32644ee85 100644 --- a/editor/sass/propertySelect.scss +++ b/editor/sass/typedInput.scss @@ -14,7 +14,7 @@ * limitations under the License. **/ -.red-ui-propertySelect-container { +.red-ui-typedInput-container { border: 1px solid $form-input-border-color; border-radius: 4px; height: 34px; @@ -36,7 +36,7 @@ vertical-align: middle; } - &.red-ui-propertySelect-focus { + &.red-ui-typedInput-focus:not(.input-error) { border-color: $form-input-focus-color !important; } @@ -45,7 +45,7 @@ border-bottom-left-radius: 4px; padding: 0 1px 0 5px; display:inline-block; - background: $propertySelect-button-background; + background: $typedInput-button-background; height: 32px; line-height: 32px; vertical-align: middle; @@ -58,20 +58,43 @@ vertical-align: middle; } + span { + display: inline-block; + height: 100%; + padding: 0 1px 0 5px; + } + &:hover { text-decoration: none; - background: $propertySelect-button-background-hover; + background: $typedInput-button-background-hover; } &:focus { text-decoration: none; } &:active { - background: $propertySelect-button-background-active; + background: $typedInput-button-background-active; text-decoration: none; } } + + a.red-ui-typedInput-option-trigger { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + padding: 0 5px 0 0; + + i { + margin-right: 0; + margin-left: 4px; + } + span { + background:#fff; + padding: 0 5px 0 5px; + } + } } -.red-ui-propertySelect-options { +.red-ui-typedInput-options { @include component-shadow; position: absolute; border: 1px solid $primary-border-color; @@ -84,13 +107,13 @@ color: #333; &:hover { text-decoration: none; - background: $propertySelect-button-background-hover; + background: $typedInput-button-background-hover; } &:focus { text-decoration: none; } &:active { - background: $propertySelect-button-background-active; + background: $typedInput-button-background-active; text-decoration: none; } diff --git a/nodes/core/logic/10-switch.html b/nodes/core/logic/10-switch.html index 9dc56627f..74dc17833 100644 --- a/nodes/core/logic/10-switch.html +++ b/nodes/core/logic/10-switch.html @@ -65,7 +65,7 @@ return this.name||"switch"; }, oneditprepare: function() { - $("#node-input-property").propertySelect({default:this.propertyType||'msg',options:['msg','flow','global']}); + $("#node-input-property").typedInput({default:this.propertyType||'msg',options:['msg','flow','global']}); var operators = [ {v:"eq",t:"=="}, {v:"neq",t:"!="}, @@ -104,13 +104,13 @@ if (type === "btwn") { var labelWidth = rule.find(".node-input-rule-btwn-label").width(); - btwnField1.propertySelect("width",(width-selectWidth-120)); - btwnField2.propertySelect("width",(width-selectWidth-120)); + btwnField1.typedInput("width",(width-selectWidth-120)); + btwnField2.typedInput("width",(width-selectWidth-120)); } else { if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else") { // valueField.hide(); } else { - valueField.propertySelect("width",(width-selectWidth-120)); + valueField.typedInput("width",(width-selectWidth-120)); } } } @@ -128,10 +128,10 @@ selectField.append($("").val(operators[d].v).text(operators[d].t)); } - var valueField = $('',{class:"node-input-rule-value",type:"text",style:"margin-left: 5px; width: 145px;"}).appendTo(row).propertySelect({default:'str',options:['msg','flow','global','str','num']}); - var btwnValueField = $('',{class:"node-input-rule-btwn-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).propertySelect({default:'num',options:['msg','flow','global','str','num']}); + var valueField = $('',{class:"node-input-rule-value",type:"text",style:"margin-left: 5px; width: 145px;"}).appendTo(row).typedInput({default:'str',options:['msg','flow','global','str','num']}); + var btwnValueField = $('',{class:"node-input-rule-btwn-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',options:['msg','flow','global','str','num']}); var btwnAndLabel = $('',{class:"node-input-rule-btwn-label"}).text(" "+andLabel+" ").appendTo(row3); - var btwnValue2Field = $('',{class:"node-input-rule-btwn-value2",type:"text",style:"margin-left:2px;"}).appendTo(row3).propertySelect({default:'num',options:['msg','flow','global','str','num']}); + var btwnValue2Field = $('',{class:"node-input-rule-btwn-value2",type:"text",style:"margin-left:2px;"}).appendTo(row3).typedInput({default:'num',options:['msg','flow','global','str','num']}); var finalspan = $('',{style:"float: right;margin-right: 10px;"}).appendTo(row); finalspan.append(' → '+i+' '); @@ -185,12 +185,12 @@ selectField.find("option").filter(function() {return $(this).val() == rule.t;}).attr('selected',true); if (rule.t == "btwn") { btwnValueField.val(rule.v); - btwnValueField.propertySelect('type',rule.vt||'num'); + btwnValueField.typedInput('type',rule.vt||'num'); btwnValue2Field.val(rule.v2); - btwnValue2Field.propertySelect('type',rule.v2t||'num'); + btwnValue2Field.typedInput('type',rule.v2t||'num'); } else if (typeof rule.v != "undefined") { valueField.val(rule.v); - valueField.propertySelect('type',rule.vt||'str'); + valueField.typedInput('type',rule.vt||'str'); } if (rule.case) { caseSensitive.prop('checked',true); @@ -267,12 +267,12 @@ if (!(type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else")) { if (type === "btwn") { r.v = rule.find(".node-input-rule-btwn-value").val(); - r.vt = rule.find(".node-input-rule-btwn-value").propertySelect('type'); + r.vt = rule.find(".node-input-rule-btwn-value").typedInput('type'); r.v2 = rule.find(".node-input-rule-btwn-value2").val(); - r.v2t = rule.find(".node-input-rule-btwn-value2").propertySelect('type'); + r.v2t = rule.find(".node-input-rule-btwn-value2").typedInput('type'); } else { r.v = rule.find(".node-input-rule-value").val(); - r.vt = rule.find(".node-input-rule-value").propertySelect('type'); + r.vt = rule.find(".node-input-rule-value").typedInput('type'); } if (type === "regex") { r.case = rule.find(".node-input-rule-case").prop("checked"); @@ -281,7 +281,7 @@ node.rules.push(r); }); this.outputs = node.rules.length; - this.propertyType = $("#node-input-property").propertySelect('type'); + this.propertyType = $("#node-input-property").typedInput('type'); } }); diff --git a/nodes/core/logic/15-change.html b/nodes/core/logic/15-change.html index 15c756578..5c9cad8b0 100644 --- a/nodes/core/logic/15-change.html +++ b/nodes/core/logic/15-change.html @@ -17,7 +17,7 @@