/** * The functions here are global because they need to be * accesed from outside (in reports view). */ var STORAGE_TREE_KEY = "scinote-sidebar-tree-collapsed-ids"; var STORAGE_TOGGLE_KEY = "scinote-sidebar-toggled"; /** * Get all collapsed sidebar elements. * @return An array of sidebar element IDs. */ function sessionGetCollapsedSidebarElements() { var val = sessionStorage.getItem(STORAGE_TREE_KEY); if (val === null) { val = "[]"; sessionStorage.setItem(STORAGE_TREE_KEY, val); } return JSON.parse(val); } /** * Collapse a specified element in the sidebar. * @param id - The collapsed element's ID. */ function sessionCollapseSidebarElement(project, id) { var ids = sessionGetCollapsedSidebarElements(); var item = _.findWhere(ids, { prid: project }); var collapsed = { prid: project, ids: [] }; var stored_projects = _.pluck(ids, 'prid'); if ( _.contains(stored_projects, project ) ){ if ( item && _.indexOf(item.ids, id) === -1 ) { _.findWhere(ids, { prid: project }).ids.push(id); } } else { collapsed.ids.push(id); ids.push(collapsed); } sessionStorage.setItem(STORAGE_TREE_KEY, JSON.stringify(ids)); } /** * Expand a specified element in the sidebar. * @param id - The expanded element's ID. */ function sessionExpandSidebarElement(project, id, elements) { var ids = sessionGetCollapsedSidebarElements(); var item = _.findWhere(ids, { prid: project}); var index = -1; if ( item ) { index = _.indexOf(item.ids, id); recalculateElementsPositions(ids, item, elements); } if ( index !== -1 ) { item.ids.splice(index, 1); sessionStorage.setItem(STORAGE_TREE_KEY, JSON.stringify(ids)); } } /** * Recalculate the position of the elements after an experiment * is added or archived. */ function recalculateElementsPositions(ids, item, elements) { var diff; if ( item.eleNum > elements ){ diff = item.eleNum - elements; _.map(item.ids, function(element, index){ item.ids[index] = element - diff; }); } else if ( item.eleNum < elements ) { diff = elements - item.eleNum ; _.map(item.ids, function(element, index){ item.ids[index] = element + diff; }); } if ( item.eleNum !== elements) { item.eleNum = elements; sessionStorage.setItem(STORAGE_TREE_KEY, JSON.stringify(ids)); } } /** * Get the session stored toggled boolean or null value if * sidebar toggle state was not changed by user. It allow for * automatic toggling for small devices. * * @return True if sidebar is toggled; false otherwise. */ function sessionIsSidebarToggled() { var val = sessionStorage.getItem(STORAGE_TOGGLE_KEY); if (val === null) { return null; } return val === "toggled"; } /** * Store the sidebar toggled boolean to session storage. */ function sessionToggleSidebar() { if (sessionIsSidebarToggled()) { sessionStorage.setItem(STORAGE_TOGGLE_KEY, "not_toggled"); } else { sessionStorage.setItem(STORAGE_TOGGLE_KEY, "toggled"); } } /** * Setup the sidebar collapsing & expanding functionality. */ function setupSidebarTree() { function toggleLi(el, collapse, animate) { var children = el .find(" > ul > li"); if (collapse) { if (animate) { children.hide("fast"); } else { children.hide(); } el .find(" > span i") .attr("title", "Expand this branch") .removeClass("expanded"); } else { if (animate) { children.show("fast"); } else { children.show(); } el .find(" > span i") .attr("title", "Collapse this branch") .addClass("expanded"); } } // Add triangle icons and titles to every parent node $(".tree li:has(ul)") .addClass("parent_li") .find(" > span i") .attr("title", "Collapse this branch"); $(".tree li.parent_li ") .find("> span i") .addClass("glyphicon glyphicon-triangle-right expanded"); // Add IDs to all parent var i = 0; _.each($('[data-parent="candidate"]'), function(el) { $(el).attr("data-toggle-id", i++); }); // Get the current project var project = $('[data-project-id]').data('projectId'); // Set number of elements sessionExpandSidebarElement(project, null, $('[data-parent="candidate"]').length ); // Get the session-stored elements var collapsedIds = sessionGetCollapsedSidebarElements(); // Get the current project stered elements var currentProjectIds = _.findWhere(collapsedIds, { prid: project }); if ( currentProjectIds ){ currentProjectIds.ids = _.filter(currentProjectIds.ids, function(val) { return val !== null; }).join(", "); // Collapse session-stored elements _.each($('li.parent_li[data-parent="candidate"]'), function(el) { var id = $(el).data("toggle-id"); var li = $(".tree li.parent_li[data-toggle-id='" + id + "']"); if( li.hasClass("active") || li.find(".active").length > 0){ // Always expand the active element toggleLi(li, false, false); } else if ( $.inArray( id.toString(), currentProjectIds.ids.split(", ")) !== -1 ) { // Expande element toggleLi(li, false, false); } else { // Collapse the session-stored element toggleLi(li, true, false); } }); } else { // Collapse all _.each($('li.parent_li[data-parent="candidate"]'), function(el) { var id = $(el).data("toggle-id"); var li = $(".tree li.parent_li[data-toggle-id='" + id + "']"); if( li.hasClass("active") ){ // Always expand the active element toggleLi(li, false, false); sessionCollapseSidebarElement(project, id); } else { // Element collapsed by default toggleLi(li, true, false); } }); } // Add onclick callback to every triangle icon $(".tree li.parent_li ") .find("> span i") .on("click", function (e) { var el = $(this) .parent("span") .parent("li.parent_li"); if (el.find(" > ul > li").is(":visible")) { toggleLi(el, true, true); sessionExpandSidebarElement(project, el.data("toggle-id"), $('[data-parent="candidate"]').length ); } else { toggleLi(el, false, true); sessionCollapseSidebarElement(project, el.data("toggle-id")); } e.stopPropagation(); return false; }); } /** * Initialize the show/hide toggling of sidebar. */ function initializeSidebarToggle() { var wrapper = $("#wrapper"); var toggled = sessionIsSidebarToggled(); if (toggled || toggled === null && $(window).width() < <%= Constants::SCREEN_WIDTH_LARGE %>) { wrapper.addClass("no-animation"); wrapper.addClass("toggled"); // Cause reflow of the wrapper element wrapper[0].offsetHeight; wrapper.removeClass("no-animation"); $(".navbar-secondary").addClass("navbar-without-sidebar"); } $("#toggle-sidebar-link").on("click", function() { $("#wrapper").toggleClass("toggled"); sessionToggleSidebar(); $(".navbar-secondary").toggleClass("navbar-without-sidebar", sessionIsSidebarToggled()); return false; }); } // Resize the sidebar to accomodate to the page size function resizeSidebarContents() { var wrapper = $("#wrapper"); var tree = $("#sidebar-wrapper .tree"); var toggled = sessionIsSidebarToggled(); var navbar = $(".navbar-secondary"); if (tree.length && tree.length == 1) { tree.css( "height", ($(window).height() - tree.position().top - 50) + "px" ); } // Automatic toggling of sidebar for smaller devices if (toggled === null) { if ($(window).width() < <%= Constants::SCREEN_WIDTH_LARGE %>) { wrapper.addClass("toggled"); navbar.addClass("navbar-without-sidebar"); } else { wrapper.removeClass("toggled"); navbar.removeClass("navbar-without-sidebar"); } } } (function () { // Initialize click listeners setupSidebarTree(); initializeSidebarToggle(); // Actually display wrapper, which is, up to now, // hidden $("#wrapper").show(); // Resize the sidebar automatically resizeSidebarContents(); // Bind onto window resize function $(window).resize(function() { resizeSidebarContents(); }); }());