weston wrote:[color=blue]
> 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[/color]
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.
[color=blue]
> (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[/color]
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)
[color=blue]
> Here's an implementation... that sortof works:
>
>
http://localhost/additional/ScrollBar/testscroll.html[/color]
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.
[color=blue]
> You can see ...[/color]
<snip>
Two assumptions too far.
[color=blue]
> 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);[/color]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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).
[color=blue]
> scrollNub.style.top = coords.y;
> }
>}[/color]
<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.