Improvements to repeater collapsing
Removed the expand all, collapse all buttons, they are a bit too bulky so have been replaced with the standard CTRL+click behavior. Added foundation library to repeater.js Add "titleFrom" option to specify which input to use for the collapsed title Styling improvements Refs #2632 + #2631
This commit is contained in:
parent
4dbe172a43
commit
e7609aa5e8
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}(window.jQuery);
|
||||
|
|
|
|||
|
|
@ -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;}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,6 @@
|
|||
data-sortable-container="#<?= $this->getId('items') ?>"
|
||||
data-sortable-handle=".<?= $this->getId('items') ?>-handle">
|
||||
|
||||
<div class="field-repeater-buttons">
|
||||
<a href="javascript:;" class="item repeater-collapse-all">
|
||||
<?= e(trans('backend::lang.dashboard.collapse_all')) ?>
|
||||
</a>
|
||||
|
||||
<a href="javascript:;" class="item repeater-expand-all">
|
||||
<?= e(trans('backend::lang.dashboard.expand_all')) ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<ul id="<?= $this->getId('items') ?>" class="field-repeater-items">
|
||||
<?php foreach ($this->formWidgets as $index => $widget): ?>
|
||||
<?= $this->makePartial('repeater_item', [
|
||||
|
|
|
|||
Loading…
Reference in New Issue