reptile7's JavaScript blog
Sunday, October 28, 2012
 
Drag to Resize, Part 2
Blog Entry #268

We return now to our analysis of the Changing Wrapping Width Example of Netscape's Dynamic HTML in Netscape Communicator resource.

Event, revisited

We previously dealt with mousemove capture at the level of the document object in our discussion of the HTML Goodies JavaScript Script Tip #91 Script in Blog Entries #107 and #108. In the Mozilla/W3C compatibility section of the latter entry I wrote in part:
Event (with a capital E) is not a reference for the event object that we've been variabilizing as ev; rather, Event is some sort of behind-the-scenes constructible core object: typeof Event returns function and document.write(Event) outputs a function Event() { [native code] } string [upon collapsing excess white space]. You won't find anything about Event, whatever it is, in any of Netscape's or Mozilla's materials; my bet is that, like the captureEvents( ) method, Event is now obsolete.
That was back when I was working in the 'Classic Mac realm', so I thought it prudent to rerun a window.alert(Event); test with the modern GUI browsers on my Intel Mac to see if any of them recognized the Event function: all of them did, variously returning [object Event], function Event() { [native code] }, [object EventConstructor], or [Event]. Rerunning the typeof Event test gave function with most of these browsers but did give object with Safari, which inspired me to go after Event with a for...in loop. (Although every function in JavaScript is a Function object, my attempts to probe other typeof-designated functions with a for...in loop have been uniformly unsuccessful.)

So it would seem that Event is not so obsolete after all. Indeed, in the course of looking up the captureEvents( ) method at the Dottoro Web Reference I learned that Event now references the Event interface of the Events DOM and that MOUSEDOWN, MOUSEMOVE, etc. are nonstandard "constants" of that interface; in corroboration, the Event interface's three standard constants - CAPTURING_PHASE, AT_TARGET, and BUBBLING_PHASE - always show up in my result += "Event." + i + " = " + Event[i] + "<br>"; for...in output, regardless of browser.

There's more I could say about this Event constant business, but given its dubious utility, let's just move on, shall we?

In practice

Both versions of the original example work well with Netscape 4.x for the most part. However, I find that Netscape 4.x's onmouseup support is a bit buggy: on occasion when I mouseup over the Netscape Communicator heading or one of the paragraphs, the enddrag( ) function is not called and the layer1 layer and its contents continue to expand or contract in response to mousemoves in the layer1 content area. Perhaps this is a result of the particular version of Netscape that I'm using (Communicator 4.61), it could be a Mac thing, maybe the Netscape guys themselves observed this and swept it under the rug, I don't know.

Modernize it

Go here to access the demo at the beginning of the previous entry - check the page source for the full coding.

Coding the example for modern browsers* is easier than it is for Netscape 4.x for the following reasons:
(a) Per the HTML 4.01 Specification, modern browsers allow us to bind onmousemove to a div element.
(b) Modern browsers support event bubbling and thus do not need to capture the mousedown, mousemove, and mouseup events, which all bubble.
(*And more than a few not-so-modern browsers: (a) and (b) are true for IE 4+ and Netscape 6+.)

To straddle the Netscape/Microsoft event model 'divide' we can:
(1) use an e = e ? e : event; conditional statement to give an event object a common e identifier for both event models; and
(2) replace e.pageX with e.clientX. (We are only interested in relative e.clientX readings and consequently it is unnecessary to 'correct' those readings by adding document.body.scrollLeft to them even if the document width exceeds the viewport width.)
(1) and (2) are needed for IE 5-8 users; IE 9+ supports the Netscape-cum-W3C event model and the pageX property - as of this writing, pageX is not standard but is on track to be added to the Events DOM's MouseEvent interface.

var layer1 = document.getElementById("layer1"), oldX;
layer1.onmousedown = begindrag;
function begindrag(e) {
    e = e ? e : event;
    oldX = e.clientX;
    layer1.onmousemove = drag; }


As for the example's HTML, I kept the wrapcss.htm layer1 div element and loaded the mytext.htm body element content - the hr element, the h1 element, the p element text - into it. The mytext.htm h1/p stylings were also brought into the main document.

The layer1 div element is the containing block for its constituent elements and thus sets the wrapping width for those elements. We can change the div's wrapping width by writing its style.width property:

var layerWidth = 300;
function drag(e) {
    e = e ? e : event;
    layerWidth = (layerWidth + e.clientX - oldX);
    layer1.style.width = layerWidth + "px";
    oldX = e.clientX; }


I saw no point in having separate drag( ) and changeWidth( ) functions so I brought the changeWidth( ) operations into the drag( ) function.

In theory, we should be able to change the wrapping width of the layer1 layer with a corresponding

document.ids.layer1.width = layerWidth + "px";

statement; in practice, document.ids.layer1.width can be read but not written - that's why we used the layer object's load( ) method for this operation.

Finally, here's my enddrag( ) code:

layer1.onmouseup = enddrag;
function enddrag(e) { layer1.onmousemove = null; }


The original enddrag( ) function disconnects mousemoves from the drag( ) function by setting layer1.onmousemove to 0; I set it to null because a top-level for...in probe of the layer1 div features a layer1.onmousemove = null line in its output with Firefox and Opera. Moreover, a top-level typeof layer1.onmousemove test returns object with newer browsers and undefined with some older browsers but in no cases does it return number. The original enddrag( )'s releaseEvents( ) operation is not relevant to modern browsers: our mousemoves are going to be dispatched come what may and we're not capturing them anyway.

And that concludes our tour of the DHiNC examples. What's next to go under the microscope? Right now I've got my eye on the JavaScript sector of Lissa Explains It All, which contains several scripts that (a) have cool effects but (b) are alleged to be "IE only" (not, as we'll see) - sounds right up our alley, eh? So that's what we'll tuck into in the following entry, beginning with the "snow fall on my Web page" script.

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)