I don't want to give away too much about the project, but I ended up building a diagramming system that let users add and remove elements in a graphical hierarchy and see the relationships between them. All of this was done entirely in the browser - no going back to the server and its friendly relational database and Ruby code - and it turned out quite nicely. The diagram could get quite large, though, so we decided that you should be able to scroll around in it a bit like how Google Maps works.
You can see a scrolling example here, and "View Source" to see all of the code involved.
In this case, the framing window is a div called "main-window" and the internal part that scrolls is another div called "scrolling-section". Here it contains a picture as a background image, but it could contain other divs or a table or text or whatever. I set a starting offset for the "top" and "left" values so we see the middle of the picture, not the top corner.
To start with, we set up a few global variables for the page - these keep track of where you started dragging around, where your mouse is, whether the mouse button is being held down, and where the limits are for the scrolling:
When the user clicks down anywhere inside the inner div, it calls the "setClickPos" function:
Here we set a number of the global variables for our starting information. The click event itself holds the coordinates that were clicked, and we store these in "clickposx" and "clickposy". We also get the width and height of the framing div and the current div so we can calculate the bottom and right limits for our scrolling (the top and left limits are of course 0). We then set the flag that says whether the mouse is down or not. The mouseup function is really simple: "ismousedown = false;" - it just lets the page know that we've finished dragging.
The tricky part is in the moveTarget function:
This function could be made a bit shorter, but I like to break out my calculations into separate lines, since it makes it easier to follow and easier to debug: if you're doing everything in one line, and there's an error in that line, it's trickier to figure out where the problem is. The first thing we do is check our flag to see if the mouse is down or not. If the mouse is down, then we figure out the current mouse position and subtract the original click position from it to find the distance that we've dragged since we clicked. We then figure out the left and top offsets we'll need to apply to the div. Before we do that, though, we check to make sure we're not dragging out of bounds - this looks uglier than it actually is, since the offset positions are negative.
Then we call the simple "moveToPosition" function:
Here we change the position back to a string with the appropriate "px" suffix.
While I was working on this, I would often stop and just move the diagram around a bunch with the mouse and watch it scrolling - it just looked so cool! Now you can do it to.