mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
290 lines
10 KiB
JavaScript
290 lines
10 KiB
JavaScript
$(document).ready(function() {
|
|
|
|
// Pagination
|
|
$('select#per_page').change(function() {
|
|
this.form.submit();
|
|
});
|
|
|
|
// "Toggle" checkbox for object lists (PK column)
|
|
$('input:checkbox.toggle').click(function() {
|
|
$(this).closest('table').find('input:checkbox[name=pk]').prop('checked', $(this).prop('checked'));
|
|
|
|
// Show the "select all" box if present
|
|
if ($(this).is(':checked')) {
|
|
$('#select_all_box').removeClass('hidden');
|
|
} else {
|
|
$('#select_all').prop('checked', false);
|
|
}
|
|
});
|
|
|
|
// Uncheck the "toggle" and "select all" checkboxes if an item is unchecked
|
|
$('input:checkbox[name=pk]').click(function (event) {
|
|
if (!$(this).attr('checked')) {
|
|
$('input:checkbox.toggle, #select_all').prop('checked', false);
|
|
}
|
|
});
|
|
|
|
// Enable hidden buttons when "select all" is checked
|
|
$('#select_all').click(function() {
|
|
if ($(this).is(':checked')) {
|
|
$('#select_all_box').find('button').prop('disabled', '');
|
|
} else {
|
|
$('#select_all_box').find('button').prop('disabled', 'disabled');
|
|
}
|
|
});
|
|
|
|
// Slugify
|
|
function slugify(s, num_chars) {
|
|
s = s.replace(/[^\-\.\w\s]/g, ''); // Remove unneeded chars
|
|
s = s.replace(/^[\s\.]+|[\s\.]+$/g, ''); // Trim leading/trailing spaces
|
|
s = s.replace(/[\-\.\s]+/g, '-'); // Convert spaces and decimals to hyphens
|
|
s = s.toLowerCase(); // Convert to lowercase
|
|
return s.substring(0, num_chars); // Trim to first num_chars chars
|
|
}
|
|
var slug_field = $('#id_slug');
|
|
slug_field.change(function() {
|
|
$(this).attr('_changed', true);
|
|
});
|
|
if (slug_field) {
|
|
var slug_source = $('#id_' + slug_field.attr('slug-source'));
|
|
slug_source.on('keyup change', function() {
|
|
if (slug_field && !slug_field.attr('_changed')) {
|
|
slug_field.val(slugify($(this).val(), 50));
|
|
}
|
|
})
|
|
}
|
|
|
|
// Bulk edit nullification
|
|
$('input:checkbox[name=_nullify]').click(function() {
|
|
$('#id_' + this.value).toggle('disabled');
|
|
});
|
|
|
|
// Set formaction and submit using a link
|
|
$('a.formaction').click(function(event) {
|
|
event.preventDefault();
|
|
var form = $(this).closest('form');
|
|
form.attr('action', $(this).attr('href'));
|
|
form.submit();
|
|
});
|
|
|
|
// Parse URLs which may contain variable refrences to other field values
|
|
function parseURL(url) {
|
|
var filter_regex = /\{\{([a-z_]+)\}\}/g;
|
|
var match;
|
|
var rendered_url = url;
|
|
var filter_field;
|
|
while (match = filter_regex.exec(url)) {
|
|
filter_field = $('#id_' + match[1]);
|
|
var custom_attr = $('option:selected', filter_field).attr('api-value');
|
|
if (custom_attr) {
|
|
rendered_url = rendered_url.replace(match[0], custom_attr);
|
|
} else if (filter_field.val()) {
|
|
rendered_url = rendered_url.replace(match[0], filter_field.val());
|
|
} else if (filter_field.attr('nullable') == 'true') {
|
|
rendered_url = rendered_url.replace(match[0], 'null');
|
|
}
|
|
}
|
|
return rendered_url
|
|
}
|
|
|
|
// Assign color picker selection classes
|
|
function colorPickerClassCopy(data, container) {
|
|
if (data.element) {
|
|
$(container).addClass($(data.element).attr("class"));
|
|
}
|
|
return data.text;
|
|
}
|
|
|
|
// Color Picker
|
|
$('.netbox-select2-color-picker').select2({
|
|
allowClear: true,
|
|
placeholder: "---------",
|
|
theme: "bootstrap",
|
|
templateResult: colorPickerClassCopy,
|
|
templateSelection: colorPickerClassCopy
|
|
});
|
|
|
|
// Static choice selection
|
|
$('.netbox-select2-static').select2({
|
|
allowClear: true,
|
|
placeholder: "---------",
|
|
theme: "bootstrap"
|
|
});
|
|
|
|
// API backed selection
|
|
// Includes live search and chained fields
|
|
// The `multiple` setting may be controled via a data-* attribute
|
|
$('.netbox-select2-api').select2({
|
|
allowClear: true,
|
|
placeholder: "---------",
|
|
theme: "bootstrap",
|
|
ajax: {
|
|
delay: 500,
|
|
|
|
url: function(params) {
|
|
var element = this[0];
|
|
var url = parseURL(element.getAttribute("data-url"));
|
|
|
|
if (url.includes("{{")) {
|
|
// URL is not fully rendered yet, abort the request
|
|
return false;
|
|
}
|
|
return url;
|
|
},
|
|
|
|
data: function(params) {
|
|
var element = this[0];
|
|
// Paging. Note that `params.page` indexes at 1
|
|
var offset = (params.page - 1) * 50 || 0;
|
|
// Base query params
|
|
var parameters = {
|
|
q: params.term,
|
|
brief: 1,
|
|
limit: 50,
|
|
offset: offset,
|
|
};
|
|
|
|
// filter-for fields from a chain
|
|
var attr_name = "data-filter-for-" + $(element).attr("name");
|
|
var form = $(element).closest('form');
|
|
var filter_for_elements = form.find("select[" + attr_name + "]");
|
|
|
|
filter_for_elements.each(function(index, filter_for_element) {
|
|
var param_name = $(filter_for_element).attr(attr_name);
|
|
var value = $(filter_for_element).val();
|
|
|
|
if (param_name && value) {
|
|
parameters[param_name] = value;
|
|
}
|
|
});
|
|
|
|
// Conditional query params
|
|
$.each(element.attributes, function(index, attr){
|
|
if (attr.name.includes("data-conditional-query-param-")){
|
|
var conditional = attr.name.split("data-conditional-query-param-")[1].split("__");
|
|
var field = $("#id_" + conditional[0]);
|
|
var field_value = conditional[1];
|
|
|
|
if ($('option:selected', field).attr('api-value') === field_value){
|
|
var _val = attr.value.split("=");
|
|
parameters[_val[0]] = _val[1];
|
|
}
|
|
}
|
|
});
|
|
|
|
// Additional query params
|
|
$.each(element.attributes, function(index, attr){
|
|
if (attr.name.includes("data-additional-query-param-")){
|
|
var param_name = attr.name.split("data-additional-query-param-")[1]
|
|
parameters[param_name] = attr.value;
|
|
}
|
|
});
|
|
|
|
// This will handle params with multiple values (i.e. for list filter forms)
|
|
return $.param(parameters, true);
|
|
},
|
|
|
|
processResults: function (data) {
|
|
var element = this.$element[0];
|
|
var results = $.map(data.results, function (obj) {
|
|
obj.text = obj[element.getAttribute('display-field')] || obj.name;
|
|
obj.id = obj[element.getAttribute('value-field')] || obj.id;
|
|
|
|
if(element.getAttribute('disabled-indicator') && obj[element.getAttribute('disabled-indicator')]) {
|
|
// The disabled-indicator equated to true, so we disable this option
|
|
obj.disabled = true;
|
|
}
|
|
return obj;
|
|
});
|
|
|
|
// Handle the null option, but only add it once
|
|
if (element.getAttribute('data-null-option') && data.previous === null) {
|
|
var null_option = $(element).children()[0]
|
|
results.unshift({
|
|
id: null_option.value,
|
|
text: null_option.text
|
|
});
|
|
}
|
|
|
|
// Check if there are more results to page
|
|
var page = data.next !== null;
|
|
return {
|
|
results: results,
|
|
pagination: {
|
|
more: page
|
|
}
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// API backed tags
|
|
var tags = $('#id_tags');
|
|
if (tags.length > 0 && tags.val().length > 0){
|
|
tags = $('#id_tags').val().split(/,\s*/);
|
|
} else {
|
|
tags = [];
|
|
}
|
|
tag_objs = $.map(tags, function (tag) {
|
|
return {
|
|
id: tag,
|
|
text: tag,
|
|
selected: true
|
|
}
|
|
});
|
|
// Replace the django issued text input with a select element
|
|
$('#id_tags').replaceWith('<select name="tags" id="id_tags" class="form-control"></select>');
|
|
$('#id_tags').select2({
|
|
tags: true,
|
|
data: tag_objs,
|
|
multiple: true,
|
|
allowClear: true,
|
|
placeholder: "Tags",
|
|
|
|
ajax: {
|
|
delay: 250,
|
|
url: "/api/extras/tags/",
|
|
|
|
data: function(params) {
|
|
// Paging. Note that `params.page` indexes at 1
|
|
var offset = (params.page - 1) * 50 || 0;
|
|
var parameters = {
|
|
q: params.term,
|
|
brief: 1,
|
|
limit: 50,
|
|
offset: offset,
|
|
};
|
|
return parameters;
|
|
},
|
|
|
|
processResults: function (data) {
|
|
var results = $.map(data.results, function (obj) {
|
|
return {
|
|
id: obj.name,
|
|
text: obj.name
|
|
}
|
|
});
|
|
|
|
// Check if there are more results to page
|
|
var page = data.next !== null;
|
|
return {
|
|
results: results,
|
|
pagination: {
|
|
more: page
|
|
}
|
|
};
|
|
}
|
|
}
|
|
});
|
|
$('#id_tags').closest('form').submit(function(event){
|
|
// django-taggit can only accept a single comma seperated string value
|
|
var value = $('#id_tags').val();
|
|
if (value.length > 0){
|
|
var final_tags = value.join(', ');
|
|
$('#id_tags').val(null).trigger('change');
|
|
var option = new Option(final_tags, final_tags, true, true);
|
|
$('#id_tags').append(option).trigger('change');
|
|
}
|
|
});
|
|
});
|