From 62d479674145af2882aa4cad1d7a6a4a22ded4c1 Mon Sep 17 00:00:00 2001 From: zmagod Date: Mon, 9 Jul 2018 15:40:52 +0200 Subject: [PATCH] adds the ability to scroll to the active element in the navigation sidebar on page load [fixes SCI-2492] --- app/assets/javascripts/sidebar.js.erb | 456 +++++++++++++------------- 1 file changed, 232 insertions(+), 224 deletions(-) diff --git a/app/assets/javascripts/sidebar.js.erb b/app/assets/javascripts/sidebar.js.erb index 1845e7989..4ba1f43f3 100644 --- a/app/assets/javascripts/sidebar.js.erb +++ b/app/assets/javascripts/sidebar.js.erb @@ -1,244 +1,249 @@ -/** - * The functions here are global because they need to be - * accesed from outside (in reports view). - */ +(function(global) { + /** + * 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_TREE_KEY = "scinote-sidebar-tree-collapsed-ids"; -/** - * 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); + /** + * Get all collapsed sidebar elements. + * @return An array of sidebar element IDs. + */ + global.sessionGetCollapsedSidebarElements = function() { + var val = sessionStorage.getItem(STORAGE_TREE_KEY); + if (val === null) { + val = "[]"; + sessionStorage.setItem(STORAGE_TREE_KEY, val); } - } 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); + return JSON.parse(val); } - if ( index !== -1 ) { - item.ids.splice(index, 1); + /** + * Collapse a specified element in the sidebar. + * @param id - The collapsed element's ID. + */ + global.sessionCollapseSidebarElement = function(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)); } -} -/** - * Recalculate the position of the elements after an experiment - * is added or archived. - */ -function recalculateElementsPositions(ids, item, elements) { - var diff; + /** + * Expand a specified element in the sidebar. + * @param id - The expanded element's ID. + */ + global.sessionExpandSidebarElement = function(project, id, elements) { + var ids = sessionGetCollapsedSidebarElements(); + var item = _.findWhere(ids, { prid: project}); + var index = -1; - 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 ) { + index = _.indexOf(item.ids, id); + recalculateElementsPositions(ids, item, elements); + } - if ( item.eleNum !== elements) { - item.eleNum = elements; - sessionStorage.setItem(STORAGE_TREE_KEY, JSON.stringify(ids)); - } -} - -/** - * 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", I18n.t('sidebar.branch_expand')) - .removeClass("expanded"); - } else { - if (animate) { - children.show("fast"); - } else { - children.show(); - } - el - .find(" > span i") - .attr("title", I18n.t('sidebar.branch_collapse')) - .addClass("expanded"); + if ( index !== -1 ) { + item.ids.splice(index, 1); + sessionStorage.setItem(STORAGE_TREE_KEY, JSON.stringify(ids)); } } - // Add triangle icons and titles to every parent node - $(".tree li:has(ul)") - .addClass("parent_li") - .find(" > span i") - .attr("title", I18n.t('sidebar.branch_collapse')); - $(".tree li.parent_li ") - .find("> span i") - .removeClass("no-arrow") - .addClass("glyphicon glyphicon-triangle-right expanded"); + /** + * Recalculate the position of the elements after an experiment + * is added or archived. + */ + global.recalculateElementsPositions = function(ids, item, elements) { + var diff; - // 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 stored 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")); + 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; + }); } - e.stopPropagation(); - return false; - }); - // Add bold style to all levels of selected element - $(".tree li.active ") - .parents('.parent_li[data-parent="candidate"]') - .find("> span a") - .css("font-weight", "bold"); - - // Add custom borders to tree links - $(".tree li span.tree-link ").after("
"); -} - -// Resize the sidebar to accomodate to the page size -function resizeSidebarContents() { - var tree = $("#sidebar-wrapper .tree"); - - // Set vertical scrollbar on navigation tree - if (tree.length && tree.length == 1) { - tree.css( - "height", - ($(window).height() - tree.position().top - 50) + "px" - ); + if ( item.eleNum !== elements) { + item.eleNum = elements; + sessionStorage.setItem(STORAGE_TREE_KEY, JSON.stringify(ids)); + } + } + + /** + * Setup the sidebar collapsing & expanding functionality. + */ + global.setupSidebarTree = function() { + 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", I18n.t('sidebar.branch_expand')) + .removeClass("expanded"); + } else { + if (animate) { + children.show("fast"); + } else { + children.show(); + } + el + .find(" > span i") + .attr("title", I18n.t('sidebar.branch_collapse')) + .addClass("expanded"); + } + } + + // Add triangle icons and titles to every parent node + $(".tree li:has(ul)") + .addClass("parent_li") + .find(" > span i") + .attr("title", I18n.t('sidebar.branch_collapse')); + $(".tree li.parent_li ") + .find("> span i") + .removeClass("no-arrow") + .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 stored 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; + }); + + // Add bold style to all levels of selected element + $(".tree li.active ") + .parents('.parent_li[data-parent="candidate"]') + .find("> span a") + .css("font-weight", "bold"); + + // Add custom borders to tree links + $(".tree li span.tree-link ").after("
"); + } + + // Resize the sidebar to accomodate to the page size + global.resizeSidebarContents = function() { + var tree = $("#sidebar-wrapper .tree"); + + // Set vertical scrollbar on navigation tree + if (tree.length && tree.length == 1) { + tree.css( + "height", + ($(window).height() - tree.position().top - 50) + "px" + ); + } + } + + function scrollToSelectedItem() { + var offset = $('#slide-panel .active').offset().top - 50; + $('#slide-panel .tree').scrollTo(offset, 10); } -} -(function () { // Initialize click listeners setupSidebarTree(); @@ -252,5 +257,8 @@ function resizeSidebarContents() { // Bind onto window resize function $(window).resize(function() { resizeSidebarContents(); + scrollToSelectedItem() }); -}()); + + $(document).ready(scrollToSelectedItem); +})(window);