', {'class': 'ui-resizable-border-' + key}));
}
node.append(handle);
handles[key] = handle;
});
node.addClass('ui-inner-handles');
node.resizable({
handles: handles,
autoHide: true,
stop: $.proxy(function(event, data) {
this.updatePosition({
x: parseInt(data.position.left, 10),
y: parseInt(data.position.top, 10)
});
}, this)
});
}
else {
node.removeClass('ui-inner-handles');
node.resizable("destroy");
}
},
/**
* Toggle shape selection.
*
* @param {bool} state
*/
toggleSelect: function(state) {
state = state || !this.selected;
this.selected = state;
if (this.selected) {
this.domNode.addClass('map-element-selected');
}
else {
this.domNode.removeClass('map-element-selected');
}
return this.selected;
},
/**
* Align shape to map or map grid.
*
* @param {bool} doAutoAlign if we should align element to grid
*/
align: function(doAutoAlign) {
var dims = {
height: this.domNode.height(),
width: this.domNode.width()
},
dimensions = this.getDimensions(),
x = dimensions.x,
y = dimensions.y,
shiftX = Math.round(dims.width / 2),
shiftY = Math.round(dims.height / 2),
newX = x,
newY = y,
newWidth = dims.width,
newHeight = dims.height,
gridSize = parseInt(this.sysmap.data.grid_size, 10);
// Lines should not be aligned
if (this instanceof Shape && this.data.type == SVGMapShape.TYPE_LINE) {
this.domNode.css({
top: dimensions.y + 'px',
left: dimensions.x + 'px',
width: dimensions.width + 'px',
height: dimensions.height + 'px'
});
return;
}
// if 'fit to map' area coords are 0 always
if (this.data.elementsubtype === '1' && this.data.areatype === '0'
&& this.data.elementtype === '3') {
newX = 0;
newY = 0;
}
// if autoalign is off
else if (doAutoAlign === false
|| (typeof doAutoAlign === 'undefined' && this.sysmap.data.grid_align == '0')) {
if ((x + dims.width) > this.sysmap.data.width) {
newX = this.sysmap.data.width - dims.width;
}
if ((y + dims.height) > this.sysmap.data.height) {
newY = this.sysmap.data.height - dims.height;
}
if (newX < 0) {
newX = 0;
newWidth = this.sysmap.data.width;
}
if (newY < 0) {
newY = 0;
newHeight = this.sysmap.data.height;
}
}
else {
newX = x + shiftX;
newY = y + shiftY;
newX = Math.floor(newX / gridSize) * gridSize;
newY = Math.floor(newY / gridSize) * gridSize;
newX += Math.round(gridSize / 2) - shiftX;
newY += Math.round(gridSize / 2) - shiftY;
while ((newX + dims.width) > this.sysmap.data.width) {
newX -= gridSize;
}
while ((newY + dims.height) > this.sysmap.data.height) {
newY -= gridSize;
}
while (newX < 0) {
newX += gridSize;
}
while (newY < 0) {
newY += gridSize;
}
}
this.data.y = newY;
this.data.x = newX;
if (this instanceof Shape || this.data.elementsubtype === '1') {
this.data.width = newWidth;
this.data.height = newHeight;
}
this.domNode.css({
top: this.data.y + 'px',
left: this.data.x + 'px',
width: newWidth,
height: newHeight
});
},
/**
* Updates element position.
*
* @param {object} coords
*/
updatePosition: function(coords, invalidate) {
if (this instanceof Shape && this.data.type == SVGMapShape.TYPE_LINE) {
var dx = coords.x - Math.min(parseInt(this.data.x, 10), parseInt(this.data.width, 10)),
dy = coords.y - Math.min(parseInt(this.data.y, 10), parseInt(this.data.height, 10));
this.data.x = parseInt(this.data.x, 10) + dx;
this.data.y = parseInt(this.data.y, 10) + dy;
this.data.width = parseInt(this.data.width, 10) + dx;
this.data.height = parseInt(this.data.height, 10) + dy;
this.updateHandles();
}
else {
this.data.x = coords.x;
this.data.y = coords.y;
}
if (invalidate !== false) {
this.align();
this.trigger('afterMove', this);
}
else {
var dimensions = this.getDimensions();
this.domNode.css({
top: dimensions.y + 'px',
left: dimensions.x + 'px'
});
}
},
/**
* Removes Shape object, delete all reference to it.
*/
remove: function() {
this.makeDraggable(false);
this.domNode.remove();
delete this.sysmap.data.shapes[this.id];
delete this.sysmap.shapes[this.id];
if (typeof this.sysmap.selection.shapes[this.id] !== 'undefined') {
this.sysmap.selection.count.shapes--;
}
delete this.sysmap.selection.shapes[this.id];
},
/**
* Gets Shape data.
*
* @returns {Object}
*/
getData: function() {
return this.data;
}
};
Observer.makeObserver(Shape.prototype);
/**
* @class Creates a new Selement.
*
* @property {object} sysmap reference to Map object
* @property {object} data selement db values
* @property {bool} selected if element is now selected by user
* @property {string} id elementid
* @property {object} domNode reference to related DOM element
*
* @param {object} sysmap reference to Map object
* @param {object} selementData element db values
*/
function Selement(sysmap, selementData) {
this.sysmap = sysmap;
this.selected = false;
if (!selementData) {
selementData = {
selementid: getUniqueId(),
elementtype: '4', // image
elements: {},
iconid_off: this.sysmap.defaultIconId, // first imageid
label: t('S_NEW_ELEMENT'),
label_location: -1, // set default map label location
x: 0,
y: 0,
urls: {},
elementName: this.sysmap.defaultIconName, // first image name
use_iconmap: '1',
evaltype: 0, // TAG_EVAL_TYPE_AND_OR
tags: [],
inherited_label: null
};
}
else {
if ($.isArray(selementData.urls)) {
selementData.urls = {};
}
}
this.data = selementData;
this.updateLabel();
this.id = this.data.selementid;
this.expanded = this.data.expanded;
delete this.data.expanded;
// assign by reference
this.sysmap.data.selements[this.id] = this.data;
// create dom
this.domNode = $('
', {style: 'position: absolute; z-index: 100'})
.appendTo(this.sysmap.container)
.addClass('cursor-pointer sysmap_element')
.attr('data-id', this.id)
.attr('data-type', 'selements');
this.makeDraggable(true);
this.makeResizable(this.data.elementtype == 3 && this.data.elementsubtype == 1 && this.data.areatype == 1);
this.updateIcon();
this.domNode.css({
top: this.data.y + 'px',
left: this.data.x + 'px'
});
}
Selement.TYPE_HOST = 0; // SYSMAP_ELEMENT_TYPE_HOST
Selement.TYPE_MAP = 1; // SYSMAP_ELEMENT_TYPE_MAP
Selement.TYPE_TRIGGER = 2; // SYSMAP_ELEMENT_TYPE_TRIGGER
Selement.TYPE_HOST_GROUP = 3; // SYSMAP_ELEMENT_TYPE_HOST_GROUP
Selement.TYPE_IMAGE = 4; // SYSMAP_ELEMENT_TYPE_IMAGE
Selement.prototype = {
/**
* Returns element data.
*/
getData: Shape.prototype.getData,
/**
* Allows dragging of element
*/
makeDraggable: Shape.prototype.makeDraggable,
/**
* Allows resizing of element
*/
makeResizable: Shape.prototype.makeResizable,
/**
* Update label data inherited from map configuration.
*/
updateLabel: function () {
if (this.sysmap.data.label_format != 0) {
switch (parseInt(this.data.elementtype, 10)) {
case Selement.TYPE_HOST_GROUP:
this.data.label_type = this.sysmap.data.label_type_hostgroup;
if (this.data.label_type == CMap.LABEL_TYPE_CUSTOM) {
this.data.inherited_label = this.sysmap.data.label_string_hostgroup;
}
break;
case Selement.TYPE_HOST:
this.data.label_type = this.sysmap.data.label_type_host;
if (this.data.label_type == CMap.LABEL_TYPE_CUSTOM) {
this.data.inherited_label = this.sysmap.data.label_string_host;
}
break;
case Selement.TYPE_TRIGGER:
this.data.label_type = this.sysmap.data.label_type_trigger;
if (this.data.label_type == CMap.LABEL_TYPE_CUSTOM) {
this.data.inherited_label = this.sysmap.data.label_string_trigger;
}
break;
case Selement.TYPE_MAP:
this.data.label_type = this.sysmap.data.label_type_map;
if (this.data.label_type == CMap.LABEL_TYPE_CUSTOM) {
this.data.inherited_label = this.sysmap.data.label_string_map;
}
break;
case Selement.TYPE_IMAGE:
this.data.label_type = this.sysmap.data.label_type_image;
if (this.data.label_type == CMap.LABEL_TYPE_CUSTOM) {
this.data.inherited_label = this.sysmap.data.label_string_image;
}
break;
}
}
else {
this.data.label_type = this.sysmap.data.label_type;
this.data.inherited_label = null;
}
if (this.data.label_type == CMap.LABEL_TYPE_LABEL) {
this.data.inherited_label = this.data.label;
}
else if (this.data.label_type == CMap.LABEL_TYPE_NAME) {
if (this.data.elementtype != Selement.TYPE_IMAGE) {
this.data.inherited_label = this.data.elements[0].elementName;
}
else {
this.data.inherited_label = t('S_IMAGE');
}
}
if (this.data.label_type != CMap.LABEL_TYPE_CUSTOM && this.data.label_type != CMap.LABEL_TYPE_LABEL
&& this.data.label_type != CMap.LABEL_TYPE_IP) {
this.data.expanded = null;
}
else if (this.data.label_type == CMap.LABEL_TYPE_IP && this.data.elementtype == Selement.TYPE_HOST) {
this.data.inherited_label = '{HOST.IP}';
}
},
/**
* Return label based on map constructor configuration.
*
* @param {boolean} return label with expanded macros.
*
* @returns {string} or null
*/
getLabel: function (expand) {
var label = this.data.label;
if (typeof(expand) === 'undefined') {
expand = true;
}
if (this.data.label_type != CMap.LABEL_TYPE_NOTHING && this.data.label_type != CMap.LABEL_TYPE_STATUS) {
if (expand && typeof(this.expanded) === 'string' && (this.sysmap.data.expand_macros === '1'
|| (this.data.label_type == CMap.LABEL_TYPE_IP
&& this.data.elementtype == Selement.TYPE_HOST))) {
label = this.expanded;
}
else if (typeof this.data.inherited_label === 'string') {
label = this.data.inherited_label;
}
}
else {
label = null;
}
return label;
},
/**
* Updates element fields.
*
* @param {object} data
* @param {bool} unsetUndefined If true, all fields that are not in data parameter will be removed
* from element.
*/
update: function(data, unsetUndefined) {
var fieldName,
dataFelds = ['elementtype', 'elements', 'iconid_off', 'iconid_on', 'iconid_maintenance',
'iconid_disabled', 'label', 'label_location', 'x', 'y', 'elementsubtype', 'areatype', 'width',
'height', 'viewtype', 'urls', 'elementName', 'use_iconmap', 'evaltype', 'tags'
],
fieldsUnsettable = ['iconid_off', 'iconid_on', 'iconid_maintenance', 'iconid_disabled'],
i,
ln,
invalidate = ((typeof(data.label) !== 'undefined' && this.data.label !== data.label)
|| (typeof(data.elementtype) !== 'undefined' && this.data.elementtype !== data.elementtype)
|| (typeof(data.elements) !== 'undefined'
&& Object.keys(this.data.elements).length !== Object.keys(data.elements).length));
unsetUndefined = unsetUndefined || false;
if (!invalidate && typeof(data.elements) !== 'undefined') {
var k,
id,
key,
kln,
keys,
ids = Object.keys(this.data.elements);
for (i = 0, ln = ids.length; i < ln && !invalidate; i++) {
id = ids[i];
keys = Object.keys(this.data.elements[id]);
for (k = 0, kln = keys.length; k < kln; k++) {
key = keys[k];
if (this.data.elements[id][key] !== data.elements[id][key]) {
invalidate = true;
break;
}
}
}
}
// update elements fields, if not massupdate, remove fields that are not in new values
for (i = 0, ln = dataFelds.length; i < ln; i++) {
fieldName = dataFelds[i];
if (typeof data[fieldName] !== 'undefined') {
this.data[fieldName] = data[fieldName];
}
else if (unsetUndefined && (fieldsUnsettable.indexOf(fieldName) === -1)) {
delete this.data[fieldName];
}
}
// if elementsubtype is not set, it should be 0
if (unsetUndefined && typeof this.data.elementsubtype === 'undefined') {
this.data.elementsubtype = '0';
}
if (unsetUndefined && typeof this.data.use_iconmap === 'undefined') {
this.data.use_iconmap = '0';
}
this.makeResizable(
this.data.elementtype == 3 && this.data.elementsubtype == 1 && this.data.areatype == 1
);
if (this.data.elementtype === '2') {
// For element type trigger not exist single element name.
delete this.data['elementName'];
}
else if (this.data.elementtype === '4') {
// If element is image, unset advanced icons.
this.data.iconid_on = '0';
this.data.iconid_maintenance = '0';
this.data.iconid_disabled = '0';
// If image element, set elementName to image name.
for (i in this.sysmap.iconList) {
if (this.sysmap.iconList[i].imageid === this.data.iconid_off) {
this.data.elementName = this.sysmap.iconList[i].name;
}
}
}
else {
this.data.elementName = this.data.elements[0].elementName;
}
this.updateLabel();
this.updateIcon();
this.align(false);
this.trigger('afterMove', this);
if (invalidate) {
this.sysmap.expandMacros(this);
}
},
/**
* Updates element position.
*
* @param {object} coords
*/
updatePosition: Shape.prototype.updatePosition,
/**
* Remove element.
*/
remove: function() {
this.domNode.remove();
delete this.sysmap.data.selements[this.id];
delete this.sysmap.selements[this.id];
if (typeof this.sysmap.selection.selements[this.id] !== 'undefined') {
this.sysmap.selection.count.selements--;
}
delete this.sysmap.selection.selements[this.id];
},
/**
* Toggle element selection.
*
* @param {bool} state
*/
toggleSelect: Shape.prototype.toggleSelect,
/**
* Align element to map or map grid.
*
* @param {bool} doAutoAlign if we should align element to grid
*/
align: Shape.prototype.align,
/**
* Get element dimensions.
*/
getDimensions: Shape.prototype.getDimensions,
/**
* Updates element icon and height/width in case element is area type.
*/
updateIcon: function() {
var oldIconClass = this.domNode.get(0).className.match(/sysmap_iconid_\d+/);
if (oldIconClass !== null) {
this.domNode.removeClass(oldIconClass[0]);
}
if ((this.data.use_iconmap === '1' && this.sysmap.data.iconmapid !== '0')
&& (this.data.elementtype === '0'
|| (this.data.elementtype === '3' && this.data.elementsubtype === '1'))) {
this.domNode.addClass('sysmap_iconid_' + this.sysmap.defaultAutoIconId);
}
else {
this.domNode.addClass('sysmap_iconid_' + this.data.iconid_off);
}
if (this.data.elementtype === '3' && this.data.elementsubtype === '1') {
if (this.data.areatype === '1') {
this.domNode
.css({
width: this.data.width + 'px',
height: this.data.height + 'px'
})
.addClass('map-element-area-bg');
}
else {
this.domNode
.css({
width: this.sysmap.data.width + 'px',
height: this.sysmap.data.height + 'px'
})
.addClass('map-element-area-bg');
}
}
else {
this.domNode
.css({
width: '',
height: ''
})
.removeClass('map-element-area-bg');
}
},
getName: function () {
var name;
if (typeof this.data.elementName === 'undefined') {
name = this.data.elements[0].elementName;
if (Object.keys(this.data.elements).length > 1) {
name += '...';
}
}
else {
name = this.data.elementName;
}
return name;
}
};
Observer.makeObserver(Selement.prototype);
/**
* Form for elements.
*
* @param {object} formContainer jQuery object
* @param {object} sysmap
*/
function SelementForm(formContainer, sysmap) {
var formTplData = {
sysmapid: sysmap.sysmapid
},
tpl = new Template($('#mapElementFormTpl').html()),
i,
icon,
formActions = [
{
action: 'show',
value: '#subtypeRow, #hostGroupSelectRow',
cond: [{
elementType: '3'
}]
},
{
action: 'show',
value: '#hostSelectRow',
cond: [{
elementType: '0'
}]
},
{
action: 'show',
value: '#triggerSelectRow, #triggerListRow',
cond: [{
elementType: '2'
}]
},
{
action: 'show',
value: '#mapSelectRow',
cond: [{
elementType: '1'
}]
},
{
action: 'show',
value: '#areaTypeRow, #areaPlacingRow',
cond: [{
elementType: '3',
subtypeHostGroupElements: 'checked'
}]
},
{
action: 'show',
value: '#areaSizeRow',
cond: [{
elementType: '3',
subtypeHostGroupElements: 'checked',
areaTypeCustom: 'checked'
}]
},
{
action: 'hide',
value: '#iconProblemRow, #iconMainetnanceRow, #iconDisabledRow',
cond: [{
elementType: '4'
}]
},
{
action: 'disable',
value: '#iconid_off, #iconid_on, #iconid_maintenance, #iconid_disabled',
cond: [
{
use_iconmap: 'checked',
elementType: '0'
},
{
use_iconmap: 'checked',
elementType: '3',
subtypeHostGroupElements: 'checked'
}
]
},
{
action: 'show',
value: '#useIconMapRow',
cond: [
{
elementType: '0'
},
{
elementType: '3',
subtypeHostGroupElements: 'checked'
}
]
},
{
action: 'show',
value: '#tags-select-row',
cond: [
{
elementType: '0'
},
{
elementType: '3'
}
]
}
];
this.active = false;
this.sysmap = sysmap;
this.formContainer = formContainer;
// create form
this.domNode = $(tpl.evaluate(formTplData)).appendTo(formContainer);
// populate icons selects
const select_icon_off = document.getElementById('iconid_off');
const select_icon_on = document.getElementById('iconid_on');
const select_icon_maintenance = document.getElementById('iconid_maintenance');
const select_icon_disabled = document.getElementById('iconid_disabled');
select_icon_on.addOption({label: t('S_DEFAULT'), value: '0', class_name: ZBX_STYLE_DEFAULT_OPTION});
select_icon_maintenance.addOption({label: t('S_DEFAULT'), value: '0', class_name: ZBX_STYLE_DEFAULT_OPTION});
select_icon_disabled.addOption({label: t('S_DEFAULT'), value: '0', class_name: ZBX_STYLE_DEFAULT_OPTION});
for (i in this.sysmap.iconList) {
icon = this.sysmap.iconList[i];
select_icon_off.addOption({label: icon.name, value: icon.imageid});
select_icon_on.addOption({label: icon.name, value: icon.imageid});
select_icon_maintenance.addOption({label: icon.name, value: icon.imageid});
select_icon_disabled.addOption({label: icon.name, value: icon.imageid});
}
// hosts
$('#elementNameHost').multiSelectHelper({
id: 'elementNameHost',
object_name: 'hosts',
name: 'elementValue',
selectedLimit: 1,
popup: {
parameters: {
srctbl: 'hosts',
srcfld1: 'hostid',
dstfrm: 'selementForm',
dstfld1: 'elementNameHost'
}
}
});
// map
$('#elementNameMap').multiSelectHelper({
id: 'elementNameMap',
object_name: 'sysmaps',
name: 'elementValue',
selectedLimit: 1,
popup: {
parameters: {
srctbl: 'sysmaps',
srcfld1: 'sysmapid',
dstfrm: 'selementForm',
dstfld1: 'elementNameMap'
}
}
});
// triggers
$('#elementNameTriggers').multiSelectHelper({
id: 'elementNameTriggers',
object_name: 'triggers',
name: 'elementValue',
objectOptions: {
real_hosts: true
},
popup: {
parameters: {
srctbl: 'triggers',
srcfld1: 'triggerid',
dstfrm: 'selementForm',
dstfld1: 'elementNameTriggers',
with_triggers: '1',
real_hosts: '1',
multiselect: '1'
}
}
});
// host group
$('#elementNameHostGroup').multiSelectHelper({
id: 'elementNameHostGroup',
object_name: 'hostGroup',
name: 'elementValue',
selectedLimit: 1,
popup: {
parameters: {
srctbl: 'host_groups',
srcfld1: 'groupid',
dstfrm: 'selementForm',
dstfld1: 'elementNameHostGroup'
}
}
});
this.actionProcessor = new ActionProcessor(formActions);
this.actionProcessor.process();
}
SelementForm.prototype = {
/**
* Shows element form.
*/
show: function() {
this.formContainer.draggable('option', 'handle', '#formDragHandler');
this.formContainer.show();
this.domNode.show();
// Element must first be visible so that outerWidth() and outerHeight() are correct.
this.formContainer.positionOverlayDialogue();
this.active = true;
},
/**
* Hides element form.
*/
hide: function() {
this.domNode.toggle(false);
this.active = false;
},
/**
* Adds element urls to form.
*
* @param {object} urls
*/
addUrls: function(urls) {
var tpl = new Template($('#selementFormUrls').html()),
i,
url;
if (typeof urls === 'undefined' || $.isEmptyObject(urls)) {
urls = {empty: {}};
}
for (i in urls) {
url = urls[i];
// generate unique urlid
url.selementurlid = $('#urlContainer tbody tr[id^=urlrow]').length;
while ($('#urlrow_' + url.selementurlid).length) {
url.selementurlid++;
}
$(tpl.evaluate(url)).appendTo('#urlContainer tbody');
}
},
/**
* Append form tag field options.
*
* @param {array} tags
*/
addTags: function(tags) {
var tpl = new Template($('#tag-row-tmpl').html()),
$add_btn_row = $('#selement-tags .element-table-add').closest('tr'),
counter = $('#selement-tags').data('dynamicRows').counter;
for (const i in tags) {
var tag = jQuery.extend({tag: '', operator: 0, value: '', rowNum: ++counter}, tags[i]),
row = $(tpl.evaluate(tag));
row.insertBefore($add_btn_row);
row
.find('[name="tags[' + tag.rowNum + '][tag]"]')
.val(tag.tag);
row
.find('[name="tags[' + tag.rowNum + '][operator]"]')
.val(tag.operator);
row
.find('[name="tags[' + tag.rowNum + '][value]"]')
.val(tag.value);
new CTagFilterItem(row[0]);
}
$('#selement-tags').data('dynamicRows').counter = counter;
},
/**
* Set evaltype field value.
*
* @param {integer} value
*/
setEvaltype: function(value) {
$('#operator [name="evaltype"][value='+value+']').prop('checked', true);
},
/**
* Add triggers to the list.
*/
addTriggers: function(triggers) {
var tpl = new Template($('#selementFormTriggers').html()),
selected_triggers = $('#elementNameTriggers').multiSelect('getData'),
triggerids = [],
triggers_to_insert = [];
if (typeof triggers === 'undefined' || $.isEmptyObject(triggers)) {
triggers = [];
}
triggers = triggers.concat(selected_triggers);
if (triggers) {
triggers.forEach(function(trigger) {
if ($('input[name^="element_id[' + trigger.id + ']"]').length == 0) {
triggerids.push(trigger.id);
triggers_to_insert[trigger.id] = {
id: trigger.id,
name: typeof trigger.prefix == 'undefined'
? trigger.name
: trigger.prefix + trigger.name
};
}
});
if (triggerids.length != 0) {
// get priority
var ajaxUrl = new Curl('jsrpc.php');
ajaxUrl.setArgument('type', 11);
$.ajax({
url: ajaxUrl.getUrl(),
type: 'post',
dataType: 'html',
data: {
method: 'trigger.get',
triggerids: triggerids
},
success: function(data) {
data = JSON.parse(data);
triggers.forEach(function(sorted_trigger) {
data.result.forEach(function(trigger) {
if (sorted_trigger.id == trigger.triggerid) {
if ($('input[name^="element_id[' + trigger.triggerid + ']"]').length == 0) {
trigger.name = triggers_to_insert[trigger.triggerid].name;
$(tpl.evaluate(trigger)).appendTo('#triggerContainer tbody');
return false;
}
}
});
});
SelementForm.prototype.recalculateSortOrder();
SelementForm.prototype.initSortable();
}
});
}
$('#elementNameTriggers').multiSelect('clean');
}
},
/**
* Set form controls with element fields values.
*
* @param {object} selement
*/
setValues: function(selement) {
for (var elementName in selement) {
$('[name=' + elementName + ']', this.domNode).val([selement[elementName]]);
}
// set default icon state
if (empty(selement.iconid_on)) {
$('[name=iconid_on]', this.domNode).val(0);
}
if (empty(selement.iconid_disabled)) {
$('[name=iconid_disabled]', this.domNode).val(0);
}
if (empty(selement.iconid_maintenance)) {
$('[name=iconid_maintenance]', this.domNode).val(0);
}
// clear urls
$('#urlContainer tbody tr').remove();
this.addUrls(selement.urls);
// Set tag properties.
var tags = selement.tags;
if (!tags || Object.getOwnPropertyNames(tags).length == 0) {
tags = {0: {}};
}
this.cleanTagsField();
this.addTags(tags);
this.setEvaltype(selement.evaltype);
// Iconmap.
if (this.sysmap.data.iconmapid === '0') {
$('#use_iconmap').prop({
checked: false,
disabled: true
});
}
this.actionProcessor.process();
switch (selement.elementtype) {
// host
case '0':
$('#elementNameHost').multiSelect('addData', [{
'id': selement.elements[0].hostid,
'name': selement.elements[0].elementName
}]);
break;
// map
case '1':
$('#elementNameMap').multiSelect('addData', [{
'id': selement.elements[0].sysmapid,
'name': selement.elements[0].elementName
}]);
break;
// trigger
case '2':
var triggers = [];
for (i in selement.elements) {
triggers[i] = {'id': selement.elements[i].triggerid, 'name': selement.elements[i].elementName};
}
this.addTriggers(triggers);
break;
// host group
case '3':
$('#elementNameHostGroup').multiSelect('addData', [{
'id': selement.elements[0].groupid,
'name': selement.elements[0].elementName
}]);
break;
}
},
/**
* Remove tag filter rows from DOM.
*/
cleanTagsField: function() {
$('#selement-tags .form_row').remove();
},
/**
* Gets form values for element fields.
*
* @returns {Object|Boolean}
*/
getValues: function() {
var values = $(':input', '#selementForm')
.not(this.actionProcessor.hidden)
.not('[name^="tags"]')
.serializeArray(),
data = {
urls: {}
},
i,
urlPattern = /^url_(\d+)_(name|url)$/,
url,
urlNames = {},
elementsData = {};
for (i = 0; i < values.length; i++) {
url = urlPattern.exec(values[i].name);
if (url !== null) {
if (typeof data.urls[url[1]] === 'undefined') {
data.urls[url[1]] = {};
}
data.urls[url[1]][url[2]] = values[i].value.toString();
}
else {
data[values[i].name] = values[i].value.toString();
}
}
if (data.elementtype == '0' || data.elementtype == '3') {
data.tags = {};
$('input, z-select', '#selementForm').filter(function() {
return this.name.match(/tags\[\d+\]\[tag\]/);
}).each(function() {
if (this.value !== '') {
var nr = parseInt(this.name.match(/^tags\[(\d+)\]\[tag\]$/)[1]);
data.tags[Object.getOwnPropertyNames(data.tags).length] = {
tag: this.value,
operator: $('[name="tags['+nr+'][operator]"]').val(),
value: $('[name="tags['+nr+'][value]"]').val()
};
}
});
}
data.elements = {};
// set element id and name
switch (data.elementtype) {
// host
case '0':
elementsData = $('#elementNameHost').multiSelect('getData');
if (elementsData.length != 0) {
data.elements[0] = {
hostid: elementsData[0].id,
elementName: elementsData[0].name
};
}
break;
// map
case '1':
elementsData = $('#elementNameMap').multiSelect('getData');
if (elementsData.length != 0) {
data.elements[0] = {
sysmapid: elementsData[0].id,
elementName: elementsData[0].name
};
}
break;
// triggers
case '2':
i = 0;
$('input[name^="element_id"]').each(function() {
data.elements[i] = {
triggerid: $(this).val(),
elementName: $('input[name^="element_name[' + $(this).val() + ']"]').val(),
priority: $('input[name^="element_priority[' + $(this).val() + ']"]').val()
};
i++;
});
break;
// host group
case '3':
elementsData = $('#elementNameHostGroup').multiSelect('getData');
if (elementsData.length != 0) {
data.elements[0] = {
groupid: elementsData[0].id,
elementName: elementsData[0].name
};
}
break;
}
// validate urls
for (i in data.urls) {
if (data.urls[i].name === '' && data.urls[i].url === '') {
delete data.urls[i];
continue;
}
if (data.urls[i].name === '' || data.urls[i].url === '') {
alert(t('S_INCORRECT_ELEMENT_MAP_LINK'));
return false;
}
if (typeof urlNames[data.urls[i].name] !== 'undefined') {
alert(t('S_EACH_URL_SHOULD_HAVE_UNIQUE') + " '" + data.urls[i].name + "'.");
return false;
}
urlNames[data.urls[i].name] = 1;
}
// validate element id
if ($.isEmptyObject(data.elements) && data.elementtype !== '4') {
switch (data.elementtype) {
case '0': alert('Host is not selected.');
return false;
case '1': alert('Map is not selected.');
return false;
case '2': alert('Trigger is not selected.');
return false;
case '3': alert('Host group is not selected.');
return false;
}
}
return data;
},
/**
* Drag and drop trigger sorting.
*/
initSortable: function() {
var triggerContainer = $('#triggerContainer');
triggerContainer.sortable({
disabled: (triggerContainer.find('tr.sortable').length < 2),
items: 'tbody tr.sortable',
axis: 'y',
containment: 'parent',
cursor: 'grabbing',
handle: 'div.drag-icon',
tolerance: 'pointer',
opacity: 0.6,
update: this.recalculateSortOrder,
start: function(e, ui) {
$(ui.placeholder).height($(ui.helper).height());
}
});
},
/**
* Sorting triggers by severity.
*/
recalculateSortOrder: function() {
if ($('input[name^="element_id"]').length != 0) {
var triggers = [],
priority;
$('input[name^="element_id"]').each(function() {
priority = $('input[name^="element_priority[' + $(this).val() + ']"]').val()
if (!triggers[priority]) {
triggers[priority] = {
'priority': priority,
'html': $('#triggerrow_' + $(this).val())[0].outerHTML
}
}
else {
triggers[priority].html += $('#triggerrow_' + $(this).val())[0].outerHTML;
}
});
triggers.sort(function (a, b) {
return b.priority - a.priority;
});
$('#triggerContainer tbody').html('');
triggers.forEach(function(trigger) {
$('#triggerContainer tbody').append(trigger.html);
});
}
}
};
/**
* Elements mass update form.
*
* @param {object} formContainer jQuery object
* @param {object} sysmap
*/
function MassForm(formContainer, sysmap) {
var i,
icon,
formActions = [
{
action: 'enable',
value: '#massLabel',
cond: [{
chkboxLabel: 'checked'
}]
},
{
action: 'enable',
value: '#massLabelLocation',
cond: [{
chkboxLabelLocation: 'checked'
}]
},
{
action: 'enable',
value: '#massUseIconmap',
cond: [{
chkboxMassUseIconmap: 'checked'
}]
},
{
action: 'enable',
value: '#massIconidOff',
cond: [{
chkboxMassIconidOff: 'checked'
}]
},
{
action: 'enable',
value: '#massIconidOn',
cond: [{
chkboxMassIconidOn: 'checked'
}]
},
{
action: 'enable',
value: '#massIconidMaintenance',
cond: [{
chkboxMassIconidMaintenance: 'checked'
}]
},
{
action: 'enable',
value: '#massIconidDisabled',
cond: [{
chkboxMassIconidDisabled: 'checked'
}]
}
];
this.sysmap = sysmap;
this.formContainer = formContainer;
// create form
var tpl = new Template($('#mapMassFormTpl').html());
this.domNode = $(tpl.evaluate()).appendTo(formContainer);
// populate icons selects
const select_icon_off = document.getElementById('massIconidOff');
const select_icon_on = document.getElementById('massIconidOn');
const select_icon_maintenance = document.getElementById('massIconidMaintenance');
const select_icon_disabled = document.getElementById('massIconidDisabled');
select_icon_on.addOption({label: t('S_DEFAULT'), value: '0', class_name: ZBX_STYLE_DEFAULT_OPTION});
select_icon_maintenance.addOption({label: t('S_DEFAULT'), value: '0', class_name: ZBX_STYLE_DEFAULT_OPTION});
select_icon_disabled.addOption({label: t('S_DEFAULT'), value: '0', class_name: ZBX_STYLE_DEFAULT_OPTION});
for (i in this.sysmap.iconList) {
icon = this.sysmap.iconList[i];
select_icon_off.addOption({label: icon.name, value: icon.imageid});
select_icon_on.addOption({label: icon.name, value: icon.imageid});
select_icon_maintenance.addOption({label: icon.name, value: icon.imageid});
select_icon_disabled.addOption({label: icon.name, value: icon.imageid});
}
document.getElementById('massLabelLocation').selectedIndex = 0;
select_icon_off.selectedIndex = 0
select_icon_on.selectedIndex = 0
select_icon_maintenance.selectedIndex = 0
select_icon_disabled.selectedIndex = 0
this.actionProcessor = new ActionProcessor(formActions);
this.actionProcessor.process();
}
MassForm.prototype = {
/**
* Show mass update form.
*/
show: function() {
this.formContainer.draggable('option', 'handle', '#massDragHandler');
this.formContainer.show();
this.domNode.show();
// Element must first be visible so that outerWidth() and outerHeight() are correct.
this.formContainer.positionOverlayDialogue();
this.updateList();
},
/**
* Hide mass update form.
*/
hide: function() {
this.domNode.toggle(false);
$(':checkbox', this.domNode).prop('checked', false);
$('z-select', this.domNode).each(function() {
this.selectedIndex = 0;
});
$('textarea', this.domNode).val('');
this.actionProcessor.process();
},
/**
* Get values from mass update form that should be updated in all selected elements.
*
* @return array
*/
getValues: function() {
var values = $('#massForm').serializeArray(),
data = {},
i,
ln;
for (i = 0, ln = values.length; i < ln; i++) {
// special case for use iconmap checkbox, because unchecked checkbox is not submitted with form
if (values[i].name === 'chkbox_use_iconmap') {
data['use_iconmap'] = '0';
}
if (values[i].name.match(/^chkbox_/) !== null) {
continue;
}
data[values[i].name] = values[i].value.toString();
}
return data;
},
/**
* Updates list of selected elements in mass update form.
*/
updateList: function() {
var tpl = new Template($('#mapMassFormListRow').html()),
id,
list = [],
element,
elementTypeText,
i,
ln;
$('#massList tbody').empty();
for (id in this.sysmap.selection.selements) {
element = this.sysmap.selements[id];
switch (element.data.elementtype) {
case '0': elementTypeText = t('S_HOST'); break;
case '1': elementTypeText = t('S_MAP'); break;
case '2': elementTypeText = t('S_TRIGGER'); break;
case '3': elementTypeText = t('S_HOST_GROUP'); break;
case '4': elementTypeText = t('S_IMAGE'); break;
}
list.push({
elementType: elementTypeText,
elementName: element.getName().replace(/&/g,'&').replace(//g,'>')
.replace(/\"/g,'"').replace(/\'/g,''')
});
}
// sort by element type and then by element name
list.sort(function(a, b) {
var elementTypeA = a.elementType.toLowerCase(),
elementTypeB = b.elementType.toLowerCase(),
elementNameA,
elementNameB;
if (elementTypeA < elementTypeB) {
return -1;
}
if (elementTypeA > elementTypeB) {
return 1;
}
elementNameA = a.elementName.toLowerCase();
elementNameB = b.elementName.toLowerCase();
if (elementNameA < elementNameB) {
return -1;
}
if (elementNameA > elementNameB) {
return 1;
}
return 0;
});
for (i = 0, ln = list.length; i < ln; i++) {
$(tpl.evaluate(list[i])).appendTo('#massList tbody');
}
}
};
/**
* Form for shape editing.
*
* @param {object} formContainer jQuery object
* @param {object} sysmap
*/
function ShapeForm(formContainer, sysmap) {
this.sysmap = sysmap;
this.formContainer = formContainer;
this.triggerids = {};
this.domNode = $(new Template($('#mapShapeFormTpl').html()).evaluate()).appendTo(formContainer);
this.domNode.find('.color-picker input').colorpicker();
}
ShapeForm.prototype = {
/**
* Show form.
*/
show: function() {
this.formContainer.draggable('option', 'handle', '#shapeDragHandler');
this.formContainer.show();
this.domNode.show();
// Element must first be visible so that outerWidth() and outerHeight() are correct.
this.formContainer.positionOverlayDialogue();
this.active = true;
},
/**
* Hides element form.
*/
hide: function() {
this.domNode.toggle(false);
this.active = false;
},
/**
* Set form controls with shape fields values.
*
* @param {object} shape
*/
setValues: function(shape) {
for (var field in shape) {
$('[name=' + field + ']', this.domNode).val([shape[field]]);
}
$('.color-picker input', this.domNode).change();
$('#border_type').change();
$('#last_shape_type').val(shape.type);
$('input[type=radio][name=type]:checked').change();
},
/**
* Get values from shape update form that should be updated
*
* @return array
*/
getValues: function() {
var values = $('#shapeForm').serializeArray(),
data = {},
i,
ln,
min_size,
width = parseInt(this.sysmap.data.width),
height = parseInt(this.sysmap.data.height);
for (i = 0, ln = values.length; i < ln; i++) {
data[values[i].name] = values[i].value.toString();
}
data.x = parseInt(data.x, 10);
data.y = parseInt(data.y, 10);
data.width = parseInt(data.width, 10);
data.height = parseInt(data.height, 10);
data.x = isNaN(data.x) || (data.x < 0) ? 0 : data.x;
data.y = isNaN(data.y) || (data.y < 0) ? 0 : data.y;
min_size = (data.type != SVGMapShape.TYPE_LINE) ? 1 : 0;
data.width = isNaN(data.width) || (data.width < min_size) ? min_size : data.width;
data.height = isNaN(data.height) || (data.height < min_size) ? min_size : data.height;
data.x = (data.x >= width) ? width : data.x;
data.y = (data.y >= height) ? height : data.y;
data.width = (data.width >= width) ? width : data.width;
data.height = (data.height >= height) ? height : data.height;
return data;
}
};
/**
* Form for shape editing.
*
* @param {object} formContainer jQuery object
* @param {object} sysmap
*/
function MassShapeForm(formContainer, sysmap) {
var formActions = [];
var mapping = {
chkboxType: '[name="mass_type"]',
chkboxText: '#mass_text',
chkboxFont: '#mass_font',
chkboxFontSize: '#mass_font_size',
chkboxFontColor: '#mass_font_color',
chkboxTextHalign: '#mass_text_halign',
chkboxTextValign: '#mass_text_valign',
chkboxBackground: '#mass_background_color',
chkboxBorderType: '#mass_border_type',
chkboxBorderWidth: '#mass_border_width',
chkboxBorderColor: '#mass_border_color'
};
Object.keys(mapping).forEach(function (key) {
var condition = {};
condition[key] = 'checked';
formActions.push({
action: 'enable',
value: mapping[key],
cond: [condition]
});
});
this.sysmap = sysmap;
this.formContainer = formContainer;
this.triggerids = {};
this.domNode = $(new Template($('#mapMassShapeFormTpl').html()).evaluate()).appendTo(formContainer);
this.domNode.find('.color-picker input').colorpicker();
this.actionProcessor = new ActionProcessor(formActions);
this.actionProcessor.process();
}
MassShapeForm.prototype = {
/**
* Show form.
*/
show: function(figures) {
var value = figures ? 0 : 2;
$('.shape_figure_row', this.domNode).toggle(figures);
$('.switchable-content', this.domNode).each(function (i, element) {
element.textContent = element.hasAttribute('data-value-' + value) ?
element.getAttribute('data-value-' + value) :
element.getAttribute('data-value');
});
this.formContainer.draggable('option', 'handle', '#massShapeDragHandler');
this.formContainer.show();
this.domNode.show();
// Element must first be visible so that outerWidth() and outerHeight() are correct.
this.formContainer.positionOverlayDialogue();
this.active = true;
},
/**
* Hides element form.
*/
hide: function() {
this.domNode.toggle(false);
this.active = false;
$(':checkbox', this.domNode).prop('checked', false).prop("disabled", false);
$('textarea, input[type=text]', this.domNode).val('');
$('.color-picker input', this.domNode).change();
this.actionProcessor.process();
},
/**
* Get values from mass update form that should be updated in all selected shapes.
*
* @return array
*/
getValues: function() {
var values = $('#massShapeForm').serializeArray(),
data = {},
i,
ln;
for (i = 0, ln = values.length; i < ln; i++) {
if (values[i].name.match(/^mass_/) !== null) {
data[values[i].name.substring("mass_".length)] = values[i].value.toString();
}
}
return data;
}
};
/**
* Form for editin links.
*
* @param {object} formContainer jQuesry object
* @param {object} sysmap
*/
function LinkForm(formContainer, sysmap) {
this.sysmap = sysmap;
this.formContainer = formContainer;
this.triggerids = {};
this.domNode = $(new Template($('#linkFormTpl').html()).evaluate()).appendTo(formContainer);
this.domNode.find('.color-picker input').colorpicker();
}
LinkForm.prototype = {
/**
* Show form.
*/
show: function() {
this.domNode.show();
$('.element-edit-control').prop('disabled', true);
},
/**
* Hide form.
*/
hide: function() {
$('#linkForm').hide();
$('.element-edit-control').prop('disabled', false);
},
/**
* Get form values for link fields.
*/
getValues: function() {
var values = $('#linkForm').serializeArray(),
data = {
linktriggers: {}
},
i,
ln,
linkTriggerPattern = /^linktrigger_(\w+)_(triggerid|linktriggerid|drawtype|color|desc_exp)$/,
colorPattern = /^[0-9a-f]{6}$/i,
linkTrigger;
for (i = 0, ln = values.length; i < ln; i++) {
linkTrigger = linkTriggerPattern.exec(values[i].name);
if (linkTrigger !== null) {
if (linkTrigger[2] == 'color' && !values[i].value.toString().match(colorPattern)) {
throw sprintf(t('S_COLOR_IS_NOT_CORRECT'), values[i].value);
}
if (typeof data.linktriggers[linkTrigger[1]] === 'undefined') {
data.linktriggers[linkTrigger[1]] = {};
}
data.linktriggers[linkTrigger[1]][linkTrigger[2]] = values[i].value.toString();
}
else {
if (values[i].name == 'color' && !values[i].value.toString().match(colorPattern)) {
throw sprintf(t('S_COLOR_IS_NOT_CORRECT'), values[i].value);
}
data[values[i].name] = values[i].value.toString();
}
}
return data;
},
/**
* Update form controls with values from link.
*
* @param {object} link
*/
setValues: function(link) {
var selement1,
tmp,
selementid,
selement,
elementName,
optgroups = {},
optgroupType,
optgroupLabel,
optgroup,
i,
ln;
/*
* If only one element is selected, make sure that element1 is equal to the selected element and
* element2 - to the connected.
*/
if (this.sysmap.selection.count.selements === 1 && this.sysmap.selection.count.shapes === 0) {
// get currently selected element
for (selementid in this.sysmap.selection.selements) {
selement1 = this.sysmap.selements[selementid];
}
if (selement1.id !== link.selementid1) {
tmp = link.selementid1;
link.selementid1 = selement1.id;
link.selementid2 = tmp;
}
}
// populate list of elements to connect with
const connect_to_select = document.createElement('z-select');
connect_to_select._button.id = 'label-selementid2';
connect_to_select.id = 'selementid2';
connect_to_select.name = 'selementid2';
// sort by type
for (selementid in this.sysmap.selements) {
selement = this.sysmap.selements[selementid];
if (selement.id == link.selementid1) {
continue;
}
if (optgroups[selement.data.elementtype] === void(0)) {
optgroups[selement.data.elementtype] = [];
}
optgroups[selement.data.elementtype].push(selement);
}
for (optgroupType in optgroups) {
switch (optgroupType) {
case '0':
optgroupLabel = t('S_HOST');
break;
case '1':
optgroupLabel = t('S_MAP');
break;
case '2':
optgroupLabel = t('S_TRIGGER');
break;
case '3':
optgroupLabel = t('S_HOST_GROUP');
break;
case '4':
optgroupLabel = t('S_IMAGE');
break;
}
optgroup = {label: optgroupLabel, options: []};
for (i = 0, ln = optgroups[optgroupType].length; i < ln; i++) {
optgroup.options.push({
value: optgroups[optgroupType][i].id,
label: optgroups[optgroupType][i].getName()
});
}
connect_to_select.addOptionGroup(optgroup);
}
$('#selementid2').replaceWith(connect_to_select);
// set values for form elements
for (elementName in link) {
$('[name=' + elementName + ']', this.domNode).val(link[elementName]);
}
// clear triggers
this.triggerids = {};
$('#linkTriggerscontainer tbody tr').remove();
this.addLinkTriggers(link.linktriggers);
},
/**
* Add link triggers to link form.
*
* @param {object} triggers
*/
addLinkTriggers: function(triggers) {
var tpl = new Template($('#linkTriggerRow').html()),
linkTrigger,
table = $('#linkTriggerscontainer tbody');
for (linkTrigger in triggers) {
this.triggerids[triggers[linkTrigger].triggerid] = linkTrigger;
$(tpl.evaluate(triggers[linkTrigger])).appendTo(table);
$('#linktrigger_' + triggers[linkTrigger].linktriggerid + '_drawtype')
.val(triggers[linkTrigger].drawtype);
}
table.find('.color-picker input').colorpicker();
$('.color-picker input', this.domNode).change();
},
/**
* Add new triggers which were selected in popup to trigger list.
*
* @param {object} triggers
*/
addNewTriggers: function(triggers) {
var tpl = new Template($('#linkTriggerRow').html()),
linkTrigger = {
color: 'DD0000'
},
linktriggerid,
i,
ln,
table = $('#linkTriggerscontainer tbody');
for (i = 0, ln = triggers.length; i < ln; i++) {
if (typeof this.triggerids[triggers[i].triggerid] !== 'undefined') {
continue;
}
linktriggerid = getUniqueId();
// store linktriggerid to generate every time unique one
this.sysmap.allLinkTriggerIds[linktriggerid] = true;
// store triggerid to forbid selecting same trigger twice
this.triggerids[triggers[i].triggerid] = linktriggerid;
linkTrigger.linktriggerid = linktriggerid;
linkTrigger.desc_exp = triggers[i].description;
linkTrigger.triggerid = triggers[i].triggerid;
$(tpl.evaluate(linkTrigger)).appendTo(table);
}
table.find('.color-picker input').colorpicker();
$('.color-picker input', this.domNode).change();
},
/**
* Updates links list for element.
*
* @param {string} selementIds
*/
updateList: function(selementIds) {
var links = this.sysmap.getLinksBySelementIds(selementIds),
linkTable,
rowTpl,
list,
i, j,
selement,
tmp,
ln,
link,
linktriggers,
fromElementName,
toElementName;
$('.element-links').hide();
$('.element-links tbody').empty();
if (links.length) {
$('#mapLinksContainer').show();
if (objectSize(selementIds) > 1) {
rowTpl = '#massElementLinkTableRowTpl';
linkTable = $('#mass-element-links');
}
else {
rowTpl = '#elementLinkTableRowTpl';
linkTable = $('#element-links');
}
rowTpl = new Template($(rowTpl).html());
list = [];
for (i = 0, ln = links.length; i < ln; i++) {
link = this.sysmap.links[links[i]].data;
/*
* If one element selected and it's not link.selementid1, we need to swap link.selementid1
* and link.selementid2 in order that sorting works correctly.
*/
if (objectSize(selementIds) == 1 && !selementIds[link.selementid1]) {
// Get currently selected element.
for (var selementId in this.sysmap.selection.selements) {
selement = this.sysmap.selements[selementId];
}
if (selement.id !== link.selementid1) {
tmp = link.selementid1;
link.selementid1 = selement.id;
link.selementid2 = tmp;
}
}
linktriggers = [];
for (var linktrigger in link.linktriggers) {
linktriggers.push(link.linktriggers[linktrigger].desc_exp);
}
fromElementName = this.sysmap.selements[link.selementid1].getName();
toElementName = this.sysmap.selements[link.selementid2].getName();
list.push({
fromElementName: fromElementName,
toElementName: toElementName,
linkid: link.linkid,
linktriggers: linktriggers
});
}
// Sort by "from" element and then by "to" element.
list.sort(function(a, b) {
var fromElementA = a.fromElementName.toLowerCase(),
fromElementB = b.fromElementName.toLowerCase(),
toElementA = a.toElementName.toLowerCase(),
toElementB = b.toElementName.toLowerCase(),
linkIdA = a.linkid,
linkIdB = b.linkid;
if (fromElementA < fromElementB) {
return -1;
}
else if (fromElementA > fromElementB) {
return 1;
}
if (toElementA < toElementB) {
return -1;
}
else if (toElementA > toElementB) {
return 1;
}
if (linkIdA < linkIdB) {
return -1;
}
else if (linkIdA > linkIdB) {
return 1;
}
return 0;
});
for (i = 0, ln = list.length; i < ln; i++) {
var row = $(rowTpl.evaluate(list[i])),
row_urls = $('.element-urls', row);
for (j = 0; j < list[i].linktriggers.length; j++) {
if (j != 0) {
row_urls.append($('
'));
}
row_urls.append($('').text(list[i].linktriggers[j]));
}
row.appendTo(linkTable.find('tbody'));
}
linkTable.closest('.element-links').show();
}
else {
$('#mapLinksContainer').hide();
}
}
};
var sysmap = new CMap(containerId, mapData);
Shape.prototype.bind('afterMove', function(event, element) {
if (sysmap.selection.count.shapes === 1 && sysmap.selection.count.selements === 0
&& sysmap.selection.shapes[element.id] !== void(0)) {
$('#shapeX').val(element.data.x);
$('#shapeY').val(element.data.y);
if (typeof element.data.width !== 'undefined') {
$('#shapeForm input[name=width]').val(element.data.width);
}
if (typeof element.data.height !== 'undefined') {
$('#shapeForm input[name=height]').val(element.data.height);
}
}
sysmap.updateImage();
});
Selement.prototype.bind('afterMove', function(event, element) {
if (sysmap.selection.count.selements === 1 && sysmap.selection.count.shapes === 0
&& sysmap.selection.selements[element.id] !== void(0)) {
$('#x').val(element.data.x);
$('#y').val(element.data.y);
if (typeof element.data.width !== 'undefined') {
$('#areaSizeWidth').val(element.data.width);
}
if (typeof element.data.height !== 'undefined') {
$('#areaSizeHeight').val(element.data.height);
}
}
if (sysmap.buffered_expand === false) {
sysmap.updateImage();
}
});
return sysmap;
}
return {
object: null,
run: function(containerId, mapData) {
if (this.object !== null) {
throw new Error('Map has already been run.');
}
this.object = createMap(containerId, mapData);
}
};
}(jQuery));
jQuery(function ($) {
/*
* Reposition the overlay dialogue window. The previous position is remembered using offset(). Each time overlay
* dialogue is opened, it could have different content (shape form, element form etc) and different size, so the
* new top and left position must be calculated. If the overlay dialogue is opened for the first time, position is
* set depending on map size and canvas top position. This makes map more visible at first. In case popup window is
* dragged outside visible view port or window is resized, popup will again be repositioned so it doesn't go outside
* the viewport. In case the popup is too large, position it with a small margin depending on whether is too long
* or too wide.
*/
$.fn.positionOverlayDialogue = function () {
var $map = $('#map-area'),
map_offset = $map.offset(),
map_margin = 10,
$dialogue = $(this),
$dialogue_host = $dialogue.offsetParent(),
dialogue_host_offset = $dialogue_host.offset(),
// Usable area relative to host.
dialogue_host_x_min = $dialogue_host.scrollLeft(),
dialogue_host_x_max = Math.min($dialogue_host[0].scrollWidth,
$(window).width() + $(window).scrollLeft() - dialogue_host_offset.left + $dialogue_host.scrollLeft()
) - 1,
dialogue_host_y_min = $dialogue_host.scrollTop(),
dialogue_host_y_max = Math.min($dialogue_host[0].scrollHeight,
$(window).height() + $(window).scrollTop() - dialogue_host_offset.top + $dialogue_host.scrollTop()
) - 1,
// Coordinates of map's top right corner relative to dialogue host.
pos_x = map_offset.left + $map[0].scrollWidth - dialogue_host_offset.left + $dialogue_host.scrollLeft(),
pos_y = map_offset.top - map_margin - dialogue_host_offset.top + $dialogue_host.scrollTop();
return this.css({
left: Math.max(dialogue_host_x_min, Math.min(dialogue_host_x_max - $dialogue.outerWidth(), pos_x)),
top: Math.max(dialogue_host_y_min, Math.min(dialogue_host_y_max - $dialogue.outerHeight(), pos_y))
});
};
});