0

When using an accordion with big panes, selecting a pane will take you to its bottom content and leave the top content out off the screen's visibility. Forcing the user to scroll up each time when selecting a pane.

Is it possible to auto scroll to top of the pane content when selecting a pane?

Accordion available here: https://jsfiddle.net/4hqv4eao/4/

require([
    "dijit/layout/AccordionContainer",
    "dijit/layout/ContentPane",
    "dojo/ready"
  ],
  function(AccordionContainer, ContentPane, ready) {

    ready(function() {

      var acc = new AccordionContainer({}, "accordion");

      acc.addChild(new ContentPane({
        title: "Title 1",
      }, "pane1"));

      acc.addChild(new ContentPane({
        title: "Title 2",
      }, "pane2"));

      acc.addChild(new ContentPane({
        title: "Title 3",
      }, "pane3"));      

      acc.addChild(new ContentPane({
        title: "Title 4",
      }, "pane4"));        

      acc.startup();
    });

  });

1 Answer 1

1

Using a click function for each pane (I used a for loop and the className dijitAccordionInnerContainer), you can get the accordions y position (I used the function from here to get the exact y positon) and use javascripts scrollBy method.

Here's the function to get the exact positon (thanks to kirupa):

// Helper function to get an element's exact position
function getPosition(el) {
  var xPos = 0;
  var yPos = 0;

  while (el) {
    if (el.tagName == "BODY") {
      // deal with browser quirks with body/window/document and page scroll
      var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
      var yScroll = el.scrollTop || document.documentElement.scrollTop;

      xPos += (el.offsetLeft - xScroll + el.clientLeft);
      yPos += (el.offsetTop - yScroll + el.clientTop);
    } else {
      // for all other non-BODY elements
      xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
      yPos += (el.offsetTop - el.scrollTop + el.clientTop);
    }

    el = el.offsetParent;
  }
  return {
    x: xPos,
    y: yPos
  };
}

Here's the code I added to scroll to the top of the accordion:

var panes;
var pane;
panes = document.getElementsByClassName('dijitAccordionInnerContainer');

for (var i = 0; i < panes.length; i++) {
  panes[i].addEventListener('click', function(e) {
    pane = this;
    setTimeout(function() {
      window.scrollBy(0, getPosition(pane).y);
    }, 200);
  });
}

I used the setTimeout function so the accordion would be finished updating before getting it's position (there may be a better way for doing this).

Here's the updated fiddler.

3
  • The fix does not seem to be working when using the accordion with an iframe. More precisely it does not work if you provide a fix height to the iframe: web page test. It does work if you do not provide the fix height, but then again the iframe does not show the full content. Not sure where to go from here
    – Michelle
    Commented Jan 19, 2018 at 22:47
  • 1
    It's getting the position of the pane based on the iframe, then scrolling the window of the iframe. Since you are setting a fixed width of the iframe it will not scroll the iframe. In order for it to work in an iframe you'll need to get the position of the pane based on the parent of the iframe. To scroll the window, you'll need to do something like window.parent.scrollBy instead of window.scrollBy.
    – Anthony
    Commented Jan 22, 2018 at 16:04
  • Hmm I replaced window.scrollBy with window.parent.scrollBy but doesn't seem to have any effect: web page test2 for (var i = 0; i < panes.length; i++) { panes[i].addEventListener('click', function(e) { pane = this; setTimeout(function() { window.parent.scrollBy(0, getPosition(pane).y); }, 200); }); }
    – Michelle
    Commented Jan 23, 2018 at 9:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.