Files
DocumentServer-v-9.2.0/web-apps/apps/common/main/lib/component/Button.js
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

1172 lines
48 KiB
JavaScript

/*
* (c) Copyright Ascensio System SIA 2010-2024
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
/**
* Button.js
*
* Created on 1/20/14
*
*/
/**
* Using template
*
* A simple button with text:
* <button type="button" class="btn" id="id-button">Caption</button>
*
* A simple button with icon:
* <button type="button" class="btn" id="id-button"><span class="icon">&nbsp;</span></button>
*
* A button with menu:
* <div class="btn-group" id="id-button">
* <button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
* <span class="icon">&nbsp;</span>
* <span class="caret"></span>
* </button>
* <ul class="dropdown-menu" role="menu">
* </ul>
* </div>
*
* A split button:
* <div class="btn-group split" id="id-button">
* <button type="button" class="btn"><span class="icon">&nbsp;</span></button>
* <button type="button" class="btn dropdown-toggle" data-toggle="dropdown">
* <span class="caret"></span>
* <span class="sr-only"></span>
* </button>
* <ul class="dropdown-menu" role="menu">
* </ul>
* </div>
*
* A useful classes of button size
*
* - `'small'`
* - `'normal'`
* - `'large'`
* - `'huge'`
*
* A useful classes of button type
*
* - `'default'`
* - `'active'`
*
*
* Buttons can also be toggled. To enable this, you simple set the {@link #enableToggle} property to `true`.
*
* Example usage:
* new Common.UI.Button({
* el: $('#id'),
* enableToggle: true
* });
*
*
* @property {Boolean} disabled
* True if this button is disabled. Read-only.
*
* disabled: false,
*
*
* @property {Boolean} pressed
* True if this button is pressed (only if enableToggle = true). Read-only.
*
* pressed: false,
*
*
* @cfg {Boolean} [allowDepress=true]
* False to not allow a pressed Button to be depressed. Only valid when {@link #enableToggle} is true.
*
* @cfg {String/Object} hint
* The tooltip for the button - can be a string to be used as bootstrap tooltip
*
*/
if (Common === undefined)
var Common = {};
define([
'common/main/lib/component/BaseView',
'common/main/lib/component/ToggleManager'
], function () {
'use strict';
window.createButtonSet = function() {
function ButtonsArray(args) {};
ButtonsArray.prototype = new Array;
ButtonsArray.prototype.constructor = ButtonsArray;
var _disabled = false;
ButtonsArray.prototype.add = function(button) {
button.setDisabled(_disabled);
this.push(button);
};
ButtonsArray.prototype.setDisabled = function(disable) {
// if ( _disabled != disable ) //bug when disable buttons outside the group
{
_disabled = disable;
this.forEach( function(button) {
button.setDisabled(disable);
});
}
};
ButtonsArray.prototype.toggle = function(state, suppress) {
this.forEach(function(button) {
button.toggle(state, suppress);
});
};
ButtonsArray.prototype.pressed = function() {
return this.some(function(button) {
return button.pressed;
});
};
ButtonsArray.prototype.contains = function(id) {
return this.some(function(button) {
return button.id == id;
});
};
ButtonsArray.prototype.concat = function () {
var args = Array.prototype.slice.call(arguments);
var result = Array.prototype.slice.call(this);
args.forEach(function(sub){
if (sub instanceof Array )
Array.prototype.push.apply(result, sub);
else if (sub)
result.push(sub);
});
return result;
};
var _out_array = Object.create(ButtonsArray.prototype);
for ( var i in arguments ) {
_out_array.add(arguments[i]);
}
return _out_array;
};
var templateBtnIcon =
'<% if ( iconImg ) { %>' +
'<img src="<%= iconImg %>">' +
'<% } else { %>' +
'<% if (/svgicon/.test(iconCls)) {' +
'print(\'<svg class=\"icon uni-scale\"><use class=\"zoom-int\" xlink:href=\"#\' + /svgicon\\s(\\S+)/.exec(iconCls)[1] + \'\"></use></svg>\');' +
'} else ' +
'print(\'<i class=\"icon \' + iconCls + \'\">&nbsp;</i>\'); %>' +
'<% } %>';
var templateBtnCaption =
'<%= caption %>' +
'<i class="caret"></i>';
var templateHugeCaption =
'<button type="button" class="btn <%= cls %>" id="<%= id %>" style="<%= style %>" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>> ' +
'<div class="inner-box-icon">' +
templateBtnIcon +
'</div>' +
'<div class="inner-box-caption">' +
'<span class="caption"><%= caption %></span>' +
'</div>' +
'</button>';
var templateHugeMenuCaption =
'<div class="btn-group icon-top" id="<%= id %>" style="<%= style %>">' +
'<button type="button" class="btn dropdown-toggle <%= cls %>" data-toggle="dropdown" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>' +
'<div class="inner-box-icon">' +
templateBtnIcon +
'</div>' +
'<div class="inner-box-caption">' +
'<span class="caption">' + templateBtnCaption + '</span>' +
'<i class="caret compact-caret"></i>' +
'</div>' +
'</button>' +
'</div>';
var templateHugeSplitCaption =
'<div class="btn-group x-huge split icon-top" id="<%= id %>" style="<%= style %>">' +
'<button type="button" class="btn <%= cls %> inner-box-icon">' +
'<span class="btn-fixflex-hcenter">' +
templateBtnIcon +
'</span>' +
'</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">' + templateBtnCaption + '</span>' +
'<i class="caret compact-caret"></i>' +
'</span>' +
'</button>' +
'</div>';
var getWidthOfCaption = function (txt) {
var props = Common.UI.Themes.getThemeProps('font');
var el = document.createElement('span');
el.style.fontSize = props && props.size ? props.size : '11px';
el.style.fontFamily = props && props.name ? props.name : 'Arial, Helvetica, "Helvetica Neue", sans-serif';
el.style.position = "absolute";
el.style.top = '-1000px';
el.style.left = '-1000px';
el.innerHTML = txt;
document.body.appendChild(el);
var result = el.offsetWidth;
document.body.removeChild(el);
return result;
};
var getShortText = function (txt, max) {
var lastIndex = txt.length - 1,
word = txt;
while (getWidthOfCaption(word) > max) {
word = txt.slice(0, lastIndex).trim() + '...';
lastIndex--;
}
return word;
};
Common.UI.Button = Common.UI.BaseView.extend({
options : {
id : null,
hint : false,
delayRenderHint : true,
enableToggle : false,
allowDepress : true,
toggleGroup : null,
cls : '',
iconCls : '',
caption : '',
menu : null,
disabled : false,
pressed : false,
split : false,
visible : true,
dataHint : '',
dataHintDirection: '',
dataHintOffset: '0, 0',
scaling : true,
canFocused : false, // used for button with menu
takeFocusOnClose: false, // used for button with menu, for future use in toolbar when canFocused=true, but takeFocusOnClose=false
action: '' // action for button
},
template: _.template([
'<% var applyicon = function() { %>',
'<% if (iconImg) { print(\'<img src=\"\' + iconImg + \'\">\'); } else { %>',
// '<% if (iconCls != "") { print(\'<i class=\"icon \' + iconCls + \'\">&nbsp;</i>\'); }} %>',
'<% if (iconCls != "") { ' +
' if (/svgicon/.test(iconCls)) {' +
'print(\'<svg class=\"icon uni-scale\"><use class=\"zoom-int\" xlink:href=\"#\' + /svgicon\\s(\\S+)/.exec(iconCls)[1] + \'\"></use></svg>\');' +
'} else ' +
'print(\'<i class=\"icon \' + iconCls + \'\">&nbsp;</i>\'); ' +
'}} %>',
'<% } %>',
'<% if ( !menu && onlyIcon ) { %>',
'<button type="button" class="btn <%= cls %>" id="<%= id %>" style="<%= style %>" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>',
'<% applyicon() %>',
'</button>',
'<% } else if ( !menu ) { %>',
'<button type="button" class="btn <%= cls %>" id="<%= id %>" style="<%= style %>" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>',
'<% applyicon() %>',
'<span class="caption"><%= caption %></span>',
'</button>',
'<% } else if (onlyIcon) {%>',
'<div class="btn-group" id="<%= id %>" style="<%= style %>">',
'<button type="button" class="btn dropdown-toggle <%= cls %>" data-toggle="dropdown" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>',
'<% applyicon() %>',
'</button>',
'</div>',
'<% } else if (split == false) {%>',
'<div class="btn-group" id="<%= id %>" style="<%= style %>">',
'<button type="button" class="btn dropdown-toggle <%= cls %>" data-toggle="dropdown" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>',
'<% applyicon() %>',
'<span class="caption"><%= caption %></span>',
'<span class="inner-box-caret">' +
'<i class="caret"></i>' +
'</span>',
'</button>',
'</div>',
'<% } else { %>',
'<div class="btn-group split <%= groupCls %>" id="<%= id %>" style="<%= style %>">',
'<button type="button" class="btn <%= cls %>">',
'<% applyicon() %>',
'<span class="caption"><%= caption %></span>',
'</button>',
'<button type="button" class="btn <%= cls %> dropdown-toggle" data-toggle="dropdown" data-hint="<%= dataHint %>" data-hint-direction="<%= dataHintDirection %>" data-hint-offset="<%= dataHintOffset %>" <% if (dataHintTitle) { %> data-hint-title="<%= dataHintTitle %>" <% } %>>',
'<i class="caret"></i>',
'<span class="sr-only"></span>',
'</button>',
'</div>',
'<% } %>'
].join('')),
initialize : function(options) {
Common.UI.BaseView.prototype.initialize.call(this, options);
var me = this;
me.id = me.options.id || Common.UI.getId();
me.hint = me.options.hint;
me.enableToggle = me.options.enableToggle;
me.allowDepress = me.options.allowDepress;
me.cls = me.options.cls;
me.iconCls = me.options.iconCls;
me.menu = me.options.menu;
me.split = me.options.split;
me.toggleGroup = me.options.toggleGroup;
me.disabled = me.options.disabled;
me.visible = me.options.visible;
me.pressed = me.options.pressed;
me.caption = me.options.caption;
me.template = me.options.template || me.template;
me.style = me.options.style;
me.rendered = false;
me.stopPropagation = me.options.stopPropagation;
me.delayRenderHint = me.options.delayRenderHint;
me.action = me.options.action || '';
// if ( /(?<!-)svg-icon(?!-)/.test(me.options.iconCls) )
// me.options.scaling = false;
if ( me.options.scaling === false && me.options.iconCls) {
me.iconCls = me.options.iconCls + ' scaling-off';
}
me.options.takeFocusOnClose && (me.options.canFocused = true);
if (me.options.el) {
me.render();
} else if (me.options.parentEl)
me.render(me.options.parentEl);
},
getCaptionWithBreaks: function (caption) {
var words = caption.split(' '),
newCaption = null,
maxWidth = 160 - 4, //85 - 4
containAnd = words.indexOf('&');
if (containAnd > -1) { // add & to previous word
words[containAnd - 1] += ' &';
words.splice(containAnd, 1);
}
if (words.length > 1) {
maxWidth = !!this.menu || this.split === true ? maxWidth - 10 : maxWidth;
if (words.length < 3) {
words[0] = getShortText(words[0], !!this.menu ? maxWidth + 10 : maxWidth);
words[1] = getShortText(words[1], maxWidth);
newCaption = words[0] + '<br>' + words[1];
} else {
var otherWords = '';
if (getWidthOfCaption(words[0] + ' ' + words[1]) < maxWidth) { // first and second words in first line
for (var i = 2; i < words.length; i++) {
otherWords += words[i] + ' ';
}
if (getWidthOfCaption(otherWords + (!!this.menu ? 10 : 0))*2 < getWidthOfCaption(words[0] + ' ' + words[1])) {
otherWords = getShortText((words[1] + ' ' + otherWords).trim(), maxWidth);
newCaption = words[0] + '<br>' + otherWords;
} else {
otherWords = getShortText(otherWords.trim(), maxWidth);
newCaption = words[0] + ' ' + words[1] + '<br>' + otherWords;
}
} else { // only first word is in first line
for (var j = 1; j < words.length; j++) {
otherWords += words[j] + ' ';
}
otherWords = getShortText(otherWords.trim(), maxWidth);
newCaption = words[0] + '<br>' + otherWords;
}
}
} else {
var width = getWidthOfCaption(caption);
newCaption = width < maxWidth ? caption : getShortText(caption, maxWidth);
if (!!this.menu || this.split === true) {
newCaption += '<br>';
}
}
return newCaption;
},
render: function(parentEl) {
var me = this;
me.trigger('render:before', me);
me.cmpEl = me.$el || $(me.el);
if (parentEl) {
me.setElement(parentEl, false);
if (!me.rendered) {
if ( /icon-top/.test(me.cls) && !!me.caption && /huge/.test(me.cls) ) {
if ( me.split === true ) {
!!me.cls && (me.cls = me.cls.replace(/\s?(?:x-huge|icon-top)/g, ''));
this.template = _.template(templateHugeSplitCaption);
} else
if ( !!me.menu ) {
this.template = _.template(templateHugeMenuCaption);
} else {
this.template = _.template(templateHugeCaption);
}
var newCaption = this.getCaptionWithBreaks(this.caption);
if (newCaption) {
me.caption = newCaption;
}
}
me.cmpEl = $(this.template({
id : me.id,
cls : me.cls,
groupCls : me.split && /btn-toolbar/.test(me.cls) ? 'no-borders' : '',
iconCls : me.iconCls,
iconImg : me.options.iconImg,
menu : me.menu,
split : me.split,
onlyIcon : me.options.onlyIcon,
disabled : me.disabled,
pressed : me.pressed,
caption : me.caption,
style : me.style,
dataHint : me.options.dataHint,
dataHintDirection: me.options.dataHintDirection,
dataHintOffset: me.options.dataHintOffset,
dataHintTitle: me.options.dataHintTitle
}));
if (me.menu && _.isObject(me.menu) && _.isFunction(me.menu.render)) {
me.menu.render(me.cmpEl);
me.options.canFocused && me.attachKeyEvents();
}
parentEl.html(me.cmpEl);
me.$icon = me.$el.find('.icon');
}
}
if (!me.rendered) {
var el = me.cmpEl,
isGroup = el.hasClass('btn-group'),
isSplit = el.hasClass('split');
if (_.isString(me.toggleGroup)) {
me.enableToggle = true;
}
var buttonHandler = function(e) {
if (!me.disabled && (e.which === 1 || e.which===undefined)) {
me.doToggle();
if (me.options.hint) {
var tip = me.btnEl.data('bs.tooltip');
if (tip) {
if (tip.dontShow===undefined)
tip.dontShow = true;
tip.hide();
}
}
me.split && me.options.takeFocusOnClose && me.focus();
me.trigger('click', me, e);
}
};
var doSplitSelect = function(select, element, e) {
if (!select) {
// Is mouse under button
var isUnderMouse = false;
$('button', el).each(function(index, button){
if ($(button).is(':hover')) {
isUnderMouse = true;
return false;
}
});
if (!isUnderMouse) {
el.removeClass('over');
$('button', el).removeClass('over');
}
}
if ( element == 'button') {
if (!select && (me.enableToggle && me.allowDepress && me.pressed))
return;
if (select && !isSplit && (me.enableToggle && me.allowDepress && !me.pressed)) { // to depress button with menu
e.preventDefault();
return;
}
$('button:first', el).toggleClass('active', select);
} else
$('[data-toggle^=dropdown]:first', el).toggleClass('active', select);
el.toggleClass('active', select);
me.stopPropagation && e.stopPropagation();
};
var menuHandler = function(e) {
if (!me.disabled && e.which == 1) {
if (isSplit) {
if (me.options.hint) {
var tip = (me.btnMenuEl ? me.btnMenuEl : me.btnEl).data('bs.tooltip');
if (tip) {
if (tip.dontShow===undefined)
tip.dontShow = true;
tip.hide();
}
}
doSplitSelect(!me.isMenuOpen(), 'arrow', e);
}
}
};
var doSetActiveState = function(e, state) {
if (isSplit) {
doSplitSelect(state, 'button', e);
} else {
el.toggleClass('active', state);
$('button', el).toggleClass('active', state);
}
me.stopPropagation && e.stopPropagation();
};
var splitElement;
var onMouseDown = function (e) {
splitElement = e.currentTarget.className.match(/dropdown/) ? 'arrow' : 'button';
doSplitSelect(true, splitElement, e);
$(document).on('mouseup', onMouseUp);
};
var onMouseUp = function (e) {
doSplitSelect(false, splitElement, e);
$(document).off('mouseup', onMouseUp);
};
var onAfterHideMenu = function(e, isFromInputControl) {
me.cmpEl.find('.dropdown-toggle').blur();
if (me.cmpEl.hasClass('active') !== me.pressed)
me.cmpEl.trigger('button.internal.active', [me.pressed]);
};
if (isGroup) {
if (isSplit) {
$('[data-toggle^=dropdown]', el).on('mousedown', _.bind(menuHandler, this));
$('button', el).on('mousedown', _.bind(onMouseDown, this));
(me.options.width>0) && $('button:first', el).css('width', me.options.width - $('[data-toggle^=dropdown]', el).outerWidth());
}
el.on('hide.bs.dropdown', _.bind(doSplitSelect, me, false, 'arrow'));
el.on('show.bs.dropdown', _.bind(doSplitSelect, me, true, 'arrow'));
el.on('hidden.bs.dropdown', _.bind(onAfterHideMenu, me));
$('button:first', el).on('click', buttonHandler);
} else {
el.on('click', buttonHandler);
}
el.on('button.internal.active', _.bind(doSetActiveState, me));
el.on('mouseover', function(e) {
if (!me.disabled) {
me.cmpEl.addClass('over');
me.trigger('mouseover', me, e);
}
});
el.on('mouseout', function(e) {
me.cmpEl.removeClass('over');
if (!me.disabled) {
me.trigger('mouseout', me, e);
}
});
// Register the button in the toggle manager
Common.UI.ToggleManager.register(me);
if ( me.options.scaling !== false ) {
el.attr('ratio', 'ratio');
me.applyScaling(Common.UI.Scaling.currentRatio());
el.on('app:scaling', function (e, info) {
if ( me.options.scaling != info.ratio ) {
me.applyScaling(info.ratio);
}
});
}
var $btn = $('button', el).length>0 ? $('button', el) : me.cmpEl;
if (!me.menu)
$btn.addClass('canfocused');
if (me.enableToggle && !me.menu) {
$btn.attr('aria-pressed', !!me.pressed)
}
if (me.menu) {
$('[data-toggle^=dropdown]', el).attr('aria-haspopup', 'menu');
$('[data-toggle^=dropdown]', el).attr('aria-expanded', false);
}
if ((!me.caption && me.options.hint) || me.options.ariaLabel) {
var ariaLabel = me.options.ariaLabel ? me.options.ariaLabel : ((typeof me.options.hint == 'string') ? me.options.hint : me.options.hint[0]);
$btn.attr('aria-label', ariaLabel);
}
Common.NotificationCenter.on('uitheme:changed', this.onThemeChanged.bind(this));
}
me.rendered = true;
me.options.hint && me.createHint(me.options.hint);
if (me.pressed) {
me.toggle(me.pressed, true);
}
if (me.disabled) {
me.setDisabled(!(me.disabled=false));
}
if (!me.visible) {
me.setVisible(me.visible);
}
me.trigger('render:after', me);
return this;
},
doToggle: function(){
var me = this;
if (me.enableToggle && (me.allowDepress !== false || !me.pressed)) {
me.toggle();
}
},
toggle: function(toggle, suppressEvent) {
var state = toggle === undefined ? !this.pressed : !!toggle;
this.pressed = state;
if (this.cmpEl) {
this.cmpEl.attr('aria-pressed', state);
this.cmpEl.trigger('button.internal.active', [state]);
}
if (!suppressEvent)
this.trigger('toggle', this, state);
},
click: function(opts) {
if ( !this.disabled ) {
this.doToggle();
this.trigger('click', this, opts);
}
},
isActive: function() {
if (this.enableToggle)
return this.pressed;
return this.cmpEl.hasClass('active');
},
setDisabled: function(disabled) {
if (this.rendered && this.disabled != disabled) {
var el = this.cmpEl,
isGroup = el.hasClass('btn-group'),
me = this;
disabled = (disabled===true);
if (disabled !== el.hasClass('disabled')) {
var decorateBtn = function(button) {
button.toggleClass('disabled', disabled);
if (!me.options.allowMouseEventsOnDisabled)
(disabled) ? button.attr({disabled: disabled}) : button.removeAttr('disabled');
};
decorateBtn(el);
isGroup && decorateBtn(el.children('button'));
}
if ((disabled || !Common.Utils.isGecko) && this.options.hint) {
var tip = this.btnEl.data('bs.tooltip');
if (tip) {
disabled && tip.hide();
!Common.Utils.isGecko && (tip.enabled = !disabled);
}
if (this.btnMenuEl) {
tip = this.btnMenuEl.data('bs.tooltip');
if (tip) {
disabled && tip.hide();
!Common.Utils.isGecko && (tip.enabled = !disabled);
}
}
}
if (disabled && this.menu && _.isObject(this.menu) && this.menu.rendered && this.menu.isVisible())
setTimeout(function(){ me.menu.hide()}, 1);
if ( !!me.options.signals ) {
var opts = me.options.signals;
if ( !(opts.indexOf('disabled') < 0) ) {
me.trigger('disabled', me, disabled);
}
}
if (me.tabindex!==undefined) {
var el = this.split ? this.cmpEl : this.$el && this.$el.find('button').addBack().filter('button');
disabled && (this.tabindex = el.attr('tabindex'));
el.attr('tabindex', disabled ? "-1" : me.tabindex);
}
}
this.disabled = disabled;
},
isDisabled: function() {
return this.disabled;
},
setIconCls: function(cls) {
var btnIconEl = $(this.el).find('i.icon'),
oldCls = this.iconCls,
svgIcon = $(this.el).find('.icon use.zoom-int');
this.iconCls = cls;
if (/svgicon/.test(this.iconCls)) {
var icon = /svgicon\s(\S+)/.exec(this.iconCls);
svgIcon.attr('xlink:href', icon && icon.length > 1 ? '#' + icon[1] : '');
} else {
if (svgIcon.length) {
var icon = /btn-[^\s]+/.exec(this.iconCls);
svgIcon.attr('href', icon ? '#' + icon[0]: '');
}
btnIconEl.removeClass(oldCls);
btnIconEl.addClass(cls || '');
if (this.options.scaling === false) {
btnIconEl.addClass('scaling-off');
}
}
},
changeIcon: function(opts) {
var me = this,
btnIconEl = $(this.el).find('i.icon');
if (btnIconEl.length > 1) btnIconEl = $(btnIconEl[0]);
if (opts && (opts.curr || opts.next) && btnIconEl) {
var svgIcon = $(this.el).find('.icon use.zoom-int');
if (opts.curr) {
btnIconEl.removeClass(opts.curr);
me.iconCls = me.iconCls.replace(opts.curr, '').trim();
}
if (opts.next) {
!btnIconEl.hasClass(opts.next) && (btnIconEl.addClass(opts.next));
(me.iconCls.indexOf(opts.next)<0) && (me.iconCls += ' ' + opts.next);
}
svgIcon.length && !!opts.next && svgIcon.attr('href', '#' + opts.next);
if ( !!me.options.signals ) {
if ( !(me.options.signals.indexOf('icon:changed') < 0) ) {
me.trigger('icon:changed', me, opts);
}
}
}
},
hasIcon: function(iconcls) {
return this.$icon.hasClass(iconcls);
},
setVisible: function(visible) {
if (this.cmpEl) this.cmpEl.toggleClass('hidden', !visible);
this.visible = visible;
if ( !!this.options.signals ) {
if ( !(this.options.signals.indexOf('visible') < 0) ) {
this.trigger('visible', this, visible);
}
}
},
isVisible: function() {
return (this.cmpEl) ? this.cmpEl.is(":visible") : $(this.el).is(":visible");
},
createHint: function(hint, isHtml) {
this.options.hint = hint;
if (!this.rendered) return;
var me = this,
cmpEl = this.cmpEl,
modalParents = cmpEl.closest('.asc-window'),
tipZIndex = modalParents.length > 0 ? parseInt(modalParents.css('z-index')) + 10 : undefined;
if (!this.btnEl) {
if (typeof this.options.hint == 'object' && this.options.hint.length>1 && $('button', cmpEl).length>0) {
var btnEl = $('button', cmpEl);
this.btnEl = $(btnEl[0]);
this.btnMenuEl = $(btnEl[1]);
} else {
this.btnEl = cmpEl;
}
}
var tip = this.btnEl.data('bs.tooltip');
tip && tip.updateTitle(typeof hint === 'string' ? hint : hint[0]);
if (this.btnMenuEl) {
tip = this.btnMenuEl.data('bs.tooltip');
tip && tip.updateTitle(hint[1]);
}
if (!this._isTooltipInited) {
if (this.delayRenderHint) {
this.btnEl.one('mouseenter', function(){ // hide tooltip when mouse is over menu
me.btnEl.tooltip({
html: !!isHtml,
title : (typeof me.options.hint == 'string') ? me.options.hint : me.options.hint[0],
placement : me.options.hintAnchor||'cursor',
zIndex : tipZIndex,
container : me.options.hintContainer
});
!Common.Utils.isGecko && (me.btnEl.data('bs.tooltip').enabled = !me.disabled);
me.btnEl.mouseenter();
});
this.btnMenuEl && this.btnMenuEl.one('mouseenter', function(){ // hide tooltip when mouse is over menu
me.btnMenuEl.tooltip({
html: !!isHtml,
title : me.options.hint[1],
placement : me.options.hintAnchor||'cursor',
zIndex : tipZIndex,
container : me.options.hintContainer
});
!Common.Utils.isGecko && (me.btnMenuEl.data('bs.tooltip').enabled = !me.disabled);
me.btnMenuEl.mouseenter();
});
} else {
this.btnEl.tooltip({
html: !!isHtml,
title : (typeof this.options.hint == 'string') ? this.options.hint : this.options.hint[0],
placement : this.options.hintAnchor||'cursor',
zIndex : tipZIndex,
container : this.options.hintContainer
});
this.btnMenuEl && this.btnMenuEl.tooltip({
html: !!isHtml,
title : this.options.hint[1],
placement : this.options.hintAnchor||'cursor',
zIndex : tipZIndex,
container : this.options.hintContainer
});
}
if (modalParents.length > 0) {
var onModalClose = function(dlg) {
if (modalParents[0] !== dlg.$window[0]) return;
var tip = me.btnEl.data('bs.tooltip');
if (tip) {
if (tip.dontShow===undefined)
tip.dontShow = true;
tip.hide();
}
if (me.btnMenuEl) {
tip = me.btnMenuEl.data('bs.tooltip');
if (tip) {
if (tip.dontShow===undefined)
tip.dontShow = true;
tip.hide();
}
}
Common.NotificationCenter.off({'modal:close': onModalClose});
};
Common.NotificationCenter.on({'modal:close': onModalClose});
}
this._isTooltipInited = true;
}
},
updateHint: function(hint, isHtml) {
this.options.hint = hint;
this.hint = hint;
if (!this.rendered) return;
this.createHint(hint, isHtml);
if (this.disabled || !Common.Utils.isGecko) {
var tip = this.btnEl.data('bs.tooltip');
if (tip) {
this.disabled && tip.hide();
!Common.Utils.isGecko && (tip.enabled = !this.disabled);
}
if (this.btnMenuEl) {
tip = this.btnMenuEl.data('bs.tooltip');
if (tip) {
this.disabled && tip.hide();
!Common.Utils.isGecko && (tip.enabled = !this.disabled);
}
}
}
if (!this.caption) {
var cmpEl = this.cmpEl,
$btn = $('button', cmpEl).length>0 ? $('button', cmpEl) : cmpEl;
$btn.attr('aria-label', (typeof hint == 'string') ? hint : hint[0]);
}
},
setCaption: function(caption) {
if (this.caption != caption) {
var isHuge = false;
if ( /icon-top/.test(this.options.cls) && !!this.caption && /huge/.test(this.options.cls) ) {
var newCaption = this.getCaptionWithBreaks(caption);
this.caption = newCaption || caption;
isHuge = true;
} else
this.caption = caption;
if (this.rendered) {
var captionNode = this.cmpEl.find('.caption');
if (captionNode.length > 0) {
captionNode.html(isHuge && (this.split || this.menu) ? _.template(templateBtnCaption)({caption: this.caption}) : this.caption);
} else {
this.cmpEl.find('button:first').addBack().filter('button').html(this.caption);
}
}
}
},
setMenu: function (m) {
if (m && _.isObject(m) && _.isFunction(m.render)){
this.menu = m;
if (this.rendered) {
this.menu.render(this.cmpEl);
this.options.canFocused && this.attachKeyEvents();
}
this.trigger('menu:created', this);
}
},
attachKeyEvents: function() {
var me = this;
if (me.menu && me.menu.rendered && me.cmpEl) {
var btnEl = $('button', me.cmpEl);
!me.split && btnEl.addClass('move-focus');
me.menu.on('keydown:before', function(menu, e) {
if ((e.keyCode === Common.UI.Keys.DOWN || e.keyCode === Common.UI.Keys.SPACE) && !me.isMenuOpen()) {
$(btnEl[me.split ? 1 : 0]).click();
e.preventDefault();
e.stopPropagation();
return false;
}
});
me.options.takeFocusOnClose && me.menu.on('hide:after', function() {
setTimeout(function(){me.focus();}, 1);
});
}
},
applyScaling: function (ratio) {
const me = this;
if ( me.options.scaling != ratio ) {
// me.cmpEl.attr('ratio', ratio);
me.options.scaling = ratio;
if (ratio > 2) {
const $el = me.$el.is('button') ? me.$el : me.$el.find('button:first');
if (!$el.find('svg.icon').length) {
const iconCls = me.iconCls || $el.find('i.icon').attr('class');
const re_icon_name = /btn-[^\s]+/.exec(iconCls);
const icon_name = re_icon_name ? re_icon_name[0] : "null";
const rtlCls = (iconCls ? iconCls.indexOf('icon-rtl') : -1) > -1 ? 'icon-rtl' : '';
const svg_icon = '<svg class="icon %rtlCls"><use class="zoom-int" href="#%iconname"></use></svg>'.replace('%iconname', icon_name).replace('%rtlCls', rtlCls);
$el.find('i.icon').after(svg_icon);
}
} else {
if (!me.$el.find('i.icon')) {
const png_icon = '<i class="icon %cls">&nbsp;</i>'.replace('%cls', me.iconCls);
me.$el.find('svg.icon').after(png_icon);
}
}
}
},
isMenuOpen: function() {
return this.cmpEl && this.cmpEl.hasClass('open');
},
focus: function() {
this.split ? this.cmpEl.focus() : this.$el && this.$el.find('button').addBack().filter('button').focus();
},
setTabIndex: function(tabindex) {
if (!this.rendered)
return;
this.tabindex = tabindex.toString();
if (!this.disabled) {
this.split ? this.cmpEl.attr('tabindex', this.tabindex) : this.$el && this.$el.find('button').addBack().filter('button').attr('tabindex', this.tabindex);
}
},
onThemeChanged: function() {
if (!this.rendered) return;
var el = this.cmpEl;
if (this.options.width>0) {
el && el.hasClass('btn-group') && el.hasClass('split') && $('button:first', el).css('width', this.options.width - $('[data-toggle^=dropdown]', el).outerWidth());
} else if (el && this.caption && /icon-top/.test(this.options.cls) && /huge/.test(this.options.cls)) { // recalc captions of huge button
var captionNode = el.find('.caption');
if (captionNode.length > 0) {
captionNode.html((this.split || this.menu) ? _.template(templateBtnCaption)({caption: this.caption}) : this.caption);
}
}
}
});
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.baseUrl = options.baseUrl || '';
this.iconsSet = Common.UI.iconsStr2IconsObj(options.iconsSet || ['']);
var icons = Common.UI.getSuitableIcons(this.iconsSet);
this.iconNormalImg = this.baseUrl + icons['normal'];
this.iconActiveImg = this.baseUrl + 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'],
});
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));
if (this.cmpEl && this.options.customAttributes) {
for (var key in this.options.customAttributes) {
if (Object.prototype.hasOwnProperty.call(this.options.customAttributes, key)) {
this.cmpEl.attr(Common.Utils.String.htmlEncode(key), Common.Utils.String.htmlEncode(this.options.customAttributes[key]));
}
}
}
},
updateIcons: function() {
var icons = Common.UI.getSuitableIcons(this.iconsSet);
this.iconNormalImg = this.baseUrl + icons['normal'];
this.iconActiveImg = this.baseUrl + 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 || {}));
Common.UI.GroupedButtons = function (buttons, opts) {
let _buttons = buttons,
_parent = buttons && buttons.length>0 && buttons[0].cmpEl ? buttons[0].cmpEl.parent() : null;
_parent.addClass('grouped-buttons');
if (opts) {
opts.underline && _parent.addClass('underline');
opts.flat && _parent.addClass('flat');
}
let _update = function() {
let first, last;
_buttons && _buttons.forEach(function(item) {
if (!first && item.isVisible()) {
first = true;
item.cmpEl.addClass('first');
} else
item.cmpEl.removeClass('first');
item.cmpEl.removeClass('last');
item.isVisible() && (last = item);
});
last && last.cmpEl.addClass('last');
};
let _init = function() {
_buttons && _buttons.forEach(function(item) {
item.options.signals = item.options.signals || [];
item.options.signals.push('visible');
item.on('visible', _update);
});
};
_init();
_update();
return {
update: _update
}
};
});