You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
300 lines
7.8 KiB
300 lines
7.8 KiB
1 year ago
|
/*
|
||
|
** Zabbix
|
||
|
** Copyright (C) 2001-2023 Zabbix SIA
|
||
|
**
|
||
|
** This program is free software; you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation; either version 2 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program; if not, write to the Free Software
|
||
|
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
**/
|
||
|
|
||
|
|
||
|
(function($) {
|
||
|
'use strict';
|
||
|
|
||
|
function updateProperties(obj, $elm) {
|
||
|
obj.$hidden.prop('disabled', obj.options.disabled ? true : null);
|
||
|
obj.$input
|
||
|
.prop('disabled', obj.options.disabled ? true : null)
|
||
|
.prop('readonly', obj.options.disabled ? null : true)
|
||
|
.prop('title', obj.options.disabled ? '' : obj.options.hint);
|
||
|
obj.$button
|
||
|
.prop('disabled', obj.options.disabled ? true : null)
|
||
|
.prop('title', obj.options.disabled ? '' : obj.options.hint);
|
||
|
|
||
|
$elm
|
||
|
.toggleClass('multilineinput-readonly', (obj.options.readonly && !obj.options.disabled))
|
||
|
.toggleClass('multilineinput-disabled', obj.options.disabled);
|
||
|
}
|
||
|
|
||
|
function setDisabled(e) {
|
||
|
if ($(this)[0] !== e.target) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var obj = e.data,
|
||
|
$elm = $(this);
|
||
|
|
||
|
obj.options.disabled = (e.type === 'disable');
|
||
|
updateProperties(obj, $elm);
|
||
|
}
|
||
|
|
||
|
function setReadOnly(e) {
|
||
|
if ($(this)[0] !== e.target) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var obj = e.data,
|
||
|
$elm = $(this);
|
||
|
|
||
|
obj.options.readonly = (e.type === 'readonly');
|
||
|
updateProperties(obj, $elm);
|
||
|
}
|
||
|
|
||
|
function openModal(e) {
|
||
|
e.preventDefault();
|
||
|
|
||
|
var obj = e.data;
|
||
|
|
||
|
if (obj.options.disabled) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
function updateCharCount(count) {
|
||
|
$('span', $footer).text(count);
|
||
|
}
|
||
|
|
||
|
function updateLineNumbers(lines_count) {
|
||
|
var min_rows = 3,
|
||
|
line_height = 18,
|
||
|
diff = lines_count - $line_numbers[0].childElementCount,
|
||
|
li = '';
|
||
|
|
||
|
switch (obj.options.grow) {
|
||
|
case 'fixed':
|
||
|
$content.height(obj.options.rows * line_height + 2);
|
||
|
break;
|
||
|
case 'auto':
|
||
|
var rows = Math.max(min_rows, lines_count);
|
||
|
rows = obj.options.rows == 0 ? rows : Math.min(rows, obj.options.rows)
|
||
|
$content.height(rows * line_height + 2);
|
||
|
break;
|
||
|
default:
|
||
|
$content.height($content.css('max-height'));
|
||
|
}
|
||
|
|
||
|
while (diff > 0) {
|
||
|
li += '<li></li>';
|
||
|
diff--;
|
||
|
}
|
||
|
$line_numbers.append(li);
|
||
|
|
||
|
while (diff < 0) {
|
||
|
$line_numbers.find('li:eq(0)').remove();
|
||
|
diff++;
|
||
|
}
|
||
|
|
||
|
$line_numbers.css('top', -Math.floor($textarea.prop('scrollTop') - 1));
|
||
|
$textarea.css('margin-left', $line_numbers.outerWidth());
|
||
|
}
|
||
|
|
||
|
var height_offset = 190,
|
||
|
$content = $('<div>', {class: 'multilineinput-container'}),
|
||
|
monospace_font = obj.options.monospace_font ? ' monospace-font' : '',
|
||
|
$textarea = $('<textarea>', {
|
||
|
class: 'multilineinput-textarea' + monospace_font,
|
||
|
text: obj.$hidden.val(),
|
||
|
readonly: obj.options.readonly ? true : null,
|
||
|
placeholder: obj.options.placeholder_textarea,
|
||
|
spellcheck: false
|
||
|
}).attr('wrap', 'off'),
|
||
|
$line_numbers = $('<ul>', {class: 'multilineinput-line-numbers' + monospace_font}).append('<li>'),
|
||
|
$footer = $('<div>', {class: 'multilineinput-char-count'});
|
||
|
|
||
|
if ('maxlength' in obj.options) {
|
||
|
$textarea.attr('maxlength', obj.options.maxlength);
|
||
|
$footer.html(sprintf(t('S_N_CHAR_COUNT_REMAINING'), '<span>0</span>'));
|
||
|
}
|
||
|
else {
|
||
|
$footer.html(sprintf(t('S_N_CHAR_COUNT'), '<span>0</span>'));
|
||
|
}
|
||
|
|
||
|
overlayDialogue({
|
||
|
'title': obj.options.title,
|
||
|
'class': 'modal-popup multilineinput-modal',
|
||
|
'content': $content,
|
||
|
'footer': $footer,
|
||
|
'buttons': [
|
||
|
{
|
||
|
title: t('S_APPLY'),
|
||
|
action: function() {
|
||
|
obj.$node.multilineInput('value', $textarea.val());
|
||
|
},
|
||
|
enabled: !obj.options.readonly
|
||
|
},
|
||
|
{
|
||
|
title: t('S_CANCEL'),
|
||
|
class: 'btn-alt',
|
||
|
action: function() {}
|
||
|
}
|
||
|
]
|
||
|
}, obj.$button);
|
||
|
|
||
|
if (obj.options.label_before.length) {
|
||
|
height_offset += $('<div>', {class: 'multilineinput-label' + monospace_font})
|
||
|
.html(obj.options.label_before)
|
||
|
.insertBefore($content)
|
||
|
.height();
|
||
|
}
|
||
|
|
||
|
if (obj.options.label_after.length) {
|
||
|
height_offset += $('<div>', {class: 'multilineinput-label' + monospace_font})
|
||
|
.html(obj.options.label_after)
|
||
|
.insertAfter($content)
|
||
|
.height();
|
||
|
}
|
||
|
|
||
|
$content
|
||
|
.append(obj.options.line_numbers ? $line_numbers : '', $textarea)
|
||
|
.css('max-height', 'calc(100vh - ' + (height_offset + 2) + 'px)');
|
||
|
|
||
|
$textarea[0].setSelectionRange(0, 0);
|
||
|
|
||
|
$textarea
|
||
|
.on('change contextmenu keydown keyup paste scroll', function() {
|
||
|
var value = $(this).val();
|
||
|
|
||
|
updateCharCount(('maxlength' in obj.options) ? obj.options.maxlength - value.length : value.length);
|
||
|
|
||
|
if (obj.options.line_numbers) {
|
||
|
updateLineNumbers(value.split("\n").length);
|
||
|
}
|
||
|
})
|
||
|
.trigger('change')
|
||
|
.focus();
|
||
|
}
|
||
|
|
||
|
var methods = {
|
||
|
init: function(options) {
|
||
|
return this.each(function() {
|
||
|
var $this = $(this),
|
||
|
obj = {
|
||
|
$node: $this,
|
||
|
options: $.extend({
|
||
|
title: '',
|
||
|
hint: t('S_CLICK_TO_VIEW_OR_EDIT'),
|
||
|
value: '',
|
||
|
placeholder: '',
|
||
|
placeholder_textarea: '',
|
||
|
label_before: '',
|
||
|
label_after: '',
|
||
|
rows: 20,
|
||
|
grow: 'fixed',
|
||
|
readonly: false,
|
||
|
disabled: false,
|
||
|
autofocus: false,
|
||
|
line_numbers: true,
|
||
|
monospace_font: true
|
||
|
}, options)
|
||
|
};
|
||
|
|
||
|
obj.$hidden = $('<input>', {
|
||
|
type: 'hidden',
|
||
|
name: $this.data('name')
|
||
|
});
|
||
|
|
||
|
obj.$input = $('<input>', {
|
||
|
type: 'text',
|
||
|
placeholder: obj.options.placeholder,
|
||
|
title: obj.options.hint,
|
||
|
tabindex: -1
|
||
|
})
|
||
|
.toggleClass('monospace-font', obj.options.monospace_font)
|
||
|
.prop('readonly', obj.options.disabled ? null : true)
|
||
|
.on('mousedown', obj, openModal);
|
||
|
|
||
|
obj.$button = $('<button>', {
|
||
|
class: ZBX_ICON_PENCIL,
|
||
|
type: 'button',
|
||
|
title: obj.options.hint,
|
||
|
autofocus: obj.options.autofocus || null
|
||
|
}).on('click', obj, openModal);
|
||
|
|
||
|
$this
|
||
|
.data('multilineInput', obj)
|
||
|
.append(obj.$hidden, obj.$input, obj.$button)
|
||
|
.on('disable enable', obj, setDisabled)
|
||
|
.on('readonly readwrite', obj, setReadOnly)
|
||
|
.trigger(obj.options.disabled ? 'disable' : 'enable');
|
||
|
|
||
|
methods.value.call($this, obj.options.value);
|
||
|
});
|
||
|
},
|
||
|
/**
|
||
|
* @param {string|undefined} value Set field value. Without parameter - get field value
|
||
|
*
|
||
|
* @returns {string|object}
|
||
|
*/
|
||
|
value: function(value) {
|
||
|
if (typeof value === 'undefined') {
|
||
|
return this.data('multilineInput').$hidden.val();
|
||
|
}
|
||
|
else {
|
||
|
return this.each(function() {
|
||
|
var $this = $(this),
|
||
|
obj = $this.data('multilineInput'),
|
||
|
value_lines = $.trim(value).split("\n");
|
||
|
|
||
|
obj.$hidden.val(value);
|
||
|
obj.$input.val(value_lines.length > 1
|
||
|
? value_lines[0] + String.fromCharCode(8230) // U+2026 Horizontal ellipsis character.
|
||
|
: value_lines[0]
|
||
|
);
|
||
|
$this.trigger('change');
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
disable: function() {
|
||
|
return this.each(function() {
|
||
|
$(this).trigger('disable');
|
||
|
});
|
||
|
},
|
||
|
enable: function() {
|
||
|
return this.each(function() {
|
||
|
$(this).trigger('enable');
|
||
|
});
|
||
|
},
|
||
|
setReadOnly: function() {
|
||
|
return this.each(function() {
|
||
|
$(this).trigger('readonly');
|
||
|
});
|
||
|
},
|
||
|
unsetReadOnly: function() {
|
||
|
return this.each(function() {
|
||
|
$(this).trigger('readwrite');
|
||
|
});
|
||
|
},
|
||
|
destroy: function() {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Multiline input helper.
|
||
|
*/
|
||
|
$.fn.multilineInput = function(method) {
|
||
|
if (methods[method]) {
|
||
|
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
||
|
}
|
||
|
|
||
|
return methods.init.apply(this, arguments);
|
||
|
};
|
||
|
})(jQuery);
|