diff --git a/modules/system/assets/ui/js/inspector.editor.autocomplete.js b/modules/system/assets/ui/js/inspector.editor.autocomplete.js index 0c204f78b..54ea3290d 100644 --- a/modules/system/assets/ui/js/inspector.editor.autocomplete.js +++ b/modules/system/assets/ui/js/inspector.editor.autocomplete.js @@ -135,6 +135,9 @@ $.oc.foundation.element.addClass(container, 'loading-indicator-container size-small') this.showLoadingIndicator() + data['inspectorProperty'] = this.propertyDefinition.property + data['inspectorClassName'] = this.inspector.options.inspectorClass + $form.request('onInspectableGetOptions', { data: data, }) diff --git a/modules/system/assets/ui/js/inspector.editor.object.js b/modules/system/assets/ui/js/inspector.editor.object.js index b949f5c46..31ffe2c3c 100644 --- a/modules/system/assets/ui/js/inspector.editor.object.js +++ b/modules/system/assets/ui/js/inspector.editor.object.js @@ -34,7 +34,8 @@ inspectorContainer = document.createElement('div'), options = { enableExternalParameterEditor: false, - onChange: this.proxy(this.onInspectorDataChange) + onChange: this.proxy(this.onInspectorDataChange), + inspectorClass: this.inspector.options.inspectorClass }, values = this.inspector.getPropertyValue(this.propertyDefinition.property) diff --git a/modules/system/assets/ui/js/inspector.editor.objectlist.js b/modules/system/assets/ui/js/inspector.editor.objectlist.js index 53dcf2821..d14661a61 100644 --- a/modules/system/assets/ui/js/inspector.editor.objectlist.js +++ b/modules/system/assets/ui/js/inspector.editor.objectlist.js @@ -292,7 +292,8 @@ values = $.parseJSON(dataStr), options = { enableExternalParameterEditor: false, - onChange: this.proxy(this.onInspectorDataChange) + onChange: this.proxy(this.onInspectorDataChange), + inspectorClass: this.inspector.options.inspectorClass } this.currentRowInspector = new $.oc.inspector.surface(inspectorContainer, properties, values, diff --git a/modules/system/assets/ui/js/inspector.editor.set.js b/modules/system/assets/ui/js/inspector.editor.set.js index 8ee495ec6..77e347317 100644 --- a/modules/system/assets/ui/js/inspector.editor.set.js +++ b/modules/system/assets/ui/js/inspector.editor.set.js @@ -159,6 +159,9 @@ $.oc.foundation.element.addClass(link, 'loading-indicator-container size-small') this.showLoadingIndicator() + data['inspectorProperty'] = this.propertyDefinition.property + data['inspectorClassName'] = this.inspector.options.inspectorClass + $form.request('onInspectableGetOptions', { data: data, }) diff --git a/modules/system/assets/ui/js/inspector.manager.js b/modules/system/assets/ui/js/inspector.manager.js index 3e138106c..73267680d 100644 --- a/modules/system/assets/ui/js/inspector.manager.js +++ b/modules/system/assets/ui/js/inspector.manager.js @@ -83,7 +83,7 @@ } else { // If the container is already in use, apply values to the inspectable elements - if (!this.applyValuesFromContainer($container)) { + if (!this.applyValuesFromContainer($container) || !this.containerHidingAllowed($container)) { return } @@ -128,6 +128,17 @@ return true } + InspectorManager.prototype.containerHidingAllowed = function($container) { + var allowedEvent = $.Event('beforeContainerHide.oc.inspector') + + $container.trigger(allowedEvent) + if (allowedEvent.isDefaultPrevented()) { + return false + } + + return true + } + InspectorManager.prototype.onInspectableClicked = function(ev) { var $element = $(ev.currentTarget) diff --git a/modules/system/assets/ui/js/inspector.surface.js b/modules/system/assets/ui/js/inspector.surface.js index b395f7a2d..63d9b6ff3 100644 --- a/modules/system/assets/ui/js/inspector.surface.js +++ b/modules/system/assets/ui/js/inspector.surface.js @@ -821,6 +821,10 @@ return true } + Surface.prototype.hasChanges = function() { + return !this.comparePropertyValues(this.originalValues, this.values) + } + // EVENT HANDLERS // diff --git a/modules/system/assets/ui/js/inspector.wrapper.base.js b/modules/system/assets/ui/js/inspector.wrapper.base.js index 12e4fbcf4..d3d020062 100644 --- a/modules/system/assets/ui/js/inspector.wrapper.base.js +++ b/modules/system/assets/ui/js/inspector.wrapper.base.js @@ -21,8 +21,19 @@ var BaseWrapper = function($element, sourceWrapper, options) { this.$element = $element + this.options = $.extend({}, BaseWrapper.DEFAULTS, typeof options == 'object' && options) + this.switched = false + + Base.call(this) + if (!sourceWrapper) { - this.surface = surface + if (!this.triggerShowingAndInit()) { + // this.init() is called inside triggerShowing() + + return + } + + this.surface = null this.title = null this.description = null } @@ -32,13 +43,9 @@ this.description = sourceWrapper.description sourceWrapper = null + + this.init() } - - this.options = $.extend({}, BaseWrapper.DEFAULTS, typeof options == 'object' && options) - this.switched = false - - Base.call(this) - this.init() } BaseWrapper.prototype = Object.create(BaseProto) @@ -48,6 +55,8 @@ if (!this.switched) { this.$element.removeClass('inspector-open') this.setInspectorVisibleFlag(false) + + this.$element.trigger('hidden.oc.inspector') } this.surface = null @@ -104,9 +113,9 @@ } BaseWrapper.prototype.initSurface = function(containerElement, properties, values) { - var options = { - enableExternalParameterEditor: this.isExternalParametersEditorEnabled() - } + var options = this.$element.data() || {} + + options.enableExternalParameterEditor = this.isExternalParametersEditorEnabled() this.surface = new $.oc.inspector.surface( containerElement, @@ -203,6 +212,10 @@ this.$element.attr('data-property-' + property, value) } } + + if (this.surface.hasChanges()) { + this.$element.trigger('change') + } } // @@ -210,7 +223,7 @@ // BaseWrapper.prototype.loadConfiguration = function() { - var $configurationField = this.$element.find('input[data-inspector-config]'), + var configString = this.$element.data('inspector-config'), result = { properties: {}, title: null, @@ -220,6 +233,15 @@ result.title = this.$element.data('inspector-title') result.description = this.$element.data('inspector-description') + if (configString !== undefined) { + result.properties = this.parseConfiguration(configString) + + this.configurationLoaded(result) + return + } + + var $configurationField = this.$element.find('input[data-inspector-config]') + if ($configurationField.length > 0) { result.properties = this.parseConfiguration($configurationField.val()) @@ -280,6 +302,37 @@ this.configurationLoaded(result) } + // + // Events + // + + BaseWrapper.prototype.triggerShowingAndInit = function() { + var e = $.Event('showing.oc.inspector') + + this.$element.trigger(e, [{callback: this.proxy(this.init)}]) + if (e.isDefaultPrevented()) { + this.$element = null + + return false + } + + if (!e.isPropagationStopped()) { + this.init() + } + } + + BaseWrapper.prototype.triggerHiding = function() { + var hidingEvent = $.Event('hiding.oc.inspector'), + values = this.surface.getValues() + + this.$element.trigger(hidingEvent, [{values: values}]) + if (hidingEvent.isDefaultPrevented()) { + return false + } + + return true + } + 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 f96205ab7..8ed49dfbb 100644 --- a/modules/system/assets/ui/js/inspector.wrapper.container.js +++ b/modules/system/assets/ui/js/inspector.wrapper.container.js @@ -169,12 +169,15 @@ InspectorContainer.prototype.registerHandlers = function() { this.options.container.on('apply.oc.inspector', this.proxy(this.onApplyValues)) + this.options.container.on('beforeContainerHide.oc.inspector', this.proxy(this.onBeforeHide)) } InspectorContainer.prototype.unregisterHandlers = function() { var $layout = $(this.getLayout()) 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)) @@ -196,12 +199,24 @@ } } + InspectorContainer.prototype.onBeforeHide = function(ev) { + if (!this.triggerHiding()) { + ev.preventDefault() + return false + } + } + InspectorContainer.prototype.onClose = function(ev) { if (!this.validateAndApply()) { ev.preventDefault() return false } + if (!this.triggerHiding()) { + ev.preventDefault() + return false + } + this.surface.dispose() this.dispose() diff --git a/modules/system/assets/ui/js/inspector.wrapper.popup.js b/modules/system/assets/ui/js/inspector.wrapper.popup.js index a8a22f09e..8ee408fb2 100644 --- a/modules/system/assets/ui/js/inspector.wrapper.popup.js +++ b/modules/system/assets/ui/js/inspector.wrapper.popup.js @@ -157,11 +157,7 @@ return false } - var hidingEvent = $.Event('hiding.oc.inspector'), - values = this.surface.getValues() - - this.$element.trigger(hidingEvent, [{values: values}]) - if (hidingEvent.isDefaultPrevented()) { + if (!this.triggerHiding()) { ev.preventDefault() return false } diff --git a/modules/system/assets/ui/less/inspector.less b/modules/system/assets/ui/less/inspector.less index ff2eb9bbb..ef5e26e40 100644 --- a/modules/system/assets/ui/less/inspector.less +++ b/modules/system/assets/ui/less/inspector.less @@ -122,6 +122,33 @@ } } + &.autocomplete { + padding: 0; + + .autocomplete-container { + input[type=text] { + padding: 5px 12px; + } + + ul.dropdown-menu { + background: white; + font-size: 12px; + + li a { + padding: 5px 12px; + } + } + + .loading-indicator { + span { + margin-top: -12px; + right: 10px; + left: auto; + } + } + } + } + &.trigger-cell { padding: 0!important; @@ -419,6 +446,156 @@ div.control-popover { } } +.inspector-columns-editor { + min-height: 400px; + margin-bottom: 20px; + border-bottom: 1px solid #bdc3c7; + + .items-column { + width: 250px; + } + + .inspector-wrapper { + background: #f2f2f2; // Use @color-inspector-bg instead + border-left: 2px solid #bdc3c7; + } + + .toolbar { + padding: 20px; + } +} + +.inspector-table-list { + border-top: 1px solid #e2e2e2; + .user-select(none); +} + +div.inspector-dictionary-container { + border: 1px solid #e0e0e0; + + .values { + height: 300px; + } + + table.headers { + width: 100%; + border: none; + + td { + width: 50%; + padding: 7px 5px; + font-size: 13px; + text-transform: uppercase; + font-weight: 600; + color: #333333; + background: white; + border-bottom: 1px solid #e0e0e0; + + &:first-child { + border-right: 1px solid #e0e0e0; + } + } + } + + table.inspector-dictionary-table{ + width: 100%; + border: none; + + tbody tr { + td { + width: 50%; + padding: 0!important; + border-bottom: 1px solid #e0e0e0; + + div { + border: 1px solid #fff; + } + + &.active div { + border-color: #5fb6f5; + } + + input { + width: 100%; + height: 100%; + display: block; + outline: none; + border: none; + padding: 7px 5px; + + &:focus { + border: none; + outline: none; + } + } + + &:first-child { + border-right: 1px solid #e0e0e0; + } + } + + &:last-child td { + border-bottom: none; + } + } + } +} + +.inspector-header { + background: #d35400; + padding: 14px 16px; + position: relative; + color: #ffffff; + + h3 { + font-size: 14px; + font-weight: 600; + margin-top: 0; + margin-bottom: 0; + padding-right: 15px; + line-height: 130%; + } + + p { + font-size: 13px; + font-weight: 100; + margin: 10px 0 0 0; + + &:empty { + display: none; + } + } + + span { + position: absolute; + top: 12px; + float: none; + color: #ffffff; + cursor: pointer; + + .opacity(0.4); + &:hover { + .opacity(1); + color: #ffffff; + } + } + + .detach { + right: 26px; + } + + .close { + right: 11px; + font-size: 21px; + } +} + +.inspector-container { + .control-scrollpad { + position: absolute; + } +} + .select2-dropdown { &.ocInspectorDropdown { font-size: 12px; diff --git a/modules/system/assets/ui/less/popover.less b/modules/system/assets/ui/less/popover.less index 5477dbeda..5e3297e91 100644 --- a/modules/system/assets/ui/less/popover.less +++ b/modules/system/assets/ui/less/popover.less @@ -172,6 +172,25 @@ div.control-popover { .opacity(1); } } + + .inspector-move-to-container { + .opacity(0.4); + position: absolute; + top: 12px; + right: 26px; + float: none; + color: #ffffff; + cursor: pointer; + + &:hover { + .opacity(1); + color: #ffffff; + } + + &:before { + .transform(~'transform: rotate(270deg)'); + } + } } &.placement-bottom .popover-head:before { diff --git a/modules/system/assets/ui/storm-min.js b/modules/system/assets/ui/storm-min.js index 4a5e548ff..ab9f0f18e 100644 --- a/modules/system/assets/ui/storm-min.js +++ b/modules/system/assets/ui/storm-min.js @@ -3479,4 +3479,1826 @@ $(window).on('ajaxInvalidField',function(event,element,name,messages,isFirst){if event.preventDefault() var $el=$(element) $el.closest('[data-control=tab]').ocTab('goToElement',$el) -$el.focus()})}(window.jQuery); \ No newline at end of file +$el.focus()})}(window.jQuery);+function($){"use strict";if($.oc===undefined) +$.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.')} +this.options=$.extend({},Surface.DEFAULTS,typeof options=='object'&&options) +this.rawProperties=properties +this.parsedProperties=$.oc.inspector.engine.processPropertyGroups(properties) +this.container=containerElement +this.inspectorUniqueId=inspectorUniqueId +this.values=values +this.originalValues=$.extend(true,{},values) +this.idCounter=1 +this.popupCounter=0 +this.parentSurface=parentSurface +this.editors=[] +this.externalParameterEditors=[] +this.tableContainer=null +this.groupManager=null +this.group=null +if(group!==undefined){this.group=group} +if(!this.parentSurface){this.groupManager=new $.oc.inspector.groupManager(this.inspectorUniqueId)} +Base.call(this) +this.init()} +Surface.prototype=Object.create(BaseProto) +Surface.prototype.constructor=Surface +Surface.prototype.dispose=function(){this.unregisterHandlers() +this.disposeControls() +this.disposeEditors() +this.removeElements() +this.disposeExternalParameterEditors() +this.container=null +this.tableContainer=null +this.rawProperties=null +this.parsedProperties=null +this.editors=null +this.externalParameterEditors=null +this.values=null +this.originalValues=null +this.options.onChange=null +this.options.onPopupDisplayed=null +this.options.onPopupHidden=null +this.parentSurface=null +this.groupManager=null +this.group=null +BaseProto.dispose.call(this)} +Surface.prototype.init=function(){if(this.groupManager&&!this.group){this.group=this.groupManager.createGroup('root')} +this.build() +if(!this.parentSurface){$.oc.foundation.controlUtils.markDisposable(this.tableContainer)} +this.registerHandlers()} +Surface.prototype.registerHandlers=function(){if(!this.parentSurface){$(this.tableContainer).one('dispose-control',this.proxy(this.dispose)) +$(this.tableContainer).on('click','tr.group, tr.control-group',this.proxy(this.onGroupClick))}} +Surface.prototype.unregisterHandlers=function(){if(!this.parentSurface){$(this.tableContainer).off('dispose-control',this.proxy(this.dispose)) +$(this.tableContainer).off('click','tr.group, tr.control-group',this.proxy(this.onGroupClick))}} +Surface.prototype.build=function(){this.tableContainer=document.createElement('div') +var dataTable=document.createElement('table'),tbody=document.createElement('tbody') +$.oc.foundation.element.addClass(dataTable,'inspector-fields') +if(this.parsedProperties.hasGroups){$.oc.foundation.element.addClass(dataTable,'has-groups')} +var currentGroup=this.group +for(var i=0,len=this.parsedProperties.properties.length;i=0;i--){var row=groups[i].findGroupRow(table) +if(row){this.toggleGroup(row,true)}}} +Surface.prototype.expandOrCollapseRows=function(rows,collapse,duration,noAnimation){var row=rows.pop(),self=this +if(row){if(!noAnimation){setTimeout(function toggleRow(){$.oc.foundation.element.toggleClass(row,'collapsed',collapse) +$.oc.foundation.element.toggleClass(row,'expanded',!collapse) +self.expandOrCollapseRows(rows,collapse,duration,noAnimation)},duration)}else{$.oc.foundation.element.toggleClass(row,'collapsed',collapse) +$.oc.foundation.element.toggleClass(row,'expanded',!collapse) +self.expandOrCollapseRows(rows,collapse,duration,noAnimation)}}} +Surface.prototype.getGroupManager=function(){return this.getRootSurface().groupManager} +Surface.prototype.buildEditor=function(row,property,dataTable,group){if(property.itemType!=='property'){return} +this.validateEditorType(property.type) +var cell=document.createElement('td'),type=property.type +row.appendChild(cell) +if(type===undefined){type='string'} +var editor=new $.oc.inspector.propertyEditors[type](this,property,cell,group) +if(editor.isGroupedEditor()){$.oc.foundation.element.addClass(dataTable,'has-groups') +$.oc.foundation.element.addClass(row,'control-group') +this.applyGroupIndexAttribute(property,row,editor.group,true) +this.buildGroupExpandControl(row.querySelector('span.title-element'),property,true,editor.hasChildSurface(),editor.group) +if(cell.children.length==0){row.querySelector('th').setAttribute('colspan',2) +row.removeChild(cell)}} +this.editors.push(editor)} +Surface.prototype.generateSequencedId=function(){this.idCounter++ +return this.inspectorUniqueId+'-'+this.idCounter} +Surface.prototype.getPropertyValue=function(property){return this.values[property]} +Surface.prototype.setPropertyValue=function(property,value,supressChangeEvents,forceEditorUpdate){if(value!==undefined){this.values[property]=value} +else{if(this.values[property]!==undefined){delete this.values[property]}} +if(!supressChangeEvents){if(this.originalValues[property]===undefined||!this.comparePropertyValues(this.originalValues[property],value)){this.markPropertyChanged(property,true)} +else{this.markPropertyChanged(property,false)} +this.notifyEditorsPropertyChanged(property,value) +if(this.options.onChange!==null){this.options.onChange(property,value)}} +if(forceEditorUpdate){var editor=this.findPropertyEditor(property) +if(editor){editor.updateDisplayedValue(value)}} +return value} +Surface.prototype.notifyEditorsPropertyChanged=function(property,value){for(var i=0,len=this.editors.length;i tbody > tr') +surface.tableContainer=this.getRootSurface().tableContainer +for(var i=rows.length-1;i>=0;i--){var row=rows[i] +mergeAfterRow.parentNode.insertBefore(row,mergeAfterRow.nextSibling) +this.applyGroupLevelToRow(row,surface.group)}} +Surface.prototype.getRowHeadElement=function(row){for(var i=row.children.length-1;i>=0;i--){var element=row.children[i] +if(element.tagName==='TH'){return element}} +return null} +Surface.prototype.getInspectorUniqueId=function(){return this.inspectorUniqueId} +Surface.prototype.getRootSurface=function(){var current=this +while(current){if(!current.parentSurface){return current} +current=current.parentSurface}} +Surface.prototype.removeElements=function(){if(!this.parentSurface){this.tableContainer.parentNode.removeChild(this.tableContainer);}} +Surface.prototype.disposeEditors=function(){for(var i=0,len=this.editors.length;i0} +BaseWrapper.prototype.initSurface=function(containerElement,properties,values){var options=this.$element.data()||{} +options.enableExternalParameterEditor=this.isExternalParametersEditorEnabled() +this.surface=new $.oc.inspector.surface(containerElement,properties,values,$.oc.inspector.helpers.generateElementUniqueId(this.$element.get(0)),options)} +BaseWrapper.prototype.createSurfaceAndUi=function(properties,values){} +BaseWrapper.prototype.setInspectorVisibleFlag=function(value){this.$element.data('oc.inspectorVisible',value)} +BaseWrapper.prototype.adoptSurface=function(){} +BaseWrapper.prototype.cleanupAfterSwitch=function(){this.switched=true +this.dispose()} +BaseWrapper.prototype.loadValues=function(configuration){var $valuesField=this.getElementValuesInput() +if($valuesField.length>0){var valuesStr=$.trim($valuesField.val()) +try{return valuesStr.length===0?{}:$.parseJSON(valuesStr)}catch(err){throw new Error('Error parsing Inspector field values. '+err)}} +var values={},attributes=this.$element.get(0).attributes +for(var i=0,len=attributes.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')}} +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') +if(configString!==undefined){result.properties=this.parseConfiguration(configString) +this.configurationLoaded(result) +return} +var $configurationField=this.$element.find('input[data-inspector-config]') +if($configurationField.length>0){result.properties=this.parseConfiguration($configurationField.val()) +this.configurationLoaded(result) +return} +var $form=this.$element.closest('form'),data=this.$element.data(),self=this +$.oc.stripeLoadIndicator.show() +var request=$form.request('onGetInspectorConfiguration',{data:data}).done(function inspectorConfigurationRequestDoneClosure(data){self.onConfigurartionRequestDone(data,result)}).always(function(){$.oc.stripeLoadIndicator.hide()})} +BaseWrapper.prototype.parseConfiguration=function(configuration){if(!$.isArray(configuration)&&!$.isPlainObject(configuration)){if($.trim(configuration)===0){return{}} +try{return $.parseJSON(configuration)}catch(err){throw new Error('Error parsing Inspector configuration. '+err)}}else{return configuration}} +BaseWrapper.prototype.configurationLoaded=function(configuration){var values=this.loadValues(configuration.properties) +this.title=configuration.title +this.description=configuration.description +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} +if(data.configuration.description!==undefined){result.description=data.configuration.description} +this.configurationLoaded(result)} +BaseWrapper.prototype.triggerShowingAndInit=function(){var e=$.Event('showing.oc.inspector') +this.$element.trigger(e,[{callback:this.proxy(this.init)}]) +if(e.isDefaultPrevented()){this.$element=null +return false} +if(!e.isPropagationStopped()){this.init()}} +BaseWrapper.prototype.triggerHiding=function(){var hidingEvent=$.Event('hiding.oc.inspector'),values=this.surface.getValues() +this.$element.trigger(hidingEvent,[{values:values}]) +if(hidingEvent.isDefaultPrevented()){return false} +return true} +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 +this.popoverObj=null +this.cleaningUp=false +Base.call(this,$element,surface,options)} +InspectorPopup.prototype=Object.create(BaseProto) +InspectorPopup.prototype.constructor=Base +InspectorPopup.prototype.dispose=function(){this.unregisterHandlers() +this.$popoverContainer=null +this.popoverObj=null +BaseProto.dispose.call(this)} +InspectorPopup.prototype.createSurfaceAndUi=function(properties,values,title,description){this.showPopover() +this.initSurface(this.$popoverContainer.find('[data-surface-container]').get(0),properties,values) +this.registerPopupHandlers()} +InspectorPopup.prototype.adoptSurface=function(){this.showPopover() +this.surface.moveToContainer(this.$popoverContainer.find('[data-surface-container]').get(0)) +this.registerPopupHandlers()} +InspectorPopup.prototype.cleanupAfterSwitch=function(){this.cleaningUp=true +this.switched=true +this.forceClose()} +InspectorPopup.prototype.getPopoverContents=function(){return'
\ +

\ +

\ + \ +
\ +
\ +
\ + '} +InspectorPopup.prototype.showPopover=function(){var offset=this.$element.data('inspector-offset'),offsetX=this.$element.data('inspector-offset-x'),offsetY=this.$element.data('inspector-offset-y'),placement=this.$element.data('inspector-placement'),fallbackPlacement=this.$element.data('inspector-fallback-placement') +if(offset===undefined){offset=15} +if(placement===undefined){placement='bottom'} +if(fallbackPlacement===undefined){fallbackPlacement='bottom'} +this.$element.ocPopover({content:this.getPopoverContents(),highlightModalTarget:true,modal:true,placement:placement,fallbackPlacement:fallbackPlacement,containerClass:'control-inspector',container:this.$element.data('inspector-container'),offset:offset,offsetX:offsetX,offsetY:offsetY,width:400}) +this.setInspectorVisibleFlag(true) +this.popoverObj=this.$element.data('oc.popover') +this.$popoverContainer=this.popoverObj.$container +if(this.options.containerSupported){var moveToContainerButton=$('') +this.$popoverContainer.find('.popover-head').append(moveToContainerButton)} +this.$popoverContainer.find('[data-inspector-title]').text(this.title) +this.$popoverContainer.find('[data-inspector-description]').text(this.description)} +InspectorPopup.prototype.forceClose=function(){this.$popoverContainer.trigger('close.oc.popover')} +InspectorPopup.prototype.registerPopupHandlers=function(){this.surface.options.onPopupDisplayed=this.proxy(this.onPopupEditorDisplayed) +this.surface.options.onPopupHidden=this.proxy(this.onPopupEditorHidden) +this.popoverObj.options.onCheckDocumentClickTarget=this.proxy(this.onCheckDocumentClickTarget) +this.$element.on('hiding.oc.popover',this.proxy(this.onBeforeHide)) +this.$element.on('hide.oc.popover',this.proxy(this.onHide)) +this.$popoverContainer.on('keydown',this.proxy(this.onPopoverKeyDown)) +if(this.options.containerSupported){this.$popoverContainer.on('click','span.inspector-move-to-container',this.proxy(this.onMoveToContainer))}} +InspectorPopup.prototype.unregisterHandlers=function(){this.popoverObj.options.onCheckDocumentClickTarget=null +this.$element.off('hiding.oc.popover',this.proxy(this.onBeforeHide)) +this.$element.off('hide.oc.popover',this.proxy(this.onHide)) +this.$popoverContainer.off('keydown',this.proxy(this.onPopoverKeyDown)) +if(this.options.containerSupported){this.$popoverContainer.off('click','span.inspector-move-to-container',this.proxy(this.onMoveToContainer))} +this.surface.options.onPopupDisplayed=null +this.surface.options.onPopupHidden=null} +InspectorPopup.prototype.onBeforeHide=function(ev){if(this.cleaningUp){return} +if(!this.surface.validate()){ev.preventDefault() +return false} +if(!this.triggerHiding()){ev.preventDefault() +return false} +this.applyValues()} +InspectorPopup.prototype.onHide=function(ev){this.dispose()} +InspectorPopup.prototype.onPopoverKeyDown=function(ev){if(ev.keyCode==13){$(ev.currentTarget).trigger('close.oc.popover')}} +InspectorPopup.prototype.onPopupEditorDisplayed=function(){this.popoverObj.options.closeOnPageClick=false +this.popoverObj.options.closeOnEsc=false} +InspectorPopup.prototype.onPopupEditorHidden=function(){this.popoverObj.options.closeOnPageClick=true +this.popoverObj.options.closeOnEsc=true} +InspectorPopup.prototype.onCheckDocumentClickTarget=function(element){if($.contains(this.$element,element)||this.$element.get(0)===element){return true}} +InspectorPopup.prototype.onMoveToContainer=function(){$.oc.inspector.manager.switchToContainer(this)} +$.oc.inspector.wrappers.popup=InspectorPopup}(window.jQuery);+function($){"use strict";var Base=$.oc.inspector.wrappers.base,BaseProto=Base.prototype +var InspectorContainer=function($element,surface,options){if(!options.container){throw new Error('Cannot create Inspector container wrapper without a container element.')} +this.surfaceContainer=null +Base.call(this,$element,surface,options)} +InspectorContainer.prototype=Object.create(BaseProto) +InspectorContainer.prototype.constructor=Base +InspectorContainer.prototype.init=function(){this.registerHandlers() +BaseProto.init.call(this)} +InspectorContainer.prototype.dispose=function(){this.unregisterHandlers() +this.removeControls() +this.surfaceContainer=null +BaseProto.dispose.call(this)} +InspectorContainer.prototype.createSurfaceAndUi=function(properties,values){this.buildUi() +this.initSurface(this.surfaceContainer,properties,values)} +InspectorContainer.prototype.adoptSurface=function(){this.buildUi() +this.surface.moveToContainer(this.surfaceContainer)} +InspectorContainer.prototype.buildUi=function(){var scrollable=this.isScrollable(),head=this.buildHead(),layoutElements=this.buildLayout() +layoutElements.headContainer.appendChild(head) +if(scrollable){var scrollpad=this.buildScrollpad() +this.surfaceContainer=scrollpad.container +layoutElements.bodyContainer.appendChild(scrollpad.scrollpad) +$(scrollpad.scrollpad).scrollpad()} +else{this.surfaceContainer=layoutElements.bodyContainer} +this.setInspectorVisibleFlag(true)} +InspectorContainer.prototype.buildHead=function(){var container=document.createElement('div'),header=document.createElement('h3'),paragraph=document.createElement('p'),detachButton=document.createElement('span'),closeButton=document.createElement('span') +container.setAttribute('class','inspector-header') +detachButton.setAttribute('class','oc-icon-external-link-square detach') +closeButton.setAttribute('class','close') +header.textContent=this.title +paragraph.textContent=this.description +closeButton.innerHTML='×';container.appendChild(header) +container.appendChild(paragraph) +container.appendChild(detachButton) +container.appendChild(closeButton) +return container} +InspectorContainer.prototype.buildScrollpad=function(){var scrollpad=document.createElement('div'),scrollWrapper=document.createElement('div'),scrollableContainer=document.createElement('div') +scrollpad.setAttribute('class','control-scrollpad') +scrollpad.setAttribute('data-control','scrollpad') +scrollWrapper.setAttribute('class','scroll-wrapper inspector-wrapper') +scrollpad.appendChild(scrollWrapper) +scrollWrapper.appendChild(scrollableContainer) +return{scrollpad:scrollpad,container:scrollableContainer}} +InspectorContainer.prototype.buildLayout=function(){var layout=document.createElement('div'),headRow=document.createElement('div'),bodyRow=document.createElement('div'),bodyCell=document.createElement('div'),layoutRelative=document.createElement('div') +layout.setAttribute('class','layout') +headRow.setAttribute('class','layout-row min-size') +bodyRow.setAttribute('class','layout-row') +bodyCell.setAttribute('class','layout-cell') +layoutRelative.setAttribute('class','layout-relative') +bodyCell.appendChild(layoutRelative) +bodyRow.appendChild(bodyCell) +layout.appendChild(headRow) +layout.appendChild(bodyRow) +this.options.container.get(0).appendChild(layout) +$.oc.foundation.controlUtils.markDisposable(layout) +this.registerLayoutHandlers(layout) +return{headContainer:headRow,bodyContainer:layoutRelative}} +InspectorContainer.prototype.validateAndApply=function(){if(!this.surface.validate()){return false} +this.applyValues() +return true} +InspectorContainer.prototype.isScrollable=function(){return this.options.container.data('inspector-scrollable')!==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)) +$layout.on('click','span.close',this.proxy(this.onClose)) +$layout.on('click','span.detach',this.proxy(this.onDetach))} +InspectorContainer.prototype.registerHandlers=function(){this.options.container.on('apply.oc.inspector',this.proxy(this.onApplyValues)) +this.options.container.on('beforeContainerHide.oc.inspector',this.proxy(this.onBeforeHide))} +InspectorContainer.prototype.unregisterHandlers=function(){var $layout=$(this.getLayout()) +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))} +InspectorContainer.prototype.removeControls=function(){if(this.isScrollable()){this.options.container.find('.control-scrollpad').scrollpad('dispose')} +var layout=this.getLayout() +layout.parentNode.removeChild(layout)} +InspectorContainer.prototype.onApplyValues=function(ev){if(!this.validateAndApply()){ev.preventDefault() +return false}} +InspectorContainer.prototype.onBeforeHide=function(ev){if(!this.triggerHiding()){ev.preventDefault() +return false}} +InspectorContainer.prototype.onClose=function(ev){if(!this.validateAndApply()){ev.preventDefault() +return false} +if(!this.triggerHiding()){ev.preventDefault() +return false} +this.surface.dispose() +this.dispose()} +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 +this.cachedGroupStatuses=null} +GroupManager.prototype.createGroup=function(groupId,parentGroup){var group=new Group(groupId) +if(parentGroup){parentGroup.groups.push(group) +group.parentGroup=parentGroup} +else{this.rootGroup=group} +return group} +GroupManager.prototype.getGroupIndex=function(group){return group.getGroupIndex()} +GroupManager.prototype.isParentGroupExpanded=function(group){if(!group.parentGroup){return true} +return this.isGroupExpanded(group.parentGroup)} +GroupManager.prototype.isGroupExpanded=function(group){if(!group.parentGroup){return true} +var groupIndex=this.getGroupIndex(group),statuses=this.readGroupStatuses() +if(statuses[groupIndex]!==undefined) +return statuses[groupIndex] +return false} +GroupManager.prototype.setGroupStatus=function(groupIndex,expanded){var statuses=this.readGroupStatuses() +statuses[groupIndex]=expanded +this.writeGroupStatuses(statuses)} +GroupManager.prototype.readGroupStatuses=function(){if(this.cachedGroupStatuses!==null){return this.cachedGroupStatuses} +var statuses=getInspectorGroupStatuses() +if(statuses[this.controlId]!==undefined){this.cachedGroupStatuses=statuses[this.controlId]} +else{this.cachedGroupStatuses={}} +return this.cachedGroupStatuses} +GroupManager.prototype.writeGroupStatuses=function(updatedStatuses){var statuses=getInspectorGroupStatuses() +statuses[this.controlId]=updatedStatuses +setInspectorGroupStatuses(statuses) +this.cachedGroupStatuses=updatedStatuses} +GroupManager.prototype.findGroupByIndex=function(index){return this.rootGroup.findGroupByIndex(index)} +GroupManager.prototype.findGroupRows=function(table,index,ignoreCollapsedSubgroups){var group=this.findGroupByIndex(index) +if(!group){throw new Error('Cannot find the requested row group.')} +return group.findGroupRows(table,ignoreCollapsedSubgroups,this)} +GroupManager.prototype.markGroupRowInvalid=function(group,table){var currentGroup=group +while(currentGroup){var row=currentGroup.findGroupRow(table) +if(row){$.oc.foundation.element.addClass(row,'invalid')} +currentGroup=currentGroup.parentGroup}} +GroupManager.prototype.unmarkInvalidGroups=function(table){var rows=table.querySelectorAll('tr.invalid') +for(var i=rows.length-1;i>=0;i--){$.oc.foundation.element.removeClass(rows[i],'invalid')}} +GroupManager.prototype.isRowVisible=function(table,rowGroupIndex){var group=this.findGroupByIndex(index) +if(!group){throw new Error('Cannot find the requested row group.')} +var current=group +while(current){if(!this.isGroupExpanded(current)){return false} +current=current.parentGroup} +return true} +function getInspectorGroupStatuses(){var statuses=document.body.getAttribute('data-inspector-group-statuses') +if(statuses!==null){return JSON.parse(statuses)} +return{}} +function setInspectorGroupStatuses(statuses){document.body.setAttribute('data-inspector-group-statuses',JSON.stringify(statuses))} +var Group=function(groupId){this.groupId=groupId +this.parentGroup=null +this.groupIndex=null +this.groups=[]} +Group.prototype.getGroupIndex=function(){if(this.groupIndex!==null){return this.groupIndex} +var result='',current=this +while(current){if(result.length>0){result=current.groupId+'-'+result} +else{result=String(current.groupId)} +current=current.parentGroup} +this.groupIndex=result +return result} +Group.prototype.findGroupByIndex=function(index){if(this.getGroupIndex()==index){return this} +for(var i=this.groups.length-1;i>=0;i--){var groupResult=this.groups[i].findGroupByIndex(index) +if(groupResult!==null){return groupResult}} +return null} +Group.prototype.getLevel=function(){var current=this,level=-1 +while(current){level++ +current=current.parentGroup} +return level} +Group.prototype.getGroupAndAllParents=function(){var current=this,result=[] +while(current){result.push(current) +current=current.parentGroup} +return result} +Group.prototype.findGroupRows=function(table,ignoreCollapsedSubgroups,groupManager){var groupIndex=this.getGroupIndex(),rows=table.querySelectorAll('tr[data-parent-group-index="'+groupIndex+'"]'),result=Array.prototype.slice.call(rows) +for(var i=0,len=this.groups.length;i \ + \ + \ + \ + '} +PopupBase.prototype.updateDisplayedValue=function(value){this.setLinkText(this.getLink(),value)} +PopupBase.prototype.registerHandlers=function(){var link=this.getLink(),$link=$(link) +link.addEventListener('click',this.proxy(this.onTriggerClick)) +$link.on('shown.oc.popup',this.proxy(this.onPopupShown)) +$link.on('hidden.oc.popup',this.proxy(this.onPopupHidden))} +PopupBase.prototype.unregisterHandlers=function(){var link=this.getLink(),$link=$(link) +link.removeEventListener('click',this.proxy(this.onTriggerClick)) +$link.off('shown.oc.popup',this.proxy(this.onPopupShown)) +$link.off('hidden.oc.popup',this.proxy(this.onPopupHidden))} +PopupBase.prototype.getLink=function(){return this.containerCell.querySelector('a.trigger')} +PopupBase.prototype.configurePopup=function(popup){} +PopupBase.prototype.handleSubmit=function($form){} +PopupBase.prototype.hidePopup=function(){$(this.getLink()).popup('hide')} +PopupBase.prototype.onTriggerClick=function(ev){$.oc.foundation.event.stop(ev) +var content=this.getPopupContent() +content=content.replace('{{property}}',this.propertyDefinition.title) +$(ev.target).popup({content:content}) +return false} +PopupBase.prototype.onPopupShown=function(ev,link,popup){$(popup).on('submit.inspector','form',this.proxy(this.onSubmit)) +this.popup=popup.get(0) +this.configurePopup(popup) +this.getRootSurface().popupDisplayed()} +PopupBase.prototype.onPopupHidden=function(ev,link,popup){$(popup).off('.inspector','form',this.proxy(this.onSubmit)) +this.popup=null +this.getRootSurface().popupHidden()} +PopupBase.prototype.onSubmit=function(ev){ev.preventDefault() +if(this.handleSubmit($(ev.target))===false){return false} +this.setLinkText(this.getLink()) +this.hidePopup() +return false} +$.oc.inspector.propertyEditors.popupBase=PopupBase}(window.jQuery);+function($){"use strict";var Base=$.oc.inspector.propertyEditors.popupBase,BaseProto=Base.prototype +var TextEditor=function(inspector,propertyDefinition,containerCell,group){Base.call(this,inspector,propertyDefinition,containerCell,group)} +TextEditor.prototype=Object.create(BaseProto) +TextEditor.prototype.constructor=Base +TextEditor.prototype.setLinkText=function(link,value){var value=value!==undefined?value:this.inspector.getPropertyValue(this.propertyDefinition.property) +if(value===undefined){value=this.propertyDefinition.default} +if(!value){value=this.propertyDefinition.placeholder +$.oc.foundation.element.addClass(link,'placeholder')} +else{$.oc.foundation.element.removeClass(link,'placeholder')} +if(typeof value==='string'){value=value.replace(/(?:\r\n|\r|\n)/g,' ');value=$.trim(value) +value=value.substring(0,300);} +link.textContent=value} +TextEditor.prototype.getPopupContent=function(){return'
\ + \ +