PageSourceSearch

http://mrtg.adau.net.id/cacti/include/layout.js?666a6d4acff74d80292c7cce8bb1f138

js adau.net.id collected 2026-10-08 12:24:27 UTC 132,139 bytes, 4,805 lines download raw bytes

1/*
2 +-------------------------------------------------------------------------+
3 | Copyright (C) 2004-2024 The Cacti Group                                 |
4 |                                                                         |
5 | This program is free software; you can redistribute it and/or           |
6 | modify it under the terms of the GNU General Public License             |
7 | as published by the Free Software Foundation; either version 2          |
8 | of the License, or (at your option) any later version.                  |
9 |                                                                         |
10 | This program is distributed in the hope that it will be useful,         |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of          |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           |
13 | GNU General Public License for more details.                            |
14 +-------------------------------------------------------------------------+
15 | Cacti: The Complete RRDtool-based Graphing Solution                     |
16 +-------------------------------------------------------------------------+
17 | This code is designed, written, and maintained by the Cacti Group. See  |
18 | about.php and/or the AUTHORS file for specific developer information.   |
19 +-------------------------------------------------------------------------+
20 | http://www.cacti.net/                                                   |
21 +-------------------------------------------------------------------------+
22*/
23
24const MESSAGE_LEVEL_NONE  = 0;
25const MESSAGE_LEVEL_INFO  = 1;
26const MESSAGE_LEVEL_WARN  = 2;
27const MESSAGE_LEVEL_ERROR = 3;
28const MESSAGE_LEVEL_CSRF  = 4;
29const MESSAGE_LEVEL_MIXED = 5;
30
31var theme;
32var myRefresh;
33var userMenuTimer;
34var userMenuOpenTimer = null;
35var graphMenuTimer;
36var graphMenuElement = 0;
37var pulsating = true;
38var pageLoaded = false;
39var shiftPressed = false;
40var sessionMessage = null;
41var sessionMessageOpen = null;
42var sessionMessageTimer = null;
43var myTitle;
44var myHref;
45var lastPage = null;
46var statePushed = false;
47var popFired = false;
48var hostInfoHeight = 0;
49var marginLeftTree = null;
50var marginLeftConsole = null;
51var minTreeWidth = null;
52var maxTreeWidth = null;
53var pageName;
54var columnsHidden = 0;
55var lastColumnsHidden = {};
56var lastWidth = {};
57var resizeDelta = 100;
58var resizeTime = 0;
59var resizeTimeout = false;
60var formArray;
61var pageWidth = null;
62var isHover = false;
63var hoverTimer = false;
64var previousMainWidth = null;
65var previousColumns   = null;
66var faIcons = {
67	open: {
68		icon: '<i class="fas fa-caret-down" aria-hidden="true"></i>'
69	},
70	close: {
71		icon: '<i class="fas fa-times-circle" aria-hidden="true"></i>'
72	},
73	checkAll: {
74		icon: '<i class="fas fa-check" aria-hidden="true"></i>'
75	},
76	uncheckAll: {
77		icon: '<i class="fas fa-ban" aria-hidden="true"></i>'
78	},
79	flipAll: {
80		icon: '<i class="fas fa-undo" aria-hidden="true"></i>'
81	},
82	collapseAll: {
83		icon: '<i class="fas fa-double-angle-down" aria-hidden="true"></i>'
84	},
85	expandAll: {
86		icon: '<i class="fas fa-double-angle-right" aria-hidden="true"></i>'
87	},
88	collapse: {
89		icon: '<i class="fas fa-chevron-down" aria-hidden="true"></i>'
90	},
91	expand: {
92		icon: '<i class="fas fa-chevron-right" aria-hidden="true"></i>'
93	}
94};
95
96window.paceOptions = {
97	ajax: true,
98	document: true,
99	elements: false,
100	minTime: 400,
101	startOnPageLoad: false,
102	restartOnPushState: false,
103	restartOnRequestAfter: 120,
104	eventLag: false,
105};
106
107window.onbeforeunload = renderLoading;
108function renderLoading () {
109	Pace.stop();
110	Pace.bar.render();
111}
112
113var isMobile = {
114	Android: function() {
115		return navigator.userAgent.match(/Android/i);
116	},
117	BlackBerry: function() {
118		return navigator.userAgent.match(/BlackBerry/i);
119	},
120	iOS: function() {
121		return navigator.userAgent.match(/iPhone|iPad|iPod/i);
122	},
123	Opera: function() {
124		return navigator.userAgent.match(/Opera Mini/i);
125	},
126	Windows: function() {
127		return navigator.userAgent.match(/IEMobile/i);
128	},
129	any: function() {
130		return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
131	}
132};
133
134/* simple ajax request queueing */
135jQuery.ajaxQ = (function(){
136	var id = 0, Q = {};
137
138	jQuery(document).ajaxSend(function(e, jqx){
139		jqx._id = ++id;
140		Q[jqx._id] = jqx;
141	});
142
143	jQuery(document).ajaxComplete(function(e, jqx){
144		delete Q[jqx._id];
145	});
146
147	return {
148		abortAll: function(){
149		var r = [];
150		jQuery.each(Q, function(i, jqx){
151			r.push(jqx._id);
152			jqx.abort();
153		});
154		return r;
155		}
156	};
157})();
158
159/** basename - this function will return the basename
160 *  of the php script called
161 *  @args path - the document.url
162 *  @args suffix - remove the named suffix from the file */
163function basename(path, suffix) {
164	var b = path;
165	var lastChar = b.charAt(b.length - 1);
166
167	if (lastChar === '/' || lastChar === '\\\\') {
168		b = b.slice(0, -1);
169	}
170
171	if (b.indexOf('?') > 0) {
172		var questionPosition = b.indexOf('?');
173		b = b.slice(0, questionPosition);
174	}
175
176	b = b.replace(/^.*[\\/\\\\]/g, '');
177
178	if (suffix !== undefined && b.substr(b.length - suffix.length) == suffix) {
179		b = b.substr(0, b.length - suffix.length);
180	}
181
182	return b;
183}
184
185/** getTimestampFromDate - Simple function to convert a MySQL Date
186 * to a timestamp */
187function getTimestampFromDate(dateStamp) {
188	if (typeof dateStamp != 'undefined') {
189		var dateParts = dateStamp.split(' ');
190		var timeParts = dateParts[1].split(':');
191
192		dateParts = dateParts[0].split('-');
193		var date = new Date(dateParts[0], parseInt(dateParts[1], 10) - 1, dateParts[2], timeParts[0], timeParts[1]);
194
195		return date.getTime() / 1000;
196	}
197	return '';
198}
199
200/** base64_encode - Simple function to base64 encode a utf-8 string */
201function base64_encode(string) {
202	return btoa(unescape(encodeURIComponent(string)));
203}
204
205/** getQueryString - this function will return the value
206 *  of the get request variable defined as input.
207 *  @args name - the variable name to return */
208function getQueryString(name) {
209	var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
210	return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
211}
212
213
214/** delayKeyup - this function will delay the keyup to
215 *  provide debouncing of input strokes on the keyboard
216 *  this preventing your backend server from becoming overloaded
217 *  usage: $("#yourid").delayKeyup(function(){ console.log('do something'); }, 500);
218 *  @args name - the variable name to return */
219$.fn.delayKeyup = function(callback, ms){
220	var timer = 0;
221	$(this).keyup(function(){
222		clearTimeout (timer);
223		timer = setTimeout(callback, ms);
224	});
225	return $(this);
226};
227
228/** bindFirst - Function ensures that the event is found at the top
229 * of the event stack. */
230$.fn.bindFirst = function(which, handler) {
231	var $el = $(this);
232	$el.off(which, handler);
233	$el.on(which, handler);
234
235	var events = $._data($el[0]).events;
236	var registered = events[which];
237	registered.unshift(registered.pop());
238
239	events[which] = registered;
240};
241
242/** replaceOptions - function replaces the options in a select dropdown */
243$.fn.replaceOptions = function(options, selected) {
244	var self, $option;
245
246	this.empty();
247	self = this;
248
249	$.each(options, function(index, option) {
250		if (selected == option.value) {
251			$option = $('<option></option>')
252			.attr('value', option.value)
253			.prop('selected', true)
254			.text(option.text);
255		} else {
256			$option = $('<option></option>')
257			.attr('value', option.value)
258			.text(option.text);
259		}
260		self.append($option);
261	});
262};
263
264/** textWidth - This function will return the natural width of a string
265 *  without any wrapping. */
266$.fn.textWidth = function(text){
267	var org = $(this);
268	var html = $('<span style="display:none;white-space:nowrap;position:absolute;width:auto;left:-9999px">' + (text || org.text()) + '</span>');
269	if (!text) {
270		html.css('font-family', org.css('font-family'));
271		html.css('font-weight', org.css('font-weight'));
272		html.css('font-size',   org.css('font-size'));
273		html.css('padding',     org.css('padding'));
274		html.css('margin',      org.css('margin'));
275	}
276	$('body').append(html);
277	var width = html.width();
278	html.remove();
279	return width;
280};
281
282/** textBoxWidth - This function will return the natural width of a string
283 *  without any wrapping. */
284$.fn.textBoxWidth = function() {
285	var org = $(this);
286	if (org.val()) {
287		var text = encodeURIComponent(org.val());
288	} else {
289		var text = encodeURIComponent(org.text());
290	}
291
292	var html = $('<span style="display:none;white-space:nowrap;position:absolute;width:auto;left:-9999px">' + text + '</span>');
293	html.css('font-family', org.css('font-family'));
294	html.css('font-weight', org.css('font-weight'));
295	html.css('font-size',   org.css('font-size'));
296	html.css('padding',     org.css('padding'));
297	html.css('margin',      org.css('margin'));
298	$('body').append(html);
299	var width = html.width();
300	html.remove();
301	return width;
302};
303
304/** classes - This function will return an array of all
305 *  classes of an element */
306$.fn.classes = function(callback) {
307	var classes = [];
308	$.each(this, function(i, v) {
309		var splitClassName = v.className.split(/\s+/);
310		for (var j in splitClassName) {
311			var className = splitClassName[j];
312			if (-1 === classes.indexOf(className)) {
313				classes.push(className);
314			}
315		}
316	});
317	if ('function' == typeof callback) {
318		for (var i in classes) {
319			callback(classes[i]);
320		}
321	}
322	return classes;
323};
324
325/** These three functions will set the cursor into
326 *  a textbox or textarea and optionally select characters */
327$.fn.setCursorPosition = function(position) {
328	if (this.length == 0) return this;
329	return this.setSelection(position, position);
330};
331
332$.fn.selectRange = function(start, end) {
333	if(!end) end = start;
334	return this.each(function() {
335		if (this.setSelectionRange) {
336			this.focus();
337			this.setSelectionRange(start, end);
338		} else if (this.createTextRange) {
339			var range = this.createTextRange();
340			range.collapse(true);
341			range.moveEnd('character', end);
342			range.moveStart('character', start);
343			range.select();
344		}
345	});
346
347	//return this;
348};
349
350$.fn.focusEnd = function() {
351	this.setCursorPosition($(this).val().length);
352	return this;
353};
354
355$.fn.getObjectDetails = function() {
356	var coords = {};
357
358	coords.width  = $(this).outerWidth();
359	coords.height = $(this).outerHeight();
360	coords.left = 0;
361	coords.top  = 0;
362
363	$(this).parentsUntil('body').each(function(){
364		coords.left += $(this).position().left;
365		coords.top  += $(this).position().top;
366	});
367
368	return coords;
369};
370
371$.fn.serializeForm = function() {
372	var arrayData, objectData;
373	arrayData = this.serializeArray();
374	formID = $(this).attr('id');
375	arrayData = arrayData.concat(
376		$('#'+formID+' input[type=checkbox]:not(:checked)').map(function() {
377			return {"name": this.name, "value": $(this).is(':checked') ? 'on':''}
378		}).get());
379
380	objectData = {};
381
382	$.each(arrayData, function() {
383		var value;
384
385		if (this.value != null) {
386			value = this.value;
387		} else {
388			value = '';
389		}
390
391		if (objectData[this.name] != null) {
392			if (!objectData[this.name].push) {
393				objectData[this.name] = [objectData[this.name]];
394			}
395
396			objectData[this.name].push(value);
397		} else {
398			objectData[this.name] = value;
399		}
400	});
401
402	return objectData;
403};
404
405$.fn.serializeObject = function() {
406	var arrayData, objectData, formID;
407	arrayData = this.serializeArray();
408	formID = $(this).attr('id');
409
410	objectData = {};
411
412	$.each(arrayData, function() {
413		var value;
414
415		if (this.value != null) {
416			value = this.value;
417		} else {
418			value = '';
419		}
420
421		if (objectData[this.name] != null) {
422			if (!objectData[this.name].push) {
423				objectData[this.name] = [objectData[this.name]];
424			}
425
426			objectData[this.name].push(value);
427		} else {
428			objectData[this.name] = value;
429		}
430	});
431
432	return objectData;
433};
434
435// Borrowed from mustache.js
436function escapeString(string) {
437	var entityMap = {
438		'<': '&lt;',
439		'>': '&gt;',
440		'"': '&quot;',
441		"'": '&#39;',
442		'`': '&#x60;'
443	};
444
445	return String(string).replace(/[<>"'`]/g, function fromEntityMap (s) {
446		return entityMap[s];
447	});
448}
449
450// Plugin to apply numeric format for tablesorter
451$.tablesorter.addParser({
452	id: 'numberFormat',
453	is: function(s) {
454		return /^[0-9]?[0-9,\.]*$/.test(s);
455	},
456	format: function(s) {
457		return $.tablesorter.formatFloat(s.replace(/,/g, ''));
458	},
459	type: 'numeric'
460});
461
462/** Mini jquery plugin to determine if an element has a scrollbar present */
463(function($) {
464    $.fn.hasScrollBar = function() {
465        return this.get(0).scrollHeight > this.outerHeight();
466    };
467})(jQuery);
468
469/** Mini jquery plugin to create a bind to show/hide events */
470(function ($) {
471	$.each(['show', 'hide'], function (i, ev) {
472		var el = $.fn[ev];
473		$.fn[ev] = function () {
474			this.trigger(ev);
475			return el.apply(this, arguments);
476		};
477	});
478})(jQuery);
479
480// Helper function to get text dimensions
481(function($) {
482	$.textMetrics = function(el) {
483		var h = 0, w = 0;
484
485		var div = document.createElement('div');
486		document.body.appendChild(div);
487		$(div).css({
488			position: 'absolute',
489			left: -1000,
490			top: -1000,
491			display: 'none'
492		});
493
494		$(div).html($(el).html());
495
496		var styles = ['font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing'];
497
498		$(styles).each(function() {
499			var s = this.toString();
500			$(div).css(s, $(el).css(s));
501		});
502
503		var h = $(div).outerHeight();
504		var w = $(div).outerWidth();
505
506		$(div).remove();
507
508		var ret = {
509			height: h,
510			width: w
511		};
512
513		return ret;
514	}
515})(jQuery);
516
517// helper function which selects row range when shift key is pressed during click
518function updateCheckboxes(checkboxes, clicked_element) {
519	var prev_checkbox = clicked_element.closest('table').find('[data-prev-check]:checkbox');
520
521	if (!prev_checkbox.length) {
522		return;
523	}
524
525	var check = prev_checkbox.attr('data-prev-check') == 'true';
526	var start = checkboxes.index(prev_checkbox);
527	var stop = checkboxes.index(clicked_element);
528	var i = Math.min(start, stop);
529	var j = Math.max(start, stop);
530
531	for (var k = i; k <= j; k++) {
532		var tr = $(checkboxes[k]).prop('checked', check).closest('tr');
533		if (check) {
534			tr.addClass('selected');
535		} else {
536			tr.removeClass('selected');
537		}
538	}
539}
540
541/** applySelectorVisibility - This function set's the initial visibility
542 *  of graphs for creation. Is will scan the against preset variables
543 *  taking action as required to enable or disable rows. */
544function applySelectorVisibilityAndActions() {
545	// Change for accessibility
546	$('input[type="radio"]').off('click').on('click', function() {
547		if ($(this).is(':checked')) {
548			$(this).attr('aria-checked', 'true');
549		} else {
550			$(this).attr('aria-checked', 'false');
551		}
552	});
553
554	// Apply disabled/enabled status first for Graph Templates
555	$('tr[id^="gt_line"]').each(function(data) {
556		var id = $(this).attr('id');
557		var search = id.substr(7);
558		if ($.inArray(search, gt_created_graphs) >= 0) {
559			$(this).addClass('disabled_row');
560			$(this).find(':checkbox').prop('disabled', true);
561		}
562	});
563
564	// Create Actions for Rows
565	$('tr[id^="gt_line"].selectable:not(.disabled_row)').off('click').on('click', function(event) {
566		selectUpdateRow(event, $(this));
567	});
568
569	// Create Actions for Rows
570	$('tr[id^="line"].selectable').filter(':not(.disabled_row)').off('click').on('click', function(event) {
571		selectUpdateRow(event, $(this));
572	});
573}
574
575function disableSelection() {
576	$('tr.selectable').css('-webkit-user-select','none');
577	$('tr.selectable').css('-moz-user-select','none');
578	$('tr.selectable').css('-ms-user-select','none');
579	$('tr.selectable').css('-o-user-select','none');
580	$('tr.selectable').css('user-select','none');
581}
582
583function enableSelection() {
584	$('tr.selectable').css('-webkit-user-select','');
585	$('tr.selectable').css('-moz-user-select','');
586	$('tr.selectable').css('-ms-user-select','');
587	$('tr.selectable').css('-o-user-select','');
588	$('tr.selectable').css('user-select','');
589}
590
591/** selectUpdateRow - Highlight a selectable row combined with checkbox
592 *  @arg event - The click event to support multiple selections
593 *  @arg element - The jQuery selected object */
594function selectUpdateRow(event, element) {
595	var checkboxes = element.closest('table').find('input[type=checkbox]:not(:disabled)');
596
597	if (event.shiftKey) {
598		updateCheckboxes(checkboxes, element.find(':checkbox'));
599	} else {
600		element.toggleClass('selected');
601		if (element.hasClass('selected')) {
602			element.find(':checkbox').prop('checked', true).attr('aria-checked', 'true').attr('data-prev-check', 'true');
603		} else {
604			element.find(':checkbox').prop('checked', false).removeAttr('aria-checked').removeAttr('data-prev-check');
605		}
606	}
607
608	if (element.closest('table').find(':checked').length) {
609		disableSelection();
610	} else {
611		enableSelection();
612	}
613}
614
615/** dqUpdateDeps - When a user changes the Graph dropdown for a data query
616 *  we have to check to see if those graphs are already created.
617 *  @arg snmp_query_id - The snmp query id the is current */
618function dqUpdateDeps(snmp_query_id) {
619	$('tr[id^="dqline'+snmp_query_id+'_"]').addClass('selectable').removeClass('disabled_row').find(':checkbox').prop('disabled', false);
620
621	var snmp_query_graph_id = $('#sgg_'+snmp_query_id).val();
622	var removeSelectAll = false;
623
624	// Check if select all is clicked
625	var allChecked = $('#all_'+snmp_query_id).is(':checked');
626
627	// Next for Data Queries
628	$('tr[id^="dqline'+snmp_query_id+'_"]').each(function(data) {
629		var id = $(this).attr('id');
630		var pieces = id.split('_');
631		var dq = pieces[0].substr(6);
632		var hash = pieces[1];
633
634		if ($.inArray(hash, created_graphs[snmp_query_graph_id]) >= 0) {
635			if ($(this).hasClass('selected')) {
636				removeSelectAll = true;
637			}
638
639			$(this).addClass('disabled_row').removeClass('selected').removeClass('selectable');
640			$(this).find(':checkbox').prop('disabled', true).prop('checked', false);
641		} else {
642			removeSelectAll = true;
643		}
644	});
645
646	if (allChecked && removeSelectAll) {
647		$('#all_'+snmp_query_id).prop('checked', false);
648	}
649
650	$('tr[id^="dqline'+snmp_query_id+'_"]').not('.disabled_row').off('click').on('click', function(event) {
651		selectUpdateRow(event, $(this));
652	});
653}
654
655/** selectAll - This function will select all non-disabled rows
656 *  @arg attrib - The Graph Type either graph template, or data query */
657function selectAll(attrib, checked) {
658	if (attrib == 'chk') {
659		if (checked == true) {
660			$('tr[id^="line"]:not(.disabled_row)').each(function(data) {
661				$(this).addClass('selected');
662				$(this).find(':checkbox').prop('checked', true).attr('aria-checked', 'true').attr('data-prev-check', 'true');
663			});
664			disableSelection();
665		} else {
666			$('tr[id^="line"]:not(.disabled_row)').each(function(data) {
667				$(this).removeClass('selected');
668				$(this).find(':checkbox').prop('checked', false).removeAttr('aria-checked').removeAttr('data-prev-check');
669			});
670		}
671	} else if (attrib == 'sg') {
672		if (checked == true) {
673			$('tr[id^="gt_line"]:not(.disabled_row)').each(function(data) {
674				$(this).addClass('selected');
675				$(this).find(':checkbox').prop('checked', true).attr('aria-checked', 'true').attr('data-prev-check', 'true');
676			});
677			disableSelection();
678		} else {
679			$('tr[id^="gt_line"]:not(.disabled_row)').each(function(data) {
680				$(this).removeClass('selected');
681				$(this).find(':checkbox').prop('checked', false).removeAttr('aria-checked').removeAttr('data-prev-check');
682			});
683		}
684	} else if (attrib.startsWith('sg_', 0)) {
685		var attribSplit = attrib.split('_');
686		var dq   = attribSplit[1];
687
688		if (checked == true) {
689			$('tr[id^="dqline'+dq+'\_"]:not(.disabled_row)').each(function(data) {
690				$(this).addClass('selected');
691				$(this).find(':checkbox').prop('checked', true).attr('aria-checked', 'true').attr('data-prev-check', 'true');
692			});
693			disableSelection();
694		} else {
695			$('tr[id^="dqline'+dq+'\_"]:not(.disabled_row)').each(function(data) {
696				$(this).removeClass('selected');
697				$(this).find(':checkbox').prop('checked', false).removeAttr('aria-checked').removeAttr('data-prev-check');
698			});
699		}
700	} else {
701		if (checked == true) {
702			$('tr[id^="line_'+attrib+'"]:not(.disabled_row)').each(function(data) {
703				$(this).addClass('selected');
704				$(this).find(':checkbox').prop('checked', true).attr('aria-checked', 'true').attr('data-prev-check', 'true');
705			});
706			disableSelection();
707		} else {
708			$('tr[id^="line_'+attrib+'"]:not(.disabled_row)').each(function(data) {
709				$(this).removeClass('selected');
710				$(this).find(':checkbox').prop('checked', false).removeAttr('aria-checked').removeAttr('data-prev-check');
711			});
712		}
713	}
714}
715
716/* graph filtering */
717function applyTimespanFilterChange() {
718	var href;
719
720	href  = '?header=false&predefined_timespan=' + $('#predefined_timespan').val();
721	href += '&predefined_timeshift=' + $('#predefined_timeshift').val();
722
723	loadPageNoHeader(href);
724}
725
726/** cactiReturnTo - This function simply returns to the previous page
727 *  @args href - the previous page */
728function cactiReturnTo(href) {
729	if (typeof href == 'string') {
730		href = href + (href.indexOf('?') > 0 ? '&':'?') + 'header=false';
731		loadPageNoHeader(href);
732	} else {
733		href = document.location.href;
734		href = href + (href.indexOf('?') > 0 ? '&':'?') + 'header=false';
735		loadPageNoHeader(href);
736	}
737}
738
739/** applySkin - This function re-asserts all javascript behavior to a page
740 *  that can't be set using a live attribute 'on()' */
741function applySkin() {
742	pageName = basename($(location).attr('pathname'));
743
744	$('#messageContainer').remove();
745
746	if (!theme || theme == 'classic') {
747		theme = 'classic';
748
749		// debounce submits
750		$('form').submit(function() {
751			$('input[type="submit"], button[type="submit"]').not('.import, .export').prop('disabled', true);
752		});
753	} else {
754		$('input[type="submit"], input[type="button"], button').button();
755
756		// Handle re-index changes
757		$('fieldset.reindex_methods').buttonset();
758
759		// debounce submits
760		$('form').submit(function() {
761			$('input[type="submit"], button[type="submit"]').not('.import, .export').button('disable');
762		});
763	}
764
765	setGraphTabs();
766
767	setupSortable();
768
769	setupBreadcrumbs();
770
771	applyTableSizing();
772
773	setupPageTimeout();
774
775	CsrfMagic.end();
776
777	setupSpecialKeys();
778
779	setupCollapsible();
780
781	ajaxAnchors();
782
783	applySelectorVisibilityAndActions();
784
785	$('.helpPage').off('click').on('click', function(event) {
786		event.stopPropagation();
787		getCactiHelp($(this).attr('data-page'));
788	});
789
790	if (typeof themeReady == 'function') {
791		themeReady();
792	}
793
794	makeFiltersResponsive();
795
796	setupResponsiveMenuAndTabs();
797
798	setupButtonStyle();
799
800	// Debug message actions
801	$('table.debug tr:nth-child(1)').off('click').on('click', function() {
802		if ($(this).parent().find('table').is(':visible')) {
803			$(this).parent().find('table').slideUp('fast');
804		} else {
805			$(this).parent().find('table').slideDown('fast');
806		}
807	});
808
809	$('.cactiTableCopy').off('click').on('click', function(event) {
810		event.preventDefault();
811		event.stopPropagation();
812		var containerId =  $(this).attr('id');
813		copyToClipboard(containerId);
814	});
815
816	$('i, a, th, img, input, label, select, button, .drillDown, .checkboxSlider')
817	.tooltip({
818		close: true
819	})
820	.on('focus', function() {
821		if ($(this).tooltip('instance')) {
822			$(this).tooltip('close');
823		}
824	})
825	.on('click', function() {
826		if ($(this).tooltip('instance')) {
827			$(this).tooltip('close');
828		}
829	});
830
831	$(document).tooltip({
832		items: 'div.cactiTooltipHint, span.cactiTooltipHint, .checkboxSlider',
833		content: function() {
834			var element = $(this);
835
836			if (element.is('div')) {
837				var text = DOMPurify.sanitize($(this).find('span').html());
838			} else if (element.is('span') || element.is('a')) {
839				var text = DOMPurify.sanitize($(this).prop('title'));
840			}
841
842			return text;
843		}
844	});
845
846	$(document).on('keyup keydown', function(event) {
847		shiftPressed = event.shiftKey;
848	});
849
850	$('#main').css('display', 'table');
851
852	var showPage = $('#main').map(function(i, el) {
853		var dfd = $.Deferred();
854		$(el).show(function() {
855			dfd.resolve();
856		});
857
858		return dfd;
859	});
860
861	keepWindowSize();
862
863	displayMessages();
864
865	renderLanguages();
866}
867
868function renderLanguages() {
869	if ($('select#user_language').selectmenu('instance') !== undefined) {
870		$('select#user_language').selectmenu('destroy');
871
872		$('select#user_language').languageselect({
873			width: '220',
874			change: function() {
875				var name  = $(this).attr('id');
876				var value = $(this).val();
877				var page  = basename(location.pathname);
878				if (page == 'auth_profile.php') {
879					$.post('auth_profile.php?tab='+currentTab+'&action=update_data', {
880						__csrf_magic: csrfMagicToken,
881						name: name,
882						value: value
883						}, function() {
884						if (name == 'selected_theme' || name == 'user_language') {
885							document.location = 'auth_profile.php?action=edit';
886						}
887					});
888				}
889			}
890		}).languageselect('menuWidget').addClass('ui-menu-icons customicons');
891	}
892
893	if ($('select#i18n_default_language').selectmenu('instance') !== undefined) {
894		$('select#i18n_default_language').selectmenu('destroy');
895
896		$('select#i18n_default_language').languageselect({
897			width: '220'
898		}).languageselect('menuWidget').addClass('ui-menu-icons customicons');
899	}
900
901	$('#user_language-menu').css('max-height', '200px');
902	$('#i18n_default_language-menu').css('max-height', '200px');
903}
904
905function setupButtonStyle() {
906	if ($('input#submit').length) {
907		$('input#submit').addClass('ui-state-active');
908	} else if ($('input#return').length) {
909		$('input#return').addClass('ui-state-active');
910	}
911
912	if ($('input#refresh').length) {
913		$('input#refresh').addClass('ui-state-active');
914	}
915
916	if ($('input#go').length) {
917		$('input#go').addClass('ui-state-active');
918	}
919}
920
921function raiseMessage(title, header, detail, level) {
922	var origErrorReasonTitle    = errorReasonTitle;
923	var origErrorOnPage         = errorOnPage;
924	var origMixedReasonTitle    = mixedReasonTitle;
925	var origMixedOnPage         = mixedOnPage;
926	var origSessionMessageTitle = sessionMessageTitle;
927	var origSessionMessageSave  = sessionMessageSave;
928	var origSessionMessage      = sessionMessage;
929
930	sessionMessage.message = detail;
931	sessionMessage.level   = level;
932
933	if (level == MESSAGE_LEVEL_ERROR) {
934		errorReasonTitle  = title;
935		errorOnPage       = header;
936	} else if (level == MESSAGE_LEVEL_MIXED) {
937		mixedOnPage       = header;
938		mixedReasonTitle  = title;
939	} else {
940		sessionMessageTitle = title;
941		sessionMessageSave  = header;
942	}
943
944	displayMessages();
945
946	if (level == MESSAGE_LEVEL_ERROR) {
947		errorReasonTitle  = origErrorReasonTitle;
948		errorOnPage       = origErrorOnPage;
949	} else if (level == MESSAGE_LEVEL_MIXED) {
950		mixedOnPage      = origMixedOnPage;
951		mixedReasonTitle = origMixedReasonTitle;
952	} else {
953		sessionMessageTitle = origSessionMessageTitle;
954		sessionMessageSave  = origSessionMessageSave;
955	}
956
957	sessionMessage = origSessionMessage;
958}
959
960function displayMessages() {
961	var error   = false;
962	var title   = '';
963	var header  = '';
964
965	if (typeof sessionMessageTimer == 'function' || sessionMessageTimer !== null) {
966		clearInterval(sessionMessageTimer);
967	}
968
969	if (sessionMessage == null) {
970		return;
971	}
972
973	if (typeof sessionMessage.level != 'undefined') {
974		if (sessionMessage.level == MESSAGE_LEVEL_ERROR) {
975			title = errorReasonTitle;
976			header = errorOnPage;
977			var sessionMessageButtons = {
978				'Ok': {
979					text: sessionMessageOk,
980					id: 'btnSessionMessageOk',
981					click: function() {
982						$(this).dialog('close');
983					}
984				}
985			};
986
987			sessionMessageOpen = {};
988		} else if (sessionMessage.level == MESSAGE_LEVEL_MIXED) {
989			title  = mixedReasonTitle;
990			header = mixedOnPage;
991			var sessionMessageButtons = {
992				'Ok': {
993					text: sessionMessageOk,
994					id: 'btnSessionMessageOk',
995					click: function() {
996						$(this).dialog('close');
997					}
998				}
999			};
1000
1001			sessionMessageOpen = {};
1002		} else if (sessionMessage.level == MESSAGE_LEVEL_CSRF) {
1003			var href = document.location.href;
1004			href = href + (href.indexOf('?') > 0 ? '&':'?') + 'csrf_timeout=true';
1005			document.location = href;
1006			return false;
1007		} else {
1008			title = sessionMessageTitle;
1009			header = sessionMessageSave;
1010			var sessionMessageButtons = {
1011				'Pause': {
1012					text: sessionMessagePause,
1013					id: 'btnSessionMessagePause',
1014					click: function() {
1015						if (sessionMessageTimer != null) {
1016							clearInterval(sessionMessageTimer);
1017							sessionMessageTimer = null;
1018						}
1019						$('#btnSessionMessagePause').remove();
1020						$('#btnSessionMessageOk').html('<span class="ui-button-text">' + sessionMessageOk + '</span>');
1021					}
1022				},
1023				'Ok': {
1024					text: sessionMessageOk,
1025					id: 'btnSessionMessageOk',
1026					click: function() {
1027						$(this).dialog('close');
1028						$('#messageContainer').remove();
1029						clearInterval(sessionMessageTimer);
1030					}
1031				}
1032			};
1033
1034			sessionMessageOpen = function() {
1035				sessionMessageCountdown(5000);
1036			}
1037		}
1038
1039		var returnStr = '<div id="messageContainer" style="display:none">' +
1040			'<h4>' + header + '</h4>' +
1041			'<p style="display:table-cell;overflow:auto"> ' + sessionMessage.message + '</p>' +
1042			'</div>';
1043
1044		$('#messageContainer').remove();
1045		$('body').append(returnStr);
1046
1047		var messageWidth = $(window).width();
1048		if (messageWidth > 600) {
1049			messageWidth = 600;
1050		} else {
1051			messageWidth -= 50;
1052		}
1053
1054		$('#messageContainer').dialog({
1055			open: sessionMessageOpen,
1056			draggable: true,
1057			resizable: false,
1058			height: 'auto',
1059			minWidth: messageWidth,
1060			maxWidth: 800,
1061			maxHeight: 600,
1062			title: title,
1063			buttons: sessionMessageButtons
1064		});
1065
1066		sessionMessage = null;
1067	}
1068}
1069
1070function sessionMessageCountdown(time) {
1071	var sessionMessageTimeLeft = (time / 1000);
1072
1073	$('#btnSessionMessageOk').html('<span class="ui-button-text">' + sessionMessageOk + ' (' + sessionMessageTimeLeft + ')</span>');
1074
1075	sessionMessageTimer = setInterval(function() {
1076		sessionMessageTimeLeft--;
1077
1078		$('#btnSessionMessageOk').html('<span class="ui-button-text">' + sessionMessageOk + ' (' + sessionMessageTimeLeft + ')</span>');
1079
1080		if (sessionMessageTimeLeft <= 0) {
1081			clearInterval(sessionMessageTimer);
1082			$('#messageContainer').dialog('close');
1083			$('#messageContainer').remove();
1084		}
1085	}, 1000);
1086}
1087
1088function markFilterTDs(child, filterNum) {
1089	trNum = 0;
1090
1091	$('#'+child).find('tr').each(function() {
1092		tdNum = 0;
1093		$(this).find('td').each(function() {
1094			$(this).attr('id', 'fn'+filterNum+'tr'+trNum+'td'+tdNum);
1095			tdNum++;
1096		});
1097		trNum++;
1098	});
1099}
1100
1101function makeFiltersResponsive() {
1102	storage = Storages.localStorage;
1103
1104	filterNum = 0;
1105
1106	if ($('div.cactiTableButton').closest('.cactiTable').not('#dqdebug').find('.filterTable').length) {
1107		$('div.cactiTableButton').closest('.cactiTable').not('#dqdebug').each(function() {
1108			if ($(this).find('.filterTable').length) {
1109				filterHeader = $(this).closest('.cactiTable');
1110				id     = filterHeader.attr('id');
1111				child  = id+'_child';
1112				filterContents = $('#'+child);
1113
1114				filterHeader.find('.cactiTableTitle, .cactiTableButton').css('cursor', 'pointer');
1115
1116				if (pageHasHidableColumnsAndProfile()) {
1117					if (filterHeader.find('.cactiSwitchConstraints').length == 0) {
1118						if (hScroll) {
1119							$('#main, .cactiConsoleContentArea').css({ 'overflow-x': 'visible' });
1120							filterHeader.find('div.cactiTableButton').append('<span class="cactiSwitchConstraintWrapper"><a title="'+tableConstraints+'" class="linkOverDark cactiSwitchConstraints" href="#"><i id="overflow" class="fa fa-compress"></i></a></span>');
1121						} else {
1122							$('#main, .cactiConsoleContentArea').css({ 'overflow-x': 'hidden' });
1123							filterHeader.find('div.cactiTableButton').append('<span class="cactiSwitchConstraintWrapper"><a title="'+tableConstraints+'" class="linkOverDark cactiSwitchConstraints" href="#"><i id="overflow" class="fa fa-expand"></i></a></span>');
1124						}
1125
1126						$('.cactiSwitchConstraints').off('click').on('click', function(event) {
1127							event.preventDefault();
1128							event.stopPropagation();
1129
1130							hScroll = !hScroll;
1131
1132							$.post(urlPath + 'auth_profile.php?tab=general&action=update_data', {
1133								__csrf_magic: csrfMagicToken,
1134								name: 'enable_hscroll',
1135								value: hScroll ? 'on':''
1136								}, function() {
1137								if (hScroll) {
1138									$('#main, .cactiConsoleContentArea').css({ 'overflow-x': 'visible' });
1139									$('#overflow').removeClass('fa-expand').addClass('fa-compress');
1140
1141									resetTables();
1142								} else {
1143									$('#main, .cactiConsoleContentArea').css({ 'overflow-x': 'hidden' });
1144									$('#overflow').removeClass('fa-compress').addClass('fa-expand');
1145
1146									tuneTables();
1147								}
1148
1149							});
1150						});
1151					}
1152				}
1153
1154				if (filterHeader.find('div.cactiTableButton').find('.cactiFilterAdd').length) {
1155					markFilterTDs(child, filterNum);
1156
1157					$('.cactiFilterAdd').tooltip();
1158				}
1159
1160				if (filterContents.find('#export').length) {
1161					title = $('#export').attr('value');
1162					filterHeader.find('div.cactiTableButton').append('<span title="'+title+'" style="display:none;" class="cactiFilterExport"><i class="fa fa-arrow-down"></i></span>');
1163
1164					$('.cactiFilterExport').off('click').on('click', function(event) {
1165						event.stopPropagation();
1166						$('#export').trigger('click');
1167					}).tooltip();
1168				}
1169
1170				if (filterContents.find('#import').length) {
1171					title = $('#import').attr('value');
1172					filterHeader.find('div.cactiTableButton').append('<span title="'+title+'" style="display:none;" class="cactiFilterImport"><i class="fa fa-arrow-up"></i></span>');
1173
1174					$('.cactiFilterImport').off('click').on('click', function(event) {
1175						event.stopPropagation();
1176						$('#import').trigger('click');
1177					}).tooltip();
1178				}
1179
1180				if (filterContents.find('#clear').length) {
1181					if (filterHeader.find('.cactiFilterClear').length == 0) {
1182						filterHeader.find('div.cactiTableButton').append('<span title="'+clearFilterTitle+'" style="display:none;" class="cactiFilterClear"><i class="fa fa-trash-alt"></i></span>');
1183					}
1184
1185					$('.cactiFilterClear').off('click').on('click', function(event) {
1186						event.stopPropagation();
1187						$('#clear').trigger('click');
1188					}).tooltip();
1189				}
1190
1191				toggleFilterAndIcon(id, child, true);
1192
1193				filterHeader.find('.cactiTableTitle, .cactiTableButton').off('click').on('click', function() {
1194					id     = $(this).closest('.cactiTable').attr('id');
1195					child  = id+'_child';
1196					toggleFilterAndIcon(id, child, false);
1197				});
1198
1199				if (storage.isSet('filterVisibility')) {
1200					state = storage.get('filterVisibility');
1201				} else {
1202					state = 'visible';
1203				}
1204
1205				if (state == 'hidden') {
1206					if (filterHeader.find('.cactiFilterState').length == 0) {
1207						filterHeader.find('div.cactiTableButton').append('<span class="cactiFilterState"><i class="fa fa-angle-double-down"></i></span>');
1208					}
1209				} else {
1210					if (filterHeader.find('.cactiFilterState').length == 0) {
1211						filterHeader.find('div.cactiTableButton').append('<span class="cactiFilterState"><i class="fa fa-angle-double-up"></i></span>');
1212					}
1213				}
1214
1215				if (typeof showHideFilter != 'undefined') {
1216					$('.cactiFilterState').attr('title', showHideFilter).tooltip();
1217				}
1218
1219				filterNum++;
1220			}
1221		});
1222	} else if ($('#dqdebug').length) {
1223		$('#dqdebug').find('div.cactiTableButton').each(function() {
1224			if ($(this).find('a').length) {
1225				anchors = $('div.cactiTableButton').find('a');
1226				anchors.each(function(){
1227					$(this).attr('title', $(this).text());
1228				});
1229				anchors.not('.cactiTableCopy').addClass('fa fa-trash-alt');
1230				anchors.filter('.cactiTableCopy').addClass('fa fa-copy');
1231				anchors.tooltip().text('');
1232			}
1233		});
1234	}
1235
1236	if ($('#form_graph_view').length) {
1237		$('#form_graph_view').filter('input, select').not('#date1, #date2').click(function() {
1238			closeDateFilters();
1239		});
1240	}
1241}
1242
1243function toggleFilterAndIcon(id, child, initial) {
1244	storage = Storages.localStorage;
1245
1246	if (storage.isSet('filterVisibility')) {
1247		state = storage.get('filterVisibility');
1248	} else {
1249		state = 'visible';
1250	}
1251
1252	if (initial) {
1253		if (state == 'hidden') {
1254			$('#'+child).hide();
1255			$('#'+id).find('.cactiFilterClear, .cactiFilterImport, .cactiFilterExport').show();
1256		}
1257	} else if ($('#'+child).is(':visible')) {
1258		$('#'+child).hide();
1259		$('#'+id).find('.cactiFilterClear, .cactiFilterImport, .cactiFilterExport').show();
1260		$('.cactiFilterState').find('i').removeClass('fa-angle-double-up').addClass('fa-angle-double-down');
1261		storage.set('filterVisibility', 'hidden');
1262	} else {
1263		$('#'+child).show();
1264		$('#'+id).find('.cactiFilterClear, .cactiFilterImport, .cactiFilterExport').hide();
1265		$('.cactiFilterState').find('i').removeClass('fa-angle-double-down').addClass('fa-angle-double-up');
1266		storage.set('filterVisibility', 'visible');
1267	}
1268
1269	$(window).trigger('resize');
1270}
1271
1272function setGraphTabs() {
1273	page = window.location.href;
1274
1275	if (page.indexOf('graph_view.php') >= 0) {
1276		$('.lefttab').removeClass('selected');
1277		$('#tab-graphs').addClass('selected');
1278
1279		if (page.indexOf('action=tree') > 0) {
1280			$('#preview, #listview, #treeview').removeClass('selected').prop('aria-selected', false);
1281			$('#treeview').addClass('selected').prop('aria-selected', true);
1282		} else if (page.indexOf('action=list') > 0) {
1283			$('#preview, #listview, #treeview').removeClass('selected').prop('aria-selected', false);
1284			$('#listview').addClass('selected').prop('aria-selected', true);
1285		} else if (page.indexOf('action=preview') > 0) {
1286			$('#preview, #listview, #treeview').removeClass('selected').prop('aria-selected', false);
1287			$('#preview').addClass('selected').prop('aria-selected', true);
1288		}
1289
1290		/* update menu selection */
1291		if (theme == 'classic') {
1292			$('.righttab').each(function() {
1293				if ($(this).hasClass('selected')) {
1294					if ($(this).find('img').length) {
1295						imageSRC = $(this).find('img').attr('src');
1296						if (imageSRC.indexOf('_down') < 0) {
1297							imageSRC = imageSRC.replace('.gif', '_down.gif');
1298							$(this).find('img').attr('src', imageSRC);
1299						}
1300					}
1301				} else {
1302					if ($(this).find('img').length) {
1303						imageSRC = $(this).find('img').attr('src');
1304						if (imageSRC.indexOf('_down') >= 0) {
1305							imageSRC = imageSRC.replace('_down.gif', '.gif');
1306							$(this).find('img').attr('src', imageSRC);
1307						}
1308					}
1309				}
1310			});
1311		}
1312	}
1313}
1314
1315function setupResponsiveMenuAndTabs() {
1316	$('.maintabs a.lefttab, .dropdownMenu a, .menuoptions a, #gtabs a.righttab').not('[href^="http"], [href^="https"], [href^="#"], [target="_blank"]').off('click').on('click', function(event) {
1317		page = basename($(this).attr('href'));
1318
1319		if (page == 'logout.php' || page == 'auth_changepassword.php') {
1320			return;
1321		} else if (page == 'index.php' && $(this).attr('href').indexOf('login') >= 0) {
1322			return;
1323		} else {
1324			event.preventDefault();
1325		}
1326
1327		if ($('#navigation').length) {
1328			var hasNavigation = true;
1329		} else {
1330			var hasNavigation = false;
1331		}
1332
1333		if (hasNavigation && ($(this).hasClass('selected') || (pageName == page && pageName != 'graph_view.php') && pageName != 'link.php')) {
1334			handleUserMenu(true);
1335		} else {
1336			var id   = $(this).attr('id');
1337			var href = $(this).attr('href');
1338
1339			loadTopTab(href, id, false);
1340		}
1341	});
1342
1343	$(window).on('orientationchange, fullscreenchange', function() {
1344		responsiveUI('force');
1345	});
1346}
1347
1348function getMenuState() {
1349	var storage = Storages.localStorage;
1350
1351	if (storage.isSet('menuState_' + pageName)) {
1352		state = storage.get('menuState_' + pageName);
1353
1354		return state;
1355	} else {
1356		return 'visible';
1357	}
1358}
1359
1360function responsiveUI(event) {
1361	var tree = false;
1362
1363	if (event != 'force') {
1364	    if (new Date() - resizeTime < resizeDelta) {
1365			var myEvent = event;
1366			setTimeout(function() {
1367				responsiveUI(myEvent);
1368			}, resizeDelta);
1369
1370			return false;
1371		} else {
1372			resizeTimeout = false;
1373		}
1374	}
1375
1376	if ($('.cactiTreeNavigationArea').length > 0) {
1377		tree = true;
1378	} else {
1379		tree = false;
1380	}
1381
1382	handleUserMenu(false);
1383
1384	var mainWidth = getMainWidth();
1385
1386	/* change textbox and textarea widths */
1387	$('input[type="text"], textarea').each(function() {
1388		if ($(this).attr('type') == 'text') {
1389			var offset = 20;
1390		} else {
1391			var offset = 5;
1392		}
1393
1394		if (mainWidth != 100) {
1395			if ($(this).width() > mainWidth) {
1396				$(this).css('max-width', (mainWidth - offset)+'px');
1397			} else {
1398				$(this).css('max-width', '');
1399			}
1400
1401			if ($(this).width() > mainWidth) {
1402				$(this).css('max-width', (mainWidth - offset)+'px');
1403			}
1404
1405			if ($(this).parents('.formColumnRight').is(":visible") && $(this).width() > $(this).parents('.formColumnRight').prop('clientWidth')) {
1406				$(this).css('max-width', ($(this).parents('.formColumnRight').prop('clientWidth'))+'px');
1407			} else {
1408				$(this).css('max-width', '');
1409			}
1410		}
1411	});
1412
1413	$('.filterTable').each(function() {
1414		tuneFilter($(this), mainWidth);
1415	});
1416
1417	tuneTables();
1418}
1419
1420function getMainWidth() {
1421	// Subtract 15px for the scroll bar
1422	if ($('#navigation').length && $('#navigation').is(':visible')) {
1423		var mainWidth = $('body').outerWidth() - $('#navigation').width() - 15;
1424	} else {
1425		var mainWidth = $('body').outerWidth() - 15;
1426	}
1427
1428	return mainWidth;
1429}
1430
1431function getCactiHelp(cactiPage) {
1432	var url = urlPath + 'help.php?page=' + cactiPage;
1433
1434	$.getJSON(url, function(data) {
1435		if (data.status == 'Success') {
1436			window.open(data.location, '_blank');
1437		}
1438	});
1439}
1440
1441function responsiveResizeGraphs(initialize) {
1442	var mainWidth = getMainWidth() - 30;
1443	var myColumns = $('#columns').val();
1444	var isThumb   = $('#thumbnails').is(':checked');
1445
1446	if ($('.tableRowGraph:first').length) {
1447		var graphRow = $('.tableRowGraph:first').width();
1448	} else {
1449		var graphRow = 0;
1450	}
1451
1452	if ($('.graphDrillDown:first').length) {
1453		var drillDown = $('.graphDrillDown:first').outerWidth() + 15;
1454	} else {
1455		var drillDown = 0;
1456	}
1457
1458	if (myColumns == null) {
1459		myColumns = 1;
1460	}
1461
1462	if (mainWidth < graphRow) {
1463		graphRow = mainWidth - drillDown;
1464	} else if (graphRow == 0) {
1465		graphRow = mainWidth;
1466	}
1467
1468	// Dont resize if nothing changed
1469	if (typeof initialize == 'undefined' && (previousMainWidth == null || (previousMainWidth == mainWidth && previousColumns == myColumns))) {
1470		previousMainWidth = mainWidth;
1471		return true;
1472	}
1473
1474	var myWidth = parseInt((graphRow - (drillDown * myColumns)) / myColumns);
1475
1476	$('.graphimage').each(function() {
1477		var graph_id = $(this).attr('graph_id');
1478
1479		if (!(graph_id > 0)) {
1480			graph_id = $(this).attr('id').replace('wrapper_','');
1481			graph_id = $(this).attr('id').replace('graph_','');
1482		}
1483
1484		var rra_id = $(this).attr('rra_id');
1485		var type   = $(this).attr('graph_type');
1486
1487		var original_cwidth  = $('#wrapper_'+graph_id).attr('graph_width');
1488		var original_cheight = $('#wrapper_'+graph_id).attr('graph_height');
1489
1490		/* original image attributes */
1491		var image_width   = $(this).attr('image_width');
1492		var image_height  = $(this).attr('image_height');
1493		var canvas_top    = $(this).attr('canvas_top');
1494		var canvas_left   = $(this).attr('canvas_left');
1495		var canvas_width  = $(this).attr('canvas_width');
1496		var canvas_height = $(this).attr('canvas_height');
1497
1498		var remove_whcss = false;
1499		var ratio = myWidth / image_width;
1500
1501		/* optimize display and set correct ratio if image is full size */
1502		if (image_width * original_cwidth / canvas_width < myWidth) {
1503			remove_whcss = true;
1504			ratio = original_cwidth / canvas_width;
1505		}
1506
1507		// Dont change the size if the differential is small
1508		if (ratio > .97 && ratio < 1.03) {
1509			ratio = 1;
1510		}
1511
1512		var new_image_width       = parseInt(image_width * ratio)
1513		var new_image_height      = parseInt(image_height * ratio)
1514		var new_canvas_width      = parseInt(canvas_width  * ratio);
1515		var new_canvas_height     = parseInt(canvas_height * ratio);
1516		var new_canvas_graph_top  = parseInt(canvas_top  * ratio);
1517		var new_canvas_graph_left = parseInt(canvas_left * ratio);
1518
1519		$(this).attr('graph_width', new_canvas_width);
1520		$(this).attr('graph_height', new_canvas_height);
1521		$(this).attr('graph_top', new_canvas_graph_top);
1522		$(this).attr('graph_left', new_canvas_graph_left);
1523
1524		if (!remove_whcss || type == 'svg+xml') {
1525			$(this).css('width', new_image_width);
1526			$(this).css('height', new_image_height);
1527		} else {
1528			$(this).css('width', '');
1529			$(this).css('height', '');
1530			$(this).removeAttr('width');
1531			$(this).removeAttr('height');
1532		}
1533	});
1534
1535	previousMainWidth = mainWidth;
1536	previousColumns   = myColumns;
1537
1538	if ($('.cactiTreeNavigationArea').length) {
1539		resizeTreePanel();
1540	}
1541}
1542
1543function resizeTreePanel() {
1544	if (theme != 'classic') {
1545		var docHeight      = $(window).outerHeight();
1546		var navWidth       = $('.cactiTreeNavigationArea').width();
1547		var searchHeight   = $('.cactiTreeSearch').outerHeight();
1548		var pageHeadHeight = $('.cactiPageHead').outerHeight();
1549		var breadCrHeight  = $('.breadCrumbBar').outerHeight();
1550		var pageBottomHeight = $('.cactiPageBottom').outerHeight();
1551		//console.log('----------------------');
1552
1553		var jsTreeHeight  = Math.max.apply(Math, $('#jstree').children(':visible').map(function() {
1554			return $(this).outerHeight();
1555		}).get());
1556
1557		var treeAreaHeight = docHeight - pageHeadHeight - breadCrHeight - searchHeight - pageBottomHeight;
1558		//console.log('docHeight:' + docHeight);
1559		//console.log('searchHeight:' + searchHeight);
1560		//console.log('pageHeadHeight:' + pageHeadHeight);
1561		//console.log('pageBottomHeight:' + pageBottomHeight);
1562		//console.log('breadCrHeight:' + breadCrHeight);
1563		//console.log('jsTreeHeight:' + jsTreeHeight);
1564		//console.log('treeAreaHeight:' + treeAreaHeight);
1565
1566		$('#jstree').height(jsTreeHeight + 30);
1567		$('.cactiTreeNavigationArea').height(treeAreaHeight+searchHeight);
1568
1569		var visWidth = Math.max.apply(Math, $('#jstree').children(':visible').map(function() {
1570			return $(this).width();
1571		}).get());
1572
1573		if (visWidth < 0) {
1574			$('.cactiTreeNavigationArea').css('width', 0);
1575			$('.cactiGraphContentArea').css('margin-left', 0);
1576			$('.cactiTreeNavigationArea').css('overflow-x', '');
1577		} else if (visWidth < minTreeWidth) {
1578			$('.cactiTreeNavigationArea').css('width', minTreeWidth);
1579			$('.cactiGraphContentArea').css('margin-left', minTreeWidth+5);
1580			$('.cactiTreeNavigationArea').css('overflow-x', '');
1581		} else if (visWidth > maxTreeWidth) {
1582			$('.cactiTreeNavigationArea').css('width', maxTreeWidth);
1583			$('.cactiGraphContentArea').css('margin-left', maxTreeWidth+5);
1584			$('.cactiTreeNavigationArea').css('overflow-x', 'auto');
1585		} else if (visWidth > navWidth) {
1586			$('.cactiTreeNavigationArea').css('width', visWidth);
1587			$('.cactiGraphContentArea').css('margin-left', visWidth+5);
1588			$('.cactiTreeNavigationArea').css('overflow-x', 'auto');
1589		} else {
1590			$('.cactiTreeNavigationArea').css('width', navWidth);
1591			$('.cactiGraphContentArea').css('margin-left', navWidth+5);
1592			$('.cactiTreeNavigationArea').css('overflow-x', '');
1593		}
1594	}
1595
1596	var navWidth = $('#navigation').width();
1597	if (navWidth > 220) {
1598		$('#searcher').css('width', navWidth-70);
1599	} else {
1600		$('#searcher').css('width', 150);
1601	}
1602}
1603
1604function countHiddenCols(object) {
1605	var hidden = 0;
1606
1607	$(object).find('th').each(function() {
1608		if ($(this).css('display') == 'none') {
1609			hidden++;
1610		}
1611	});
1612
1613	return hidden;
1614}
1615
1616function tuneTables() {
1617	var mainWidth = getMainWidth();
1618
1619	$('.cactiTable').each(function() {
1620		$(this).find('th:first-child').each(function() {
1621			var object = $(this).closest('.cactiTable');
1622
1623			tuneTable(object, mainWidth);
1624		});
1625	});
1626}
1627
1628function pageHasHidableColumnsAndProfile() {
1629	if (typeof userSettings != 'undefined' && userSettings && $(document).find('th').length) {
1630		return true;
1631	}
1632
1633	return false;
1634}
1635
1636function resetTables() {
1637	$('.cactiTable').each(function() {
1638		$(this).find('th:first-child').each(function() {
1639			var object = $(this).closest('.cactiTable');
1640
1641			resetTable(object);
1642		});
1643	});
1644}
1645
1646function resetTable(object) {
1647	var id = $(object).attr('id');
1648	var column = 1;
1649	$(object).find('th').each(function() {
1650		$('#'+id+' th:nth-child('+column+')').show();
1651		$('#'+id+' td:nth-child('+column+')').show();
1652		column++;
1653	});
1654}
1655
1656function tuneTable(object, width) {
1657	var rows           = $(object).find('tr').length;
1658	var tableWidth     = $(object).width();
1659	var totalCols      = $(object).find('th').length;
1660	var reducedWidth   = 0;
1661	var columnsHidden  = countHiddenCols(object);
1662	var visibleColumns = totalCols - columnsHidden;
1663	var id             = $(object).attr('id');
1664
1665	if (rows > 101) return false;
1666
1667	// Enable horizontal scroll bar
1668	if (hScroll) {
1669		$('#main, .cactiConsoleContentArea').css({ 'overflow-x': 'visible' });
1670
1671		return false;
1672	} else {
1673		$('#main, .cactiConsoleContentArea').css({ 'overflow-x': 'hidden' });
1674	}
1675
1676	// We have to both show and hide columns that fit.
1677	// So, always find the size of the page columns.
1678	var calculatedColumns = [];
1679	var calculatedWidth   = 0;
1680	var allSeenWidth      = 0;
1681	var calculatedPadding = 15;
1682	var tableChanged      = false;
1683	var stopExpand        = false;
1684	var debug             = false;
1685
1686	var tableHeaders = $(object).find('th');
1687	var tableCheckBox = $(tableHeaders).each(function() {
1688		if ($(this).index() == tableHeaders.length) {
1689			calculatedColumns.addClass('noHide');
1690		}
1691	});
1692
1693	// Traverse the table and look for columns to hide from left to right
1694	$($(object).find('th').get()).each(function() {
1695		var isLastCheckBox = $(this).hasClass('tableSubHeaderCheckbox') && $(this).index() == tableHeaders.length - 1;
1696		var columnWidth = $.textMetrics(this).width;
1697
1698		// Get the width of columns that can not be hidden
1699		if ($(this).hasClass('noHide') || isLastCheckBox) {
1700			calculatedColumns.push($(this).index());
1701			calculatedWidth += columnWidth + calculatedPadding;
1702		}
1703
1704		if ($(this).is(':visible')) {
1705			allSeenWidth += columnWidth + calculatedPadding;
1706		}
1707	});
1708
1709	if (debug) {
1710		console.log(
1711			'allSeenWidth:'     + Math.round(allSeenWidth, 1) +
1712			', calulatedWidth:'  + Math.round(calculatedWidth, 1) +
1713			', tableWidth:' + Math.round(tableWidth, 1) +
1714			', width:'  + Math.round(width, 1)
1715		);
1716	}
1717
1718	if (width < tableWidth) {
1719		$($(object).find('th').get()).each(function() {
1720			// Now traverse the available columns for hiding
1721			// and See which need to be hidden
1722			if (!calculatedColumns.includes($(this).index())) {
1723				var columnWidth = $.textMetrics(this).width + calculatedPadding;
1724				var name = $(this).find('div.sortinfo').attr('sort-column');
1725
1726				if (debug) {
1727					console.log(
1728						'ColIndex:' + $(this).index() +
1729						', ColWidth:' + Math.round(columnWidth, 1) +
1730						', TotalWidth:' + Math.round(calculatedWidth, 1) +
1731						', PageWidth:' + Math.round(width, 1)
1732					);
1733				}
1734
1735				if (width < calculatedWidth) {
1736					$(this).hide();
1737					tableChanged = true;
1738				} else {
1739					calculatedColumns.push($(this).index());
1740					calculatedWidth += columnWidth + calculatedPadding;
1741				}
1742			}
1743		});
1744
1745		if (tableChanged) {
1746			$($(object).find('td').each(function() {
1747				if (!calculatedColumns.includes($(this).index())) {
1748					$(this).hide();
1749				}
1750			}));
1751		}
1752	}
1753
1754	tableChanged = false;
1755
1756	if (allSeenWidth < width) {
1757		calculatedColumns = calculatedColumns.sort();
1758
1759		// Since we can show hidden columns now, let's go
1760		// in reverse until we run out of space
1761		$($(object).find('th').get()).each(function() {
1762			if (!calculatedColumns.includes($(this).index())) {
1763				if ($(this).is(':hidden') && stopExpand == false) {
1764					var columnWidth = $.textMetrics(this).width + calculatedPadding;
1765					var name = $(this).find('div.sortinfo').attr('sort-column');
1766
1767					if (allSeenWidth + columnWidth < tableWidth) {
1768						$(this).show();
1769
1770						var newTableWidth = $(object).width();
1771
1772						if (debug) {
1773							console.log(
1774								'Reverse ColIndex:' + $(this).index() +
1775								', columnWidth:' + Math.round(columnWidth, 1) +
1776								', allSeenWidth:' + Math.round(allSeenWidth, 1) +
1777								', width:' + Math.round(width, 1) +
1778								', newTableWidth:' + Math.round(newTableWidth, 1)
1779							);
1780						}
1781
1782						if (newTableWidth > width) {
1783							$(this).hide();
1784							stopExpand = true;
1785						} else {
1786							calculatedColumns.push($(this).index());
1787							tableChanged = true;
1788						}
1789					}
1790				}
1791			}
1792		});
1793
1794		if (tableChanged) {
1795			$($(object).find('td').each(function() {
1796				if (calculatedColumns.includes($(this).index())) {
1797					$(this).show();
1798				}
1799			}));
1800		}
1801	}
1802}
1803
1804function tuneFilter(object, width) {
1805	if ($(object).find('#timespan').length && $(object).find('#timespan').is(':visible')) {
1806		var timespan = true;
1807
1808		var timeShiftWidth = $(object).find('.shiftArrow').closest('td').width();
1809		var dateWidth      = $(object).find('#date1').closest('td').width() + $(object).find('#date1').closest('td').prev('td').width();
1810		var clearWidth     = $('#tsclear').width();
1811		var refreshWidth   = $('#tsrefresh').width();
1812	} else {
1813		var timespan = false;
1814
1815		var clearWidth     = $(object).find('#clear').width();
1816		var saveWidth      = $(object).find('#save').width();
1817		var exportWidth    = $(object).find('#export').width();
1818		var importWidth    = $(object).find('#import').width();
1819	}
1820
1821	var minTds = 2;
1822	var visTds = $(object).find('td:visible').length;
1823
1824	if ($(object).find('input[type="button"]').length) {
1825		minTds++;
1826	}
1827
1828	if ($(object).width() > width) {
1829		if (!timespan) {
1830			$($(object).find('td').get().reverse()).each(function() {
1831				if ($(this).find('input[type="button"]').length == 0) {
1832					if ($(this).is(':visible')) {
1833						$(this).hide();
1834						visTds--;
1835
1836						if ($(this).closest('td').prev().find('input, select').length == 0) {
1837							$(this).closest('td').prev().hide();
1838							visTds--;
1839						}
1840					}
1841
1842					if ($(object).width() < width) {
1843						return false;
1844					}
1845
1846					if (visTds <= minTds) {
1847						return false;
1848					}
1849				}
1850			});
1851
1852			if ($(object).width() > width) {
1853				if (saveWidth > 0) {
1854					$('#save').hide();
1855				}
1856			}
1857
1858			if ($(object).width() > width) {
1859				if (exportWidth > 0) {
1860					$('#export').hide();
1861				}
1862			}
1863
1864			if ($(object).width() > width) {
1865				if (importWidth > 0) {
1866					$('#import').hide();
1867				}
1868			}
1869
1870			if ($(object).width() > width) {
1871				if (clearWidth > 0) {
1872					$('#clear').hide();
1873				}
1874			}
1875		} else {
1876			$('#date1').closest('td').hide().prev('td').hide();
1877			$('#date2').closest('td').hide().prev('td').hide();
1878
1879			if ($(object).width() > width) {
1880				$('.shiftArrow').closest('td').hide();
1881			}
1882
1883			if ($(object).width() > width) {
1884				$('#tsclear').hide();
1885			}
1886
1887			if ($(object).width() > width) {
1888				$('#tsrefresh').hide();
1889			}
1890		}
1891	} else {
1892		if (!timespan) {
1893			if ($(object).width() + clearWidth < width) {
1894				$('#clear').show();
1895			}
1896
1897			if ($(object).width() + importWidth < width) {
1898				$('#import').show();
1899			}
1900
1901			if ($(object).width() + exportWidth < width) {
1902				$('#export').show();
1903			}
1904
1905			if ($(object).width() + saveWidth < width) {
1906				$('#save').show();
1907			}
1908
1909			if ($(object).width() < width) {
1910				$(object).find('td').each(function() {
1911					if ($(this).find('input[type="button"]').length == 0) {
1912						if (!$(this).is(':visible')) {
1913							showWidth = $(this).width();
1914							if ($(this).next('td').find('input, select').length > 0) {
1915								showWidth += $(this).next('td').width();
1916							}
1917
1918							if ($(object).width() + showWidth < width) {
1919								$(this).show();
1920								if ($(this).next('td').find('input, select').length > 0) {
1921									$(this).next('td').show();
1922								}
1923							} else {
1924								return false;
1925							}
1926						}
1927					}
1928				});
1929			}
1930		} else {
1931			if ($(object).width() + refreshWidth < width) {
1932				$('#tsrefresh').show();
1933			}
1934
1935			if ($(object).width() + clearWidth < width) {
1936				$('#tsclear').show();
1937			}
1938
1939			if ($(object).width() + timeShiftWidth < width) {
1940				$('.shiftArrow').closest('td').show();
1941			}
1942
1943			if ($(object).width() + (2 * dateWidth) < width) {
1944				$('#date1').closest('td').show().prev('td').show();
1945				$('#date2').closest('td').show().prev('td').show();
1946			}
1947		}
1948	}
1949}
1950
1951function handleUserMenu(toggle) {
1952	var windowWidth = $(window).width();
1953	var savedState  = getMenuState();
1954	var curState    = $('#navigation').is(':visible') ? 'visible':'hidden';
1955
1956	//console.log('handle called, curState:'+curState+', savedState:'+savedState+', Toggle:'+toggle);
1957	if ($('#navigation').length) {
1958		if (theme != 'classic') {
1959			if (curState == 'visible' && toggle) {
1960				menuHide(true);
1961			} else if (curState == 'hidden' && toggle) {
1962				menuShow();
1963			} else if (savedState == 'visible') {
1964				if (windowWidth < 640) {
1965					menuHide(false);
1966				} else {
1967					menuShow();
1968				}
1969			} else {
1970				menuHide(false);
1971			}
1972		} else if (windowWidth < 640) {
1973			menuHide(true);
1974		} else if (savedState == 'visible') {
1975			menuShow();
1976		} else {
1977			menuHide();
1978		}
1979	}
1980}
1981
1982function menuHide(store) {
1983	var storage = Storages.localStorage;
1984
1985	var myClass = '';
1986    var curMargin = parseInt($('#navigation_right').css('margin-left'));
1987
1988	if ($('.cactiTreeNavigationArea').length) {
1989		myClass = '.cactiTreeNavigationArea';
1990
1991		if (curMargin > 0) {
1992			marginLeftTree = curMargin;
1993			$('.cactiTreeNavigationArea').css('width', curMargin);
1994		}
1995	} else if ($('.cactiConsoleNavigationArea').length) {
1996		myClass = '.cactiConsoleNavigationArea';
1997
1998		if (curMargin > 0) {
1999			marginLeftConsole = curMargin;
2000		}
2001	}
2002
2003	$('#navigation_right').animate({'margin-left': '0px'}, 20);
2004
2005	if (myClass != '') {
2006		$(myClass).hide('slide', {direction: 'left'}, 20, function() {
2007			responsiveResizeGraphs();
2008		});
2009	}
2010
2011	$('#navigation').hide();
2012
2013	if (myClass == '.cactiTreeNavigationArea' || pageName == 'graph_view.php') {
2014		responsiveResizeGraphs();
2015	}
2016
2017	if (store) {
2018		storage.set('menuState_' + page, 'hidden');
2019	}
2020}
2021
2022function menuShow() {
2023	var storage = Storages.localStorage;
2024	var myClass = '';
2025
2026	if ($('.cactiTreeNavigationArea').length) {
2027		if (marginLeftTree == null) {
2028			marginLeftTree = minTreeWidth;
2029		}
2030
2031		var treeWidth = $('.cactiTreeNavigationArea').width();
2032
2033		myClass = '.cactiTreeNavigationArea';
2034
2035		if (marginLeftTree > treeWidth) {
2036			$('#navigation_right').animate({'margin-left': marginLeftTree}, 20);
2037			$('.cactiTreeNavigationArea').css('width', marginLeftTree);
2038		}
2039	} else if ($('.cactiConsoleNavigationArea').length) {
2040		myClass = '.cactiConsoleNavigationArea';
2041
2042		if (marginLeftConsole > 0) {
2043			$('#navigation_right').animate({'margin-left': marginLeftConsole}, 20);
2044		}
2045	}
2046
2047	if (myClass != '') {
2048		$(myClass).show('slide', {direction: 'left'}, 20, function() {
2049			responsiveResizeGraphs();
2050		});
2051	}
2052
2053	$('#navigation').show();
2054
2055	storage.set('menuState_' + pageName, 'visible');
2056}
2057
2058function loadTopTab(href, id, force) {
2059	statePushed = false;
2060	var cont = false;
2061
2062	if (force == undefined) {
2063		force = false;
2064	}
2065
2066	if (!force) {
2067		cont = checkFormStatus(href, 'toptab', id);
2068	} else {
2069		cont = true;
2070	}
2071
2072	if (cont) {
2073		var thref = stripHeaderSuppression(href);
2074		var url   = thref+(thref.indexOf('?') > 0 ? '&':'?') + 'headercontent=true';
2075
2076		$('.submenuoptions').slideUp(120);
2077		$('.menuoptions').slideUp(120);
2078
2079		if (href.indexOf('graph_view.php') >= 0) {
2080			$('.cactiGraphHeaderBackground').show();
2081			$('.cactiConsolePageHeadBackdrop').hide();
2082		} else {
2083			$('.cactiGraphHeaderBackground').hide();
2084			$('.cactiConsolePageHeadBackdrop').show();
2085		}
2086
2087		closeDateFilters();
2088
2089		clearAllTimeouts();
2090
2091		$.ajaxQ.abortAll();
2092		$.get(url)
2093			.done(function(html) {
2094				var htmlObject  = $(html);
2095				var matches     = html.match(/<title>(.*?)<\/title>/);
2096
2097				$('#main').empty().hide();
2098
2099				if (matches != null) {
2100					var htmlTitle   = matches[1];
2101					var breadCrumbs = htmlObject.find('#breadcrumbs').html();
2102					var parts       = html.split('</title>');
2103					var html        = parts[1];
2104
2105					checkForRedirects(html, href);
2106
2107					$('title').text(htmlTitle);
2108					$('#breadcrumbs').html(breadCrumbs);
2109					$('div[class^="ui-"]').remove();
2110					$('#cactiContent').replaceWith(html);
2111
2112					myTitle = htmlTitle;
2113					myHref  = cleanHeader(href);
2114
2115					pushState(myTitle, href);
2116				} else {
2117					checkForRedirects(html, href);
2118
2119					$('#cactiContent').replaceWith(html);
2120
2121					thref = stripHeaderSuppression(href);
2122
2123					pushState(myTitle, href);
2124				}
2125
2126				var hrefParts = href.split('?');
2127				pageName = basename(hrefParts[0]);
2128
2129				if (pageName != '') {
2130					if ($('#menu').find("a[href^='"+escapeString(href)+"']").length > 0) {
2131						$('#menu').find('.pic').removeClass('selected');
2132						$('#menu').find("a[href^='"+escapeString(href)+"']").addClass('selected');
2133					} else if ($('#menu').find("a[href*='/"+pageName+"']").length > 0) {
2134						$('#menu').find('.pic').removeClass('selected');
2135						$('#menu').find("a[href*='/"+pageName+"']").addClass('selected');
2136					}
2137				}
2138
2139				applySkin();
2140
2141				if (isMobile.any() != null) {
2142					window.scrollTo(0,1);
2143				} else {
2144					window.scrollTo(0,0);
2145				}
2146
2147				handleUserMenu();
2148
2149				handleConsole(pageName);
2150
2151				$('#main').css('display', 'table');
2152
2153				Pace.stop();
2154
2155				return false;
2156			})
2157			.fail(function(html) {
2158				getPresentHTTPErrorOrRedirect(html, url);
2159			}
2160		);
2161
2162		/* update menu selection */
2163		if ($('#'+id).hasClass('lefttab')) {
2164			$('.lefttab').removeClass('selected');
2165			$('.submenuoptions').find('.selected').removeClass('selected');
2166			$('#'+id).addClass('selected');
2167			hideTabId = id.substring(0, id.length-9);
2168			if (hideTabId) {
2169				$('#'+hideTabId).addClass('selected');
2170			}
2171		} else if ($('#'+id).parents('.submenuoptions').length > 0) {
2172			$('#'+id).parents('.submenuoptions').find('.selected').removeClass('selected');
2173			$('#'+id).addClass('selected');
2174		}
2175
2176		return true;
2177	} else {
2178		return false;
2179	}
2180}
2181
2182function loadPageUsingPost(href, postData, returnLocation) {
2183	$.post(href, postData, function(data) {
2184		if (returnLocation !== undefined) {
2185			$('#'+returnLocation).empty().html(data);
2186		} else {
2187			$('#main').empty().html(data);
2188		}
2189
2190		applySkin();
2191	});
2192}
2193
2194function loadPage(href, force) {
2195	statePushed = false;
2196	cont = false;
2197
2198	if (force == undefined) {
2199		force = false;
2200	}
2201
2202	if (!force) {
2203		cont = checkFormStatus(href, 'loadpage');
2204	} else {
2205		cont = true;
2206	}
2207
2208	if (cont) {
2209		closeDateFilters();
2210
2211		clearAllTimeouts();
2212
2213		$.ajaxQ.abortAll();
2214		$.get(href)
2215			.done(function(html) {
2216				var htmlObject  = $(html);
2217				var matches     = html.match(/<title>(.*?)<\/title>/);
2218
2219				if (matches != null) {
2220					var htmlTitle   = matches[1];
2221					var breadCrumbs = htmlObject.find('#breadcrumbs').html();
2222					var html        = htmlObject.find('#main').html();
2223					var jstree		= htmlObject.find('.cactiTreeNavigationArea').html();
2224
2225					checkForRedirects(html, href);
2226					if(typeof jstree !== 'undefined' && $('.cactiTreeNavigationArea').length !== 0) {
2227						$('.cactiTreeNavigationArea').html(jstree);
2228					}
2229					$('#main').empty().hide();
2230					$('title').text(htmlTitle);
2231					$('#breadcrumbs').html(breadCrumbs);
2232					$('div[class^="ui-"]').remove();
2233					$('#main').html(html);
2234
2235					myTitle = htmlTitle;
2236					myHref  = cleanHeader(href);
2237
2238					pushState(myTitle, href);
2239				} else {
2240					checkForRedirects(html, href);
2241
2242					$('#main').empty().hide();
2243					$('#main').html(html);
2244
2245					thref = stripHeaderSuppression(href);
2246
2247					pushState(myTitle, href);
2248				}
2249
2250				var hrefParts = href.split('?');
2251				pageName = basename(hrefParts[0]);
2252
2253				if (pageName != '') {
2254					// Workaround for Create Device
2255					if (pageName == 'host.php') {
2256						if (href.indexOf('create') >= 0) {
2257							$('#menu').find('.pic').removeClass('selected');
2258							$('#menu').find("a[href='"+escapeString(href)+"']").addClass('selected');
2259						} else {
2260							$('#menu').find('.pic').removeClass('selected');
2261							$('#menu').find("a[href$='host.php']").addClass('selected');
2262						}
2263					} else if ($('#menu').find("a[href^='"+escapeString(href)+"']").length > 0) {
2264						$('#menu').find('.pic').removeClass('selected');
2265						$('#menu').find("a[href^='"+escapeString(href)+"']").addClass('selected');
2266					} else if ($('#menu').find("a[href*='/"+pageName+"']").length > 0) {
2267						$('#menu').find('.pic').removeClass('selected');
2268						$('#menu').find("a[href*='/"+pageName+"']").addClass('selected');
2269					}
2270
2271					if (pageName == 'graph_templates_items.php' || pageName == 'graph_templates_inputs.php') {
2272						$('#menu').find('a[href*="graph_templates.php"]').addClass('selected');
2273					}
2274				}
2275
2276				applySkin();
2277
2278				if (isMobile.any() != null) {
2279					window.scrollTo(0,1);
2280				} else {
2281					window.scrollTo(0,0);
2282				}
2283
2284				handleConsole(pageName);
2285
2286				Pace.stop();
2287
2288				return false;
2289			})
2290			.fail(function(html) {
2291				getPresentHTTPErrorOrRedirect(html, href);
2292			}
2293		);
2294	}
2295
2296	return false;
2297}
2298
2299function setNavigationScroll() {
2300	var object = '';
2301
2302	$('.cactiConsoleNavigationArea, .cactiTreeNavigationArea').unbind('mousemove').on('mousemove', function(pos) {
2303		object = '';
2304
2305		if ($('.cactiConsoleNavigationArea').length) {
2306			object = '.cactiConsoleNavigationArea';
2307		} else if ($('.cactiTreeNavigationArea').length) {
2308			object = '.cactiTreeNavigationArea';
2309		}
2310
2311		if (object != '') {
2312			var mpos   = $(object).position();
2313			var width  = $(object).outerWidth();
2314			var height = $(object).outerHeight();
2315			if (pos.pageX < mpos.left ||
2316				pos.pageY < mpos.top ||
2317				pos.pageX > mpos.left + width - 1 ||
2318				pos.pageY > mpos.top + height - 1) {
2319
2320				if (isHover) {
2321					clearTimeout(hoverTimer);
2322					hoverTimer = setTimeout(function() {
2323						$(object).css('overflow-y', 'hidden');
2324					}, 500);
2325				}
2326
2327				isHover = false;
2328			} else {
2329				if (!isHover) {
2330					clearTimeout(hoverTimer);
2331					hoverTimer = setTimeout(function() {
2332						$(object).css('overflow-y', 'auto');
2333					}, 500);
2334				}
2335
2336				isHover = true;
2337			}
2338		}
2339	});
2340
2341	$('.cactiConsoleNavigationArea, .cactiTreeNavigationArea').unbind('mouseleave').on('mouseleave', function(pos) {
2342		if ($('.cactiConsoleNavigationArea').length) {
2343			object = '.cactiConsoleNavigationArea';
2344		} else if ($('.cactiTreeNavigationArea').length) {
2345			object = '.cactiTreeNavigationArea';
2346		}
2347
2348		isHover = false;
2349
2350		clearTimeout(hoverTimer);
2351		hoverTimer = setTimeout(function() {
2352			$(object).css('overflow-y', 'hidden');
2353		}, 500);
2354	});
2355}
2356
2357function loadPageNoHeader(href, scroll, force) {
2358	statePushed = false;
2359	cont = false;
2360
2361	if (scroll == undefined) {
2362		scroll = false;
2363	}
2364
2365	if (force == undefined) {
2366		force = false;
2367	}
2368
2369	if (!force) {
2370		cont = checkFormStatus(href, 'noheader', scroll);
2371	} else {
2372		cont = true;
2373	}
2374
2375	if (cont) {
2376		closeDateFilters();
2377
2378		clearAllTimeouts();
2379
2380		$.ajaxQ.abortAll();
2381		$.get(href)
2382			.done(function(html) {
2383				var htmlObject  = $(html);
2384				var matches     = html.match(/<title>(.*?)<\/title>/);
2385
2386				if (matches != null) {
2387					checkForRedirects(html, href);
2388
2389					var htmlTitle   = matches[1];
2390					var breadCrumbs = htmlObject.filter('#breadcrumbs').html();
2391					var html        = htmlObject.filter('#main').html();
2392
2393					$('#main').empty().hide();
2394					$('title').text(htmlTitle);
2395					$('#breadcrumbs').html(breadCrumbs);
2396					$('div[class^="ui-"]').remove();
2397					$('#main').html(html);
2398
2399					myTitle = htmlTitle;
2400					myHref  = cleanHeader(href);
2401
2402					pushState(myTitle, href);
2403				} else {
2404					checkForRedirects(html, href);
2405
2406					$('#main').empty().hide();
2407					$('div[class^="ui-"]').remove();
2408					$('#main').html(html);
2409
2410					var hrefParts = href.split('?');
2411					pageName = basename(hrefParts[0]);
2412
2413					if (pageName != '') {
2414						// Workaround for Create Device
2415						if (pageName == 'host.php') {
2416							if (href.indexOf('create') >= 0) {
2417								$('#menu').find('.pic').removeClass('selected');
2418								$('#menu').find("a[href='"+escapeString(href)+"']").addClass('selected');
2419							} else {
2420								$('#menu').find('.pic').removeClass('selected');
2421								$('#menu').find("a[href$='host.php']").addClass('selected');
2422							}
2423						} else if ($('#menu').find("a[href^='"+escapeString(href)+"']").length > 0) {
2424							$('#menu').find('.pic').removeClass('selected');
2425							$('#menu').find("a[href^='"+escapeString(href)+"']").addClass('selected');
2426						} else if ($('#menu').find("a[href*='/"+pageName+"']").length > 0) {
2427							$('#menu').find('.pic').removeClass('selected');
2428							$('#menu').find("a[href*='/"+pageName+"']").addClass('selected');
2429						}
2430
2431						if (pageName == 'graph_templates_items.php' || pageName == 'graph_templates_inputs.php') {
2432							$('#menu').find('a[href*="graph_templates.php"]').addClass('selected');
2433						}
2434					}
2435
2436					applySkin();
2437
2438					pushState(myTitle, href);
2439				}
2440
2441				if (isMobile.any() != null) {
2442					window.scrollTo(0,1);
2443				} else {
2444					window.scrollTo(0,0);
2445				}
2446
2447				handleConsole(pageName);
2448
2449				Pace.stop();
2450
2451				return false;
2452			})
2453			.fail(function(html) {
2454				getPresentHTTPErrorOrRedirect(html, href);
2455			}
2456		);
2457	}
2458
2459	return false;
2460}
2461
2462function getPresentHTTPError(data) {
2463	getPresentHTTPErrorOrRedirect(data);
2464}
2465
2466function getPresentHTTPErrorOrRedirect(data, url) {
2467	if (typeof data.status != 'undefined') {
2468		var errorStr  = data.status;
2469		var errorSub  = data.statusText;
2470		var errorText = errorReasonUnexpected;
2471		var found     = false;
2472
2473		if (typeof data.responseText != 'undefined') {
2474			var dataText = data.responseText;
2475
2476			var title_match = dataText.match(/<title>(.*?)<\/title>/);
2477			var head_match  = dataText.match(/<h1>(.*?)<\/h1>/);
2478			var para_match  = dataText.match(/<p>(.*?)<\/p>/);
2479
2480			if (title_match != null) {
2481				var errorSub = title_match[1];
2482				found = true;
2483			}
2484
2485			if (head_match != null) {
2486				var errorSub = head_match[1];
2487				found = true;
2488			}
2489
2490			if (para_match != null) {
2491				var errorText = para_match[1];
2492				found = true;
2493			}
2494
2495			if (!found && dataText != '') {
2496				var errorText = dataText;
2497			}
2498
2499			var returnStr = '<div id="httperror" style="display:none">' +
2500				'<h4>' + errorOnPage + '</h4><hr>' +
2501				'<div style="padding-bottom: 5px;"><div style="display:table-cell;width:75px"><b>' + errorNumberPrefix + '</b></div> ' +
2502				'<div style="display:table-cell"> ' + errorStr + ' ' + errorSub + '</div></div>' +
2503				'<div><div style="display:table-cell;width:75px"><b>'  + errorReasonPrefix + '</b></div> ' +
2504				'<div style="display:table-cell"> ' + errorText + '</div></div>' +
2505				'</div></div>';
2506
2507			var messageWidth = $(window).width();
2508			if (messageWidth > 400) {
2509				messageWidth = 400;
2510			} else {
2511				messageWidth -= 50;
2512			}
2513
2514			$('#httperror').remove();
2515			$('body').append(returnStr);
2516			$('#httperror').dialog({
2517				resizable: false,
2518				height: 'auto',
2519				width: messageWidth,
2520				title: errorReasonTitle,
2521				buttons: {
2522					Ok: function() {
2523						$(this).dialog('close');
2524					}
2525				}
2526			});
2527		}
2528	}
2529
2530	if (typeof url != 'undefined') {
2531		if (data.status >= 500) {
2532			// Let the HTTP Error stick log an error
2533			$.get(urlPath + 'help.php?page=' + escape(url) + '&error=' + data.status);
2534		} else if (data.status >= 400) {
2535			// Let the HTTP Error stick
2536		} else if (data.statusText != 'abort') {
2537			$.ajaxQ.abortAll();
2538			document.location = stripHeaderSuppression(url);
2539		}
2540	}
2541}
2542
2543function ajaxAnchors() {
2544	$('a.pic, a.linkOverDark, a.linkEditMain, a.console, a.hyperLink, a.tab').not('[href^="http"], [href^="https"], [href^="#"], [href^="mailto"], [target="_blank"]').off('click').on('click', function(event) {
2545		event.preventDefault();
2546		event.stopPropagation();
2547
2548		if ($(window).width() < 640) {
2549			if (theme != 'classic') {
2550				menuHide(false);
2551			}
2552		}
2553
2554		/* determine the page name */
2555		var href = $(this).attr('href');
2556
2557		if (href == '#') {
2558			return false;
2559		}
2560
2561		/* update menu selection */
2562		if ($(this).hasClass('pic')) {
2563			$(this).addClass('selected');
2564		}
2565
2566		/* update menu selection */
2567		if ($(this).hasClass('lefttab')) {
2568			$('.lefttab').removeClass('selected');
2569			$(this).addClass('selected');
2570		}
2571
2572		/* update menu selection */
2573		if ($(this).hasClass('righttab')) {
2574			$('.righttab').removeClass('selected');
2575			$(this).addClass('selected');
2576		}
2577
2578		if (href != null) {
2579			pageName = basename(href);
2580		}
2581
2582		loadPage(href);
2583
2584		return false;
2585	});
2586}
2587
2588function checkFormStatus(href, type, scroll_or_id) {
2589	var changed = false;
2590
2591	if ($('.cactiFormStart').not('#chk').length) {
2592		$('.cactiFormStart').not('#chk').each(function() {
2593			var formID     = $(this).attr('id');
2594			var submitData = $(this).serializeForm();
2595
2596			if (typeof formArray != 'undefined' && typeof formArray[formID] != 'undefined') {
2597				var formData   = formArray[formID];
2598
2599				$.each(submitData, function(index, value) {
2600					if (typeof formData[index] != 'undefined') {
2601						if (formData[index] != value) {
2602							if (index == 'settings_sendmail_path' || index == 'rrd_archive' || index == '__csrf_magicSubmit' || index == '__csrf_magic' || index == 'settings_smtp_password' || index == 'settings_smtp_password_confirm') {
2603								// Ignore this entry
2604							} else if (index.indexOf('[]') > 0) {
2605								// Ignore this entry
2606							} else {
2607								console.log('Index:-'+index+'-:Submit:'+value+', Orig:'+formData[index]);
2608								changed = true;
2609							}
2610						}
2611					}
2612				});
2613			}
2614		});
2615
2616		if (changed) {
2617			warningMessage(href, type, scroll_or_id);
2618			return false;
2619		} else {
2620			return true;
2621		}
2622	} else {
2623		return true;
2624	}
2625}
2626
2627function setupCollapsible() {
2628	var storage = Storages.localStorage;
2629
2630	$('.collapsible').each(function(data) {
2631		var id = $(this).attr('id')+'_cs';
2632		if (storage.isSet(id)) {
2633			var state = storage.get(id);
2634		} else {
2635			var state = 'show';
2636		}
2637
2638		if (state == 'hide') {
2639			$(this).addClass('collapsed');
2640			$(this).nextUntil('div.spacer').hide();
2641			$(this).find('i').removeClass('fa-angle-double-up').addClass('fa-angle-double-down');
2642			storage.set(id, 'hide');
2643		}
2644	});
2645
2646	$('.collapsible').off('click').on('click', function(data) {
2647		var id = $(this).attr('id')+'_cs';
2648
2649		if ($(this).find('i').hasClass('fa-angle-double-up')) {
2650			$(this).addClass('collapsed');
2651			$(this).nextUntil('div.spacer').slideUp('slow');
2652			$(this).find('i').removeClass('fa-angle-double-up').addClass('fa-angle-double-down');
2653			storage.set(id, 'hide');
2654		} else {
2655			$(this).removeClass('collapsed');
2656			$(this).nextUntil('div.spacer').slideDown('slow');
2657			$(this).nextUntil('div.spacer').each(function(data) {
2658				$(this).find('input, select').change();
2659			});
2660			$(this).find('i').removeClass('fa-angle-double-down').addClass('fa-angle-double-up');
2661			storage.set(id, 'show');
2662		}
2663	});
2664}
2665
2666function openUserMenu() {
2667	$('.user').removeClass('usermenuup').addClass('usermenudown');
2668	$('.menuoptions').slideDown(120, 'easeInOutCubic');
2669}
2670
2671function closeUserMenu() {
2672	$('.user').removeClass('usermenudown').addClass('usermenuup');
2673	$('.menuoptions').slideUp(120, 'easeInOutCubic');
2674}
2675
2676function handleConsole(pageName) {
2677	if (pageName == null) {
2678		pageName = basename($(location).attr('pathname'));
2679	}
2680
2681	// Modify the console pic
2682	$('#menu_main_console').find('.menu_parent').attr('href', 'index.php').addClass('console selected');
2683	$('#menu_main_console_div').remove();
2684	if (pageName != 'index.php') {
2685		$('#menu_main_console').find('.menu_parent').removeClass('selected');
2686	}
2687}
2688
2689function setupUserMenu() {
2690	handleConsole();
2691
2692	$('.menuoptions').mouseenter(function() {
2693		clearTimeout(userMenuTimer);
2694	}).mouseleave(function() {
2695		if ($('.menuoptions').is(':visible')) {
2696			userMenuTimer = setTimeout(function() { closeUserMenu(); }, 1000);
2697		}
2698	});
2699
2700	$('.user').mouseenter(function(data) {
2701		clearTimeout(userMenuTimer);
2702		userMenuOpenTimer = setTimeout(function() { openUserMenu(); }, 400);
2703		openUserMenu();
2704	}).mouseleave(function(data) {
2705		if ($('.menuoptions').is(':visible')) {
2706			userMenuTimer = setTimeout(function() { closeUserMenu(); }, 1000);
2707		} else {
2708			clearTimeout(userMenuOpenTimer);
2709		}
2710	});
2711}
2712
2713function setupSpecialKeys() {
2714	if (!isMobile.any()) {
2715		$('#filter, #rfilter').focus();
2716	} else {
2717		$('#filter, #rfilter').prop('size', '15');
2718	}
2719}
2720
2721/** setupSortable - This function will set all actions for sortable columns
2722 *  every time a page is regenerated */
2723function setupSortable() {
2724	$('th.sortable').on('click', function(e) {
2725		document.getSelection().removeAllRanges();
2726
2727		var $target = $(e.target);
2728		var sortAdd = '';
2729		var href    = '';
2730
2731		if (!$target.is('.ui-resizable-handle')) {
2732			var page      = $(this).find('.sortinfo').attr('sort-page');
2733			var column    = $(this).find('.sortinfo').attr('sort-column');
2734			var direction = $(this).find('.sortinfo').attr('sort-direction');
2735			var returnto  = $(this).find('.sortinfo').attr('sort-return');
2736
2737			if (shiftPressed) {
2738				sortAdd='&add=true';
2739			} else {
2740				sortAdd='&add=reset';
2741			}
2742
2743			href = page+(page.indexOf('?') > 0 ? '&':'?') +
2744				'sort_column=' + column +
2745				'&sort_direction=' + direction +
2746				'&header=false' +
2747				sortAdd;
2748
2749			closeDateFilters();
2750
2751			$.ajaxQ.abortAll();
2752			$.get(href)
2753				.done(function(data) {
2754					checkForRedirects(data, href);
2755
2756					$('#'+returnto).empty().hide();
2757
2758					if (returnto == 'main') {
2759						$('div[class^="ui-"]').remove();
2760					}
2761
2762					$('#'+returnto).html(data).show();
2763
2764					applySkin();
2765				})
2766				.fail(function(data) {
2767					getPresentHTTPErrorOrRedirect(data, href);
2768				}
2769			);
2770		}
2771	});
2772}
2773
2774function setupBreadcrumbs() {
2775	$('#breadcrumbs > li > a').click(function(event) {
2776		event.preventDefault();
2777		event.stopPropagation();
2778
2779		var href =  $(this).attr('href');
2780
2781		if (href != '#') {
2782			href = href.replace('action=tree_content', 'action=tree');
2783			$(this).prop('href', href);
2784			document.location = href;
2785		}
2786	});
2787}
2788
2789/** saveTableWidths - This function will initialize table widths on page
2790 *  load.  It includes the 'initial' boolean to initialize the page */
2791function saveTableWidths(initial) {
2792	// We will save columns widths persistently
2793	var storage = Storages.localStorage;
2794	var key;
2795
2796	// Initialize table width on the page
2797	$('.cactiTable').each(function(data) {
2798		var key    = $(this).attr('id');
2799
2800		if (storage.isSet(key)) {
2801			var sizes = storage.get(key);
2802		} else {
2803			var sizes = new Array();
2804		}
2805
2806		var items  = sizes ? sizes: new Array();
2807		var width  = $(document).width();
2808
2809		// if the table width changes, reset the columns
2810		if (key !== undefined && sizes == undefined) {
2811			storage.remove(key);
2812
2813			var sizes = new Array();
2814			var items = new Array();
2815		} else if (key !== undefined && initial) {
2816			if (items.length > 0) {
2817				if (items[0] + 18 < width) {
2818					storage.remove(key);
2819
2820					var sizes = new Array();
2821					var items = new Array();
2822				}
2823			}
2824		}
2825
2826		var i = 1;
2827
2828		items[0] = width;
2829		sizes[0] = width;
2830
2831		if (key !== undefined) {
2832			if (initial && items.length) {
2833				$('#'+key).find('th.ui-resizable').each(function(data) {
2834					if (items[i] == 0) {
2835						items[i] = $(this).width();
2836						sizes[i] = items[i];
2837					}
2838
2839					if (items[i] != 0) {
2840						$(this).css('width', items[i]);
2841						$(this).attr('resizeWidth', items[i]);
2842					}
2843					i++;
2844				});
2845			} else {
2846				$('#'+key).find('th.ui-resizable').each(function(data) {
2847					sizes[i] = $(this).width();
2848
2849					if (sizes[i] != 0) {
2850						$(this).css('width', items[i]);
2851						$(this).attr('resizeWidth', sizes[i]);
2852					}
2853					i++;
2854				});
2855
2856				if (i > 1) {
2857					storage.set(key, sizes);
2858				}
2859			}
2860		}
2861	});
2862}
2863
2864/** applyTableSizing - This function sets all table headers to be resizable using
2865 *  the jQueryUI function resizable.  It also calls the saveTableWidths function
2866 *  to store the widths in localStorage every time a column is resized. */
2867function applyTableSizing() {
2868	var originalSize = 0;
2869	var colWidth = 0;
2870
2871	$('.tableHeader').not('.tableFixed').find('th').resizable({
2872		handles: 'e',
2873
2874		start: function(event, ui) {
2875			colWidth     = $(this).width();
2876			originalSize = ui.size.width;
2877
2878			if (originalSize == 0) {
2879				originalSize = $(this).width();
2880			}
2881
2882			$(ui.originalElement).siblings().each(function(data) {
2883				$(this).attr('resizeWidth', $(this).width());
2884			});
2885		 },
2886
2887		resize: function(event, ui) {
2888			var resizeDelta = ui.size.width - originalSize;
2889			var newColWidth = colWidth + resizeDelta;
2890			var nextWidth = $(ui.element).next().attr('resizeWidth');
2891			$(ui.element).next().css('width', nextWidth-resizeDelta);
2892			$(ui.element).prevUntil('tr').each(function(data) {
2893				$(this).css('width', $(this).attr('resizeWidth'));
2894			});
2895			$(this).css('height', 'auto');
2896		},
2897
2898		stop: function(event, ui) {
2899			saveTableWidths(false);
2900		}
2901	});
2902
2903	saveTableWidths(true);
2904}
2905
2906function appendHeaderSuppression(url) {
2907	if (url.indexOf('action=tree_content') < 0 && url.indexOf('action=tree') >= 0) {
2908		url = url.replace('action=tree', 'action=tree_content');
2909	}
2910
2911	if (url.indexOf('header=false') < 0) {
2912		url += (url.indexOf('?') > 0 ? '&header=false':'?header=false');
2913	}
2914
2915	url = url.replace('?&', '?').replace('&&', '&');
2916
2917	return url;
2918}
2919
2920function stripHeaderSuppression(url) {
2921	url = url.replace('header=false', '').replace('?&', '?').replace('&&', '&');
2922	return url.replace('headercontent=true', '').replace('?&', '?').replace('&&', '&');
2923}
2924
2925/** setupPageTimeout - This function will setup the page timeout based upon
2926 *  the plugin developers $refresh requirements.  It also sets up a location
2927 *  to redirect the user to upon timeout.  This is generally done for automatically
2928 *  logging out the user, but can be used for simply refreshing the page as in the
2929 *  case of the Graphs page. */
2930function setupPageTimeout() {
2931	if (typeof myRefresh != 'undefined') {
2932		clearTimeout(myRefresh);
2933	}
2934
2935	if (typeof refreshMSeconds != 'undefined') {
2936		myRefresh = setTimeout(function() {
2937			if (refreshIsLogout) {
2938				document.location = urlPath + 'logout.php?action=timeout';
2939			} else {
2940				if (previousPage != '') {
2941					refreshPage = previousPage;
2942				}
2943
2944				/* fix coner case with tree refresh */
2945				refreshPage = appendHeaderSuppression(refreshPage);
2946
2947				closeDateFilters();
2948
2949				$.ajaxQ.abortAll();
2950				$.get(refreshPage)
2951					.done(function(data) {
2952						checkForRedirects(data, refreshPage);
2953
2954						$('#main').empty().hide();
2955						$('div[class^="ui-"]').remove();
2956						$('#main').html(data);
2957						applySkin();
2958					})
2959					.fail(function(data) {
2960						getPresentHTTPErrorOrRedirect(data, refreshPage);
2961					}
2962				);
2963			}
2964		}, refreshMSeconds);
2965	}
2966}
2967
2968function pulsateStart(element) {
2969	pulsating = true;
2970	pulsate(element);
2971}
2972
2973function pulsate(element) {
2974	if (pulsating) {
2975		$(element || this).delay(100).fadeOut(800).delay(100).fadeIn(800, pulsate);
2976	}
2977}
2978
2979function pulsateStop(element) {
2980	pulsating = false;
2981}
2982
2983function setTitleAndHref() {
2984	myHref  = $(location).attr('href');
2985	myTitle = $(document).attr('title');
2986}
2987
2988function clearAllTimeouts() {
2989	if (typeof installTimer != 'undefined') {
2990		return true;
2991	}
2992
2993	var id = window.setTimeout(function() {}, 0);
2994
2995	while (id--) {
2996		window.clearTimeout(id); // will do nothing if no timeout with id is present
2997	}
2998}
2999
3000function setZoneInfo() {
3001	var dt     = new Date();
3002	var tz     = -dt.getTimezoneOffset();
3003	var maxAge = 365*86400;
3004
3005	var CactiDateTime = 'CactiDateTime=' + dt.toString() + '; Max-Age=' + maxAge + '; path=' + urlPath + '; SameSite=Strict;';
3006	var CactiTimeZone = 'CactiTimeZone=' + tz.toString() + '; Max-Age=' + maxAge + '; path=' + urlPath + '; SameSite=Strict;';
3007
3008	if (window.location.protocol == 'https:') {
3009		CactiDateTime += ' Secure;';
3010		CactiTimeZone += ' Secure;';
3011	}
3012
3013	document.cookie = CactiDateTime;
3014	document.cookie = CactiTimeZone;
3015}
3016
3017$(function() {
3018	statePushed = false;
3019	popFired    = false;
3020	var tapped  = false;
3021
3022	/**
3023	 * Unbind key elements to debounce actions
3024	 */
3025	$('input, select, textarea, a').unbind();
3026
3027	// Use traditional popstate handler
3028	window.onpopstate = function(event) {
3029		handlePopState();
3030	}
3031
3032	$('#filter, #rfilter').keydown(function(event) {
3033		if (event.keyCode == 8 && $(this).val() == '') {
3034			handlePopState();
3035		}
3036	});
3037
3038	setZoneInfo();
3039
3040	setTitleAndHref();
3041
3042	setupUserMenu();
3043
3044	applySkin();
3045
3046	setupEllipsis();
3047
3048	handleUserMenu();
3049
3050	$('#navigation_right').show();
3051
3052	if (isMobile.any() != null) {
3053		$(window).on('touchstart', function(event) {
3054			if (!tapped) {
3055				tapped = setTimeout(function() { tapped=null; }, 300);
3056			} else {
3057				clearTimeout(tapped);
3058				tapped = null;
3059
3060				if (screenfull.enabled) {
3061					screenfull.request();
3062				}
3063			}
3064		});
3065
3066		$(window).on('load', function(event) {
3067			setTimeout(function() { window.scrollTo(0, 1); }, 0);
3068		});
3069	}
3070});
3071
3072/* only perform the recalculation of elements at the final end of the windows resize event */
3073var waitForFinalEvent = (function () {
3074  var timers = {};
3075
3076  return function (callback, ms, uniqueId) {
3077    if (!uniqueId) {
3078      uniqueId = "Don't call this twice without a uniqueId";
3079    }
3080
3081    if (timers[uniqueId]) {
3082      clearTimeout(timers[uniqueId]);
3083    }
3084
3085    timers[uniqueId] = setTimeout(callback, ms);
3086  };
3087})();
3088
3089function setupEllipsis() {
3090	$('<div class="dropdownMenu">'
3091		+'<ul id="submenu-ellipsis" class="submenuoptions" style="display:none;">'
3092		+'</ul>'
3093	+'</div>').appendTo('body');
3094
3095	$('.maintabs-submenu, .usertabs-submenu, .submenu-ellipsis').off('click').on('click', function(event) {
3096		event.preventDefault();
3097
3098		var submenu_index = $(this).attr('id').replace('menu-', 'submenu-');
3099		var submenu = $('#'+submenu_index);
3100
3101		if (submenu.is(':visible') === false) {
3102			/* close other drop down menus first */
3103			$('.submenuoptions').slideUp(120);
3104			$('.menuoptions').slideUp(120);
3105
3106			/* re-position */
3107			var position = $(this).position();
3108
3109			if (position.left - parseInt(submenu.outerWidth()) < 0) {
3110				submenu.css({'left': 0}).slideDown(120);
3111			} else {
3112				submenu.css({'left': position.left - parseInt(submenu.outerWidth()) + parseInt($(this).outerWidth())}).slideDown(120);
3113			}
3114		} else {
3115			submenu.slideUp(120);
3116		}
3117
3118		return false;
3119	});
3120
3121	$('.submenuoptions').mouseenter(function(event) {
3122		clearTimeout(userMenuTimer);
3123	}).mouseleave(function(event) {
3124		if ($('.submenuoptions').is(':visible')) {
3125			userMenuTimer = setTimeout(function() {$('.submenuoptions').stop().slideUp(120);}, 1000);
3126		} else {
3127			clearTimeout(userMenuOpenTimer);
3128		}
3129	});
3130
3131	$(window).on('click', function(event) {
3132		if($(event.target).parents('.submenuoptions').length == 0 && $('.submenuoptions').is(':visible')) {
3133			$('.submenuoptions').slideUp(120);
3134		}
3135		if($(event.target).parents('.menuoptions').length == 0 && $('.menuoptions').is(':visible')) {
3136			$('.menuoptions').slideUp(120);
3137		}
3138	});
3139}
3140
3141function keepWindowSize() {
3142	$(window).resize(function (event) {
3143		waitForFinalEvent(function() {
3144			$('.cactiGraphContentArea').show();
3145
3146   			var resizeTime = new Date();
3147			var myEvent = event;
3148			if (resizeTimeout === false) {
3149				resizeTimeout = true;
3150				setTimeout(function() {
3151					responsiveUI(myEvent);
3152				}, resizeDelta);
3153			}
3154			heightPage = $(window).height();
3155
3156			if ($('#cactiPageHead').is(':visible')) {
3157				heightPageHead = $('#cactiPageHead').outerHeight();
3158			} else {
3159				heightPageHead = 0;
3160			}
3161
3162			if ($('#breadCrumbBar').is(':visible')) {
3163				heightBreadCrumbBar = $('#breadCrumbBar').outerHeight();
3164			} else {
3165				heightBreadCrumbBar = 0;
3166			}
3167
3168			if ($('#cactiPageBottom').is(':visible')) {
3169				heightPageBottom = $('#cactiPageBottom').outerHeight();
3170			} else {
3171				heightPageBottom = 0;
3172			}
3173
3174			heightPageContent = heightPage - heightPageHead - heightPageBottom - heightBreadCrumbBar;
3175
3176			if (theme != 'classic') {
3177				$('body').css('height', heightPage);
3178				$('#cactiContent, #navigation, #navigation_right').css('height', heightPageContent);
3179
3180				// Handle links pages
3181				$('#content').css({'width':'100%', 'height':heightPageContent-4});
3182			} else {
3183				// Handle links pages
3184				$('#content').css({'width':'100%', 'height':$(document).height()});
3185			}
3186
3187			var navWidth = $('#navigation').width();
3188			if (navWidth > 220) {
3189				$('#searcher').css('width', navWidth-70);
3190			} else {
3191				$('#searcher').css('width', 150);
3192			}
3193
3194			responsiveResizeGraphs();
3195
3196			/* close open dropdown menus first off */
3197			$('.dropdownMenu > ul').hide();
3198
3199			if ($('#gtabs > .tabs').is(':visible')) {
3200				var graphTabWidth = $('#gtabs > .tabs').outerWidth();
3201			} else {
3202				var graphTabWidth = 0;
3203			}
3204
3205			if ($('.usertabs').length) {
3206				var userTabs = $('.usertabs').outerWidth();
3207			} else {
3208				var userTabs = 0;
3209			}
3210
3211			var bodyWidth     = $('body').width();
3212			var otherWidth    = 0;
3213			$('#tabs').find('div:not(.maintabs):visible').each(function() {
3214				otherWidth += $(this).outerWidth();
3215			});
3216
3217			var ellipsisWidth = $('.maintabs-submenu-ellipsis').outerWidth();
3218			var tabHeight     = $('#tabs').outerHeight();
3219			var mainTabPos    = false;
3220
3221			if ($('.maintabs').length) {
3222				mainTabPos    = $('.maintabs:first').position();
3223			}
3224
3225			if ($('.usertabs').length) {
3226				mainTabHeight = tabHeight;
3227				userTabPos = $('.usertabs').position();
3228			} else if (mainTabPos != false) {
3229				mainTabHeight = $('.maintabs:first nav').outerHeight();
3230				userTabPos = mainTabPos;
3231			}
3232
3233			pageWidth = bodyWidth;
3234
3235			var items = $($('.maintabs nav ul li a.lefttab').get());
3236			var done = false;
3237			items.each(function() {
3238				var id = $(this).attr('id');
3239
3240				showCurrentTab(id);
3241			});
3242
3243			// Hide top menus if you have to
3244			var items = $($('.maintabs nav ul li a.lefttab').get().reverse());
3245			var done = false;
3246			items.each(function() {
3247				var id = $(this).attr('id');
3248
3249				if (!done) {
3250					if (tabsWrapping()) {
3251						hideCurrentTab(id, true);
3252					} else {
3253						done = true;
3254					}
3255				}
3256			});
3257
3258			if ($('#submenu-ellipsis li').length == 0) {
3259				$('.ellipsis').hide();
3260			} else {
3261				$('.ellipsis').show();
3262			}
3263		}, 50, 'resize-content');
3264	}).trigger('resize');
3265}
3266
3267function hideCurrentTab(id, shrinking) {
3268	if ($('#'+id+'-ellipsis').length == 0) {
3269		var myid     = id+'-ellipsis';
3270		var href     = $('#'+id).attr('href');
3271		var selected = $('#'+id).hasClass('selected');
3272		var text     = $('#'+id).text();
3273
3274		if (shrinking) {
3275			$('#submenu-ellipsis').prepend('<li><a class="lefttab' + (selected ? ' selected':'') + '" id="'+myid+'" href="'+href+'">' + text + '</a></li>');
3276		} else {
3277			$('#submenu-ellipsis').append('<li><a class="lefttab' + (selected ? ' selected':'') + '" id="'+myid+'" href="'+href+'">' + text + '</a></li>');
3278		}
3279
3280		setupResponsiveMenuAndTabs();
3281
3282		$('#'+id).parent().hide();
3283	}
3284}
3285
3286function showCurrentTab(id) {
3287	$('#'+id+'-ellipsis').parent().remove();
3288	$('#'+id).parent().show();
3289}
3290
3291function tabsWrapping() {
3292	var mainTabPos    = $('.maintabs:first').position();
3293	var tabHeight     = $('#tabs').height();
3294
3295	if ($('.usertabs').length) {
3296		var mainTabHeight = tabHeight;
3297		var userTabPos    = $('.usertabs').position();
3298	} else {
3299		var mainTabHeight = $('.maintabs:first nav').height();
3300		var userTabPos    = mainTabPos;
3301	}
3302
3303	var bodyWidth     = $('body').width();
3304	var otherWidth    = 0;
3305	$('#tabs').find('div:not(.maintabs):visible').each(function() {
3306		otherWidth += $(this).outerWidth();
3307	});
3308
3309	var ellipsisWidth = $('.maintabs-submenu-ellipsis').outerWidth();
3310	var mtabsWidth  = $('.maintabs:not(.usertabs)').outerWidth();
3311
3312	if ($('#gtabs>.tabs').length) {
3313		var gtabsWidth = $('#gtabs>.tabs').outerWidth();
3314	} else {
3315		var gtabsWidth = 0;
3316	}
3317
3318	if ($('.usertabs').length) {
3319		var utabsWidth  = $('.usertabs').outerWidth();
3320	} else {
3321		var utabsWidth  = 0;
3322	}
3323
3324	if (gtabsWidth + mtabsWidth + utabsWidth + otherWidth + ellipsisWidth > bodyWidth - 20) {
3325		return true;
3326	}
3327
3328	if (mainTabPos.top != userTabPos.top || mainTabHeight > tabHeight) {
3329		return true;
3330	} else {
3331		return false;
3332	}
3333}
3334
3335/* Graph related javascript functions */
3336if (typeof urlPath == 'undefined') {
3337	var urlPath = '';
3338}
3339
3340var graphPage  = urlPath + 'graph_view.php';
3341var pageAction = 'preview';
3342
3343function checkForLogout(data) {
3344	checkForRedirects(data, null);
3345}
3346
3347function checkForRedirects(data, href) {
3348	if (typeof data == 'undefined') {
3349		return true;
3350	} else if (typeof data == 'object') {
3351		return true;
3352	} else if (data.indexOf('cactiLoginSuspend') >= 0) {
3353		$.ajaxQ.abortAll();
3354		document.location = urlPath + 'logout.php?action=disabled';
3355	} else if (data.indexOf('cactiRemoteState') >= 0) {
3356		$.ajaxQ.abortAll();
3357		document.location = urlPath + 'logout.php?action=remote';
3358	} else if (data.indexOf('cactiPermissionDenied') >= 0) {
3359		$.ajaxQ.abortAll();
3360		document.location = urlPath + 'permission_denied.php';
3361	} else if (data.indexOf('cactiRedirect') >= 0) {
3362		if (typeof href == 'undefined' || href == null) {
3363			$.ajaxQ.abortAll();
3364			document.location = stripHeaderSuppression(document.location.href);
3365		} else {
3366			$.ajaxQ.abortAll();
3367			document.location = stripHeaderSuppression(href);
3368		}
3369	} else if (data.indexOf('cactiLoginLogo') >= 0) {
3370		$.ajaxQ.abortAll();
3371		document.location = urlPath + 'logout.php?action=timeout';
3372	}
3373
3374	return false;
3375}
3376
3377function clearGraphFilter() {
3378	var href = appendHeaderSuppression(graphPage+'?action='+pageAction+'&clear=1');
3379
3380	closeDateFilters();
3381
3382	$.ajaxQ.abortAll();
3383	$.get(href)
3384		.done(function(data) {
3385			checkForRedirects(data, href);
3386
3387			$('#main').empty().hide();
3388			$('div[class^="ui-"]').remove();
3389			$('#main').html(data);
3390
3391			applySkin();
3392		})
3393		.fail(function(data) {
3394			getPresentHTTPErrorOrRedirect(data, href);
3395		}
3396	);
3397}
3398
3399function closeDateFilters() {
3400	date1Open = false;
3401	date2Open = false;
3402
3403	$('#date1').datetimepicker('hide');
3404	$('#date2').datetimepicker('hide');
3405}
3406
3407function saveGraphFilter(section) {
3408	closeDateFilters();
3409
3410	var error_href = graphPage;
3411
3412	$.post(graphPage+'?action=save', {
3413		section: section,
3414		columns: $('#columns').val(),
3415		graphs: $('#graphs').val(),
3416		graph_template_id: $('#graph_template_id').val(),
3417		predefined_timespan: $('#predefined_timespan').val(),
3418		predefined_timeshift: $('#predefined_timeshift').val(),
3419		thumbnails: $('#thumbnails').is(':checked'),
3420		__csrf_magic: csrfMagicToken
3421		}).done(function(data) {
3422			checkForRedirects(data);
3423
3424			$('#text').show().text(filterSettingsSaved).fadeOut(2000, function() {
3425				$('#text').empty();
3426			});
3427		})
3428		.fail(function(data) {
3429			getPresentHTTPErrorOrRedirect(data, error_href);
3430		}
3431	);
3432}
3433
3434function applyGraphFilter() {
3435	statePushed = false;
3436
3437	var href = appendHeaderSuppression(graphPage+'?action='+pageAction +
3438		'&rfilter=' + base64_encode($('#rfilter').val()) +
3439		(typeof $('#host_id').val() != 'undefined' ? '&host_id=' + $('#host_id').val():'') +
3440		'&columns=' + $('#columns').val() +
3441		'&graphs='  + $('#graphs').val() +
3442		'&graph_template_id=' + $('#graph_template_id').val() +
3443		'&thumbnails=' + $('#thumbnails').is(':checked'));
3444
3445	/* replace myHref parameter for address bar update */
3446	var urlParts  = myHref.split('?');
3447	var urlParams = new URLSearchParams(urlParts[1]);
3448
3449	urlParams.set('rfilter', base64_encode($('#rfilter').val()));
3450	if (typeof $('#host_id').val() != 'undefined') {
3451		urlParams.set('host_id', $('#host_id').val());
3452	}
3453	myHref = urlParts[0]+ '?' + urlParams.toString();
3454
3455	closeDateFilters();
3456
3457	$.ajaxQ.abortAll();
3458	$.get(href)
3459		.done(function(data) {
3460			checkForRedirects(data, href);
3461
3462			$('#main').empty().hide();
3463			$('div[class^="ui-"]').remove();
3464			$('#main').html(data);
3465			applySkin();
3466
3467			pushState(myTitle, myHref);
3468		})
3469		.fail(function(data) {
3470			getPresentHTTPErrorOrRedirect(data, href);
3471		}
3472	);
3473}
3474
3475function cleanHeader(href) {
3476	href = stripHeaderSuppression(href);
3477	href = href.replace('action=tree_content', 'action=tree');
3478	href = href.replace('?nostate=true', '?').replace('&nostate=true', '').replace('?&', '?');
3479
3480	return href;
3481}
3482
3483function pushState(myTitle, myHref) {
3484	if (myHref.indexOf('nostate') < 0) {
3485		if (statePushed == false) {
3486			if (typeof window.history.pushState != 'undefined') {
3487				var myObject = { Page: myTitle, Url: cleanHeader(myHref) };
3488				window.history.pushState(myObject, myObject.Page, myObject.Url);
3489			}
3490		}
3491	} else if (typeof window.history.popState == 'function') {
3492		window.history.popState();
3493	}
3494
3495	statePushed = true;
3496}
3497
3498function handlePopState() {
3499	var href = document.location.href;
3500
3501	if (popFired == false) {
3502		if (href.indexOf('#') == -1) {
3503			if (href.indexOf('header=false') > 0) {
3504				loadPageNoHeader(href + '&nostate=true');
3505			} else if (basename(href) == lastPage) {
3506				loadPageNoHeader(href + (href.indexOf('?') > 0 ? '&header=false&nostate=true':'?header=false&nostate=true'));
3507			} else {
3508				href.replace('header=false','').replace('?&', '?').replace('&&', '&');
3509				document.location = href + (href.indexOf('?') > 0 ? '&nostate=true':'?nostate=true');
3510			}
3511		}
3512	}
3513
3514	popFired = true;
3515	lastPage = basename(href);
3516}
3517
3518function applyGraphTimespan() {
3519	var href = appendHeaderSuppression(graphPage+'?action='+pageAction+
3520		'&predefined_timespan='+$('#predefined_timespan').val()+
3521		($('#rfilter').length ? '&rfilter=' + base64_encode($('#rfilter').val()):'') +
3522		'&predefined_timeshift='+$('#predefined_timeshift').val());
3523
3524	closeDateFilters();
3525
3526	$.ajaxQ.abortAll();
3527	$.get(href)
3528		.done(function(data) {
3529			checkForRedirects(data, href);
3530
3531			$('#main').empty().hide();
3532			$('div[class^="ui-"]').remove();
3533			$('#main').html(data);
3534			applySkin();
3535		})
3536		.fail(function(data) {
3537			getPresentHTTPErrorOrRedirect(data, href);
3538		}
3539	);
3540}
3541
3542function refreshGraphTimespanFilter() {
3543	var json = {
3544		custom: 1,
3545		button_refresh_x: 1,
3546		date1: $('#date1').val(),
3547		rfilter: base64_encode($('#rfilter').val()),
3548		date2: $('#date2').val(),
3549		predefined_timespan: $('#predefined_timespan').val(),
3550		predefined_timeshift: $('#predefined_timeshift').val(),
3551		__csrf_magic: csrfMagicToken
3552	};
3553
3554	var href = appendHeaderSuppression(graphPage+'?action='+pageAction);
3555
3556	closeDateFilters();
3557
3558	$.ajaxQ.abortAll();
3559	$.post(href, json).done(function(data) {
3560		checkForRedirects(data, href);
3561
3562		$('#main').empty().hide();
3563		$('div[class^="ui-"]').remove();
3564		$('#main').html(data);
3565		applySkin();
3566	});
3567}
3568
3569function timeshiftGraphFilterLeft() {
3570	var json = {
3571		move_left_x: 1,
3572		move_left_y: 1,
3573		date1: $('#date1').val(),
3574		date2: $('#date2').val(),
3575		predefined_timespan: $('#predefined_timespan').val(),
3576		predefined_timeshift: $('#predefined_timeshift').val(),
3577		__csrf_magic: csrfMagicToken
3578	};
3579
3580	var href = appendHeaderSuppression(graphPage+'?action='+pageAction);
3581
3582	closeDateFilters();
3583
3584	$.ajaxQ.abortAll();
3585	$.post(href, json).done(function(data) {
3586		checkForRedirects(data, href);
3587
3588		$('#main').empty().hide();
3589		$('div[class^="ui-"]').remove();
3590		$('#main').html(data);
3591		applySkin();
3592	});
3593}
3594
3595function timeshiftGraphFilterRight() {
3596	var json = {
3597		move_right_x: 1,
3598		move_right_y: 1,
3599		date1: $('#date1').val(),
3600		date2: $('#date2').val(),
3601		predefined_timespan: $('#predefined_timespan').val(),
3602		predefined_timeshift: $('#predefined_timeshift').val(),
3603		__csrf_magic: csrfMagicToken
3604	};
3605
3606	var href = appendHeaderSuppression(graphPage+'?action='+pageAction);
3607
3608	closeDateFilters();
3609
3610	$.ajaxQ.abortAll();
3611	$.post(href, json).done(function(data) {
3612		checkForRedirects(data, href);
3613
3614		$('#main').empty().hide();
3615		$('div[class^="ui-"]').remove();
3616		$('#main').html(data);
3617		applySkin();
3618	});
3619}
3620
3621function clearGraphTimespanFilter() {
3622	var json = {
3623		button_clear: 1,
3624		date1: $('#date1').val(),
3625		date2: $('#date2').val(),
3626		predefined_timespan: $('#predefined_timespan').val(),
3627		predefined_timeshift: $('#predefined_timeshift').val(),
3628		__csrf_magic: csrfMagicToken
3629	};
3630
3631	var href = appendHeaderSuppression(graphPage+'?action='+pageAction);
3632
3633	closeDateFilters();
3634
3635	$.ajaxQ.abortAll();
3636	$.post(href, json).done(function(data) {
3637		checkForRedirects(data, href);
3638
3639		$('#main').empty().hide();
3640		$('div[class^="ui-"]').remove();
3641		$('#main').html(data);
3642		applySkin();
3643	});
3644}
3645
3646function removeSpikesStdDev(local_graph_id) {
3647	var href = urlPath + 'spikekill.php' +
3648		'?method=stddev'   +
3649		'&local_graph_id=' + local_graph_id;
3650
3651	closeDateFilters();
3652
3653	$.getJSON(href)
3654		.done(function(data) {
3655			checkForRedirects(data, href);
3656
3657			redrawGraph(local_graph_id);
3658			$('#spikeresults').remove();
3659			$('body').append('<div id="spikeresults" style="overflow-y:scroll;" title="' + spikeKillResults + '"></div>');
3660			$('#spikeresults').html(data.results);
3661			$('#spikeresults').dialog({ width:1100, maxHeight: 600 });
3662		})
3663		.fail(function(data) {
3664			getPresentHTTPError(data);
3665		}
3666	);
3667}
3668
3669function removeSpikesVariance(local_graph_id) {
3670	var href = urlPath + 'spikekill.php' +
3671		'?method=variance' +
3672		'&local_graph_id=' + local_graph_id;
3673
3674	closeDateFilters();
3675
3676	$.getJSON(href)
3677		.done(function(data) {
3678			checkForRedirects(data, href);
3679
3680			redrawGraph(local_graph_id);
3681			$('#spikeresults').remove();
3682			$('body').append('<div id="spikeresults" style="overflow-y:scroll;" title="' + spikeKillResults + '"></div>');
3683			$('#spikeresults').html(data.results);
3684			$('#spikeresults').dialog({ width:1100, maxHeight: 600 });
3685		})
3686		.fail(function(data) {
3687			getPresentHTTPError(data);
3688		}
3689	);
3690}
3691
3692function removeSpikesInRange(local_graph_id) {
3693	var href = urlPath + 'spikekill.php' +
3694		'?method=fill' +
3695		'&local_graph_id=' + local_graph_id +
3696		'&outlier-start='  + graph_start    +
3697		'&outlier-end='    + graph_end;
3698
3699	closeDateFilters();
3700
3701	$.getJSON(href)
3702		.done(function(data) {
3703			checkForRedirects(data, href);
3704
3705			redrawGraph(local_graph_id);
3706			$('#spikeresults').remove();
3707			$('body').append('<div id="spikeresults" style="overflow-y:scroll;" title="' + spikeKillResults + '"></div>');
3708			$('#spikeresults').html(data.results);
3709			$('#spikeresults').dialog({ width:1100, maxHeight: 600 });
3710		})
3711		.fail(function(data) {
3712			getPresentHTTPError(data);
3713		}
3714	);
3715}
3716
3717function removeRangeFill(local_graph_id) {
3718	var href = urlPath + 'spikekill.php' +
3719		'?method=float'    +
3720		'&local_graph_id=' + local_graph_id +
3721		'&outlier-start='  + graph_start +
3722		'&outlier-end='    + graph_end;
3723
3724	closeDateFilters();
3725
3726	$.getJSON(href)
3727		.done(function(data) {
3728			checkForRedirects(data, href);
3729
3730			redrawGraph(local_graph_id);
3731			$('#spikeresults').remove();
3732			$('body').append('<div id="spikeresults" style="overflow-y:scroll;" title="' + spikeKillResults + '"></div>');
3733			$('#spikeresults').html(data.results);
3734			$('#spikeresults').dialog({ width:1100, maxHeight: 600 });
3735		})
3736		.fail(function(data) {
3737			getPresentHTTPError(data);
3738		}
3739	);
3740}
3741
3742function dryRunStdDev(local_graph_id) {
3743	var href = urlPath + 'spikekill.php' +
3744		'?method=stddev'   +
3745		'&dryrun=true'     +
3746		'&local_graph_id=' + local_graph_id;
3747
3748	closeDateFilters();
3749
3750	$.getJSON(href)
3751		.done(function(data) {
3752			checkForRedirects(data, href);
3753
3754			$('#spikeresults').remove();
3755			$('body').append('<div id="spikeresults" style="overflow-y:scroll;" title="' + spikeKillResults + '"></div>');
3756			$('#spikeresults').html(data.results);
3757			$('#spikeresults').dialog({ width:1100, maxHeight: 600 });
3758		})
3759		.fail(function(data) {
3760			getPresentHTTPError(data);
3761		}
3762	);
3763}
3764
3765function dryRunVariance(local_graph_id) {
3766	var href = urlPath + 'spikekill.php' +
3767		'?method=variance' +
3768		'&dryrun=true'     +
3769		'&local_graph_id=' + local_graph_id;
3770
3771	closeDateFilters();
3772
3773	$.getJSON(href)
3774		.done(function(data) {
3775			checkForRedirects(data, href);
3776
3777			$('#spikeresults').remove();
3778			$('body').append('<div id="spikeresults" style="overflow-y:scroll;" title="' + spikeKillResults + '"></div>');
3779			$('#spikeresults').html(data.results);
3780			$('#spikeresults').dialog({ width:1100, maxHeight: 600 });
3781		})
3782		.fail(function(data) {
3783			getPresentHTTPError(data);
3784		}
3785	);
3786}
3787
3788function dryRunSpikesInRange(local_graph_id) {
3789	var href = urlPath + 'spikekill.php' +
3790		'?method=fill' +
3791		'&dryrun=true' +
3792		'&local_graph_id=' + local_graph_id +
3793		'&outlier-start='  + graph_start +
3794		'&outlier-end='    + graph_end;
3795
3796	closeDateFilters();
3797
3798	$.getJSON(href)
3799		.done(function(data) {
3800			checkForRedirects(data, href);
3801
3802			redrawGraph(local_graph_id);
3803			$('#spikeresults').remove();
3804			$('body').append('<div id="spikeresults" style="overflow-y:scroll;" title="' + spikeKillResults + '"></div>');
3805			$('#spikeresults').html(data.results);
3806			$('#spikeresults').dialog({ width:1100, maxHeight: 600 });
3807		})
3808		.fail(function(data) {
3809			getPresentHTTPError(data);
3810		}
3811	);
3812}
3813
3814function dryRunRangeFill(local_graph_id) {
3815	var href = urlPath + 'spikekill.php' +
3816		'?method=float' +
3817		'&dryrun=true'  +
3818		'&local_graph_id=' + local_graph_id +
3819		'&outlier-start='  + graph_start +
3820		'&outlier-end='    + graph_end;
3821
3822	closeDateFilters();
3823
3824	$.getJSON(href)
3825		.done(function(data) {
3826			checkForRedirects(data, href);
3827
3828			redrawGraph(local_graph_id);
3829			$('#spikeresults').remove();
3830			$('body').append('<div id="spikeresults" style="overflow-y:scroll;" title="' + spikeKillResults + '"></div>');
3831			$('#spikeresults').html(data.results);
3832			$('#spikeresults').dialog({ width:1100, maxHeight: 600 });
3833		})
3834		.fail(function(data) {
3835			getPresentHTTPError(data);
3836		}
3837	);
3838}
3839
3840function redrawGraph(graph_id) {
3841	var mainWidth = getMainWidth() - 30;
3842	var isThumb   = $('#thumbnails').is(':checked');
3843	var myColumns = $('#columns').val();
3844	var graphRow  = $('.tableRowGraph').width();
3845	var drillDown = $('.graphDrillDown:first').outerWidth() + 10;
3846
3847	if (mainWidth < graphRow) {
3848		graphRow = mainWidth - drillDown;
3849	} else if (graphRow == 0) {
3850		graphRow = mainWidth;
3851	}
3852
3853	var myWidth = (graphRow-(drillDown * myColumns)) / myColumns;
3854
3855	var graph_height = $('#wrapper_'+graph_id).attr('graph_height');
3856	var graph_width  = $('#wrapper_'+graph_id).attr('graph_width');
3857
3858	closeDateFilters();
3859
3860	var url = 'graph_json.php?rra_id=0'   +
3861		'&local_graph_id=' + graph_id     +
3862		'&graph_start='    + graph_start  +
3863		'&graph_end='      + graph_end    +
3864		'&graph_height='   + graph_height +
3865		'&graph_width='    + graph_width  +
3866		(isThumb ? '&graph_nolegend=true':'');
3867
3868	$.getJSON(url)
3869		.done(function(data) {
3870			if (typeof data.status == 'undefined') {
3871				if (myWidth < data.image_width) {
3872					ratio=myWidth/data.image_width;
3873					data.image_width  = parseInt(data.image_width  * ratio);
3874					data.image_height = parseInt(data.image_height * ratio);
3875					data.graph_width  = parseInt(data.graph_width  * ratio);
3876					data.graph_height = parseInt(data.graph_height * ratio);
3877					data.graph_top    = parseInt(data.graph_top  * ratio);
3878					data.graph_left   = parseInt(data.graph_left * ratio);
3879				}
3880
3881				$('#wrapper_'+data.local_graph_id).empty().html(
3882					"<img class='graphimage' id='graph_"+data.local_graph_id+"'"+
3883					" src='data:image/"+data.type+";base64,"+data.image+"'"+
3884					" rra_id='"+data.rra_id+"'"+
3885					" graph_type='"+data.type+"'"+
3886					" graph_id='"+data.local_graph_id+"'"+
3887					" graph_start='"+data.graph_start+"'"+
3888					" graph_end='"+data.graph_end+"'"+
3889					" graph_left='"+data.graph_left+"'"+
3890					" graph_top='"+data.graph_top+"'"+
3891					" graph_width='"+data.graph_width+"'"+
3892					" graph_height='"+data.graph_height+"'"+
3893					" width='"+data.image_width+"'"+
3894					" height='"+data.image_height+"'"+
3895					" image_width='"+data.image_width+"'"+
3896					" image_height='"+data.image_height+"'"+
3897					" canvas_top='"+data.graph_top+"'"+
3898					" canvas_left='"+data.graph_left+"'"+
3899					" canvas_width='"+data.graph_width+"'"+
3900					" canvas_height='"+data.graph_height+"'"+
3901					" value_min='"+data.value_min+"'"+
3902					" value_max='"+data.value_max+"'>"
3903				);
3904
3905				$('#graph_'+data.local_graph_id).zoom({
3906					inputfieldStartTime : 'date1',
3907					inputfieldEndTime : 'date2',
3908					serverTimeOffset : timeOffset
3909				});
3910
3911				data = undefined;
3912			} else {
3913				getPresentHTTPError(data);
3914			}
3915		})
3916		.fail(function(data) {
3917			getPresentHTTPError(data);
3918		}
3919	);
3920}
3921
3922function initializeGraphs(disable_cache) {
3923	disable_cache = (typeof disable_cache == 'undefined') ? false : true;
3924
3925	$.ajaxQ.abortAll();
3926
3927	$('a[id$="_mrtg"]').each(function() {
3928		var graph_id = $(this).attr('id').replace('graph_','').replace('_mrtg','');
3929
3930		$(this).attr('href', urlPath + 'graph.php?local_graph_id=' + graph_id);
3931
3932		$(this).off('click').on('click', function(event) {
3933			var graph_id=$(this).attr('id').replace('graph_','').replace('_mrtg','');
3934
3935			event.preventDefault();
3936			event.stopPropagation();
3937
3938			closeDateFilters();
3939
3940			var url = urlPath + 'graph.php?local_graph_id=' + graph_id + '&hea
3940der=false';
3941
3942			$.ajaxQ.abortAll();
3943			$.get(url)
3944				.done(function(data) {
3945					checkForRedirects(data);
3946
3947					$('#main').empty().hide();
3948					$('#breadcrumbs').append('<li><a id="nav_mrgt" href="#">'+timeGraphView+'</a></li>');
3949					$('div[class^="ui-"]').remove();
3950					$('#main').html(data);
3951					applySkin();
3952					clearTimeout(myRefresh);
3953				})
3954				.fail(function(data) {
3955					getPresentHTTPErrorOrRedirect(data, url);
3956				}
3957			);
3958		});
3959	});
3960
3961	// Get these outside of the each to reduce calls
3962	var timestampDate1 = getTimestampFromDate($('#date1').val());
3963	var timestampDate2 = getTimestampFromDate($('#date2').val());
3964
3965	$('a[id$="_csv"]').each(function() {
3966		var graph_id=$(this).attr('id').replace('graph_','').replace('_csv','');
3967
3968		// Disable context menu
3969		$(this).children().contextmenu(function() {
3970			return false;
3971		});
3972
3973		var url = urlPath +
3974			'graph_xport.php'  +
3975			'?local_graph_id=' + graph_id +
3976			'&rra_id=0'        +
3977			'&view_type=tree'  +
3978			'&graph_start='    + timestampDate1 +
3979			'&graph_end='      + timestampDate2;
3980
3981		$(this).attr('href', url);
3982
3983		$(this).off('click').on('click', function(event) {
3984			var graph_id = $(this).attr('id').replace('graph_','').replace('_csv','');
3985			event.preventDefault();
3986			event.stopPropagation();
3987
3988			document.location = urlPath +
3989				'graph_xport.php'  +
3990				'?local_graph_id=' + graph_id+
3991				'&rra_id=0'        +
3992				'&view_type=tree'  +
3993				'&graph_start='    + timestampDate1+
3994				'&graph_end='      + timestampDate2;
3995
3996			Pace.stop();
3997		});
3998	});
3999
4000	$('#form_graph_view').off('submit').on('submit', function(event) {
4001		event.preventDefault();
4002		event.stopPropagation();
4003		applyFilter();
4004	});
4005
4006	var mainWidth = getMainWidth() - 30;
4007	var myColumns = $('#columns').val();
4008	var isThumb   = $('#thumbnails').is(':checked');
4009	var myWidth   = (mainWidth-(30*myColumns))/myColumns;
4010	var numGraphs = $('.graphWrapper').length;
4011
4012	$('.graphWrapper').each(function() {
4013		var graph_id = $(this).attr('graph_id');
4014		if (!(graph_id > 0)) {
4015			graph_id=$(this).attr('id').replace('wrapper_','');
4016		}
4017
4018		var rra_id = $(this).attr('rra_id');
4019		if (!(rra_id > 0)) {
4020			rra_id=0;
4021		}
4022
4023		var graph_height = $(this).attr('graph_height');
4024		var graph_width  = $(this).attr('graph_width');
4025		var error_url    = urlPath + 'graph_view.php';
4026
4027		closeDateFilters();
4028
4029		var url = urlPath + 'graph_json.php' +
4030			'?rra_id='         +rra_id +
4031			'&local_graph_id=' + graph_id +
4032			'&graph_start='    + graph_start +
4033			'&graph_end='      + graph_end +
4034			'&graph_height='   + graph_height +
4035			'&graph_width='    + graph_width +
4036			(disable_cache ? '&disable_cache=true':'') +
4037			(isThumb ? '&graph_nolegend=true':'');
4038
4039		$.getJSON(url)
4040			.done(function(data) {
4041				if (myWidth < data.image_width) {
4042					ratio = myWidth/data.image_width;
4043
4044					data.image_width  = parseInt(data.image_width  * ratio);
4045					data.image_height = parseInt(data.image_height * ratio);
4046					data.graph_width  = parseInt(data.graph_width  * ratio);
4047					data.graph_height = parseInt(data.graph_height * ratio);
4048					data.graph_top    = parseInt(data.graph_top  * ratio);
4049					data.graph_left   = parseInt(data.graph_left * ratio);
4050				}
4051
4052				var wrapper_id = '#wrapper_'+data.local_graph_id;
4053
4054				if (rra_id > 0) {
4055					wrapper_id += '[rra_id=\'' + data.rra_id + '\']';
4056				}
4057
4058				$(wrapper_id).empty().html(
4059					"<img class='graphimage' id='graph_"+data.local_graph_id+"'"+
4060					" src='data:image/"+data.type+";base64,"+data.image+"'"+
4061					" rra_id='"+data.rra_id+"'"+
4062					" graph_type='"+data.type+"'"+
4063					" graph_id='"+data.local_graph_id+"'"+
4064					" graph_start='"+data.graph_start+"'"+
4065					" graph_end='"+data.graph_end+"'"+
4066					" graph_left='"+data.graph_left+"'"+
4067					" graph_top='"+data.graph_top+"'"+
4068					" graph_width='"+data.graph_width+"'"+
4069					" graph_height='"+data.graph_height+"'"+
4070					" width='"+data.image_width+"'"+
4071					" height='"+data.image_height+"'"+
4072					" image_width='"+data.image_width+"'"+
4073					" image_height='"+data.image_height+"'"+
4074					" canvas_top='"+data.graph_top+"'"+
4075					" canvas_left='"+data.graph_left+"'"+
4076					" canvas_width='"+data.graph_width+"'"+
4077					" canvas_height='"+data.graph_height+"'"+
4078					" value_min='"+data.value_min+"'"+
4079					" value_max='"+data.value_max+"'>"
4080				);
4081
4082				var graph_id = '#graph_'+data.local_graph_id;
4083				if (rra_id > 0) {
4084					graph_id += '[rra_id=\'' + data.rra_id + '\']';
4085				}
4086
4087				$(graph_id).zoom({
4088					inputfieldStartTime : 'date1',
4089					inputfieldEndTime : 'date2',
4090					serverTimeOffset : timeOffset
4091				});
4092
4093				if (typeof realtimeArray != 'undefined') {
4094					realtimeArray[data.local_graph_id] = false;
4095				}
4096
4097				if (!--numGraphs) {
4098					responsiveResizeGraphs();
4099				}
4100
4101				data = undefined;
4102			})
4103			.fail(function(data) {
4104				getPresentHTTPErrorOrRedirect(data, error_url);
4105			}
4106		);
4107	});
4108
4109	$('#realtimeoff').off('click').on('click', function() {
4110		stopRealtime();
4111	});
4112
4113	$('#ds_step').off('change').on('change', function() {
4114		realtimeGrapher();
4115	});
4116
4117	$('a[id$="_util"]').each(function() {
4118		var graph_id = $(this).attr('id').replace('graph_','').replace('_util','');
4119
4120		$(this).attr('href', urlPath +
4121			'graph.php'    +
4122			'?action=zoom' +
4123			'&rra_id=0'    +
4124			'&local_graph_id=' + graph_id +
4125			'&graph_start='    + timestampDate1 +
4126			'&graph_end='      + timestampDate2);
4127
4128		$(this).off('click').on('click', function(event) {
4129			var graph_id = $(this).attr('id').replace('graph_','').replace('_util','');
4130
4131			event.preventDefault();
4132			event.stopPropagation();
4133
4134			closeDateFilters();
4135
4136			var url = urlPath + 'graph.php' +
4137				'?action=zoom'  +
4138				'&header=false' +
4139				'&rra_id=0'     +
4140				'&local_graph_id=' + graph_id +
4141				'&graph_start='    + getTimestampFromDate($('#date1').val()) +
4142				'&graph_end='      + getTimestampFromDate($('#date2').val());
4143
4144			$.ajaxQ.abortAll();
4145			$.get(url)
4146				.done(function(data) {
4147					checkForRedirects(data);
4148
4149					$('#main').empty().hide();
4150					$('div[class^="ui-"]').remove();
4151					$('#main').html(data);
4152					$('#breadcrumbs').append('<li><a id="nav_butil" href="#">'+utilityView+'</a></li>');
4153					applySkin();
4154					clearTimeout(myRefresh);
4155				})
4156				.fail(function(data) {
4157					getPresentHTTPErrorOrRedirect(data, url);
4158				}
4159			);
4160		});
4161	});
4162
4163	$('a[id$="_realtime"]').each(function() {
4164		// Disable right click
4165		$(this).children().on('contextmenu', function(event) {
4166			return false;
4167		});
4168
4169		$(this).off('click').on('click', function(event) {
4170			var graph_id = $(this).attr('id').replace('graph_','').replace('_realtime','');
4171
4172			event.preventDefault();
4173			event.stopPropagation();
4174
4175			if (realtimeArray[graph_id]) {
4176				$('#wrapper_'+graph_id).html(keepRealtime[graph_id]).change();
4177				$(this).html("<img class='drillDown' title='"+realtimeClickOn+"' alt='' src='" + urlPath + "images/chart_curve_go.png'>");
4178
4179				$('graph_id'+graph_id).tooltip().zoom({
4180					inputfieldStartTime : 'date1',
4181					inputfieldEndTime : 'date2',
4182					serverTimeOffset : timeOffset
4183				});
4184
4185				realtimeArray[graph_id] = false;
4186				setFilters();
4187			} else {
4188				keepRealtime[graph_id]  = $('#wrapper_'+graph_id).html();
4189				$(this).html("<i style='text-align:center;padding:0px;' title='"+realtimeClickOff+"' class='drillDown fa fa-circle-notch fa-spin'/>");
4190				$(this).find('i').tooltip();
4191				realtimeArray[graph_id] = true;
4192				setFilters();
4193				realtimeGrapher();
4194			}
4195		});
4196	});
4197}
4198
4199$.widget('custom.languageselect', $.ui.selectmenu, {
4200	_renderItem: function(ul, item) {
4201		var li = $('<li>');
4202		var wrapper = $('<div>', { text: item.label });
4203		if (item.disabled) {
4204			li.addClass( 'ui-state-disabled' );
4205		}
4206
4207		$('<span>', {
4208			style: item.element.attr('data-style') + ';float:right',
4209			'class': 'right fi fis ' + item.element.attr('data-class')
4210		}).appendTo(wrapper);
4211
4212		return li.append(wrapper).appendTo(ul);
4213	}
4214});
4215
4216// combobox example borrowed from jqueryui
4217$.widget('custom.dropcolor', {
4218	_create: function() {
4219		this.wrapper = $('<span style="display:inline-flex"><span class="ui-select-text"><div id="bgc" class="ui-icon color-icon" style="margin-left:2px;margin-right:3px;"></div></span></span>')
4220		.addClass('ui-selectmenu-button ui-selectmenu-button-closed ui-corner-all ui-button ui-widget')
4221		.insertAfter(this.element);
4222
4223		this.element.hide();
4224		this._createAutocomplete();
4225		this._createShowAllButton();
4226	},
4227
4228	_createAutocomplete: function() {
4229		var selected = this.element.children(':selected');
4230		var value  = selected.val() ? selected.text() : '';
4231		var regExp = /\(([^)]+)\)/;
4232		var hex    = regExp.exec(value);
4233
4234		if (hex != null) {
4235			this.wrapper.find('#bgc').css('background-color', '#'+hex[1]);
4236		}
4237		this.input = $('<input class="ui-autocomplete-input ui-state-default ui-selectmenu-text" style="background:transparent;border:0px;padding:0px;padding-left:24px;margin-left:-24px" value="'+value+'">')
4238		.appendTo(this.wrapper)
4239		.on('click', function() {
4240			$(this).autocomplete('search', '');
4241		})
4242		.autocomplete({
4243			delay: 0,
4244			minLength: 0,
4245			source: $.proxy(this, '_source'),
4246			select: $.proxy(this, '_select'),
4247			search: function() {
4248				$(this).data('ui-autocomplete').menu.bindings = $();
4249			},
4250			close: function() {
4251				$(this).data('ui-autocomplete').menu.bindings = $();
4252			},
4253			create: function() {
4254				$(this).data('ui-autocomplete')._renderItem = function(ul, item) {
4255					var regExp = /\(([^)]+)\)/;
4256					var hex   = regExp.exec(item.label);
4257					var mylabel = $($.parseHTML(item.label));
4258					var label = mylabel.text();
4259
4260					if (hex !== null) {
4261						color = hex[1];
4262						return $('<li>').attr('data-value', item.value).html('<div><span style="background-color:#'+color+';" class="ui-icon color-icon"></span>' + label + '</div>').appendTo(ul);
4263					} else {
4264						return $('<li>').attr('data-value', item.value).html('<div><span class="ui-icon color-icon"></span>' + label + '</div>').appendTo(ul);
4265					}
4266				}
4267
4268				$(this).data('ui-autocomplete')._resizeMenu = function () {
4269					var ul = this.menu.element;
4270					ul.outerWidth('220px');
4271				}
4272			}
4273		});
4274
4275		this._on(this.input, {
4276			autocompleteselect: function(event, ui) {
4277				ui.item.option.selected = true;
4278				this._trigger('select', event, {
4279					item: ui.item.option
4280				});
4281			},
4282
4283			autocompletechange: '_removeIfInvalid'
4284		});
4285	},
4286
4287	_select: function(event, ui) {
4288		var regExp = /\(([^)]+)\)/;
4289		var hex    = regExp.exec(ui.item.label);
4290		var id     = $(ui.item.option).attr('value');
4291
4292		if (hex !== null) {
4293			color = hex[1];
4294			this.wrapper.find('#bgc').css('background-color', '#'+color);
4295			this.wrapper.find('input').val(ui.item.value);
4296		} else {
4297			this.wrapper.find('#bgc').css('background-color', '');
4298			this.wrapper.find('input').val(ui.item.value);
4299		}
4300	},
4301
4302	_createShowAllButton: function() {
4303		var input = this.input;
4304		var wasOpen = false;
4305
4306		$('<span>')
4307		.attr('tabIndex', -1)
4308		.appendTo(this.wrapper)
4309		.addClass('ui-icon ui-icon-triangle-1-s ui-selectmenu-icon')
4310		.on('mousedown', function() {
4311			wasOpen = input.autocomplete('widget').is(':visible');
4312		})
4313		.on('click', function() {
4314			input.trigger('focus');
4315
4316			// Close if already visible
4317			if (wasOpen) {
4318				return;
4319			}
4320
4321			input.autocomplete('search', '');
4322		});
4323	},
4324
4325	_source: function(request, response) {
4326		var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), 'i');
4327		results = this.element.children('option').map(function() {
4328			var text = $(this).text();
4329			if (this.value && (!request.term || matcher.test(text))) {
4330				return {
4331					label: text,
4332					value: text,
4333					option: this
4334				};
4335			}
4336		});
4337
4338		response(results);
4339	},
4340
4341	_removeIfInvalid: function(event, ui) {
4342		// Selected an item, nothing to do
4343		if (ui.item) {
4344			return;
4345		}
4346
4347		// Search for a match (case-insensitive)
4348		var value = this.input.val();
4349		var valueLowerCase = value.toLowerCase();
4350		var valid = false;
4351
4352		this.element.children('option').each(function() {
4353			if ($(this).text().toLowerCase() === valueLowerCase) {
4354				this.selected = valid = true;
4355				return false;
4356			}
4357		});
4358
4359		// Found a match, nothing to do
4360		if (valid) {
4361			return;
4362		}
4363
4364		// Remove invalid value
4365		this.input.val('');
4366		this.element.val('');
4367		this._delay(function() {
4368			this.input.tooltip('close').attr('title', '');
4369		}, 2500 );
4370		this.input.autocomplete('instance').term = '';
4371	},
4372
4373	_destroy: function() {
4374		this.wrapper.remove();
4375		this.element.show();
4376	}
4377});
4378
4379function expandClipboardSection(section) {
4380	var isVisible = section.is(':visible');
4381	if (!isVisible) {
4382		section.slideDown('fast');
4383	}
4384
4385	var children = section.find('table').each(function (i) {
4386		expandClipboardSection($(this));
4387	});
4388}
4389
4390function copyToClipboard(containerId) {
4391	var clipboardDataId = containerId.replace('copyToClipboard','clipboardData');
4392	var clipboardData   = document.getElementById(clipboardDataId);
4393
4394	var messageWidth = $(window).width();
4395	if (messageWidth > 350) {
4396		messageWidth = 350;
4397	} else {
4398		messageWidth -= 50;
4399	}
4400
4401	if (clipboardData == null) {
4402		$('body').append('<div style="display:none;" id="clipboardMessage" title="'+clipboard+'">'+clipboardCopyFailed+'<br/><br/>'+clipboardID+': '+clipboardDataId+'</div>');
4403
4404		$('#clipboardMessage').dialog({
4405			resizable: false,
4406			draggable: false,
4407			height: 170,
4408			width: messageWidth,
4409			buttons: {
4410				Ok: function() {
4411					$(this).dialog('close');
4412					$('#clipboardMessage').remove();
4413				}
4414			}
4415		});
4416
4417		$('#clipboardMessage').dialog('open');
4418	} else if (!document.queryCommandSupported('copy')) {
4419		$('body').append('<div style="display:none;" id="clipboardMessage" title="'+clipboard+'">'+clipboardNotAvailable+'</div>');
4420
4421		$('#clipboardMessage').dialog({
4422			resizable: false,
4423			draggable: false,
4424			height: 120,
4425			width: messageWidth,
4426			buttons: {
4427				Ok: function() {
4428					$(this).dialog('close');
4429					$('#clipboardMessage').remove();
4430				}
4431			}
4432		});
4433
4434		$('#clipboardMessage').dialog('open');
4435	} else {
4436		var clipboardHeaderId = containerId.replace('copyToClipboard','clipboardHeader');
4437		var clipboardHeader   = document.getElementById(clipboardHeaderId);
4438
4439		if (clipboardData != null) {
4440			expandClipboardSection($(clipboardData));
4441		}
4442
4443		if (clipboardHeader != null) {
4444			expandClipboardSection($(clipboardHeader));
4445		}
4446
4447		// get Selection object from currently user selected text
4448		var selection = window.getSelection();
4449
4450		// unselect any user selected text (if any)
4451		selection.removeAllRanges();
4452
4453		// create new range object
4454		var range = document.createRange();
4455
4456		// set range to encompass desired element text
4457		if (clipboardHeader == null) {
4458			range.selectNode(clipboardData);
4459		} else {
4460			range.selectNode(clipboardHeader);
4461		}
4462
4463		// add range to Selection object to select it
4464		selection.addRange(range);
4465
4466		var success = document.execCommand('copy');
4467		selection.removeAllRanges();
4468
4469		var successMessage = (!success ? clipboardNotUpdated : clipboardUpdated);
4470
4471		$('body').append('<div style="display:none;" id="clipboardMessage" title="'+clipboard+'">'+successMessage+'</div>');
4472
4473		$('#clipboardMessage').dialog({
4474			resizable: false,
4475			draggable: false,
4476			height: 120,
4477			width: messageWidth,
4478			buttons: {
4479				Ok: function() {
4480					$(this).dialog('close');
4481					$('#clipboardMessage').remove();
4482				}
4483			}
4484		});
4485
4486		$('#clipboardMessage').dialog('open');
4487	}
4488}
4489
4490var snmp_password        = '';
4491var snmp_auth_protocol   = '';
4492var snmp_priv_protocol   = '';
4493var snmp_priv_passphrase = '';
4494var snmp_security_initialized = false;
4495
4496function storeSNMPSecurity() {
4497	if ($('#snmp_version').val() == '3') {
4498		if ($('#snmp_auth_protocol').val() != '[None]') {
4499			snmp_auth_protocol = $('#snmp_auth_protocol').val();
4500			snmp_password      = $('#snmp_password').val();
4501		} else {
4502			snmp_auth_protocol = '';
4503			snmp_password      = '';
4504		}
4505
4506		if ($('#snmp_priv_protocol').val() != '[None]') {
4507			snmp_priv_protocol   = $('#snmp_priv_protocol').val();
4508			snmp_priv_passphrase = $('#snmp_priv_passphrase').val();
4509		} else {
4510			snmp_priv_protocol   = '';
4511			snmp_priv_passphrase = '';
4512		}
4513	} else {
4514		$('#snmp_security_level').val(defaultSNMPSecurityLevel);
4515	}
4516}
4517
4518function setSNMPSecurity() {
4519	if ($('#snmp_version').val() == '3') {
4520		if (!snmp_security_initialized) {
4521			if ($('#snmp_auth_protocol').val() == '[None]') {
4522				$('#snmp_security_level').val('noAuthNoPriv');
4523			} else if ($('#snmp_priv_protocol').val() == '[None]') {
4524				$('#snmp_security_level').val('authNoPriv');
4525			} else {
4526				$('#snmp_security_level').val('authPriv');
4527			}
4528
4529			var selectmenu = ($('#snmp_security_level').selectmenu('instance') !== undefined);
4530			if (selectmenu) {
4531				$('#snmp_security_level').selectmenu('refresh');
4532			}
4533
4534			$('#snmp_password').keyup(function() {
4535				checkSNMPPassphrase('auth');
4536			});
4537
4538			$('#snmp_password_confirm').keyup(function() {
4539				checkSNMPPassphraseConfirm('auth');
4540			});
4541
4542			$('#snmp_priv_passphrase').keyup(function() {
4543				checkSNMPPassphrase('priv');
4544			});
4545
4546			$('#snmp_priv_passphrase_confirm').keyup(function() {
4547				checkSNMPPassphraseConfirm('priv');
4548			});
4549		}
4550
4551		snmp_security_initialized = true;
4552	}
4553}
4554
4555function setSNMP() {
4556	var snmp_version = $('#snmp_version').val();
4557
4558	storeSNMPSecurity();
4559	setSNMPSecurity();
4560
4561	switch(snmp_version) {
4562		case '0': // Not in Use
4563			$('#row_snmp_username').hide();
4564			$('#row_snmp_password').hide();
4565			$('#row_snmp_community').hide();
4566			$('#row_snmp_security_level').hide();
4567			$('#row_snmp_auth_password').hide();
4568			$('#row_snmp_auth_protocol').hide();
4569			$('#row_snmp_priv_passphrase').hide();
4570			$('#row_snmp_priv_protocol').hide();
4571			$('#row_snmp_engine_id').hide();
4572			$('#row_snmp_context').hide();
4573			$('#row_snmp_port').hide();
4574			$('#row_snmp_timeout').hide();
4575			$('#row_max_oids').hide();
4576			$('#row_bulk_walk_size').hide();
4577
4578			if ($('#row_snmp_engine_id')) {
4579				$('#row_snmp_engine_id').hide();
4580			}
4581
4582			if ($('#row_snmp_retries')) {
4583				$('#row_snmp_retries').hide();
4584			}
4585
4586			break;
4587		case '1': // SNMP v1
4588		case '2': // SNMP v2c
4589			$('#row_snmp_username').hide();
4590			$('#row_snmp_password').hide();
4591			$('#row_snmp_community').show();
4592			$('#row_snmp_security_level').hide();
4593			$('#row_snmp_auth_password').hide();
4594			$('#row_snmp_auth_protocol').hide();
4595			$('#row_snmp_priv_passphrase').hide();
4596			$('#row_snmp_priv_protocol').hide();
4597			$('#row_snmp_engine_id').hide();
4598			$('#row_snmp_context').hide();
4599			$('#row_snmp_port').show();
4600			$('#row_snmp_timeout').show();
4601			$('#row_max_oids').show();
4602			$('#row_bulk_walk_size').show();
4603
4604			if ($('#row_snmp_engine_id')) {
4605				$('#row_snmp_engine_id').hide();
4606			}
4607
4608			if ($('#row_snmp_retries')) {
4609				$('#row_snmp_retries').show();
4610			}
4611
4612			break;
4613		case '3': // SNMP v3
4614			$('#row_snmp_username').show();
4615			$('#row_snmp_password').show();
4616			$('#row_snmp_community').hide();
4617			$('#row_snmp_security_level').show();
4618			$('#row_snmp_auth_password').show();
4619			$('#row_snmp_auth_protocol').show();
4620			$('#row_snmp_priv_passphrase').show();
4621			$('#row_snmp_priv_protocol').show();
4622			$('#row_snmp_engine_id').show();
4623			$('#row_snmp_context').show();
4624			$('#row_snmp_port').show();
4625			$('#row_snmp_timeout').show();
4626			$('#row_max_oids').show();
4627			$('#row_bulk_walk_size').show();
4628
4629			if ($('#row_snmp_engine_id')) {
4630				$('#row_snmp_engine_id').show();
4631			}
4632
4633			if ($('#row_snmp_retries')) {
4634				$('#row_snmp_retries').show();
4635			}
4636
4637			if ($('#snmp_security_level').val() == 'noAuthNoPriv') {
4638				$('#snmp_auth_protocol option[value*="None"').prop('disabled', false);
4639				$('#snmp_priv_protocol option[value*="None"').prop('disabled', false);
4640
4641				if ($('#snmp_auth_protocol').val() != '[None]') {
4642					snmp_auth_protocol   = $('#snmp_auth_protocol').val();
4643					snmp_password        = $('#snmp_password').val();
4644				}
4645
4646				if ($('#snmp_priv_protocol').val() != '[None]') {
4647					snmp_priv_protocol   = $('#snmp_priv_protocol').val();
4648					snmp_priv_passphrase = $('#snmp_priv_passphrase').val();
4649				}
4650
4651				$('#snmp_auth_protocol').val('[None]');
4652				$('#snmp_priv_protocol').val('[None]');
4653				$('#row_snmp_auth_protocol').hide();
4654				$('#row_snmp_priv_protocol').hide();
4655				$('#row_snmp_password').hide();
4656				$('#row_snmp_priv_passphrase').hide();
4657			} else if ($('#snmp_security_level').val() == 'authNoPriv') {
4658				$('#snmp_auth_protocol option[value*="None"').prop('disabled', false);
4659				$('#snmp_priv_protocol option[value*="None"').prop('disabled', false);
4660
4661				if ($('#snmp_priv_protocol').val() != '[None]') {
4662					snmp_priv_protocol   = $('#snmp_priv_protocol').val();
4663					snmp_priv_passphrase = $('#snmp_priv_passphrase').val();
4664				}
4665
4666				if (snmp_auth_protocol != '[None]' && snmp_auth_protocol != '' && $('#snmp_auth_protocol').val() == '[None]') {
4667					$('#snmp_auth_protocol').val(snmp_auth_protocol);
4668					$('#snmp_password').val(snmp_password);
4669					$('#snmp_password_confirm').val(snmp_password);
4670				} else if ($('#snmp_auth_protocol').val() == '[None]' || $('#snmp_auth_protocol').val() == '') {
4671					if (defaultSNMPAuthProtocol == '' || defaultSNMPAuthProtocol == '[None]') {
4672						$('#snmp_auth_protocol').val('MD5');
4673					} else {
4674						$('#snmp_auth_protocol').val(defaultSNMPAuthProtocol);
4675					}
4676				}
4677
4678				$('#snmp_priv_protocol').val('[None]');
4679				$('#row_snmp_priv_protocol').hide();
4680				$('#row_snmp_priv_passphrase').hide();
4681
4682				$('#snmp_auth_protocol option[value*="None"').prop('disabled', true);
4683				$('#snmp_priv_protocol option[value*="None"').prop('disabled', false);
4684				checkSNMPPassphrase('auth');
4685			} else {
4686				$('#snmp_auth_protocol option[value*="None"').prop('disabled', false);
4687				$('#snmp_priv_protocol option[value*="None"').prop('disabled', false);
4688
4689				if (snmp_auth_protocol != '' && $('#snmp_auth_protocol').val() == '[None]') {
4690					$('#snmp_auth_protocol').val(snmp_auth_protocol);
4691					$('#snmp_password').val(snmp_password);
4692					$('#snmp_password_confirm').val(snmp_password);
4693				} else if ($('#snmp_auth_protocol').val() == '[None]' || $('#snmp_auth_protocol').val() == '') {
4694					if (defaultSNMPAuthProtocol == '' || defaultSNMPAuthProtocol == '[None]') {
4695						$('#snmp_auth_protocol').val('MD5');
4696					} else {
4697						$('#snmp_auth_protocol').val(defaultSNMPAuthProtocol);
4698					}
4699				}
4700
4701				if (snmp_priv_protocol != '' && $('#snmp_priv_protocol').val() == '[None]') {
4702					$('#snmp_priv_protocol').val(snmp_priv_protocol);
4703					$('#snmp_priv_passphrase').val(snmp_priv_passphrase);
4704					$('#snmp_priv_passphrase_confirm').val(snmp_priv_passphrase);
4705				} else if ($('#snmp_priv_protocol').val() == '[None]' || $('#snmp_priv_protocol').val() == '') {
4706					if (defaultSNMPPrivProtocol == '' || defaultSNMPPrivProtocol == '[None]') {
4707						$('#snmp_priv_protocol').val('DES');
4708					} else {
4709						$('#snmp_priv_protocol').val(defaultSNMPPrivProtocol);
4710					}
4711				}
4712
4713				$('#snmp_auth_protocol option[value*="None"').prop('disabled', true);
4714				$('#snmp_priv_protocol option[value*="None"').prop('disabled', true);
4715				checkSNMPPassphrase('auth');
4716				checkSNMPPassphrase('priv');
4717			}
4718
4719			if ($('#snmp_auth_protocol').val() == '[None]') {
4720				$('#row_snmp_password').hide();
4721				$('#snmp_password').val('');
4722				$('#snmp_password_confirm').val('');
4723			}
4724
4725			if ($('#snmp_priv_protocol').val() == '[None]') {
4726				$('#row_snmp_priv_passphrase').hide();
4727				$('#snmp_priv_passphrase').val('');
4728				$('#snmp_priv_passphrase_confirm').val('');
4729			}
4730
4731			selectmenu = ($('#snmp_security_level').selectmenu('instance') !== undefined);
4732			if (selectmenu) {
4733				$('#snmp_security_level').selectmenu('refresh');
4734				$('#snmp_auth_protocol').selectmenu('refresh');
4735				$('#snmp_priv_protocol').selectmenu('refresh');
4736			}
4737
4738			break;
4739	}
4740}
4741
4742function checkSNMPPassphrase(type) {
4743	var minChars = 8;
4744
4745	if (type == 'priv') {
4746		var pass = '#snmp_priv_passphrase';
4747		var conf = '#snmp_priv_passphrase_confirm';
4748		var span = 'priv';
4749	} else {
4750		var pass = '#snmp_password';
4751		var conf = '#snmp_password_confirm';
4752		var span = 'auth';
4753	}
4754
4755	if ($(pass).val().length == 0) {
4756		$('#'+span).remove();
4757		$('#'+span+'conf').remove();
4758	} else if ($(pass).val().length < minChars) {
4759		$('#'+span).remove();
4760		$(pass).after('<span id="'+span+'"><i class="badpassword fa fa-times"></i><span style="padding-left:4px;">'+passwordTooShort+'<span></span>');
4761		checkSNMPPassphraseConfirm(type);
4762	} else {
4763		$('#'+span).remove();
4764		$(pass).after('<span id="'+span+'"><i class="goodpassword fa fa-check"></i><span style="padding-left:4px;">'+passwordPass+'</span></span>');
4765		checkSNMPPassphraseConfirm(type);
4766	}
4767}
4768
4769function checkSNMPPassphraseConfirm(type) {
4770	var minChars = 8;
4771
4772	if (type == 'priv') {
4773		var pass     = '#snmp_priv_passphrase';
4774		var conf     = '#snmp_priv_passphrase_confirm';
4775		var span     = 'priv';
4776		var spanconf = 'privconf';
4777	} else {
4778		var pass     = '#snmp_password';
4779		var conf     = '#snmp_password_confirm';
4780		var span     = 'auth';
4781		var spanconf = 'authconf';
4782	}
4783
4784	if ($(conf).val().length < minChars) {
4785		var passphrase = $(pass).val();
4786
4787		if (passphrase.indexOf($(conf).val()) == 0) {
4788			$('#'+spanconf).remove();
4789			$(conf).after('<span id="'+spanconf+'"><i class="badpassword fa fa-times"></i><span style="padding-left:4px;">'+passwordMatchTooShort+'<span></span>');
4790		} else {
4791			$('#'+spanconf).remove();
4792			$(conf).after('<span id="'+spanconf+'"><i class="badpassword fa fa-times"></i><span style="padding-left:4px;">'+passwordNotMatchTooShort+'<span></span>');
4793		}
4794	} else {
4795		if ($(pass).val() != $(conf).val()) {
4796			$('#'+spanconf).remove();
4797			$(conf).after('<span id="'+spanconf+'"><i class="badpassword fa fa-times"></i><span style="padding-left:4px;">'+passwordNotMatch+'</span></span>');
4798		} else {
4799			$('#'+span).remove();
4800			$('#'+spanconf).remove();
4801			$(pass).after('<span id="'+spanconf+'"><i class="goodpassword fa fa-check"></i><span style="padding-left:4px;">'+passwordMatch+'</span></span>');
4802		}
4803	}
4804}
4805

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.