Jumat, 29 Mei 2026

MSDN

 https://web.archive.org/web/20010612064310/http://msdn.microsoft.com/voices/askgui05292001.asp


https://web.archive.org/web/20010610140949/http://msdn.microsoft.com/default.asp


https://web.archive.org/web/20010710011930/http://windows.oreilly.com/news/hejlsberg_0800.html

Deep Inside C#:
An Interview with Microsoft Chief Architect Anders Hejlsberg

by John Osborn


In July, O'Reilly editor John Osborn attended the Microsoft Professional Developer's Conference where he conducted the following interview with Anders Hejlsberg, Distinguished Engineer and Chief C# Language Architect about Microsoft's .Net framework and the C# programming language. Anders Hejlsberg is also known for having designed Turbo Pascal, one of the first languages available for PCs. Anders licensed Turbo Pascal to Borland and later led the team that created Delphi, a highly successful visual design tool for building client server applications. Also in attendance at the interview were Tony Goodhew, Microsoft C# product manager, and O'Reilly Windows editor Ron Petrusha.


Osborn:
I've been looking at press stories about C# [pronounced "See sharp"] and notice that many of them seem to lead with the observation -- or perhaps the theory -- that C# is either a clone of or a Microsoft replacement for Java. If you could write the headlines, what would you like people to say about the language?

Hejlsberg:
First of all, C# is not a Java clone. In the design of C#, we looked at a lot of languages. We looked at C++, we looked at Java, at Modula 2, C, and we looked at Smalltalk. There are just so many languages that have the same core ideas that we're interested in, such as deep object-orientation, object-simplification, and so on.

One of the key differences between C# and these other languages, particularly Java, is that we tried to stay much closer to C++ in our design. C# borrows most of its operators, keywords, and statements directly from C++. We have also kept a number of language features that Java dropped. Why are there no enums in Java, for example? I mean, what's the rationale for cutting those? Enums are clearly a meaningful concept in C++. We've preserved enums in C# and made them type-safe as well. In C#, enums are not just integers. They're actually strongly typed value types that derive from System.Enum in the .NET base-class library. An enum of type "foo" is not interchangeable with an enum of type "bar" without a cast. I think that's an important difference. We've also preserved operator overloading and type conversions. Our whole structure for name spaces is much closer to C++.

But beyond these more traditional language issues, one of our key design goals was to make the C# language component-oriented, to add to the language itself all of the concepts that you need when you write components. Concepts such as properties, methods, events, attributes, and documentation are all first-class language constructs. The work that we've done with attributes -- a feature used to add typed, extensible metadata to any object -- is completely new and innovative. I haven't seen it in any other programming language. And C# is the first language to incorporate XML comment tags that can be used by the compiler to generate readable documentation directly from source code.

Another important concept is what I call "one-stop-shopping software." When you write code in C#, you write everything in one place. There is no need for header files, IDL files (Interface Definition Language), GUIDs and complicated interfaces. And once you can write code that is self-describing in this way, then you can start embedding your software, because it is a self-contained unit. Now you can slot it into ASP pages and you can host it in various environments where it just wasn't feasible before.

But going back to these key component concepts, there's been a lot of debate in the industry about whether languages should support properties or events. Sure, we can express these concepts by methods. We can have naming patterns like a "get" block or a "set" block that emulate the behavior of a property. We can have interfaces and adapters that implement an interface and forward to an object. It's all possible to do, just as it's possible to do object-oriented programming in C. It's just harder, and there's more housekeeping, and you end up having to do all this work in order to truly express your ideas. We just think the time is right for a language that makes it easier to create components. Developers are building software components these days. They're not building monolithic applications or monolithic class libraries. Everyone is building components that inherit from some base component provided by some hosting environment. These components override some methods and properties, and they handle some events, and put the components back in. It's key to have those concepts be first class.

Osborn:
You gave an introduction to C# recently, and the first bullet on the first slide said, "The first component-oriented language in the C/C++ family."

Hejlsberg:
Yes, it's one of my primary goals. We talk about how everything is an object, which is also very key. Languages like Smalltalk and Lisp have done this before, but at great cost. I think C# contains some pretty interesting innovations that make component development easier, such as its notions of boxing and unboxing. Boxing allows the value of any value type to be converted to an object, while unboxing allows the value of an object to be converted to a simple value type. It's not as though this hasn't happened before, but the way we've applied it to the language is pretty innovative.

We've tried not to take an "ivory tower" approach to engineering C# and the .Net framework. We can't afford to rewrite all of our software. The industry just can't afford it, especially now when we're moving on Internet time. You've got to leverage what you have, and so I think interoperability is just key. We focused hard on giving programmers all of the right solutions for interoperating with Internet standards, such as HTTP, HTML, XML, and with existing Microsoft technologies, so you don't fall off a cliff the minute you find that something isn't provided by the new .NET environment, or when you realize you want to leverage some existing API or component. You've seen all the COM interoperability that we have built into the language and into the common runtime; you've seen how you can just import existing DLLs [Dynamically Linked Libraries] using the DllImport attribute; and you've seen how even if that doesn't get you there, we have the notion of unsafe code. Unsafe code allows you to write inline C code with pointers, to do unsafe casts, and to pin down memory so it won't accidentally be garbage-collected.


Read more about the .NET platform in .NET vs. J2EE: How Do They Stack Up?. Jim Farley, author of Java Enterprise in a Nutshell, compares the two platforms.

There's been a lot of discussion about unsafe code, and people seem to think we're on drugs or something. I think it's a misunderstanding. Just because code is marked "unsafe" does not mean that it is unmanaged. Of course, we're not just throwing in unsafe pointers and leaving people vulnerable to downloading unsafe code over the Internet. Unsafe code is deeply tied into the security system. We give you the flexibility to stay within the managed code box and to get the job done without falling off the cliff and having to jump into a different language and a different programming model for native code. And by keeping you within the box, we can make the code much safer because the system understands what's going on. The fact that you write unsafe code doesn't actually mean that you're leaving the managed space. So your unsafe code becomes much more efficient.

Osborn:
Tell me more about dealing with unsafe code in a managed environment.

Hejlsberg:
Yes. One of the things that characterizes managed execution environments, like Smalltalk, Java, and the .NET common language runtime, is that they provide garbage collection, and to provide garbage collection, at least with modern garbage collectors -- your "mark and sweep" garbage collectors -- you need to understand more about the code that's executing than you do about traditional unmanaged code. In order to find the dead objects by exclusion, you need to be able to walk the stack, to chase down all the live roots, and to figure out which objects are alive and which ones weren't visited. However, in order to be able to do that, you need closer cooperation from the code you are executing. The code needs to be more descriptive. It needs to tell you how I am laying out the stack, where my local variables are located, and so on.

When you're writing unsafe code in C#, you have the ability to do things that aren't typesafe, like operate with pointers. The code, of course, gets marked unsafe, and will absolutely not execute in an untrusted environment. To get it to execute, you have to grant a trust, and if you don't, the code just won't run. In that respect, it's no different than other kinds of native code. The real difference is that it's still running within the managed space. The methods you write still have descriptive tables that tell you which objects are live, so you don't have to go across a marshalling boundary whenever you go into this code. Otherwise, when you go out to undescriptive, unmanaged code (like through the Java Native Interface, for example), you have to set a watermark or erect a barrier on the stack. You have to remarshall all the arguments out of the box. Once you're using objects, you have to be very careful about which ones you touch because the GC [Garbage Collector] is still running on a different thread. It might move the object if you haven't pinned it down correctly by using some obscure method to lock the object. If you forget to do that, you're just out of luck.

We've taken a different approach. We've said, "Let's integrate this into the language. Let's provide statements, like the fixed statement, that allow you to pin down the object cooperatively with the GC and integrate it." In that way we provide the best means of bringing all existing code forward, instead of just throwing it away. It's a different design form.

Osborn:
So the memory that you're working with in unsafe code is in fact being watched by the garbage collector?

Hejlsberg:
Yes, it is. But, caveat emptor, it's unsafe. You can obtain a pointer and you can do the wrong thing. But you can do that in native code, too.

Osborn:
Another area of confusion, I think, is understanding where C# stops and the common runtime begins. What's the innovation in the C# language itself versus what it gets from the common runtime library?

Hejlsberg:
Well, I think some of this confusion comes from the fact that when people talk about Java, they don't really know which is the language and which is the runtime. Some of this confusion arises when people talk about Java. Which is the language and which is the runtime? What do people mean when they say Java? Do they mean Java, the language, Java, the syntax, or do they mean Java, the platform? People lump these different aspects together. We've taken an approach that says we want to be a multilingual platform. We're going to build a platform that actually allows you to implement multiple programming languages and also have them share a common set of APIs (Application Programming Interfaces). Let's face it, some people like to program in COBOL, some people like to program in Basic, some like C++, and some will like C#, I hope. But we're not trying to tell you to forget everything you ever did. We're not saying, "Now that there's only one language, there shall be no further innovations in this race." We're saying that our industry advances by its flexibility. How did Java come about? It came about because there were programming languages before it and there will be programming languages after it. We want to build a platform where your preference for one language over another doesn't negate the whole value proposition. We want to create a platform where there can be innovation. Who's helping COBOL programmers today? Who's taking them to the Web? Only on the .NET platform can you embed Fujitsu COBOL in an ASP page. I mean it's truly revolutionary.

Osborn:
Given the availability of multiple languages for the .NET platform, why would you choose C# over Visual Basic, C++, or even COBOL? What is it that makes C# so compelling?

Hejlsberg:
First of all, with C# we were able to start with a clean sheet of paper, so to speak. We did not have any backward compatibility requirements, and that certainly made things simpler. And not just from an implementation standpoint, but also from a usage standpoint. For example, we only have one kind of class in C#, and it is always garbage-collected. Managed C++, on the other hand, has two because it has to preserve the non-garbage collected style of programming. So, C# simply has fewer concepts you have to understand.

Language is a funny thing: It's a matter of taste. Language is almost a religious thing, and it's a lifestyle choice for programmers. I mean, we realize that we can't walk out and say, "Here's a platform where you have one language base." Even if you could do everything in that platform with one language, some people may not like its syntax; they might like curly braces instead or some other block delimiter. That's what they're familiar with. That's what makes them feel at home and productive and enabled. And so our approach with C# has simply been to offer an alternative to C++ programmers who find that language too complicated and to Java programmers who miss certain features of C and C++ that were lost in the translation. We looked for ways to simplify C++ and then put the result on a multilingual platform that provides greater interoperability, and that gives you all of these component concepts, and so forth.

Goodhew:
One of the interesting things that came out of our developer tracking study is that over 60 percent of all developers in the professional developer market use two or more languages to build their applications. And what that tells us, especially when we ask which tools programmers use, is that there isn't going to be one object-oriented programming language which is the end all and be all language that everyone will use. As Anders said earlier, people will want certain syntaxes for what they're doing or how they feel. It's a personal choice. And that's what the whole .NET platform is about, providing developers with a choice of languages in which to implement. I think we've done a pretty good job. You can basically do the same tasks in Visual Basic, .NET, and C#. Visual Basic is still viewed as more accessible to programmers. C# has more headroom and more power than VB does.

Osborn:
Meaning that you can accomplish more with fewer statements in C#?

Hejlsberg:
Well, meaning you have more power through the provision for unsafe code.

Osborn:
So you can't write unsafe code in VB?

Hejlsberg:
No, you cannot.

Goodhew:
But basically, both languages can do the same thing. That's a fundamental change from where we were with Visual Studio 6. If you wanted to build a multi-threaded MTS object using Visual Studio 6.0 and you were a VB programmer, you couldn't. You'd have to use C++. Now, with the .NET framework, you can use whichever language you want.

Hejlsberg:
It's the thing I talked about in my general session talk: The unification of programming models, which the .NET framework offers. In the evolution of languages and frameworks, we always seemed to end up marrying a programming language to a particular API and a particular form of programming. VB was about rapid application development and forms, MFC (Microsoft Foundation Classes) was about sub-classing, and ASP was about putting stuff in web pages. In each case, your choice of programming model always dictated your choice of programming language and your choice of available APIs. It added to your workload the burden of learning new languages and APIs every time you switched frameworks. We have really tried to unify all of that. We provide one API, one supporting visual design tool, and we give you the flexibility to choose whichever language works for you.

Osborn:
I'm wondering what this does to the use of scripting languages such as VBScript and JScript?

Hejlsberg:
One of the wonderful things the .NET framework has done for scripting languages is to make them compiled. Look at ASP+. Now, you're actually running real compiled code in your pages; it's not late-bound, dispatch look-ups where you don't see a runtime error until the user hits the page. ASP+ developers can use the full power of Visual Basic .NET instead of VBScript. And for the first time, they have the ability to use Perl, Python, and other popular languages if they so choose.

Petrusha:
Server-side JavaScript is now compiled?

Hejlsberg:
Yes, that's right.

Goodhew:
The .NET framework allows scripting languages to be used as full-featured languages because they now have access to a true programming framework and to the same base-class APIs. You should look at what the guys who are doing the JScript implementation have accomplished. [Editors Note: JScript is the Microsoft implementation of the ECMA 262 language specification (ECMAScript Edition 3). With only a few minor exceptions (to maintain backward compatibility), JScript is a full implementation of the ECMA standard.] So the .NET platform provides a common language framework, which is a huge benefit to script writers.

Osborn:
We've talked about Java, C++, and scripting. I have heard a number of people here at the PDC argue that there really is no difference between .NET IL (IL is the Microsoft Intermediate Language that all compilers must produce to run in the .NET framework) and the Java byte code that is consumed by the Java Virtual Machine (JVM). It's clear from the talks you've given that you do not agree. Would you care to comment further on the distinction?

Hejlsberg:
Sure. First of all, the idea of ILs is a very old idea. You could trace the concept back to the UCSD Pascal p- machine (an early implementation of Pascal for personal computers) or to Smalltalk. p-code is used by Basic and Visual Basic. Parts of Word, internally, use a p-code engine because it's more compact. So, p-code is nothing new.

I think the approach we've taken with the IL is interesting in that we give you options to control when compilation -- or translation, if you will -- of the IL to native code occurs. With managed C++, you can actually generate native code directly from source. Managed C++ can also generate IL, as can C# and VB. And when you install your code we give you the option to compile it at that point; to compile the IL to native at that point, so that when you run it there's no just-in-time compiler overhead. We also give you the option of running and compiling code dynamically, just-in-time compilation. And, of course, having an IL gives you many advantages, such as the ability to move to different CPU architectures and to introduce verifiability in type safety and then build the security system on top of that.

I think one of the key differences between our IL design and Java byte code specifically, is that we made the decision up-front to not have interpreters. Our code will always run native. So, even when you produce IL, you are never running an interpreter. We even have different styles of JITs. For the compact framework, we have the EconoJIT, as we call it, which is a very simple JIT [Editor's Note: .NET Compact is a subset of the .NET framework designed to be ported to other devices and platforms.]. For the desktop version we have a more full-fledged JIT, and we even have JITs that use the same back end as our C++ compiler. However, those take longer so you would only use them at install time.

When you make the decision up-front to favor execution of native code over interpretation, you are making a decision that strongly influences design of the IL. It changes which instructions are included, what type information is included, and how it is conveyed. If you look at the two ILs, you'll notice that they're quite different. In a sense, our IL is type-neutral. There's no information in the instructions that specifies the type of the arguments. Rather, that is inferred by what's been pushed on the stack. This approach makes the IL more compact. A JIT compiler needs to have that information anyway, so there's no reason to carry it along in the instructions. So you end up with some different design decisions, which in turn makes it easier to translate IL into native code.

Osborn:
What distinction needs to be made between interpretation and the approach that you're describing?

Hejlsberg:
At the core of an interpreter is a loop that fetches some bytes out of a p-code stream, which then falls into a big switch statement that says, "Oh, this was an ADD instruction, so it goes over here, but this wasn't" -- and so forth.

An interpreter emulates a CPU. We turn it upside down and we do one pass -- we always do one pass -- where we convert the instructions into machine code. Now, that machine code, in the case of EconoJIT, is actually very simple in that it just builds a list of calls and push instructions, and calls to runtime helpers. Then it sets off on that list instead. And, of course, that code executes much faster than interpreted code.

Osborn:
So, let me run through this: You're completely compiling the code. Then, when you're done, the bits are ready to run completely, though the point at which translation from IL to machine code occurs may vary.

Hejlsberg:
Yes. But then we may, if it's in a memory-constrained environment on a small device, throw the code away after we've run it.

Osborn:
Jumping back to the particulars of language syntax: I'm wondering whether C# includes built-in support for regular expressions. I didn't see that support in the language reference, but maybe it's somewhere else.

Hejlsberg:
First of all, there's a regular expression class in the base-class libraries. We don't have any direct support in the language for regular expressions, but we do have some features that are actually very similar. It's not worth making a big deal about them, but, for example, we give you the ability to write verbatim string literals where you don't have to write two back slashes every time you want to specify one. It actually helps a whole bunch when you're writing regular expressions and when you're writing quotes within quotes. That's a little thing that helps, but clearly the core is in the .NET framework, which can be shared by all programming languages.

Osborn:
There appears to be a difference in the way we should view namespaces in C# and Java. Are they conceptually the same or are they implemented differently.

Hejlsberg:
Conceptually, yes, but they are implemented very differently. In Java, package names are also a physical thing that dictates the directory structure of your source code files. In C#, we have a complete separation between physical packaging and logical naming, so whatever you call your namespaces has nothing to do with the actual physical packaging of your code. That gives you a lot more flexibility to package things together in physical distribution units without forcing you to also have a bunch of directories. In the language itself, there are clearly some differences. In Java, the packaging is also your physical structure, and because of this a Java source file has to be in the right directory and can only contain one public type or one public class. Since C# does not have that sort of marriage between physical and logical, you can name your source files anything you want. Each source file can contribute to multiple namespaces and can take multiple public classes. Further, you can choose to write all of your sources in one big file if you like, or you can spread them across smaller files. Conceptually, what happens with C# at compilation is that you give the compiler all of the source files that make up your project and then it just goes off and figures out what to do.

Osborn:
I have a question about generic programming: Do you think it is an important concept, one that ought to be part of an object-oriented language? And if so, what are your plans to make generic programming a part of C#.

Goodhew:
Well, some of what we had hoped to include in the first release has been constrained because -- unlike what everyone believes about Microsoft -- we do not have unlimited resources. We had to make some hard decisions in terms of what is actually in this first release.

Osborn:
How many people were involved in the development of C#?

Hejlsberg:
The language design team consisted of four people. The compiler team had another five developers.

Petrusha:
What about the framework?

Hejlsberg:
That's much bigger. The whole company is involved.

Goodhew:
In terms of the entire Visual Studio and .NET platform group, we are about a thousand-person division. That includes program management, developers, testers, all the build functions, the frameworks, the runtimes, the ASP programming models, and then all of the people like myself, the management overhead.

Hejlsberg:
But with respect to the generics that you asked about, I definitely think generics are a very useful concept and you can certainly tell that from all the generics research that's taking place in academia and industry. Templates are one solution to the problem. In our internal discussions, we concluded that we wanted to do it right for this new platform. But what we would really like is to have generics understood by the underlying runtime. This is different from how some of the generic prototypes have been built. Take Java's notions of "erasure" where there's really no knowledge of generics in the system. By having the common language runtime understand the concept of generics, multiple languages can share the functionality. You can write a generic class in C# over in one place and someone else using a different language can use it.

But making generics part of the runtime also enables you to do certain things much more efficiently. Instantiation of generics should ideally happen at runtime. With C++, instantiation of templates happens at compile time, and then you have two options: you can either let your code bloat or you can try, in the linker, to get rid of some of the bloat. But, if you have multiple applications, you can forget about it. You're just going to get bloated code.

If you push the knowledge of generics into the common language runtime, then the runtime can understand that when an application or a component asks for a list of "Foo's," it should first ask: "Do I already have an instantiation of a list of "Foo?" If so, use that one. Indeed, if Foo is a reference type, and if we do the design right, we can share the instantiation for all reference types. For value types, such as ints and floats, and we can create one instantiation per value type. But only when an application asks for it. We've done a lot of the design work and groundwork necessary to add generics to the runtime.

It's interesting you asked earlier about the IL because deciding to add generics impacts the design of the IL. If the instructions in the IL embed type information -- if, for example, an Add instruction is not an Add, but is an Add int or an Add float or an Add double -- then you've baked the type into the instruction stream and the IL is not generic at that point. Our IL format is actually truly type neutral. And, by keeping it type neutral, we can add generics later and not get ourselves into trouble, at least not as much trouble. That's one of the reasons our IL looks different from Java byte code. We have type neutral IL. The Add instruction adds whatever the two things are on top of the stack. In a generic world, that could translate into different code when the generic is instantiated.

Osborn:
Is that available to all .NET languages?

Hejlsberg:
Yes. Microsoft Research in Cambridge has created a generics version of the common language runtime and the C# compiler. We're looking at how to move that forward right now. It's not going to happen in the first release, that much we know, but we are working on making sure that we do things right for the first release so that generics fit into the picture.

Osborn:
What are the planned release dates for C#, the .NET framework, and the next version of Visual Studio?

Goodhew:
Well, we've brought the technology preview to the 6,500 attendees here at PDC. We expect to go to beta sometime in the fall (2000), and then we'll release when ready. One of the really exciting things we've done is take a good solid look at how the Windows 2000 launch release went and the way we involved key customers in the joint development and the joint deployment process. In the case of .NET framework and Visual Studio .NET, we will again work with customers to determine when the final product is ready to release. We're going to let them tell us when the product is ready. And, because we've got real customers involved in the process, we should get a much better product in terms of quality. The downside of that is the process then becomes a little indeterminate. This is a fundamental change. We are looking to hit a quality bar for the release of the product rather than just pick an arbitrary date and say we'll ship.

Osborn:
So, instead of a code completion date, we're looking at a "ready-to-go" date?

Goodhew:
Yes, that's right. I think developers will find the release of Visual Studio .Net to be one of the highest quality releases in Microsoft's history.

Osborn:
You have submitted C# to ECMA. Is standardization really a serious objective? Would you like C# to be available on other platforms?

Hejlsberg:
Absolutely. It's certainly our objective to present C# to the industry as a possible standard, which is why we've submitted it to ECMA. We certainly hope to gain support in ECMA for a process that will lead to a commonly designed language which has a common language infrastructure. And what I mean by a common infrastructure is the core set of class libraries this specification entails, such that if other companies using other platforms implement it, they could reasonably expect to find those classes available to their programs.

Goodhew:
I might point out that we're taking a true open standards approach with ECMA. When and if ECMA actually arrives at a standard for C# and a common language infrastructure, the result will be available under ECMA's copyright and licensing policies, which are truly open. Any customer, and any person, will be able to license the ECMA C# standard, subset it, superset it, and they won't have to pay royalties. They'll be able take it and go implement it on any platform or any device. We fully expect people to do that. That is something fundamentally different from our competitors who wandered around the standards bodies, looking for someone to rubber-stamp their proprietary languages.

John:
One question I heard at breakfast and lunch was: "How is portability really possible on a platform that doesn't have Microsoft COM baked into its infrastructure?"

Hejlsberg:
It's completely possible. COM is not a must for standardization of C# and a common language infrastructure. Not at all. C# has a class model that is completely rich, whereas COM is just another view of how applications can interoperate. But there's nothing in C# or the core common runtime that says there must be COM, GUIDS, HRESULTS, AddRefs, or Releases. There's none of that. The .NET common language runtime completely eliminates that. But it gives you great interoperability with COM, which I will continue forever to think is super important for the reason I gave earlier. But it's not a prerequisite at all.

Goodhew:
I think some of those comments were inspired by the initial version of the language reference that we provided to the public. Microsoft wrote it in Microsoft meetings in which we were thinking primarily in terms of Microsoft platforms. As a result, we make references to things like COM and DLLs in the spec when really a DLL is a specific case of the more general problem of how to invoke native code on a given platform. One of the benefits of going to a standards organization and working with people like IBM, with whom we worked on the SOAP specification, is that we ensure we don't make any such references that tie us or lock us into something like the COM framework in future versions of the specification.

As Anders said, COM interop and COM support is critically important to us and to existing Microsoft customers. I think we've done a great job supporting COM on the .NET platform. But people in the industry have been reading too much into our use of the words COM and DLL. They conclude that the .NET platform is for Windows platforms only, and that's absolutely incorrect.

Hejlsberg:
And I think that just as COM interop is important to Microsoft and to customers who are building solutions on Microsoft platforms, a standardization of C# and the common language infrastructure should allow for other implementations to add meaningful interop with any platform on which they choose to implement the language.

Osborn:
So you won't insist on there being a "pure C#" or a "pure .NET" implementation?

Hejlsberg:
What's "pure?" How many "pure" Java applications really exist? I venture to guess very, very few. That's what the numbers I'm seeing suggest. Let's face it, people need to leverage their existing code. It's just not possible to require companies to throw everything away.

Goodhew:
Have you had a chance to talk to Roger Sessions? [Editor's Note: Roger Sessions is president of ObjectWatch and the author of COM+ and the Battle for the Middle Tier.]

Osborn:
No, I haven't.

Goodhew:
Roger got the relevant section out of the Enterprise JavaBeans [EJB] specification, which talks about permissible vendor extensions. Not surprisingly, the vendor extensions include things like transactions management, which is fairly important in building enterprise systems, as well as security, messaging, and more. In an article, Sessions lists roughly eleven areas of functionality, which are vendor specific implementations that are permitted. So, if you pick IBM Websphere as your EJB implementation, the code that you write for your EJB application will inevitably lock you into Websphere. This notion that Java is 100% pure and gives you 100% portability just isn't true. There's a great interview with James Gosling on IBM's developer works site in which he directly addresses this issue. He said, yeah, the whole write-once-run-anywhere, 100%-pure-thing was a really goofy idea, and was more of a marketing thing. He says, in effect, "We didn't think we'd ever be able to deliver all that, and basically we haven't." Here's the inventor of the language saying that neither purity nor portability exists.

Osborn:
Have we missed any untold great features or innovations in C# that you'd like to talk about?

Hejlsberg:
There's one thing about the whole .NET framework and, by implication, about C# as well, that I'd like to mention, and that's the shift in how you build distributed applications. Not so long ago we were building two-tier client server apps, and then object protocols such as CORBA, IIOP, RMI, and DCOM came along. That type of programming is really the underpinning of an EJB, which is implemented as either CORBA or RMI underneath. We have learned to build these strongly connected distributed systems, but they don't scale. They just don't scale on the Web because they're stateful, they hold state on the server, and you can't just roll in another machine, plug it into the farm and have the thing replicate itself.

When we first sat down to design the .NET framework we took a step back and looked at what's actually happening on the Web. It's becoming this loosely connected, very distributed world, and we tried to understand what that does to your underlying programming model. And so we designed from the ground up with the assumption in place that distributed apps are built in a loosely connected, stateless fashion that gives you great scalability. You just scale out. You roll in more racks and plug them in. And once you make that fundamental assumption, it changes everything. It changes how you design your basic services, how you design all your messaging, and it even changes how you design your UI. It's a new programming model. We have chosen to use XML and SOAP as the means to make this model work. They are deeply integrated into .Net and this integration is so core to every decision we have made in designing the .NET framework that it's not something you could just walk in and sprinkle on later.

Osborn:
Could you point to one specific place where this would be evident to a programmer?

Hejlsberg:
One fairly good example of this is how XML integrates with C#. We have this notion of "attributes" in C# that allows you to add declarative information to types and members. Just as you can say a member is public or private, you also want to be able to say this one's transacted, or this one's supposed to be a Web service, or this one is supposed to be serializable as XML. So we've added attributes to provide this generic mechanism, but then we utilize it in all of our Web services and XML infrastructure. We also give you the ability to put attributes on classes and on fields in your classes that say: "When this class goes to XML, it needs to become "this" tagname in XML and it needs to go into "this" XML namespace. You want to be able to say a specific field in one place becomes an element, and that another becomes an attribute. You also want to control the schema of the XML that goes out; control it where you're writing your class declaration, so that all of the additional declarative information is available. When attributes are properly used in this way to decorate your C# code, the system can simply turn a specific class into XML, send it over the wire, and when it comes back we can reconstitute the object on the other side. It's all done in one place. It's not like additional definition files or assorted infos and naming patterns. It's right there. It gives you statement completion when you build it in the IDE, and we can then provide you with higher-level tools that do the work for you.

I know I'm on a tangent here, but some of the infrastructure we provide is truly exciting. Simply because we have these attributes, you can ask our XML serialization infrastructure or our Web services infrastructure to translate any given class into XML. When you do, we'll actually take the schema for the class, the XSD schema, and we'll build a specialized parser that derives from our generic XML parser (which is part of the .NET base classes), and then override methods and add logic into the parser so that it is specialized for that schema. So we've instantiated a parser that at native code speed can rip through XML. If it's not correct, we'll give you a nice error message, which tells you precisely what went wrong. Then we cache it in our code-caching infrastructure, and it sits around until the next time a class with an identical schema comes by and it just goes, "Bam!" I mean, incredible, incredible throughput.

Osborn:
So, there's a lot of really interesting engineering under the covers.

Hejlsberg:
Yeah, and I just think that we're a generation ahead when it comes to the thinking in this space.

Osborn:
Great. Thanks for your time.

Hejlsberg:
You're welcome.

Sabtu, 23 Mei 2026

Jumat, 22 Mei 2026

All About Scripting

 

All About Scripting

 

Nancy Winnick Cluts
Microsoft Corporation

October 27, 1997

Contents

Introduction
What Scripting Is, and Why and When to Use It
VBScript
JScript
Using Both VBScript and JScript
Server-Side Scripting
Scriptlets
Is Scripting Just for Browsers?
Scripting Resources

Introduction

In the beginning, there was HTML.
And the hordes used HTML to produce Web pages.
And they looked at the Web pages, and saw that they were good.
But after a time, visitors to the Web sites grew restless and bored with the Web sites.
They clamored for more.
They wanted the page to interact with them.
They wanted dynamic content.
The hordes were also restless.
They wanted to be able to provide different content in different contexts.
Thus, the notion of scripting was born.

Okay, maybe I'm being just a tad dramatic. But it's a lot more poetic than telling you that scripting HTML is like creating a Microsoft Excel macro: You create your spreadsheet data and create a macro to dynamically update rows or columns based on a specified calculation. With scripting, you write your HTML code and create scripts to take action based on user input or variables.

In this article, I am going to talk about what scripting is and why you might want to use it. I'll give you some information about the different scripting languages (Visual Basic® Scripting Edition [VBScript] and JScript™) that are available and include examples of scripting. I'll also provide information about server-side scripting and, at the end of this article, a list of links to resources for more information about scripting.

What Scripting Is, and Why and When to Use It

Scripting enables you to set and store variables, and work with data in your HTML code. Many Web sites now employ scripting to check the browser a user is running, validate input, work with applets or controls, and communicate to the user. Let's say that you are creating a Web site that contains a form for ordering ballet tickets. Users can choose the ballet they want to see by entering the title. Now let's say a user types in "Swine Lake." Well, if she were looking for a version starring Miss Piggy, that might be correct, but most ballet companies actually perform "Swan Lake." You could use scripting to validate the name of the ballet and, if the name is not valid, you can display a message box alerting the user to type in a valid name (and even suggest what the correct name might be).

Scripts can be used in harmony with controls or applets, too. In the example above, you could write an applet that gathers the names of the ballets playing during the season and provide that information to the user in a list box. You could use scripting to validate the information once it was chosen or to confirm the order with the user.

Two of the most popular scripting languages today are ECMAScript (formerly known as JavaScript) and VBScript. You can use any scripting language you like as long as your audience's browsers support it. In fact, you can use a combination of scripting in your HTML source code. In the following sections of this article, I will give you more information about VBScript and JScript and provide you with a few examples of each scripting language.

VBScript

Visual Basic Scripting Edition, also known as VBScript, enables authors to create scripts using a subset of the Microsoft Visual Basic language. If you are already a Visual Basic programmer, or if you are not a programmer but are looking for a scripting language that is easy to learn, VBScript might be the right language for you. VBScript is implemented as a fast, portable interpreter for use in Web browsers and applications that use ActiveX™ controls, Java applets, and OLE Automation servers.

VBScript is a strict subset of the Visual Basic for Applications language that is used in popular applications such as Microsoft Excel, Microsoft Access, Microsoft Project, and the Visual Basic 4.0 development system. VBScript was designed to be fast, so it does not support the use of strict types—it only supports the use of Variants. It also must be safe for the World Wide Web, so it does not include functionality that directly accesses the client machine's operating system or file system. For example, you cannot do file I/O or read the registry on the client machine.

VBScript provides support for three separate classes of objects:

  • Objects provided by the VBScript engine (the core run-time functionality with a minimal set of basic Visual Basic objects)
  • Objects provided by Internet Explorer
  • Objects provided by the VBScript author (that the Web author creates and/or inserts herself through the <OBJECT> HTML tag)

Examples

These examples are all available for testing and viewing from the VBScript Web site in the samples section I'm showing you only a few of the samples the site has to offer.

Example 1: Hello World

Let's start with the classic Hello World example using VBScript. The following code shows you how simple it is to create a button (by using INPUT TYPE=BUTTON) that, when clicked (Sub BtnHello_OnClick), displays a message box (MsgBox) with the text, "Hello, world!":

<CENTER>
 <P>
 <H2>Hello, world sample</H2>

 <INPUT TYPE=BUTTON VALUE="Click me" NAME="BtnHello">
</CENTER>

<SCRIPT LANGUAGE="VBScript">
<!--
 Sub BtnHello_OnClick
  MsgBox "Hello, world!", 0, "My first active document"
 End Sub
-->
</SCRIPT>

That was pretty simple. Of course, many of us aren't going to use scripting to simply put up a box that says "Hello, world!" Let's move on to a more realistic example.

Example 2: Client-Side Validation

The Ordering Flowers example demonstrates how you can use VBScript to create a form and gather and validate data given by the user. This form can be used for ordering flowers It uses radio buttons (INPUT TYPE=RADIO NAME) to enable the user to choose which type of card to include with the flowers, text input fields (INPUT NAME=) to gather information on where to send the flowers, and a button (INPUT TYPE=BUTTON) to submit the request. Here is the HTML source code:

 <INPUT TYPE=RADIO NAME=OptOccasion CHECKED> Birthday

 <INPUT TYPE=RADIO NAME=OptOccasion> Anniversary

 <INPUT TYPE=RADIO NAME=OptOccasion> Get well soon


<FONT SIZE=3>
<B>When and where should the flowers be sent?</B>
</FONT>
<BR>

 Date <INPUT NAME=TxtDate  SIZE=60>
 Name <INPUT NAME=TxtName  SIZE=60>
 Address  <INPUT NAME=TxtAddress SIZE=60>
 City <INPUT NAME=TxtCity  SIZE=60>
 State <INPUT NAME=TxtState  SIZE=60>
 Zip code <INPUT NAME=TxtZip  SIZE=60>
 <INPUT TYPE=BUTTON VALUE="Submit" NAME="BtnSubmit">
 <INPUT TYPE=BUTTON VALUE="Clear" NAME="BtnClear">
 <INPUT TYPE=BUTTON VALUE="Init" NAME="BtnInit"><BR>

Now that we have a place to put the information, VBScript code is used to validate the data. The fields are initialized when the window is loaded (Sub Window_OnLoad()) in the BtnInit_OnClick() function.

<SCRIPT LANGUAGE="VBScript">
<!-- Option Explicit

 Dim strMsgBoxTitle
 Dim bValidOrder

 Sub Window_OnLoad
  strMsgBoxTitle = "MSFTD"
  Call BtnInit_OnClick
 End Sub

 Sub BtnInit_OnClick
  TxtName.Value = "Joe Smith"
  TxtAddress.Value = "1 Main Street"
  TxtCity.Value = "Springfield"
  TxtState.Value = "Washington"
  TxtZip.Value = "12345"

  TxtDate.Value = Date + 3
 End Sub

When the user clicks the Submit button, VBScript code is used again to validate the input. In the function BtnSubmit_OnClick(), each text field is checked for valid entry. The function CheckSpecified() checks for non-null entries and that the delivery date is reasonable. If it's not, a message box displays this message: "Not even we can deliver that fast!"

 Sub BtnSubmit_OnClick
  bValidOrder = True

  Call CheckSpecified(txtName.Value,  "Please specify a name.")
  Call CheckSpecified(txtAddress.Value,  "Please specify an address.")
  Call CheckSpecified(txtCity.Value,  "Please specify a city.")
  Call CheckSpecified(txtState.Value,  "Please specify a state.")
  Call CheckSpecified(txtZip.Value,  "Please specify a zip code.")
  Call CheckSpecified(txtDate.Value,  "Please specify a date.")
  Call ValidateDeliveryDate

  If bValidOrder Then
   MsgBox "Thank you for your order!", 0, strMsgBoxTitle

   ' TODO:  Actually send the order.
  End If
 End Sub

 Sub ValidateDeliveryDate
  Dim SoonestWeCanDeliver
  Dim RequestedDate

  If Not bValidOrder Then Exit Sub

  SoonestWeCanDeliver = Date + 2
  RequestedDate = CDate(TxtDate.Value)
  If RequestedDate < SoonestWeCanDeliver Then
   bValidOrder = False
   MsgBox "Not even we can deliver that fast!", 0, strMsgBoxTitle
  End If
 End Sub

 Sub CheckSpecified(ByVal strFieldValue, ByVal strMsg)
  If strFieldValue = "" And bValidOrder Then
   MsgBox strMsg, 0, strMsgBoxTitle
   bValidOrder = False
  End If
 End Sub

 Sub BtnClear_OnClick
  TxtName.Value = ""
  TxtAddress.Value = ""
  TxtCity.Value = ""
  TxtState.Value = ""
  TxtZip.Value = ""
  TxtDate.Value = ""
 End Sub
-->
</SCRIPT>

Example 3: Cookies

The last VBScript example I will show you is Maintaining State with Cookies This example shows you how easy it is to save values across Web pages using cookies. Users can click buttons to read a variable, save a variable, remove a variable, read a cookie, and flip Web pages. To use this example, go ahead and click the Save Variable Button. The following VBScript is run:

     Sub SetVariable(strVariableName, varVariableValue)
         Document.Cookie = strVariableName & "=" & varVariableValue
     End Sub

I am creative, so I picked test as the variable and 1 as the value. Then I clicked the Read Variable button to see that the right variable was set. It was. Then I checked to see if the value was actually saved across Web pages by clicking the Next Page button and clicking Read Variable on that page. The following VBScript reads the variable I entered on the previous page:

 Function ReadVariable(strVariableName)
  'these five variables are used in the string manipulation
  'code that finds the variable in the cookie.
         Dim intLocation
  Dim intNameLength
  Dim intValueLength
  Dim intNextSemicolon
  Dim strTemp

  'calculate length and location of variable name
  intNameLength = Len(strVariableName)
  intLocation = Instr(Document.Cookie, strVariableName)

  'check for existence of variable name
  If intLocation = 0 Then
      'variable not found, so it can't be read
      ReadVariable = NOT_FOUND
  Else
      'get a smaller substring to work with
      strTemp = Right(Document.Cookie, Len(Document.Cookie) - intLocation + 1)

      'check to make sure we found the full string, not just a substring
      If Mid(strTemp, intNameLength + 1, 1) <> "=" Then
          'oops, only found substring, not good enough
   ReadVariable = NOT_FOUND

   'note that this will incorrectly give a not found result if and only if
   'a search for a variable whose name is a substring of a preceding
   'variable is undertaken.  For example, this will fail:
   '
   'search for:  MyVar
          'cookie contains:  MyVariable=2;MyVar=1
      Else
   'found full string
   intNextSemicolon = Instr(strTemp, ";")

   'if not found, then we need the last element of the cookie
   If intNextSemicolon = 0 Then intNextSemicolon = Len(strTemp) + 1

   'check for empty variable (Var1=;)
   If intNextSemicolon = (intNameLength + 2) Then
       'variable is empty
       ReadVariable = ""
   Else
       'calculate value normally
             intValueLength = intNextSemicolon - intNameLength - 2
       ReadVariable = Mid(strTemp, intNameLength + 2, intValueLength)
   End If
      End If
        End if
    End Function

JScript

JScript is Microsoft's implementation of an ECMA-compliant scripting language (like JavaScript) that is targeted specifically to the Internet. Like VBScript, JScript is implemented as a fast, portable interpreter for use in Web browsers and applications that use ActiveX controls, Java applets, and OLE Automation servers. JScript is not Java and has nothing to do with Java. It is closer in syntax to C or C++. If you are a C or C++ developer, you will probably find JScript to be a very easy scripting language to learn (I know I did).

Also like VBScript, JScript supports three separate classes of objects for use within JScript:

  • Objects provided by the JScript engine
  • Objects provided by Internet Explorer (found in the Microsoft Scripting site.
  • Objects provided by the Web page author via the HTML <OBJECT> tag.

JScript? JavaScript? ECMAScript? What's the Deal Here?

You may be confused by the term ECMAScript that I've been using in this article. You're in good company. Here's the deal. ECMA (European Computer Manufacturers Association) is a European-based association for standardizing information and communications systems. The standard recently approved, known as ECMA-262, is based on joint submissions from Microsoft and Netscape. JScript 3.0 is Microsoft's implementation of the new ECMA-262 scripting language. JavaScript is a scripting language written by Netscape that preceded the ECMA standard. Basically, when talking about JScript or JavaScript, we are talking about implementations of the same standard scripting language, ECMA—the implementations are just marketed by different companies.

Examples

These examples are available for testing and viewing from the JScript Web site. As with the VBScript examples, I'm showing only a sampling of what they have to offer. You may experience a sense of déjà vu in this section because two of the JScript examples are the same as the VBScript examples. They are a bit different in how they work. I decided to show you examples that show off VBScript and JScript rather than trying to cobble together an example that shows only syntax variation (if I did that, I'd run the risk of showing you either VB-like JScript or C-like VBScript). Let's start with the perennially popular Hello World example.

Example 1: Hello World

The Hello World example is the bare-bones JScript example. It provides a button that, when clicked, displays a message box with the text, "Hello, world!"

<CENTER>
 <P>
 <H2>Hello, world sample</H2>

 <FORM Name="Form1" ACTION="">
 <INPUT TYPE=BUTTON VALUE="Click me"
  NAME="BtnHello"
  OnClick="sayhello()"
 >
 </FORM>

</CENTER>

<SCRIPT LANGUAGE="JavaScript">
<!--

    function sayhello ()
    {
        alert("Hello, world!")
    }

//-->
</SCRIPT>

Here again, HTML code is used to set up the button and JScript is used to perform an action (displaying the message box using the alert function) when the button is clicked.

Example 2: Client-Side Validation

The second ordering flowers example demonstrates client-side validation using JScript. As in the VBScript example, this example uses radio buttons to enable the user to choose which type of card to include with the flowers, text input fields to gather information on where to send the flowers, and a button to submit the request. The HTML source code is the same for this example as it is for the VBScript example, so I won't show it here. What is different, however, is the script. The following JScript code is used to do client-side validation:

<SCRIPT LANGUAGE="JavaScript">
<!--
 var bValidOrder
 var f = document.form1

 function Init()
 {
  var d
  document.form1.TxtName.value = "Joe Smith"
  document.form1.TxtAddress.value = "1 Main Street"
  document.form1.TxtCity.value = "Springfield"
  document.form1.TxtState.value = "Washington"
  document.form1.TxtZip.value = "12345"

  d = new Date()
  d.setDate(d.getDate() + 3)
  f.TxtDate.value = (d.getMonth() + 1) + "/" + d.getDate() +
   "/" + d.getYear()
 }

 function SubmitOrder()
 {
  bValidOrder = true

  CheckSpecified(f.TxtName.value,"Please specify a name.")
  CheckSpecified(f.TxtAddress.value,"Please specify an address.")
  CheckSpecified(f.TxtCity.value,"Please specify a city.")
  CheckSpecified(f.TxtState.value,"Please specify a state.")
  CheckSpecified(f.TxtZip.value,"Please specify a zip code.")
  CheckSpecified(f.TxtDate.value,"Please specify a date.")

  ValidateDeliveryDate()

  if (bValidOrder)
  {
   alert("Thank you for your order!")
   // TODO:  Actually send the order.
  }
 }

 function ValidateDeliveryDate()
 {
  var SoonestWeCanDeliver
  var RequestedDate
  var t

  if (bValidOrder)
  {
   SoonestWeCanDeliver = new Date()
   SoonestWeCanDeliver.setDate(SoonestWeCanDeliver.getDate() + 2)
   t = Date.parse(f.TxtDate.value)
   RequestedDate = new Date()
   RequestedDate.setTime(t)

   if (RequestedDate.getTime() < SoonestWeCanDeliver.getTime())
   {
    bValidOrder = false
    alert("Not even we can deliver that fast!")
   }
  }
 }

 function CheckSpecified(strFieldValue, strMsg)
 {
  if (strFieldValue == "")
  {
   if (bValidOrder)
   {
    alert(strMsg)
    bValidOrder = false
   }
  }
 }

 function Clear()
 {
  f.TxtName.value = ""
  f.TxtAddress.value = ""
  f.TxtCity.value = ""
  f.TxtState.value = ""
  f.TxtZip.value = ""
  f.TxtDate.value = ""
 }
//-->
</SCRIPT>

Using Both VBScript and JScript

Although there are two different scripting languages, they can peacefully coexist on the same Web page. There's an example on the Internet Explorer Web site that demonstrates a mortgage calculator implemented with VBScript or JScript. Just click the button to choose which script to run and view the source for all of the details. It's interesting to see what code that performs identical tasks looks like in two different languages.

Server-Side Scripting

Server-side scripting is scripting done on the server. Well, that's the easy definition. It enables you to run scripts on the server rather than on the client machine. This works well for information that can be stored in a central place (like a database). With server-side scripting, you can enable visitors to your site to have personalized views of the content you offer. The script on the server can conditionally show or not show content that the user has requested, based on information kept in a database on the server.

To implement server-side scripting, you use Active Server Pages (ASP). ASP technology is built directly into Microsoft Web servers. It is supported on Windows NT® running Internet Information Services (IIS) 3.0, Windows NT Workstation 4.0 running Peer Web Services, and Windows® 95 Personal Web Server. If you want to use Active Server Pages with either Personal Web Server on Windows 95 or Peer Web Services on Windows NT Workstation 4.0, you must install the Active Server Pages components after installing your server software. These components are not distributed with the Setup programs for Personal Web Server or Peer Web Services. To register and download the Setup program for these components, go to the Internet Information Server 3.0 page and click the Download link.

To use server-side scripting, create a file with an ASP extension, for example, filename.asp. The file may contain any combination of HTML, scripting (such as VBScript or JScript), and calls to components (ActiveX controls or Java applets written by yourself or bought off the shelf). ASP files on the server can be updated at any time. Simply save the changes to the file and the script will be automatically compiled the next time the Web page is loaded.

ASP includes five standard objects for global use:

  • Request—To get information from the user
  • Response—To send information to the user
  • Server—To control the Internet Information Server
  • Session—To store information about and change settings for the user's current Web-server session
  • Application—To share application-level information and control settings for the lifetime of the application

Like scripting in HTML, which uses <!-- and --> as delimiters, ASP uses delimiters too. ASP uses <% and %> to enclose script commands. The scripting languages supported by ASP include VBScript and JScript and enable you to provide some real logic to the HTML code that your ASP script sends to the browser. The following example (from the troubleshooting techniques provided by the IIS team) demonstrates how ASP can be used with VBScript to process a logon request:

<%@ LANGUAGE="VBSCRIPT" %>
<!-- FILE: login.asp -->
<HTML>
<HEAD>
<TITLE>Login Example</TITLE>
</HEAD>
<BODY>

<% IF IsEmpty(Request.Form("Name")) THEN
 Response.Write "Please enter your Name"
%>
 <FORM ACTION="login.asp" METHOD=POST>
  <INPUT NAME="Name"
  TYPE=TEXTBOX MAXLENGTH=20>
 <INPUT TYPE="SUBMIT" VALUE="Submit">
 </FORM>
<%
 ELSE
'User verification code goes here Response.Write "Welcome " & Request.Form("Name") & "!"
END IF
%>

</BODY>
</HTML>

Scriptlets

One new technology (with a name that sounds amazingly like a type of candy) is scriptlet technology. Scriptlet technology enables Web authors create reusable objects using Dynamic HTML. The concept of scriptlets is simple: they are Web pages that contain script written according to specified conventions. To use a scriptlet, insert an <OBJECT> tag into another Web page and invoke the scriptlet by its standard URL. In Internet Explorer 4.0, the syntax for marking an object as a scriptlet is the MIME type text/x-scriptlet.

Is Scripting Just for Browsers?

I've talked a lot about scripting in the context of a Web browser, but you can also use the Windows Script Host to use script outside of a browser. The Microsoft Script Host is a language-independent scripting host for ActiveX scripting engines on 32-bit Windows platforms. In the future, the Windows Script Host will be integrated into Windows 98, Windows NT Workstation version 5.0, and Windows NT Server version 5.0. Currently, the VBScript and JScript engines are provided with the Windows Script Host. It can be run either from the command line (cscript.exe) or through Windows (wscript.exe). The Windows Script Host is ideal for non-interactive scripts that perform administrative tasks. Full documentation for the Windows Script Host is available from the Microsoft Scripting site.

Scripting Resources

This article is designed to provide you with some background information about scripting in general and to give you pointers to more information. There's plenty of information on the Internet that covers scripting, including technical articles, documentation, Web sites, and samples. This list contains the promised pointers (in the form of links) to some of these resources. With these links in hand, you should be able to start your scripting today.

Flyout Menu With HTML COMPONENT, JScript, and XML (No SubMenu)

 







default.html

<HTML><HEAD>

<style>

.flyoutMenu {

BACKGROUND-COLOR: #f1f1f1; BEHAVIOR: url(default.htc); BORDER-BOTTOM: #999999 1px solid; BORDER-LEFT: #999999 0px solid; BORDER-RIGHT: #999999 1px solid; BORDER-TOP: #999999 0px solid

}

.flyoutHeading {

BACKGROUND-COLOR: #f1f1f1; CURSOR: default; FONT-FAMILY: Verdana, Arial, Helvetica; FONT-SIZE: 80%; FONT-WEIGHT: bold; PADDING-BOTTOM: 4px; PADDING-LEFT: 2px; PADDING-TOP: 2px

}

.flyoutLink {

BORDER-BOTTOM: #f1f1f1 1px solid; BORDER-LEFT: #f1f1f1 1px solid; BORDER-RIGHT: #f1f1f1 1px solid; BORDER-TOP: #f1f1f1 1px solid; CURSOR: hand; FONT-FAMILY: Verdana, Arial, Helvetica; FONT-SIZE: 80%; PADDING-LEFT: 6px; PADDING-RIGHT: 25px; PADDING-TOP: 1px

}

.flyoutMenu TD.flyoutLink {

BORDER-BOTTOM: #f1f1f1 1px solid; BORDER-LEFT: #f1f1f1 1px solid; BORDER-RIGHT: #f1f1f1 1px solid; BORDER-TOP: #f1f1f1 1px solid; CURSOR: hand; FONT-FAMILY: Verdana, Arial, Helvetica; FONT-SIZE: 80%; PADDING-BOTTOM: 3px; PADDING-LEFT: 6px; PADDING-RIGHT: 25px; PADDING-TOP: 1px

}

.flyoutLink A {

COLOR: black; TEXT-DECORATION: none

}

.flyoutLink A:hover {

COLOR: black; TEXT-DECORATION: none

}

.flyoutLink A:visited {

COLOR: black; TEXT-DECORATION: none

}

.flyoutLink A:active {

COLOR: black; TEXT-DECORATION: none

}

.flyoutSubHeading {

BACKGROUND-COLOR: #f1f1f1; CURSOR: default; FONT-FAMILY: Verdana, Arial, Helvetica; FONT-SIZE: 90%; FONT-WEIGHT: bold; PADDING-BOTTOM: 4px; PADDING-LEFT: 7px; PADDING-TOP: 2px

}

.flyoutSubLink {

BORDER-BOTTOM: #f1f1f1 1px solid; BORDER-LEFT: #f1f1f1 1px solid; BORDER-RIGHT: #f1f1f1 1px solid; BORDER-TOP: #f1f1f1 1px solid; CURSOR: hand; FONT-FAMILY: Verdana, Arial, Helvetica; FONT-SIZE: 90%; PADDING-BOTTOM: 3px; PADDING-LEFT: 11px; PADDING-RIGHT: 15px; PADDING-TOP: 1px

}

.flyoutSubLink A {

COLOR: black; TEXT-DECORATION: none

}

.flyoutSubLink A:hover {

COLOR: black; TEXT-DECORATION: none

}

.flyoutSubLink A:visited {

COLOR: black; TEXT-DECORATION: none

}

.flyoutSubLink A:active {

COLOR: black; TEXT-DECORATION: none

}

</style>

</head>

<BODY bgColor=#cccccc leftMargin=10 text=#000000 topMargin=10>

<h1>FLYOUT MENU</H1>

<TABLE border=0 cellPadding=2 cellSpacing=0 class=flyoutMenu 

            width=180 xmlns:msxsl="urn:schemas-microsoft-com:xslt" 

            menudata="menu.xml">

              <TBODY>

              <TR>

                <TD>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle="pt"><A 

                        href="metacreations.html">Metacreations 

                       </A> </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle=""><A 

                        href="directx.html">Direct X 

                        </A> </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle=""><A 

                        href="kode.html">Code Center</A> 

                      </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle="dl"><A 

                        href="dhtml.html">DHTML</A> 

                      </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle="ht"><A 

                        href="javascript.html">Java Script

                        </A> </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle="mg"><A 

                        href="animation.html">Animation 3D 

                        </A> </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle="col"><A 

                        href="dom.html">DOM 

                        </A> </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle=""><A 

                        href="css.html">CSS</A> 

                    </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle="devcom"><A 

                        href="xml.html">XML 

                        </A> </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle="train"><A 

                        href="http://msdn.microsoft.com/tce/">Training, Career 

                        &amp; Events</A> </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle="subscr"><A 

                        href="http://msdn.microsoft.com/subscriptions/">Subscriptions</A> 

                      </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle=""><A 

                        href="http://msdn.microsoft.com/partners/">Partners 

                        &amp; Certification</A> 

              </TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>

            <TABLE border=0 cellPadding=2 cellSpacing=0 class=flyoutMenu 

            width=180 xmlns:msxsl="urn:schemas-microsoft-com:xslt" 

            menudata="/menu.xml">

              <TBODY>

              <TR>

                <TD>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle=""><A 

                        href="http://msdn.microsoft.com/isapi/gomscom.asp?target=/technet/">IT 

                        Professionals</A> </TD></TR></TBODY></TABLE>

                  <TABLE border=0 cellPadding=0 cellSpacing=0 width=175>

                    <TBODY>

                    <TR>

                      <TD class=flyoutLink handle=""><A 

                        href="http://msdn.microsoft.com/architecture/">Architects</A> 

                      </TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>

</body>

</html>

===================================================

File : default.htc

<PUBLIC:COMPONENT>

<PUBLIC:PROPERTY NAME="menudata" />
<PUBLIC:METHOD NAME="show_flyout" />
<PUBLIC:METHOD NAME="kill_flyout" />
<PUBLIC:METHOD NAME="scroll" />
<PUBLIC:METHOD NAME="event_oncontentready" />
<PUBLIC:ATTACH EVENT="oncontentready" ONEVENT="event_oncontentready()" />

<SCRIPT language="JScript">
// modified by Dudi Gunawan graduated from UNIVERSITAS PENDIDIKAN INDONESIA, Bandung/////
// Copyright © 2001 Microsoft Corporation////////
// file name default.htc///

var IMAGES = ""
var MENU_WIDTH = 180
var MENU_BORDER_COLOR = '#999999'
var MENU_BACKGROUND_COLOR = '#ffffff'
var MENU_CURRENTPAGE_COLOR = '#ffffff'
var MENU_MOUSEOVER_COLOR = '#ffffff'
var MENU_MOUSEDOWN_COLOR = 'rgb(111,183,255)'
var MENU_SHADOW_COLOR = '#666666'
var FLYOUT_DELAY = 200
var KILL_DELAY = 300
var SCROLL_DELAY = 35
var SCROLL_PXPERSEC = 150
var MIN_FLYOUT_WIDTH = 100
var MAX_FLYOUT_WIDTH = 410

var global = window.document
global.fo_currentMenu = null
global.fo_shadows = new Array
global.fo_killTimer = null

var flyoutTimer = null
var scrollTimer = null
var flyoutCount = 0
var flyouts = new Array
var rowHeight = 0
var menuToShow = null
var scrollDelta = 0
var scrollStart = 0
var scrollTime = 0
var scrollArea = null
var contentReady = 0
var hideIFrames = true

function newid()
{
var id
do
id = 'id' + Math.random().toString().substr(2, 10)
while (global.all(id))
return id
}

function new_XML_document()
{
try
{
var doc = new ActiveXObject("MSXMl.DOMDocument")
return doc
}
catch(err)
{
return null
}
}

function event_oncontentready()
{
if (!global.firstFlyoutInstance)
{
global.firstFlyoutInstance = true
global.body.attachEvent("onmousemove", body_onmousemove)
}
if (this.id == '')
this.id = newid()
if (navigator.appVersion.indexOf("MSIE 5.0") == -1)
hideIFrames = false
var mdd = null
if (menudata)
if (menudata.substr(0, 1) == '#')
{
try 
{
mdd = eval(menudata.substr(1)).XMLDocument.documentElement
}
catch(ex)
{
window.setTimeout(this.id + ".event_oncontentready()", 100, "JScript")
return
}
}
else
{
var md = new_XML_document()
if (md)
{
md.async = false
md.load(menudata)
if (md.parseError.errorCode == 0)
mdd = md.documentElement
}
else
mdd = null
}

var items = this.all.tags("TD")
var i
var nParentItem = 0
var nParentLen = -1
var lhref = normalized_href(location.href)

for (i=0; i<items.length; i++)
{
var item = items[i]
if (item.className == "flyoutLink" || item.className == "flyoutSubLink")
{
var disabled = false
var anchors = item.all.tags("A")
if (anchors.length > 0)
{
var anchor = anchors.item(0)
var ahref = normalized_href(anchor.href)
if (ahref == lhref)
{
anchor.outerHTML = anchor.innerHTML
item.style.borderColor = MENU_BORDER_COLOR
item.style.backgroundColor = MENU_CURRENTPAGE_COLOR
item.style.cursor = 'default'
disabled = true
nParentItem = 0
nParentLen = 9999
}
else 
{
var slash = ahref.lastIndexOf("/")
if (slash == ahref.length - 1)
if (lhref.substr(0, slash + 1) == ahref)
if (ahref.length > nParentLen)
{
nParentItem = i
nParentLen = ahref.length
}
}
}
item.defaultBorder = item.style.borderColor
item.defaultBackground = item.style.backgroundColor
item.attachEvent("onmouseover", item_onmouseover)
item.attachEvent("onmouseout", item_onmouseout)
if (!disabled)
{
item.attachEvent("onmousedown", item_onmousedown)
item.attachEvent("onmouseup", item_onmouseup)
}
if (item.handle && mdd)
{
var sm = mdd.selectSingleNode("//submenu[@handle='" + item.handle + "']")
if (sm)
{
var fa = document.createElement("div")
fa.width = 4
fa.height = 7
fa.style.position = "absolute"
fa.style.left = MENU_WIDTH - 15
fa.style.marginTop = 4
fa.style.fontSize = "1px"
fa.style.backgroundImage = "url(" + IMAGES + "flyout_arrow.bmp)"
fa.style.width = "4px"
fa.style.height = "7px"
item.insertAdjacentElement("afterBegin", fa)
var table = document.createElement("table") //submenu
table.attachEvent("onmouseover", submenu_onmouseover)
table.attachEvent("onmouseout", submenu_onmouseout)
table.width = MAX_FLYOUT_WIDTH + 6
table.cellPadding = 0
table.cellSpacing = 0
table.className = "flyoutMenu"
table.style.border = "solid 1px " + MENU_BORDER_COLOR
table.style.position = "absolute"
table.style.left = MENU_WIDTH - 4
table.style.top = 0
table.baseTop = element_top(item) - 3
cell = table.insertRow().insertCell()
cell.style.padding = "2px 0px"
scrollArea = document.createElement("div")
scrollArea.id = newid()
cell.insertAdjacentElement("afterBegin", scrollArea)

upScroller = create_sublink('<center><div style="width: 15px; height: 16px; font-size: 1px"></div></center>')
upScroller.style.display = 'none'
upScroller.rows[0].cells[0].scroller = scrollArea
cell.insertAdjacentElement("afterBegin", upScroller)
downScroller = create_sublink('<center><div style="width: 15px; height: 16px; font-size: 1px"></div></center>')
downScroller.style.display = 'none'
downScroller.rows[0].cells[0].scroller = scrollArea
cell.insertAdjacentElement("beforeEnd", downScroller)
scrollArea.upScroller = upScroller
scrollArea.downScroller = downScroller

var it = sm.firstChild
var ic = 0
var j
var mi //menu item
while (it)
{
ic++
var tn = it.tagName
var att = it.attributes
if (tn == 'item')
{
var h = '<a href="' + att.getNamedItem("href").value + '">' + att.getNamedItem("label").value + '</a>'
mi = create_sublink(h)
}
else if (tn == 'heading')
mi = create_sublink(att.getNamedItem("label").value, "flyoutSubHeading")
else if (tn == 'separator')
mi = create_separator()
else
mi = create_sublink("", "flyoutSubHeading")
scrollArea.insertAdjacentElement('beforeEnd', mi)
it = it.nextSibling
}
global.body.insertAdjacentElement('afterBegin', table)
item.flyoutid = flyoutCount
flyouts[flyoutCount++] = table
var maxWidth = MIN_FLYOUT_WIDTH
for (j=0; j<ic; j++)
{
mi = scrollArea.childNodes(j)
if (mi.offsetWidth > maxWidth) 
maxWidth = mi.offsetWidth
}
if (maxWidth > MAX_FLYOUT_WIDTH)
maxWidth = MAX_FLYOUT_WIDTH
table.width = ''

rowHeight = scrollArea.childNodes(0).offsetHeight
for (j=0; j<ic; j++)
{
mi = scrollArea.childNodes(j)
mi.style.width = maxWidth + mi.widthAdjust
}

upScroller.style.width = maxWidth
downScroller.style.width = maxWidth
table.style.display = "none"
}
}
}
}
if (nParentItem != 0)
{
items[nParentItem].style.borderColor = MENU_BORDER_COLOR
items[nParentItem].defaultBorder = MENU_BORDER_COLOR
}
}

function normalized_href(href)
{
href = href.toLowerCase();
var slash = href.lastIndexOf("/");
if (-1 != slash) 
{
var filename = href.substr(slash + 1);
if ("default.htm" == filename || "default.asp" == filename)
href = href.substr(0, slash + 1);
}
return href;
}

function image_load(src)
{
var img = new Image()
img.src = src
return img
}

function item_onmouseover()
{
var e = whichItem()
if (e.contains(window.event.fromElement))
return
if (e.style.backgroundColor != MENU_CURRENTPAGE_COLOR)
{
e.style.borderColor = MENU_BORDER_COLOR
e.style.backgroundColor = MENU_MOUSEOVER_COLOR
}
if (e.submenu == null)
{
if (e.handle)
{
menuToShow = flyouts[e.flyoutid]
if (menuToShow)
menuToShow.baseTop = element_top(e) - 3
}
else
menuToShow = null
flyoutTimer = window.setTimeout(this.id + ".show_flyout()", FLYOUT_DELAY, "JScript")
}
else if (scrollArea = e.scroller) //not a "==" typo
{
if (e.offsetParent.offsetTop > scrollArea.offsetTop)
scrollDelta = +1
else
scrollDelta = -1
scrollStart = scrollArea.scrollTop
scrollTime = current_time()
scrollTimer = window.setInterval(this.id + ".scroll()", SCROLL_DELAY, "JScript")
}
var a = e.all.tags("A")
if (a.length > 0)
window.status = a[0].href
}

function current_time()
{
var temp = new Date()
return temp.valueOf()
}

function item_onmouseout()
{
var e = whichItem()
var te = window.event.toElement
if (te)
if (e.contains(te))
return
e.style.borderColor = e.defaultBorder
e.style.backgroundColor = e.defaultBackground
if (flyoutTimer)
{
window.clearTimeout(flyoutTimer)
flyoutTimer = null
}
if (gs = scrollTimer)
{
window.clearInterval(gs)
scrollTimer = null
}
window.status = ""
}

function whichItem()
{
var e = event.srcElement
while (e.tagName != "TD")
e = e.parentElement
return e
}

function item_onmousedown()
{
if ((event.button & 1) == 0)
return;
var e = whichItem()
e.style.backgroundColor = MENU_MOUSEDOWN_COLOR
e.mouseIsDown = 1
}

function item_onmouseup()
{
if ((event.button & 1) == 0)
return;
var e = whichItem()
if (e.mouseIsDown != 1)
return
e.mouseIsDown = false
e.style.backgroundColor = MENU_MOUSEOVER_COLOR
var a = e.all.tags("A")
if (a.length > 0)
top.location.href = a[0].href
}

function scroll()
{
var temp = scrollStart + Math.round((current_time() - scrollTime) * 0.001 * SCROLL_PXPERSEC) * scrollDelta
scrollArea.scrollTop = temp
upImg = scrollArea.upScroller.all.tags("DIV").item(0)
dnImg = scrollArea.downScroller.all.tags("DIV").item(0)
if (temp <= 0)
upImg.style.backgroundImage = "url(" + IMAGES + "ico_wir_xp1.bmp)"
else
upImg.style.backgroundImage = "url(" + IMAGES + "ico_support_xp.bmp)"
if (temp >= scrollArea.scrollHeight - scrollArea.offsetHeight)
dnImg.style.backgroundImage = "url(" + IMAGES + "ico_wir_xp.bmp)"
else
dnImg.style.backgroundImage = "url(" + IMAGES + "ico_support_xp1.bmp)"
if (scrollArea.scrollTop != temp)
{
window.clearInterval(scrollTimer)
scrollTimer = null
}
}

function remove_flyout()
{
if (global.fo_currentMenu)
{
var i
for (i=0; i<global.fo_shadows.length; i++)
global.fo_shadows[i].removeNode(true);
global.fo_shadows = new Array();
global.fo_currentMenu.style.display = 'none'
show_elements("SELECT")
show_elements("OBJECT")
if (hideIFrames) show_elements("IFRAME")
}
}

function show_flyout()
{
flyoutTimer = null
if (global.readyState != 'complete')
{
flyoutTimer = window.setTimeout(this.id + ".show_flyout()", 50, "JScript")
return
}
if (global.fo_currentMenu == menuToShow)
return

remove_flyout()

global.fo_currentMenu = menuToShow

if (menuToShow)
{
var menuChildren = menuToShow.rows[0].cells[0].childNodes
var upScroller = menuChildren(0).style
var scrollArea = menuChildren(1).style
var downScroller = menuChildren(2).style

upScroller.display = 'none'
downScroller.display = 'none'
scrollArea.overflow = 'visible'

var menuStyle = menuToShow.style
menuStyle.zIndex = 10
menuStyle.top = menuToShow.baseTop
menuStyle.display = ''

var docBody = global.body
var docTop = docBody.scrollTop
var screenHeight = docBody.clientHeight

if (menuStyle.posTop - docTop + menuToShow.offsetHeight > screenHeight)
{
menuStyle.posTop -= menuToShow.offsetHeight - 25
if (menuStyle.posTop < docTop)
{
menuStyle.posTop = (screenHeight - menuToShow.offsetHeight) / 2 + docTop - 2
if (menuStyle.posTop < docTop)
{
upScroller.display = '';
menuChildren(0).all.tags("DIV").item(0).style.backgroundImage = "url(" + IMAGES + "ico_wir_xp1.bmp)"
downScroller.display = '';
menuChildren(2).all.tags("DIV").item(0).style.backgroundImage = "url(" + IMAGES + "ico_support_xp1.bmp)"
scrollArea.overflow = 'hidden';

var vrows = Math.floor((screenHeight - 8) / rowHeight) - 2
if (vrows <= 0)
{
remove_flyout()
return
}

scrollArea.height = vrows * rowHeight
menuStyle.posTop = (screenHeight - menuToShow.offsetHeight) / 2 + docTop - 2
menuChildren(1).scrollTop = 0
}
}
}
makeRectangularDropShadow(menuToShow, MENU_SHADOW_COLOR, 4)
menuToShow.focus()
global.fo_muLeft = menuToShow.offsetLeft
global.fo_muRight = global.fo_muLeft + menuToShow.offsetWidth
global.fo_muTop = menuToShow.offsetTop
global.fo_muBottom = global.fo_muTop + menuToShow.offsetHeight
hide_elements("SELECT")
hide_elements("OBJECT")
if (hideIFrames) hide_elements("IFRAME")
}
}

function element_top(el)
{
var et = 0
while (el)
{
et += el.offsetTop
el = el.offsetParent
}
return et
}

function makeRectangularDropShadow(el, color, size)
{
var i;
for (i=size; i>0; i--)
{
var rect = document.createElement('div');
var rs = rect.style
rs.position = 'absolute';
rs.left = (el.style.posLeft + i) + 'px';
rs.top = (el.style.posTop + i) + 'px';
rs.width = el.offsetWidth + 'px';
rs.height = el.offsetHeight + 'px';
rs.zIndex = el.style.zIndex - i;
rs.backgroundColor = color;
var opacity = 1 - i / (i + 1);
rs.filter = 'alpha(opacity=' + (100 * opacity) + ')';
el.insertAdjacentElement('afterEnd', rect);
global.fo_shadows[global.fo_shadows.length] = rect;
}
}

function submenu_onmouseout()
{
var gc = global.fo_currentMenu
if (!gc) return
var event = window.event
if (!gc.contains(event.toElement))
{
if (event.x < MENU_WIDTH)
return
global.fo_killTimer = window.setTimeout(this.id + ".kill_flyout()", KILL_DELAY, "JScript")
event.cancelBubble = true
}
}

function submenu_onmouseover()
{
if (kt = global.fo_killTimer) //not a == typo
{
window.clearTimeout(kt)
global.fo_killTimer = null
}
}

function kill_flyout()
{
global.fo_killTimer = null
remove_flyout()
global.fo_currentMenu = ''
}

function body_onmousemove()
{
if (!global.fo_currentMenu)
return
if (global.fo_killTimer)
return
if (global.fo_currentMenu.contains(window.event.srcElement))
return
if (window.event.x < MENU_WIDTH)
return
kill_flyout()
}

function create_sublink(html, className)
{
var sublink = document.createElement("table")
sublink.cellPadding = 0
sublink.cellSpacing = 0
sublink.style.margin = "0px 2px"
sublink.widthAdjust = 0
var td = sublink.insertRow().insertCell()
if (!className) className = "flyoutSubLink"
td.className = className
td.submenu = "1"
td.innerHTML = html
return sublink
}

function create_separator()
{
var sep = document.createElement("table")
sep.cellPadding = 0
sep.cellSpacing = 0
sep.style.margin = "2px 0px"
sep.widthAdjust = 4
var td = sep.insertRow().insertCell()
td.width = "100%"
td.height = "1"
td.bgColor = MENU_BORDER_COLOR
return sep
}

function hide_elements(tagName)
{
windowed_element_visibility(tagName, -1)
}

function show_elements(tagName)
{
windowed_element_visibility(tagName, +1)
}

function windowed_element_visibility(tagName, change)
{
var els = global.all.tags(tagName)
var i
for (i=0; i < els.length; i++)
{
var el = els.item(i)
if (elements_overlap(el))
{
if (el.visLevel)
el.visLevel += change
else
el.visLevel = change
if (el.visLevel == -1)
{
el.visibilitySave = el.style.visibility
el.style.visibility = "hidden"
}
else if (el.visLevel == 0)
el.style.visibility = el.visibilitySave
}
}
}

function elements_overlap(el)
{
var left = 0
var top = 0
var width = el.offsetWidth
var height = el.offsetHeight
while (el)
{
left += el.offsetLeft
top += el.offsetTop
el = el.offsetParent
}
return ((left < global.fo_muRight) && (left + width > global.fo_muLeft) && (top < global.fo_muBottom) && (top + height > global.fo_muTop))
}

</SCRIPT>

</PUBLIC:COMPONENT>

====================================================

menu.xml

<?xml version="1.0"?>

<!--TOOLBAR_EXEMPT-->

<menu>

<menugroup>

<submenu handle="pt" href="/products/" label="Products &amp; Technologies">

<heading label="DXTransform" />

<item href="barn.html" label="Barn"/>

<item href="blinds.html" label="Blinds"/>

<item href="fade.html" label="Fade"/>

<item href="zigzag.html" label="Zigzag"/>

<item href="inset.html" label="Inset"/>

<item href="pixelate.html" label="Pixelate"/>

<item href="radialwipe.html" label="Radial Wipe"/>

<item href="slide.html" label="Slide I"/>

<item href="slide2.html" label="Slide II"/>

<item href="slide3.html" label="Slide III"/>

<item href="slide4.html" label="Slide IV"/>

<item href="slide5.html" label="Slide V"/>

<item href="slide6.html" label="Slide VII"/>

<item href="spiral.html" label="Spiral"/>

<item href="wheel.html" label="Wheel"/>

<item href="stretch1.html" label="Stretch I"/>

<item href="stretch2.html" label="Stretch II"/>

<item href="stretch3.html" label="Stretch III"/>

<item href="wipe1.html" label="Wipe I"/>

<item href="wipe2.html" label="Wipe II"/>

<item href="wipe3.html" label="Wipe III"/>

<item href="burnfilm.html" label="Burn Film"/>

<item href="centercurls.html" label="Center Curls"/>

<item href="colorfade.html" label="Color Fade"/>

<item href="curtain.html" label="Curtains"/>

<item href="flowmotion.html" label="Flow Motion"/>

<item href="glassblock.html" label="Glass Block"/>

<item href="grid.html" label="Grid"/>

<item href="jaws.html" label="Jaws"/>

<item href="lens.html" label="Lens"/>

<item href="liquid.html" label="Liquid"/>

<item href="lightwipe.html" label="Light Wipe"/>

<item href="pagecurl.html" label="Page Curl"/>

<item href="peelabcd.html" label="Peel ABCD"/>

<item href="ripple.html" label="Ripple"/>

<item href="threshold.html" label="Threshold"/>

<item href="twister" label="Twister"/>

<item href="vacuum.html" label="Vacuum"/>

<item href="water.html" label="Water"/>

<item href="wheel.html" label="Wheel"/>

<item href="wormhole.html" label="Wormhole"/>

<item href="white.html" label="White"/>

<item href="rolldown.html" label="Roll Down"/>

<item href="multiple.html" label="Multiple Transform"/>

<item href="singlefade.html" label="Single Fade"/>

</submenu>

<submenu href="/library/" label="MSDN Library"/>

<submenu href="/code/" label="Code Center"/>

<submenu handle="dl" href="/downloads/" label="Downloads">

<item href="/downloads/" label="Developer Downloads"/>

<item href="/subscriptions/resources/subdwnld.asp" label="Subscriber Downloads"/>

<item href="http://www.microsoft.com/downloads" label="Microsoft Download Center"/>

<item href="/isapi/gosupport.asp?target=/support/servicepacks/default.asp?sd=msdn&amp;fr=0" label="Service Packs"/>

<item href="http://www.research.microsoft.com/downloads/" label="Microsoft Research Downloads"/>

</submenu>


<submenu href="/howto/" handle="ht" label="How-To Articles">

<item href="/howto/" label="Search How-Tos"/>

<item href="/howto/howto_index.asp" label="How-To Index"/>

</submenu>

<submenu handle="mg" href="/msdnmag/" label="MSDN Magazine">

<item href="/msdnmag/default.aspx" label="Kurikulum"/>

<item href="/msdnmag/backissues02.aspx" label="Kesiswaan"/>

<item href="/msdnmag/backissues01.aspx" label="Kepegawaian "/>

<item href="/msdnmag/backissues00.aspx" label="Sarana "/>

<item href="/msdnmag/netindex.asp" label="Komite Sekolah"/>


</submenu>


<submenu handle="col" href="/columns/" label="Columns &amp; Shows">

<heading label="Voices Columns" />

<item href="/columns/vbnet.asp" label="Adventures in Visual Basic .NET"/>

<item href="/columns/askgui.asp" label="Ask Dr. GUI"/>

<item href="/columns/service.asp" label="At Your Service"/>

<item href="/columns/secure.asp" label="Code Secure"/>

<item href="/columns/deepc.asp" label="Deep C++"/>

<item href="/columns/data.asp" label="Diving Into Data Access"/>

<item href="/columns/drguinet.asp" label="Dr. GUI .NET"/>

<item href="/columns/directx.asp" label="Driving DirectX"/>

<item href="/columns/embedded.asp" label="Get Embedded"/>

<item href="/columns/xml.asp" label="Extreme XML"/>

<item href="/columns/designers.asp" label=".NET Designers"/>

<item href="/columns/aspnet.asp" label="Nothin' but ASP.NET "/>

<item href="/columns/office.asp" label="Office Talk "/>

<item href="/columns/scripting.asp" label="Scripting Clinic "/>

<item href="/columns/two4road.asp" label="Two for the Road"/>

<item href="/columns/webmen.asp" label="Web Team Talking "/>

<item href="/columns/winforms.asp" label="Wonders of Windows Forms"/>

<item href="/columns/csharp.asp" label="Working with C# "/>

<heading label="MSDN Magazine Columns &amp;nbsp;" />

<item href="/msdnmag/columns/c.asp" label="C++ Q &amp; A"/>

<item href="/msdnmag/columns/web.asp" label="Web Q &amp; A"/>

<item href="/msdnmag/columns/basics.asp" label="Advanced Basics"/>

<item href="/msdnmag/columns/net.asp" label=".NET"/>

<item href="/msdnmag/columns/data.asp" label="Data Points"/>

<item href="/msdnmag/columns/xml.asp" label="XML Files"/>


<heading label="Shows" />

<item href="/theshow/default.asp" label="The .NET Show"/>

<item href="/vbtv/default.asp" label="VBTV"/>

</submenu>

    <submenu href="/support/" label="Support" />


<submenu handle="devcom" href="/community/" label="Developer Community">

            <item href="/community/" label="MSDN Community Home Page"/>

<item href="/newsgroups/" label="Newsgroups"/>

<item href="/chats/" label="Technical Chats"/>

<item href="/usergroups/" label="User Groups"/>

<item href="/community/related/" label="Related Communities"/>

<item href="/vkiosk/" label="Volunteer Kiosk"/>


</submenu>

<submenu handle="train" href="intel.html" label="Intel">

<item href="fire.html" label="Fire"/>

<item href="cloud.html" label="Cloud"/>

<item href="star.html" label="Star"/>

<item href="Water" label="Water"/>

<item href="curtainswde.html" label="Curtains"/>

<item href="smoke.html" label="Smoke"/>

</submenu>

<submenu handle="subscr" href="/subscriptions/" label="Subscriptions">

<item href="/subscriptions/" label="HTML"/>

<item href="/subscriptions/prodinfo/overview.asp

" label="JScript"/>

<item href=" /subscriptions/prodinfo/subscribe.asp

" label="XML"/>

<item href=" /subscriptions/resources/highlights.asp

" label="Style Sheet"/>

</submenu>

<submenu href="/partners/" label="Partners &amp; Certification"/>


</menugroup>

<menugroup>

<submenu href="/isapi/gomscom.asp?target=/technet/" label="IT Professionals"/>

<submenu href="/architecture/" label="Architects"/>

</menugroup>

</menu>