diff --git a/modules/backend/formwidgets/repeater/assets/css/repeater.css b/modules/backend/formwidgets/repeater/assets/css/repeater.css index 0c58d3497..f51888fd2 100644 --- a/modules/backend/formwidgets/repeater/assets/css/repeater.css +++ b/modules/backend/formwidgets/repeater/assets/css/repeater.css @@ -1,27 +1,6 @@ .field-repeater { padding-top: 5px; } -.field-repeater .field-repeater-buttons { - text-align: right; - margin-bottom: 10px; - margin-top: -15px; - font-size: 12px; -} -.field-repeater .field-repeater-buttons * { - text-align: left; -} -.field-repeater .field-repeater-buttons .item { - color: #000000; - opacity: 0.5; - line-height: 20px; - margin: 0 10px; - display: inline-block; -} -.field-repeater .field-repeater-buttons .item:hover, -.field-repeater .field-repeater-buttons .item:focus { - opacity: 0.7; - text-decoration: none; -} .field-repeater ul.field-repeater-items, .field-repeater li.field-repeater-item { padding: 0; @@ -40,6 +19,9 @@ .field-repeater ul.field-repeater-items > li.dragged .repeater-item-remove { opacity: 0; } +.field-repeater ul.field-repeater-items > li.dragged .repeater-item-collapsed-title { + top: 5px; +} .field-repeater ul.field-repeater-items > li.placeholder { display: block; position: relative; @@ -67,8 +49,6 @@ padding-left: 15px; border-left: 1px solid #dbdee0; min-height: 30px; - -webkit-transition: all 0.5s; - transition: all 0.5s; } .field-repeater li.field-repeater-item:before { color: #bdc3c7; @@ -95,33 +75,11 @@ .field-repeater li.field-repeater-item.collapsed .repeater-item-collapsed-title { display: block; } -.field-repeater li.field-repeater-item .repeater-item-collapse { - position: absolute; - top: -10px; - right: 40px; - height: 20px; - z-index: 90; - font-size: 12px; -} -.field-repeater li.field-repeater-item .repeater-item-collapse a { - -webkit-transition: all 0.3s; - transition: all 0.3s; - color: #000000; - opacity: 0.5; - line-height: 20px; - margin: 0 10px; - display: block; - float: left; -} -.field-repeater li.field-repeater-item .repeater-item-collapse a:hover, -.field-repeater li.field-repeater-item .repeater-item-collapse a:focus { - opacity: 0.7; - text-decoration: none; -} .field-repeater li.field-repeater-item .repeater-item-collapsed-title { display: none; - top: -7px; + top: -5px; position: absolute; + font-size: 13px; } .field-repeater li.field-repeater-item .field-repeater-form { position: relative; @@ -150,18 +108,43 @@ .field-repeater li.field-repeater-item .repeater-item-handle:hover { color: #999; } +.field-repeater li.field-repeater-item .repeater-item-collapse { + position: absolute; + top: -9px; + right: 22px; + z-index: 90; +} +.field-repeater li.field-repeater-item .repeater-item-collapse a, +.field-repeater li.field-repeater-item .repeater-item-collapse button { + -webkit-transition: transform 0.3s; + transition: transform 0.3s; + color: #bdc3c7; + line-height: 20px; + display: block; + font-size: 12px; +} +.field-repeater li.field-repeater-item .repeater-item-collapse a:hover, +.field-repeater li.field-repeater-item .repeater-item-collapse button:hover, +.field-repeater li.field-repeater-item .repeater-item-collapse a:focus, +.field-repeater li.field-repeater-item .repeater-item-collapse button:focus { + color: #999; + text-decoration: none; +} .field-repeater li.field-repeater-item .repeater-item-remove { position: absolute; top: -10px; right: 0; z-index: 90; } +.field-repeater li.field-repeater-item .repeater-item-collapse, .field-repeater li.field-repeater-item .repeater-item-handle, .field-repeater li.field-repeater-item .repeater-item-remove { width: 20px; height: 20px; text-align: center; } +.field-repeater li.field-repeater-item:hover .repeater-item-collapse, +.field-repeater li.field-repeater-item:active .repeater-item-collapse, .field-repeater li.field-repeater-item:hover .repeater-item-handle, .field-repeater li.field-repeater-item:active .repeater-item-handle, .field-repeater li.field-repeater-item:hover .repeater-item-remove, diff --git a/modules/backend/formwidgets/repeater/assets/js/repeater.js b/modules/backend/formwidgets/repeater/assets/js/repeater.js index 5d98fc86d..a8963218b 100644 --- a/modules/backend/formwidgets/repeater/assets/js/repeater.js +++ b/modules/backend/formwidgets/repeater/assets/js/repeater.js @@ -6,14 +6,14 @@ * - data-option="value" - an option with a value * * JavaScript API: - * $('a#someElement').fieldRepeater({ option: 'value' }) - * - * Dependences: - * - Some other plugin (filename.js) + * $('a#someElement').fieldRepeater({...}) */ +function ($) { "use strict"; + var Base = $.oc.foundation.base, + BaseProto = Base.prototype + // FIELD REPEATER CLASS DEFINITION // ============================ @@ -22,23 +22,46 @@ this.$el = $(element) this.$sortable = $(options.sortableContainer, this.$el) - // Init + $.oc.foundation.controlUtils.markDisposable(element) + Base.call(this) this.init() } + Repeater.prototype = Object.create(BaseProto) + Repeater.prototype.constructor = Repeater + Repeater.DEFAULTS = { sortableHandle: '.repeater-item-handle', - sortableContainer: 'ul.field-repeater-items' + sortableContainer: 'ul.field-repeater-items', + titleFrom: null } Repeater.prototype.init = function() { - // Init with no arguments this.bindSorting() - var self = this - this.$el.on('click', '.repeater-item-collapse-one', self.toggleCollapse) - this.$el.on('click', '.repeater-collapse-all', self.collapseAll) - this.$el.on('click', '.repeater-expand-all', self.expandAll) + this.$el.on('click', '> ul > li > .repeater-item-collapse .repeater-item-collapse-one', this.proxy(this.toggleCollapse)) + + this.$el.one('dispose-control', this.proxy(this.dispose)) + } + + Repeater.prototype.dispose = function() { + this.$sortable.sortable('destroy') + + this.$el.off('click', '> ul > li > .repeater-item-collapse .repeater-item-collapse-one', this.proxy(this.toggleCollapse)) + + this.$el.off('dispose-control', this.proxy(this.dispose)) + this.$el.removeData('oc.repeater') + + this.$el = null + this.$sortable = null + this.options = null + + BaseProto.dispose.call(this) + } + + // Deprecated + Repeater.prototype.unbind = function() { + this.dispose() } Repeater.prototype.bindSorting = function() { @@ -50,50 +73,66 @@ this.$sortable.sortable(sortableOptions) } - Repeater.prototype.unbind = function() { - this.$sortable.sortable('destroy') - this.$el.removeData('oc.repeater') - } + Repeater.prototype.toggleCollapse = function(ev) { + var $item = $(ev.target).closest('.field-repeater-item'), + isCollapsed = $item.hasClass('collapsed') - Repeater.prototype.toggleCollapse = function() { - var $item = $(this).closest('.field-repeater-item') - - if ($item.hasClass('collapsed')) { - Repeater.prototype.expand($item) - } else { - Repeater.prototype.collapse($item) + if (event.ctrlKey || event.metaKey) { + isCollapsed ? this.expandAll() : this.collapseAll() + } + else { + isCollapsed ? this.expand($item) : this.collapse($item) } } Repeater.prototype.collapseAll = function() { - var items = $(this).closest('.field-repeater').find('.field-repeater-item') + var self = this, + items = $('.field-repeater-item', this.$el) $.each(items, function(key, item){ - Repeater.prototype.collapse($(item)) + self.collapse($(item)) }) } Repeater.prototype.expandAll = function() { - var items = $(this).closest('.field-repeater').find('.field-repeater-item') + var self = this, + items = $('.field-repeater-item', this.$el) $.each(items, function(key, item){ - Repeater.prototype.expand($(item)) + self.expand($(item)) }) } Repeater.prototype.collapse = function($item) { $item.addClass('collapsed') - - var $textInput = $item.find('input[type=text]').first() - if($textInput.length) { - $item.find('.repeater-item-collapsed-title').text($textInput.val()); - } + $('.repeater-item-collapsed-title', $item).text(this.getCollapseTitle($item)); } Repeater.prototype.expand = function($item) { $item.removeClass('collapsed') } + Repeater.prototype.getCollapseTitle = function($item) { + var $target, + defaultText = '' + + if (this.options.titleFrom) { + $target = $('[data-field-name="'+this.options.titleFrom+'"]') + if (!$target.length) { + $target = $item + } + } + else { + $target = $item + } + + var $textInput = $('input[type=text]:first', $target) + if ($textInput.length) { + return $textInput.val() + } + + return defaultText + } // FIELD REPEATER PLUGIN DEFINITION // ============================ @@ -131,4 +170,4 @@ $('[data-control="fieldrepeater"]').fieldRepeater() }); -}(window.jQuery); \ No newline at end of file +}(window.jQuery); diff --git a/modules/backend/formwidgets/repeater/assets/less/repeater.less b/modules/backend/formwidgets/repeater/assets/less/repeater.less index 8262bc0c0..4c2fa3bf4 100644 --- a/modules/backend/formwidgets/repeater/assets/less/repeater.less +++ b/modules/backend/formwidgets/repeater/assets/less/repeater.less @@ -1,33 +1,8 @@ @import "../../../../assets/less/core/boot.less"; .field-repeater { - padding-top: 5px; - .field-repeater-buttons { - text-align: right; - margin-bottom: 10px; - margin-top: -15px; - font-size: 12px; - - * { - text-align: left; - } - - a { - color: #000000; - opacity: 0.5; - line-height: 20px; - margin:0 10px; - display: inline-block; - } - a:hover, - a:focus { - opacity: 0.7; - text-decoration: none; - } - } - ul.field-repeater-items, li.field-repeater-item { padding: 0; @@ -48,6 +23,10 @@ .repeater-item-remove { opacity: 0; } + + .repeater-item-collapsed-title { + top: 5px; + } } &.placeholder { @@ -73,8 +52,6 @@ padding-left: 15px; border-left: 1px solid #dbdee0; min-height: 30px; - -webkit-transition: all 0.5s; - transition: all 0.5s; &:before { color: #bdc3c7; @@ -96,42 +73,16 @@ } } - .repeater-item-collapsed-title{ + .repeater-item-collapsed-title { display: block; } } - .repeater-item-collapse { - position: absolute; - top: -10px; - right: 40px; - height: 20px; - z-index: 90; - font-size: 12px; - - a, - button { - -webkit-transition: all 0.3s; - transition: all 0.3s; - color: #000000; - opacity: 0.5; - line-height: 20px; - margin:0 10px; - display: block; - float: left; - - &:hover, - &:focus { - opacity: 0.7; - text-decoration: none; - } - } - } - - .repeater-item-collapsed-title{ + .repeater-item-collapsed-title { display: none; - top: -7px; + top: -5px; position: absolute; + font-size: 13px; } .field-repeater-form { @@ -155,6 +106,27 @@ } } + .repeater-item-collapse { + position: absolute; + top: -9px; + right: 22px; + z-index: 90; + + a, button { + .transition(~'transform 0.3s'); + color: #bdc3c7; + line-height: 20px; + display: block; + font-size: 12px; + + &:hover, + &:focus { + color: #999; + text-decoration: none; + } + } + } + .repeater-item-remove { position: absolute; top: -10px; @@ -162,6 +134,7 @@ z-index: 90; } + .repeater-item-collapse, .repeater-item-handle, .repeater-item-remove { width: 20px; @@ -170,6 +143,7 @@ } &:hover, &:active { + .repeater-item-collapse, .repeater-item-handle, .repeater-item-remove { opacity: 1; @@ -209,5 +183,4 @@ > a { color: #bdc3c7;} } } - -} \ No newline at end of file +} diff --git a/modules/backend/formwidgets/repeater/partials/_repeater.htm b/modules/backend/formwidgets/repeater/partials/_repeater.htm index e95856dba..59cba2994 100644 --- a/modules/backend/formwidgets/repeater/partials/_repeater.htm +++ b/modules/backend/formwidgets/repeater/partials/_repeater.htm @@ -3,16 +3,6 @@ data-sortable-container="#getId('items') ?>" data-sortable-handle=".getId('items') ?>-handle"> -
- - - - - - - -
-