reptile7's JavaScript blog
Wednesday, June 29, 2011
 
Magic Div Ride
Blog Entry #219

In today's post we will discuss HTML Goodies' "Hovering HTML Windows and Animated Hovering Using JavaScript" tutorial, which is authored by Jonathan Campbell. "Animated" is the operative word in the title of the tutorial (so we'll call it "Animated Hovering" going forward): à la the "How to Create a JavaScript Animation" tutorial (hereafter "JavaScript Animation") we covered not so long ago, "Animated Hovering" presents code for moving an HTML element across the viewport by iteratively incrementing its style.left and style.top properties. "Animated Hovering" is another Beyond HTML : JavaScript sector tutorial for which a separate entry is a bit of a judgment call; however, the tutorial's demo is missing, and when I encounter a missing demo, man, that's like waving a red cape in front of me, if you get my drift, so here we go.

The "window" and its contents

You may recall that the "JavaScript Animation" tutorial works with a ball.gif image; for its part the "Animated Hovering" tutorial works with an id="winbox1" span element. The author terms the winbox1 span a window, presumably because of its rectangular shape (and perhaps because of the partial border 'chrome' provided by its table element child), but this use of the term "window" rubs me the wrong way - "window" should be reserved for an actual browser window, IMO. As a positionable block of content, the winbox1 span is what Netscape would have called a layer back in the day, but given that Netscape itself abandoned the layer element/object in going from Netscape 4 to Netscape 6 (and that was over ten years ago, folks), maybe we should just call it a span, huh?

Now then, what do we have in that span? There is no limit with what you can actually put within the <SPAN [sic] window element, for the most part, the author alleges. In the tutorial, the author charges the span with a two-row table: the table's first row holds an img placeholder (whose src image is AWOL - see the winbox1 span image in the next section) and its second row contains a standard text string.

<table border="1" cellspacing="0" cellpadding="0">
<tr><td><img width="109" height="123" src="http://www.jdcampbell.com/demo2/anim2.gif" alt=""></td></tr>
<tr><td><font size="3" color="yellow"> This is some standard text, how do you like the dynamic <SPAN animation? </font></td></tr>
</table>


Are you ready to throw that red flag in your hands? The span element is an inline element - more precisely, it's one of the %inline; group of elements - and has an (%inline;)* content model, and therefore it shouldn't contain a block-level element such as a table element. If we're going to put the table in a container (and it really doesn't need one), then we should use a div element for that purpose.

Span style

The winbox1 span element markup is given below:

<span id="winbox1" style="position:absolute; top:50; left:50; height:190px; width:150px; background=blue;"> ... </span>

The start-tag is equipped with a style attribute that sets - well, should set - six CSS styles for the span. The first thing you'll notice is that the syntax for setting the background(-color) property is incorrect: it should be background:blue;. (In the tutorial comment thread, CodeMonkey pointed out this error almost two years ago - why hasn't it been fixed?) Second, the top and left values don't have unit identifiers, which is "illegal" (unless the values were 0); those top/left declarations should be ignored, although in practice the browsers on my computer interpret the 50s as 50pxs, which is almost certainly what the author intended (other units could be used here - e.g., mm or pt - but clearly px makes the most sense in this context). So I'm good to go and I would guess that most other users are also OK top/left-wise, but the safe thing to do is to specify top:50px; left:50px; to accommodate user agents that might be less forgiving in this regard.

The width and height declarations initially set off warning bells in my mind but are in fact legit. The width and height properties duly apply to block-level elements and also apply to what are called "replaced" elements - specifically, the object, img, iframe, and applet elements, which are all inline elements unless you set them otherwise - but do not normally apply to other inline elements such as the span element. (Ever the iconoclast, IE will let you apply width and height to non-replaced inline elements, but other browsers won't.) However, when a non-replaced %inline; element is absolutely positioned and thus completely removed from the normal flow of its document, it is no longer "inline" and can be given a width and height:

[The winbox1 span]
(The table height (201 pixels) exceeds the span height (190 pixels) per the original code.)

That said, a table-containing span element, positioned or not, will not pass through a validator without throwing an error, so if validation is an issue for you, then you should either exchange the span for a div or ditch it altogether.

Span movement

So, the winbox1 span's starting coordinates are (50px,50px), that is, its upper-left-hand corner is 50 pixels to the right of the document content area's left edge and 50 pixels below the document content area's top edge. The span is then sent on a checkmark-like trajectory (we'll roll out a demo in a little bit) via the following script:

var posx = 50; var posy = 350;
setInterval("MoveOver( );", 500);

function MoveOver( ) {
    posx += 50; posy -= 20;
    document.getElementById("winbox1").style.left = posx;
    document.getElementById("winbox1").style.top = posy; }


As for the "JavaScript Animation" ball.gif image, the winbox1 span motion is animated via a setInterval( ) command. The author doesn't mention that setInterval( ) is a method of the window object, nor that the first setInterval( ) argument can/should be specified in the form of a function pointer, i.e., window.setInterval(MoveOver, 500);, not that those are original sins on his part.

The first MoveOver( ) iteration chutes the span to (100px,330px); with each subsequent iteration the span shifts rightward by 50 pixels and upward by 20 pixels. No window.clearInterval( ) command stops the span when it hits or moves beyond the top/right edges of the viewport. Some browsers (IE, Safari, Chrome) seem to stop tracking the span once it's out of sight, but an added if (posy <= 0) window.alert(posx); conditional confirms that MoveOver( ) execution goes on and on and on.

Once again units are omitted for the left and top assignments. The code samples in "JavaScript Animation" get it right; in MoveOver( ) we should see:

document.getElementById("winbox1").style.left = posx + "px";
document.getElementById("winbox1").style.top = posy + "px";
/* In JavaScript, all CSS 2.1 property values have a string data type. */


At no point does the script actually read the span's left and top values; consequently, the span's initial position/left/top settings (plus its other styles) can alternatively be specified in an external or internal style sheet, which was off-limits for the left/top-reading code in "JavaScript Animation".

Demo
You can see the above code in action by clicking on this link.
After presenting its code the tutorial offers a link to a demo. Clicking the link leads to a http://ewisefirm.com/cmsfiles/jons-span1.html page that contains no trace of a demo or anything else related to the author. In addition, the http://www.jdcampbell.com/demo2/anim2.gif URL of the image that is supposed to be in the first row of the winbox1 span's table leads to a "404 Not Found" page.

I go to the Internet Archive in hopes of finding a past version of the tutorial with a functioning demo. "Animated Hovering" was first "crawled" by the Internet Archive on 5 December 2008; this tutorial crawl's this link goes to a page with a demo that is flawed - the anim2.gif image is missing and, less importantly, there's no blue background - but does basically work. The Internet Archive has no record of the anim2.gif image or of the demo2/ directory that ostensibly held it.

My own demo appears in the div below.

 
Demo notes • I have no idea what anim2.gif was an image of. The animated div in my demo alternatively sports an at_sign_rotating.gif image that I picked out at Webdeveloper.com's "Animated GIFs for Free Download" resource. • The author places the winbox1 span in a document whose body is delimited with a <page> ... </page> element, which is neither a standard element nor a proprietary Microsoft element nor a proprietary Netscape element - a sure sign that the code was written with an HTML editor. I've exchanged the page element for a relatively positioned div frame. • The original span document body begins with a series of This is a <SPAN dynamic HTML animation window-in-window example... headings, which are centered with center elements; moreover, the text in the span table's second row is marked up with a font element. (It's one thing to encounter the center and font elements in a circa-2000 script, but in a 2008 script? Oh dear.) I've thrown out the headings as they don't seem appropriate at this point. As for the font element, I've traded in its color="yellow" and size="3" attributes for color:yellow; and font-size:medium; style declarations, respectively. • An if (posy <= -190) window.clearInterval(timerID); conditional stops the animation when the bottom edge of the animated div reaches the top of the outer frame.
We won't discuss the next Beyond HTML : JavaScript sector tutorial, "So You Want To Open A Window, Huh?"; we've dealt with the window.open( ) topic ad nauseam and there's no need to revisit it. The following sector tutorial, "A Quick Tutorial on JavaScript Variable Passing", was covered in Blog Entries #193 and #194. The subsequent sector tutorial, "What's The Time? Using JavaScript to Localize Time Displays", is actually the first part of a four-part "JavaScript Date/Time Methods" series that is strangely no longer listed in the sector and that we went over in Blog Entry #171. After that is a "JavaScript for Programmers - Events" book excerpt - we'll do this one next time as it will give us the opportunity to nail down some 'event history' and look at an interesting drawing program example. reptile7

Saturday, June 18, 2011
 
Modular, Dynamic, Resources
Blog Entry #218

Next up in HTML Goodies' Beyond HTML : JavaScript sector are three tutorials that don't really deserve their own entries but that I wanted to comment on briefly.



"Creating a Modular JavaScript Toolbox"

Authored by Anthony Corbelli, this tutorial presents code for creating script elements and adding them to a head element on the fly in the name of incorporating .js "modules" into a main document.

var hHead = document.getElementsByTagName("head").item(0);
/* The head element is one of a small handful of elements that
cannot validly take the id attribute. */
function AddModule(mFileName) {
    var sTag = document.createElement("script");
    sTag.setAttribute("src", mFileName);
    sTag.setAttribute("type", "text/javascript");
    hHead.appendChild(sTag); }

AddModule("NewScript1.js");
AddModule("NewScript2.js");
AddModule("NewScriptEtc.js");


Maybe I'm missing something, but I fail to see the advantage in doing this vis-à-vis importing scripts in the normal way:

<script type="text/javascript" src="NewScript1.js"></script>
<script type="text/javascript" src="NewScript2.js"></script>
<script type="text/javascript" src="NewScriptEtc.js"></script>


That's it. Task accomplished. Go for a coffee break.



"Creating Dynamic Websites Using JavaScript"

Also authored by Anthony Corbelli, this tutorial presents code that dynamically sets some basic CSS properties (ground we broke very early on) for a series of div elements.
(1) The author first specifies a dynamic_style.css style sheet that statically sets the properties in question.
(2) Next is a dynamic_display.js script comprising four functions that separately change the
(a) background-color,
(b) color,
(c) width and height, or
(d) left and top
propert(y|ies) for a specific div element.
(3) The tutorial code concludes with an ourTestPage.html main document that specifies the div elements and their contents.

Some readers might conclude from the tutorial's opening paragraph that the tutorial code's operations date to the debut of JavaScript: in fact, JavaScript 1.0 and 1.1 provide no access at all to the div element*, whereas JavaScript 1.2-1.3's access to the div element via the layer and style objects is buggy (my attempts to dynamically set div styles via document.tags expressions when using Netscape 4.61 have been uniformly unsuccessful**, for example). Support for the code specifically goes back to IE 5 on the Microsoft side - it'd go back to IE 4 if you were to replace the document.getElementById references in the dynamic_display.js script with document.all references - and to Netscape 6 on the Netscape side.

*JavaScript 1.0 and 1.1 slightly predate HTML 3.2, which introduced the div element; however, there is no document.all-type mechanism in these versions of JavaScript that would allow access to new elements after the fact.

**The document.tags mechanism allows me to statically set the background color, foreground color, and width of a div element but not change those properties with event handlers.

Div elements (more generally, block-level elements) can be styled with most CSS properties and thus are a pretty safe choice for illustrating DHTML. For their part the background-color, color, and position and by extension left and top properties apply to all elements; the tutorial negligently does not mention that the width and height properties do not apply to non-replaced inline elements (e.g., span, a, em) under normal circumstances.

Regarding the dynamic_style.css style sheet, the author alleges, Note that if you do not declare a style for a class or tag, some JavaScript implementations will refuse to modify them; maybe this is true for some user agents but it's not true for any of the DHTML-supporting browsers on my computer, all of which smoothly execute object.style.property = "value"; commands without needing 'pre-values' to work with. (The position property must be set before changing the left and top property values, but the position property can itself be set dynamically.)

No demo is offered for the tutorial code, so I thought I would load it into a TextEdit file and see how it runs. Some observations:

• The ourTestPage.html user interface is a set of links that when clicked respectively trigger the dynamic_display.js functions; however, these links are rendered as normal text because they lack href attributes.

• Without delineating the szModBox div element in some way (say, with a background color or border), there's no visual effect upon clicking the Click here to modify the box size! link.

• So, I give the szModBox div element a border: 1px solid red;. Clicking the Click here to modify the box size! link changes the div width but not its height because the ModifyBoxSize( ) function's mElement.style.height = newheight; assignment contains a typo: newheight should be newHeight.

• The pModBox div element's position: absolute; left: 15px; top: 15px; places it between the bgModBox and cModBox div elements; above and beyond its unsightly appearance, this placement interferes with the clicking of the Click here to modify the background color! and Click here to modify the text color! links.

The demo below sorts out these issues:

Click here to modify the background color!

Click here to modify the text color!

Click here to modify the box position!

Click here to modify the box size!




"JavaScript Resources: Tutorials, Articles and References"

Composed by Scott Clark, this tutorial provides links to various JavaScript-related resources organized into four categories:
(1) JavaScript tutorial and article collections;
(2) JavaScript references;
(3) JavaScript script archives; and
(4) JavaScript discussion forums.
I've checked the links and can confirm that they're all live as of this writing.

Every one of the resources, without exception, has been culled from the internet.com empire of Web sites, which includes HTML Goodies, and thus the tutorial has a somewhat self-promotional feel to it; even the links to the JavaScript 1.5 Guide and Reference lead to WebReference pages. It is of course the author's prerogative to do this, but I nonetheless find it a bit sloppy that there are no tutorial links to official sites maintained by Mozilla, the W3C, and Microsoft, so perhaps I should fill in some blanks in this regard, eh?

Mozilla

• The Mozilla Foundation is today the steward of JavaScript. Mozilla's JavaScript portal will connect you to the current JavaScript Guide and Reference and to pages that detail new developments in JavaScript 1.6-1.8.5.

• Although now deemed "obsolete" by Mozilla, the JavaScript 1.3 Client-Side Guide and Reference remain the best sources of information on classical (pre-DOM) JavaScript and its basic interfaces for working with various HTML element objects.

• JavaScript shed its client-side features in going from JavaScript 1.3 to JavaScript 1.4; Mozilla now documents these features in its Document Object Model (DOM) reference.

W3C

Most of the non-programming parts of classical JavaScript are, or are on track to be, documented somewhere in a W3C specification. Here are the highlights:

• Properties and methods relating to HTML elements are inventoried in the DOM Level 2 HTML Specification.

• Event handlers relating to HTML elements are summarized here in the HTML 4.01 Specification. The Netscape-cum-W3C event model is described in the DOM Level 2 Events Specification.

• The window object, the history object, the location object, and the navigator object (more precisely, the interfaces implemented by these objects) are all now part of HTML5.

• Some classical window object properties and methods (e.g., innerWidth, pageXOffset, scrollTo( )) and the screen object will be defined in a CSSOM View Module.

Microsoft

• In my book, the crown jewel of the MSDN Library is its HTML and DHTML Reference: DOM objects, properties, methods, event handlers, they're all here.

• Microsoft hosts largely overlapping documentation for both JavaScript and JScript, the Microsoft 'dialect' of JavaScript.

• Microsoft's event model, which differs from the W3C event model, is described in an "Understanding the Event Model" article.



In the following entry we'll check over the next Beyond HTML : JavaScript sector tutorial, "Hovering HTML Windows and Animated Hovering Using JavaScript".

reptile7

Wednesday, June 08, 2011
 
Introductory Ajax Laboratory
Blog Entry #217

Having deconstructed the XMLHttpRequest script code of HTML Goodies' "How to Develop Web Applications with Ajax: Part 1" tutorial over the last two entries, we are ready to put it into action. Our specific goal is to replace the firstChild.data (highlighted in yellow below) of the ajax.html document's id="xmlObj" p element

<p id="xmlObj">
This is some sample data. It is the default data for this web page.
<a href="data.xml" title="View the XML data." onclick="ajaxRead('data.xml'); this.style.display='none'; return false">View XML data</a>
</p>


with the textContent of the data.xml document's data element

  <data>
    This is some sample data. It is stored in an XML file and retrieved by JavaScript.
  </data>


which we will access via an XMLHttpRequest object's responseXML return.

I respectively place the tutorial's ajax.html and data.xml documents in separate TextEdit files and then upload those files to my EarthLink server space. I navigate to the ajax.html page and click the View XML data link. In the event:

• The data element textContent is written to the xmlObj p element with Opera and Opera alone.

• With all of the other XMLHttpRequest-supporting browsers on my computer, the View XML data link does at least disappear, but the p element's

This is some sample data. It is the default data for this web page.

string remains in place and an xmlObj.responseXML is null (or equivalent) error is thrown.

So, I go back and take a closer look at Mozilla's description of the responseXML property:
Returns a Document containing the response to the request, or null if the request was unsuccessful, has not yet been sent, or cannot be parsed as XML or HTML.
In their various XMLHttpRequest examples, Mozilla, Microsoft, and Apple all test the XMLHttpRequest status property, which returns the HTTP status code of the server response, after checking the request's readyState:

if (http_request.readyState == 4) {
    if (http_request.status == 200) { // If the response is OK...
        ... }


I precede the updateObj( ) function call with a window.alert(xmlObj.status); command and rerun the tutorial code; an alert( ) box displaying 200 duly pops up, so we can safely conclude that the xmlObj.responseXML is null error isn't resulting from an unsent or unsuccessful request.

The XMLHttpRequest object has a responseText property that returns a requested file as one big string; a corresponding window.alert(xmlObj.responseText); command pops up an alert( ) box displaying the intact data.xml document - the XML declaration, the root and data elements, even the white space formatting -

[The xmlObj.responseXML return]

so we are getting our hands on the data.xml data, just not in the form that we want it.

Ah, but what about the cannot be parsed as XML business? At the end of the Object Methods section of Apple's "Dynamic HTML and XML: The XMLHttpRequest Object" article is an all-important note:
Note: It is essential that the data returned from the server be sent with a Content-Type set to text/xml. Content that is sent as text/plain or text/html* is accepted by the instance of the request object; however, it will only be available for use via the responseText property*. [*We'll see below that this is no longer true.]
The XMLHttpRequest object has a getResponseHeader( ) method that [r]eturns the string containing the text of the specified header. Upon preceding the updateObj( ) function call with a window.alert(xmlObj.getResponseHeader("Content-Type")); command, the resulting alert( ) box displays text/plain; in corroboration, a HEAD request for my data.xml file at Rex Swain's HTTP Viewer also returns a text/plain Content-Type. It would seem that the home.earthlink.net server doesn't see the data.xml document as a document at all, XML or otherwise.

To deal with this type of contingency, Netscape implemented in Netscape 7 an XMLHttpRequest overrideMimeType( ) method for overriding the MIME type returned by the server. In illustration, Mozilla's "Getting Started [with Ajax]" article features a Step 4 – Working with the XML response example whose httprequest_test_xml.html document contains the following block of instantiation code:

if (window.XMLHttpRequest) { // Mozilla, Safari,...
    http_request = new XMLHttpRequest( );
    if (http_request.overrideMimeType) {
        http_request.overrideMimeType("text/xml"); } }


I am gratified to report that deploying a corresponding conditional in the ajax.html document eliminates the xmlObj.responseXML is null error and gives a functioning demo with Firefox, Safari, Chrome, and Camino; the use of application/xml for the overrideMimeType( ) argument also works.

Opera supports the overrideMimeType( ) method but doesn't need it in this case - evidently there's something in the Opera code (perhaps in its JavaScript engine) that says "It's XML" when an .xml file is called on.

responseText extraction

There's just one little problem with our use of the overrideMimeType( ) method: IE doesn't support it. However, the demo can be made to work for IE users by making recourse to the responseText return.

/* This conditional has been successfully tested with Netscape 7.02, which supports the overrideMimeType( ) method,
and with Netscape 6.2.3., which does not. */
if (xmlObj.responseXML) {
    updateObj("xmlObj", xmlObj.responseXML.getElementsByTagName("data").item(0).firstChild.data); }
else {
    var datastart = xmlObj.responseText.indexOf("data") + 5;
    var dataend = xmlObj.responseText.indexOf("</data>");
    updateObj("xmlObj", xmlObj.responseText.substring(datastart, dataend)); }
/* Neither Netscape 7.02 nor Netscape 6.2.3 supports the textContent property. */


If the server reports a non-text/xml Content-Type that cannot be overridden with the overrideMimeType( ) method, then the xmlObj.responseXML condition of the preceding code's if clause returns null by default and converts to false; subsequently, the else clause locates and extracts the data element content via the String object's indexOf( ) and substring( ) methods, respectively.

Demo

You can try it all out in the div below - click on the View XML data link to see if you are Ajax-ready. If you're a 'sans-JavaScript' user, then clicking the link will display a screen shot of a corresponding data2.xml page as rendered by Firefox in a new window.

Developing Web Applications with Ajax

This page demonstrates the use of Asynchronous Javascript and XML (Ajax) technology to update a web page's content by reading from a remote file dynamically -- no page reloading is required. Note that this operation does not work for users without JavaScript enabled.

This is some sample data. It is the default data for this web page. View XML data


(To fend off possible support- and network-related errors, Mozilla, Microsoft, and Apple place parts of their example code in the try clauses of try...catch statements. The tutorial author doesn't do this, and I don't either in my demo - maybe I should.)

In the name of completeness: When the data element content is loaded into the xmlObj p element, the leading and trailing white space of that content is entirely discarded by the (Ajax-supporting) browsers on my computer excepting Opera, which discards the leading white space but pastes in the trailing white space's two space characters.

Retrieving HTML

Right before the tutorial's concluding That’s all there is to it section the author throws out an interesting possibility:
If you wanted to update an object with HTML instead of just plain text, you could also use
document.getElementById(obj).innerHTML = data;
Presumably he means for that HTML to be fabricated in the current document, but the question arises: Can we use an XMLHttpRequest object to GET a remote HTML document? That we can. The responseXML return for such a document will be null and thus we won't be able to walk that document's DOM tree, but we can definitely use the responseText property in conjunction with String object methods to grab what we want in the document as shown in the responseText extraction section above.

November 2016 Update:
The responseXML operation will recognize an HTML document as an [object HTMLDocument] if the responseType property of the XMLHttpRequest object is set to document just before the open( ) initialization - no overrideMimeType( ) action is required. In this regard, the above demo actually extracts the text of a
<data1 style="display:none;"> ... </data1> element placed near the beginning of the body of the previous post.

The author has also written "How to Develop Web Applications with Ajax: Pt. 2", "Developing Web Applications with Ajax, Pt. 3", and "Developing Web Applications with Ajax, Pt. 4" tutorials; we won't be discussing them, but by all means read through them if this sort of thing is your cup of tea.

Moving on in HTML Goodies' Beyond HTML : JavaScript sector, we will in the following entry begin with some 'quick takes' and then take up the sector's "Hovering HTML Windows and Animated Hovering Using JavaScript" tutorial.

reptile7


Powered by Blogger

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