The Dojo parser is a Core resource that is the standard means of
instantiating a widget defined in markup and ensuring that its visible
representation, linked via its domNode
, gets inserted into the page. Once
the domNode
is assigned into the
page, the browser renders it on the page. So, while a widget's DOM
node is the vital part of the dijit that makes it visible, the
totality of the dijit is considerably more. This section provides an
introduction to the parser, as well as play-by-play coverage on
exactly how it works.
Aside from seeing some references in the introductory material in Chapter 1 and some exposure in the drag-and-drop examples from Chapter 7, the parser hasn't been formally introduced because its most common use case is instantiating widgets in a page. Without further ado, here's an official example of the parser instantiating a widget from markup. Note the emphasized lines in Example 11-2, which highlight where the parser-related action is happening.
Example 11-2. Automatically parsing a widget
<html>
<head>
<title>Fun With the Parser!</title>
<!-- pull in the standard CSS that styles the stock dijits -->
<link rel="stylesheet" type="text/css"
href="http://o.aolcdn.com/dojo/1.1/dojo/resources/dojo.css" />
<link rel="stylesheet" type="text/css"
href="http://o.aolcdn.com/dojo/1.1/dijit/themes/tundra/tundra.css" />
<script
type="text/javascript"
src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js"
djConfig="parseOnLoad:true"
></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
</script>
</head>
<body class="tundra">
<button dojoType="dijit.form.Button"
>Sign Up!</button>
</body>
</html>
To summarize what's happening, there's just a simple page that
includes an off-the-shelf button from Dijit that does absolutely
nothing except look pretty—but for the purposes of introducing the
parser without diving into Dijit specifics, this is just fine. The
only thing you need to know about the Button
dijit at this time is that it is
fetched via a call to dojo.require
and inserted into the page
via the dojoType
tag.
Tip
Any custom addOnLoad
logic you could include is executed after the widgets are
parsed—making it safe for you to reference them.
You won't see any direct invocations of the parser in Example 11-2; that's by design. The
vast majority of the time, you simply dojo.require
dijits into your page, set
the parseOnLoad
flag in djConfig
, and let the rest happen behind
the scenes. In fact, that's all that occurs in this example. It's
worth taking a moment to ponder just how absolutely elegant it is
that you can take a dijit off the shelf and, in just a few
keystrokes, insert it into the page. No additional headache, hassle,
or fuss is required.
There are bound to be times when you will need to manually parse a page or some node in the DOM. Fortunately, it's just one function call away. Consider Example 11-3, a variation that manually parses the widget in the page.
Example 11-3. Manually parsing a page
<html>
<head>
<title>Hello Parser</title>
<!-- pull in the standard CSS that styles the stock dijits -->
<link rel="stylesheet" type="text/css"
href="http://o.aolcdn.com/dojo/1.1/dojo/resources/dojo.css" />
<link rel="stylesheet" type="text/css"
href="http://o.aolcdn.com/dojo/1.1/dijit/themes/tundra/tundra.css" />
<script
type="text/javascript"
src="http://o.aolcdn.com/dojo/1.1/dojo/dojo.xd.js"
djConfig="parseOnLoad: false"
></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
dojo.addOnLoad(function( ) {
dojo.parser.parse( );
//manually parse after the page loads
});
</script>
<head/>
<body class="tundra" >
<button dojoType="dijit.form.Button" >Sign Up!</button>
</body>
</html>
Although manually parsing the entire page is useful, you'll
more often need to manually parse a DOM node. The parser accepts an
optional argument that provides the root of a node in the DOM tree
that it scans for dojoType
tags
and instantiates. Thus, you provide the parent of the node you wish
to parse to the parse
function.
Here's one possible modification of the previous code block that
illustrates:
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
dojo.addOnLoad(function( ) {
//The parser traverses the DOM tree passed in and instantiates widgets.
//In this case, the button is the only leaf in the tree, so it is all that
//gets parsed
dojo.parser.parse(document.getElementsByTagName("button")[0].parentNode);
});
</script>
Warning
Trying to manually parse a widget on the page by passing the
widget's DOM node into the parse
method will fail, and you may not
receive any visible indication that parsing failed. Fortunately,
if you can locate a reference to a node, referencing its parent
through the parentNode
is just
a few keystrokes away.
Although what the parser accomplishes really does seem like
magic, it really just boils down to rigorous, well-designed
automation. As you now know, the parser has two primary use cases:
parsing the page on load via djConfig="parseOnLoad:true"
or manually
parsing a widget. This section elaborates on the details that go
into making those two things happen.
Parsing a widget when the page loads entails three basic requirements:
Include
parseOnLoad:true
as a key/value pair todjConfig
, which the parser will detect when it is loaded and use to trigger automatic parsing.Require the parser via
dojo.require("dojo.parser")
so that the parser is available and can register an automatic call todojo.parser.parse( )
when the page loads. Because no arguments are passed to the call, the entire body of the page provides the basis for parsing.Provide
dojoType
tags as needed in the markup for widgets that should be parsed.
Manually parsing a widget that has already been defined in markup after the page loads is similar:
Require the parser via
dojo.require("dojo.parser")
. BecauseparseOnLoad
is not detected to be true, no automatic call todojo.parser.parse( )
occurs.Provide the corresponding
dojoType
tag in the markup for a widget—maybe even dynamically after the page has already loaded.Manually call
dojo.parser.parse( )
, optionally providing a specific DOM node as an argument as the starting point for the parsing operation.
But what about the actual parsing process? You know—the part
about finding all of the dojoType
tags and instantiating them into widgets? Again, it's all simple
automation when you get right down to it. Here's exactly what
happens:
dojo.query("[dojoType]")
is called to deterministically fetch the nodes in the page that need to be parsed.Class information (as in
dojo.declare
type classes) is distilled from each node; attributes are iterated over and lightweight type conversion is performed. Recall that attributes may provide information to a class'sconstructor
.Any
dojo/method
ordojo/connect
script tags internal to the node are detected and scheduled for processing. (More on these in the upcoming section "Defining Methods in Markup.")An instance of the class is created by using its
constructor
unless amarkupFactory
method is defined, in which case it is used.markupFactory
is a special method that allows you to define a custom constructor function for widgets that need different initialization in markup than they do via programmatic creation. All dijits inherit from a base class,_Widget
, which fires off a standard series of lifecycle methods. One of these lifecycle methods inserts the dijit'sdomNode
into the page, which makes it visible. Lifecycle methods are discussed in detail in the next chapter.If a
jsId
attribute is present, then the class instance is mapped to the global JavaScript namespace. (Common for data stores and widgets that you have a reason to make global.)Any connections provided via
dojo/connect
ordojo/method SCRIPT
tags in markup are processed (more on this later in the chapter) and each widget'sstartup
lifecycle method is called.startup
is another standard lifecycle method inherited from_Widget
(coming up in the next chapter) which allows you to manipulate any widgets that are contained in the one being instantiated.
Hopefully, that didn't make you feel the same way that you did when you learned that Santa Claus wasn't real, but you had to learn sometime. The next chapter focuses exclusively on dijit lifecycle methods where dedicated coverage of these concepts is provided.
Get Dojo: The Definitive Guide now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.