// 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); } } });