Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

Mysteriouser and Mysteriouser

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.

Jay Allen, Mark Davis, and Heidi Housten
Microsoft Corporation

February 14, 2002

We apologize to our readers for temporarily disappearing without a trace. We intend to remain as mysterious as Agatha Christie was after her month-long disappearance, but we will say that any rumors of our demise are unfounded! Sadly, Dan has had to leave the team—we will miss his wit and sharp insights, if not the sharp insults. Thanks, Dan. We will unveil our next victim as soon as we can find one who hasn't been scared off by rumors, unfounded of course, of the team shenanigans!

This month we decided to clear out a collection of the smaller questions that have been blocking our inbox, as well as highlighting our first major ASP.NET question.

Contents

Nesting Instincts—displaying hierarchical data in ASP.NET
In and Out of Context Menus—adding items to the Internet Explorer Context Menu
Framing Timeouts—timeouts between frames

Web Team in Short

Nesting Instincts

Dear Web Team:

I have been having fun exploring ASP.NET. At first I thought it was just overcomplicated hype, but now that I've had the chance to really dabble in it, I love how simple it is to do a lot of things, particularly displaying data!

Unfortunately I have gotten stuck trying to nest ASP:repeaters in order to display hierarchical data. I am just trying to do a simple listing of all the CDs I have, which are categorized by artist. I can get the artist list easily enough, but can't figure out how to display the children.

Thanks!
Lisa

The Web Team replies:

There was a small brawl on the team over who would get to research this question—one of our first on ASP.NET! Hurrah! We've been waiting months for this one Lisa!

This question actually introduces a lot of new things that are beyond the scope of our humble column, but have been covered impressively in the ASP.NET Quickstart Guide. The most relevant section for the purposes of this question is called Data Binding Server Controls. You can even download the entire .NET Framework SDK if this taster really whets your appetite.

The ASP:repeaters are powerful and you can use nearly anything as the datasource. It is possible to bind to a property, a collection, an expression, a DataView, or even the results of a function call. If a collection supports ICollection, IEnumerable, or IlistSource, then you can bind a repeater control to it. Of course this had us thinking up all sorts of elaborate ways to solve your problem, but in then end it was a simple method on the new .NET DataView that won for simplicity and elegance. Allow us to introduce the Dataview.CreateChildView() method. It returns a dataview for the child datatable based on the specified data relation.

To make it easier to visualize, here is a sample. First of all, we used an XML file for the data input to make it easier for you to just cut and paste. If you don't happen to have a .NET Web server available to test this sample, there are some free .NET hosting services for experimenting. You can find a list of them on the GotDotNet Web site.

musicLibrary.xml
<Artists>
   <Artist name="The Chipmunks">
      <CD id="4550" name="Eponymous" image="Eponymous.jpg" />
      <CD id="4557" name="Hibernation" image="Hibernation.jpg" />
      <CD id="4577" name="Going Nuts" image="GoingNuts.jpg" />
   </Artist>
   <Artist name="The Dogs">
      <CD id="4640" name="Full Moon" image="FullMoon.jpg" />
      <CD id="4637" name="Old Shoes" image="OldShoes.jpg" />
      <CD id="4664" name="My House" image="MyHouse.jpg" />
   </Artist>
</Artists> 

music.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Data" %>

<HTML>
<SCRIPT LANGUAGE="VB" runat="server">
    Dim DS As Dataset = New DataSet

    Sub Page_Load(Src As Object, E As EventArgs) 

        DS.ReadXml(Server.MapPath("musicLibrary.xml"))

        Dim CSource As DataView
        CSource = DS.Tables("Artist").defaultView
        MusicList.DataSource = CSource

        'a little code to help display what table relations exist
        RelationsGrid.DataSource=DS.Relations

        DataBind()

    End Sub
</SCRIPT>

<BODY>

<ASP:Repeater id="MusicList" runat="server">
   <ItemTemplate name="ArtistTemplate">
    <BR /><BR /><B><%# Container.DataItem("name") %></b><br />

    <ASP:Repeater id="CDList" runat=server
     datasource='<%# Container.DataItem.CreateChildView("Artist_CD")%>'>
       <ItemTemplate name="CDTemplate">
        <IMG SRC="<%# Container.DataItem("image") %>ALIGN="absmiddle"/>
        <%# Container.DataItem("name") %><BR />
       </ItemTemplate>
    </ASP:Repeater>

 </ItemTemplate>
   
</ASP:Repeater>

  <BR /><BR />
  <ASP:DataGrid ID="RelationsGrid" runat="server"
    Width="300"
    BackColor="#ccccff" 
    BorderColor="black"
    ShowFooter="false" 
    CellPadding=3 
    CellSpacing="0"
    Font-Name="Verdana"
    Font-Size="8pt"
    HeaderStyle-BackColor="#aaaadd"
    MaintainState="false"
  />

</BODY>
</HTML>

Some of you may have noticed immediately that the first line of music.aspx is language=VB. This was not a typo on our part. ASP.NET introduces using Visual Basic® instead of VBScript. It is also possible to compile ASP.NET pages for improved performance once you have finished with the development cycle. The next line is also interesting—we need to import the namespace for the new dataView object.

A little further down you'll notice the Page_Load method. This points to another interesting change for ASP.NET. Page_Load is an event on the server, not the client! You no longer sprinkle ASP through out your page. It is now event driven and more properly encapsulated. We could go on and on about how cool ASP.NET is and about the changes it brings, but we still have our question to answer. Check some of the links we've given you if you want more.

We first declare our Dataset ,and then in the Page_Load event we read in our XML file. We set CSource to the defaultView of the Artist table, and set the MusicList.datasource to this view. If you look down into the <body> tag you'll find the first repeater server control, which is declared as MusicList. The repeater, and other server controls, allows you to specify how each element should be presented by using the <itemTemplate>. Since we are binding the Artist Table to this repeater, we will print out the artist name in the item template. Then we add another repeater control that provides the template for the Artist's CDs.

We specify the current data element of the parent repeater as container.dataitem. To get the child elements from the Artist, we set the datasource for the new repeater control to Container.Dataitem.CreateChildView("Artist_CD"). Artist_CD specifies the relationship to use when creating the child view. In our simple sample data there is only one relationship. Notice that we don't have to define this relationship ourselves; the Dataset recognizes the relationship based on the data in the XML file. If you have complicated or variable data, it might be better to provide a document type definition (DTD) and specify the relationships. Notice that we threw in the dataGrid server control, RelationsGrid, to display all the relations from the DS dataset. If you have some more complicated XML around, you might be interested in seeing what relations get automatically created. It is also a handy little tool if you aren't sure what the relation will be called.

To show the data for the CDs, we generate another item template for the nested repeater control and presto! Well, we did skip one important thing at the end of the page_load event handler. The page's databind method is the magic word to render this code. This gives the developer much more control over when and what happens. You could specify that only a specific control gets databound if you want to do some other things before binding the rest of the page, or perhaps you only need to render one control based on user input.

Thanks for that challenge, Lisa! We look forward to more .NET questions now that Visual Studio® .NET has been launched.

In and Out of Context Menus

Dear Web Team:

I have added an item to the IE [Microsoft Internet Explorer] context menu. If I right click when I am on a hyperlink, is there any way to capture that hyperlink address? I can add a menu item, but am unable to capture the hyperlink address.

The following function is useful, but I am unable to get the selected hyperlink address.

function test()
{
   var parentwin = external.menuArguments;
   var doc = parentwin.document;
   var sel = doc.selection;
   var rng = sel.createRange();
   var str = new String(rng.text);
   if(str.length == 0)
        rng.text = "MY INSERTED TEXT";
   else
        rng.text =  str.toUpperCase();
    alert(external.menuArguments.location.href);
}

With Regards,
Rameswara Reddy, Chittepu
MCP

The Web Team replies:

You're in good company with your question! The right click context menus seem to come up every month with an amazing variety of requests. We were surprised when we looked through our archives to find that we haven't touched on adding a context menu item. There is an excellent article on MSDN about the Internet Explorer Browser that also covers adding to the context menu. From your sample code, it looks like you may have found it already. The key to the answer to your question is the section The Context Menu Event, which points out that the event object is available to the menu extension. We used this to get a hold of the srcElement that fired the context menu event handler in the following variation on your code.

<SCRIPT LANGUAGE="JavaScript" defer>
    var parentwin = external.menuArguments;
    var doc = parentwin.document;
    var element = parentwin.event.srcElement;
    parentwin.alert(element.href)
</SCRIPT>

We'll leave it to our eager readers to read the article themselves to discover how to fine tune context menus so that the viewer gets different options depending on what type of content they clicked on, be it normal text, an image, a link, or something else. We love the extensibility and power those folks in the Internet Explorer team have given us.

Framing Timeouts

Dear Web Team:

I made a site using a frameset with header and content. On some images (in the header frame), I used the mouseout events to trigger a setTimeOut call. I tried to cancel it by using a cleartimeout on the content frame, but it didn't work well. Canceling the setTimout doesn't always succeed. And it happens only in IE5.0, not in 5.5 or 6 (its working well on these versions).

Here are the snippets of the code:

On the header frame content:

<TD ONMOUSEOUT="frames[1].timeoutvar=setTimeOut('some javascript',500)"><img></TD>

On the content frame content:

<SCRIPT>
var timeoutvar;
</SCRIPT>
<TD ONMOUSEOVER="cleartimeout(timeoutvar)"><img></TD>

Can you tell me how to make it run well on IE5.0?

Thanks,
andre

The Web Team replies:

The problem here is an easy oversight to make. Currently you are setting the timeout to run in the header frame and are storing the reference to it in another frame. Some functions seem to work better if they run in the same frame. If we refer to Frames[1] as f1 for simplicity, we would just change the onmouseout of your header frame to read:

ONMOUSEOUT="f1.timeoutvar=f1.setTimeOut('some jscript',500)"

You should find that this performs much better. In general, at least in the older browser versions, performance seems to improve if you call methods on the target frame if they are stored there as well. This is particularly relevant when trying to add options to a select box in another frame. Make sure you create the option in that other frame so you are adding it to a local select box, instead of trying to cross frame boundaries.

Web Team in Short

What Is the Image Object?

Q: Will wants to know more about the Image object that is available from Microsoft JScript®, instantiated as follows:

var myImg = new Image();

A: The Image object represents an HTML IMG element and is often used to improve the user experience by pre-loading images into the browser cache. The Image object has properties that correspond to each IMG attribute, so please refer to the MSDN Online documentation for the IMG element for details.

A Limited Dialog

Q: Greg has been passing the value of the calling document's innerHTML property to a modal dialog and has noticed that this data is limited to 4K.

A: This limitation is probably there to avoid any potential buffer overrun. To workaround this, I would suggest that you pass the document's body object and have the dialog access the innerHTML property. Here's an example.

Contents of test.htm:

<HTML>
<BODY>
<INPUT TYPE="button" VALUE="Launch dialog" 
   ONCLICK="showModalDialog( 'dialog.htm', document.body );">
</BODY>
</HTML>

Contents of dialog.htm:

<HTML>
<BODY ONLOAD=" mydiv.innerText = window.dialogArguments.innerHTML;">
<DIV ID="mydiv"></DIV>
</BODY>
</HTML>

Getting Binary with JScript

Q: Trent wants to create a binary file from JScript.

A: File management is usually performed using the FileSystemObject. Unfortunately, the FileSystemObject component was not designed to support creating binary files. An alternative is to use the Stream object that is provided with ADODB 2.5. The Stream object has a Type property that can be set to adTypeBinary (1). Use the Write method to write the contents of a byte array to the stream and then call the SaveToFile method to save the data to a file. There are some caveats. The Write method accepts a byte array, but JScript has no support for byte arrays. You can load binary data from a file, using the LoadFromFile method, or from any method or property that returns a byte array. You could also write a custom ActiveX® object to create a byte array. For an example of this usage, please refer to HOWTO: Use the ADODB.Stream Object to Send Binary Files to the Browser through ASP (Q276488).

Adjust the Alignment

Q: Zvi wants to align text to the right in an input box.

A: You can use the text-align CSS attribute to set the text alignment in a text box:

<INPUT TYPE="text" STYLE="text-align:right" VALUE="1,000.00">

Drink Me!

Q: Pete wants to make use of the thumbnail generator used by Microsoft Windows® to display small images of Web pages and other files.

A: You can make use of the IExtractImage COM interface that is provided by Windows folders. You can find more information on this interface in the MSDN Online documentation. You can also find an example XML Web service (Thumbnail Generator) at the GotDotNet Web site. The Web service can be installed on your .NET Web server and will deliver a thumbnail image of the Web site at a specified URL. Source code is provided for the image extraction application, which is run by the Web service, and demonstrates how to use the IExtractImage interface.

Make Your Choice

Q: Bharti asks how to determine which button on an ASP page was clicked if there is more than one to choose from.

A: You can determine which button the user clicked by providing a distinguishing name and value for each button. The name and value of the button is sent as part of the form data, so your ASP page can identify the button. This is demonstrated in the following example:

Contents of test.htm:

<FORM ACTION="http://localhost/example.asp" METHOD="post">
<INPUT TYPE="SUBMIT" NAME="OK" VALUE="OK">
<INPUT TYPE="SUBMIT" NAME="Cancel" VALUE="Cancel">
</FORM>

Contents of example.asp:

<%@ language="JScript" %>
<% 
if ( Request.Form( "OK" ) == "OK" )
   Response.Write( "You clicked OK" );
else
   Response.Write( "You clicked Cancel" );
%>

The Web Team

Mark Davis is a software design engineer on the Internet Explorer SDK team. Mark originates from England and is currently training to climb the major summits in the Northwest.

Heidi Housten works as a Consultant with Microsoft Consulting Services in Sweden after spending some time in Developer Support and MSDN. It is only a rumor that she moved there to escape the drizzle of Seattle; she really went for the traditional crayfish parties in August.

Jay Allen, a Support Engineer for the Internet Client team in Microsoft Developer Support, longs for the integration of Notepad and Emacs Lisp. What little time is not consumed by his four children is usually spent reading math books, studying Japanese and programming in Haskell.


The Web Team's Greatest Hits

List of Web Team Topics


  
Show:
© 2015 Microsoft