1<script type="text/x-jquery-tmpl" id="hostInterfaceRow">
2<tr class="interfaceRow" id="hostInterfaceRow_#{iface.interfaceid}" data-interfaceid="#{iface.interfaceid}">
3	<td class="interface-drag-control <?= ZBX_STYLE_TD_DRAG_ICON ?>">
4		<div class="<?= ZBX_STYLE_DRAG_ICON ?>"></div>
5		<input type="hidden" name="interfaces[#{iface.interfaceid}][items]" value="#{iface.items}" />
6		<input type="hidden" name="interfaces[#{iface.interfaceid}][locked]" value="#{iface.locked}" />
7	</td>
8	<td class="interface-ip">
9		<input type="hidden" name="interfaces[#{iface.interfaceid}][isNew]" value="#{iface.isNew}">
10		<input type="hidden" name="interfaces[#{iface.interfaceid}][interfaceid]" value="#{iface.interfaceid}">
11		<input type="hidden" id="interface_type_#{iface.interfaceid}" name="interfaces[#{iface.interfaceid}][type]" value="#{iface.type}">
12		<input name="interfaces[#{iface.interfaceid}][ip]" type="text" style="width: <?= ZBX_TEXTAREA_INTERFACE_IP_WIDTH ?>px" maxlength="64" value="#{iface.ip}">
13		<div class="interface-bulk">
14			<input type="checkbox" id="interfaces_#{iface.interfaceid}_bulk" name="interfaces[#{iface.interfaceid}][bulk]" value="1" #{attrs.checked_bulk}>
15			<label for="interfaces_#{iface.interfaceid}_bulk"><?= _('Use bulk requests') ?></label>
16		</div>
17	</td>
18	<td class="interface-dns">
19		<input name="interfaces[#{iface.interfaceid}][dns]" type="text" style="width: <?= ZBX_TEXTAREA_INTERFACE_DNS_WIDTH ?>px" maxlength="64" value="#{iface.dns}">
20	</td>
21	<?= (new CCol(
22			(new CRadioButtonList('interfaces[#{iface.interfaceid}][useip]', null))
23				->addValue(_('IP'), INTERFACE_USE_IP, 'interfaces[#{iface.interfaceid}][useip]['.INTERFACE_USE_IP.']')
24				->addValue(_('DNS'), INTERFACE_USE_DNS,
25					'interfaces[#{iface.interfaceid}][useip]['.INTERFACE_USE_DNS.']'
26				)
27				->setModern(true)
28		))->toString()
29	?>
30	<td class="interface-port">
31		<input name="interfaces[#{iface.interfaceid}][port]" type="text" style="width: <?= ZBX_TEXTAREA_INTERFACE_PORT_WIDTH ?>px" maxlength="64" value="#{iface.port}">
32	</td>
33	<td class="interface-default">
34		<input class="mainInterface" type="radio" id="interface_main_#{iface.interfaceid}" name="mainInterfaces[#{iface.type}]" value="#{iface.interfaceid}">
35		<label class="checkboxLikeLabel" for="interface_main_#{iface.interfaceid}" style="height: 16px; width: 16px;"></label>
36	</td>
37	<td class="<?= ZBX_STYLE_NOWRAP ?> interface-control">
38		<button class="<?= ZBX_STYLE_BTN_LINK ?> remove" type="button" id="removeInterface_#{iface.interfaceid}" data-interfaceid="#{iface.interfaceid}" #{attrs.disabled}><?= _('Remove') ?></button>
39	</td>
40</tr>
41</script>
42
43<script type="text/javascript">
44	var hostInterfacesManager = (function() {
45		'use strict';
46
47		var rowTemplate = new Template(jQuery('#hostInterfaceRow').html()),
48			ports = {
49				agent: 10050,
50				snmp: 161,
51				jmx: 12345,
52				ipmi: 623
53			},
54			allHostInterfaces = {};
55
56		function renderHostInterfaceRow(hostInterface) {
57			var domAttrs = getDomElementsAttrsForInterface(hostInterface),
58				domId = getDomIdForRowInsert(hostInterface.type),
59				domRow;
60
61			jQuery(domId).before(rowTemplate.evaluate({iface: hostInterface, attrs: domAttrs}));
62
63			domRow = jQuery('#hostInterfaceRow_' + hostInterface.interfaceid);
64
65			if (hostInterface.type != <?= INTERFACE_TYPE_SNMP ?>) {
66				jQuery('.interface-bulk', domRow).remove();
67			}
68
69			jQuery('#interfaces_' + hostInterface.interfaceid + '_useip_' + hostInterface.useip).prop('checked', true);
70
71			if (hostInterface.locked > 0) {
72				addNotDraggableIcon(domRow);
73			}
74			else {
75				addDraggableIcon(domRow);
76			}
77		}
78
79		function resetMainInterfaces() {
80			var typeInterfaces,
81				hostInterfaces = getMainInterfacesByType();
82
83			for (var hostInterfaceType in hostInterfaces) {
84				typeInterfaces = hostInterfaces[hostInterfaceType];
85
86				if (!typeInterfaces.main && typeInterfaces.all.length) {
87					for (var i = 0; i < typeInterfaces.all.length; i++) {
88						if (allHostInterfaces[typeInterfaces.all[i]].main === '1') {
89							typeInterfaces.main = allHostInterfaces[typeInterfaces.all[i]].interfaceid;
90						}
91					}
92					if (!typeInterfaces.main) {
93						typeInterfaces.main = typeInterfaces.all[0];
94						allHostInterfaces[typeInterfaces.main].main = '1';
95					}
96				}
97			}
98
99			for (var hostInterfaceType in hostInterfaces){
100				typeInterfaces = hostInterfaces[hostInterfaceType];
101
102				if (typeInterfaces.main) {
103					jQuery('#interface_main_' + typeInterfaces.main).prop('checked', true);
104				}
105			}
106		}
107
108		function getMainInterfacesByType() {
109			var hostInterface,
110				types = {};
111			types[getHostInterfaceNumericType('agent')] = {main: null, all: []};
112			types[getHostInterfaceNumericType('snmp')] = {main: null, all: []};
113			types[getHostInterfaceNumericType('jmx')] = {main: null, all: []};
114			types[getHostInterfaceNumericType('ipmi')] = {main: null, all: []};
115
116			for (var hostInterfaceId in allHostInterfaces) {
117				hostInterface = allHostInterfaces[hostInterfaceId];
118
119				types[hostInterface.type].all.push(hostInterfaceId);
120				if (hostInterface.main === '1') {
121					if (types[hostInterface.type].main !== null) {
122						throw new Error('Multiple default interfaces for same type.');
123					}
124					types[hostInterface.type].main = hostInterfaceId;
125				}
126			}
127			return types;
128		}
129
130		function addDraggableIcon(domElement) {
131			domElement.draggable({
132				handle: 'div.<?= ZBX_STYLE_DRAG_ICON ?>',
133				revert: 'invalid',
134				helper: function(event) {
135					var hostInterfaceId = jQuery(this).data('interfaceid');
136					var clone = jQuery(this).clone();
137					// Make sure to update names for all radio and checkboxes for them not to affect selection of
138					// originals.
139					// If original is addressed by any means (ex. by ID), make sure, to update these means in clone,
140					// for clone not to be addressed in place of original.
141					clone.find("[name$='[useip]']").each(function(){
142						jQuery(this).attr('name','interfaces[' + hostInterfaceId + '][useip_handle]');
143					});
144					clone.find("#interface_main_" + hostInterfaceId)
145						.attr('name','mainInterfaces[handle]')
146						.attr('id','interface_main_' + hostInterfaceId + '_handle');
147					return clone;
148				},
149				start: function(event, ui) {
150					jQuery(ui.helper).css({'z-index': '1000'});
151					// Visibility is added to original element to hide it, while helper is beeing moved, but to keep
152					// it's place visually.
153					jQuery(this).css({'visibility': 'hidden'});
154				},
155				stop: function(event, ui) {
156					resetMainInterfaces();
157					jQuery(this).css({'visibility': ''});
158				}
159			});
160		}
161
162		function addNotDraggableIcon(domElement) {
163			jQuery('td.<?= ZBX_STYLE_TD_DRAG_ICON ?> div.<?= ZBX_STYLE_DRAG_ICON ?>', domElement)
164				.addClass('<?= ZBX_STYLE_DISABLED ?>')
165				.hover(
166					function (event) {
167						hintBox.showHint(event, this,
168							<?= CJs::encodeJson(_('Interface is used by items that require this type of the interface.')) ?>
169						);
170					},
171					function (event) {
172						hintBox.hideHint(event, this);
173					}
174				);
175		}
176
177		function getDomElementsAttrsForInterface(hostInterface) {
178			var attrs = {
179				disabled: ''
180			};
181
182			if (hostInterface.items > 0) {
183				attrs.disabled = 'disabled="disabled"';
184			}
185
186			if (hostInterface.type == <?= INTERFACE_TYPE_SNMP ?>) {
187				if (hostInterface.bulk == 1) {
188					attrs.checked_bulk = 'checked=checked';
189				}
190				else {
191					attrs.checked_bulk = '';
192				}
193			}
194
195			return attrs;
196		}
197
198		function getDomIdForRowInsert(hostInterfaceType) {
199			var footerRowId;
200
201			switch (hostInterfaceType) {
202				case getHostInterfaceNumericType('agent'):
203					footerRowId = '#agentInterfacesFooter';
204					break;
205				case getHostInterfaceNumericType('snmp'):
206					footerRowId = '#SNMPInterfacesFooter';
207					break;
208				case getHostInterfaceNumericType('jmx'):
209					footerRowId = '#JMXInterfacesFooter';
210					break;
211				case getHostInterfaceNumericType('ipmi'):
212					footerRowId = '#IPMIInterfacesFooter';
213					break;
214				default:
215					throw new Error('Unknown host interface type.');
216			}
217			return footerRowId;
218		}
219
220		function createNewHostInterface(hostInterfaceType) {
221			var newInterface = {
222				isNew: true,
223				useip: 1,
224				type: getHostInterfaceNumericType(hostInterfaceType),
225				port: ports[hostInterfaceType],
226				ip: '127.0.0.1'
227			};
228
229			if (newInterface.type == <?= INTERFACE_TYPE_SNMP ?>) {
230				newInterface.bulk = 1;
231			}
232
233			newInterface.interfaceid = 1;
234			while (allHostInterfaces[newInterface.interfaceid] !== void(0)) {
235				newInterface.interfaceid++;
236			}
237
238			addHostInterface(newInterface);
239
240			return newInterface;
241		}
242
243		function addHostInterface(hostInterface) {
244			allHostInterfaces[hostInterface.interfaceid] = hostInterface;
245		}
246
247		function moveRowToAnotherTypeTable(hostInterfaceId, newHostInterfaceType) {
248			var newDomId = getDomIdForRowInsert(newHostInterfaceType);
249
250			jQuery('#interface_main_' + hostInterfaceId).attr('name', 'mainInterfaces[' + newHostInterfaceType + ']');
251			jQuery('#interface_main_' + hostInterfaceId).prop('checked', false);
252			jQuery('#interface_type_' + hostInterfaceId).val(newHostInterfaceType);
253			jQuery('#hostInterfaceRow_' + hostInterfaceId).insertBefore(newDomId);
254		}
255
256		return {
257			add: function(hostInterfaces) {
258				for (var i = 0; i < hostInterfaces.length; i++) {
259					addHostInterface(hostInterfaces[i]);
260					renderHostInterfaceRow(hostInterfaces[i]);
261				}
262				resetMainInterfaces();
263			},
264
265			addNew: function(type) {
266				var hostInterface = createNewHostInterface(type);
267
268				allHostInterfaces[hostInterface.interfaceid] = hostInterface;
269				renderHostInterfaceRow(hostInterface);
270				resetMainInterfaces();
271			},
272
273			remove: function(hostInterfaceId) {
274				delete allHostInterfaces[hostInterfaceId];
275			},
276
277			setType: function(hostInterfaceId, typeName) {
278				var newTypeNum = getHostInterfaceNumericType(typeName);
279
280				if (allHostInterfaces[hostInterfaceId].type !== newTypeNum) {
281					moveRowToAnotherTypeTable(hostInterfaceId, newTypeNum);
282					allHostInterfaces[hostInterfaceId].type = newTypeNum;
283					allHostInterfaces[hostInterfaceId].main = '0';
284				}
285			},
286
287			resetMainInterfaces: function() {
288				resetMainInterfaces();
289			},
290
291			setMainInterface: function(hostInterfaceId) {
292				var interfacesByType = getMainInterfacesByType(),
293					newMainInterfaceType = allHostInterfaces[hostInterfaceId].type,
294					oldMainInterfaceId = interfacesByType[newMainInterfaceType].main;
295
296				if (hostInterfaceId !== oldMainInterfaceId) {
297					allHostInterfaces[hostInterfaceId].main = '1';
298					allHostInterfaces[oldMainInterfaceId].main = '0';
299				}
300			},
301
302			setUseipForInterface: function(hostInterfaceId, useip) {
303				allHostInterfaces[hostInterfaceId].useip = useip;
304			},
305
306			disable: function() {
307				jQuery('.interface-drag-control, .interface-control').html('');
308				jQuery('.interfaceRow').find('input')
309					.removeAttr('id')
310					.removeAttr('name');
311				jQuery('.interfaceRow').find('input[type="text"]').attr('readonly', true);
312				jQuery('.interfaceRow').find('input[type="radio"], input[type="checkbox"]').attr('disabled', true);
313			}
314		}
315	}());
316
317	jQuery(document).ready(function() {
318		'use strict';
319
320		jQuery('#hostlist').on('click', 'button.remove', function() {
321			var interfaceId = jQuery(this).data('interfaceid');
322			jQuery('#hostInterfaceRow_' + interfaceId).remove();
323			hostInterfacesManager.remove(interfaceId);
324			hostInterfacesManager.resetMainInterfaces();
325		});
326
327		jQuery('#hostlist').on('click', 'input[type=radio].mainInterface', function() {
328			var interfaceId = jQuery(this).val();
329			hostInterfacesManager.setMainInterface(interfaceId);
330		});
331
332		jQuery('#hostlist').on('click', 'input[type=radio][id*="_useip_"]', function() {
333			var interfaceId = jQuery(this).attr('id').match(/\d+/);
334			hostInterfacesManager.setUseipForInterface(interfaceId[0], jQuery(this).val());
335		});
336
337		jQuery('#tls_connect, #tls_in_psk, #tls_in_cert').change(function() {
338			// If certificate is selected or checked.
339			if (jQuery('input[name=tls_connect]:checked').val() == <?= HOST_ENCRYPTION_CERTIFICATE ?>
340					|| jQuery('#tls_in_cert').is(':checked')) {
341				jQuery('#tls_issuer, #tls_subject').closest('li').show();
342			}
343			else {
344				jQuery('#tls_issuer, #tls_subject').closest('li').hide();
345			}
346
347			// If PSK is selected or checked.
348			if (jQuery('input[name=tls_connect]:checked').val() == <?= HOST_ENCRYPTION_PSK ?>
349					|| jQuery('#tls_in_psk').is(':checked')) {
350				jQuery('#tls_psk, #tls_psk_identity').closest('li').show();
351			}
352			else {
353				jQuery('#tls_psk, #tls_psk_identity').closest('li').hide();
354			}
355		});
356
357		jQuery('#agentInterfaces, #SNMPInterfaces, #JMXInterfaces, #IPMIInterfaces').parent().droppable({
358			tolerance: 'pointer',
359			drop: function(event, ui) {
360				var hostInterfaceTypeName = jQuery(this).data('type'),
361					hostInterfaceId = ui.draggable.data('interfaceid');
362
363				if (getHostInterfaceNumericType(hostInterfaceTypeName) == <?= INTERFACE_TYPE_SNMP ?>) {
364					if (jQuery('.interface-bulk', jQuery('#hostInterfaceRow_' + hostInterfaceId)).length == 0) {
365						var bulkDiv = jQuery('<div>', {
366							'class': 'interface-bulk'
367						});
368
369						// append checkbox
370						bulkDiv.append(jQuery('<input>', {
371							id: 'interfaces_' + hostInterfaceId + '_bulk',
372							type: 'checkbox',
373							name: 'interfaces[' + hostInterfaceId + '][bulk]',
374							value: 1,
375							checked: true
376						}));
377
378						// append label
379						bulkDiv.append(jQuery('<label>', {
380							'for': 'interfaces_' + hostInterfaceId + '_bulk',
381							text: '<?= _('Use bulk requests') ?>'
382						}));
383
384						jQuery('.interface-ip', jQuery('#hostInterfaceRow_' + hostInterfaceId)).append(bulkDiv);
385					}
386				}
387				else {
388					jQuery('.interface-bulk', jQuery('#hostInterfaceRow_' + hostInterfaceId)).remove();
389				}
390
391				hostInterfacesManager.setType(hostInterfaceId, hostInterfaceTypeName);
392			},
393			activate: function(event, ui) {
394				if (!jQuery(this).find(ui.draggable).length) {
395					jQuery(this).addClass('<?= ZBX_STYLE_DRAG_DROP_AREA ?>');
396				}
397			},
398			deactivate: function(event, ui) {
399				jQuery(this).removeClass('<?= ZBX_STYLE_DRAG_DROP_AREA ?>');
400			}
401		});
402
403		jQuery('#addAgentInterface').on('click', function() {
404			hostInterfacesManager.addNew('agent');
405		});
406		jQuery('#addSNMPInterface').on('click', function() {
407			hostInterfacesManager.addNew('snmp');
408		});
409		jQuery('#addJMXInterface').on('click', function() {
410			hostInterfacesManager.addNew('jmx');
411		});
412		jQuery('#addIPMIInterface').on('click', function() {
413			hostInterfacesManager.addNew('ipmi');
414		});
415
416		// radio button of inventory modes was clicked
417		jQuery('input[name=inventory_mode]').click(function() {
418			// action depending on which button was clicked
419			var inventoryFields = jQuery('#inventorylist :input:gt(2)');
420
421			switch (jQuery(this).val()) {
422				case '<?= HOST_INVENTORY_DISABLED ?>':
423					inventoryFields.prop('disabled', true);
424					jQuery('.populating_item').hide();
425					break;
426				case '<?= HOST_INVENTORY_MANUAL ?>':
427					inventoryFields.prop('disabled', false);
428					jQuery('.populating_item').hide();
429					break;
430				case '<?= HOST_INVENTORY_AUTOMATIC ?>':
431					inventoryFields.prop('disabled', false);
432					inventoryFields.filter('.linked_to_item').prop('disabled', true);
433					jQuery('.populating_item').show();
434					break;
435			}
436		});
437
438		/**
439		 * Mass update
440		 */
441		jQuery('#mass_replace_tpls').on('change', function() {
442			jQuery('#mass_clear_tpls').prop('disabled', !this.checked);
443		}).change();
444
445		// Refresh field visibility on document load.
446		if ((jQuery('#tls_accept').val() & <?= HOST_ENCRYPTION_NONE ?>) == <?= HOST_ENCRYPTION_NONE ?>) {
447			jQuery('#tls_in_none').prop('checked', true);
448		}
449		if ((jQuery('#tls_accept').val() & <?= HOST_ENCRYPTION_PSK ?>) == <?= HOST_ENCRYPTION_PSK ?>) {
450			jQuery('#tls_in_psk').prop('checked', true);
451		}
452		if ((jQuery('#tls_accept').val() & <?= HOST_ENCRYPTION_CERTIFICATE ?>) == <?= HOST_ENCRYPTION_CERTIFICATE ?>) {
453			jQuery('#tls_in_cert').prop('checked', true);
454		}
455
456		jQuery('input[name=tls_connect]').trigger('change');
457
458		// Depending on checkboxes, create a value for hidden field 'tls_accept'.
459		jQuery('#hostForm').submit(function() {
460			var tls_accept = 0x00;
461
462			if (jQuery('#tls_in_none').is(':checked')) {
463				tls_accept |= <?= HOST_ENCRYPTION_NONE ?>;
464			}
465			if (jQuery('#tls_in_psk').is(':checked')) {
466				tls_accept |= <?= HOST_ENCRYPTION_PSK ?>;
467			}
468			if (jQuery('#tls_in_cert').is(':checked')) {
469				tls_accept |= <?= HOST_ENCRYPTION_CERTIFICATE ?>;
470			}
471
472			jQuery('#tls_accept').val(tls_accept);
473		});
474	});
475
476	function getHostInterfaceNumericType(typeName) {
477		var typeNum;
478
479		switch (typeName) {
480			case 'agent':
481				typeNum = '<?= INTERFACE_TYPE_AGENT ?>';
482				break;
483			case 'snmp':
484				typeNum = '<?= INTERFACE_TYPE_SNMP ?>';
485				break;
486			case 'jmx':
487				typeNum = '<?= INTERFACE_TYPE_JMX ?>';
488				break;
489			case 'ipmi':
490				typeNum = '<?= INTERFACE_TYPE_IPMI ?>';
491				break;
492			default:
493				throw new Error('Unknown host interface type name.');
494		}
495		return typeNum;
496	}
497</script>
498