diff --git a/modules/system/assets/ui/js/inspector.editor.dropdown.js b/modules/system/assets/ui/js/inspector.editor.dropdown.js index e31f4bac1..98ee023ea 100644 --- a/modules/system/assets/ui/js/inspector.editor.dropdown.js +++ b/modules/system/assets/ui/js/inspector.editor.dropdown.js @@ -235,7 +235,7 @@ $form.request('onInspectableGetOptions', { data: data, - }).done(function optionsRequestDoneClosure(data) { + }).done(function dropdownOptionsRequestDoneClosure(data) { self.optionsRequestDone(data, currentValue, true) }).always( this.proxy(this.hideLoadingIndicator) diff --git a/modules/system/assets/ui/js/inspector.editor.objectlist.js b/modules/system/assets/ui/js/inspector.editor.objectlist.js new file mode 100644 index 000000000..12e5386c5 --- /dev/null +++ b/modules/system/assets/ui/js/inspector.editor.objectlist.js @@ -0,0 +1,503 @@ +/* + * Inspector object list editor class. + */ ++function ($) { "use strict"; + + var Base = $.oc.inspector.propertyEditors.base, + BaseProto = Base.prototype + + var ObjectListEditor = function(inspector, propertyDefinition, containerCell) { + this.currentRowInspector = null + this.popup = null + + if (propertyDefinition.titleProperty === undefined) { + throw new Error('The titleProperty property should be specified in the objectList editor configuration. Property: ' + propertyDefinition.property) + } + + if (propertyDefinition.itemProperties === undefined) { + throw new Error('The itemProperties property should be specified in the objectList editor configuration. Property: ' + propertyDefinition.property) + } + + Base.call(this, inspector, propertyDefinition, containerCell) + } + + ObjectListEditor.prototype = Object.create(BaseProto) + ObjectListEditor.prototype.constructor = Base + + ObjectListEditor.prototype.dispose = function() { + this.unregisterHandlers() + this.removeControls() + + this.currentRowInspector = null + this.popup = null + + BaseProto.dispose.call(this) + } + + // + // Building + // + + ObjectListEditor.prototype.build = function() { + var link = document.createElement('a') + + $.oc.foundation.element.addClass(link, 'trigger') + link.setAttribute('href', '#') + this.setLinkText(link) + + $.oc.foundation.element.addClass(this.containerCell, 'trigger-cell') + + this.containerCell.appendChild(link) + } + + ObjectListEditor.prototype.setLinkText = function(link, value) { + var value = value !== undefined ? value + : this.inspector.getPropertyValue(this.propertyDefinition.property) + + if (value === undefined) { + var placeholder = this.propertyDefinition.placeholder + + if (placeholder !== undefined) { + $.oc.foundation.element.addClass(link, 'placeholder') + link.textContent = placeholder + } + else { + link.textContent = 'Items: 0' + } + } + else { + if (value.length === undefined) { + throw new Error('Object list value an array. Property: ' + this.propertyDefinition.property) + } + + $.oc.foundation.element.removeClass(link, 'placeholder') + link.textContent = 'Items: ' + value.length + } + } + + ObjectListEditor.prototype.getPopupContent = function() { + return '
' + } + + ObjectListEditor.prototype.buildPopupContents = function(popup) { + this.buildItemsTable(popup) + } + + ObjectListEditor.prototype.buildItemsTable = function(popup) { + var table = popup.querySelector('table'), + tbody = document.createElement('tbody'), + items = this.inspector.getPropertyValue(this.propertyDefinition.property), + titleProperty = this.propertyDefinition.titleProperty + + if (items === undefined || items.length === 0) { + var row = this.buildEmptyRow() + + tbody.appendChild(row) + } + else { + var firstRow = undefined + + for (var i = 0, len = items.length; i < len; i++) { + var item = items[i], + itemText = item[titleProperty], + row = this.buildTableRow(itemText, 'rowlink') + + row.setAttribute('data-inspector-values', JSON.stringify(item)) + tbody.appendChild(row) + + if (firstRow === undefined) { + firstRow = row + } + } + } + + table.appendChild(tbody) + + if (firstRow !== undefined) { + this.selectRow(firstRow) + } + + this.updateScrollpads() + } + + ObjectListEditor.prototype.buildEmptyRow = function() { + return this.buildTableRow('No items found', 'no-data', 'nolink') + } + + ObjectListEditor.prototype.removeEmptyRow = function() { + var tbody = this.getTableBody(), + row = tbody.querySelector('tr.no-data') + + if (row) { + tbody.removeChild(row) + } + } + + ObjectListEditor.prototype.buildTableRow = function(text, rowClass, cellClass) { + var row = document.createElement('tr'), + cell = document.createElement('td') + + cell.textContent = text + + if (rowClass !== undefined) { + $.oc.foundation.element.addClass(row, rowClass) + } + + if (cellClass !== undefined) { + $.oc.foundation.element.addClass(cell, cellClass) + } + + row.appendChild(cell) + return row + } + + ObjectListEditor.prototype.updateScrollpads = function() { + $('.control-scrollpad', this.popup).scrollpad('update') + } + + // + // Built-in Inspector management + // + + ObjectListEditor.prototype.selectRow = function(row) { + var tbody = row.parentNode, + inspectorContainer = this.getInspectorContainer(), + selectedRow = this.getSelectedRow() + + if (selectedRow) { +// TODO: validation of the currently existing Inspector is required + this.applyDataToRow(selectedRow) + $.oc.foundation.element.removeClass(selectedRow, 'active') + } + + this.disposeInspector() + + $.oc.foundation.element.addClass(row, 'active') + + this.createInspectorForRow(row, inspectorContainer) + } + + ObjectListEditor.prototype.createInspectorForRow = function(row, inspectorContainer) { + var dataStr = row.getAttribute('data-inspector-values') + + if (dataStr === undefined || typeof dataStr !== 'string') { + throw new Error('Values not found for the selected row.') + } + + var properties = this.propertyDefinition.itemProperties, + values = $.parseJSON(dataStr), + options = { + enableExternalParameterEditor: false, + onChange: this.proxy(this.onInspectorDataChange) + } + + this.currentRowInspector = new $.oc.inspector.surface(inspectorContainer, properties, values, + $.oc.inspector.helpers.generateElementUniqueId(inspectorContainer), options) + } + + ObjectListEditor.prototype.disposeInspector = function() { + $.oc.foundation.controlUtils.disposeControls(this.popup) + this.currentRowInspector = null + } + + ObjectListEditor.prototype.applyDataToRow = function(row) { + if (this.currentRowInspector === null) { + return + } + + var data = this.currentRowInspector.getValues() + row.setAttribute('data-inspector-values', JSON.stringify(data)) + } + + ObjectListEditor.prototype.updateRowText = function(property, value) { + var selectedRow = this.getSelectedRow() + + if (!selectedRow) { + throw new Exception('A row is not found for the updated data') + } + + if (property !== this.propertyDefinition.titleProperty) { + return + } + + selectedRow.firstChild.textContent = value + } + + ObjectListEditor.prototype.getSelectedRow = function() { + if (!this.popup) { + throw new Error('Trying to get selected row without a popup reference.') + } + + var rows = this.getTableBody().children + + for (var i = 0, len = rows.length; i < len; i++) { + if ($.oc.foundation.element.hasClass(rows[i], 'active')) { + return rows[i] + } + } + + return null + } + + ObjectListEditor.prototype.createItem = function() { + var selectedRow = this.getSelectedRow() + + if (selectedRow) { +// TODO: validation of the currently existing Inspector is required + this.applyDataToRow(selectedRow) + $.oc.foundation.element.removeClass(selectedRow, 'active') + } + + this.disposeInspector() + + var title = 'New item', + row = this.buildTableRow(title, 'rowlink active'), + tbody = this.getTableBody(), + data = {} + + data[this.propertyDefinition.titleProperty] = title + + row.setAttribute('data-inspector-values', JSON.stringify(data)) + tbody.appendChild(row) + + this.selectRow(row) + + this.removeEmptyRow() + this.updateScrollpads() + } + + ObjectListEditor.prototype.deleteItem = function() { + var selectedRow = this.getSelectedRow() + + if (!selectedRow) { + return + } + + var nextRow = selectedRow.nextElementSibling, + prevRow = selectedRow.previousElementSibling, + tbody = this.getTableBody() + + this.disposeInspector() + tbody.removeChild(selectedRow) + + var newSelectedRow = nextRow ? nextRow : prevRow + + if (newSelectedRow) { + this.selectRow(newSelectedRow) + } else { + tbody.appendChild(this.buildEmptyRow()) + } + + this.updateScrollpads() + } + + ObjectListEditor.prototype.applyDataToParentInspector = function() { + var selectedRow = this.getSelectedRow(), + tbody = this.getTableBody(), + dataRows = tbody.querySelectorAll('tr[data-inspector-values]'), + link = this.getLink(), + result = [] + + if (selectedRow) { +// TODO: validation of the currently existing Inspector is required + this.applyDataToRow(selectedRow) + } + + for (var i = 0, len = dataRows.length; i < len; i++) { + var dataRow = dataRows[i] + + result.push($.parseJSON(dataRow.getAttribute('data-inspector-values'))) + } + + this.inspector.setPropertyValue(this.propertyDefinition.property, result) + this.setLinkText(link, result) + + $(link).popup('hide') + return false + } + + // + // Helpers + // + + ObjectListEditor.prototype.getLink = function() { + return this.containerCell.querySelector('a.trigger') + } + + ObjectListEditor.prototype.getPopupFormElement = function() { + var form = this.popup.querySelector('form') + + if (!form) { + throw new Error('Cannot find form element in the popup window.') + } + + return form + } + + ObjectListEditor.prototype.getInspectorContainer = function() { + return this.popup.querySelector('div[data-inspector-container]') + } + + ObjectListEditor.prototype.getTableBody = function() { + return this.popup.querySelector('table.inspector-table-list tbody') + } + + // + // Event handlers + // + + ObjectListEditor.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)) + } + + ObjectListEditor.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)) + } + + ObjectListEditor.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 + } + + ObjectListEditor.prototype.onPopupShown = function(ev, link, popup) { + $(popup).on('submit.inspector', 'form', this.proxy(this.onSubmit)) + $(popup).on('click', 'tr.rowlink', this.proxy(this.onRowClick)) + $(popup).on('click.inspector', '[data-cmd]', this.proxy(this.onCommand)) + + this.popup = popup.get(0) + + this.buildPopupContents(this.popup) + } + + ObjectListEditor.prototype.onPopupHidden = function(ev, link, popup) { + $(popup).off('.inspector', this.proxy(this.onSubmit)) + $(popup).off('click', 'tr.rowlink', this.proxy(this.onRowClick)) + $(popup).off('click.inspector', '[data-cmd]', this.proxy(this.onCommand)) + + this.disposeInspector() + this.popup = null + } + + ObjectListEditor.prototype.onSubmit = function(ev) { + this.applyDataToParentInspector() + + ev.preventDefault() + return false + } + + ObjectListEditor.prototype.onRowClick = function(ev) { + this.selectRow(ev.currentTarget) + } + + ObjectListEditor.prototype.onInspectorDataChange = function(property, value) { + this.updateRowText(property, value) + } + + ObjectListEditor.prototype.onCommand = function(ev) { + var command = ev.currentTarget.getAttribute('data-cmd') + + switch (command) { + case 'create-item' : + this.createItem() + break; + case 'delete-item' : + this.deleteItem() + break; + } + } + + // + // Disposing + // + + ObjectListEditor.prototype.removeControls = function() { + if (this.popup) { + this.disposeInspector(this.popup) + } + } + + $.oc.inspector.propertyEditors.objectList = ObjectListEditor +}(window.jQuery); \ No newline at end of file diff --git a/modules/system/assets/ui/js/inspector.editor.set.js b/modules/system/assets/ui/js/inspector.editor.set.js index 5cbf7939b..2cc8afb10 100644 --- a/modules/system/assets/ui/js/inspector.editor.set.js +++ b/modules/system/assets/ui/js/inspector.editor.set.js @@ -10,6 +10,7 @@ var SetEditor = function(inspector, propertyDefinition, containerCell) { this.editors = [] + this.loadedItems = null Base.call(this, inspector, propertyDefinition, containerCell) } @@ -19,6 +20,7 @@ SetEditor.prototype.dispose = function() { this.disposeEditors() + this.disposeControls() this.editors = null @@ -30,10 +32,6 @@ // SetEditor.prototype.build = function() { - if (!this.propertyDefinition.items) { - throw new Error('The items are not defined for the set-typed property "' + this.propertyDefinition.property + '"') - } - var link = document.createElement('a') $.oc.foundation.element.addClass(link, 'trigger') @@ -41,10 +39,19 @@ link.setAttribute('data-group-index', this.getGroupIndex()) this.setLinkText(link) - $.oc.foundation.element.addClass(this.containerCell, 'set') + $.oc.foundation.element.addClass(this.containerCell, 'trigger-cell') this.containerCell.appendChild(link) + if (this.propertyDefinition.items !== undefined) { + this.loadStaticItems() + } + else { + this.loadDynamicItems() + } + } + + SetEditor.prototype.loadStaticItems = function() { for (var itemValue in this.propertyDefinition.items) { this.buildItemEditor(itemValue, this.propertyDefinition.items[itemValue]) } @@ -52,14 +59,14 @@ SetEditor.prototype.setLinkText = function(link, value) { var value = value !== undefined ? value - : this.inspector.getPropertyValue(this.propertyDefinition.property), - text = '[]' + : this.getNormalizedValue(), + text = '[ ]' if (value === undefined) { value = this.propertyDefinition.default } - if (value !== undefined && value.length !== undefined && value.length > 0) { + if (value !== undefined && value.length !== undefined && value.length > 0 && typeof value !== 'string') { var textValues = [] for (var i = 0, len = value.length; i < len; i++) { textValues.push(this.valueToText(value[i])) @@ -108,7 +115,48 @@ return this.propertyDefinition.default.indexOf(value) > -1 } - + + // + // Dynamic items + // + + SetEditor.prototype.showLoadingIndicator = function() { + $(this.getLink()).loadIndicator() + } + + SetEditor.prototype.hideLoadingIndicator = function() { + $(this.getLink()).loadIndicator('hide') + } + + SetEditor.prototype.loadDynamicItems = function() { + var link = this.getLink(), + data = this.inspector.getValues(), + $form = $(link).closest('form') + + $.oc.foundation.element.addClass(link, 'loading-indicator-container size-small') + this.showLoadingIndicator() + + $form.request('onInspectableGetOptions', { + data: data, + }) + .done(this.proxy(this.itemsRequestDone)) + .always(this.proxy(this.hideLoadingIndicator)) + } + + SetEditor.prototype.itemsRequestDone = function(data, currentValue, initialization) { + this.loadedItems = {} + + if (data.options) { + for (var i = 0, len = data.options.length; i < len; i++) { + this.buildItemEditor(data.options[i].value, data.options[i].title) + + this.loadedItems[data.options[i].value] = data.options[i].title + } + } + + this.setLinkText(this.getLink()) + } + // // Helpers // @@ -117,20 +165,67 @@ return this.containerCell.querySelector('a.trigger') } + SetEditor.prototype.getItemsSource = function() { + if (this.propertyDefinition.items !== undefined) { + return this.propertyDefinition.items + } + + return this.loadedItems + } + SetEditor.prototype.valueToText = function(value) { - if (!this.propertyDefinition.items) { + var source = this.getItemsSource() + + if (!source) { return value } - for (var itemValue in this.propertyDefinition.items) { + for (var itemValue in source) { if (itemValue == value) { - return this.propertyDefinition.items[itemValue] + return source[itemValue] } } return value } + /* + * Removes items that don't exist in the defined items from + * the value. + */ + SetEditor.prototype.cleanUpValue = function(value) { + if (!value) { + return value + } + + var result = [], + source = this.getItemsSource() + + for (var i = 0, len = value.length; i < len; i++) { + var currentValue = value[i] + + if (source[currentValue] !== undefined) { + result.push(currentValue) + } + } + + return result + } + + SetEditor.prototype.getNormalizedValue = function() { + var value = this.inspector.getPropertyValue(this.propertyDefinition.property) + + if (value === undefined) { + return value + } + + if (value.length === undefined || typeof value === 'string') { + return undefined + } + + return value + } + // // Editor API methods // @@ -159,7 +254,7 @@ // current set value is [create] and checkboxValue is "create". // The result of the method will be TRUE. - var value = this.inspector.getPropertyValue(this.propertyDefinition.property) + var value = this.getNormalizedValue() if (value === undefined) { return this.isCheckedByDefault(checkboxValue) @@ -173,7 +268,7 @@ } SetEditor.prototype.setPropertyValue = function(checkboxValue, isChecked) { - var currentValue = this.inspector.getPropertyValue(this.propertyDefinition.property) + var currentValue = this.getNormalizedValue() if (currentValue === undefined) { currentValue = this.propertyDefinition.default @@ -195,7 +290,7 @@ } } - this.inspector.setPropertyValue(this.propertyDefinition.property, currentValue) + this.inspector.setPropertyValue(this.propertyDefinition.property, this.cleanUpValue(currentValue)) this.setLinkText(this.getLink()) } @@ -215,5 +310,15 @@ } } + SetEditor.prototype.disposeControls = function() { + var link = this.getLink() + + if (this.propertyDefinition.items === undefined) { + $(link).loadIndicator('destroy') + } + + link.parentNode.removeChild(link) + } + $.oc.inspector.propertyEditors.set = SetEditor }(window.jQuery); \ No newline at end of file diff --git a/modules/system/assets/ui/js/inspector.editor.text.js b/modules/system/assets/ui/js/inspector.editor.text.js index 2e7f1b4a5..bd6727853 100644 --- a/modules/system/assets/ui/js/inspector.editor.text.js +++ b/modules/system/assets/ui/js/inspector.editor.text.js @@ -26,7 +26,7 @@ link.setAttribute('href', '#') this.setLinkText(link) - $.oc.foundation.element.addClass(this.containerCell, 'text-multiline') + $.oc.foundation.element.addClass(this.containerCell, 'trigger-cell') this.containerCell.appendChild(link) } diff --git a/modules/system/assets/ui/js/inspector.surface.js b/modules/system/assets/ui/js/inspector.surface.js index 9eaf2cb4e..3f1fe3d9d 100644 --- a/modules/system/assets/ui/js/inspector.surface.js +++ b/modules/system/assets/ui/js/inspector.surface.js @@ -76,6 +76,7 @@ this.externalParameterEditors = null this.values = null this.originalValues = null + this.options.onChange = null BaseProto.dispose.call(this) } @@ -230,16 +231,11 @@ } } - Surface.prototype.applyGroupIndexAttribute = function(property, row) { - if (property.groupIndex !== undefined && property.itemType == 'property') { - row.setAttribute('data-group-index', property.groupIndex) - } - } - Surface.prototype.getRowCssClass = function(property) { var result = property.itemType - if (property.itemType == 'property' && property.groupIndex !== undefined) { + // The property.groupedControl flag doesn't allow to collapse the grouped control row itself. + if (property.itemType == 'property' && property.groupIndex !== undefined && !property.groupedControl) { result += ' grouped' result += this.isGroupExpanded(property.group) ? ' expanded' : ' collapsed' } @@ -315,6 +311,12 @@ // Field grouping // + Surface.prototype.applyGroupIndexAttribute = function(property, row) { + if (property.groupIndex !== undefined && property.itemType == 'property' && !property.groupedControl) { + row.setAttribute('data-group-index', property.groupIndex) + } + } + Surface.prototype.isGroupExpanded = function(group) { var statuses = this.loadGroupStatuses() @@ -417,6 +419,7 @@ $.oc.foundation.element.addClass(row, 'control-group') property.groupIndex = editor.getGroupIndex() + property.groupedControl = true this.buildGroupExpandControl(row.querySelector('span.title-element'), property, true) } @@ -437,46 +440,11 @@ return this.values[property] } - Surface.prototype.getValues = function() { - var result = {} - - // TODO: implement validation in this method. It should be optional, - // as the method is used by other classes internally, but the validation - // is required only for the external callers. - - for (var i=0, len = this.parsedProperties.properties.length; i < len; i++) { - var property = this.parsedProperties.properties[i] - - if (property.itemType !== 'property') { - continue - } - - var value = null, - externalParameterEditor = this.findExternalParameterEditor(property.property) - - if (!externalParameterEditor || !externalParameterEditor.isEditorVisible()) { - value = this.getPropertyValue(property.property) - - if (value === undefined) { - value = property.default - } - } - else { - value = externalParameterEditor.getValue() - value = '{{ ' + value + ' }}' - } - - result[property.property] = value - } - - return result - } - Surface.prototype.setPropertyValue = function(property, value, supressChangeEvents, forceEditorUpdate) { this.values[property] = value if (!supressChangeEvents) { - if (this.originalValues[property] === undefined || this.originalValues[property] != value) { + if (this.originalValues[property] === undefined || !this.comparePropertyValues(this.originalValues[property], value)) { this.markPropertyChanged(property, true) } else { @@ -484,6 +452,10 @@ } this.notifyEditorsPropertyChanged(property, value) + + if (this.options.onChange !== null) { + this.options.onChange(property, value) + } } if (forceEditorUpdate) { @@ -598,6 +570,61 @@ return div.innerHTML } + Surface.prototype.comparePropertyValues = function(oldValue, newValue) { + if (oldValue === undefined && newValue !== undefined) { + return false + } + + if (oldValue !== undefined && newValue === undefined) { + return false + } + + if (typeof oldValue == 'object' && typeof newValue == 'object') { + return JSON.stringify(oldValue) == JSON.stringify(newValue) + } + + return oldValue == newValue + } + + // + // External API + // + + Surface.prototype.getValues = function() { + var result = {} + +// TODO: implement validation in this method. It should be optional, +// as the method is used by other classes internally, but the validation +// is required only for the external callers. + + for (var i=0, len = this.parsedProperties.properties.length; i < len; i++) { + var property = this.parsedProperties.properties[i] + + if (property.itemType !== 'property') { + continue + } + + var value = null, + externalParameterEditor = this.findExternalParameterEditor(property.property) + + if (!externalParameterEditor || !externalParameterEditor.isEditorVisible()) { + value = this.getPropertyValue(property.property) + + if (value === undefined) { + value = property.default + } + } + else { + value = externalParameterEditor.getValue() + value = '{{ ' + value + ' }}' + } + + result[property.property] = value + } + + return result + } + // EVENT HANDLERS // @@ -614,7 +641,8 @@ // ============================ Surface.DEFAULTS = { - enableExternalParameterEditor: false + enableExternalParameterEditor: false, + onChange: null } // REGISTRATION diff --git a/modules/system/assets/ui/js/loader.base.js b/modules/system/assets/ui/js/loader.base.js index 9a87d2575..b75c8f554 100644 --- a/modules/system/assets/ui/js/loader.base.js +++ b/modules/system/assets/ui/js/loader.base.js @@ -54,6 +54,11 @@ this.tally++ } + LoadIndicator.prototype.destroy = function() { + this.$el.removeData('oc.loadIndicator') + this.$el = null + } + LoadIndicator.DEFAULTS = { text: '' } diff --git a/modules/system/assets/ui/less/inspector.less b/modules/system/assets/ui/less/inspector.less index c2a5db052..3bb12fc8a 100644 --- a/modules/system/assets/ui/less/inspector.less +++ b/modules/system/assets/ui/less/inspector.less @@ -116,9 +116,12 @@ } } - &.text-multiline, &.set { + &.trigger-cell { + padding: 0!important; + a.trigger { display: block; + padding: 5px 12px 7px 12px; overflow: hidden; text-overflow: ellipsis; color: @color-inspector-text; @@ -127,6 +130,16 @@ &.placeholder { color: #b5babd; } + + .loading-indicator { + background-color: @color-inspector-bg; + + span { + margin-top: -12px; + right: 10px; + left: auto; + } + } } } @@ -317,7 +330,7 @@ .select2-selection { background: transparent; - height: 30px; + height: 29px; line-height: 29px; padding: 0 3px 0 12px; .border-radius(0) !important; diff --git a/modules/system/assets/ui/less/list.less b/modules/system/assets/ui/less/list.less index a46e2864d..c3e35a373 100644 --- a/modules/system/assets/ui/less/list.less +++ b/modules/system/assets/ui/less/list.less @@ -34,6 +34,10 @@ table.table.data { font-size: 12px; + &.no-offset-bottom { + margin-bottom: 0!important; + } + thead { background: @color-list-head-bg; @@ -228,6 +232,12 @@ table.table.data { } } + &.no-active-indicator tbody { + tr td:first-child { + border-left: none; + } + } + tfoot { a { color: @color-list-text; text-decoration: none; } td, th { diff --git a/modules/system/assets/ui/storm-min.js b/modules/system/assets/ui/storm-min.js index 13ea7676f..7f7bfd4c8 100644 --- a/modules/system/assets/ui/storm-min.js +++ b/modules/system/assets/ui/storm-min.js @@ -1786,6 +1786,8 @@ if(this.options.opaque!==undefined){indicator.addClass('is-opaque')} this.$el.prepend(indicator) this.$el.addClass('in-progress') this.tally++} +LoadIndicator.prototype.destroy=function(){this.$el.removeData('oc.loadIndicator') +this.$el=null} LoadIndicator.DEFAULTS={text:''} var old=$.fn.loadIndicator $.fn.loadIndicator=function(option){var args=arguments;return this.each(function(){var $this=$(this) diff --git a/modules/system/assets/ui/storm.css b/modules/system/assets/ui/storm.css index 5bd007316..026c95b3f 100644 --- a/modules/system/assets/ui/storm.css +++ b/modules/system/assets/ui/storm.css @@ -2320,6 +2320,7 @@ table td[class*="col-"],table th[class*="col-"]{position:static;float:none;displ .table-responsive > .table-bordered > tbody > tr:last-child > th,.table-responsive > .table-bordered > tfoot > tr:last-child > th,.table-responsive > .table-bordered > tbody > tr:last-child > td,.table-responsive > .table-bordered > tfoot > tr:last-child > td{border-bottom:0} } table.table.data{font-size:12px} +table.table.data.no-offset-bottom{margin-bottom:0 !important} table.table.data thead{background:#ffffff} table.table.data thead td,table.table.data thead th{border-width:1px;border-top:1px solid #e2e2e2 !important;border-color:#e2e2e2;padding:0;font-weight:normal} table.table.data thead td > a,table.table.data thead th > a,table.table.data thead td > span,table.table.data thead th > span{display:block;padding:13px 15px;text-transform:uppercase;color:#333333;text-decoration:none} @@ -2359,6 +2360,7 @@ table.table.data tbody td.column-slim{padding-left:0;padding-right:0} table.table.data tbody.icons td i[class^="icon-"]{display:inline-block;margin-right:7px;font-size:15px;color:#95a5a6;position:relative;top:1px} table.table.data tbody.clickable{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} table.table.data tbody td.column-compact{padding:0} +table.table.data.no-active-indicator tbody tr td:first-child{border-left:none} table.table.data tfoot a{color:#666666;text-decoration:none} table.table.data tfoot td,table.table.data tfoot th{border-color:#e2e2e2;padding:10px 15px} table.table.data th.list-cell-type-switch,table.table.data td.list-cell-type-switch{text-align:center} @@ -2440,8 +2442,11 @@ table.table.data tr.list-tree-level-10 td.list-cell-index-1{padding-left:125px} .inspector-fields td.text input[type=text]::-moz-placeholder{font-weight:normal !important;color:#b5babd} .inspector-fields td.text input[type=text]:-ms-input-placeholder{font-weight:normal !important;color:#b5babd} .inspector-fields td.text.active{background:#ffffff;border-left:1px solid #c8cccd} -.inspector-fields td.text-multiline a.trigger,.inspector-fields td.set a.trigger{display:block;overflow:hidden;text-overflow:ellipsis;color:#333333;text-decoration:none} -.inspector-fields td.text-multiline a.trigger.placeholder,.inspector-fields td.set a.trigger.placeholder{color:#b5babd} +.inspector-fields td.trigger-cell{padding:0 !important} +.inspector-fields td.trigger-cell a.trigger{display:block;padding:5px 12px 7px 12px;overflow:hidden;text-overflow:ellipsis;color:#333333;text-decoration:none} +.inspector-fields td.trigger-cell a.trigger.placeholder{color:#b5babd} +.inspector-fields td.trigger-cell a.trigger .loading-indicator{background-color:#f2f2f2} +.inspector-fields td.trigger-cell a.trigger .loading-indicator span{margin-top:-12px;right:10px;left:auto} .inspector-fields td.dropdown{padding:0 !important} .inspector-fields td select{width:90%} .inspector-fields td div.external-param-editor-container{position:relative;padding-right:15px} @@ -2467,7 +2472,7 @@ table.table.data tr.list-tree-level-10 td.list-cell-index-1{padding-left:125px} .inspector-fields div.custom-checkbox{margin-top:0;margin-bottom:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} .inspector-fields div.custom-checkbox label:before{top:-12px} .inspector-fields .select2-container{width:100% !important} -.inspector-fields .select2-container .select2-selection{background:transparent;height:30px;line-height:29px;padding:0 3px 0 12px;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;border:none !important;font-size:12px} +.inspector-fields .select2-container .select2-selection{background:transparent;height:29px;line-height:29px;padding:0 3px 0 12px;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;border:none !important;font-size:12px} .inspector-fields .select2-container .select2-selection.select2-default{font-weight:normal !important} .inspector-fields .select2-container .loading-indicator > span{top:15px} .inspector-fields .select2-container.select2-container--open{-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;border:none !important}