DHTML: Dynamic Navigation through DOM element with scrollTop


I had a task to implement vertical navigation by the long list of items which does not fit the browser window. It has to be hidden if list of items shorter than height of the window. Note also I has to use frames.




Okey, let's start. First, I disabled standard scrollbars within the window:

<style>
html,body { overflow: hidden; }
body { position: absolute; top: 0; left: 0; }
</style>

Then I disabled scrollbars in DIV area which should be navigated:


#taglist{ width:100%; overflow:hidden; }

Then I created DIV area with up/down buttons bound to right lower corner of the window. I wrote in CSS file:


.sbnav { position: absolute; bottom: 5px; right: 5px; text-align:right; background-color: #fbffba; padding:3px; }
.sbnav-up { margin-bottom: 6px; }
.sbnav-down { margin-top: 6px; }

and in HTML (the simpliest piece):

<div id="taglist"></div>

Couple more tricks in this work:
1. Shift displayed area. For this purpose I have to control scrollTop DOM property. I wrote two functions for that: sbNavUp() and sbNavDown()
2. I found very useful: setInterval and clearInterval on mouse events (onmousedown and onmouseup).

Below is Javascript implementation. You will also need graphics for up and down buttons, and some HTML to define DOM object to be navigated, and DOM object which contain navigation.
NOTE that I had to put 110 and 115 values because area which should be navigatable is lower (shorter) than whole size of frame (window).

So, HTML for navigation arrows looks like this:

<div class="sbnav" id="sbnav">
<a href="#" id="sbnav_up" title="Up"><img src="/static/images/nav_up.gif" alt="Up" height="7" slass="sbnav-up" width="14" /></a><br />
<a href="#" id="sbnav_down" title="Down"><img src="/static/images/nav_down.gif" alt="Down" height="7" class="sbnav-down" width="14" /></a> </div>

Javascript calls on HTML page:
window.onload = sbNavControl;
window.onresize = sbNavControl;

Thus, I show or hide buttons on window resize.

Javascript implementation:

getWindowHeight function is available under the link.

/** Sidebar navigation */

var navStep = 2; // in pixels
var navSpeed = 10; // in milliseconds

/** Navigate list of interests up */

function sbNavUp() {
try {
var taglistObj = top.frames['sidebarcontent'].document.getElementById('taglist');
var offset = taglistObj.scrollTop;
if (offset > navStep) taglistObj.scrollTop -= navStep;
else if (offset <= navStep && offset > 0) taglistObj.scrollTop = 0;
} catch(e) {jsErr(e)}
}

/** Navigate list of interests down */

function sbNavDown() {
try {
var taglistObj = top.frames['sidebarcontent'].document.getElementById('taglist');
var offset = taglistObj.scrollTop;
if (offset+navStep < taglistObj.scrollHeight) taglistObj.scrollTop += navStep;
else if (offset+navStep >= taglistObj.scrollHeight && offset < taglistObj.scrollHeight) taglistObj.scrollTop = taglistObj.scrollHeight;
} catch(e) {jsErr(e)}
}

/** Show/hide navigational buttons */

function sbNavControl() {
try {
var taglistObj = top.frames['sidebarcontent'].document.getElementById('taglist');
var sbnabObj = top.frames['sidebarcontent'].document.getElementById("sbnav");
if (!taglistObj || !sbnabObj) return;
// reset height to default
taglistObj.style.height = '';
// display/hide nav buttons
var taglistHeight = taglistObj.offsetHeight;
if (taglistHeight > getWindowHeight()-110) sbnabObj.style.display = '';
else sbnabObj.style.display = 'none';
// set height in order to make navigation work
taglistObj.style.height = (getWindowHeight()-115) + "px";

// onMouseDown and onMouseUp events
var btnUp = top.frames['sidebarcontent'].document.getElementById("sbnav_up");
var btnDown = top.frames['sidebarcontent'].document.getElementById("sbnav_down");
if (!btnUp || !btnDown) return;
var sbNavUpInterval = ''; var sbNavDownInterval = '';
function sbNavUpStart() { sbNavUpInterval = self.setInterval("sbNavUp()", navSpeed); }
function sbNavDownStart() { sbNavDownInterval = self.setInterval("sbNavDown()", navSpeed); }
function sbNavUpStop() { self.clearInterval(sbNavUpInterval); }
function sbNavDownStop() { self.clearInterval(sbNavDownInterval); }
btnUp.onmousedown = sbNavUpStart;
btnUp.onmouseup = sbNavUpStop;
btnDown.onmousedown = sbNavDownStart;
btnDown.onmouseup = sbNavDownStop;
} catch(e) {}
}

Comments

Popular posts from this blog

Data visualization for Roadmap Microsite (Angular and D3.js)

Conceptual design

Four tools for prototyping: Sketch, Figma, Principle, and FramerX