Michael Wallent
Lead Program Manager, DHTML
Microsoft Corporation
December 7, 1998
The following article was originally published in the Site Builder Magazine (now known as MSDN Online Voices) "DHTML Dude" column.
Ah, the holiday season. Growing up in New England, this was a big thing. I can remember listening to Alvin and the Chipmunks sing, along with Herb Alpert and the Tijuana Brass (Holiday Songs), on a rickety old record player-console-coffee table that passed for high tech then.
On Christmas Eve, my dad would read "A Visit from Saint Nicholas," by Clement Moore. I would write my yearly note to Santa and leave it on the kitchen table along with the requisite quid pro quo bribe of milk and cookies for toys. After I went to bed, my dad would drink the milk and cookies (leaving crumbs and milk stains to prove the existence of the jolly old elf), smear some sooty fingerprints on the note, and write his gracious reply. My mom saved these notes, and showed them to me just recently. One of my more literary accomplishments came from the year 1974, when I was five:
"Deer Santa - I waz gud this yer. Plees give me a pruple bike. Love Mike."
Inspired by these childhood missives, I thought I would take the opportunity to answer some of the many letters that I have received in the past month.
My "Dude Rant" caused quite a few letters. A number of you sent me the quote by Scott Isaacs, from his book Inside DHTML book, about the goodness of "document.all". The goal of my comments about the use or lack of document.all instead of referring to an element directly was to inform and educate that in most instances, the use of document.all.Something over Something is not required. Two cases require reference to an element using the document.all method instead the direct access: referring to an element inside a form and referring to an <IFRAME> element. However, I stand by my former rant about the many uses of direct referral, and still believe (and use on a daily basis) that as the preferred method.
Dear Dude:
You wrote:
"the moveElement function, the mechanism for incrementing the position is very simple. I autoincrement posTop and posLeft. This is significantly faster than using the top and left properties."
My question to you:
I thought I read that you cannot write directly to the top and left properties -- that you have to use posTop/posLeft or pixelTop/pixelLeft. Is this correct?
Signed, Positionally Puzzled
Dear Puzzled:
Actually, both the element.style.left/top and element.style.posLeft/posTop properties are read/write. The difference between the two is that the element.style.left/top properties' return value is "String" -- and the units are indicated. The element.style.posLeft/posTop properties return floating point representations of the position, without units. Given the following HTML:
<DIV id=MyDiv style="position: absolute; top: 50%; left: 50px">
MyDiv.style.left would return "50px".
MyDiv.style.top would return "50%".
MyDiv.style.posLeft would return "50" as a floating point number.
MyDiv.style.posTop would return "50" as a floating point number.
MyDiv.style.posLeft++ would cause the <DIV> to be positioned at "51px".
Autoincrementing either the left or top property would perform an operation on the string, and would not be helpful.
However, directly setting the element.style.left/top properties is very useful if you want to change the unit of the property (from percent to pixels, for example).
Hope that helps.
Dear Dude:
I am trying something which I have never seen done before, and I have not found a way to accomplish. I was hoping you could give me some help. I have an HTML page which is populated with a few text (<input....>) boxes and a button when the page is first loaded. When I click the button, I would like to have a NEW text box created and ADDED to the page.
Any suggestions?
Signed, Addled in Abilene
Dear Addled:
There are at least three ways to do what you are asking (two of which work with both Internet Explorer 4.0 and 5, and one of which is new for Internet Explorer 5).
Using this method, all of the possible elements are loaded on the page, but some are hidden using the display:none property. At the right time, the elements' display property is set back from none, and they show up again.
<html> <body> <div id=InitialContent> Some Inputs <input type=text> <input type=button onclick="ShowMore()"> </div> <div id=AdditionalContent style="display: none"> More Inputs<input type=text> </div> <script language="JScript"> function ShowMore() { AdditionalContent.style.display = ""; } </script> </body> </html>
Using this method, the new elements are actually created on the fly.
<html> <body> <div id=InitialContent> Some Inputs <input type=text> <input type=button onclick="ShowMore()"> </div> <script language="JScript"> function ShowMore() { InitialContent.insertAdjacentHTML("AfterEnd", "<div id=AdditionalContent> More Inputs<input type=text></div>"); } </script> </body> </html>
Using this method, the actual HTML to be rendered is inserted in the document. Making the creation of new elements easier was actually a focus for Internet Explorer 5, which leads us to the third way.
Here, instead of inserting HTML code into the document, you can create new elements in a much more programmatic way.
<html> <body> <div id=InitialContent> Some Inputs <input type=text> <input type=button onclick="ShowMore()"> </div> <script language="JScript"> function ShowMore() { var newDiv, newInput, newText; // create the new div to contain the new content newDiv = document.createElement("DIV"); newDiv.id = "AdditionalContent"; // create the input - make sure to set the type newInput = document.createElement("INPUT"); newInput.type = text; // inserting text means using text nodes // create a new text node newText = document.createTextNode("More Inputs"); // now, insert the text into the DIV newDiv.insertBefore(newText, null); // insert the input into the div, after the text newDiv.insertBefore(newInput, null); // now, put the DIV with the text and input into the document document.body.insertBefore(newDiv, null); } </script> </body> </html>
For more information on using the new Document Object Model (DOM) support in Internet Explorer 5, please see Internet Explorer 5: All Power to the Document Object Model.
Dear Dude:
Recently, whilst creating a system which allowed users to "customize" the appearance of their home page by adding and removing images, I ran into a slight problem with the Radio Button. The system listed all of the images in a specified directory and provided a radio button next to each image so the user could choose one only to display.
In your article you showed a method of determining which radio button is checked:
function getRadioValue(radioName) { var collection; collection = document.all[radioName]; for (i=0;i<collection.length;i++) { if (collection[i].checked) return(collection[i].value); } }
And you boldly stated that: "This function will work with any set of radio buttons."
Not quite; your code won't work if there is only one radio button. This is because the radio button is only a collection if there are two or more. I use the following code to handle this exception:
function getRadioValue(radioName) { var collection; collection = document.all[radioName]; //Check for only 1 radio button if (collection.checked) return collection.value; else //Find checked radio button for (i=0;i<collection.length;i++) { if (collection[i].checked) return(collection[i].value); } }
I must say that when I ran into this problem I found it rather weird, but I hope it's useful info.... Do with it as you will ;)
Signed, Radioactive Man
Dear Man:
In the words of the immortal Ed McMahon, "You are correct, sir!" Thanks for the tip.
Dear Dude:
I'd like to know of a way to check someone's screen resolution directly from a site (if at all possible).
Signed, Joe
Dear Joe:
The window.screen.availHeight and window.screen.availWidth properties give you the user's current screen resolutions.
Dear Dude:
I've always wondered how the mouseovers work on the Knowledge Base result pages on the Support Online site. There doesn't seem to be any obvious script. How do those links change color?
Signed, Scriptless in Sacramento
Dear Scriptless:
The method that and many other sites use is called "pseudoclasses". Pseudoclasses are a Cascading Style Sheets (CSS)mechanism that allows an author to define the style of an element when it's in a given state. On the A (anchor) tag, you can use the hover, link, active, and visited pseudoclasses. For example:
<html> <style> a {font-family: verdana; color: blue} a:hover {font-family: courier; color: red} </style> <body> <a href="about:blank">Hover Over Me</a> </body> </html>
On this page, as the mouse "hovers" (mouses over) any link, the color and font will change.
Dear Dude:
Hi, there. I often read your column, and I find that it helps quite a bit, but I now have a problem that I've never really come across... I need the functionality of Modal Dialogs, along with the ability to be able to talk between frames ... The reason is that I open up a page in the dialog in one frame, and then have a hidden frame that calls Active Server Pages (ASP) pages, and returns the results to the top frame ... works great in a normal window ... but Modal Dialogs don't have a parent property, which prevents me from talking to the other frame... Is there any way of making a normal window appear (more importantly act) like a modal dialog, or can I get my dialog to talk between frames?
Signed, Modal in Mobile
Dear Modal:
Two things can help you out. First, when a page is opened via showModalDialog() or showModelessDialog() instead of the parent property, we expose the "opener" property, which would point to the creating window. Second, it's possible -- and easy -- to pass parameters to a dialog, as shown:
window.showModalDialog("colordlg.htm", document, "resizable: yes; status: no")
In the dialog source, the parameter can be retrieved:
otherDoc = window.dialogArguments;
Dear Dude:
In a past article, you suggest setting the SRC property of the <IFRAME> tag. When I try to do this (using the IFRAME ID, such as ifrmBatches.Src="foo.asp?bar=2"), I get an error indicating that SRC isn't a valid property. Indeed, if I check the TypeName of the IFRAME, I'm told it's an HTMLWindow2 object rather than the expected HTMLIFrame. The Workshop (and MSDN with Visual Studio 6.0) indicates:
The <IFRAME> functions as a document within a document. Consequently, access to the IFRAME object is provided through the frames collection. Use the frames collection to read or write to elements contained in an <IFRAME>.
But I'm not clear about which frames collection that references. The parent of the IFRAME? The IFRAME itself? (It is a window, apparently, although frames.length = zero...)
Signed, Feeling Framed
Dear Framed:
Yes, there is some confusion here. Let me try to clear this up. If you refer to an <IFRAME> directly, such as "MyIFrame.something", the element you are referring to is the inner window inside the <IFRAME>. On a window object, you change location by using the location.href property. When you refer to an <IFRAME> using the document.all.MyIFrame method, you are referring to the element that contains the window. On this object, you change location by using the src property. Here's a sample that shows accessing <IFRAME>s both ways, and how to set the location with both.
<html> <body> <iframe id=TheIFrame src="about:blank"> </iframe> <br> <input type="button" onclick="setWindow()" value="Set Location With Window"> <input type="button" onclick="setElement()" value="Set Location With Element"> <script language=JScript> function setWindow() { TheIFrame.location.href = "http://www.microsoft.com" } function setElement() { document.all.TheIFrame.src = "http://home.microsoft.com" } </script> </body> </html>
Well, that's all the space I have for this month. I wish you a happy, prosperous holiday season and new year.
Michael Wallent is Microsoft's group program manager for DHTML. This year, he will read "A Visit from Saint Nicholas" to his daughter, Peri, for the first time. However, he'll probably skip writing the note, as Peri is only 10 months old.