JS: Implement collapsible-container behavior

This commit is contained in:
Florian Strohmaier 2018-11-21 13:59:54 +01:00 committed by Johannes Meyer
parent 14caccc384
commit b07ffd4987
4 changed files with 152 additions and 19 deletions

View File

@ -76,7 +76,7 @@ $innerLayoutScript = $this->layout()->innerLayout . '.phtml';
}
}());
</script>
<button id="collapsible-control-ghost" title="<?= $this->translate('Collapse') ?>" aria-label="<?= t('Collapse') ?>" data-label-expand="<?= t('Expand') ?>" class="collapsible-control">
<button id="collapsible-control-ghost" title="<?= $this->translate('Collapse') ?>" aria-label="<?= t('Collapse') ?>" class="collapsible-control">
<i class="icon-angle-double-down"></i>
<i class="icon-angle-double-up"></i>
</button>

View File

@ -24,6 +24,7 @@ class JavaScript
'js/icinga/timezone.js',
'js/icinga/behavior/application-state.js',
'js/icinga/behavior/autofocus.js',
'js/icinga/behavior/collapsibleContainer.js',
'js/icinga/behavior/detach.js',
'js/icinga/behavior/tooltip.js',
'js/icinga/behavior/sparkline.js',

View File

@ -161,13 +161,6 @@ a:hover > .icon-cancel {
background-color: @tr-hover-color;
cursor: pointer;
}
caption {
border-top: 1px solid @gray-light;
caption-side: bottom;
font-style: italic;
text-align: right;
}
}
.name-value-table {
@ -235,27 +228,68 @@ a:hover > .icon-cancel {
}
// Collapsible Control
.collapsible-table-container {
&.collapsed.has-collapsible .collapsible {
overflow: hidden;
max-height: 8em;
}
}
.collapsible-container {
.collapsible-container,
.collapsible-table-container {
&.collapsed:not(.has-collapsible),
&.collapsed.has-collapsible .collapsible {
overflow: hidden;
max-height: 96px;
}
&.collapsed:not(.has-collapsible) {
.collapsible-control {
bottom: 4px;
}
}
}
.collapsible-container,
.collapsible-table-container {
position: relative;
.icon-angle-double-down {
display: none;
.table-wrapper {
overflow: hidden;
}
&.collapsed .icon-angle-double-up {
display: none;
.collapsed .table-wrapper {
overflow: hidden;
max-height: 12em;
}
}
&.collapsed .icon-angle-double-down {
display: inline-block;
}
.collapsible-control > i:before {
margin-right: 0;
}
#collapsible-control-ghost {
display: none;
}
.collapsible-control > .icon-angle-double-down {
display: none;
}
.collapsible-control > .icon-angle-double-up {
display: block;
}
.collapsed {
.collapsible-control > .icon-angle-double-up {
display: none;
}
.collapsible-control > .icon-angle-double-down {
display: block;
}
}
.collapsible-control {
.rounded-corners(50%);
@ -263,10 +297,12 @@ a:hover > .icon-cancel {
color: @gray;
width: 2em;
height: 2em;
z-index: 1;
position: absolute;
border: none;
z-index: 1;
bottom: -1em;
right: .25em;
-webkit-box-shadow: 0 0 1/3em rgba(0,0,0,.3);
-moz-box-shadow: 0 0 1/3em rgba(0,0,0,.3);
box-shadow: 0 0 1/3em rgba(0,0,0,.3);
-moz-box-shadow: 0 0 1/3em rgba(0,0,0,.3);
box-shadow: 0 0 1/3em rgba(0,0,0,.3);
}

View File

@ -0,0 +1,96 @@
/*! Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
;(function(Icinga, $) {
'use strict';
var expandedContainers = [];
var maxLength = 32;
var defaultNumOfRows = 2;
var defaultHeight = 36;
function CollapsibleContainer(icinga) {
Icinga.EventListener.call(this, icinga);
this.on('rendered', '#col2', this.onRendered, this);
this.on('click', '.collapsible-container .collapsible-control, .collapsible-table-container .collapsible-control', this.onControlClicked, this);
}
CollapsibleContainer.prototype = new Icinga.EventListener();
CollapsibleContainer.prototype.onRendered = function(event) {
$(event.target).find('.collapsible-container').each(function() {
var $this = $(this);
if ($this.find('.collapsible').length > 0) {
$this.addClass('has-collapsible');
if ($this.find('.collapsible').innerHeight() > ($this.attr('data-height') || defaultHeight)) {
$this.append($('#collapsible-control-ghost').clone().removeAttr('id'));
}
} else {
if ($this.innerHeight() > ($this.attr('data-height') || defaultHeight)) {
$this.append($('#collapsible-control-ghost').clone().removeAttr('id'));
}
}
updateCollapsedState($this);
});
$(event.target).find('.collapsible-table-container').each(function() {
var $this = $(this);
if ($this.find('.collapsible').length > 0) {
$this.addClass('has-collapsible');
if ($this.find('tr').length > ($this.attr('data-numofrows') || defaultNumOfRows)) {
$this.append($('#collapsible-control-ghost').clone().removeAttr('id'));
}
if ($this.find('li').length > ($this.attr('data-numofrows') || defaultNumOfRows)) {
$this.append($('#collapsible-control-ghost').clone().removeAttr('id'));
}
}
updateCollapsedState($this);
});
};
CollapsibleContainer.prototype.onControlClicked = function(event) {
var $target = $(event.target);
var $c = $target.closest('.collapsible-container, .collapsible-table-container');
if ($c.hasClass('collapsed')) {
if (expandedContainers.length > maxLength - 1) {
expandedContainers.shift();
}
expandedContainers.push($c.attr('id'));
} else {
expandedContainers.splice(expandedContainers.indexOf($c.attr('id')), 1);
}
updateCollapsedState($c);
};
function updateCollapsedState($container, listener) {
var $collapsible;
if ($container.hasClass('has-collapsible')) {
$collapsible = $container.find('.collapsible');
} else {
$collapsible = $container;
}
if (expandedContainers.indexOf($container.attr('id')) > -1) {
$container.removeClass('collapsed');
$collapsible.css({ maxHeight: 'none' });
} else {
$container.addClass('collapsed');
if ($container.hasClass('collapsible-container')) {
$collapsible.css({ maxHeight: $container.data('height') || defaultHeight });
}
if ($container.hasClass('collapsible-table-container')) {
$collapsible.css({ maxHeight: ($container.data('numofrows') || defaultNumOfRows) * $container.find('tr').height() });
}
}
}
Icinga.Behaviors = Icinga.Behaviors || {};
Icinga.Behaviors.collapsibleContainer = CollapsibleContainer;
})(Icinga, jQuery);