From 48feffd60a3f3c3a248744a6f761ac65b90a8262 Mon Sep 17 00:00:00 2001 From: alekseybobkov Date: Thu, 29 Oct 2015 22:01:29 -0700 Subject: [PATCH] Added live update mode for Inspector. --- .../assets/ui/js/inspector.editor.base.js | 6 ++- .../assets/ui/js/inspector.editor.object.js | 4 +- .../ui/js/inspector.editor.stringlist.js | 1 - .../js/inspector.externalparametereditor.js | 8 +-- .../system/assets/ui/js/inspector.surface.js | 40 +++++++++++++-- .../assets/ui/js/inspector.wrapper.base.js | 26 ++++++++-- .../ui/js/inspector.wrapper.container.js | 20 ++++++++ modules/system/assets/ui/storm-min.js | 49 +++++++++++++------ 8 files changed, 123 insertions(+), 31 deletions(-) diff --git a/modules/system/assets/ui/js/inspector.editor.base.js b/modules/system/assets/ui/js/inspector.editor.base.js index 915ed0d7f..46d1030b6 100644 --- a/modules/system/assets/ui/js/inspector.editor.base.js +++ b/modules/system/assets/ui/js/inspector.editor.base.js @@ -127,7 +127,7 @@ return this.inspector.getPropertyValue(this.propertyDefinition.property) } - BaseEditor.prototype.validate = function() { + BaseEditor.prototype.validate = function(silentMode) { var value = this.getValueToValidate() if (value === undefined) { @@ -136,7 +136,9 @@ var validationResult = this.validationSet.validate(value) if (validationResult !== null) { - $.oc.flashMsg({text: validationResult, 'class': 'error', 'interval': 5}) + if (!silentMode) { + $.oc.flashMsg({text: validationResult, 'class': 'error', 'interval': 5}) + } return false } diff --git a/modules/system/assets/ui/js/inspector.editor.object.js b/modules/system/assets/ui/js/inspector.editor.object.js index 31ffe2c3c..ea9349c26 100644 --- a/modules/system/assets/ui/js/inspector.editor.object.js +++ b/modules/system/assets/ui/js/inspector.editor.object.js @@ -120,7 +120,7 @@ return this.getValueOrRemove(result) } - ObjectEditor.prototype.validate = function() { + ObjectEditor.prototype.validate = function(silentMode) { var values = values = this.childInspector.getValues() if (this.cleanUpValue(values) === $.oc.inspector.removedProperty) { @@ -130,7 +130,7 @@ return true } - return this.childInspector.validate() + return this.childInspector.validate(silentMode) } // diff --git a/modules/system/assets/ui/js/inspector.editor.stringlist.js b/modules/system/assets/ui/js/inspector.editor.stringlist.js index ee03a74ac..2779e750c 100644 --- a/modules/system/assets/ui/js/inspector.editor.stringlist.js +++ b/modules/system/assets/ui/js/inspector.editor.stringlist.js @@ -88,7 +88,6 @@ } this.inspector.setPropertyValue(this.propertyDefinition.property, resultValue) -// TODO: validate here } $.oc.inspector.propertyEditors.stringList = StringListEditor diff --git a/modules/system/assets/ui/js/inspector.externalparametereditor.js b/modules/system/assets/ui/js/inspector.externalparametereditor.js index 95f1acdc2..d373a9dcb 100644 --- a/modules/system/assets/ui/js/inspector.externalparametereditor.js +++ b/modules/system/assets/ui/js/inspector.externalparametereditor.js @@ -241,12 +241,14 @@ this.getInput().focus() } - ExternalParameterEditor.prototype.validate = function() { + ExternalParameterEditor.prototype.validate = function(silentMode) { var value = $.trim(this.getValue()) if (value.length === 0) { - $.oc.flashMsg({text: 'Please enter the external parameter name.', 'class': 'error', 'interval': 5}) - this.focus() + if (!silentMode) { + $.oc.flashMsg({text: 'Please enter the external parameter name.', 'class': 'error', 'interval': 5}) + this.focus() + } return false } diff --git a/modules/system/assets/ui/js/inspector.surface.js b/modules/system/assets/ui/js/inspector.surface.js index 4c6d78e75..c6d5b24d3 100644 --- a/modules/system/assets/ui/js/inspector.surface.js +++ b/modules/system/assets/ui/js/inspector.surface.js @@ -797,7 +797,33 @@ return result } - Surface.prototype.validate = function() { + Surface.prototype.getValidValues = function() { + var allValues = this.getValues(), + result = {} + + for (var property in allValues) { + var editor = this.findPropertyEditor(property) + + if (!editor) { + throw new Error('Cannot find editor for property ' + property) + } + + var externalEditor = this.findExternalParameterEditor(property) + if (externalEditor && externalEditor.isEditorVisible() && !externalEditor.validate(true)) { + continue + } + + if (!editor.validate(true)) { + continue + } + + result[property] = allValues[property] + } + + return result + } + + Surface.prototype.validate = function(silentMode) { this.getGroupManager().unmarkInvalidGroups(this.getRootTable()) for (var i = 0, len = this.editors.length; i < len; i++) { @@ -805,8 +831,10 @@ externalEditor = this.findExternalParameterEditor(editor.propertyDefinition.property) if (externalEditor && externalEditor.isEditorVisible()) { - if (!externalEditor.validate()) { - editor.markInvalid() + if (!externalEditor.validate(silentMode)) { + if (!silentMode) { + editor.markInvalid() + } return false } else { @@ -814,8 +842,10 @@ } } - if (!editor.validate()) { - editor.markInvalid() + if (!editor.validate(silentMode)) { + if (!silentMode) { + editor.markInvalid() + } return false } } diff --git a/modules/system/assets/ui/js/inspector.wrapper.base.js b/modules/system/assets/ui/js/inspector.wrapper.base.js index d3d020062..5d3c6acc1 100644 --- a/modules/system/assets/ui/js/inspector.wrapper.base.js +++ b/modules/system/assets/ui/js/inspector.wrapper.base.js @@ -23,6 +23,7 @@ this.options = $.extend({}, BaseWrapper.DEFAULTS, typeof options == 'object' && options) this.switched = false + this.configuration = null Base.call(this) @@ -63,6 +64,7 @@ this.$element = null this.title = null this.description = null + this.configuration = null BaseProto.dispose.call(this) } @@ -194,9 +196,21 @@ return values } - BaseWrapper.prototype.applyValues = function() { + BaseWrapper.prototype.applyValues = function(liveUpdateMode) { var $valuesField = this.getElementValuesInput(), - values = this.surface.getValues() + values = liveUpdateMode ? + this.surface.getValidValues() : + this.surface.getValues() + + if (liveUpdateMode) { + // In the live update mode, when only valid values are applied, + // we don't want to change all other values (invalid properties), + // so we merge existing values with the valid values. + + var existingValues = this.loadValues(this.configuration) + + values = $.extend(existingValues, values) + } if ($valuesField.length > 0) { $valuesField.val(JSON.stringify(values)) @@ -214,7 +228,12 @@ } if (this.surface.hasChanges()) { - this.$element.trigger('change') + if (!liveUpdateMode) { + this.$element.trigger('change') + } + else { + this.$element.trigger('livechange') + } } } @@ -284,6 +303,7 @@ this.title = configuration.title this.description = configuration.description + this.configuration = configuration this.createSurfaceAndUi(configuration.properties, values) } diff --git a/modules/system/assets/ui/js/inspector.wrapper.container.js b/modules/system/assets/ui/js/inspector.wrapper.container.js index 8ed49dfbb..5031e2aee 100644 --- a/modules/system/assets/ui/js/inspector.wrapper.container.js +++ b/modules/system/assets/ui/js/inspector.wrapper.container.js @@ -41,12 +41,20 @@ this.buildUi() this.initSurface(this.surfaceContainer, properties, values) + + if (this.isLiveUpdateEnabled()) { + this.surface.options.onChange = this.proxy(this.onLiveUpdate) + } } InspectorContainer.prototype.adoptSurface = function() { this.buildUi() this.surface.moveToContainer(this.surfaceContainer) + + if (this.isLiveUpdateEnabled()) { + this.surface.options.onChange = this.proxy(this.onLiveUpdate) + } } InspectorContainer.prototype.buildUi = function() { @@ -155,6 +163,10 @@ return this.options.container.data('inspector-scrollable') !== undefined } + InspectorContainer.prototype.isLiveUpdateEnabled = function() { + return this.options.container.data('inspector-live-update') !== undefined + } + InspectorContainer.prototype.getLayout = function() { return this.options.container.get(0).querySelector('div.layout') } @@ -181,6 +193,10 @@ $layout.off('dispose-control', this.proxy(this.dispose)) $layout.off('click', 'span.close', this.proxy(this.onClose)) $layout.off('click', 'span.detach', this.proxy(this.onDetach)) + + if (this.surface !== null && this.surface.options.onChange === this.proxy(this.onLiveUpdate)) { + this.surface.options.onChange = null + } } InspectorContainer.prototype.removeControls = function() { @@ -222,6 +238,10 @@ this.dispose() } + InspectorContainer.prototype.onLiveUpdate = function() { + this.applyValues(true) + } + InspectorContainer.prototype.onDetach = function() { $.oc.inspector.manager.switchToPopup(this) } diff --git a/modules/system/assets/ui/storm-min.js b/modules/system/assets/ui/storm-min.js index 3387a36d1..32268461d 100644 --- a/modules/system/assets/ui/storm-min.js +++ b/modules/system/assets/ui/storm-min.js @@ -3567,12 +3567,20 @@ else{value=externalParameterEditor.getValue() value='{{ '+value+' }}'} result[property.property]=value} return result} -Surface.prototype.validate=function(){this.getGroupManager().unmarkInvalidGroups(this.getRootTable()) +Surface.prototype.getValidValues=function(){var allValues=this.getValues(),result={} +for(var property in allValues){var editor=this.findPropertyEditor(property) +if(!editor){throw new Error('Cannot find editor for property '+property)} +var externalEditor=this.findExternalParameterEditor(property) +if(externalEditor&&externalEditor.isEditorVisible()&&!externalEditor.validate(true)){continue} +if(!editor.validate(true)){continue} +result[property]=allValues[property]} +return result} +Surface.prototype.validate=function(silentMode){this.getGroupManager().unmarkInvalidGroups(this.getRootTable()) for(var i=0,len=this.editors.length;i0){$valuesField.val(JSON.stringify(values))} else{for(var property in values){var value=values[property] if($.isArray(value)||$.isPlainObject(value)){throw new Error('Inspector data-property-xxx attributes do not support complex values. Property: '+property)} this.$element.attr('data-property-'+property,value)}} -if(this.surface.hasChanges()){this.$element.trigger('change')}} +if(this.surface.hasChanges()){if(!liveUpdateMode){this.$element.trigger('change')} +else{this.$element.trigger('livechange')}}} BaseWrapper.prototype.loadConfiguration=function(){var configString=this.$element.data('inspector-config'),result={properties:{},title:null,description:null} result.title=this.$element.data('inspector-title') result.description=this.$element.data('inspector-description') @@ -3709,6 +3722,7 @@ try{return $.parseJSON(configuration)}catch(err){throw new Error('Error parsing BaseWrapper.prototype.configurationLoaded=function(configuration){var values=this.loadValues(configuration.properties) this.title=configuration.title this.description=configuration.description +this.configuration=configuration this.createSurfaceAndUi(configuration.properties,values)} BaseWrapper.prototype.onConfigurartionRequestDone=function(data,result){result.properties=this.parseConfiguration(data.configuration.properties) if(data.configuration.title!==undefined){result.title=data.configuration.title} @@ -3815,9 +3829,11 @@ this.removeControls() this.surfaceContainer=null BaseProto.dispose.call(this)} InspectorContainer.prototype.createSurfaceAndUi=function(properties,values){this.buildUi() -this.initSurface(this.surfaceContainer,properties,values)} +this.initSurface(this.surfaceContainer,properties,values) +if(this.isLiveUpdateEnabled()){this.surface.options.onChange=this.proxy(this.onLiveUpdate)}} InspectorContainer.prototype.adoptSurface=function(){this.buildUi() -this.surface.moveToContainer(this.surfaceContainer)} +this.surface.moveToContainer(this.surfaceContainer) +if(this.isLiveUpdateEnabled()){this.surface.options.onChange=this.proxy(this.onLiveUpdate)}} InspectorContainer.prototype.buildUi=function(){var scrollable=this.isScrollable(),head=this.buildHead(),layoutElements=this.buildLayout() layoutElements.headContainer.appendChild(head) if(scrollable){var scrollpad=this.buildScrollpad() @@ -3862,6 +3878,7 @@ InspectorContainer.prototype.validateAndApply=function(){if(!this.surface.valida this.applyValues() return true} InspectorContainer.prototype.isScrollable=function(){return this.options.container.data('inspector-scrollable')!==undefined} +InspectorContainer.prototype.isLiveUpdateEnabled=function(){return this.options.container.data('inspector-live-update')!==undefined} InspectorContainer.prototype.getLayout=function(){return this.options.container.get(0).querySelector('div.layout')} InspectorContainer.prototype.registerLayoutHandlers=function(layout){var $layout=$(layout) $layout.one('dispose-control',this.proxy(this.dispose)) @@ -3874,7 +3891,8 @@ this.options.container.off('apply.oc.inspector',this.proxy(this.onApplyValues)) this.options.container.off('beforeContainerHide.oc.inspector',this.proxy(this.onBeforeHide)) $layout.off('dispose-control',this.proxy(this.dispose)) $layout.off('click','span.close',this.proxy(this.onClose)) -$layout.off('click','span.detach',this.proxy(this.onDetach))} +$layout.off('click','span.detach',this.proxy(this.onDetach)) +if(this.surface!==null&&this.surface.options.onChange===this.proxy(this.onLiveUpdate)){this.surface.options.onChange=null}} InspectorContainer.prototype.removeControls=function(){if(this.isScrollable()){this.options.container.find('.control-scrollpad').scrollpad('dispose')} var layout=this.getLayout() layout.parentNode.removeChild(layout)} @@ -3888,6 +3906,7 @@ if(!this.triggerHiding()){ev.preventDefault() return false} this.surface.dispose() this.dispose()} +InspectorContainer.prototype.onLiveUpdate=function(){this.applyValues(true)} InspectorContainer.prototype.onDetach=function(){$.oc.inspector.manager.switchToPopup(this)} $.oc.inspector.wrappers.container=InspectorContainer}(window.jQuery);+function($){"use strict";var GroupManager=function(controlId){this.controlId=controlId this.rootGroup=null @@ -4039,10 +4058,10 @@ BaseEditor.prototype.throwError=function(errorMessage){throw new Error(errorMess BaseEditor.prototype.initValidation=function(){this.validationSet=new $.oc.inspector.validationSet(this.propertyDefinition,this.propertyDefinition.property)} BaseEditor.prototype.disposeValidation=function(){this.validationSet.dispose()} BaseEditor.prototype.getValueToValidate=function(){return this.inspector.getPropertyValue(this.propertyDefinition.property)} -BaseEditor.prototype.validate=function(){var value=this.getValueToValidate() +BaseEditor.prototype.validate=function(silentMode){var value=this.getValueToValidate() if(value===undefined){value=this.getUndefinedValue()} var validationResult=this.validationSet.validate(value) -if(validationResult!==null){$.oc.flashMsg({text:validationResult,'class':'error','interval':5}) +if(validationResult!==null){if(!silentMode){$.oc.flashMsg({text:validationResult,'class':'error','interval':5})} return false} return true} BaseEditor.prototype.markInvalid=function(){$.oc.foundation.element.addClass(this.containerRow,'invalid') @@ -4681,9 +4700,9 @@ ObjectEditor.prototype.getUndefinedValue=function(){var result={} for(var i=0,len=this.propertyDefinition.properties.length;i