diff --git a/modules/backend/assets/css/october.css b/modules/backend/assets/css/october.css index 7b3266f31..a260bf377 100644 --- a/modules/backend/assets/css/october.css +++ b/modules/backend/assets/css/october.css @@ -13618,6 +13618,71 @@ html.cssanimations .fancy-layout .form-tabless-fields .loading-indicator-contain .inspector-fields td select { width: 90%; } +.inspector-fields td div.external-param-editor-container { + position: relative; + padding-right: 30px; +} +.inspector-fields td div.external-param-editor-container div.external-editor { + bottom: 0; + margin: -5px -12px; + right: 30px; + left: auto; + top: 0; + position: absolute; + -webkit-transition: left 0.2s; + transition: left 0.2s; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + will-change: transform; +} +.inspector-fields td div.external-param-editor-container div.external-editor div.controls { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; +} +.inspector-fields td div.external-param-editor-container div.external-editor div.controls a { + position: absolute; + left: 0; + top: 0; + display: inline-block; + height: 100%; + width: 30px; + color: #2b3e50; + outline: none; +} +.inspector-fields td div.external-param-editor-container div.external-editor div.controls a i { + display: inline-block; + position: relative; + left: 10px; + top: 4px; + font-size: 15px; +} +.inspector-fields td div.external-param-editor-container div.external-editor div.controls input { + position: absolute; + display: block; + border: none; + width: 100%; + height: 100%; + left: 0; + top: 0; + padding-left: 30px; + padding-right: 12px; + background: transparent; +} +.inspector-fields td div.external-param-editor-container.editor-visible div.external-editor div.controls input { + background: #f2f2f2; +} +.inspector-fields td.active div.external-param-editor-container div.external-editor div.controls input { + background: white; +} +.inspector-fields td.dropdown div.external-param-editor-container div.external-editor { + height: 100%; + margin: 0; + bottom: auto; +} .inspector-fields th { font-weight: 500; } diff --git a/modules/backend/assets/js/october.inspector.js b/modules/backend/assets/js/october.inspector.js index a4baa7f33..2b5ed0382 100644 --- a/modules/backend/assets/js/october.inspector.js +++ b/modules/backend/assets/js/october.inspector.js @@ -29,6 +29,7 @@ * - placeholder - placholder text, for text and dropdown properties * - depends - a list of properties the property depend on, for dropdown lists * - options - an option list for dropdown lists, optional. If not provided the options are loaded with AJAX. + * - noExternalParameter - disables the external parameter feature for the property. * Example of the configuration string (a single property): * [{"property":"max-width","title":"Max width","type":"string"}] * @@ -36,6 +37,10 @@ * The inspector uses this field to read and write field values. The field value is a JSON string, an object with keys matching property * names and values matching property values. * + * Any HTML element that wraps the inspectable element can have the data-inspector-external-parameters property that enables the external + * parameters support. External parameters saved with the special syntax {{paramName}}. The external parameter feature can be disabled + * on per-property basis with the noExternalParameter option. + * * Events * - change - the event is triggered on the inspectable element when it's properties are updated. * - showing.oc.inspector - triggered before the Inspector is displayed. Allows to cancel the action with e.preventDefault() @@ -96,10 +101,10 @@ data-dismiss="popover" \ aria-hidden="true">× \ \ -
\ + \ \ {{#properties}} \ - \ ', data) + return Mustache.render('', data) } InspectorEditorString.prototype.validate = function() { @@ -525,6 +725,7 @@ InspectorEditorString.prototype.focus = function() { $(this.selector).focus() + $(this.selector).closest('td').scrollLeft(0) } $.oc.inspector.editors.inspectorEditorString = InspectorEditorString; @@ -550,14 +751,8 @@ } InspectorEditorCheckbox.prototype.renderEditor = function() { - var isChecked = this.inspector.readProperty(this.fieldDef.property) - - if (isChecked == '0' || isChecked == 'false') - isChecked = false - var data = { id: this.editorId, - checked: isChecked ? 'checked' : null, cbId: this.editorId + '-cb', title: this.fieldDef.title } @@ -565,6 +760,15 @@ return Mustache.render(this.getTemplate(), data) } + InspectorEditorCheckbox.prototype.init = function() { + var isChecked = this.inspector.readProperty(this.fieldDef.property) + + if (isChecked == '0' || isChecked == 'false') + isChecked = false + + $(this.selector).prop(checked, isChecked) + } + InspectorEditorCheckbox.prototype.focus = function() { $(this.selector).closest('div').focus() } @@ -576,7 +780,7 @@ custom-checkbox nolabel"> \ \ + id="{{cbId}}"/> \ \ \ \ @@ -594,6 +798,7 @@ this.editorId = editorId this.selector = '#'+this.editorId+' select' this.dynamicOptions = this.fieldDef.options ? false : true + this.initialization = false var self = this @@ -603,7 +808,7 @@ } InspectorEditorDropdown.prototype.applyValue = function() { - this.inspector.writeProperty(this.fieldDef.property, $(this.selector).val()) + this.inspector.writeProperty(this.fieldDef.property, $(this.selector).val(), this.initialization) } InspectorEditorDropdown.prototype.renderEditor = function() { @@ -678,7 +883,7 @@ this.indicatorContainer.addClass('loading-indicator-container').addClass('size-small').addClass('transparent') } - this.loadOptions() + this.loadOptions(true) } if (this.fieldDef.depends) @@ -721,7 +926,7 @@ this.indicatorContainer.loadIndicator('hide') } - InspectorEditorDropdown.prototype.loadOptions = function() { + InspectorEditorDropdown.prototype.loadOptions = function(initialization) { var $form = $(this.selector).closest('form'), data = this.inspector.propertyValues, $select = $(this.selector), @@ -755,7 +960,9 @@ else $('option:first-child', $select).attr("selected", "selected"); + self.initialization = initialization $select.trigger('change') + self.initialization = false self.hideLoadingIndicator() }, diff --git a/modules/backend/assets/less/controls/inspector.less b/modules/backend/assets/less/controls/inspector.less index 2a2b94622..15cea3c08 100644 --- a/modules/backend/assets/less/controls/inspector.less +++ b/modules/backend/assets/less/controls/inspector.less @@ -90,6 +90,92 @@ select { width: 90%; } + + div.external-param-editor-container { + position: relative; + padding-right: 30px; + + div.external-editor { + bottom: 0; + margin: -5px -12px; + right: 30px; + left: auto; + top: 0; + position: absolute; + + .transition(left 0.2s); + .transform( ~'translateZ(0)'); + will-change: transform; + + div.controls { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + + a { + position: absolute; + left: 0; + top: 0; + display: inline-block; + height: 100%; + width: 30px; + color: #2b3e50; + outline: none; + + i { + display: inline-block; + position: relative; + left: 10px; + top: 4px; + font-size: 15px; + } + } + + input { + position: absolute; + display: block; + border: none; + width: 100%; + height: 100%; + left: 0; + top: 0; + padding-left: 30px; + padding-right: 12px; + background: transparent; + } + } + } + + &.editor-visible { + div.external-editor { + div.controls { + input { + background: @color-inspector-bg; + } + } + } + } + } + + &.active { + div.external-param-editor-container { + div.external-editor { + div.controls { + input { + background: white; + } + } + } + } + } + + &.dropdown div.external-param-editor-container div.external-editor { + height: 100%; + margin: 0; + bottom: auto; + } } th { diff --git a/modules/cms/assets/js/october.cmspage.js b/modules/cms/assets/js/october.cmspage.js index 2a12c3f76..43bd96ef4 100644 --- a/modules/cms/assets/js/october.cmspage.js +++ b/modules/cms/assets/js/october.cmspage.js @@ -580,7 +580,7 @@ var $componentList = $('#cms-master-tabs > div.tab-content > .tab-pane.active .control-componentlist .layout') if ($componentList.length == 0) { - alert('Components can be added only to pages and layouts.') + alert('Components can be added only to pages, partials and layouts.') return; } diff --git a/modules/cms/classes/ComponentBase.php b/modules/cms/classes/ComponentBase.php index 67e3a705b..b6a6be477 100644 --- a/modules/cms/classes/ComponentBase.php +++ b/modules/cms/classes/ComponentBase.php @@ -183,36 +183,4 @@ abstract class ComponentBase extends Extendable return $value; } - - /** - * Creates a page link to another page. Allows mapping to the other page's - * component properties for the purpose of extracting URL routing parameters. - * @param string $page Page name or page file name - * @param string $class Component class name - * @param array $mappings ['componentProperty' => 'routed value'] - * @return string - */ - // protected function makePageLink($page, $class, $mappings = []) - // { - // if (!isset($this->pageLinkCache[$page.$class])) { - // $this->pageLinkCache[$page.$class] = $this->getOtherPageComponent($page, $class); - // } - - // if (!$component = $this->pageLinkCache[$page.$class]) - // return null; - - // $params = []; - // foreach ($mappings as $property => $value) { - - // if (!$param = $component->property($property)) - // continue; - - // if (substr($param, 0, 1) == ':') - // $param = substr($param, 1); - - // $params[$param] = $value; - // } - - // return $this->pageUrl($page, $params); - // } } diff --git a/modules/cms/classes/ComponentHelpers.php b/modules/cms/classes/ComponentHelpers.php index 101eca678..b65e4c95e 100644 --- a/modules/cms/classes/ComponentHelpers.php +++ b/modules/cms/classes/ComponentHelpers.php @@ -20,12 +20,13 @@ class ComponentHelpers $result = []; $property = [ - 'property' => 'oc.alias', - 'title' => Lang::get('cms::lang.component.alias'), - 'description' => Lang::get('cms::lang.component.alias_description'), - 'type' => 'string', - 'validationPattern' => '^[a-zA-Z]+[0-9a-z\_]*$', - 'validationMessage' => Lang::get('cms::lang.component.validation_message') + 'property' => 'oc.alias', + 'title' => Lang::get('cms::lang.component.alias'), + 'description' => Lang::get('cms::lang.component.alias_description'), + 'type' => 'string', + 'validationPattern' => '^[a-zA-Z]+[0-9a-z\_]*$', + 'validationMessage' => Lang::get('cms::lang.component.validation_message'), + 'noExternalParameter' => true ]; $result[] = $property; diff --git a/modules/cms/classes/Controller.php b/modules/cms/classes/Controller.php index a1246fdd1..907382369 100644 --- a/modules/cms/classes/Controller.php +++ b/modules/cms/classes/Controller.php @@ -100,6 +100,8 @@ class Controller extends BaseController protected static $instance = null; + protected $partialComponentStack = []; + /** * Creates the controller. * @param \Cms\Classes\Theme $theme Specifies the CMS theme. @@ -391,6 +393,8 @@ class Controller extends BaseController { $manager = ComponentManager::instance(); + $properties = $this->setComponentPropertiesFromParameters($properties, []); + if ($addToLayout) { if (!$componentObj = $manager->makeComponent($name, $this->layoutObj, $properties)) { throw new CmsException(Lang::get('cms::lang.component.not_found', ['name'=>$name])); @@ -664,6 +668,8 @@ class Controller extends BaseController */ public function renderPartial($name, $parameters = [], $throwException = true) { + $vars = $this->vars; + /* * Alias @ symbol for :: */ @@ -748,12 +754,63 @@ class Controller extends BaseController } } + /* + * Run partial functions (only for real partials) + */ + + if ($partial instanceof \Cms\Classes\Partial) { + $manager = ComponentManager::instance(); + + foreach ($partial->settings['components'] as $component => $properties) { + list($name, $alias) = strpos($component, ' ') ? + explode(' ', $component) : array($component, $component); + + $properties = $this->setComponentPropertiesFromParameters($properties, $parameters, []); + + if (!$componentObj = $manager->makeComponent($name, $this->pageObj, $properties)) + throw new CmsException(Lang::get('cms::lang.component.not_found', ['name'=>$name])); + + $componentObj->alias = $alias; + $parameters[$alias] = $partial->components[$alias] = $componentObj; + + array_push($this->partialComponentStack, [ + 'name' => $alias, + 'obj' => $componentObj + ]); + + $componentObj->init(); + $componentObj->onInit(); // Deprecated: Remove ithis line if year >= 2015 + } + + CmsException::mask($this->page, 300); + $parser = new CodeParser($partial); + $partialObj = $parser->source($this->page, $this->layout, $this); + CmsException::unmask(); + + CmsException::mask($partial, 300); + $partialObj->onStart(); + $partial->runComponents(); + $partialObj->onEnd(); + CmsException::unmask(); + } + + /* + * Render the parital + */ CmsException::mask($partial, 400); $this->loader->setObject($partial); $template = $this->twig->loadTemplate($partial->getFullPath()); - $result = $template->render(array_merge($this->vars, $parameters)); - CmsException::unmask(); + $result = $template->render(array_merge($this->vars, $parameters)); + CmsException::unmask($this->partialComponentStack); + + if ($partial instanceof \Cms\Classes\Partial) { + if ($this->partialComponentStack) { + array_pop($this->partialComponentStack); + } + } + + $this->vars = $vars; $this->componentContext = null; return $result; } @@ -961,6 +1018,11 @@ class Controller extends BaseController return $this->layout->components[$name]; } + foreach ($this->partialComponentStack as $componentInfo) { + if ($componentInfo['name'] == $name) + return $componentInfo['obj']; + } + return null; } @@ -1017,50 +1079,32 @@ class Controller extends BaseController } /** - * Creates a basic component object for another page, useful for extracting properties. - * @param string $page Page name or page file name - * @param string $class Component class name - * @return ComponentBase + * Sets component property values from partial parameters. + * The property values should be defined as {{ param }}. + * @param array &$properties Specifies the component properties loaded from the partial. + * @param array $parameters Specifies the partial parameters. + * @return Returns updated properties. */ - // public function getOtherPageComponent($page, $class) - // { - // $class = Str::normalizeClassName($class); - // $theme = $this->getTheme(); - // $manager = ComponentManager::instance(); - // $componentObj = new $class; + protected function setComponentPropertiesFromParameters(&$properties, $parameters) + { + $result = []; - // if (($page = Page::loadCached($theme, $page)) && isset($page->settings['components'])) { - // foreach ($page->settings['components'] as $component => $properties) { - // list($name, $alias) = strpos($component, ' ') ? - // explode(' ', $component) : - // array($component, $component) - // ; - // if ($manager->resolve($name) == $class) { - // $componentObj->setProperties($properties); - // $componentObj->alias = $alias; - // return $componentObj; - // } - // } + $routerParameters = $this->router->getParameters(); - // if (!isset($page->settings['layout'])) - // return null; + foreach ($properties as $propertyName=>$propertyValue) { + $matches = []; + if (preg_match('/^\{\{([^\}]+)\}\}$/', $propertyValue, $matches)) { + $paramName = trim($matches[1]); - // $layout = $page->settings['layout']; - // if (($layout = Layout::loadCached($theme, $layout)) && isset($layout->settings['components'])) { - // foreach ($layout->settings['components'] as $component => $properties) { - // list($name, $alias) = strpos($component, ' ') ? - // explode(' ', $component) : - // array($component, $component) - // ; - // if ($manager->resolve($name) == $class) { - // $componentObj->setProperties($properties); - // $componentObj->alias = $alias; - // return $componentObj; - // } - // } - // } - // } + if ( substr($paramName, 0, 1) == ':' ) { + $paramName = substr($paramName, 1); + $result[$propertyName] = array_key_exists($paramName, $routerParameters) ? $routerParameters[$paramName] : null; + } else + $result[$propertyName] = array_key_exists($paramName, $parameters) ? $parameters[$paramName] : null; + } else + $result[$propertyName] = $propertyValue; + } - // return null; - // } + return $result; + } } diff --git a/modules/cms/classes/Partial.php b/modules/cms/classes/Partial.php index 55549266f..690319e60 100644 --- a/modules/cms/classes/Partial.php +++ b/modules/cms/classes/Partial.php @@ -17,4 +17,13 @@ class Partial extends CmsCompoundObject { return 'partials'; } + + /** + * Returns name of a PHP class to us a parent for the PHP class created for the object's PHP section. + * @return mixed Returns the class name or null. + */ + public function getCodeClassParent() + { + return '\Cms\Classes\PartialCode'; + } } diff --git a/modules/cms/classes/PartialCode.php b/modules/cms/classes/PartialCode.php new file mode 100644 index 000000000..4f125efd1 --- /dev/null +++ b/modules/cms/classes/PartialCode.php @@ -0,0 +1,11 @@ +addJs('/modules/cms/assets/js/october.cmspage.js', 'core'); $this->addJs('/modules/cms/assets/js/october.dragcomponents.js', 'core'); $this->addJs('/modules/cms/assets/js/october.tokenexpander.js', 'core'); + $this->addJs('/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js', 'core'); + $this->addCss('/modules/cms/assets/css/october.components.css', 'core'); // Preload Ace editor modes explicitly, because they could be changed dynamically diff --git a/modules/cms/controllers/index/_form_page.htm b/modules/cms/controllers/index/_form_page.htm index b326b632d..07cad3fd1 100644 --- a/modules/cms/controllers/index/_form_page.htm +++ b/modules/cms/controllers/index/_form_page.htm @@ -1,8 +1,12 @@ - 'layout', - 'data-change-monitor' => 'true', - 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')) -]) ?> + 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => e(trans('backend::lang.form.confirm_tab_close')), + 'data-inspector-external-parameters' => true + ]; + +echo Form::open($formConfig) ?> render() ?>
\ @@ -156,6 +161,9 @@ if (this.itemType == 'property' && this.groupIndex !== undefined) result += self.groupExpanded(this.group) ? ' expanded' : ' collapsed' + if (this.itemType == 'property' && this.noExternalParameter) + result += ' no-external-parameter' + return result } }, @@ -211,7 +219,7 @@ width: 400 }) - self.$el.on('hiding.oc.popover', function(e){self.onBeforeHide(e)}) + self.$el.on('hiding.oc.popover', function(e){return self.onBeforeHide(e)}) self.$el.on('hide.oc.popover', function(){self.cleanup()}) self.$el.addClass('inspector-open') @@ -225,12 +233,15 @@ self.editors[0].focus() } + if (self.$el.closest('[data-inspector-external-parameters]').length > 0) + self.initExternalParameterEditor(self.$el.data('oc.popover').$container) + $.each(self.editors, function(){ if (this.init !== undefined) this.init() }) - $('[data-toggle=tooltip]', self.$el.data('oc.popover').$container).tooltip({placement: 'auto right', container: 'body'}) + $('[data-toggle=tooltip]', self.$el.data('oc.popover').$container).tooltip({placement: 'auto right', container: 'body', delay: 500}) var $container = self.$el.data('oc.popover').$container $container.on('click', 'tr.group', function(){ @@ -248,6 +259,145 @@ displayPopover() } + /* + * Initializes the external parameter editors for properties that support this feature. + */ + Inspector.prototype.initExternalParameterEditor = function($container) { + var self = this + + $('table.inspector-fields tr', $container).each(function(){ + if (!$(this).hasClass('no-external-parameter')) { + var property = $(this).data('property'), + $td = $('td', this), + $editorContainer = $('
'), + $editor = $( + '
\ +
\ + \ + \ + \ + \ +
\ +
') + + $editorContainer.append($td.children()) + $editorContainer.append($editor) + $td.append($editorContainer) + + var $editorLink = $('a', $editor) + + $editorLink.click(function() { + return self.toggleExternalParameterEditor($(this)) + }) + .attr('title', 'Click to enter the external parameter name to load the property value from') + .tooltip({'container': 'body', delay: 500}) + + var $input = $editor.find('input'), + propertyValue = self.propertyValues[property] + + $input.on('focus', function(){ + var $field = $(this) + + $('td', $field.closest('table')).removeClass('active') + $field.closest('td').addClass('active') + }) + + $input.on('change', function(){ + self.markPropertyChanged(property, true) + }) + + var matches = [] + if (matches = propertyValue.match(/^\{\{([^\}]+)\}\}$/)) { + var value = $.trim(matches[1]) + + if (value.length > 0) { + self.showExternalParameterEditor($editorContainer, $editor, $editorLink, $td, true) + $editor.find('input').val(value) + self.writeProperty(property, null, true) + } + } + } + }) + } + + Inspector.prototype.showExternalParameterEditor = function($container, $editor, $editorLink, $cell, noAnimation) { + var position = $editor.position() + $('input', $editor).focus() + + if (!noAnimation) { + $editor.css({ + 'left': position.left + 'px', + 'right': 0 + }) + } else + $editor.css('right', 0) + + setTimeout(function(){ + $editor.css('left', 0) + $cell.scrollTop(0) + }, 0) + + $container.addClass('editor-visible') + $editorLink.attr('data-original-title', 'Click to enter the property value') + this.toggleCellEditorVisibility($cell, false) + $editor.find('input').attr('tabindex', 0) + } + + Inspector.prototype.toggleExternalParameterEditor = function($editorLink) { + var $container = $editorLink.closest('.external-param-editor-container'), + $editor = $('.external-editor', $container), + $cell = $editorLink.closest('td'), + self = this + + $editorLink.tooltip('hide') + + if (!$container.hasClass('editor-visible')) { + self.showExternalParameterEditor($container, $editor, $editorLink, $cell) + } else { + var left = $container.width() + + $editor.css('left', left + 'px') + setTimeout(function(){ + $editor.css({ + 'left': 'auto', + 'right': '30px' + }) + $container.removeClass('editor-visible') + $container.closest('td').removeClass('active') + }, 200) + $editorLink.attr('data-original-title', 'Click to enter the external parameter name to load the property value from') + $editor.find('input').attr('tabindex', -1) + self.toggleCellEditorVisibility($cell, true) + } + + return false + } + + Inspector.prototype.toggleCellEditorVisibility = function($cell, show) { + var $container = $('.external-param-editor-container', $cell) + + $container.children().each(function(){ + var $el = $(this) + + if ($el.hasClass('external-editor')) + return + + if (show) + $el.removeClass('hide') + else { + var height = $cell.data('inspector-cell-height') + + if (!height) { + height = $cell.height() + $cell.data('inspector-cell-height', height) + } + + $container.css('height', height + 'px') + $el.addClass('hide') + } + }) + } + /* * Creates group nodes in the property set */ @@ -379,17 +529,22 @@ return null } - Inspector.prototype.writeProperty = function(property, value) { + Inspector.prototype.writeProperty = function(property, value, noChangedStatusUpdate) { this.propertyValues[property] = value this.propertyValuesField.val(JSON.stringify(this.propertyValues)) if (this.originalPropertyValues[property] === undefined || this.originalPropertyValues[property] != value) { - this.$el.trigger('change') - this.markPropertyChanged(property, true) - } else - this.markPropertyChanged(property, false) + if (!noChangedStatusUpdate) { + this.$el.trigger('change') + this.markPropertyChanged(property, true) + } + } else { + if (!noChangedStatusUpdate) + this.markPropertyChanged(property, false) + } - this.$el.trigger('propertyChanged.oc.Inspector', [property]) + if (!noChangedStatusUpdate) + this.$el.trigger('propertyChanged.oc.Inspector', [property]) return value } @@ -412,6 +567,7 @@ var editor = new $.oc.inspector.editors[editorClass](editorId, this, data) this.editors.push(editor) + editor.inspectorCellId = editorId return editor.renderEditor() } @@ -429,11 +585,40 @@ } Inspector.prototype.onBeforeHide = function(e) { + var $container = this.$el.data('inspector-container'), + externalParamErrorFound = false, + self = this + $.each(this.editors, function() { - this.applyValue() + if (!self.editorExternalPropertyEnabled(this)) + this.applyValue() + else { + var $cell = $('#'+this.inspectorCellId, $container), + $extPropEditorContainer = $cell.find('.external-param-editor-container'), + $input = $extPropEditorContainer.find('.external-editor input'), + val = $.trim($input.val()) + + if (val.length == 0) { + alert('Please enter external parameter name for the '+this.fieldDef.title+' property.') + externalParamErrorFound = true + setTimeout(function(){ + $input.focus() + }, 0) + return false + } + + self.writeProperty(this.fieldDef.property, '{{ '+val+' }}') + } }) - var eH = $.Event('hiding.oc.inspector') + if (externalParamErrorFound) { + e.preventDefault() + return false + } + + var eH = $.Event('hiding.oc.inspector'), + ispector = this + this.$el.trigger(eH, [{values: this.propertyValues}]) if (eH.isDefaultPrevented()) { e.preventDefault() @@ -441,6 +626,9 @@ } $.each(this.editors, function() { + if (ispector.editorExternalPropertyEnabled(this)) + return true + if (this.validate === undefined) return true @@ -458,10 +646,17 @@ return false }) - var $contianer = this.$el.data('inspector-container') $('[data-toggle=tooltip]', this.$el.data('oc.popover').$container).tooltip('hide') } + Inspector.prototype.editorExternalPropertyEnabled = function(editor) { + var $container = this.$el.data('inspector-container'), + $cell = $('#'+editor.inspectorCellId, $container), + $extPropEditorContainer = $cell.find('.external-param-editor-container') + + return $extPropEditorContainer.hasClass('editor-visible') + } + // // EDITOR DEFINITIONS // ================== @@ -474,6 +669,7 @@ * - validate(), optional, validates the value and returns the validation error message * - applyValue(), applies the editor value * - focus(), focuses the editor input element, if applicable + * - init(), sets the initial editor value */ // STRING EDITOR @@ -483,7 +679,7 @@ this.inspector = inspector this.fieldDef = fieldDef this.editorId = editorId - this.selector = '#'+this.editorId+' input' + this.selector = '#'+this.editorId+' input.string-editor' var self = this $(document).on('focus', this.selector, function() { @@ -498,6 +694,11 @@ }) } + InspectorEditorString.prototype.init = function() { + var value = $.trim(this.inspector.readProperty(this.fieldDef.property)) + $(this.selector).val(value) + } + InspectorEditorString.prototype.applyValue = function() { this.inspector.writeProperty(this.fieldDef.property, $.trim($(this.selector).val())) } @@ -505,11 +706,10 @@ InspectorEditorString.prototype.renderEditor = function() { var data = { id: this.editorId, - value: $.trim(this.inspector.readProperty(this.fieldDef.property)), placeholder: this.fieldDef.placeholder !== undefined ? this.fieldDef.placeholder : '' } - return Mustache.render('