Project

General

Profile

Download (10.8 KB) Statistics
| Branch: | Tag: | Revision:
1
/*
2
 * pfSense.js
3
 *
4
 * part of pfSense (https://www.pfsense.org)
5
 * Copyright (c) 2004-2018 Rubicon Communications, LLC (Netgate)
6
 * All rights reserved.
7
 *
8
 * 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
 *
12
 * http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * 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
 */
20

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

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

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

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

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

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

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

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

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

    
55

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
154
			if (!isV6)
155
				max = 32;
156

    
157
			if (input.val() == "") {
158
				return;
159
			}
160

    
161
			var attr = $(select).attr('disabled');
162

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

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

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

    
181
		// Fire immediately
182
		input.change();
183
	});
184

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

    
196
				if (!msg)
197
					var msg = $.trim(this.value).toLowerCase();
198

    
199
				var q = 'Are you sure you wish to '+ msg +'?';
200

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

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

    
212
	// Add toggle-all when there are multiple checkboxes
213
	$('.control-label + .checkbox.multi').each(function() {
214
		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>');
215

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

    
221
			all.prop('checked', (all.length != checked.length));
222
		});
223

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

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

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

    
241
		advButt.insertAfter($('#save'));
242

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

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

    
252
	  originalLeave.call(this, obj);
253

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

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

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

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

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

    
284
	// Focus first input
285
	$(':input:enabled:visible:first').focus();
286

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

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

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

    
302
	var Disable = function($element) {
303
		this.$element = $element;
304
	};
305

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

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

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

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

    
321
			if (options === 'toggle') {
322
				data.toggle();
323
			}
324
		});
325

    
326
		$(document).trigger('toggled.sui.disable');
327

    
328
		return this;
329
	}
330

    
331
	var old = $.fn.disable;
332

    
333
	$.fn.disable = Plugin;
334
	$.fn.disable.Constructor = Disable;
335

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

    
341
	(function(Plugin, $, window) {
342
		$(window).load(function() {
343
			var $controls = $('[data-toggle=disable]');
344

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