diff --git a/Gruntfile.js b/Gruntfile.js index ffb1df3c3..bf6994aca 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -152,6 +152,10 @@ module.exports = function(grunt) { "public/vendor/vendor.css": [ // TODO: resolve relative resource paths in // bootstrap/FA/jquery + ], + "public/vendor/jsonata/jsonata.js": [ + "node_modules/jsonata/jsonata.js", + "editor/vendor/jsonata/formatter.js" ] } } @@ -160,7 +164,11 @@ module.exports = function(grunt) { build: { files: { 'public/red/red.min.js': 'public/red/red.js', - 'public/red/main.min.js': 'public/red/main.js' + 'public/red/main.min.js': 'public/red/main.js', + 'public/vendor/jsonata/jsonata.min.js': 'public/vendor/jsonata/jsonata.js', + 'public/vendor/ace/mode-jsonata.js': 'editor/vendor/jsonata/mode-jsonata.js', + 'public/vendor/ace/worker-jsonata.js': 'editor/vendor/jsonata/worker-jsonata.js', + 'public/vendor/ace/snippets/jsonata.js': 'editor/vendor/jsonata/snippets-jsonata.js' } } }, diff --git a/editor/images/typedInput/expr.png b/editor/images/typedInput/expr.png new file mode 100644 index 000000000..704105ce5 Binary files /dev/null and b/editor/images/typedInput/expr.png differ diff --git a/editor/js/i18n.js b/editor/js/i18n.js index cf29a6b43..f03b89a7b 100644 --- a/editor/js/i18n.js +++ b/editor/js/i18n.js @@ -23,7 +23,7 @@ RED.i18n = (function() { dynamicLoad: false, load:'current', ns: { - namespaces: ["editor","node-red"], + namespaces: ["editor","node-red","jsonata"], defaultNs: "editor" }, fallbackLng: ['en-US'], diff --git a/editor/js/ui/common/typedInput.js b/editor/js/ui/common/typedInput.js index a455efc66..e7a26cf3d 100644 --- a/editor/js/ui/common/typedInput.js +++ b/editor/js/ui/common/typedInput.js @@ -85,6 +85,7 @@ } return true; } + var allOptions = { msg: {value:"msg",label:"msg.",validate:validateExpression}, flow: {value:"flow",label:"flow.",validate:validateExpression}, @@ -94,7 +95,22 @@ bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.png",options:["true","false"]}, json: {value:"json",label:"JSON",icon:"red/images/typedInput/json.png", validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}}}, re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.png"}, - date: {value:"date",label:"timestamp",hasValue:false} + date: {value:"date",label:"timestamp",hasValue:false}, + jsonata: { + value: "jsonata", + label: "expression", + icon: "red/images/typedInput/expr.png", + 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"), + complete: function(v) { + that.value(v.replace(/\n/g,"\t")); + } + }) + } + } }; var nlsd = false; @@ -188,7 +204,7 @@ that.uiSelect.addClass('red-ui-typedInput-focus'); }); - + this.optionExpandButton = $('').appendTo(this.uiSelect); this.type(this.options.default||this.typeList[0].value); @@ -322,11 +338,16 @@ this.uiSelect.width(this.uiWidth); } if (this.typeMap[this.propertyType] && this.typeMap[this.propertyType].hasValue === false) { - this.selectTrigger.css('width',"100%"); + this.selectTrigger.addClass("red-ui-typedInput-full-width"); } else { - this.selectTrigger.width('auto'); + this.selectTrigger.removeClass("red-ui-typedInput-full-width"); var labelWidth = this._getLabelWidth(this.selectTrigger); this.elementDiv.css('left',labelWidth+"px"); + if (this.optionExpandButton.is(":visible")) { + this.elementDiv.css('right',"22px"); + } else { + this.elementDiv.css('right','0'); + } if (this.optionSelectTrigger) { this.optionSelectTrigger.css({'left':(labelWidth)+"px",'width':'calc( 100% - '+labelWidth+'px )'}); } @@ -396,6 +417,9 @@ this.selectLabel.text(opt.label); } if (opt.options) { + if (this.optionExpandButton) { + this.optionExpandButton.hide(); + } if (this.optionSelectTrigger) { this.optionSelectTrigger.show(); this.elementDiv.hide(); @@ -429,6 +453,16 @@ } this.elementDiv.show(); } + if (opt.expand && typeof opt.expand === 'function') { + this.optionExpandButton.show(); + this.optionExpandButton.off('click'); + this.optionExpandButton.on('click',function(evt) { + evt.preventDefault(); + opt.expand.call(that); + }) + } else { + this.optionExpandButton.hide(); + } this.element.trigger('change',this.propertyType,this.value()); } if (image) { diff --git a/editor/js/ui/editor.js b/editor/js/ui/editor.js index c689352b0..915c29649 100644 --- a/editor/js/ui/editor.js +++ b/editor/js/ui/editor.js @@ -494,12 +494,13 @@ RED.editor = (function() { } function getEditStackTitle() { - var title = '