Project

General

Profile

Download (10.9 KB) Statistics
| Branch: | Tag: | Revision:
1
/*
2
 * pfSense.js
3
 *
4
 * part of pfSense (https://www.pfsense.org)
5
 * Copyright (c) 2004-2013 BSD Perimeter
6
 * Copyright (c) 2013-2016 Electric Sheep Fencing
7
 * Copyright (c) 2014-2019 Rubicon Communications, LLC (Netgate)
8
 * All rights reserved.
9
 *
10
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 * http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22

    
23
/*
24
 * This file should only contain functions that will be used on more than 2 pages
25
 */
26

    
27
$(function() {
28
	// Attach collapsable behaviour to select options
29
	(function()
30
	{
31
		var selects = $('select[data-toggle="collapse"]');
32

    
33
		selects.on('change', function(){
34
			var options = $(this).find('option');
35
			var selectedValue = $(this).find(':selected').val();
36

    
37
			options.each(function(){
38
				if ($(this).val() == selectedValue)
39
					return;
40

    
41
				targets = $('.toggle-'+ $(this).val() +'.in:not(.toggle-'+ selectedValue +')');
42

    
43
				// Hide related collapsables which are visible (.in)
44
				targets.collapse('hide');
45

    
46
				// Disable all invisible inputs
47
				targets.find(':input').prop('disabled', true);
48
			});
49

    
50
			$('.toggle-' + selectedValue).collapse('show').find(':input').prop('disabled', false);
51
		});
52

    
53
		// Trigger change to open currently selected item
54
		selects.trigger('change');
55
	})();
56

    
57

    
58
	// Add +/- buttons to certain Groups; to allow adding multiple entries
59
	// This time making the buttons col-2 wide so they can fit on the same line as the
60
	// rest of the group (providing the total width of the group is col-8 or less)
61
	(function()
62
	{
63
		var groups = $('div.form-group.user-duplication-horiz');
64
		var controlsContainer = $('<div class="col-sm-2"></div>');
65
		var plus = $('<a class="btn btn-sm btn-success"><i class="fa fa-plus icon-embed-btn"></i>Add</a>');
66
		var minus = $('<a class="btn btn-sm btn-warning"><i class="fa fa-trash icon-embed-btn"></i>Delete</a>');
67

    
68
		minus.on('click', function(){
69
			$(this).parents('div.form-group').remove();
70
		});
71

    
72
		plus.on('click', function(){
73
			var group = $(this).parents('div.form-group');
74

    
75
			var clone = group.clone(true);
76
			clone.find('*').val('');
77
			clone.appendTo(group.parent());
78
		});
79

    
80
		groups.each(function(idx, group){
81
			var controlsClone = controlsContainer.clone(true).appendTo(group);
82
			minus.clone(true).appendTo(controlsClone);
83

    
84
			if (group == group.parentNode.lastElementChild)
85
				plus.clone(true).appendTo(controlsClone);
86
		});
87
	})();
88

    
89
	// Add +/- buttons to certain Groups; to allow adding multiple entries
90
	(function()
91
	{
92
		var groups = $('div.form-group.user-duplication');
93
		var controlsContainer = $('<div class="col-sm-10 col-sm-offset-2 controls"></div>');
94
		var plus = $('<a class="btn btn-xs btn-success"><i class="fa fa-plus icon-embed-btn"></i>Add</a>');
95
		var minus = $('<a class="btn btn-xs btn-warning"><i class="fa fa-trash icon-embed-btn"></i>Delete</a>');
96

    
97
		minus.on('click', function(){
98
			$(this).parents('div.form-group').remove();
99
		});
100

    
101
		plus.on('click', function(){
102
			var group = $(this).parents('div.form-group');
103

    
104
			var clone = group.clone(true);
105
			clone.find('*').removeAttr('value');
106
			clone.appendTo(group.parent());
107
		});
108

    
109
		groups.each(function(idx, group){
110
			var controlsClone = controlsContainer.clone(true).appendTo(group);
111
			minus.clone(true).appendTo(controlsClone);
112

    
113
			if (group == group.parentNode.lastElementChild)
114
				plus.clone(true).appendTo(controlsClone);
115
		});
116
	})();
117

    
118
	// Add +/- buttons to certain Groups; to allow adding multiple entries
119
	(function()
120
	{
121
		var groups = $('div.form-listitem.user-duplication');
122
		var fg = $('<div class="form-group"></div>');
123
		var controlsContainer = $('<div class="col-sm-10 col-sm-offset-2 controls"></div>');
124
		var plus = $('<a class="btn btn-xs btn-success"><i class="fa fa-plus icon-embed-btn"></i>Add</a>');
125
		var minus = $('<a class="btn btn-xs btn-warning"><i class="fa fa-trash icon-embed-btn"></i>Delete</a>');
126

    
127
		minus.on('click', function(){
128
			var groups = $('div.form-listitem.user-duplication');
129
			if (groups.length > 1) {
130
				$(this).parents('div.form-listitem').remove();
131
			}
132
		});
133

    
134
		plus.on('click', function(){
135
			var group = $(this).parents('div.form-listitem');
136
			var clone = group.clone(true);
137
			bump_input_id(clone);
138
			clone.appendTo(group.parent());
139
		});
140

    
141
		groups.each(function(idx, group){
142
			var fgClone = fg.clone(true).appendTo(group);
143
			var controlsClone = controlsContainer.clone(true).appendTo(fgClone);
144
			minus.clone(true).appendTo(controlsClone);
145
			plus.clone(true).appendTo(controlsClone);
146
		});
147
	})();
148

    
149
	// Automatically change IpAddress mask selectors to 128/32 options for IPv6/IPv4 addresses
150
	$('span.pfIpMask + select').each(function (idx, select){
151
		var input = $(select).prevAll('input[type=text]');
152

    
153
		input.on('change', function(e){
154
			var isV6 = (input.val().indexOf(':') != -1), min = 0, max = 128;
155

    
156
			if (!isV6)
157
				max = 32;
158

    
159
			if (input.val() == "") {
160
				return;
161
			}
162

    
163
			var attr = $(select).attr('disabled');
164

    
165
			// Don't do anything if the mask selector is disabled
166
			if (typeof attr === typeof undefined || attr === false) {
167
				// Eat all of the options with a value greater than max. We don't want them to be available
168
				while (select.options[0].value > max)
169
					select.remove(0);
170

    
171
				if (select.options.length < max) {
172
					for (var i=select.options.length; i<=max; i++)
173
						select.options.add(new Option(i, i), 0);
174

    
175
					if (isV6) {
176
						// Make sure index 0 is selected otherwise it will stay in "32" for V6
177
						select.options.selectedIndex = "0";
178
					}
179
				}
180
			}
181
		});
182

    
183
		// Fire immediately
184
		input.change();
185
	});
186

    
187
	// Add confirm to all btn-danger buttons and fa-trash icons
188
	// Use element title in the confirmation message, or if not available
189
	// the element value
190
	$('.btn-danger, .fa-trash').on('click', function(e){
191
		if (!($(this).hasClass('no-confirm')) && !($(this).hasClass('icon-embed-btn'))) {
192
			// Anchors using the automatic get2post system (pfSenseHelpers.js) perform the confirmation dialog
193
			// in those functions
194
			var attr = $(this).attr('usepost');
195
			if (typeof attr === typeof undefined || attr === false) {
196
				var msg = $.trim(this.textContent).toLowerCase();
197

    
198
				if (!msg)
199
					var msg = $.trim(this.value).toLowerCase();
200

    
201
				var q = 'Are you sure you wish to '+ msg +'?';
202

    
203
				if ($(this).attr('title') != undefined)
204
					q = 'Are you sure you wish to '+ $(this).attr('title').toLowerCase() + '?';
205

    
206
				if (!confirm(q)) {
207
					e.preventDefault();
208
					e.stopPropagation();	// Don't leave ancestor(s) selected.
209
				}
210
			}
211
		}
212
	});
213

    
214
	// Add toggle-all when there are multiple checkboxes
215
	$('.control-label + .checkbox.multi').each(function() {
216
		var a = $('<a name="btntoggleall" class="btn btn-xs btn-info"><i class="fa fa-check-square-o icon-embed-btn"></i>Toggle All</a>');
217

    
218
		a.on('click', function() {
219
			var wrap = $(this).parents('.form-group').find('.checkbox.multi'),
220
				all = wrap.find('input[type=checkbox]'),
221
				checked = wrap.find('input[type=checkbox]:checked');
222

    
223
			all.prop('checked', (all.length != checked.length));
224
		});
225

    
226
		if ( ! $(this).parent().hasClass("notoggleall")) {
227
			a.appendTo($(this));
228
		}
229
	});
230

    
231
	// The need to NOT hide the advanced options if the elements therein are not set to the system
232
	// default values makes it better to handle advanced option hiding in each PHP file so this is being
233
	// disabled for now by changing the class name it acts on to "auto-advanced"
234

    
235
	// Hide advanced inputs by default
236
	if ($('.auto-advanced').length > 0)
237
	{
238
		var advButt = $('<a id="toggle-advanced" class="btn btn-default">toggle advanced options</a>');
239
		advButt.on('click', function() {
240
			$('.advanced').parents('.form-group').collapse('toggle');
241
		});
242

    
243
		advButt.insertAfter($('#save'));
244

    
245
		$('.auto-advanced').parents('.form-group').collapse({toggle: true});
246
	}
247

    
248
	var originalLeave = $.fn.popover.Constructor.prototype.leave;
249
	$.fn.popover.Constructor.prototype.leave = function(obj){
250
	  var self = obj instanceof this.constructor ?
251
	    obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
252
	  var container, timeout;
253

    
254
	  originalLeave.call(this, obj);
255

    
256
	  if (self.$tip && self.$tip.length) {
257
	    container = self.$tip;
258
	    timeout = self.timeout;
259
	    container.one('mouseenter', function(){
260
	      //We entered the actual popover - call off the dogs
261
	      clearTimeout(timeout);
262
	      //Let's monitor popover content instead
263
	      container.one('mouseleave', function(){
264
	        $.fn.popover.Constructor.prototype.leave.call(self, self);
265
	      });
266
	    })
267
	  }
268
	};
269

    
270
	// Enable popovers globally
271
	$('[data-toggle="popover"]').popover({ delay: {show: 50, hide: 400} });
272

    
273
	// Force correct initial state for toggleable checkboxes
274
	$('input[type=checkbox][data-toggle="collapse"]:not(:checked)').each(function() {
275
		$( $(this).data('target') ).addClass('collapse');
276
	});
277

    
278
	$('input[type=checkbox][data-toggle="disable"]:not(:checked)').each(function() {
279
		$( $(this).data('target') ).prop('disabled', true);
280
	});
281

    
282
	$('.table-rowdblclickedit>tbody>tr').dblclick(function () {
283
		$(this).find(".fa-pencil")[0].click();
284
	});
285

    
286
	// Focus first input
287
	$(':input:enabled:visible:first').focus();
288

    
289
	$(".resizable").each(function() {
290
		$(this).css('height', 80).resizable({minHeight: 80, minWidth: 200}).parent().css('padding-bottom', 0);
291
		$(this).css('height', 78);
292
	});
293

    
294
	// Run in-page defined events
295
	while (func = window.events.shift())
296
		func();
297
});
298

    
299
// Implement data-toggle=disable
300
// Source: https://github.com/synergic-cz/synergic-ui/blob/master/src/js/disable.js
301
;(function($, window, document) {
302
	'use strict';
303

    
304
	var Disable = function($element) {
305
		this.$element = $element;
306
	};
307

    
308
	Disable.prototype.toggle = function() {
309
		this.$element.prop('disabled', !this.$element.prop('disabled'));
310
	};
311

    
312
	function Plugin(options) {
313
		$(document).trigger('toggle.sui.disable');
314

    
315
		this.each(function() {
316
			var $this = $(this);
317
			var data = $this.data('sui.disable');
318

    
319
			if (!data) {
320
				$this.data('sui.disable', (data = new Disable($this)));
321
			}
322

    
323
			if (options === 'toggle') {
324
				data.toggle();
325
			}
326
		});
327

    
328
		$(document).trigger('toggled.sui.disable');
329

    
330
		return this;
331
	}
332

    
333
	var old = $.fn.disable;
334

    
335
	$.fn.disable = Plugin;
336
	$.fn.disable.Constructor = Disable;
337

    
338
	$.fn.disable.noConflict = function() {
339
		$.fn.disable = old;
340
		return this;
341
	};
342

    
343
	(function(Plugin, $, window) {
344
		$(window).on("load", function() {
345
			var $controls = $('[data-toggle=disable]');
346

    
347
			$controls.each(function() {
348
				var $this = $(this);
349
				var eventType = $this.data('disable-event');
350
				if (!eventType) {
351
					eventType = 'change';
352
				}
353
				$this.on(eventType + '.sui.disable.data-api', function() {
354
					Plugin.call($($this.data('target')), 'toggle');
355
				});
356
			});
357
		});
358
	}(Plugin, $, window, document));
359
}(jQuery, window, document));
(1-1/4)