diff --git a/modules/backend/ServiceProvider.php b/modules/backend/ServiceProvider.php index a22da1905..3937b82cc 100644 --- a/modules/backend/ServiceProvider.php +++ b/modules/backend/ServiceProvider.php @@ -45,16 +45,6 @@ class ServiceProvider extends ModuleServiceProvider public function boot() { parent::boot('backend'); - - Event::listen('pages.builder.registerControls', function($controlLibrary) { - $controlLibrary->registerControl('text', - 'backend::lang.form.control_text', - $controlLibrary::GROUP_STANDARD, - 'icon-terminal', - $controlLibrary->getStandardProperties(), - null - ); - }); } /** diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index 8506b0bf3..65810c9b6 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -202,8 +202,7 @@ return [ 'insert_row_below' => 'Insert Row Below', 'delete_row' => 'Delete Row', 'concurrency_file_changed_title' => 'File was changed', - 'concurrency_file_changed_description' => "The file you're editing has been changed on disk by another user. You can either reload the file and lose your changes or override the file on the disk.", - 'control_text' => 'Text field', + 'concurrency_file_changed_description' => "The file you're editing has been changed on disk by another user. You can either reload the file and lose your changes or override the file on the disk." ], 'relation' => [ 'missing_config' => "Relation behavior does not have any configuration for ':config'.", diff --git a/modules/system/assets/ui/js/foundation.element.js b/modules/system/assets/ui/js/foundation.element.js index 713dc7547..60a4cfc81 100644 --- a/modules/system/assets/ui/js/foundation.element.js +++ b/modules/system/assets/ui/js/foundation.element.js @@ -26,13 +26,19 @@ }, addClass: function(el, className) { - if (this.hasClass(el, className)) - return + var classes = className.split(' ') - if (el.classList) - el.classList.add(className); - else - el.className += ' ' + className; + for (var i = 0, len = classes.length; i < len; i++) { + var currentClass = classes[i].trim() + + if (this.hasClass(el, currentClass)) + return + + if (el.classList) + el.classList.add(currentClass); + else + el.className += ' ' + currentClass; + } }, removeClass: function(el, className) { diff --git a/modules/system/assets/ui/js/inspector.editor.base.js b/modules/system/assets/ui/js/inspector.editor.base.js new file mode 100644 index 000000000..5274a2893 --- /dev/null +++ b/modules/system/assets/ui/js/inspector.editor.base.js @@ -0,0 +1,58 @@ +/* + * Inspector editor base class. + */ ++function ($) { "use strict"; + + // NAMESPACES + // ============================ + + if ($.oc === undefined) + $.oc = {} + + if ($.oc.inspector === undefined) + $.oc.inspector = {} + + if ($.oc.inspector.propertyEditors === undefined) + $.oc.inspector.propertyEditors = {} + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + var BaseEditor = function(inspector, propertyDefinition, containerCell) { + this.inspector = inspector + this.propertyDefinition = propertyDefinition + this.containerCell = containerCell + + Base.call(this) + + this.init() + } + + BaseEditor.prototype = Object.create(BaseProto) + BaseEditor.prototype.constructor = Base + + BaseEditor.prototype.dispose = function() { + this.inspector = null + this.propertyDefinition = null + this.containerCell = null + + BaseProto.dispose.call(this) + } + + BaseEditor.prototype.init = function() { + this.build() + this.registerHandlers() + } + + BaseEditor.prototype.build = function() { + return null + } + + BaseEditor.prototype.registerHandlers = function() { + } + + $.oc.inspector.propertyEditors.base = BaseEditor +}(window.jQuery); \ No newline at end of file diff --git a/modules/system/assets/ui/js/inspector.editor.string.js b/modules/system/assets/ui/js/inspector.editor.string.js new file mode 100644 index 000000000..33cf0e897 --- /dev/null +++ b/modules/system/assets/ui/js/inspector.editor.string.js @@ -0,0 +1,69 @@ +/* + * Inspector string editor class. + */ ++function ($) { "use strict"; + + var Base = $.oc.inspector.propertyEditors.base, + BaseProto = Base.prototype + + var StringEditor = function(inspector, propertyDefinition, containerCell) { + Base.call(this, inspector, propertyDefinition, containerCell) + } + + StringEditor.prototype = Object.create(BaseProto) + StringEditor.prototype.constructor = Base + + StringEditor.prototype.dispose = function() { + this.unregisterHandlers() + + BaseProto.dispose.call(this) + } + + StringEditor.prototype.build = function() { + var editor = document.createElement('input'), + placeholder = this.propertyDefinition.placeholder !== undefined ? this.propertyDefinition.placeholder : '', + value = this.inspector.getPropertyValue(this.propertyDefinition.property) + + editor.setAttribute('type', 'text') + editor.setAttribute('class', 'string-editor') + editor.setAttribute('placeholder', 'placeholder') + + if (value === undefined) { + value = this.propertyDefinition.default + } + + editor.value = value + + $.oc.foundation.element.addClass(this.containerCell, 'text') + + this.containerCell.appendChild(editor) + } + + StringEditor.prototype.getInput = function() { + return this.containerCell.querySelector('input') + } + + StringEditor.prototype.registerHandlers = function() { + var input = this.getInput() + + input.addEventListener('focus', this.proxy(this.onInputFocus)) + input.addEventListener('change', this.proxy(this.onInputChange)) + } + + StringEditor.prototype.unregisterHandlers = function() { + var input = this.getInput() + + input.removeEventListener('focus', this.proxy(this.onInputFocus)) + input.removeEventListener('change', this.proxy(this.onInputChange)) + } + + StringEditor.prototype.onInputFocus = function(ev) { + this.inspector.makeCellActive(this.containerCell) + } + + StringEditor.prototype.onInputChange = function() { + + } + + $.oc.inspector.propertyEditors.string = StringEditor +}(window.jQuery); \ No newline at end of file diff --git a/modules/system/assets/ui/js/inspector.engine.js b/modules/system/assets/ui/js/inspector.engine.js new file mode 100644 index 000000000..b97aedd5e --- /dev/null +++ b/modules/system/assets/ui/js/inspector.engine.js @@ -0,0 +1,91 @@ +/* + * Inspector engine helpers. + * + * The helpers are used mostly by the Inspector Surface. + * + */ ++function ($) { "use strict"; + + // NAMESPACES + // ============================ + + if ($.oc === undefined) + $.oc = {} + + if ($.oc.inspector === undefined) + $.oc.inspector = {} + + $.oc.inspector.engine = {} + + // CLASS DEFINITION + // ============================ + + function findGroup(group, properties) { + for (var i = 0, len = properties.length; i < len; i++) { + var property = properties[i] + + if (property.itemType !== undefined && property.itemType == 'group' && item.title == group) { + return property + } + } + + return null + } + + $.oc.inspector.engine.processPropertyGroups = function(properties) { + var fields = [], + result = { + hasGroups: false, + properties: [] + }, + groupIndex = 0 + + + for (var i = 0, len = properties.length; i < len; i++) { + var property = properties[i] + + property.itemType = 'property' + + if (property.group === undefined) { + fields.push(property) + } + else { + var group = findGroup(property.group) + + if (!group) { + group = { + itemType: 'group', + title: property.group, + properties: [], + groupIndex: groupIndex + } + + groupIndex++ + fields.push(group) + } + + property.groupIndex = group.groupIndex + group.properties.push(property) + } + } + + for (var i = 0, len = properties.length; i < len; i++) { + var property = properties[i] + + result.properties.push(property) + + if (property.itemType == 'group') { + result.hasGroups = true + + for (var j = 0, propertiesLen = property.properties.length; j < propertiesLen; j++) { + result.properties.push(property.properties[j]) + } + + delete property.properties + } + } + + return result + } + +}(window.jQuery); diff --git a/modules/system/assets/ui/js/inspector.helpers.js b/modules/system/assets/ui/js/inspector.helpers.js new file mode 100644 index 000000000..71afde027 --- /dev/null +++ b/modules/system/assets/ui/js/inspector.helpers.js @@ -0,0 +1,32 @@ +/* + * Inspector helper functions. + * + */ ++function ($) { "use strict"; + + // NAMESPACES + // ============================ + + if ($.oc === undefined) + $.oc = {} + + if ($.oc.inspector === undefined) + $.oc.inspector = {} + + $.oc.inspector.helpers = {} + + $.oc.inspector.helpers.generateElementUniqueId = function(element) { + if (element.hasAttribute('data-inspector-id')) { + return element.getAttribute('data-inspector-id') + } + + var id = $.oc.inspector.helpers.generateUniqueId() + element.setAttribute('data-inspector-id', id) + + return id + } + + $.oc.inspector.helpers.generateUniqueId = function() { + return "inspectorid-" + Math.floor(Math.random() * new Date().getTime()); + } +}(window.jQuery) \ No newline at end of file diff --git a/modules/system/assets/ui/js/inspector.surface.js b/modules/system/assets/ui/js/inspector.surface.js new file mode 100644 index 000000000..95302198e --- /dev/null +++ b/modules/system/assets/ui/js/inspector.surface.js @@ -0,0 +1,333 @@ +/* + * Inspector Surface class. + * + * The class creates Inspector user interface and all the editors + * corresponding to the passed configuration in a specified container + * element. + * + */ ++function ($) { "use strict"; + + // NAMESPACES + // ============================ + + if ($.oc === undefined) + $.oc = {} + + if ($.oc.inspector === undefined) + $.oc.inspector = {} + + // CLASS DEFINITION + // ============================ + + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + + /** + * Creates the Inspector surface in a container. + * - containerElement container DOM element + * - properties array (array of objects) + * - values - property values, an object + * - inspectorUniqueId - a string containing the unique inspector identifier. + * The identifier should be a constant for an inspectable element. Use + * $.oc.inspector.helpers.generateElementUniqueId(element) to generate a persistent ID + * for an element. Use $.oc.inspector.helpers.generateUniqueId() to generate an ID + * not associated with an element. Inspector uses the ID for storing configuration + * related to an element in the document DOM. + */ + var Surface = function(containerElement, properties, values, inspectorUniqueId, options) { + this.options = $.extend({}, Surface.DEFAULTS, typeof option == 'object' && option) + this.rawProperties = properties + this.parsedProperties = $.oc.inspector.engine.processPropertyGroups(properties) + this.container = containerElement + this.inspectorUniqueId = inspectorUniqueId + this.values = values + + this.editors = [] + this.tableContainer = null + + Base.call(this) + + this.init() + } + + Surface.prototype = Object.create(BaseProto) + Surface.prototype.constructor = Surface + + Surface.prototype.dispose = function() { + this.removeElements() + this.disposeEditors() + + this.container = null + this.tableContainer = null + this.rawProperties = null + this.parsedProperties = null + this.editors = null + this.values = null + + BaseProto.dispose.call(this) + } + + // INTERNAL METHODS + // ============================ + + Surface.prototype.init = function() { + this.build() + } + + // + // Building + // + + /** + * Builds the Inspector table. The markup generated by this method looks + * like this: + * + *
|
+ *
+ *
+ *
+ *
+ * Expand/Collapse
+ * Label
+ *
+ *
+ * |
+ * + * Editor markup + * | + *
|---|