So far, what we've described of the DOM's functionality is fairly genericmost of the methods and properties outlined in the previous section are part of the W3C's proposed standard for the Level 1 DOM. (The Extending Dreamweaver manual details which items are non-standard.) How do we employ all this scripting power to write Dreamweaver extensions? DOM Object In the discussion of the Dreamweaver Application Programming Interface (API) in Chapter 1, "Dreamweaver Configuration and the API," we saw that the API includes a number of custom objects. One of those objects is the DOM for the user's current document. This object contains many crucial methods and properties for working with user documents. Accessing the DOM Object Before the DOM object's methods and properties can be used, we must officially access the target document's DOM. We do this by calling another function dw.getDocumentDOM() to give the DOM object a name and open it to scripting control. In scripting terms, we call this instantiating the DOM object. The syntax for the instantiation statement looks like this: var myDOM = dw.getDocumentDOM(); Any references to DOM object methods or properties for the current document can then access the DOM object by referring to its name, like this: myDOM.setSelection(); myDOM.pageUp(); And so forth. In general, DOM objects can only be named for open documents; although if there are multiple open documents (as when working with frames , for instance), multiple DOM objects can exist. Table 4.10 lists the specifications of the dw.getDocumentDOM() function . Table 4.10. Specifications for dw.getDocumentDOM() Specification | Details | Syntax | dw.getDocumentDOM() dreamweaver.getDocumentDOM() (The dreamweaver object can be referred to as dw or dreamweaver . Throughout this book, we'll use dw .) | 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 will be used as the source of the DOM object. Optional arguments: "document" , "parent" , "parent.frames[number]" , "parent.frames['framename']" , or 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). | The DOM Object at Work After we have our instantiated DOM object, we have access to the document's hierarchy of nodes, and we can use the hundreds of DOM object methods that are part of the Dreamweaver API. No wonder the Macromedia documentation calls this "the most important function"! Using the DOM to Work with Objects Using the DOM, we can gain access to all objects in the user's document. After we have access, we can make determinations about document content, change object properties, and perform other editing operations. Use the charts shown in Table 4.1 through Table 4.9 to determine what properties of objects can be changed. Based on the listings in those charts , you should understand what these code samples can do: //change the background color and default text color of the user's page var myDOM = dw.getDocumentDOM(); myDOM.body.bgcolor = "#000000"; myDOM.body.text = "#FFFFFF"; //determine the absolute file address of the user's page var myDOM = dw.getDocumentDOM(); var myURL = myDOM.URL; //determine the number of elements in the document's body section var myDOM=dw.getDocumentDOM(); var myBODY=myDOM.body; var myCONTENTS=myBODY.childNodes.length; //if the first item on the page is a table, change its border to "3" var myDOM=dw.getDocumentDOM(); var myBODY=myDOM.body; var myFIRST=myBODY.childNodes.item(0); if (myFIRST.tagName == "TABLE") { myFIRST.border="3"; } You also have access to the hundreds of DOM methods in the Dreamweaver API, to make working with objects easier. This book isn't long enough to list and discuss every one of those; check out the Extending Dreamweaver manual for that. Table 4.11 details some useful functions for working with objects in a document. Table 4.11. General purpose API functions for working with objects Function | dom.insertHTML() | Description | Inserts the specified HTML code at the insertion point. | Syntax | dom.insertHTML(' code to insert goes here ') | Arguments | The code to insert. | Returns | nothing | Example | //inserts the code for a spacer image, //using relative URL myDOM = dw.getDocumentDOM(); myDOM.insertHTML('<img src="shim.gif" width="10" height="10">'); | Function | dom.insertText() | Description | Inserts the specified text at the insertion point. | Syntax | dom.insertText(' text to insert goes here ') | Arguments | The text to insert. | Returns | nothing | Example | //inserts a text string into the text portion of the document //including the proper HTML coding for the ampersand myDOM = dw.getDocumentDOM(); myDOM.insertText('Hello & good-bye .'); | Function | dom.insertObject() | Description | Inserts the specified Dreamweaver object at the insertion point. | Syntax | dom.insertObject( objectName ) | Arguments | The name of the object file (minus its filename extension) to insert. | Returns | nothing | Example | //inserts an image object, as though it were // chosen from the Objects panel myDOM = dw.getDocumentDOM(); myDOM.insertObject('Image'); | Function | dom.wrapTag() | Description | Wraps the specified tag around the current selection. The selection must be able to accept a tag wrapped around it without generating invalid HTML, or Dreamweaver will report an error. | Syntax | dom.wrapTag( startTag ) | Arguments | The name of the tag to wrap around the selection (as it appears in its opening tag). | Returns | nothing | Example | //if the current selection is an image, //wraps a link around the image tag myDOM = dw.getDocumentDOM(); myObject = myDOM.getSelectedNode(); if (myObject.nodeType == "1" && myObject.tagName == 'IMG') { myDOM.wrapTag('<a href="mypage.html">'); } | Function | dom.stripTag() | Description | Removes the tag from around the current selection. If the tag has contents, it'll remain . If the selection contains more or less than one tag, Dreamweaver will report an error. | Syntax | dom.stripTag() | Arguments | none | Returns | nothing | Example | //if the current selection is a link, //the link is removed myDOM = dw.getDocumentDOM(); myObject = myDOM.getSelectedNode(); if (myObject.nodeType == "1" && myObject.tagName == 'A') { myDOM.stripTag(); } | Using the DOM to Work with Selections Working with selections is an important part of using the DOM. We may need to know what the user has selected, move the insertion point, expand or contract the current selection, or select new page elements. We may need to gain access to selected objects, or create selections from certain objects. The DOM object includes a variety of powerful functions for working with selections. These are detailed in Table 4.12 through Table 4.14. Table 4.12. API Functions for getting information about the current selection Function | dom.getSelectedNode() | Description | Gets access to the node that contains the current selection or insertion point. | Syntax | variableName = dom.getSelectedNode() | Arguments | None | Returns | The document object at the top of the DOM hierarchy (DOCUMENT_NODE type). | Example | //returns true if the current selection is part of a text node myDOM = dw.getDocumentDOM(); var currentNode = myDOM.getSelectedNode(); if (currentNode.nodeType == "3") { return "true"; } else { return "false"; } | Function | dom.getSelection() | Description | Gets access to the current selection, expressed as character offsets into the current document. | Syntax | variableName = dom.getSelection() | Arguments | None | Returns | An array consisting of two numbers . The first item in the array represents character offset at the start of the selection. The second item represents the offset value at the end of the selection. If the current selection is an insertion point, the two items in the array are the same. | Example | //determine if the selection is an insertion point myDOM = dw.getDocumentDOM(); var mySelection = myDOM.getSelection(); if (mySelection[0] == mySelection[1]) { window.alert("The current selection is an insertion point."); } | Table 4.13. API functions for using selection offsets to work with objects Function | dom.nodeToOffsets() | Description | Gets the position of a specified object (node) in the document, expressed as character offsets into the document. | Syntax | variableName = dom.nodeToOffsets( objectName ) | Arguments | An object (node) | Returns | An array consisting of two numbers. The first item in the array represents character offset at the start of the node. The second item represents the offset value at the end of the node. (Once we have these values, we can select the node.) | Example | //finds the offsets for the first image in a document //and uses them to select the image var myDOM = dw.getDocumentDOM(); var firstImage = myDOM.images[0]; imageOffsets = myDOM.nodeToOffsets(firstImage); myDOM.setSelection(imageOffsets[0], imageOffsets[1]); | Function | dom.offsetsToNode() | Description | Gets access to the object (node) in the document that completely surrounds the current selection. | Syntax | variableName = dom.nodeToOffsets( offsetBegin,offsetEnd ) | Arguments | Two numbers, representing the character offsets of a selection. | Returns | The object (node) that contains the selection. | Example | //determines the node containing the current selection, //and returns true if it's a text node var myDOM = dw.getDocumentDOM(); var mySelection = myDOM.getSelection(); var currentObject = myDOM.offsetsToNode( mySelection[0], mySelection[1]); | Notes | Using this function with dom.getSelection() , as in the example here, is the same as using dom.getSelectedNode() . | Table 4.14. API Functions for setting and manipulating the selection Function | dom.selectAll() | Description | Selects all, as if the user had chosen Edit > Select All. In most cases, this selects all the content in a document. Other times (for instance, if the current insertion point is inside a table), it selects all of some element in the document. | Syntax | dom.selectAll() | Arguments | none | Returns | nothing | Notes | To ensure that all contents of the active document are selected, use dom.setSelection() instead of this command. | Function | dom.selectTable() | Description | Selects a table. | Syntax | dom.selectTable() | Arguments | none | Returns | nothing | Enabler | dom.canSelectTable() (Returns true if the current selection is within a table.) | Example | //determines if the insertion point is within a table, //and if so, selects the table var myDOM = dw.getDocumentDOM(); if (myDOM.canSelectTable()) { myDOM.selectTable(); } | Function | dom.setSelectedNode() | Description | Selects the specified object (node). | Syntax | dom.setSelectedNode(node, [bSelectInside] , [bJumpToNode] ) | Arguments | An object (node)Required. bSelectInside (Boolean)If the specified node is an element node, this determines if the selection includes the innerHTML (the contents but not the outer tags) or the outerHTML (the contents and the surrounding tags). Optional. Defaults to false, if omitted. bJumpToNode (Boolean)If this option is set to true , the document window will scroll to show the selection. Optional. Defaults to false if omitted. | Returns | nothing | Example | //selects the first image in the document, //and scrolls the document window to show the selection var myDOM = dw.getDocumentDOM(); var firstImage = myDOM.images[0]; myDOM.setSelectedNode(firstImage,0,1); | Notes | Using this function is equivalent to calling dom.nodeToOffsets() and passing the return value to dom.setSelection() . | Function | dom.setSelection() | Description | Sets the selection based on two numbers representing character offsets into the document. | Syntax | dom.setSelection( offsetBegin , offsetEnd ) | Arguments | Two numbers, representing the desired beginning and ending of the selection expressed as character offsets into the document. | Returns | nothing | Example | //finds the current selection, and changes it //to an insertion point at the end of the selection var myDOM = dw.getDocumentDOM(); var mySelection = myDOM.getSelection(); myDOM.setSelection(mySelection[1],mySelection[1]); | Notes | If the newly set selection would not be a valid HTML selection, Dreamweaver automatically expands the selection to include the nearest valid selection. | Function | dw.selectAll() | Description | Selects all in the active document, or in the site window, or (Mac only) in the edit field that has focus in a dialog box or floating panel. | Syntax | dw.selectAll() or dreamweaver.selectAll() | Arguments | none | Returns | nothing | Enabler | dw.canSelectAll() (Returns true if Dreamweaver can perform the Select All operation.) | Example | if (dw.canSelectAll()) { dw.selectAll(); } | Notes | To ensure that all contents of the active document are selected, use dom.setSelection() instead of this command. | Function | dom.selectChild() | Description | Selects a child of the current selection. | Syntax | dom.selectChild() | Arguments | none | Returns | nothing | Notes | For better control over which child to select, use dom.getSelectedNode() and access the childNodes property. | Function | dom.selectParent() | Description | Selects the parent object of the current selection. | Syntax | dom.selectParent() | Arguments | none | Returns | nothing | Notes | This is similar to using dom.getSelectedNode() and accessing the parentNode property. | A few notes about selections are in order. Selections can be accessed or set in two ways: by object or by character offsets. Generally, we need to work with both methods to accomplish our goals. Object-based selection commands should be familiar to you by now. The dom.getSelectedNode() function gains access to whatever object is currently selected; dom.setSelectedNode() selects a specified object. Using character offsets may be a little more unfamiliar. The dom.getSelection() function always returns an array of two numbers. The first number represents the beginning of the selectionit's the number you would get if you switched to Code view and counted characters from the beginning of the HTML code to where the selection starts. The second number represents the end of the selection. Some examples of character offsets: -
In any document, the HTML element starts at character 0 and ends at the last character in the document. -
In any document, the head element will start at character 7immediately after the six characters of the <html> tag, in other words. -
Any time the current selection is only an insertion point; the beginning and ending offsets will be the same. After we understand this, we can see how to combine the selection functions to perform useful tasks : To select a particular object in the document: //get access to the object var myObject = myDOM.body.childNodes.item(0); //select the object myDOM.setSelectedNode(myObject); To delete a particular object: //get access to the object var myObject = myDOM.body.childNodes.item(0); //select the object myDOM.setSelectedNode(myObject); //delete the current selection myDOM.deleteSelection(); To determine what kind of object the user has selected: //get access to the selected object var myObject = myDOM.getSelectedNode(); //use conditionals to determine the node type and properties if (myObject.nodeType == "3") { window.alert("You have selected text."); } To place the insertion point after the currently selected object: //get access to the selected object var myObject = myDOM.getSelectedNode(); //determine the offsets of the selected object mySelection = myObject.nodeToOffsets(); //set the selection to an insertion point that matches the final offset myDOM.setSelection(mySelection[1],mySelection[1]); Using the DOM to Work with Strings of Code Another way to access and work with page contents is by treating the document and its elements as strings of HTML code, and performing string operations on them. As Table 4.4 showed earlier in this chapter, objects of the ELEMENT_NODE type include two properties innerHTML and outerHTML that return strings. This is a different way of accessing the object code. This script, for instance, will return an object with properties that can be set and functions that can be performed on it: var myDOM = dw.getDocumentDOM(); var myObject = myDOM.body.childNodes.item(0); if (myObject.nodeType == "1" && myObject.tagName == "IMG") { myObject.alt = "This is an image."; } This script accesses the same code, but as a string subject to string methods: var myDOM = dw.getDocumentDOM(); var myObject = myDOM.body.childNodes.item(0); var myString = myObject.outerHTML; window.alert(myString.toUpperCase()); Why would you use this method? It's often the best way to pull a section of code or text out of a document, edit it, and put it back into the document. (We'll see how this works in the next chapter.) Enhancing Objects and Behaviors Using the DOM Being able to work with the DOM is most important when we're doing work that involves more than just inserting new code into documents. Therefore, objects and behaviors rely on the DOM less than other extension types. But there are tasks within objects and behaviors that require DOM access and knowledge. isDomRequired() As part of the API for objects, this function determines whether an object can be inserted if Code view and Design view have not been synchronized. If the HTML code of a user's document contains invalid markup instructions (incomplete tag pairs, for instance), the DOM is not valid, and certain objects should not be inserted. The function itself only requires a return value of true or false ; but when you are determining how to apply the function, you need to know whether the code you are inserting will work properly without a valid DOM. canAcceptBehavior() We've already had a little experience with this function. As part of the API for behaviors, it controls whether a behavior will be grayed out in the behaviors inspector menu, usually based on whether a required element of the behavior is present on the page. Behaviors that control images are useless unless there are images on a page, for instance. To implement this level of functionality for canAcceptBehavior() , we need to be able to step through the code to see if any IMG tags are present. After a DOM object has been instantiated, as we've seen above, we can do this: function canAcceptBehavior() { var myDOM = dw.getDocumentDOM(); if (myDOM.images[0]) { return true; } else { return false; } } (If you're curiousand you probably are, or you wouldn't be reading this booktry it out! Open up one of the behaviors we created in the previous chapter, and add the preceding canAcceptBehavior() function. Then reload extensions and try the behavior out, first in a document with images and then in a document with no images.) |