Trouble attempting to create a custom vertical scrollbar / slider

W

weston

I'm making a foray into trying to create custom vertical scrollbars and
sliders, and thought I had a basic idea how to do it, but seem to be
having some trouble with the implementation.

My thinking was:

(a) create a div for the slider / scroll nub to move within
(b) attach event handlers which, onmousedown, specify the slider/nub is
moveable, and onmouseup, specify it's not
(c) attach an event handler to the contaning div which, onmousemove,
checks to see if the slider/nub is moveable, and if it is, bring it to
the y-coordinate of the mouse within the containing div

Here's an implementation... that sortof works:

http://localhost/additional/ScrollBar/testscroll.html

You can see that if you mousedown on the nub and try to drag it, it
moves *just a little bit*... and then stops.

My code looks something like this (full listing available via view
source):

nubArea = document.getElementById('nubAreaDiv');
scrollNub = document.getElementById('scrollNubImg');
scrollNub.mobile = false;
scrollNub.onmousedown = function () { this.mobile = true; }
scrollNub.onmouseup = function () { this.mobile = false; }
scrollNub.onmouseout = function () { this.mobile = false; }
nubArea.onmousemove = function (e) {
if(scrollNub.mobile) {
coords = getMouseCoordsWithinEventTarget(e);
scrollNub.style.top = coords.y;
} }


I thought maybe having an onmouseout event on the nub which cancels its
motion might have be the problem, so I moved that event onto the
containing div by changing that line to:

nubArea.onmouseout = function () { scrollNub.mobile = false; }

That didn't seem to make any difference.

So I tried taking it out altogether:


http://weston.canncentral.org/web_lab/ScrollBar/testscroll-var2.html

That seems to change the behavior -- you do see some movement of the
scrollNub, but it's jumpy and more than a little wonky. Releaseing the
mouse click doesn't seem to stop movement. When the nub is moving, it
seems to jump back and forth between the top and the mouse position.

I'm thinking there's something I'm missing about how events are being
fired and caught, but I'm open to any feedback. Thanks!
 
S

Stephen Kellett

In message said:
I'm making a foray into trying to create custom vertical scrollbars and
sliders, and thought I had a basic idea how to do it, but seem to be
having some trouble with the implementation.

Why reinvent the wheel? - take a look at script.aculo.us - this is
already done for you.

I think you'll find the only person that can see that is you. localhost
is by definition on the machine you are using and not visible to anyone
else.

Stephen
 
W

weston

Stephen said:
localhost is by definition on the machine you are using and not visible to anyone
else.

Very, very true, and I really, really meant to post the non-local link:

http://weston.canncentral.org/web_lab/ScrollBar/testscroll.html
Why reinvent the wheel? - take a look at script.aculo.us - this is
already done for you.

I've certainly considered using scriptaculous. It can certainly save me
time.... but I'm not sure it can help me find out where my
misconceptions are. Hence my coming here to ask questions about my
non-working solution. :)
 
R

Richard Cornford

weston said:
I'm making a foray into trying to create custom vertical
scrollbars and sliders, and thought I had a basic idea
how to do it, but seem to be having some trouble with
the implementation.

My thinking was:

(a) create a div for the slider / scroll nub to move within
(b) attach event handlers which, onmousedown, specify the
slider/nub is moveable, and onmouseup, specify it's not

It would be a good idea for the handler that stops process to also carry
out a final positioning action so that your 'nub' doesn't stop short of
the user's intended final position.
(c) attach an event handler to the contaning div which,
onmousemove, checks to see if the slider/nub is moveable,
and if it is, bring it to the y-coordinate of the mouse
within the containing div

Remember that the mosemoeve events are generated with _every_ pixel to
pixel transition so attempting to have the browser do any significant
number of calculations and re-draw the display at that rate can be
problematic.

My preferred pattern for this type of thing is along the lines of:-

1. Import animation timer and an efficient page-relative mouse
position reporting scripts (search the group's archive (at, for
example, google groups) for "TimedQue" and "MoveFollow" in posts
by me for examples of both (they have evolved over time so look
for the most recent source)).
2. Onmousedown in the container; flag 'dragging' as active and attach
a document-level onmouseup handler to stop the dragging (so any
mouse-up on the page will stop the process). (for IE it is also
useful to start a document-level onselectstart handler that
cancels the default action of drag selection). Finally a
positioning function is registered with the animation timer
component, that uses the difference between the current
page-wide mouse co-ordinates and the element's page co-ordinates
to work out where the nub is supposed to be placed and places it
there (this function is only triggered at 40+ millisecond
intervals as that is good enough for user interaction and
infrequent enough that the browser (usually) does not get bogged
down trying to keep up).

My TimedQue component keeps executing its function arguments at
intervals until the function returns false (or, while it doesn't return
true). The positioning function then returns the 'dragging' flag so that
it will keep being executed at intervals until the mouseup event re-sets
the flag to false. The positioning function takes the form:-

function potion(){
if(dragging){
/*
Work out the mouse's position relative to the container
using the page-wide mouse positing reporting facility
(the page co-ordinates of the element only need to be
worked out onmousedown and stored at that point) and
potion the 'nub' t that point.
*/
}
return dragging;
}

The mouse up function does (in order):-

1. Remove the document-level mouseup listener (and the onselectstart,
and any other pertinent, listeners).
2. Directly calls the - position - function, so that the 'nub' is in
the correct final position.
3. Sets the 'dragging' flag back to false. (the animation component
drops the position function as a result)

Here's an implementation... that sortof works:

http://localhost/additional/ScrollBar/testscroll.html

Even if that URL worked I would not look at it. You have a situation
that is simple enough to be presented here as the code for a fully
'working' a cut-down test case that demonstrates the issue in isolation.
And external link to the same demonstration on-line may satisfy the
preferences of some but I read Usenet off-line and will not re-connect
to the Internet just to look at source code.
You can see ...
<snip>

Two assumptions too far.
My code looks something like this (full listing available
via view source):

nubArea = document.getElementById('nubAreaDiv');
scrollNub = document.getElementById('scrollNubImg');
scrollNub.mobile = false;
scrollNub.onmousedown = function () { this.mobile = true; }
scrollNub.onmouseup = function () { this.mobile = false; }
scrollNub.onmouseout = function () { this.mobile = false; }
nubArea.onmousemove = function (e) {
if(scrollNub.mobile) {
coords = getMouseCoordsWithinEventTarget(e);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Two (at least) elements may be originating mosemove events that bubble
up to your - nubArea - element. So even if your -
getMouseCoordsWithinEventTarget - produces reliable offsets when the
mouse is moving over the 'nub' the generated Y offset will be the offset
over the 'nub' and when it is outside the 'nub' it will be the offset
from the - nubArea - element. As the handler than moves the 'nub' to the
offset all offsets from the - nubArea - should move the 'nub' under the
mouse, and then offsets over that area may move the 'nub' towards the
top of its container. The result will likely be jittery.

You probably want to forget about offsets from targets and only be
calculating offsets from the - nubArea - element (so the event's
(possible) built-in target offset properties will not help here).
scrollNub.style.top = coords.y;
}
}
<snip>

If you are not already familiar with the issue, it would be a good idea
for you to do some research into the "IE memory leak problem" (google
for it) as this script does produce the 'circular' reference chains that
are at the root of the issue.

Incidentally, the reason for learning to do this for yourself, rather
than using other people's scripts, is that if you do not know how to do
it for yourself you are not going be in a position to judge whether a
third party script is suitable. Will have to trust its author to have
seen and properly addressed all the issues, and will find yourself
limited in what you can achieve by the availability of third party
scripts (that is, you will never be employable as a javascript author).

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top