// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
var JSBase = (function() {
'use strict';
var csrftoken = $('meta[name=csrf-token]').attr('content'),
errorsContainer = $('#errors-container'),
defaultErrorReason = 'Data call failed',
defaultTimeout = 10000;
// Make sure an element is not an ID: does not start with #.
// `elementID`: The element ID to check.
function checkIfNotID(elementID) {
var localElement = elementID;
if (localElement[0] === '#') {
localElement = elementID.slice(1);
}
return localElement;
}
// Make sure the element ID starts with #.
// `elementID`: The element ID to check.
function checkIfID(elementID) {
var localElement = elementID;
if (localElement[0] !== '#') {
localElement = '#' + localElement;
}
return localElement;
}
// Make sure the class name starts with a dot.
// `className`: The name of the class to check.
function checkIfClass(className) {
var localName = className;
if (localName[0] !== '.') {
localName = '.' + localName;
}
return localName;
}
// Add error alerts at the top of the page in the default container.
// `id`: The id of the element to add.
// `code`: The error code (int).
// `reason`: Option reason that will be added to the error message.
function setErrorAlert(id, code, reason) {
var localId = checkIfID(id),
text = '';
text = '
' +
'';
if (reason !== null && reason !== undefined) {
text = text + reason + ' ';
}
text = text +
'Error while loading data from the server (error code: ' +
code + '). ' +
'Please contact the website administrators.';
text = text + '
';
errorsContainer.append(text);
$(localId).alert();
}
// Load static HTML content from an URL.
// `elementID`: The ID of the element.
// `contentURL`: The URL where the static content will be taken.
function loadHTMLContent(elementID, contentURL) {
var realID = checkIfID(elementID);
$(realID).empty().load(contentURL);
}
// Replace content of an element based on its id.
// `elementID`: The ID of the element to search.
// `staticContent`: The content that the element will be replaced with.
function replaceContentByID(elementID, staticContent) {
var realID = checkIfID(elementID);
$(realID).empty().append(staticContent);
}
// Remove an element by its ID from the DOM.
// `elementID`: The ID of the element to remove.
function removeElementByID(elementID) {
var realID = checkIfID(elementID);
$(realID).remove();
}
// Replace content of elements based on their class name.
// It loops through all the elements removing their content and appending
// the provided one.
// `className`: The name of the class to search.
// `staticContent`: The content that the elements will be replaced with.
function replaceContentByClass(className, staticContent) {
var realClass = checkIfClass(className);
$(realClass).each(function() {
$(this).empty().append(staticContent);
});
}
// Remove hidden class from element and apply animation to show it.
// `elementID`: The ID of the element to show.
function showElementByID(elementID) {
var realID = checkIfID(elementID);
$(realID)
.removeClass('hidden')
.fadeIn('slow', 'linear');
}
// Hide the provided DOM element.
// `elementID`: The ID of the element to hide.
function hideElementByID(elementID) {
var realID = checkIfID(elementID);
$(realID).hide();
}
// Remove CSS class from the specified DOM element ID.
// `elementID`: The ID of the element.
// `cssClass`: The CSS class to remove or an Array of classes as string.
function removeCssClassForID(elementID, cssClass) {
var realID = checkIfID(elementID);
if (cssClass.constructor === Array) {
cssClass.forEach(function(element) {
$(realID).removeClass(element);
});
} else {
$(realID).removeClass(cssClass);
}
}
// Remove CSS class from the specified DOM element class.
// `className`: The name of the class to search.
// `cssClass`: The CSS class to remove or an Array of classes as string.
function removeCssClassForClass(className, cssClass) {
var realClass = checkIfClass(className);
if (cssClass.constructor === Array) {
cssClass.forEach(function(element) {
$(realClass).removeClass(element);
});
} else {
$(realClass).removeClass(cssClass);
}
}
// Add CSS class to the specified DOM element ID.
// `elementID`: The ID of the element.
// `cssClass`: The CSS class to add or an Array of classes as string.
function addCssClassForID(elementID, cssClass) {
var realID = checkIfID(elementID);
if (cssClass.constructor === Array) {
cssClass.forEach(function(element) {
$(realID).addClass(element);
});
} else {
$(realID).addClass(cssClass);
}
}
// Return an ajax promise.
// `url`: The URL for the ajax call.
// `method`: The type of ajax call, default to 'GET'.
// `data`: The data to be passed to the ajax call.
// `successFunction`: Optional function, or array of functions,
// to be called on success.
// `errorFunction`: Optional function to be call on error.
// `errorReason`: Error message to be displayed.
// `headers`: Optional headers to set for the ajax call.
// `errorId`: ID to use for the error message div element.
function createDeferredCall(url, method, data, successFunction,
errorFunction, errorReason, headers, errorId) {
var ajaxSettings, ajaxCall;
if (method === null || method === undefined) {
method = 'GET';
}
if (errorReason === null || errorReason === undefined) {
errorReason = defaultErrorReason;
}
if (errorId === null || errorId === undefined) {
errorId = '#error';
} else {
errorId = checkIfID(errorId);
}
ajaxSettings = {
'type': method,
'traditional': true,
'cache': true,
'dataType': 'json',
'beforeSend': function(jqXHR) {
jqXHR.setRequestHeader('X-CSRFToken', csrftoken);
},
'timeout': defaultTimeout,
'statusCode': {
400: function() {
setErrorAlert(errorId + '-400', 404, errorReason);
},
403: function() {
setErrorAlert(errorId + '-403', 403, errorReason);
},
404: function() {
setErrorAlert(errorId + '-404', 404, errorReason);
},
408: function() {
errorReason = errorReason + 'nbsp;(timeout)';
setErrorAlert(errorId + '-408', 408, errorReason);
},
500: function() {
setErrorAlert(errorId + '-500', 500, errorReason);
}
}
};
if (data !== null && data !== undefined) {
ajaxSettings.data = data;
}
if (successFunction !== null && successFunction !== undefined) {
ajaxSettings.success = successFunction;
}
if (errorFunction !== null && errorFunction !== undefined) {
ajaxSettings.error = errorFunction;
}
if (headers !== null && headers !== undefined) {
ajaxSettings.headers = headers;
}
ajaxCall = $.ajax(url, ajaxSettings);
return ajaxCall;
}
/*
Populate the sidebar navigation with the provided elements.
The "Top" link, is already populated since it's available in the base
template.
elements: An array of objects. Each object must have the href, and name
attributes set. An optional subnav attribute can be defined, and must
be another array of similar objects, to add a navigation sub-level.
*/
function populateSideBarNav(elements) {
if (elements === undefined || elements === null) {
return;
}
var sidebarNav = '',
arrayLen = elements.length,
element = null,
i = 0,
j = 0,
subNav = null,
subNavLen;
// Append the stuff only if we have the element.
// On mobile platforms the element is not available.
if ($('#sidebar-nav').length !== 0) {
sidebarNav = '