Because the stored book-mark must include the replaced text as part of its specification, the start point of the current range must be adjusted back to the beginning of the replacement t
Trang 1Listing 19-11 (continued)
document.all.counter.innerText = i }
// BEGIN UNDO BUFFER CODE // buffer global variables var newRanges = new Array() var origSearchString // store original search string and bookmarks of each replaced range function pushUndoNew(rng, srchString, replString) {
origSearchString = srchString rng.moveStart(“character”, -replString.length) newRanges[newRanges.length] = rng.getBookmark() }
// empty array and search string global function clearUndoBuffer() {
document.all.counter.innerText = “0”
origSearchString = “”
newRanges.length = 0 }
// perform the undo function undoReplace() {
if (newRanges.length && origSearchString) { for (var i = 0; i < newRanges.length; i++) { rng.moveToBookmark(newRanges[i])
rng.text = origSearchString }
document.all.counter.innerText = i clearUndoBuffer()
} }
</SCRIPT>
</HEAD>
<BODY>
<H1>TextRange.findText() Method</H1>
<HR>
<FORM>
<P>Enter a string to search for in the following text:
<INPUT TYPE=”text” NAME=”searchString” SIZE=20 VALUE=”Law”>
<INPUT TYPE=”checkbox” NAME=”caseSensitive”>Case-sensitive
<INPUT TYPE=”checkbox” NAME=”wholeWord”>Whole words only</P>
<P>Enter a string with which to replace found text:
<INPUT TYPE=”text” NAME=”replaceString” SIZE=20 VALUE=”legislation”></P>
<P><INPUT TYPE=”button” VALUE=”Search and Replace (with prompt)”
onClick=”sAndR(this.form)”></P>
<P><INPUT TYPE=”button” VALUE=”Search, Replace, and Count (no prompt)” onClick=”sAndRCount(this.form)”>
Trang 2<SPAN ID=”counter”>0</SPAN> items found and replaced.</P>
<P><INPUT TYPE=”button” VALUE=”Undo Search and Replace”
onClick=”undoReplace()”></P>
</FORM>
<DIV ID=”rights”>
<A NAME=”article1”>
<H2>ARTICLE I</H2>
</A>
<P>
Congress shall make no law respecting an establishment of religion, or
prohibiting the free exercise thereof; or abridging the freedom of speech, or of
the press; or the right of the people peaceably to assemble, and to petition the
government for a redress of grievances.
</P>
[The rest of the text is snipped for printing here, but it is on the CD-ROM
version.]
</DIV>
</BODY>
</HTML>
Having a search and replace function available in a document is only one-half of the
battle The other half is offering the facilities to undo the changes To that end,
Listing 19-11 includes an undo buffer that accurately undoes only the changes made
in the initial replacement actions
The undo buffer stores its data in two global variables The first,
origSearchString, is simply the string used to perform the original search This
variable is the string that has to be put back in the places where it had been
replaced The second global variable is an array that stores TextRangebookmarks
(see getBookmark()later in this chapter) These references are string values that
don’t mean much to humans, but the browser can use them to recreate a range
with its desired start and end point Values for both the global search string and
bookmark specifications are stored in calls to the pushUndoNew()method each
time text is replaced
A perhaps unexpected action of setting the textproperty of a text range is that the
start and end points collapse to the end of the new text Because the stored
book-mark must include the replaced text as part of its specification, the start point of
the current range must be adjusted back to the beginning of the replacement text
before the bookmark can be saved Thus, the pushUndoNew()function receives the
replacement text string so that the moveStart()method can be adjusted by the
number of characters matching the length of the replacement string
After all of the bookmarks are stored in the array, the undo action can do its job in a
rather simple forloop inside the undoReplace()function After verifying that the
TextRange.findText()
Trang 3undo buffer has data stored in it, the function loops through the array of book-marks and replaces the bookmarked text with the old string The benefit of using the bookmarks rather than using the replacement function again is that only those ranges originally affected by the search-and-replace operation are touched in the undo operation For example, in this document if you replace a case-sensitive
“states” with “States” two replacements are performed At that point, however, the document has four instances of “States,” two of which existed before Redoing the replacement function by inverting the search and replace strings would convert all four back to the lowercase version — not the desired effect
getBookmark()
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
Listing 19-11 earlier in this chapter shows how the getBookmark()method is used
to preserve specifications for text ranges so that they can be called upon again to
be used to undo changes made to the text range The getBookmark()method is used to save the snapshots, while the moveToBookmark()method is used during the undo process
inRange(otherRangeRef)
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
Use The Evaluator (Chapter 13) to see the inRange()method in action The follow-ing statements generate two distinct text ranges, one for the myPparagraph ele-ment and the other for the myEMelement nested within
a = document.body.createTextRange() a.moveToElementText(myP)
b = document.body.createTextRange() b.moveToElementText(myEM)
Trang 4Because the myPtext range is larger than the other, invoke the inRange()method
on it, fully expecting the return value of true
a.inRange(b)
But if you switch the references, you see that the larger text range is not “in” the
smaller one:
b.inRange(a)
isEqual(otherRangeRef)
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
Use The Evaluator (Chapter 13) to try the isEqual()method Begin by creating
two separate TextRangeobjects, one for the myPelement and one for myEM
a = document.body.createTextRange()
a.moveToElement(myP)
b = document.body.createTextRange()
b.moveToElement(myEM)
Because these two ranges encompass different sets of text, they are not equal, as
the results show from the following statement:
a.isEqual(b)
But if you now adjust the first range boundaries to surround the myEMelement,
both ranges are the same values:
a.moveToElement(myEM)
a.isEqual(b)
move(“unit”[, count])
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
TextRange.move()
Trang 5Use The Evaluator (Chapter 13) to experiment with the move()method To see how the method returns just the number of units it moves the pointer, begin by creating
a text range and set it to enclose the myPelement:
a = document.body.createTextRange() a.moveToElementText(myP)
Now enter the following statement to collapse and move the range backward by 20 words
a.move(“word”, -20)
Continue to click the Evaluate button and watch the returned value in the Results box The value shows 20while it can still move backward by 20 words But eventu-ally the last movement will be some other value closer to zero And after the range
is at the beginning of the BODY element, the range can move no more in that direc-tion, so the result is zero
moveEnd(“unit“[, count]) moveStart(“unit”[, count])
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
Use The Evaluator (Chapter 13) to experiment with the moveEnd()and
moveStart()methods Begin by creating a text range and set it to enclose the
myEMelement:
a = document.body.createTextRange() a.moveToElementText(myEM)
To help you see how movements of the pointers affect the text enclosed by the range, type ainto the bottom text box and view all the properties of the text range Note especially the htmlTextand textproperties
Now enter the following statement to move the end of the range forward by one word
a.moveEnd(“word”)
Trang 6Click on the List Properties button to see that the text of the range now includes
the word following the EM element Try each of the following statements in the top
text box and examine both the integer results and (by clicking the List Properties
button) the properties of the range after each statement:
a.moveStart(“word”, -1)
a.moveEnd(“sentence”)
Notice that for a sentence, a default unit of 1 expands to the end of the current
sen-tence And if you move the start point backward by one sentence, you’ll see that
the lack of a period-ending sentence prior to the myPelement causes strange
results
Finally, force the start point backward in increments of 20 words and watch the
results as the starting point nears and reaches the start of the BODY:
a.moveStart(“word”, -20)
Eventually the last movement will be some other value closer to zero And as soon
as the range is at the beginning of the BODY element, the range can move no more
in that direction, so the result is zero
moveToBookmark(“bookmarkString”)
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
Listing 19-11 earlier in this chapter shows how to use the moveToBookmark()
method to restore a text range so that changes that created the state saved by the
bookmark can be undone The getBookmark()method is used to save the
snap-shots, while the moveToBookmark()method is used during the undo process
moveToElementText(elemObjRef)
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
TextRange.moveToElement()
Trang 7A majority of examples for other TextRangeobject methods in this chapter use the
moveToElementText()method Listings 19-10 and 19-11 earlier in this chapter show the method within an application context
moveToPoint(x, y)
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
Use The Evaluator to see the moveToPoint()method in action Begin by creating a text range for the entire BODY element:
a = document.body.createTextRange()
Now, invoke the moveToPoint()method to a location 100, 100, which turns out to
be in the rectangle space of the Results textarea:
a.moveToPoint(100,100)
If you type ainto the bottom text box and view the properties, both the htmlText
and textproperties are empty because the insertion point represents no visible text content But if you gradually move, for example, the start point backward one character at a time, you will see the htmlTextand textproperties begin to fill in with the body text that comes before the TEXTAREA element, namely the “Results:” label and the <BR>tag between it and the TEXTAREA element Enter the following statement into the top text box and click the Evaluate button several times
a.moveStart(“character”, -1)
Enter ainto the bottom text box after each evaluation to list the properties of the range
parentElement()
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Trang 8Use The Evaluator (Chapter 13) to experiment with the parentElement()method
Begin by setting the text range to the myEMelement:
a = document.body.createTextRange()
a.moveToElementText(myEM)
To inspect the object returned by the parentElement()method, enter the
follow-ing statement in the lower text box:
a.parentElement()
If you scroll down to the outerHTMLproperty, you see that the parent of the text
range is the myEMelement, tag and all
Next, extend the end point of the text range by one word:
a.moveEnd(“word”)
Because part of the text range now contains text of the myPobject, the outerHTML
property of a.parentElement()shows the entire myPelement and tags
pasteHTML(“HTMLText”)
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
Use The Evaluator (Chapter 13) to experiment with the pasteHTML()method The
goal of the following sequence is to change the <EM>tag to a <SPAN>tag whose
STYLEattribute sets the color of the original text that was in the EM element
Begin by creating the text range and setting the boundaries to the myEMelement:
a = document.body.createTextRange()
a.moveToElementText(myEM)
While you can pass the HTML string directly as a parameter to pasteHTML()
,stor-ing the HTML str,stor-ing in its own temporary variable may be more convenient (and
more easily testable), such as:
b = “<SPAN STYLE=’color:red’>” + a.text + “</SPAN>”
TextRange.pasteHTML()
Trang 9Notice that we concatenate the text of the current text range, because it has not yet been modified Now we can paste the new HTML string into the current text range
a.pasteHTML(b)
At this point the EM element is gone from the object model, and the SPAN element
is in its place Prove it to yourself by looking at the HTML for the myPelement:
myP.innerHTML
As noted earlier, the pasteHTML()method is not the only way to insert or replace HTML in a document This method makes excellent sense when the user selects some text in the document to be replaced, because you can use the
document.selection.createRange()method to get the text range for the selec-tion But if you’re not using text ranges for other related operations, consider the other generic object properties and methods available to you
select()
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
See Listing 19-11 earlier in this chapter for an example of the select()method in use
setEndPoint(“type”, otherRangeRef)
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
Use The Evaluator to experiment with the setEndPoint()method Begin by creat-ing two independent text ranges, one for the myPelement and one for myEM:
a = document.body.createTextRange() a.moveToElementText(myP)
b = document.body.createTextRange() b.moveToElementText(myEM)
Trang 10Before moving any end points, compare the HTML for each of those ranges:
a.htmlText
b.htmlText
Now, move the start point of the atext range to the end point of the btext range:
a.setEndPoint(“StartToEnd”, b)
If you now view the HTML for the a range,
a.htmlText
you see that the <P>tag of the original atext range is nowhere to be found This
demonstration is a good lesson to use the setEndPoint()method primarily if you
are concerned only with visible body text being inside ranges, rather than an
ele-ment with its tags
TextRectangle Object
Properties
bottom
left
right
top
NN2 NN3 NN4 NN6 IE3/J1 IE3/J2 IE4 IE5 IE5.5
Example
Listing 19-12 lets you click one of four nested elements to see how the
TextRectangleis treated When you click one of the elements, that element’s
TextRectangledimension properties are used to set the size of a positioned
ele-ment that highlights the space of the rectangle Be careful not to confuse the visible
rectangle object that you see on the page with the abstract TextRectangleobject
that is associated with each of the clicked elements
TextRectangle.bottom