diff --git a/netbox/project-static/img/ajax-loader.gif b/netbox/project-static/img/ajax-loader.gif
deleted file mode 100644
index 24f1e8658..000000000
Binary files a/netbox/project-static/img/ajax-loader.gif and /dev/null differ
diff --git a/netbox/project-static/js/cabletrace.js b/netbox/project-static/js/cabletrace.js
deleted file mode 100644
index 2307cef87..000000000
--- a/netbox/project-static/js/cabletrace.js
+++ /dev/null
@@ -1,24 +0,0 @@
-$('#cabletrace_modal').on('show.bs.modal', function (event) {
- var button = $(event.relatedTarget);
- var obj = button.data('obj');
- var url = button.data('url');
- var modal_title = $(this).find('.modal-title');
- var modal_body = $(this).find('.modal-body');
- modal_title.text(obj);
- modal_body.empty();
- $.ajax({
- url: url,
- dataType: 'json',
- success: function(json) {
- $.each(json, function(i, segment) {
- modal_body.append(
- '
' +
- '
' + segment[0].device.name + '
' + segment[0].name + '
' +
- '
Cable #' + segment[1].id + '
' +
- '
' + segment[2].device.name + '
' + segment[2].name + '
' +
- '
'
- );
- })
- }
- });
-});
diff --git a/netbox/project-static/js/connection_toggles.js b/netbox/project-static/js/connection_toggles.js
deleted file mode 100644
index c10b0b8eb..000000000
--- a/netbox/project-static/js/connection_toggles.js
+++ /dev/null
@@ -1,46 +0,0 @@
-function toggleConnection(elem) {
- var url = netbox_api_path + "dcim/cables/" + elem.attr('data') + "/";
- if (elem.hasClass('connected')) {
- $.ajax({
- url: url,
- method: 'PATCH',
- dataType: 'json',
- beforeSend: function(xhr, settings) {
- xhr.setRequestHeader("X-CSRFToken", netbox_csrf_token);
- },
- data: {
- 'status': 'planned'
- },
- context: this,
- success: function() {
- elem.parents('tr').removeClass('success').addClass('info');
- elem.removeClass('connected btn-warning').addClass('btn-success');
- elem.attr('title', 'Mark installed');
- elem.children('i').removeClass('mdi mdi-lan-disconnect').addClass('mdi mdi-lan-connect')
- }
- });
- } else {
- $.ajax({
- url: url,
- method: 'PATCH',
- dataType: 'json',
- beforeSend: function(xhr, settings) {
- xhr.setRequestHeader("X-CSRFToken", netbox_csrf_token);
- },
- data: {
- 'status': 'connected'
- },
- context: this,
- success: function() {
- elem.parents('tr').removeClass('info').addClass('success');
- elem.removeClass('btn-success').addClass('connected btn-warning');
- elem.attr('title', 'Mark planned');
- elem.children('i').removeClass('mdi mdi-lan-connect').addClass('mdi mdi-lan-disconnect')
- }
- });
- }
- return false;
-}
-$(".cable-toggle").click(function() {
- return toggleConnection($(this));
-});
diff --git a/netbox/project-static/js/forms.js b/netbox/project-static/js/forms.js
deleted file mode 100644
index b95100acc..000000000
--- a/netbox/project-static/js/forms.js
+++ /dev/null
@@ -1,445 +0,0 @@
-$(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]:visible').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');
- if (slug_field) {
- var slug_source = $('#id_' + slug_field.attr('slug-source'));
- var slug_length = slug_field.attr('maxlength');
- if (slug_field.val()) {
- slug_field.attr('_changed', true);
- }
- slug_field.change(function() {
- $(this).attr('_changed', true);
- });
- slug_source.on('keyup change', function() {
- if (slug_field && !slug_field.attr('_changed')) {
- slug_field.val(slugify($(this).val(), (slug_length ? slug_length : 50)));
- }
- });
- $('button.reslugify').click(function() {
- slug_field.val(slugify(slug_source.val(), (slug_length ? slug_length : 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 references 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('data-null-option')) {
- rendered_url = rendered_url.replace(match[0], 'null');
- }
- }
- return rendered_url
- }
-
- // Assign color picker selection classes
- function colorPickerClassCopy(data, container) {
- if (data.element) {
- // Swap the style
- $(container).attr('style', $(data.element).attr("style"));
- }
- return data.text;
- }
-
- // Speed selector
- $("a.set_speed").click(function(e) {
- e.preventDefault();
- $("#id_" + $(this).attr("target")).val($(this).attr("data"));
- });
-
- // Color Picker
- $('.netbox-select2-color-picker').select2({
- allowClear: true,
- placeholder: "---------",
- theme: "bootstrap",
- templateResult: colorPickerClassCopy,
- templateSelection: colorPickerClassCopy,
- width: "off"
- });
-
- // Static choice selection
- $('.netbox-select2-static').select2({
- allowClear: true,
- placeholder: "---------",
- theme: "bootstrap",
- width: "off"
- });
-
- // API backed selection
- // Includes live search and chained fields
- // The `multiple` setting may be controlled via a data-* attribute
- $('.netbox-select2-api').select2({
- allowClear: true,
- placeholder: "---------",
- theme: "bootstrap",
- width: "off",
- 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,
- limit: 50,
- offset: offset,
- brief: true,
- };
-
- // Attach any extra query parameters
- $.each(element.attributes, function(index, attr){
- if (attr.name.includes("data-query-param-")){
- var param_name = attr.name.split("data-query-param-")[1];
-
- $.each($.parseJSON(attr.value), function(index, value) {
- // Referencing the value of another form field
- if (value.startsWith('$')) {
- let ref_field = $('#id_' + value.slice(1));
- if (ref_field.val() && ref_field.is(":visible")) {
- value = ref_field.val();
- } else if (ref_field.attr("required") && ref_field.attr("data-null-option")) {
- value = "null";
- } else {
- return true; // Skip if ref_field has no value
- }
- }
- if (param_name in parameters) {
- if (Array.isArray(parameters[param_name])) {
- parameters[param_name].push(value);
- } else {
- parameters[param_name] = [parameters[param_name], value];
- }
- } else {
- parameters[param_name] = 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];
- $(element).children('option').attr('disabled', false);
- var results = data.results;
-
- results = results.reduce((results,record,idx) => {
- record.text = record[element.getAttribute('display-field')] || record.name;
- if (record._depth) {
- // Annotate hierarchical depth for MPTT objects
- record.text = '--'.repeat(record._depth) + ' ' + record.text;
- }
- record.id = record[element.getAttribute('value-field')] || record.id;
- if(element.getAttribute('disabled-indicator') && record[element.getAttribute('disabled-indicator')]) {
- // The disabled-indicator equated to true, so we disable this option
- record.disabled = true;
- }
- results[idx] = record;
-
- return results;
- },Object.create(null));
-
- results = Object.values(results);
-
- // Handle the null option, but only add it once
- if (element.getAttribute('data-null-option') && data.previous === null) {
- results.unshift({
- id: 'null',
- text: element.getAttribute('data-null-option')
- });
- }
-
- // Check if there are more results to page
- var page = data.next !== null;
- return {
- results: results,
- pagination: {
- more: page
- }
- };
- }
- }
- });
-
- // Flatpickr selectors
- $('.date-picker').flatpickr({
- allowInput: true
- });
- $('.datetime-picker').flatpickr({
- allowInput: true,
- enableSeconds: true,
- enableTime: true,
- time_24hr: true
- });
- $('.time-picker').flatpickr({
- allowInput: true,
- enableSeconds: true,
- enableTime: true,
- noCalendar: true,
- time_24hr: true
- });
-
- // API backed tags
- var tags = $('#id_tags.tagfield');
- if (tags.length > 0 && tags.val().length > 0){
- tags = $('#id_tags.tagfield').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.tagfield').replaceWith('');
- $('#id_tags.tagfield').select2({
- tags: true,
- data: tag_objs,
- multiple: true,
- allowClear: true,
- placeholder: "Tags",
- theme: "bootstrap",
- width: "off",
- ajax: {
- delay: 250,
- url: netbox_api_path + "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) {
- // If tag contains space add double quotes
- if (/\s/.test(obj.name))
- obj.name = '"' + obj.name + '"'
-
- 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.tagfield').closest('form').submit(function(event){
- // django-taggit can only accept a single comma seperated string value
- var value = $('#id_tags.tagfield').val();
- if (value.length > 0){
- var final_tags = value.join(', ');
- $('#id_tags.tagfield').val(null).trigger('change');
- var option = new Option(final_tags, final_tags, true, true);
- $('#id_tags.tagfield').append(option).trigger('change');
- }
- });
-
- if( $('select#id_mode').length > 0 ) {
- $('select#id_mode').on('change', function () {
- if ($(this).val() == '') {
- $('select#id_untagged_vlan').val();
- $('select#id_untagged_vlan').trigger('change');
- $('select#id_tagged_vlans').val([]);
- $('select#id_tagged_vlans').trigger('change');
- $('select#id_untagged_vlan').parent().parent().hide();
- $('select#id_tagged_vlans').parent().parent().hide();
- }
- else if ($(this).val() == 'access') {
- $('select#id_tagged_vlans').val([]);
- $('select#id_tagged_vlans').trigger('change');
- $('select#id_untagged_vlan').parent().parent().show();
- $('select#id_tagged_vlans').parent().parent().hide();
- }
- else if ($(this).val() == 'tagged') {
- $('select#id_untagged_vlan').parent().parent().show();
- $('select#id_tagged_vlans').parent().parent().show();
- }
- else if ($(this).val() == 'tagged-all') {
- $('select#id_tagged_vlans').val([]);
- $('select#id_tagged_vlans').trigger('change');
- $('select#id_untagged_vlan').parent().parent().show();
- $('select#id_tagged_vlans').parent().parent().hide();
- }
- });
- $('select#id_mode').trigger('change');
- }
-
- // Scroll up an offset equal to the first nav element if a hash is present
- // Cannot use '#navbar' because it is not always visible, like in small windows
- function headerOffsetScroll() {
- if (window.location.hash) {
- // Short wait needed to allow the page to scroll to the element
- setTimeout(function() {
- window.scrollBy(0, -$('nav').height())
- }, 10);
- }
- }
-
- // Account for the header height when hash-scrolling
- window.addEventListener('load', headerOffsetScroll);
- window.addEventListener('hashchange', headerOffsetScroll);
-
- // Offset between the preview window and the window edges
- const IMAGE_PREVIEW_OFFSET_X = 20;
- const IMAGE_PREVIEW_OFFSET_Y = 10;
-
- // Preview an image attachment when the link is hovered over
- $('a.image-preview').on('mouseover', function(e) {
- // Twice the offset to account for all sides of the picture
- var maxWidth = window.innerWidth - (e.clientX + (IMAGE_PREVIEW_OFFSET_X * 2));
- var maxHeight = window.innerHeight - (e.clientY + (IMAGE_PREVIEW_OFFSET_Y * 2));
- var img = $('
').attr('id', 'image-preview-window').css({
- display: 'none',
- position: 'absolute',
- maxWidth: maxWidth + 'px',
- maxHeight: maxHeight + 'px',
- left: e.pageX + IMAGE_PREVIEW_OFFSET_X + 'px',
- top: e.pageY + IMAGE_PREVIEW_OFFSET_Y + 'px',
- boxShadow: '0 0px 12px 3px rgba(0, 0, 0, 0.4)',
- });
-
- // Remove any existing preview windows and add the current one
- $('#image-preview-window').remove();
- $('body').append(img);
-
- // Once loaded, show the preview if the image is indeed an image
- img.on('load', function(e) {
- if (e.target.complete && e.target.naturalWidth) {
- $('#image-preview-window').fadeIn('fast');
- }
- });
-
- // Begin loading
- img.attr('src', e.target.href);
- });
-
- // Fade the image out; it will be deleted when another one is previewed
- $('a.image-preview').on('mouseout', function() {
- $('#image-preview-window').fadeOut('fast');
- });
-
- // Rearrange options within a