Skip to content

Commit

Permalink
Merge pull request #2904 from ONLYOFFICE/feature/custom-toolbar-buttons
Browse files Browse the repository at this point in the history
Feature/custom toolbar buttons
  • Loading branch information
JuliaRadzhabova authored Mar 28, 2024
2 parents f2669e3 + 5a1f1ce commit 4d1e562
Show file tree
Hide file tree
Showing 16 changed files with 585 additions and 33 deletions.
81 changes: 73 additions & 8 deletions apps/common/main/lib/component/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ define([
'print(\'<i class=\"icon \' + iconCls + \'\">&nbsp;</i>\'); %>' +
'<% } %>';

var templateBtnCaption =
'<%= caption %>' +
'<i class="caret"></i>';

var templateHugeCaption =
'<button type="button" class="btn <%= cls %>" id="<%= id %>" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>> ' +
'<div class="inner-box-icon">' +
Expand All @@ -208,9 +212,7 @@ define([
templateBtnIcon +
'</div>' +
'<div class="inner-box-caption">' +
'<span class="caption"><%= caption %>' +
'<i class="caret"></i>' +
'</span>' +
'<span class="caption">' + templateBtnCaption + '</span>' +
'<i class="caret compact-caret"></i>' +
'</div>' +
'</button>' +
Expand All @@ -225,9 +227,7 @@ define([
'</button>' +
'<button type="button" class="btn <%= cls %> inner-box-caption dropdown-toggle" data-toggle="dropdown" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>' +
'<span class="btn-fixflex-vcenter">' +
'<span class="caption"><%= caption %>' +
'<i class="caret"></i>' +
'</span>' +
'<span class="caption">' + templateBtnCaption + '</span>' +
'<i class="caret compact-caret"></i>' +
'</span>' +
'</button>' +
Expand Down Expand Up @@ -898,7 +898,7 @@ define([

setCaption: function(caption) {
if (this.caption != caption) {
if ( /icon-top/.test(this.cls) && !!this.caption && /huge/.test(this.cls) ) {
if ( /icon-top/.test(this.options.cls) && !!this.caption && /huge/.test(this.options.cls) ) {
var newCaption = this.getCaptionWithBreaks(caption);
this.caption = newCaption || caption;
} else
Expand All @@ -908,7 +908,7 @@ define([
var captionNode = this.cmpEl.find('.caption');

if (captionNode.length > 0) {
captionNode.html(this.caption);
captionNode.html((this.split || this.menu) ? _.template(templateBtnCaption)({caption: this.caption}) : this.caption);
} else {
this.cmpEl.find('button:first').addBack().filter('button').html(this.caption);
}
Expand Down Expand Up @@ -988,5 +988,70 @@ define([
}
}
});

Common.UI.ButtonCustom = Common.UI.Button.extend(_.extend({
initialize : function(options) {
options.iconCls = 'icon-custom ' + (options.iconCls || '');
Common.UI.Button.prototype.initialize.call(this, options);

this.iconsSet = Common.UI.iconsStr2IconsObj(options.iconsSet || ['']);
var icons = Common.UI.getSuitableIcons(this.iconsSet);
this.iconNormalImg = icons['normal'];
this.iconActiveImg = icons['active'];
},

render: function (parentEl) {
Common.UI.Button.prototype.render.call(this, parentEl);

var _current_active = false,
me = this;
this.cmpButtonFirst = $('button:first', this.$el || $(this.el));
const _callback = function (records, observer) {
var _hasactive = me.cmpButtonFirst.hasClass('active') || me.cmpButtonFirst.is(':active');
if ( _hasactive !== _current_active ) {
me.updateIcon();
_current_active = _hasactive;
}
};
this.cmpButtonFirst[0] && (new MutationObserver(_callback))
.observe(this.cmpButtonFirst[0], {
attributes : true,
attributeFilter : ['class'],
});

if (this.menu && !this.split) {
var onMouseDown = function (e) {
_callback();
$(document).on('mouseup', onMouseUp);
};
var onMouseUp = function (e) {
_callback();
$(document).off('mouseup', onMouseUp);
};
this.cmpButtonFirst.on('mousedown', _.bind(onMouseDown, this));
}

this.updateIcon();
Common.NotificationCenter.on('uitheme:changed', this.updateIcons.bind(this));
},

updateIcons: function() {
var icons = Common.UI.getSuitableIcons(this.iconsSet);
this.iconNormalImg = icons['normal'];
this.iconActiveImg = icons['active'];
this.updateIcon();
},

updateIcon: function() {
this.$icon && this.$icon.css({'background-image': 'url('+ (this.cmpButtonFirst && (this.cmpButtonFirst.hasClass('active') || this.cmpButtonFirst.is(':active')) ? this.iconActiveImg : this.iconNormalImg) +')'});
},

applyScaling: function (ratio) {
if ( this.options.scaling !== ratio ) {
this.options.scaling = ratio;
this.updateIcons();
}
}
}, Common.UI.ButtonCustom || {}));
});

108 changes: 108 additions & 0 deletions apps/common/main/lib/component/Mixtbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,10 +392,38 @@ define([
}
},

getTab: function(tab) {
if (tab && this.$panels) {
var panel = this.$panels.filter('[data-tab=' + tab + ']');
return panel.length ? panel : undefined;
}
},

createTab: function(tab, visible) {
if (!tab.action || !tab.caption) return;

var _panel = $('<section id="' + tab.action + '" class="panel" data-tab="' + tab.action + '"></section>');
this.addTab(tab, _panel, this.getLastTabIdx());
this.setVisible(tab.action, !!visible);
return _panel;
},

getMorePanel: function(tab) {
return tab && btnsMore[tab] ? btnsMore[tab].panel : null;
},

getLastTabIdx: function() {
return config.tabs.length;
},

isCompact: function () {
return this.isFolded;
},

isExpanded: function () {
return !this.isFolded || optsFold.$bar && optsFold.$bar.hasClass('expanded');
},

hasTabInvisible: function() {
if ($boxTabs.length<1) return false;

Expand Down Expand Up @@ -447,6 +475,9 @@ define([
_.each($active.find('.btn-slot .x-huge'), function(item) {
_btns.push($(item).closest('.btn-slot'));
});
btnsMore[data.tab] && btnsMore[data.tab].panel && _.each(btnsMore[data.tab].panel.find('.btn-slot .x-huge'), function(item) {
_btns.push($(item).closest('.btn-slot'));
});
data.buttons = _btns;
}
if (!_flex) {
Expand Down Expand Up @@ -603,6 +634,83 @@ define([
}
},

addCustomItems: function(tab, added, removed) {
if (!tab.action) return;

var $panel = tab.action ? this.getTab(tab.action) || this.createTab(tab, true) || this.getTab('plugins') : null,
$morepanel = this.getMorePanel(tab.action),
$moresection = $panel ? $panel.find('.more-box') : null,
compactcls = '';
($moresection.length<1) && ($moresection = null);
if ($panel) {
if (removed) {
removed.forEach(function(button, index) {
if (button.cmpEl) {
var group = button.cmpEl.closest('.group');
button.cmpEl.closest('.btn-slot').remove();
if (group.children().length<1) {
var in_more = group.closest('.more-container').length>0;
in_more ? group.next('.separator').remove() : group.prev('.separator').remove();
group.remove();
if (in_more && $morepanel.children().filter('.group').length === 0) {
btnsMore[tab.action] && btnsMore[tab.action].isActive() && btnsMore[tab.action].toggle(false);
$moresection && $moresection.css('display', "none");
}
}
}
});
$panel.find('.btn-slot:not(.slot-btn-more).x-huge').last().hasClass('compactwidth') && (compactcls = 'compactwidth');
}
added && added.forEach(function(button, index) {
var _groups, _group;
if ($morepanel) {
_groups = $morepanel.children().filter('.group');
if (_groups.length>0) {
$moresection = null;
$panel = $morepanel;
compactcls = 'compactwidth';
}
}
if (!_groups || _groups.length<1)
_groups = $panel.children().filter('.group');

if (_groups.length>0 && !button.options.separator && index>0) // add first button to new group
_group = $(_groups[_groups.length-1]);
else {
if (button.options.separator) {
var el = $('<div class="separator long"></div>');
$moresection ? $moresection.before(el) : el.appendTo($panel);
}
_group = $('<div class="group"></div>');
$moresection ? $moresection.before(_group) : _group.appendTo($panel);
}
var $slot = $('<span class="btn-slot text x-huge ' + (!(button.options.caption || '').trim() ? 'nocaption ' : ' ') + compactcls + '"></span>').appendTo(_group);
button.render($slot);
});
}
this.clearActiveData(tab.action);
this.processPanelVisible(null, true);

var visible = !this.isTabEmpty(tab.action) && Common.UI.LayoutManager.isElementVisible('toolbar-' + tab.action);
this.setVisible(tab.action, visible);
if (!visible && this.isTabActive(tab.action) && this.isExpanded()) {
if (this.getTab('home'))
this.setTab('home');
else {
tab = this.$tabs.siblings(':not(.x-lone):visible').first().find('> a[data-tab]').data('tab');
this.setTab(tab);
}
}
},

isTabEmpty: function(tab) {
var $panel = this.getTab(tab),
$morepanel = this.getMorePanel(tab),
$moresection = $panel ? $panel.find('.more-box') : null;
($moresection.length<1) && ($moresection = null);
return $panel ? !($panel.find('> .group').length>0 || $morepanel && $morepanel.find('.group').length>0) : false;
},

resizeToolbar: function(reset) {
var $active = this.$panels.filter('.active'),
more_section = $active.find('.more-box');
Expand Down
Loading

0 comments on commit 4d1e562

Please sign in to comment.