diff --git a/Gruntfile.js b/Gruntfile.js index a3c44bd88..2871e9d67 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -124,7 +124,8 @@ module.exports = function(grunt) { "editor/js/ui/library.js", "editor/js/ui/notifications.js", "editor/js/ui/subflow.js", - "editor/js/ui/touch/radialMenu.js" + "editor/js/ui/touch/radialMenu.js", + "editor/js/ui/propertySelect.js" ], dest: "public/red/red.js" }, diff --git a/editor/images/09.png b/editor/images/09.png new file mode 100644 index 000000000..247371fe5 Binary files /dev/null and b/editor/images/09.png differ diff --git a/editor/images/az.png b/editor/images/az.png new file mode 100644 index 000000000..5f5d2404e Binary files /dev/null and b/editor/images/az.png differ diff --git a/editor/images/json.png b/editor/images/json.png new file mode 100644 index 000000000..57ac8761f Binary files /dev/null and b/editor/images/json.png differ diff --git a/editor/images/re.png b/editor/images/re.png new file mode 100644 index 000000000..87deb02ae Binary files /dev/null and b/editor/images/re.png differ diff --git a/editor/js/ui/propertySelect.js b/editor/js/ui/propertySelect.js new file mode 100644 index 000000000..bd8af8309 --- /dev/null +++ b/editor/js/ui/propertySelect.js @@ -0,0 +1,174 @@ +/** + * 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.",style:"code"}, + flow: {value:"flow",label:"flow.",style:"code"}, + global: {value:"global",label:"global.",style:"code"}, + str: {value:"str",label:"string",icon:"red/images/az.png"}, + num: {value:"num",label:"number",icon:"red/images/09.png"}, + json: {value:"json",label:"JSON",icon:"red/images/json.png"}, + re: {value:"re",label:"regular expression",icon:"red/images/re.png"} + }; + var nlsd = false; + + $.widget( "nodered.propertySelect", { + _create: function() { + /* + { + options: [] + } + */ + if (!nlsd && RED && RED._) { + for (var i in allOptions) { + if (allOptions.hasOwnProperty(i)) { + allOptions[i].label = RED._("propertySelect.type."+i,{defaultValue:allOptions[i].label}); + } + } + } + nlsd = true; + var that = this; + this.disarmClick = false; + this.element.addClass('red-ui-propertySelect'); + this.uiWidth = this.element.width(); + + this.uiSelect = this.element + .wrap( "
" ) + .parent(); + + 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/sass/colors.scss b/editor/sass/colors.scss index 12e14f587..d95050e77 100644 --- a/editor/sass/colors.scss +++ b/editor/sass/colors.scss @@ -43,3 +43,7 @@ $workspace-button-color-disabled: #ccc; $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; diff --git a/editor/sass/jquery.scss b/editor/sass/jquery.scss index f8f71c9ce..62704bf9f 100644 --- a/editor/sass/jquery.scss +++ b/editor/sass/jquery.scss @@ -22,6 +22,9 @@ font-size: 14px !important; font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif !important; } +.ui-widget input { + box-shadow: none; +} /* jQuery Theme overrides */ .ui-tabs .ui-tabs-panel { diff --git a/editor/sass/propertySelect.scss b/editor/sass/propertySelect.scss new file mode 100644 index 000000000..76617e31e --- /dev/null +++ b/editor/sass/propertySelect.scss @@ -0,0 +1,99 @@ +/** + * 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. + **/ + +.red-ui-propertySelect-container { + border: 1px solid $form-input-border-color; + border-radius: 4px; + height: 34px; + display: inline-block; + padding: 0; + margin: 0; + vertical-align: middle; + box-sizing: border-box; + overflow:hidden; + + input { + padding: 0 0 0 1px; + margin:0; + height: 32px; + border:none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + box-shadow: none; + vertical-align: middle; + } + + &.red-ui-propertySelect-focus { + border-color: $form-input-focus-color !important; + } + + a { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + padding: 0 1px 0 5px; + display:inline-block; + background: $propertySelect-button-background; + height: 32px; + line-height: 32px; + vertical-align: middle; + color: #555; + i { + position:relative; + top:-3px; + margin-right:4px; + margin-top: 1px; + vertical-align: middle; + } + + &:hover { + text-decoration: none; + background: $propertySelect-button-background-hover; + } + &:focus { + text-decoration: none; + } + &:active { + background: $propertySelect-button-background-active; + text-decoration: none; + } + } +} +.red-ui-propertySelect-options { + @include component-shadow; + position: absolute; + border: 1px solid $primary-border-color; + background: #fff; + z-index: 2000; + a { + padding: 6px 18px 6px 6px; + display: block; + border-bottom: 1px solid $secondary-border-color; + color: #333; + &:hover { + text-decoration: none; + background: $propertySelect-button-background-hover; + } + &:focus { + text-decoration: none; + } + &:active { + background: $propertySelect-button-background-active; + text-decoration: none; + } + + + } +} diff --git a/editor/sass/style.scss b/editor/sass/style.scss index 49a339cff..543a19993 100644 --- a/editor/sass/style.scss +++ b/editor/sass/style.scss @@ -41,6 +41,8 @@ @import "popover"; @import "flow"; +@import "propertySelect"; + @import "dragdrop"; @import "keyboard"; diff --git a/red/api/locales/en-US/editor.json b/red/api/locales/en-US/editor.json index c702a527b..c098d01e1 100644 --- a/red/api/locales/en-US/editor.json +++ b/red/api/locales/en-US/editor.json @@ -203,5 +203,12 @@ "subflows": "subflows", "flows": "flows" } + }, + "propertySelect": { + "type": { + "str": "string", + "num": "number", + "re": "regular expression" + } } }