From 2d849b264019b21710eb4fa5027bda838d2fb4ba Mon Sep 17 00:00:00 2001 From: alekseybobkov Date: Tue, 3 Nov 2015 22:02:10 -0800 Subject: [PATCH] Implemented Inspector ignoreIfEmpty and ignoreIfDefault properties. Minor refactoring of Inspector. --- .../ui/js/inspector.editor.autocomplete.js | 29 +++++- .../assets/ui/js/inspector.editor.base.js | 12 +++ .../assets/ui/js/inspector.editor.dropdown.js | 34 ++++++- .../assets/ui/js/inspector.editor.object.js | 11 +-- .../assets/ui/js/inspector.editor.set.js | 22 ++--- .../system/assets/ui/js/inspector.surface.js | 59 ++++++++++-- .../assets/ui/js/inspector.wrapper.base.js | 64 +++++++++++-- .../ui/js/inspector.wrapper.container.js | 2 + .../assets/ui/js/inspector.wrapper.popup.js | 2 + modules/system/assets/ui/storm-min.js | 89 ++++++++++++++----- 10 files changed, 266 insertions(+), 58 deletions(-) diff --git a/modules/system/assets/ui/js/inspector.editor.autocomplete.js b/modules/system/assets/ui/js/inspector.editor.autocomplete.js index 4f79a1b6a..c80524cce 100644 --- a/modules/system/assets/ui/js/inspector.editor.autocomplete.js +++ b/modules/system/assets/ui/js/inspector.editor.autocomplete.js @@ -139,6 +139,10 @@ $.oc.foundation.element.addClass(container, 'loading-indicator-container size-small') this.showLoadingIndicator() + if (this.triggerGetItems(data) === false) { + return + } + data['inspectorProperty'] = this.propertyDefinition.property data['inspectorClassName'] = this.inspector.options.inspectorClass @@ -149,13 +153,36 @@ .always(this.proxy(this.hideLoadingIndicator)) } - AutocompleteEditor.prototype.itemsRequestDone = function(data, currentValue, initialization) { + AutocompleteEditor.prototype.triggerGetItems = function(values) { + var $inspectable = this.getInspectableElement() + if (!$inspectable) { + return true + } + + var itemsEvent = $.Event('autocompleteitems.oc.inspector') + + $inspectable.trigger(itemsEvent, [{ + values: values, + callback: this.proxy(this.itemsRequestDone), + property: this.inspector.getPropertyPath(this.propertyDefinition.property) + }]) + + if (itemsEvent.isDefaultPrevented()) { + return false + } + + return true + } + + AutocompleteEditor.prototype.itemsRequestDone = function(data) { if (this.isDisposed()) { // Handle the case when the asynchronous request finishes after // the editor is disposed return } + this.hideLoadingIndicator() + var loadedItems = {} if (data.options) { diff --git a/modules/system/assets/ui/js/inspector.editor.base.js b/modules/system/assets/ui/js/inspector.editor.base.js index 46d1030b6..5bdf6dfbe 100644 --- a/modules/system/assets/ui/js/inspector.editor.base.js +++ b/modules/system/assets/ui/js/inspector.editor.base.js @@ -111,6 +111,18 @@ throw new Error(errorMessage + ' Property: ' + this.propertyDefinition.property) } + BaseEditor.prototype.getInspectableElement = function() { + return this.getRootSurface().getInspectableElement() + } + + BaseEditor.prototype.isEmptyValue = function(value) { + return value === undefined + || value === null + || $.isEmptyObject(value) + || (typeof value == 'string' && $.trim(value).length === 0) + || (Object.prototype.toString.call(value) === '[object Array]' && value.length === 0) + } + // // Validation // diff --git a/modules/system/assets/ui/js/inspector.editor.dropdown.js b/modules/system/assets/ui/js/inspector.editor.dropdown.js index 2e97fdbc3..02fd3eec7 100644 --- a/modules/system/assets/ui/js/inspector.editor.dropdown.js +++ b/modules/system/assets/ui/js/inspector.editor.dropdown.js @@ -247,6 +247,11 @@ currentValue = this.propertyDefinition.default } + var callback = function dropdownOptionsRequestDoneClosure(data) { + self.hideLoadingIndicator() + self.optionsRequestDone(data, currentValue, true) + } + if (this.propertyDefinition.depends) { this.saveDependencyValues() } @@ -256,15 +261,38 @@ this.showLoadingIndicator() + if (this.triggerGetOptions(data, callback) === false) { + return + } + $form.request('onInspectableGetOptions', { data: data, - }).done(function dropdownOptionsRequestDoneClosure(data) { - self.optionsRequestDone(data, currentValue, true) - }).always( + }).done(callback).always( this.proxy(this.hideLoadingIndicator) ) } + DropdownEditor.prototype.triggerGetOptions = function(values, callback) { + var $inspectable = this.getInspectableElement() + if (!$inspectable) { + return true + } + + var optionsEvent = $.Event('dropdownoptions.oc.inspector') + + $inspectable.trigger(optionsEvent, [{ + values: values, + callback: callback, + property: this.inspector.getPropertyPath(this.propertyDefinition.property) + }]) + + if (optionsEvent.isDefaultPrevented()) { + return false + } + + return true + } + DropdownEditor.prototype.saveDependencyValues = function() { this.prevDependencyValues = this.getDependencyValues() } diff --git a/modules/system/assets/ui/js/inspector.editor.object.js b/modules/system/assets/ui/js/inspector.editor.object.js index ea9349c26..d88c28118 100644 --- a/modules/system/assets/ui/js/inspector.editor.object.js +++ b/modules/system/assets/ui/js/inspector.editor.object.js @@ -49,7 +49,8 @@ this.inspector.getInspectorUniqueId() + '-' + this.propertyDefinition.property, options, this.inspector, - this.group) + this.group, + this.propertyDefinition.property) this.inspector.mergeChildSurface(this.childInspector, currentRow) } @@ -70,14 +71,6 @@ return this.getValueOrRemove(value) } - ObjectEditor.prototype.isEmptyValue = function(value) { - return value === undefined - || value === null - || $.isEmptyObject(value) - || (typeof value == 'string' && $.trim(value).length === 0) - || (Object.prototype.toString.call(value) === '[object Array]' && value.length === 0) - } - ObjectEditor.prototype.getValueOrRemove = function(value) { if (this.propertyDefinition.ignoreIfPropertyEmpty === undefined) { return value diff --git a/modules/system/assets/ui/js/inspector.editor.set.js b/modules/system/assets/ui/js/inspector.editor.set.js index b63e3f416..3bffc4d7c 100644 --- a/modules/system/assets/ui/js/inspector.editor.set.js +++ b/modules/system/assets/ui/js/inspector.editor.set.js @@ -318,19 +318,21 @@ currentValue = [] } - if (isChecked) { - if (currentValue.indexOf(checkboxValue) === -1) { - currentValue.push(checkboxValue) - } - } - else { - var index = currentValue.indexOf(checkboxValue) - if (index !== -1) { - currentValue.splice(index, 1) + var resultValue = [] + for (var itemValue in this.propertyDefinition.items) { + if (itemValue !== checkboxValue) { + if (currentValue.indexOf(itemValue) !== -1) { + resultValue.push(itemValue) + } + } + else { + if (isChecked) { + resultValue.push(itemValue) + } } } - this.inspector.setPropertyValue(this.propertyDefinition.property, this.cleanUpValue(currentValue)) + this.inspector.setPropertyValue(this.propertyDefinition.property, this.cleanUpValue(resultValue)) this.setLinkText(this.getLink()) } diff --git a/modules/system/assets/ui/js/inspector.surface.js b/modules/system/assets/ui/js/inspector.surface.js index c6d5b24d3..25cd1cf6e 100644 --- a/modules/system/assets/ui/js/inspector.surface.js +++ b/modules/system/assets/ui/js/inspector.surface.js @@ -35,7 +35,7 @@ * not associated with an element. Inspector uses the ID for storing configuration * related to an element in the document DOM. */ - var Surface = function(containerElement, properties, values, inspectorUniqueId, options, parentSurface, group) { + var Surface = function(containerElement, properties, values, inspectorUniqueId, options, parentSurface, group, propertyName) { if (inspectorUniqueId === undefined) { throw new Error('Inspector surface unique ID should be defined.') } @@ -50,6 +50,7 @@ this.idCounter = 1 this.popupCounter = 0 this.parentSurface = parentSurface + this.propertyName = propertyName this.editors = [] this.externalParameterEditors = [] @@ -91,6 +92,7 @@ this.options.onChange = null this.options.onPopupDisplayed = null this.options.onPopupHidden = null + this.options.onGetInspectableElement = null this.parentSurface = null this.groupManager = null this.group = null @@ -482,8 +484,6 @@ var editor = new $.oc.inspector.propertyEditors[type](this, property, cell, group) if (editor.isGroupedEditor()) { -// property.groupedControl = true - $.oc.foundation.element.addClass(dataTable, 'has-groups') $.oc.foundation.element.addClass(row, 'control-group') @@ -642,6 +642,31 @@ } } + Surface.prototype.getInspectableElement = function() { + if (this.options.onGetInspectableElement !== null) { + return this.options.onGetInspectableElement() + } + } + + Surface.prototype.getPropertyPath = function(propertyName) { + var result = [], + current = this + + result.push(propertyName) + + while (current) { + if (current.propertyName) { + result.push(current.propertyName) + } + + current = current.parentSurface + } + + result.reverse() + + return result.join('.') + } + // // Nested surfaces support // @@ -785,6 +810,22 @@ if (value === $.oc.inspector.removedProperty) { continue } + + if (property.ignoreIfEmpty !== undefined && (property.ignoreIfEmpty === true || property.ignoreIfEmpty === "true") && editor) { + if (editor.isEmptyValue(value)) { + continue + } + } + + if (property.ignoreIfDefault !== undefined && (property.ignoreIfDefault === true || property.ignoreIfDefault === "true") && editor) { + if (property.default === undefined) { + throw new Error('The ignoreIfDefault feature cannot be used without the default property value.') + } + + if (this.comparePropertyValues(value, property.default)) { + continue + } + } } else { value = externalParameterEditor.getValue() @@ -810,10 +851,12 @@ var externalEditor = this.findExternalParameterEditor(property) if (externalEditor && externalEditor.isEditorVisible() && !externalEditor.validate(true)) { + result[property] = $.oc.inspector.invalidProperty continue } if (!editor.validate(true)) { + result[property] = $.oc.inspector.invalidProperty continue } @@ -853,8 +896,10 @@ return true } - Surface.prototype.hasChanges = function() { - return !this.comparePropertyValues(this.originalValues, this.values) + Surface.prototype.hasChanges = function(originalValues) { + var values = originalValues !== undefined ? originalValues : this.originalValues + + return !this.comparePropertyValues(values, this.values) } // EVENT HANDLERS @@ -876,7 +921,8 @@ enableExternalParameterEditor: false, onChange: null, onPopupDisplayed: null, - onPopupHidden: null + onPopupHidden: null, + onGetInspectableElement: null } // REGISTRATION @@ -884,4 +930,5 @@ $.oc.inspector.surface = Surface $.oc.inspector.removedProperty = {removed: true} + $.oc.inspector.invalidProperty = {invalid: true} }(window.jQuery); \ No newline at end of file diff --git a/modules/system/assets/ui/js/inspector.wrapper.base.js b/modules/system/assets/ui/js/inspector.wrapper.base.js index 4330ae0b9..06cbf884e 100644 --- a/modules/system/assets/ui/js/inspector.wrapper.base.js +++ b/modules/system/assets/ui/js/inspector.wrapper.base.js @@ -60,6 +60,10 @@ this.$element.trigger('hidden.oc.inspector') } + if (this.surface !== null && this.surface.options.onGetInspectableElement === this.proxy(this.onGetInspectableElement)) { + this.surface.options.onGetInspectableElement = null + } + this.surface = null this.$element = null this.title = null @@ -118,6 +122,7 @@ var options = this.$element.data() || {} options.enableExternalParameterEditor = this.isExternalParametersEditorEnabled() + options.onGetInspectableElement = this.proxy(this.onGetInspectableElement) this.surface = new $.oc.inspector.surface( containerElement, @@ -127,6 +132,10 @@ options) } + BaseWrapper.prototype.isLiveUpdateEnabled = function() { + return false + } + // // Wrapper API // @@ -140,7 +149,7 @@ } BaseWrapper.prototype.adoptSurface = function() { - + this.surface.options.onGetInspectableElement = this.proxy(this.onGetInspectableElement) } BaseWrapper.prototype.cleanupAfterSwitch = function() { @@ -204,12 +213,30 @@ 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. + // we don't want to change all other values (invalid properties). var existingValues = this.loadValues(this.configuration) - values = $.extend(existingValues, values) + for (var property in values) { + if (values[property] !== $.oc.inspector.invalidProperty) { + existingValues[property] = values[property] + } + } + + // Properties that use settings like ignoreIfPropertyEmpty could + // be removed from the list returned by getValidValues(). Removed + // properties should be removed from the result list. + + var filteredValues = {} + + for (var property in existingValues) { + if (values.hasOwnProperty(property)) { + filteredValues[property] = existingValues[property] + } + } + + + values = filteredValues } if ($valuesField.length > 0) { @@ -231,12 +258,29 @@ // regardless of whether Surface properties match or don't match // the original properties of the inspectable element. Without it // there could be undesirable side effects. - if (this.surface.hasChanges() || liveUpdateMode) { - if (!liveUpdateMode) { - this.$element.trigger('change') + + if (liveUpdateMode) { + this.$element.trigger('livechange') + } + else { + var hasChanges = false + + if (this.isLiveUpdateEnabled()) { + var currentValues = this.loadValues(this.configuration) + + // If the Inspector setup supports the live update mode, + // evaluate changes as a difference between the current element + // properties and internal properties stored in the Surface. + // If there is no differences, the properties have already + // been applied with a preceding live update. + hasChanges = this.surface.hasChanges(currentValues) } else { - this.$element.trigger('livechange') + hasChanges = this.surface.hasChanges() + } + + if (hasChanges) { + this.$element.trigger('change') } } } @@ -357,6 +401,10 @@ return true } + BaseWrapper.prototype.onGetInspectableElement = function() { + return this.$element + } + BaseWrapper.DEFAULTS = { containerSupported: false } diff --git a/modules/system/assets/ui/js/inspector.wrapper.container.js b/modules/system/assets/ui/js/inspector.wrapper.container.js index 5031e2aee..46724a94f 100644 --- a/modules/system/assets/ui/js/inspector.wrapper.container.js +++ b/modules/system/assets/ui/js/inspector.wrapper.container.js @@ -55,6 +55,8 @@ if (this.isLiveUpdateEnabled()) { this.surface.options.onChange = this.proxy(this.onLiveUpdate) } + + BaseProto.adoptSurface.call(this) } InspectorContainer.prototype.buildUi = function() { diff --git a/modules/system/assets/ui/js/inspector.wrapper.popup.js b/modules/system/assets/ui/js/inspector.wrapper.popup.js index a8b3da0c0..09d85799f 100644 --- a/modules/system/assets/ui/js/inspector.wrapper.popup.js +++ b/modules/system/assets/ui/js/inspector.wrapper.popup.js @@ -45,6 +45,8 @@ this.repositionPopover() this.registerPopupHandlers() + + BaseProto.adoptSurface.call(this) } InspectorPopup.prototype.cleanupAfterSwitch = function() { diff --git a/modules/system/assets/ui/storm-min.js b/modules/system/assets/ui/storm-min.js index bef8c986a..d76799cc5 100644 --- a/modules/system/assets/ui/storm-min.js +++ b/modules/system/assets/ui/storm-min.js @@ -3332,7 +3332,7 @@ $.oc={} if($.oc.inspector===undefined) $.oc.inspector={} var Base=$.oc.foundation.base,BaseProto=Base.prototype -var Surface=function(containerElement,properties,values,inspectorUniqueId,options,parentSurface,group){if(inspectorUniqueId===undefined){throw new Error('Inspector surface unique ID should be defined.')} +var Surface=function(containerElement,properties,values,inspectorUniqueId,options,parentSurface,group,propertyName){if(inspectorUniqueId===undefined){throw new Error('Inspector surface unique ID should be defined.')} this.options=$.extend({},Surface.DEFAULTS,typeof options=='object'&&options) this.rawProperties=properties this.parsedProperties=$.oc.inspector.engine.processPropertyGroups(properties) @@ -3343,6 +3343,7 @@ this.originalValues=$.extend(true,{},this.values) this.idCounter=1 this.popupCounter=0 this.parentSurface=parentSurface +this.propertyName=propertyName this.editors=[] this.externalParameterEditors=[] this.tableContainer=null @@ -3370,6 +3371,7 @@ this.originalValues=null this.options.onChange=null this.options.onPopupDisplayed=null this.options.onPopupHidden=null +this.options.onGetInspectableElement=null this.parentSurface=null this.groupManager=null this.group=null @@ -3527,6 +3529,13 @@ this.popupCounter++} Surface.prototype.popupHidden=function(){this.popupCounter-- if(this.popupCounter<0){this.popupCounter=0} if(this.popupCounter===0&&this.options.onPopupHidden!==null){this.options.onPopupHidden()}} +Surface.prototype.getInspectableElement=function(){if(this.options.onGetInspectableElement!==null){return this.options.onGetInspectableElement()}} +Surface.prototype.getPropertyPath=function(propertyName){var result=[],current=this +result.push(propertyName) +while(current){if(current.propertyName){result.push(current.propertyName)} +current=current.parentSurface} +result.reverse() +return result.join('.')} Surface.prototype.mergeChildSurface=function(surface,mergeAfterRow){var rows=surface.tableContainer.querySelectorAll('table.inspector-fields > tbody > tr') surface.tableContainer=this.getRootSurface().tableContainer for(var i=rows.length-1;i>=0;i--){var row=rows[i] @@ -3562,7 +3571,10 @@ if(!externalParameterEditor||!externalParameterEditor.isEditorVisible()){value=t if(value===undefined){var editor=this.findPropertyEditor(property.property) if(editor){value=editor.getUndefinedValue()} else{value=property.default}} -if(value===$.oc.inspector.removedProperty){continue}} +if(value===$.oc.inspector.removedProperty){continue} +if(property.ignoreIfEmpty!==undefined&&(property.ignoreIfEmpty===true||property.ignoreIfEmpty==="true")&&editor){if(editor.isEmptyValue(value)){continue}} +if(property.ignoreIfDefault!==undefined&&(property.ignoreIfDefault===true||property.ignoreIfDefault==="true")&&editor){if(property.default===undefined){throw new Error('The ignoreIfDefault feature cannot be used without the default property value.')} +if(this.comparePropertyValues(value,property.default)){continue}}} else{value=externalParameterEditor.getValue() value='{{ '+value+' }}'} result[property.property]=value} @@ -3571,8 +3583,10 @@ Surface.prototype.getValidValues=function(){var allValues=this.getValues(),resul 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} +if(externalEditor&&externalEditor.isEditorVisible()&&!externalEditor.validate(true)){result[property]=$.oc.inspector.invalidProperty +continue} +if(!editor.validate(true)){result[property]=$.oc.inspector.invalidProperty +continue} result[property]=allValues[property]} return result} Surface.prototype.validate=function(silentMode){this.getGroupManager().unmarkInvalidGroups(this.getRootTable()) @@ -3583,14 +3597,16 @@ else{continue}} if(!editor.validate(silentMode)){if(!silentMode){editor.markInvalid()} return false}} return true} -Surface.prototype.hasChanges=function(){return!this.comparePropertyValues(this.originalValues,this.values)} +Surface.prototype.hasChanges=function(originalValues){var values=originalValues!==undefined?originalValues:this.originalValues +return!this.comparePropertyValues(values,this.values)} Surface.prototype.onGroupClick=function(ev){var row=ev.currentTarget this.toggleGroup(row) $.oc.foundation.event.stop(ev) return false} -Surface.DEFAULTS={enableExternalParameterEditor:false,onChange:null,onPopupDisplayed:null,onPopupHidden:null} +Surface.DEFAULTS={enableExternalParameterEditor:false,onChange:null,onPopupDisplayed:null,onPopupHidden:null,onGetInspectableElement:null} $.oc.inspector.surface=Surface -$.oc.inspector.removedProperty={removed:true}}(window.jQuery);+function($){"use strict";var Base=$.oc.foundation.base,BaseProto=Base.prototype +$.oc.inspector.removedProperty={removed:true} +$.oc.inspector.invalidProperty={invalid:true}}(window.jQuery);+function($){"use strict";var Base=$.oc.foundation.base,BaseProto=Base.prototype var InspectorManager=function(){Base.call(this) this.init()} InspectorManager.prototype=Object.create(BaseProto) @@ -3664,6 +3680,7 @@ BaseWrapper.prototype.constructor=Base BaseWrapper.prototype.dispose=function(){if(!this.switched){this.$element.removeClass('inspector-open') this.setInspectorVisibleFlag(false) this.$element.trigger('hidden.oc.inspector')} +if(this.surface!==null&&this.surface.options.onGetInspectableElement===this.proxy(this.onGetInspectableElement)){this.surface.options.onGetInspectableElement=null} this.surface=null this.$element=null this.title=null @@ -3681,10 +3698,12 @@ return code} BaseWrapper.prototype.isExternalParametersEditorEnabled=function(){return this.$element.closest('[data-inspector-external-parameters]').length>0} BaseWrapper.prototype.initSurface=function(containerElement,properties,values){var options=this.$element.data()||{} options.enableExternalParameterEditor=this.isExternalParametersEditorEnabled() +options.onGetInspectableElement=this.proxy(this.onGetInspectableElement) this.surface=new $.oc.inspector.surface(containerElement,properties,values,$.oc.inspector.helpers.generateElementUniqueId(this.$element.get(0)),options)} +BaseWrapper.prototype.isLiveUpdateEnabled=function(){return false} BaseWrapper.prototype.createSurfaceAndUi=function(properties,values){} BaseWrapper.prototype.setInspectorVisibleFlag=function(value){this.$element.data('oc.inspectorVisible',value)} -BaseWrapper.prototype.adoptSurface=function(){} +BaseWrapper.prototype.adoptSurface=function(){this.surface.options.onGetInspectableElement=this.proxy(this.onGetInspectableElement)} BaseWrapper.prototype.cleanupAfterSwitch=function(){this.switched=true this.dispose()} BaseWrapper.prototype.loadValues=function(configuration){var $valuesField=this.getElementValuesInput() @@ -3697,13 +3716,20 @@ values[normalizedPropertyName]=attribute.value}} return values} BaseWrapper.prototype.applyValues=function(liveUpdateMode){var $valuesField=this.getElementValuesInput(),values=liveUpdateMode?this.surface.getValidValues():this.surface.getValues() if(liveUpdateMode){var existingValues=this.loadValues(this.configuration) -values=$.extend(existingValues,values)} +for(var property in values){if(values[property]!==$.oc.inspector.invalidProperty){existingValues[property]=values[property]}} +var filteredValues={} +for(var property in existingValues){if(values.hasOwnProperty(property)){filteredValues[property]=existingValues[property]}} +values=filteredValues} if($valuesField.length>0){$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()||liveUpdateMode){if(!liveUpdateMode){this.$element.trigger('change')} -else{this.$element.trigger('livechange')}}} +if(liveUpdateMode){this.$element.trigger('livechange')} +else{var hasChanges=false +if(this.isLiveUpdateEnabled()){var currentValues=this.loadValues(this.configuration) +hasChanges=this.surface.hasChanges(currentValues)} +else{hasChanges=this.surface.hasChanges()} +if(hasChanges){this.$element.trigger('change')}}} 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') @@ -3737,6 +3763,7 @@ BaseWrapper.prototype.triggerHiding=function(){var hidingEvent=$.Event('hiding.o this.$element.trigger(hidingEvent,[{values:values}]) if(hidingEvent.isDefaultPrevented()){return false} return true} +BaseWrapper.prototype.onGetInspectableElement=function(){return this.$element} BaseWrapper.DEFAULTS={containerSupported:false} $.oc.inspector.wrappers.base=BaseWrapper}(window.jQuery);+function($){"use strict";var Base=$.oc.inspector.wrappers.base,BaseProto=Base.prototype var InspectorPopup=function($element,surface,options){this.$popoverContainer=null @@ -3756,7 +3783,8 @@ this.registerPopupHandlers()} InspectorPopup.prototype.adoptSurface=function(){this.showPopover() this.surface.moveToContainer(this.$popoverContainer.find('[data-surface-container]').get(0)) this.repositionPopover() -this.registerPopupHandlers()} +this.registerPopupHandlers() +BaseProto.adoptSurface.call(this)} InspectorPopup.prototype.cleanupAfterSwitch=function(){this.cleaningUp=true this.switched=true this.forceClose()} @@ -3833,7 +3861,8 @@ 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)}} +if(this.isLiveUpdateEnabled()){this.surface.options.onChange=this.proxy(this.onLiveUpdate)} +BaseProto.adoptSurface.call(this)} InspectorContainer.prototype.buildUi=function(){var scrollable=this.isScrollable(),head=this.buildHead(),layoutElements=this.buildLayout() layoutElements.headContainer.appendChild(head) if(scrollable){var scrollpad=this.buildScrollpad() @@ -4055,6 +4084,8 @@ BaseEditor.prototype.updateDisplayedValue=function(value){} BaseEditor.prototype.getPropertyName=function(){return this.propertyDefinition.property} BaseEditor.prototype.getUndefinedValue=function(){return this.propertyDefinition.default===undefined?undefined:this.propertyDefinition.default} BaseEditor.prototype.throwError=function(errorMessage){throw new Error(errorMessage+' Property: '+this.propertyDefinition.property)} +BaseEditor.prototype.getInspectableElement=function(){return this.getRootSurface().getInspectableElement()} +BaseEditor.prototype.isEmptyValue=function(value){return value===undefined||value===null||$.isEmptyObject(value)||(typeof value=='string'&&$.trim(value).length===0)||(Object.prototype.toString.call(value)==='[object Array]'&&value.length===0)} 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)} @@ -4205,11 +4236,20 @@ if(value===undefined){value=this.propertyDefinition.default} select.value=value} DropdownEditor.prototype.loadDynamicOptions=function(initialization){var currentValue=this.inspector.getPropertyValue(this.propertyDefinition.property),data=this.inspector.getValues(),self=this,$form=$(this.getSelect()).closest('form') if(currentValue===undefined){currentValue=this.propertyDefinition.default} +var callback=function dropdownOptionsRequestDoneClosure(data){self.hideLoadingIndicator() +self.optionsRequestDone(data,currentValue,true)} if(this.propertyDefinition.depends){this.saveDependencyValues()} data['inspectorProperty']=this.propertyDefinition.property data['inspectorClassName']=this.inspector.options.inspectorClass this.showLoadingIndicator() -$form.request('onInspectableGetOptions',{data:data,}).done(function dropdownOptionsRequestDoneClosure(data){self.optionsRequestDone(data,currentValue,true)}).always(this.proxy(this.hideLoadingIndicator))} +if(this.triggerGetOptions(data,callback)===false){return} +$form.request('onInspectableGetOptions',{data:data,}).done(callback).always(this.proxy(this.hideLoadingIndicator))} +DropdownEditor.prototype.triggerGetOptions=function(values,callback){var $inspectable=this.getInspectableElement() +if(!$inspectable){return true} +var optionsEvent=$.Event('dropdownoptions.oc.inspector') +$inspectable.trigger(optionsEvent,[{values:values,callback:callback,property:this.inspector.getPropertyPath(this.propertyDefinition.property)}]) +if(optionsEvent.isDefaultPrevented()){return false} +return true} DropdownEditor.prototype.saveDependencyValues=function(){this.prevDependencyValues=this.getDependencyValues()} DropdownEditor.prototype.getDependencyValues=function(){var result='' for(var i=0,len=this.propertyDefinition.depends.length;i-1} SetEditor.prototype.setPropertyValue=function(checkboxValue,isChecked){var currentValue=this.getNormalizedValue() if(currentValue===undefined){currentValue=this.propertyDefinition.default} if(!currentValue){currentValue=[]} -if(isChecked){if(currentValue.indexOf(checkboxValue)===-1){currentValue.push(checkboxValue)}} -else{var index=currentValue.indexOf(checkboxValue) -if(index!==-1){currentValue.splice(index,1)}} -this.inspector.setPropertyValue(this.propertyDefinition.property,this.cleanUpValue(currentValue)) +var resultValue=[] +for(var itemValue in this.propertyDefinition.items){if(itemValue!==checkboxValue){if(currentValue.indexOf(itemValue)!==-1){resultValue.push(itemValue)}} +else{if(isChecked){resultValue.push(itemValue)}}} +this.inspector.setPropertyValue(this.propertyDefinition.property,this.cleanUpValue(resultValue)) this.setLinkText(this.getLink())} SetEditor.prototype.generateSequencedId=function(){return this.inspector.generateSequencedId()} SetEditor.prototype.disposeEditors=function(){for(var i=0,len=this.editors.length;i=0;i--){loadedItems[data.options[i].value]=data.options[i].title}} this.buildAutoComplete(loadedItems)}