HTML, Elements, Events, and Back
As of December 2011, this topic has been archived. As a result, it is no longer actively maintained. For more information, see Archived Content. For information, recommendations, and guidance regarding the current version of Internet Explorer, see Internet Explorer Developer Center.
Heidi Housten and Kusuma Vellanki
July 3, 2000
This month, Heidi Housten officially joins the Web Team Talking. In her first column, Heidi joins Kusuma Vellanki to explore a variety of Web-development topics, including questions about disabling a browser's Forward/Back buttons, sinking events, calling form elements, and sending tabular data from HTML to Office applications.
Going Back and forth—Disabling the browser's Forward/Back buttons
Sink it in—Handling events
Calling all elements—Calling form elements you've never met before
Turning the tables—Sending HTML to Office applications
Dear Web Team:
Q: Can anyone tell me if there is a way to disable the browser's Forward/Back buttons? The reason is that I can't allow the client to browse back to pages when they're on the Web site.
By disabling the Back button, I'd be okay—but so far, no luck on doing that. So I asked myself if I could delete the history list of the browser, and therefore block the back of the browser ... no can do either.
I have to find a way to catch the event back and redirect to the same page using VBScript.
The Web Team Replies:
Serge, we have answers galore to your question, and we've decided to hit you with everything we have! So brace yourself. Here they come.
There is no way to clear the session history through script, as you have found. Our mantra for most session-history questions like this is location.replace. Because you control all of the pages on your site, you can use location.replace to navigate from one page to another. This will replace the current history entry with the new page, so you always have only one entry from your site on the stack. Here's a snippet that shows how you can change your links to get this behavior.
This takes care of the Forward/Back problem. But this may not be the complete answer, depending on why you need this functionality. Is the main intention not to allow users to view the page again in that session? If so, you also have to prevent users from accessing this page by typing in the URL manually. Or is your intention to pull the page from the server each time, instead of from the cache, as would happen when the user clicks on the Forward/Back buttons?
The answer to the first question is pretty simple. You can use a session variable that is set when the user first requests a page, and the value of that variable will determine whether the user is allowed to access the page in the same session again.
The second question is a little more complicated. Internet Explorer 4.0 used the cache headers even when the user clicked on the Forward/Back buttons. Internet Explorer 5 complies with the HTTP specification, which states that when the user clicks on the Forward/Back buttons, the pages should be shown to the user exactly as they were viewed when they were saved in the history. In either case, you can still add HTTP headers to prevent the file from being cached on disk, which will force the browser to request it from the server. Refer to the Knowledge Base (KB) article Q234067 "HOWTO: Prevent Caching in Internet Explorer" for more information about these HTTP headers.
If the above solution does not work, you can leverage the session cookies' functionality to ensure that the page is always pulled from the server. To demonstrate, we've included some sample Active Server Pages (ASP) code.
Also, refer to the KB article Q199805 "PRB: Forward and Back Button Behavior in Internet Explorer" for more information regarding the Forward/Back button behavior in Internet Explorer.
Dear Web Team:
Any help would be appreciated.
The Web Team Replies:
Doug, you have to drill down in the document object model and find the appropriate connection point to sink the events. In this case, you need to sink HTMLWindowEvents. The KB article Q246247 HOWTO: Sink HTML Document Events for WebBrowser Host has some sample code that will get you started on sinking HTMLDocumentEvents.
When using Visual C++, get the document interface pointer (explained in the KB article) and use the get_parentWindow() method to obtain the IHTMLWindow2 interface. You can then query this for the connection point container and get the HTMLWindowEvents2 connection point to sink events.
For Visual Basic, use this code snippet, which is a modified version of the code in the KB article. This code demonstrates how to sink HTMLWindowEvents in addition to HT<:DocumentEvents.
Dim WithEvents doc As HTMLDocument Dim WithEvents win As HTMLWindow2 Private Sub Command1_Click() WebBrowser1.Navigate "http://kusuma/scratch/temp.html" End Sub Private Sub Form_Load() WebBrowser1.Navigate "http://www.microsoft.com/" End Sub Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant) Dim htm As IHTMLDocument2 Dim htmwin As IHTMLWindow2 On Error Resume Next Set htm = WebBrowser1.Document Set win = htm.parentWindow If Err.Number = 0 Then MsgBox "HREF is " & htm.location.href End If Set doc = htm End Sub Private Function doc_onclick() As Boolean MsgBox "Clicked the document!" ' Tell IE to continue processing the event. doc_onclick = True End Function Private Sub WebBrowser1_BeforeNavigate2(ByVal pDisp As Object, URL As Variant, Flags As Variant, TargetFrameName As Variant, PostData As Variant, Headers As Variant, Cancel As Boolean) Set doc = Nothing End Sub Private Sub win_onload() MsgBox "load" End Sub Private Sub win_onunload() MsgBox "unload" End Sub
The best place to find the information about the various event interfaces is the type library. In Visual Studio, you can use the OleView tool to view the type library information in mshtml.dll (or, starting with Internet Explorer 5, mshtml.tlb) and shdocvw.dll to see the different event interfaces that are available. For implementations that use Visual C++, look for the interfaces that have the word "Events" in their names. For implementations that use Visual Basic, you need to declare the objects using the "with events" keyword—and, in this case, you will be using the CoClass names that expose the event interfaces mentioned above. Event interfaces for the WebBrowser events, such as BeforeNavigate2, are exposed from shdocvw.dll; event interfaces for specific HTML objects, such as the window, img, and anchor objects, are exposed from mshtml.dll.
For general information about working with the document object model using Visual C++ or Visual Basic, refer to the Hosting and Reuse area of the MSDN Library.
Dear Web Team:
I'm writing a short script that will take an HTML form, collect the data, and send it to an e-mail address. However, I can't seem to find any way to get the field names from the Request object, other than taking the raw data and parsing it manually.
The Web Team replies:
So you want your page to work, even when you don't know what you are doing? That's easy. We practically fought over who got to whip up a small page to illustrate how to whiz through the request.form collection using a "for each" loop and print each form element's name and value without needing to know their names in advance. This is particularly useful for prototyping a new design, when names and elements can be changing all the time. In the "for each" loop, in the code below, the formElement variable will contain the name of the element. Use that to access the value in the collection.
Sometimes, when testing, it would be handy just to modify the querystring in the URL box. Duplicating the code for the form collection and changing the second loop to read from the request.querystring could easily handle this.
<HTML> <HEAD> <TITLE>Finding all the incoming form elements</TITLE> </HEAD> <BODY BGCOLOR="#FFFFFF" TEXT="#000000"> <FORM METHOD=POST> First Item: <INPUT TYPE=TEXT NAME=First><BR> Second Item: <INPUT TYPE=TEXT NAME=Second><BR> Third Item: <INPUT TYPE=TEXT NAME=Third><BR> <INPUT TYPE=SUBMIT> </FORM> <% for each formElement in request.form() response.write formElement & " contains: " response.write request.form(formElement) & ".<BR>" next %> </BODY> </HTML>
Dear Web Team:
When using ASP to develop reports, I get a lot of requests to convert reports to Word, Excel, etc. The process I take for doing so:
- Create the associated object, e.g., oExcel = createobject("Excel.Sheet").
- Insert the values, e.g., oExcel.Worksheets(4).Range("D20").Value = "".
- Create a temp file, oExcel.saveAs(sUniqueFile).
- And Redirect to the file.
Is there an easier way to build an HTML report in ASP and convert it to all the necessary Word/Excel documents?
The Web Team Replies:
There is an elegantly simple and little-known way to get information from the server into Excel and Word, available in Office 97 and later versions. The key: Content-type. Excel and Word both can interpret HTML. This little trick means that you can use exactly the same ASP file and output it to Word, Excel, or the browser just by setting the content-type. Once it's in the viewer's Office applications, the viewer can do whatever he or she might want to do with any Office document, except save it back to the server.
One limitation is that you can display only a single Excel sheet, rather than a workbook full.
Because this is all simple HTML, the files are quite small. This makes a great, lightweight method of making reports available to those who might have slow connections.
Here is a simple example:
<%@ language=vbscript %> <% response.buffer = true response.ContentType = "application/vnd.ms-excel" response.AddHeader "content-disposition", "inline; filename=dynamic.xls" response.write "<table width=200>" response.write "<tr>" for i = 1 to 4 response.write "<td width=40>" response.write i + i response.write "</td>" next response.write "<td width=40><b>=sum(A1:D1)</b></td>" response.write "</tr>" response.write "</table>" response.flush response.end %>
There are several cool things to notice here.
The fourth line of the code does the magic of telling the browser which application to open. To open Word, you would change the content-type to application/msword.
The fifth line of the code is a response.addHeader. This line specifies the file name to display if the user chooses to save, rather than open, the file.
The line after the end of the for loop contains a sum formula that Excel will act upon correctly—and because of the <B> tags that surround it, it will be displayed in bold.
A little note: This will typically open Excel or Word in the browser. This behavior can be changed. Open an instance of Windows Explorer (not Internet Explorer!). Select Folder Options from the Tools menu. Click the File Types tab in the dialog box that appears. Scroll down to the relevant file extension—in this case, xls—and select it. Then click the Advanced button. Near the bottom of this new dialog box, you will see the option Browse in Same Window. Select or deselect this option according to your preference.
We've given a simple example here. The Office 2000 applications are capable of understanding more complicated HTML. You could experiment by creating an Excel file in Excel and saving it as HTML, then take a gander at the HTML saved. You may also want to explore some of the applications' more sophisticated Web features, which allow people to access and update files on the server, too. .
Q: Jens wants to simulate the Stop button behavior in Internet Explorer, similar to using Netscape's window.stop() method.
A: We'll let you in on a currently undocumented feature: You can use document.execCommand("Stop").
Q: Richard wants to wrap (or attach) a binary type file in an XML document.
Q: Jaka is trying to insert a line break in the body of a message when using the mailto URL <A HREF="mailto:email@example.com?subject=Hello&body=line%20one%0D%0Anew%20line">Drop us a line</A>.
A: Escape the % in the carriage return and line feed characters to %25. Refer to Q251230 for more information.
Q: Sean is trying to append headers in the BeforeNavigate2 event.
A: The headers argument is an IN parameter, so you cannot append headers in this event. Cancel the event by setting the Cancel flag, then append the new headers and call Navigate/Navigate2 explicitly with the same information as in the BeforeNavigate2 event.
Q: Jussi and Justin want to cancel the context-sensitive menu in Internet Explorer 5.
A: You can cancel the oncontextmenu event, and you can override it for specific elements, such as <DIV> and <IMG> tags.
Q: Patrick asked how to create an object in JScript.
A: Use the new ActiveXObject like this:
rs = new ActiveXObject("ADODB.Recordset"[,server])
See the Scripting Technologies site for online and downloadable references on both scripting languages.
Q: We have had many inquiries on how to do DHTML menus like the ones used on the MSDN site.
A: Have a look at George Young's in-depth series on building TOCs using XML and DHTML in MSDN Online's "Code Corner" column.
Q: Steven asked how to e-mail a Web page using ASP instead of CGI.
A: Use CDONTS; it can also send HTML. KB article Q186204 "HOWTO: Use CDONTS to Collect and Mail Information From a User" shows the basics. You can also find quite a few additional references using the lovely new MSDN Search. Just search for CDONTS.
Q: Clive runs into trouble using the Scripting.Dictionary in an ASP application variable.
A: See KB article Q194803 "PRB: Scripting.Dictionary Object Fails in ASP Application Scope".
Q: Anton would like to have vertical text without using graphics.
A: In Internet Explorer 5.5, a new attribute called writingMode allows vertical text alignment. However, this turns the text on its side, instead of placing one letter below another. It is intended mostly for languages that are written vertically rather than horizontally.