// custom mdpi.com generic javascript
// object size function
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
// resize end - use resizeend event instead of resize to trigger events after resizing has ended
// https://github.com/InventingWithMonster/resize-end
var TIMEOUT = 200,
EVENT_KEY = 'resizeend',
$window = $(window),
timer;
if (window.addEventListener)
{
window.addEventListener('resize', windowResize);
}
else
{
window.attachEvent('onresize', windowResize);
}
function windowResize()
{
clearTimeout(timer);
timer = setTimeout(function () {
$(window).trigger(EVENT_KEY);
}, TIMEOUT);
}
var SHOW_EXPANDING_EVENT = "showexpandingevent";
// function for executing a defined function after all images inside the given container
// are fully loaded and ready
function waitForImagesReady(container, params, func)
{
var img = container.find('img[src]');
var totalImg = img.length;
if (totalImg == 0) {
func(params);
}
else {
var waitImgDone = function() {
totalImg--;
if (totalImg == 0) {
func(params);
}
};
img.each(function() {
if (this.complete)
{
waitImgDone(); // img loaded already from cache
}
else
{
$(this).load(waitImgDone).error(waitImgDone); // img loaded (load event triggered)
}
});
}
}
var mdpi_column_height_module = (function()
{
// store the module public variables in Object for easier access
var moduleVariables = new Object();
moduleVariables["mainColumnImagesReady"] = false;
moduleVariables["extendingContentsReady"] = false;
moduleVariables["leftColumn"] = null;
moduleVariables["middleColumn"] = null;
moduleVariables["rightColumn"] = null;
moduleVariables["mainColumn"] = null;
var calculateColumnHeight = function(column)
{
var expandingContainers = column.find(".extending-content.content-ready");
var expandingContainersElements = [];
// get the max container length & add the expanding div elements into array
// the array is ordered so that first come the first items of all containers,
// then second items of all containers, etc to guarantee that the available
// space is divided nicely to all existing expanding containers
var maxExpandingContainerLength = 0;
var elements = new Object();
for (var i = 0; i < expandingContainers.length; i++) {
var containerElements = $(expandingContainers[i]).find(".expanding-div").not(".empty");
var containerLength = containerElements.length;
expandingContainersElements.push(containerElements);
maxExpandingContainerLength = Math.max(containerLength, maxExpandingContainerLength);
}
for (var i = 0; i < maxExpandingContainerLength; i++)
{
for (var j = 0; j < expandingContainers.length; j++)
{
var currentElement = (expandingContainersElements[j].length > i ? expandingContainersElements[j][i] : null);
elements[i * expandingContainers.length + j] = currentElement;
}
}
calculate(elements, 0, column);
};
// method for calculating single element addition. First check whether there is enough free
// space for addition.
// 1) yes, add the element, wait for the possible images to be ready
// 2) no, do nothing
var calculate = function(elementArray, currentIndex, column)
{
if (Object.size(elementArray) > currentIndex)
{
element = $(elementArray[currentIndex]);
var uniqueElement = element;
// if we encounter a null value, just skip forwards
if (element == null) {
calculate(elementArray, currentIndex + 1, column);
return;
}
if ('undefined' != typeof element.data("content-raw")) {
uniqueElement = $("
").html(unescape(element.data("content-raw")));
}
// if we encounter an unique item that has already been expanded (like article in latest articles), just skip forwards
var uniqueItem = uniqueElement.find("input.unique-dynamic-item");
if (1 === uniqueItem.length && 1 === $(".expanding-div.expanded input.unique-dynamic-item[value='" + uniqueItem.val() + "']").length) {
calculate(elementArray, currentIndex + 1, column);
return;
}
if (column.height() < moduleVariables["mainColumn"].height())
{
// expand and show the current element
element = $(elementArray[currentIndex]);
var extendingContent = element.closest(".extending-content");
//extendingContent.show();
if (!extendingContent.is(":visible")) {
extendingContent.show(0, function() {
setTimeout(function() {
extendingContent.trigger(SHOW_EXPANDING_EVENT);
//column.find(".expanding-div").removeClass("expanded").addClass("collapsed");
//calculateColumnHeight(column);
//calcColumnHeights();
}, 1);
});
}
element.addClass("expanded").removeClass("collapsed");
if (element.html() == '') {
element.html(unescape(element.data("content-raw")));
}
// wait for the images to be loaded - add function pointer to call this function again after loading is ready
waitForImagesReady(element, [column, elementArray, currentIndex] , function(params) {
var localColumn = params[0];
var localElementArray = params[1];
var localCurrentIndex = params[2];
calculate(localElementArray, localCurrentIndex + 1, localColumn);
});
}
// went already too far - hide the previous element and all the rest of the elements
// if we are calculating middle column (i.e. left or right is the main one, the middle
// is allowed to go over
else
{
var hidingIndex = (column === moduleVariables["middleColumn"] ? currentIndex : currentIndex - 1);
handleExtendingDivHiding(elementArray, hidingIndex, column);
handlePadding(column);
}
}
// check the status one more time for the last element
else if (Object.size(elementArray) == currentIndex)
{
if (column.height() > moduleVariables["mainColumn"].height())
{
handleExtendingDivHiding(elementArray, currentIndex - 1, column);
}
handlePadding(column);
}
};
/**
* Function to handle hiding the rest of the divs, hiding the container divs if needed
* and calculating the padding div height if present (and if some containers are extended)
*/
var handleExtendingDivHiding = function(elementArray, index, column)
{
for (var i = Math.max(index, 0); i < Object.size(elementArray); i++)
{
var element = $(elementArray[i]);
element.removeClass("expanded").addClass("collapsed");
}
// hide the extending-container divs if there are no expanded divs inside
column.find(".extending-content").each(function()
{
if ($(this).find(".expanding-div.expanded").length == 0)
{
$(this).hide();
}
});
};
/**
* Function for handling the possible padding div heights
*/
var handlePadding = function(column)
{
if (typeof Foundation === 'undefined' || Foundation.utils.is_medium_up())
{
// if we have a padding element defined, set the height for that
var paddingElement = column.find(".column-padding");
//if (paddingElement.length > 0 && column.find(".extending-content:visible").length > 0)
if (paddingElement.length > 0)
{
paddingElement.css('height', moduleVariables["mainColumn"].height() - column.height() + 11 + 'px');
}
}
};
function calcColumnHeights(force, mainColumn)
{
// make sure that both middle column images are loaded and ajax contents are
// loaded before starting the heigh calculations
if (moduleVariables["mainColumnImagesReady"] && moduleVariables["extendingContentsReady"])
{
// remove the padding-div height in every case
$(".column-padding").css('height', '0px');
if (force || typeof Foundation === 'undefined' || Foundation.utils.is_medium_up())
{
//console.log("recalculating heights...");
$(".expanding-div").removeClass("expanded").addClass("collapsed");
if ("#right-column" !== mainColumn)
{
calculateColumnHeight(moduleVariables["rightColumn"]);
}
if ("#middle-column" !== mainColumn)
{
calculateColumnHeight(moduleVariables["middleColumn"]);
}
if ("#left-column" !== mainColumn)
{
calculateColumnHeight(moduleVariables["leftColumn"]);
}
}
}
}
/**
* Public API of the height calculation module
*/
return {
/**
* Public setter for module variables
*/
setVariable: function(name, value)
{
if (name in moduleVariables) {
moduleVariables[name] = value;
}
},
/*
* Public getter for module variables
*/
getVariable: function(name)
{
if (name in moduleVariables) {
return moduleVariables[name];
}
return null;
},
/*
* Function to calculate and even column heights for two/three column
* layouts.
*
* Generically only applied on medium-up media sizes (can be overwritten with the
* force = true parameter)
*/
calculateColumnHeights: function(force, mainColumn)
{
calcColumnHeights(force, mainColumn);
}
};
})();
$(document).ready(function()
{
if ('undefined' === typeof(mainColumn1))
{
mainColumn1 = "#middle-column";
}
mdpi_column_height_module.setVariable("leftColumn", $("#left-column"));
mdpi_column_height_module.setVariable("middleColumn", $("#middle-column"));
mdpi_column_height_module.setVariable("rightColumn", $("#right-column"));
mdpi_column_height_module.setVariable("mainColumn", $(mainColumn1));
if (typeof(extendingReady) !== 'undefined' && extendingReady)
{
mdpi_column_height_module.setVariable("extendingContentsReady", true);
}
// add listener to check when the middle column images are ready...
waitForImagesReady($(mainColumn1), [], function(params) {
mdpi_column_height_module.setVariable("mainColumnImagesReady", true);
mdpi_column_height_module.calculateColumnHeights(true, mainColumn1);
});
// initialize the column height contents
$(".extending-content").each(function()
{
var element = $(this);
if (element.data('url'))
{
$.ajax({
url: element.data('url'),
success: function(msg)
{
// minumum number of shown items: if zero, hide the header too if no space
//var element_min_items = element.data("min-shown-items") ? parseInt(element.data("min-shown-items")) : 0;
//if (msg.data.length > 0 && element_min_items > 0) {
//element.show();
//}
// create a placeholder div for each of the items
$.each(msg.data, function(i, object) {
var new_div = $(document.createElement('div'));
new_div.attr('data-content-raw', escape(object));
new_div.addClass("expanding-div");
// handle whether the item belongs to the minimum shown elements or not
//if (element_min_items > i) {
//new_div.html(object);
//new_div.addClass("expanded");
//}
//else {
//new_div.addClass("collapsed");
//}
element.addClass("collapsed");
if (element.find(".last-item").length > 0)
{
element.find(".last-item").before(new_div);
}
else if (element.find(".target-item").length > 0)
{
element.find(".target-item").append(new_div);
}
else
{
element.append(new_div);
}
});
// add the content-ready class - calculations are started once all extending divs have content ready
element.addClass("content-ready");
if ($(".extending-content").not(".content-ready").length == 0)
{
mdpi_column_height_module.setVariable("extendingContentsReady", true);
mdpi_column_height_module.calculateColumnHeights(true);
}
}
});
}
});
/**
* checkbox change state handling for select-all checkboxes
*/
$(":checkbox").change(function(e)
{
var select_all_name = $(this).data('select-all');
if (select_all_name)
{
var status = $(this).is(":checked");
$(":checkbox").each(function(e)
{
if ($(this).data('select-all-name') === select_all_name || $(this).data('select-all') === select_all_name)
{
$(this).prop("checked", status);
}
});
}
});
$("#js-home-journal-select").on("change", function(e) {
window.location.assign("/journal/"+$(this).val());
});
/***********************************************************************************
* Captcha dialog handling
**********************************************************************************/
$('body').on('click', '#reloadCaptcha', function()
{
var img = $(this).prev('img');
var imgSrc = img.attr('src').split('?')[0];
img.attr('src', imgSrc + '?' + (new Date()).getTime());
});
function getEmailCaptchaData(element) {
var params;
if (element.data("author-id"))
{
params = "?author_id=" + element.data("author-id");
}
else if (element.data("editor-id"))
{
params = "?editor_id=" + element.data("editor-id");
}
else if (element.data("user-id"))
{
params = "?user_id=" + element.data("user-id");
}
else if (element.data("reviewer-id"))
{
params = "?reviewer_id=" + element.data("reviewer-id");
}
else
{
params = "?email_prefix=" + element.data("email-prefix");
}
if (element.data("email-cc"))
{
params += "&email_cc=" + element.data("email-cc")
}
return params;
}
// email link click event - show captcha if needed
$(document).on("click","a.toEncode.emailCaptcha", function (e) {
e.stopImmediatePropagation();
var emailLink = $(this);
if (emailLink.attr('href').indexOf("@") < 0)
{
e.preventDefault();
var param = getEmailCaptchaData(emailLink);
var captcha = $("#captchaModal");
captcha.load("/email/captcha" + param, function(data)
{
// force reload the captcha at beginning
var href= $(this).find(".captcha_reload").prop("href");
var regexp = /(?:javascript:)(.*)(?:\()/;
window[regexp.exec(href)[1]]();
captcha.foundation('reveal', 'open');
});
}
});
// handle the captcha form submit
$("#captchaModal").on("submit", "#emailCaptchaForm", function (e)
{
e.preventDefault();
var form = $(this);
var params;
if ($("#authorId").val())
{
params = "?author_id=" + $("#authorId").val()
}
else if ($("#editorId").val())
{
params = "?editor_id=" + $("#editorId").val()
}
else if ($("#userId").val())
{
params = "?user_id=" + $("#userId").val();
}
else if ($("#reviewerId").val())
{
params = "?reviewer_id=" + $("#reviewerId").val();
}
else
{
params = "?email_prefix=" + $("#emailPrefix").val()
}
if ($("#emailCC").val()) {
params += "&email_cc=" + $("#emailCC").val()
}
$.post(
form.attr('action') + params,
form.serialize(),
function (data)
{
if (data.succ)
{
$("#captchaModal").foundation('reveal', 'close');
e.preventDefault();
var param = data.email;
var type = data.type;
var confirm = $("#captchaConfirmEmailModal");
confirm.load("/email/captcha_confirmation", { email: param, type: type, _token: data.csrf }, function(data) {
if ("[]" !== data) {
confirm.foundation('reveal', 'open');
}
});
/*window.location____ = "mailto:" + data.email;*/
}
else
{
$("#errorMsg").show();
/* console.log("#",image_id);*/
/* console.log(imageId = $imgcaptcha.attr("href").split("captcha_")[0]);*/
var $refreshcaptcha = form.find("a.captcha_reload"),
imageId = $refreshcaptcha.attr("href").split('javascript:reload_captcha_')[1].split('(')[0];
console.log(imageId);
window['reload_captcha_' + imageId]();
}
}
);
});
// handle the captcha alert
$('.genericCaptcha').click(function(e)
{
var form = $(this).closest("form");
var email = form.find("input[type='email']");
if (form.length > 0) {
if (email.val().indexOf('@') > 0)
{
e.preventDefault();
$("#captchaModal").load('/alert/captcha/' + form.prop("id"), function(data)
{
// force reload the captcha at beginning
var href= $(this).find(".captcha_reload").prop("href");
var regexp = /(?:javascript:)(.*)(?:\()/;
window[regexp.exec(href)[1]]();
return $("#captchaModal").foundation("reveal", "open");
});
}
else
{
return;
form.submit();
}
}
});
// handle the captcha access restriction
$('.accessCaptcha').click(function(e)
{
e.preventDefault();
var target = $(this).data("target");
$.post(
'/access/captcha/check/' + target,
function (data) {
if (data.succ) {
window.location____ = data.url;
}
else {
$("#captchaModal").load('/access/captcha/' + target, function(data) {
// force reload the captcha at beginning
var href= $(this).find(".captcha_reload").prop("href");
var regexp = /(?:javascript:)(.*)(?:\()/;
window[regexp.exec(href)[1]]();
return $("#captchaModal").foundation("reveal", "open");
});
}
}
);
});
// handle the captcha form submit
$("#captchaModal").on("submit", "#accessCaptchaForm", function (e)
{
e.preventDefault();
var form = $(this);
var params;
$.post(
form.attr('action'),
form.serialize(),
function (data)
{
if (data.succ)
{
$("#captchaModal").foundation('reveal', 'close');
window.location____ = data.url;
}
else
{
$("#errorMsg").show();
var refreshcaptcha = form.find("a.captcha_reload");
var imageId = refreshcaptcha.attr("href").split('javascript:reload_captcha_')[1].split('(')[0];
window['reload_captcha_' + imageId]();
}
}
);
});
// handle the captcha alert form
$("#captchaModal").on("submit", "#alertCaptchaForm", function (e)
{
e.preventDefault();
var form = $(this);
$.post(
form.attr('action'),
form.serialize(),
function (data)
{
if (data.succ)
{
$("#captchaModal").foundation("reveal", "close");
var origForm = $("#" + data.form);
origForm[0].submit();
}
else
{
$("#errorMsg").show();
}
}
);
});
/*****
* Article listing exporting functionality showing/hiding
*/
$("a.export-options-show").click(function(e)
{
e.preventDefault();
var listing = $(this).closest(".article-listing");
listing.find("div.article-content, .export-element").toggleClass("export-expanded");
$(document).foundation('equalizer', 'reflow');
});
$(".accordian-link").click(function(e)
{
e.preventDefault();
var target = $(this).data('target');
$('#' + target).toggle();
$(this).find('span').toggle();
$(document).foundation('equalizer', 'reflow');
});
/**
* Popupgallery
*/
$(document).on("click", '.abstract-figures-show', function(e)
{
e.preventDefault();
var abstractImagePreview = $(this).next(".abstract-image-preview");
abstractImagePreview.find(".openpopupgallery.cycle-slide img").each(function(e)
{
$(this).prop("src", $(this).data("src"));
});
$(this).find("span").toggle();
abstractImagePreview.toggle();
$(document).foundation('equalizer', 'reflow');
});
$('.popupgallery').each(function() {
$(this).magnificPopup({
type: 'image',
delegate: 'a',
index: 2,
image: {
verticalFit: false
},
gallery: {
enabled: true
}
});
});
$(document).on("click", '.js-browse-figures .openpopupgallery', function(){
var target = $(this).data('target');
$('#' + target + '.popupgallery').magnificPopup('open');
});
/*
$(document).on("click", '.abstract-image-preview .openpopupgallery', function(){
var target = $(this).data('target');
var index = $(this).data('imgindex');
$('#' + target + '.popupgallery').magnificPopup('open');
$('#' + target + '.popupgallery').magnificPopup('goTo', index);
});
*/
/* TODO: can be removed once the old versions are removed form cache */
$("a.js-author-card__biography-item").on("click", function(e) {
e.preventDefault();
e.stopPropagation();
$(this).closest(".author-card__biography").find(".js-author-card__biography-item").toggle();
});
$("a.js-profile-card__biography-item").on("click", function(e) {
e.preventDefault();
e.stopPropagation();
$(this).closest(".profile-card__biography").find(".js-profile-card__biography-item").toggle();
});
$("#main-content").on('click', '[data-counterslink]', function(e) {
$.ajax({
url: $(this).data('counterslink')
});
});
$(document).on("click", ".rss-link", function(e) {
e.preventDefault();
$('#rssNotificationModal .js-rss-notification-confirm').attr("href", $(this).attr("href"));
$('#rssNotificationModal').foundation('reveal','open');
});
/* TODO: can be removed once the old versions are removed form cache */
$(".author-card-drop").on("mouseover", function(e) {
if ("false" === $(this).attr("aria-expanded")) {
var cardContent = $("#" + $(this).attr("data-dropdown"));
cardContent.find(".js-default-open").show();
cardContent.find(".js-default-closed").hide();
}
});
$(".profile-card-drop").on("mouseover", function(e) {
if ("false" === $(this).attr("aria-expanded")) {
var cardContent = $("#" + $(this).attr("data-dropdown"));
cardContent.find(".js-default-open").show();
cardContent.find(".js-default-closed").hide();
}
});
/**
* Tablesorter addition to work with equalizer
*/
$("table").on("keyup", ".filters .filter", function() {
setTimeout(function() {
$(document).foundation('equalizer', 'reflow');
}, 200);
});
/**
* back to top button
*/
$(window).scroll(function() {
if ($(this).scrollTop() > 220) {
$('.back-to-top').fadeIn(500);
} else {
$('.back-to-top').fadeOut(500);
}
});
$('.back-to-top').click(function(event) {
event.preventDefault();
$('html, body').animate({scrollTop: 0}, 500);
return false;
})
$(".image-set-row__thumb-images").on("click", "img", function(e) {
var parentRow = $(this).closest(".image-set-row");
parentRow.find(".image-set-row__main-image img").attr("src", $(this).attr("src"));
});
$(".js-div-toggle").click(function(e) {
e.preventDefault();
$($(this).data("targetdiv")).toggle();
});
});
function handleJournalActiveBasedLinks(journalName, link, event, isPublic, isAcceptingSubmissions, isDiscontinued) {
var msg = "";
if (isDiscontinued) {
msg = ""+journalName+" is discontinued: " + link.data("disabledmessage");
}
else if (!isAcceptingSubmissions && link.hasClass("js-journal-active-only-submit-link")) {
msg = ""+journalName+" journal does not accept new submissions";
}
if ("" !== msg) {
event.preventDefault();
event.stopImmediatePropagation();
$("#js-action-disabled-modal-submit").toggle(link.hasClass("js-journal-active-only-submit-link"));
$("#js-action-disabled-modal-text").html(msg);
$('#actionDisabledModal').foundation('reveal','open');
}
}
$.scrollToElement = function(element, speed) {
if (speed == null) {
speed = 500;
}
return $('html, body').animate({
scrollTop: element.offset().top
}, speed);
};
$.fn.extend({
scrollToError: function() {
var formFirstError;
formFirstError = $(this).find('.element.error:visible').first();
if (formFirstError && formFirstError.length > 0) {
return $.scrollToElement(formFirstError);
}
}
});