[ LiB ] |
Commands are extensions that appear as entries on the Commands menu. (Actually, if you manipulate the menus .xml file, as discussed in the previous chapter, you can make commands appear on any menu. But they appear on the Commands menu by default.) They are the most versatile and powerful of the extension types, allowing you to perform almost any edits on a document or site. Their API requirements are simple, but because they are so flexible, they are not easy to master. This section covers what's involved in creating simple (and also not-so-simple) Dreamweaver commands.
Like all extensions, commands are made from HTML and JavaScript. Each command consists of an HTML file (the command file itself) and optional, associated JS files and/or graphics. Command files are stored in the Configuration/Commands folder. By default, all files in this folder appear on the Commands menu.
If you have ever recorded commands or saved history steps as commands, you've created simple command files! Look in your user -specific Configuration/Commands folder, and you'll find an HTML file for every saved command. The filename is the name you gave the command when you saved it. |
Like objects, commands can exist with or without dialog boxes. They can be simple or complex. A number of API-defined functions can be part of the command file, but the file also can be very simple, with no special functions. The API procedure is simple or complex, based on the file structure. (Note also that these are flexible extensions!)
There are no required API functions for commands, although a variety of optional functions exist. Figure 29.10 shows a very basic command file, with only required elements in place. Note that the body section is empty. Note also that there are no API functions, and the main function is called onLoad .
This kind of file has the following elements:
Filename The filename, minus its extension, becomes the menu entry. Command filenames can include spaces, and capitalization is respected.
Main function This is the function that makes the command do whatever you want it to do. It's a locally defined function, not part of the API, which means that it must be called explicitly. If the command has no dialog box, the function should be called in the <body> tag, using the onLoad event handler. If the command has a dialog box, the function should be called as part of the commandButtons() function (described in the following list).
Believe it or not, that's all that's absolutely required of a command file without a dialog box.
If the command includes a dialog box, a few more API elements are required. Figure 29.11 shows a sample command file with a dialog box, again containing only the necessary elements. Note that the form does not include a Submit button. The main command is now called from the commandButtons() function, not from the <body> tag.
The required elements for a command that calls up a dialog box are as follows :
Page title The title is required if the command includes a dialog box. It becomes the title of the command's dialog box if there is one. If there isn't a dialog box, the title is not required.
HTML form As with all extensions, this creates the user interface (in this case, the dialog box). Note that, as with objects, the form does not include a Submit button. Unlike objects, however, command dialog boxes are not automatically supplied with buttons; instead, command buttons must be defined and given functionality using the commandButtons() function.
commandButtons() function If there is a dialog box, this function creates the buttons that appear. If this function doesn't exist, the user will have no way to activate or close the dialog box! The command Buttons() function must return an array consisting of the name of each button, followed by the code to be executed when the button is clicked. Note that because the main command function must be called here, it should no longer be called using the <body> tag's onLoad handler.
In addition to these required elements, several optional API functions can be included. The most useful of these is canAcceptCommand() . This function determines whether the command should appear grayed-out (disabled) in the menu. A command that operates on the contents of a document, for instance, shouldn't be accessible if a document isn't open . If the function returns true, the command is accessible; if it returns false, the command is grayed-out. The API includes a whole slew of enablers (functions that determine whether something is possible) to help with this.
The API procedure for processing commands determines how and when Dreamweaver uses the file elements discussed in the preceding section. The procedure is as follows:
So far, it all sounds pretty simple. The complex aspect of commands is that you usually want them to act on documents. And acting on documents means dealing with the Dreamweaver DOM.
If you've ever torn your hair out struggling with the conflicting DOMs of Internet Explorer and Netscape, working with Dreamweaver commands will be a welcome relief, because there's only the Dreamweaver DOM to worry about. |
If you've worked in depth with JavaScriptespecially if you've created DHTML effects using JavaScriptyou're already familiar with the concept of the document object model (DOM) . The DOM is the hierarchical, or tree, structure of objects (tags, pieces of text, and so on) that makes up an HTML document. To gain access to any part of the document, you must navigate up and down the hierarchy, or climb up and down the tree.
An object is any page element that you can control by scripting. They have properties that you can access and change and methods that represent things you can do with them. Objects are also called nodes .
Just as an HTML document is constructed from tags nested inside each other, and text blocks nested inside tags, so objects, or nodes, can have parents, children, and siblings. In the following example, the <ul> object is the parent node of the three <li> objects, which are siblings of each other:
<ul> <li>Moe</li> <li>Larry</li> <li>Curly</li> </ul>
The text block Moe is the only child node of the first <li> object, and so on. Figure 29.12 shows a typical document diagrammed as a tree of objects.
A document has four kinds of objects, or nodes:
The document node type The document itself, as an entity.
The element node type All HTML tags belong to this type.
The text node type Each block of text is an object of this type.
The comment node type HTML comments.
In the earlier example, the Moe object is of the text node type; its parent <li> object is of the element node type. Different node types have different properties and methods. Tables 29.1 through 29.4 list the properties and methods of the different node types as they exist in the Dreamweaver DOM.
Property/Method | Return Value | Read-Only? |
---|---|---|
nodeType | 9 | Yes |
parentNode | Null | Yes |
parentWindow | An object representing the document's parent window | Yes |
childNodes | A NodeList containing all children | Yes |
documentElement | The <html> tag element | Yes |
body | The <body> tag element | No |
URL | The document's absolute address (or an empty string if the document hasn't been saved) | No |
getElementsByTagName | A NodeList containing all instances of the given tag (tagName) | No |
hasChildNodes() | true | No |
Property/Method | Return Value | Read-Only? |
---|---|---|
nodeType | 1 | Yes |
parentNode | The parent tag | Yes |
childNodes | A NodeList containing all immediate children | Yes |
tagName | The tag's HTML name ( TABLE , A , IMG , and so on) | Yes |
attrName | A string containing the value of the specified tag attribute | No |
innerHTML | HTML code contained within the element's opening and closing tags | No |
outerHTML | HTML code contained within the tag and the opening and closing tags | No |
getAttributes ( attrName ) | The value of the attrName attribute | No |
setAttribute | attrName , attrValue | No |
removeAttribute | attrName | No |
getElementsByTagName | A NodeList of children of the current element that are ( tagName ) tagName elements | No |
hasChildNodes() | true/false | No |
Property/Method | Return Value | Read-Only? |
---|---|---|
nodeType | 8 | Yes |
parentNode | The parent tag | Yes |
childNodes | An empty NodeList | Yes |
data | A string of text between the opening and closing comment tags | No |
hasChildNodes() | false | No |
Property/Method | Return Value | Read-Only? |
---|---|---|
nodeType | 3 | Yes |
parentNode | The parent tag | Yes |
childNodes | An empty NodeList | Yes |
data | A string of text that comprises the current object | No |
hasChildNodes() | false | No |
In addition to all the standard JavaScript means of accessing and controlling DOM objects, the Dreamweaver API includes the document, or dom , object and its methods. These are the primary methods you use to edit documents using Dreamweaver extensions. Before you can use any of these methods on a document, however, you have to officially gain access to the document's structure using the dw.getDocumentDOM() function. Table 29.5 lists the specifications for this function. This function lets you gain scripting access to the contents of user documents.
Syntax | dw.getDocumentDOM() |
---|---|
Description | This function creates a DOM object, giving access to the contents of a document's object structure. |
Arguments | No arguments are required. If no arguments are present, the currently active document is used as the source of the DOM object. The optional arguments are as follows: |
document | |
parent | |
parent. frames [ number ] | |
parent.frames [' framename '] | |
A URL. (URLs must be absolute or relative to the extension file.) | |
Returns | The document object at the top of the DOM hierarchy ( DOCUMENT_NODE type). |
You access the current user document's DOM by assigning it to a variable:
var theDOM=dw.getDocumentDOM();
After you have done this, you have access to an object of the first node type previously listed. You are officially climbing the document tree. You can now use the methods and properties of the various nodes to navigate through the document and edit it, as in these examples:
//change the background color to black var theDOM=dw.getDocumentDOM(); var theBody=theDOM.body; theBody.bgcolor="#000000"; //determine what kind of object the current selection is var theDOM=dw.getDocumentDOM(); var theSel=theDOM.getSelectedNode(); if (theSel.nodeType=="1") { window.alert(theSel.tagName); } else if (theSel.nodeType=="3") { window.alert(theSel.data); }
The subject of DOM access is much bigger than this chapter covers, and it takes practice to master. But the rewards are great. After you know how to navigate a document, you can use your command or other extension to tell Dreamweaver to do almost anything to a user document. (Such power!)
For more information on working with the DOM, and scripting extensions in general, read Dreamweaver MX Extensions , published by New Riders, or Building Dreamweaver 4 and UltraDev 4 Extensions , published by Osborne. |
In this exercise, you will create a command that finds all the images in an open document and assigns them a border width of 2. You won't need a dialog box, so this will be a simple file to create. You will, however, get some practice accessing the DOM.
<html> <head> <title>Set Image Border</title> <script language="JavaScript"> function setImageBorder() { // command code goes here } </script> </head> <body onLoad="setImageBorder()"> </body> </html>
function setImageBorder() { //get document access //get image access (collect images as an array) //set the border property of each array item }
Plotting out the main steps of a function as comments inside the function can help whittle major scripting tasks into manageable chunks . This is often called pseudocode. |
function setImageBorder() { //get document access var theDOM=dw.getDocumentDOM(); //get image access (collect images as an array) //set the border property of each array item }
function setImageBorder() { //get document access var theDOM=dw.getDocumentDOM(); //get image access (collect images as an array) var theBody=theDOM.body; var theImages=theBody.getElementsByTagName("IMG"); //set the border property of each array item }
function setImageBorder() { //get document access var theDOM=dw.getDocumentDOM(); //get image access (collect images as an array) var theBody=theDOM.body; var theImages=theBody.getElementsByTagName("IMG"); //set the border property of each array item for (var a=0;a<theImages.length;a++) { theImages[a].border="2"; } }
What If It Doesn't Work?If your command file contains a syntax error, Dreamweaver gives you a handy error message as soon as you try to choose the file. Read the error message, go back to your file, and find the error. If your object doesn't cause any errors, but it doesn't change any images, there's a logic error. Probably you didn't accurately access the DOM. The getElementsByTagName() function requires that all parameters be specified in uppercase, so make sure your code refers to IMG , not img , or it won't work. Make sure all your variable names match as you proceed into the document tree. Match your code against the code shown here, and keep tinkering until it works. |
The command so far is handyif users want a two-pixel border around their images. How about letting the user specify how wide the border should be? (The ability to set the border to 0 might come in handy if you ever inherit someone else's HTML pages from a web editor that doesn't set that feature automatically.) You'll now add a dialog box to the command created in the preceding exercise, asking for a width.
function commandButtons() { return new Array("OK","setImageBorder(); window.close();", "Apply", "setImageBorder()", "Cancel","window.close()"); }
for (var a=0;a>theImages.length;a++) { theImages[a].border=document.theForm.borderwidth.value; }
You can improve the functionality of this little command in all sorts of ways. Maybe you just want to set the border for images with or without links. Maybe you want to let the user choose which images get borders. Maybe you want to give the user the opportunity to remove the border attribute completely. With DOM access, all is possible. (To work with linked images, just determine which <img> tags have an <a> tag as their parent node.) For now, however, add the canAcceptCommand() function. If the current document doesn't have any images, it makes no sense for the command to be available. So you'll return true if there are images and false if there aren't.
function canAcceptCommand() { //access the document //if there is no document, return false //access the body //access the images, collected as an array //if the array is empty, return false //otherwise, return true }
function canAcceptCommand() { //access the document var theDOM=dw.getDocumentDOM(); //if there is no document, return false if (!theDOM) return false; //access the body var theBody=theDOM.body; //access the images, collected as an array var theImages=theBody.getElementsByTagName("IMG"); //if the array is empty, return false if (theImages.length=="0") return false; //otherwise, return true else return true; }
Do you get tired of repeatedly quitting and relaunching Dreamweaver every time you tweak an extension? Here's a shortcut: Ctrl-click (Windows) or Opt-click (Mac) the Insert bar's categories drop-down menu. The Reload Extensions option appears. When you choose this, the program reloads its extensions without quitting. |
Are you already full of ideas for your next command? If so, there's no stopping you. If not, you might need to broaden your horizons a little bit. Try these inspiration generators:
Whenever you're working in Dreamweaver, keep a notebook handy. If you find yourself often repeating the same manual procedure, wasting time performing tedious tasks, try to imagine what kind of command you could write to help yourself out. Jot down that inspiration.
Take a spin through the Extending Dreamweaver manual, especially the list of API methods that takes up the last half of the book. Just seeing all the different things you can tell Dreamweaver to do is likely to get your imagination moving.
Unless you enjoy coding for its own sake, don't spend hours and hours writing a command before you check out the Exchange. You might come across a command that does exactly what you need.
The more you work with the DOM, the easier it will be. Pretty soon, you'll want to create custom Property Inspectors, floating panels, reports , translators, and more.
[ LiB ] |