Project

General

Profile

Download (23.4 KB) Statistics
| Branch: | Tag: | Revision:
1 ac24dc24 Renato Botelho
/*
2
 * pfSenseHelpers.js
3
 *
4
 * part of pfSense (https://www.pfsense.org)
5 81299b5c Renato Botelho
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
6 ac24dc24 Renato Botelho
 * All rights reserved.
7
 *
8 b12ea3fb Renato Botelho
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11 ac24dc24 Renato Botelho
 *
12 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
13 ac24dc24 Renato Botelho
 *
14 b12ea3fb Renato Botelho
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19 08ec2d99 Stephen Beaver
 */
20
21 3ece7116 Stephen Beaver
// These helper functions are used on many/most UI pages to hide/show/disable/enable form elements where required
22
23 c744b0de Steve Beaver
// Cause the input to be displayed as a required field by adding the element-required class to the label
24
function setRequired(id, req) {
25
	if (req)
26
		$('#' + id).parent().parent('div').find('span:first').addClass('element-required');
27
	else
28
		$('#' + id).parent().parent('div').find('span:first').removeClass('element-required');
29
}
30
31 3ece7116 Stephen Beaver
// Hides the <div> in which the specified input element lives so that the input, its label and help text are hidden
32
function hideInput(id, hide) {
33 726fdb61 Phil Davis
	if (hide)
34 96c18fe4 Stephen Beaver
		$('#' + id).parent().parent('div').addClass('hidden');
35
	else
36
		$('#' + id).parent().parent('div').removeClass('hidden');
37 3ece7116 Stephen Beaver
}
38
39
// Hides the <div> in which the specified group input element lives so that the input,
40
// its label and help text are hidden
41
function hideGroupInput(id, hide) {
42 726fdb61 Phil Davis
	if (hide)
43 96c18fe4 Stephen Beaver
		$('#' + id).parent('div').addClass('hidden');
44
	else
45
		$('#' + id).parent('div').removeClass('hidden');
46 3ece7116 Stephen Beaver
}
47
48
// Hides the <div> in which the specified checkbox lives so that the checkbox, its label and help text are hidden
49
function hideCheckbox(id, hide) {
50 726fdb61 Phil Davis
	if (hide)
51 96c18fe4 Stephen Beaver
		$('#' + id).parent().parent().parent('div').addClass('hidden');
52
	else
53
		$('#' + id).parent().parent().parent('div').removeClass('hidden');
54 3ece7116 Stephen Beaver
}
55
56
// Disables the specified input element
57
function disableInput(id, disable) {
58 96c18fe4 Stephen Beaver
	$('#' + id).prop("disabled", disable);
59 3ece7116 Stephen Beaver
}
60
61
// Hides all elements of the specified class. This will usually be a section
62
function hideClass(s_class, hide) {
63 726fdb61 Phil Davis
	if (hide)
64 96c18fe4 Stephen Beaver
		$('.' + s_class).hide();
65
	else
66
		$('.' + s_class).show();
67 3ece7116 Stephen Beaver
}
68
69 96c18fe4 Stephen Beaver
function hideSelect(id, hide) {
70 726fdb61 Phil Davis
	if (hide)
71 96c18fe4 Stephen Beaver
		$('#' + id).parent('div').parent('div').addClass('hidden');
72
	else
73
		$('#' + id).parent('div').parent('div').removeClass('hidden');
74
}
75
76
function hideMultiCheckbox(id, hide) {
77 726fdb61 Phil Davis
	if (hide)
78 5e7a1d46 Stephen Beaver
		$("[name=" + id + "]").parent().addClass('hidden');
79 96c18fe4 Stephen Beaver
	else
80 5e7a1d46 Stephen Beaver
		$("[name=" + id + "]").parent().removeClass('hidden');
81 96c18fe4 Stephen Beaver
}
82
83 850c3d8b Steve Beaver
// Hides the <div> in which the specified IP address element lives so that the input, any mask selector, its label and help text are hidden
84 96c18fe4 Stephen Beaver
function hideIpAddress(id, hide) {
85 726fdb61 Phil Davis
	if (hide)
86 96c18fe4 Stephen Beaver
		$('#' + id).parent().parent().parent('div').addClass('hidden');
87
	else
88
		$('#' + id).parent().parent().parent('div').removeClass('hidden');
89
}
90
91
// Hides all elements of the specified class belonging to a multiselect.
92
function hideMultiClass(s_class, hide) {
93 726fdb61 Phil Davis
	if (hide)
94 96c18fe4 Stephen Beaver
		$('.' + s_class).parent().parent().hide();
95
	else
96
		$('.' + s_class).parent().parent().show();
97
}
98
99
// Hides div whose label contains the specified text. (Good for StaticText)
100
function hideLabel(text, hide) {
101
102
	var element = $('label:contains(' + text + ')');
103 3ece7116 Stephen Beaver
104 726fdb61 Phil Davis
	if (hide)
105 96c18fe4 Stephen Beaver
		element.parent('div').addClass('hidden');
106
	else
107
		element.parent('div').removeClass('hidden');
108 08ec2d99 Stephen Beaver
}
109
110 25a96ffb Stephen Beaver
// Hides the '/' and the subnet mask of an Ip_Address/subnet_mask group
111
function hideMask(name, hide) {
112 9d3e8723 Phil Davis
	if (hide) {
113 e1caefc7 Stephen Beaver
		$('[id^=' + name + ']').hide();
114
		$('[id^=' + name + ']').prev('span').hide();
115 01142f51 Phil Davis
		$('[id^=' + name + ']').parent('div').removeClass('input-group');
116 e1caefc7 Stephen Beaver
	} else {
117
		$('[id^=' + name + ']').show();
118
		$('[id^=' + name + ']').prev('span').show();
119 01142f51 Phil Davis
		$('[id^=' + name + ']').parent('div').addClass('input-group');
120 e1caefc7 Stephen Beaver
	}
121 25a96ffb Stephen Beaver
}
122
123 678c6a56 Steve Beaver
// Set the help text for a given input
124
function setHelpText(id, text) {
125
	$('#' + id).parent().parent('div').find('span:nth-child(2)').html(text);
126
}
127
128 39609bf9 Stephen Beaver
// Toggle table row checkboxes and background colors on the pages that use sortable tables:
129 65a0e193 Stephen Beaver
//	/usr/local/www/firewall_nat.php
130
//	/usr/local/www/firewall_nat_1to1.php
131
//	/usr/local/www/firewall_nat_out.php
132
//	/usr/local/www/firewall_rules.php
133
//	/usr/local/www/vpn_ipsec.php
134 1b6b7fc4 Stephen Beaver
// Striping of the tables is handled here, NOT with the Bootstrap table-striped class because it would
135 65a0e193 Stephen Beaver
// get confused when rows are sorted or deleted.
136
137
function fr_toggle(id, prefix) {
138
	if (!prefix)
139
		prefix = 'fr';
140
141
	var checkbox = document.getElementById(prefix + 'c' + id);
142
	checkbox.checked = !checkbox.checked;
143
	fr_bgcolor(id, prefix);
144
}
145
146 b5ef3ee9 Jared Dillard
// Change background color of selected row based on state of checkbox
147 65a0e193 Stephen Beaver
function fr_bgcolor(id, prefix) {
148
	if (!prefix)
149
		prefix = 'fr';
150
151
	var row = $('#' + prefix + id);
152
153
	if ($('#' + prefix + 'c' + id).prop('checked') ) {
154 b5ef3ee9 Jared Dillard
		row.addClass('active');
155 65a0e193 Stephen Beaver
	} else {
156 b5ef3ee9 Jared Dillard
		row.removeClass('active');
157 65a0e193 Stephen Beaver
	}
158
}
159
160 44fad9cc Stephen Beaver
// The following functions are used by Form_Groups assigned a class of "repeatable" and provide the ability
161
// to add/delete rows of sequentially numbered elements, their labels and their help text
162 08ec2d99 Stephen Beaver
// See firewall_aliases_edit.php for an example
163
164 726fdb61 Phil Davis
// NOTE: retainhelp is a global var that when defined prevents any help text from being deleted as lines are inserted.
165 44fad9cc Stephen Beaver
// IOW it causes every row to have help text, not just the last row
166
167 08ec2d99 Stephen Beaver
function setMasks() {
168
	// Find all ipaddress masks and make dynamic based on address family of input
169
	$('span.pfIpMask + select').each(function (idx, select){
170
		var input = $(select).prevAll('input[type=text]');
171
172
		input.on('change', function(e){
173
			var isV6 = (input.val().indexOf(':') != -1), min = 0, max = 128;
174
			if (!isV6)
175
				max = 32;
176
177
			if (input.val() == "")
178
				return;
179
180
			while (select.options.length > max)
181
				select.remove(0);
182
183 726fdb61 Phil Davis
			if (select.options.length < max) {
184 08ec2d99 Stephen Beaver
				for (var i=select.options.length; i<=max; i++)
185
					select.options.add(new Option(i, i), 0);
186
			}
187
		});
188
189
		// Fire immediately
190
		input.change();
191
	});
192
}
193
194
// Complicated function to move all help text associated with this input id to the same id
195
// on the row above. That way if you delete the last row, you don't lose the help
196
function moveHelpText(id) {
197 4d4782fc Stephen Beaver
198
	$('#' + id).parent('div').parent('div').find('input, select, checkbox, button').each(function() {	 // For each <span></span>
199 08ec2d99 Stephen Beaver
		var fromId = this.id;
200
		var toId = decrStringInt(fromId);
201
		var helpSpan;
202
203 4d4782fc Stephen Beaver
204 0ed3b159 Stephen Beaver
		if (!$(this).hasClass('pfIpMask') && !$(this).hasClass('btn')) {
205 726fdb61 Phil Davis
			if ($('#' + decrStringInt(fromId)).parent('div').hasClass('input-group')) {
206 39609bf9 Stephen Beaver
				helpSpan = $('#' + fromId).parent('div').parent('div').find('span:last').clone();
207
			} else {
208
				helpSpan = $('#' + fromId).parent('div').find('span:last').clone();
209
			}
210 4d4782fc Stephen Beaver
211 726fdb61 Phil Davis
			if ($(helpSpan).hasClass('help-block')) {
212
				if ($('#' + decrStringInt(fromId)).parent('div').hasClass('input-group')) {
213 08ec2d99 Stephen Beaver
					$('#' + decrStringInt(fromId)).parent('div').after(helpSpan);
214 726fdb61 Phil Davis
				} else {
215 08ec2d99 Stephen Beaver
					$('#' + decrStringInt(fromId)).after(helpSpan);
216 39609bf9 Stephen Beaver
				}
217 08ec2d99 Stephen Beaver
			}
218
		}
219
	});
220
}
221
222 22dbacd0 PiBa-NL
// Increment the number at the end of the string
223
function getStringInt( str )	{
224
  var data = str.match(/(\D*)(\d+)(\D*)/), newStr = "";
225
  return Number( data[ 2 ] );
226
}
227
228 08ec2d99 Stephen Beaver
// Increment the number at the end of the string
229
function bumpStringInt( str )	{
230
  var data = str.match(/(\D*)(\d+)(\D*)/), newStr = "";
231
232 726fdb61 Phil Davis
  if (data)
233 08ec2d99 Stephen Beaver
	newStr = data[ 1 ] + ( Number( data[ 2 ] ) + 1 ) + data[ 3 ];
234
235
  return newStr || str;
236
}
237
238
// Decrement the number at the end of the string
239
function decrStringInt( str )	{
240
  var data = str.match(/(\D*)(\d+)(\D*)/), newStr = "";
241
242 726fdb61 Phil Davis
  if (data)
243 08ec2d99 Stephen Beaver
	newStr = data[ 1 ] + ( Number( data[ 2 ] ) - 1 ) + data[ 3 ];
244
245
  return newStr || str;
246
}
247
248
// Called after a delete so that there are no gaps in the numbering. Most of the time the config system doesn't care about
249
// gaps, but I do :)
250
function renumber() {
251
	var idx = 0;
252
253
	$('.repeatable').each(function() {
254
255
		$(this).find('input').each(function() {
256
			$(this).prop("id", this.id.replace(/\d+$/, "") + idx);
257
			$(this).prop("name", this.name.replace(/\d+$/, "") + idx);
258
		});
259
260
		$(this).find('select').each(function() {
261
			$(this).prop("id", this.id.replace(/\d+$/, "") + idx);
262
			$(this).prop("name", this.name.replace(/\d+$/, "") + idx);
263
		});
264
265 4d4782fc Stephen Beaver
		$(this).find('button').each(function() {
266
			$(this).prop("id", this.id.replace(/\d+$/, "") + idx);
267
			$(this).prop("name", this.name.replace(/\d+$/, "") + idx);
268
		});
269
270 43dc3830 Stephen Beaver
//		$(this).find('label').attr('for', $(this).find('label').attr('for').replace(/\d+$/, "") + idx);
271 08ec2d99 Stephen Beaver
272
		idx++;
273
	});
274
}
275
276 88afaf7d Stephen Beaver
function delete_row(rowDelBtn) {
277 576437f5 Stephen Beaver
	var rowLabel;
278 88afaf7d Stephen Beaver
279
	// If we are deleting row zero, we need to save/restore the label
280 3b1c0951 Steve Beaver
	if ( (rowDelBtn == "deleterow0") && ((typeof retainhelp) == "undefined")) {
281 8627b174 Stephen Beaver
		rowLabel = $('#' + rowDelBtn).parent('div').parent('div').find('label').text();
282 88afaf7d Stephen Beaver
	}
283
284
	$('#' + rowDelBtn).parent('div').parent('div').remove();
285 4d4782fc Stephen Beaver
286 08ec2d99 Stephen Beaver
	renumber();
287 0bc61baa Stephen Beaver
	checkLastRow();
288 88afaf7d Stephen Beaver
289
	if (rowDelBtn == "deleterow0") {
290 8627b174 Stephen Beaver
		$('#' + rowDelBtn).parent('div').parent('div').find('label').text(rowLabel);
291 88afaf7d Stephen Beaver
	}
292 0bc61baa Stephen Beaver
}
293
294
function checkLastRow() {
295 1059fc88 Steve Beaver
	if (($('.repeatable').length <= 1) && (! $('#deleterow0').hasClass("nowarn"))) {
296 0bc61baa Stephen Beaver
		$('#deleterow0').hide();
297
	} else {
298
		$('[id^=deleterow]').show();
299
	}
300 08ec2d99 Stephen Beaver
}
301
302 22dbacd0 PiBa-NL
function bump_input_id(newGroup) {
303 08ec2d99 Stephen Beaver
	$(newGroup).find('input').each(function() {
304
		$(this).prop("id", bumpStringInt(this.id));
305
		$(this).prop("name", bumpStringInt(this.name));
306 726fdb61 Phil Davis
		if (!$(this).is('[id^=delete]'))
307 08ec2d99 Stephen Beaver
			$(this).val('');
308
	});
309
310 5ed4eb30 Stephen Beaver
	// Increment the suffix number for the deleterow button element in the new group
311
	$(newGroup).find('[id^=deleterow]').each(function() {
312 dbe64b71 Phil Davis
		$(this).prop("id", bumpStringInt(this.id));
313
		$(this).prop("name", bumpStringInt(this.name));
314
	});
315
316 08ec2d99 Stephen Beaver
	// Do the same for selectors
317
	$(newGroup).find('select').each(function() {
318
		$(this).prop("id", bumpStringInt(this.id));
319
		$(this).prop("name", bumpStringInt(this.name));
320
		// If this selector lists mask bits, we need it to be reset to all 128 options
321
		// and no items selected, so that automatic v4/v6 selection still works
322 726fdb61 Phil Davis
		if ($(this).is('[id^=address_subnet]')) {
323 08ec2d99 Stephen Beaver
			$(this).empty();
324 726fdb61 Phil Davis
			for (idx=128; idx>0; idx--) {
325 08ec2d99 Stephen Beaver
				$(this).append($('<option>', {
326
					value: idx,
327
					text: idx
328
				}));
329
			}
330
		}
331
	});
332 22dbacd0 PiBa-NL
}
333
function add_row() {
334
	// Find the last repeatable group
335
	var lastRepeatableGroup = $('.repeatable:last');
336
337
	// If the number of repeats exceeds the maximum, do not add another clone
338
	if ($('.repeatable').length >= lastRepeatableGroup.attr('max_repeats')) {
339
		// Alert user if alert message is specified
340
		if (typeof lastRepeatableGroup.attr('max_repeats_alert') !== 'undefined') {
341
			alert(lastRepeatableGroup.attr('max_repeats_alert'));
342
		}
343
		return;
344
	}
345
346
	// Clone it
347
	var newGroup = lastRepeatableGroup.clone();
348
349
	// Increment the suffix number for each input element in the new group
350
	bump_input_id(newGroup);
351 08ec2d99 Stephen Beaver
352
	// And for "for" tags
353 43dc3830 Stephen Beaver
//	$(newGroup).find('label').attr('for', bumpStringInt($(newGroup).find('label').attr('for')));
354
355 d38d215d Stephen Beaver
	$(newGroup).find('label:first').text(""); // Clear the label. We only want it on the very first row
356 08ec2d99 Stephen Beaver
357
	// Insert the updated/cloned row
358
	$(lastRepeatableGroup).after(newGroup);
359
360
	// Delete any help text from the group we have cloned
361
	$(lastRepeatableGroup).find('.help-block').each(function() {
362 726fdb61 Phil Davis
		if ((typeof retainhelp) == "undefined")
363 08ec2d99 Stephen Beaver
			$(this).remove();
364
	});
365
366
	setMasks();
367
368 0bc61baa Stephen Beaver
	checkLastRow();
369
370 c24178cd Stephen Beaver
	// Autocomplete
371 b6bd3103 Stephen Beaver
	if ( typeof addressarray !== 'undefined') {
372
		$('[id^=address]').each(function() {
373 726fdb61 Phil Davis
			if (this.id.substring(0, 8) != "address_") {
374 b6bd3103 Stephen Beaver
				$(this).autocomplete({
375
					source: addressarray
376
				});
377
			}
378
		});
379
	}
380 9f6a9f24 Stephen Beaver
381 316c5503 Stephen Beaver
	// Now that we are no longer cloning the event handlers, we need to remove and re-add after a new row
382 9f6a9f24 Stephen Beaver
	// has been added to the table
383
	$('[id^=delete]').unbind();
384
	$('[id^=delete]').click(function(event) {
385 726fdb61 Phil Davis
		if ($('.repeatable').length > 1) {
386
			if ((typeof retainhelp) == "undefined")
387 ea02e3cf Steve Beaver
				moveHelpText($(this).attr("id"));
388 9f6a9f24 Stephen Beaver
389 ea02e3cf Steve Beaver
			delete_row($(this).attr("id"));
390 1059fc88 Steve Beaver
		} else if ($(this).hasClass("nowarn")) {
391
			clearRow0();
392 726fdb61 Phil Davis
		} else {
393 af3cc7d6 NOYB
			alert('The last row may not be deleted.');
394 726fdb61 Phil Davis
		}
395 9f6a9f24 Stephen Beaver
	});
396 08ec2d99 Stephen Beaver
}
397
398
// These are action buttons, not submit buttons
399
$('[id^=addrow]').prop('type','button');
400
$('[id^=delete]').prop('type','button');
401
402
// on click . .
403
$('[id^=addrow]').click(function() {
404
	add_row();
405
});
406
407
$('[id^=delete]').click(function(event) {
408 726fdb61 Phil Davis
	if ($('.repeatable').length > 1) {
409
		if ((typeof retainhelp) == "undefined")
410 fab3c245 Steve Beaver
			moveHelpText($(this).attr("id"));
411 08ec2d99 Stephen Beaver
412 fab3c245 Steve Beaver
		delete_row($(this).attr("id"));
413 1059fc88 Steve Beaver
		} else if ($(this).hasClass("nowarn")) {
414
			clearRow0();
415
		} else {
416
			alert('The last row may not be deleted.');
417
		}
418 df4957e4 Stephen Beaver
});
419
420 1059fc88 Steve Beaver
function clearRow0() {
421
	$('#deleterow0').parent('div').parent().find('input[type=text]').val('');
422
	$('#deleterow0').parent('div').parent().find('input[type=checkbox]:checked').removeAttr('checked');
423
}
424
425 85d29bf5 Stephen Beaver
// "More information" handlers --------------------------------------------------------------------
426 0149ef4d Stephen Beaver
427
// If there is an infoblock, automatically add an info icon that toggles its display
428 c9679d8c Stephen Beaver
429 c95dabdd Stephen Beaver
var sfx = 0;
430 85d29bf5 Stephen Beaver
431 c95dabdd Stephen Beaver
$('.infoblock').each(function() {
432 cca28e34 Phil Davis
	// If the block has the class "blockopen" it is initially open
433 c95dabdd Stephen Beaver
	if (! $(this).hasClass("blockopen")) {
434 85d29bf5 Stephen Beaver
		$(this).hide();
435 c95dabdd Stephen Beaver
	} else {
436
		$(this).removeClass("blockopen");
437 85d29bf5 Stephen Beaver
	}
438
439 cca28e34 Phil Davis
	// Add the "i" icon before the infoblock, incrementing the icon id for each block (in case there are multiple infoblocks on a page)
440 c95dabdd Stephen Beaver
	$(this).before('<i class="fa fa-info-circle icon-pointer" style="color: #337AB7; font-size:20px; margin-left: 10px; margin-bottom: 10px;" id="showinfo' + sfx.toString() + '" title="More information"></i>');
441
	$(this).removeClass("infoblock");
442
	$(this).addClass("infoblock" + sfx.toString());
443
	sfx++;
444 85d29bf5 Stephen Beaver
});
445 0149ef4d Stephen Beaver
446 5a957b9a Phil Davis
// Show the help on clicking the info icon
447 85d29bf5 Stephen Beaver
$('[id^="showinfo"]').click(function() {
448
	var id = $(this).attr("id");
449 c95dabdd Stephen Beaver
	$('.' + "infoblock" + id.substr(8)).toggle();
450 f8619b46 Stephen Beaver
	document.getSelection().removeAllRanges();		// Ensure the text is un-selected (Chrome browser quirk)
451 82afb104 Stephen Beaver
});
452 85d29bf5 Stephen Beaver
// ------------------------------------------------------------------------------------------------
453 82afb104 Stephen Beaver
454 1c72e99f Stephen Beaver
// Put a dummy row into any empty table to keep IE happy
455 666be0be jim-p
// Commented out due to https://redmine.pfsense.org/issues/7504
456
//$('tbody').each(function(){
457
//	$(this).html($.trim($(this).html()))
458
//});
459 82afb104 Stephen Beaver
460 e82778da Stephen Beaver
$('tbody:empty').html("<tr><td></td></tr>");
461 d5d5836c Stephen Beaver
462 4a457d8d Stephen Beaver
// Hide configuration button for panels without configuration
463
$('.container .panel-heading a.config').each(function (idx, el){
464
	var config = $(el).parents('.panel').children('.panel-footer');
465
	if (config.length == 1)
466
		$(el).removeClass('hidden');
467
});
468 d5d5836c Stephen Beaver
469 4a457d8d Stephen Beaver
// Initial state & toggle icons of collapsed panel
470
$('.container .panel-heading a[data-toggle="collapse"]').each(function (idx, el){
471
	var body = $(el).parents('.panel').children('.panel-body')
472
	var isOpen = body.hasClass('in');
473 d5d5836c Stephen Beaver
474 4a457d8d Stephen Beaver
	$(el).children('i').toggleClass('fa-plus-circle', !isOpen);
475
	$(el).children('i').toggleClass('fa-minus-circle', isOpen);
476 d5d5836c Stephen Beaver
477 4a457d8d Stephen Beaver
	body.on('shown.bs.collapse', function(){
478
		$(el).children('i').toggleClass('fa-minus-circle', true);
479
		$(el).children('i').toggleClass('fa-plus-circle', false);
480
	});
481 d5d5836c Stephen Beaver
482 4a457d8d Stephen Beaver
	body.on('hidden.bs.collapse', function(){
483
		$(el).children('i').toggleClass('fa-minus-circle', false);
484
		$(el).children('i').toggleClass('fa-plus-circle', true);
485
	});
486 cca28e34 Phil Davis
});
487 7d8552fc Stephen Beaver
488 29fda3d3 Stephen Beaver
// Separator bar stuff ------------------------------------------------------------------------
489 7d8552fc Stephen Beaver
490 29fda3d3 Stephen Beaver
// Globals
491
gColor = 'bg-info';
492 c049c15e Phil Davis
newSeparator = false;
493 29fda3d3 Stephen Beaver
saving = false;
494
dirty = false;
495
496
$("#addsep").prop('type' ,'button');
497
498
$("#addsep").click(function() {
499 c049c15e Phil Davis
	if (newSeparator) {
500 29fda3d3 Stephen Beaver
		return(false);
501
	}
502 7d8552fc Stephen Beaver
503 29fda3d3 Stephen Beaver
	gColor = 'bg-info';
504 726fdb61 Phil Davis
	// Insert a temporary bar in which the user can enter some optional text
505 29fda3d3 Stephen Beaver
	sepcols = $( "#ruletable tr th" ).length - 2;
506
507
	$('#ruletable > tbody:last').append('<tr>' +
508
		'<td class="' + gColor + '" colspan="' + sepcols + '"><input id="newsep" placeholder="' + svbtnplaceholder + '" class="col-md-12" type="text" /></td>' +
509
		'<td class="' + gColor + '" colspan="2"><button class="btn btn-primary btn-sm" id="btnnewsep"><i class="fa fa-save icon-embed-btn"></i>' + svtxt + '</button>' +
510
		'<button class="btn btn-info btn-sm" id="btncncsep"><i class="fa fa-undo icon-embed-btn"></i>' + cncltxt + '</button>' +
511
		'&nbsp;&nbsp;&nbsp;&nbsp;' +
512
		'&nbsp;&nbsp;<a id="sepclrblue" value="bg-info"><i class="fa fa-circle text-info icon-pointer"></i></a>' +
513
		'&nbsp;&nbsp;<a id="sepclrred" value="bg-danger"><i class="fa fa-circle text-danger icon-pointer"></i></a>' +
514
		'&nbsp;&nbsp;<a id="sepclrgreen" value="bg-success"><i class="fa fa-circle text-success icon-pointer"></i></a>' +
515
		'&nbsp;&nbsp;<a id="sepclrorange" value="bg-warning"><i class="fa fa-circle text-warning icon-pointer"></i></button>' +
516
		'</td></tr>');
517
518
	$('#newsep').focus();
519 c049c15e Phil Davis
	newSeparator = true;
520 29fda3d3 Stephen Beaver
521
	$("#btnnewsep").prop('type' ,'button');
522
523
	// Watch escape and enter keys
524
	$('#newsep').keyup(function(e) {
525 726fdb61 Phil Davis
		if (e.which == 27) {
526 29fda3d3 Stephen Beaver
			$('#btncncsep').trigger('click');
527
		}
528
	});
529 7d8552fc Stephen Beaver
530 29fda3d3 Stephen Beaver
	$('#newsep').keypress(function(e) {
531 726fdb61 Phil Davis
		if (e.which == 13) {
532 29fda3d3 Stephen Beaver
			$('#btnnewsep').trigger('click');
533 7d8552fc Stephen Beaver
		}
534 29fda3d3 Stephen Beaver
	});
535
536
	handle_colors();
537 7d8552fc Stephen Beaver
538 29fda3d3 Stephen Beaver
	// Replace the temporary separator bar with the final version containing the
539
	// user's text and a delete icon
540
	$("#btnnewsep").click(function() {
541
		var septext = escapeHtml($('#newsep').val());
542
		sepcols = $( "#ruletable tr th" ).length - 1;
543
544
		$(this).parents('tr').replaceWith('<tr class="ui-sortable-handle separator">' +
545
			'<td class="' + gColor + '" colspan="' + sepcols + '">' + '<span class="' + gColor + '">' + septext + '</span></td>' +
546
			'<td class="' + gColor + '"><a href="#"><i class="fa fa-trash sepdel"></i></a>' +
547 7d8552fc Stephen Beaver
			'</td></tr>');
548
549 29fda3d3 Stephen Beaver
		$('#order-store').removeAttr('disabled');
550 c049c15e Phil Davis
		newSeparator = false;
551 29fda3d3 Stephen Beaver
		dirty = true;
552
	});
553 7d8552fc Stephen Beaver
554 29fda3d3 Stephen Beaver
	// Cancel button
555
	$('#btncncsep').click(function(e) {
556
		e.preventDefault();
557
		$(this).parents('tr').remove();
558 c049c15e Phil Davis
		newSeparator = false;
559 29fda3d3 Stephen Beaver
	});
560
});
561 7d8552fc Stephen Beaver
562 29fda3d3 Stephen Beaver
// Delete a separator row
563
$(function(){
564
	$('table').on('click','tr a .sepdel',function(e){
565
		e.preventDefault();
566
		$(this).parents('tr').remove();
567
		$('#order-store').removeAttr('disabled');
568
		dirty = true;
569
	});
570
});
571 7d8552fc Stephen Beaver
572 726fdb61 Phil Davis
// Compose an input array containing the row #, color and text for each separator
573 29fda3d3 Stephen Beaver
function save_separators() {
574
	var row = 0;
575
	var sepinput;
576
	var sepnum = 0;
577
578
	$('#ruletable > tbody > tr').each(function() {
579
		if ($(this).hasClass('separator')) {
580
			seprow = $(this).next('tr').attr("id");
581
			if (seprow == undefined) {
582
				seprow = "fr" + row;
583 7d8552fc Stephen Beaver
			}
584
585 29fda3d3 Stephen Beaver
			sepinput = '<input type="hidden" name="separator[' + sepnum + '][row]" value="' + seprow + '"></input>';
586
			$('form').append(sepinput);
587
			sepinput = '<input type="hidden" name="separator[' + sepnum + '][text]" value="' + escapeHtml($(this).find('td').text()) + '"></input>';
588
			$('form').append(sepinput);
589
			sepinput = '<input type="hidden" name="separator[' + sepnum + '][color]" value="' + $(this).find('td').prop('class') + '"></input>';
590
			$('form').append(sepinput);
591
			sepinput = '<input type="hidden" name="separator[' + sepnum + '][if]" value="' + iface + '"></input>';
592
			$('form').append(sepinput);
593
			sepnum++;
594
		} else {
595
			if ($(this).parent('tbody').hasClass('user-entries')) {
596
				row++;
597
			}
598
		}
599
	});
600
}
601 7d8552fc Stephen Beaver
602 29fda3d3 Stephen Beaver
function reindex_rules(section) {
603
	var row = 0;
604 7d8552fc Stephen Beaver
605 29fda3d3 Stephen Beaver
	section.find('tr').each(function() {
606 726fdb61 Phil Davis
		if (this.id) {
607 29fda3d3 Stephen Beaver
			$(this).attr("id", "fr" + row);
608
			$(this).attr("onclick", "fr_toggle(" + row + ")")
609
			$(this).find('input:checkbox:first').each(function() {
610
				$(this).attr("id", "frc" + row);
611
				$(this).attr("onclick", "fr_toggle(" + row + ")");
612
			});
613 7d8552fc Stephen Beaver
614 29fda3d3 Stephen Beaver
			row++;
615
		}
616 7d8552fc Stephen Beaver
	});
617 29fda3d3 Stephen Beaver
}
618 7d8552fc Stephen Beaver
619 29fda3d3 Stephen Beaver
function handle_colors() {
620
	$('[id^=sepclr]').prop("type", "button");
621
622
	$('[id^=sepclr]').click(function () {
623
		var color =	 $(this).attr('value');
624
		// Clear all the color classes
625
		$(this).parent('td').prop('class', '');
626
		$(this).parent('td').prev('td').prop('class', '');
627
		// Install our new color class
628
		$(this).parent('td').addClass(color);
629
		$(this).parent('td').prev('td').addClass(color);
630
		// Set the global color
631
		gColor = color;
632 7d8552fc Stephen Beaver
	});
633 29fda3d3 Stephen Beaver
}
634 7d8552fc Stephen Beaver
635 29fda3d3 Stephen Beaver
//JS equivalent to PHP htmlspecialchars()
636
function escapeHtml(text) {
637
	var map = {
638
		'&': '&amp;',
639
		'<': '&lt;',
640
		'>': '&gt;',
641
		'"': '&quot;',
642
		"'": '&#039;'
643
	};
644
645
	return text.replace(/[&<>"']/g, function(m) { return map[m]; });
646
}
647
// --------------------------------------------------------------------------------------------
648 7d8552fc Stephen Beaver
649 29fda3d3 Stephen Beaver
// Select every option in the specified multiselect
650
function AllServers(id, selectAll) {
651
   for (i = 0; i < id.length; i++)	   {
652
	   id.eq(i).prop('selected', selectAll);
653
   }
654
}
655 3f597adb Stephen Beaver
656 29fda3d3 Stephen Beaver
// Move all selected options from one multiselect to another
657
function moveOptions(From, To)	{
658
	var len = From.length;
659
	var option;
660
661
	if (len > 0) {
662
		for (i=0; i<len; i++) {
663
			if (From.eq(i).is(':selected')) {
664
				option = From.eq(i).val();
665
				value  = From.eq(i).text();
666
				To.append(new Option(value, option));
667
				From.eq(i).remove();
668 7d8552fc Stephen Beaver
			}
669 29fda3d3 Stephen Beaver
		}
670 7d8552fc Stephen Beaver
	}
671 29fda3d3 Stephen Beaver
}
672 7d8552fc Stephen Beaver
673 29fda3d3 Stephen Beaver
// ------------- Service start/stop/restart functions.
674 7f30df9a Stephen Beaver
// If a start/stop/restart button is clicked, parse the button name and make a POST via AJAX
675 29fda3d3 Stephen Beaver
$('[id*=restartservice-], [id*=stopservice-], [id*=startservice-]').click(function(event) {
676
	var args = this.id.split('-');
677
	var action, name, mode_zone, id;
678
679
	if (args[0] == "openvpn") {
680
		action = args[1];
681
		name = args[0];
682
		mode_zone = args[2];
683
		id = args[3];
684 dbd0501b doktornotor
	} else if (args[0] == "captiveportal") {
685 29fda3d3 Stephen Beaver
		action = args[1];
686
		name = args[0];
687
		mode_zone = args[2];
688
		id = args[3];
689
	} else {
690
		action = args[0];
691 21a8edd7 Steve Beaver
		args.shift();
692
		name = args.join('-');
693 2ccf2ede Stephen Beaver
	}
694
695 29fda3d3 Stephen Beaver
	$(this).children('i').removeClass().addClass('fa fa-cog fa-spin text-success');
696 4c08c292 Stephen Beaver
	this.blur();
697 29fda3d3 Stephen Beaver
698
	ajaxRequest = $.ajax(
699
		{
700
			url: "/status_services.php",
701
			type: "post",
702
			data: {
703
				ajax: 		"ajax",
704
				mode: 		action,
705
				service: 	name,
706
				vpnmode: 	mode_zone,
707
				zone: 		mode_zone,
708
				id: 		id
709 2ccf2ede Stephen Beaver
			}
710
		}
711 29fda3d3 Stephen Beaver
	);
712
713
	// Once the AJAX call has returned, refresh the page to show the new service
714
	ajaxRequest.done(function (response, textStatus, jqXHR) {
715
		location.reload(true);
716
	});
717
});
718 f0136b17 Steve Beaver
719
// The scripts that follow are an EXPERIMENT in using jQuery/Javascript to automatically convert
720
// GET calls to POST calls
721 e04daed0 Steve Beaver
// Any anchor with the attribute "usepost" usses these functions.
722 f0136b17 Steve Beaver
723
// Any time an anchor is clicked and the "usepost" attibute is present, convert the href attribute
724
// to POST format, make a POST form and submit it
725
726 64d53c69 Steve Beaver
interceptGET();
727 e04daed0 Steve Beaver
728 64d53c69 Steve Beaver
function interceptGET() {
729
	$('a').click(function(e) {
730
		// Does the clicked anchor have the "usepost" attribute?
731
		var attr = $(this).attr('usepost');
732 e04daed0 Steve Beaver
733 64d53c69 Steve Beaver
		if (typeof attr !== typeof undefined && attr !== false) {
734
			// Automatically apply a confirmation dialog to "Delete" icons
735
			if (!($(this).hasClass('no-confirm')) && !($(this).hasClass('icon-embed-btn')) &&
736
			   ($(this).hasClass('fa-trash'))) {
737
				var msg = $.trim(this.textContent).toLowerCase();
738 e04daed0 Steve Beaver
739 64d53c69 Steve Beaver
				if (!msg)
740
					var msg = $.trim(this.value).toLowerCase();
741 e04daed0 Steve Beaver
742 64d53c69 Steve Beaver
				var q = 'Are you sure you wish to '+ msg +'?';
743
744
				if ($(this).attr('title') != undefined)
745
					q = 'Are you sure you wish to '+ $(this).attr('title').toLowerCase() + '?';
746
747
				if (!confirm(q)) {
748
					return false;
749
				}
750 e04daed0 Steve Beaver
			}
751
752 64d53c69 Steve Beaver
			var target = $(this).attr("href").split("?");
753 f0136b17 Steve Beaver
754 64d53c69 Steve Beaver
			postSubmit(get2post(target[1]),target[0]);
755
			return false;
756
		}
757
	});
758
}
759 f0136b17 Steve Beaver
760 19be2fc2 Nazar Mokrynskyi
// Convert a GET argument list such as ?name=fred&action=delete into an object of POST
761
// parameters such as {name : fred, action : delete}
762 f0136b17 Steve Beaver
function get2post(getargs) {
763 19be2fc2 Nazar Mokrynskyi
	var argdict = {};
764 f0136b17 Steve Beaver
	var argarray = getargs.split('&');
765
766 19be2fc2 Nazar Mokrynskyi
	argarray.forEach(function(arg) {
767
		arg = arg.split('=');
768
		argdict[arg[0]] = arg[1];
769
	});
770 f0136b17 Steve Beaver
771 19be2fc2 Nazar Mokrynskyi
	return argdict;
772 f0136b17 Steve Beaver
}
773
774
// Create a form, add, the POST data and submit it
775 06f6b161 Steve Beaver
function postSubmit(data, target) {
776 19be2fc2 Nazar Mokrynskyi
	var $form = $('<form>');
777
778
	for (var name in data) {
779
		$form.append(
780
			$("<input>")
781
				.attr("type", "hidden")
782
				.attr("name", name)
783
				.val(data[name])
784
		);
785 f0136b17 Steve Beaver
    }
786
787 19be2fc2 Nazar Mokrynskyi
	$form
788
		.attr("method", "POST")
789
		.attr("action", target)
790
		// The CSRF magic is required because we will be viewing the results of the POST
791
		.append(
792
			$("<input>")
793
				.attr("type", "hidden")
794
				.attr("name", "__csrf_magic")
795
				.val(csrfMagicToken)
796
		)
797
		.appendTo('body')
798
		.submit();
799 f0136b17 Steve Beaver
}