JavaScript: The Definitive Guide, 4th edition by David Flanagan Unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. This page was updated April 10, 2006. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification UNCONFIRMED errors and suggestions from readers: (1) 2nd paragraph; In Perl 5, "associative arrays" are now known as "hashes", so JavaScript objects are similar to Perl hashes, Java Maps (particularly HashMaps or Hashtables), and C++ STL maps. {4} Table 1-2; According to this table IE5 does not support any part of W3C DOM standard. But IE5 do have partial support for the W3C DOM standard. {6} Example1-1; you have the statement prior to the .. sequence. I have a lways seen that the section is before the of the html. [6] HTML code in Section 1.5; The HTML code shown does not adhere to the W3C recommendation for several reasons: 1. It does not have a tag. 2. The tag appears too early in the document. 3. The (12) towards bottom; substitute "This has been fixed, and a number of other secutity holes as well." or something for the quantity flummoxed sentence that exists (14) Top (missing first line of Example 1-3); The first line of the html example (Example 1-3. Computing loan payments with JavaScript) is apparently missing. It should be the opening tag: . {15} within the IF loop of the script; The following three statements of example 1-3 report an error by my browser: document.loandata.payment.value = round(montly); document.loandata.total.value = round(monthly * payments); document.loandata.totalinterest.value = round((monthly * payments) - principal); The problem seems to be solved when the method "round()" is called using "Math.round()". In other words the following will work fine: document.loandata.payment.value = Math.round(monthly); document.loandata.total.value = Math.round(monthly * payments); document.loandata.totalinterest.value = Math.round((monthly * payments) - principal); {17} First line of the page.; The line reads: Here's what you'll find in Part III: then it proceeds to outlin e chapters 12-22. It should have said Part II [19] 1st paragraph; There are far better ways of debugging JavaScript programs than inserting print statements. First, nearly every browser has a JavaScript console that will show basic syntax and runtime errors. Mozilla additionally has the Edit|Preferences...|Debug|Show strict JavaScript warnings feature to indicate further possible bugs. Mozilla even has an interactive JavaScript debugger, Venkman, that can be used to step through code and examine variables. {26} last paragraph of 2.6; The statement "Literals are an important part of any programming language, as it is impossible to write a program without them." is simply not true for many (most?) languages. Take C for example: int i; i=i-i; /* i=0 */ ++i; /* i=1 */ ... ... ++i; /* i=n */ This way, any integer number can be constructed without using a single literal. With type conversion any string or floating point number can be constructed, so that every program can be written without using a literal. Similar hacks are possible in most languages that have increment/decrement operators. [30-31] Hexadecimal and Octal Literals Section; It's not clear that hexadecimal literals can be larger than 2^32-1 or 2^31-1. It should be noted that even "integer" literals are still treated as floating point literals, and therefore have the same range as floating point numbers. [33] Section 3.2; The maximum length of a JavaScript string is not mentioned. Is a string guaranteed to hold at least 65535 characters, or is the limit much higher? {36} 1st paragraph; The example extracts the second, third, fourth and fifth characters sub= s,substring(1,4); The book misses the fifth character [55] figure 4-1; Figure 4-1 on page 55 is not very clear: It does nothing to disprove the assumption that a call object on the scope chain corresponds to a function call on the call stack when g() is invoked. The middle part of the figure looks a lot like a call stack that we know from C, C++, and Java. However, the actual behaviour is very different from that of a call stack: a call object (as shown in the middle) does not correspond to the variables that are pushed on the call stack during the call to g(). This difference is not obvious from the code shown on the left in the figure. The left shows only function definitions, and no function calls. This allows us to falsely believe that a call object corresponds to a function call. As page 174 justly describes: "Nested functions are perfectly understandable when they are invoked in the same lexical scope in which they are defined." This simple situation is shown in figure 4-1. The reader whould benefit from an example where a function call is shown in a different lexical scope than the scope from the function definition. I suggest adding the following example: --------------------------------------------------------------- var x=1; function f() { var y=2; function g() { var z=3; return x*100+y*10+z; } debug("call to g() from within f(): " + g()); return g; } var func = f(); debug("call to g() NOT from within f(): " + func()); --------------------------------------------------------------- The output produced by the debug statements is: call to g() from within f(): 123 call to function g() NOT from within f(): 123 During both calls to g() , all three x,y, and z, are available. During the second call to g() , variable y is not on the call stack because f() is not being called. Yet y is available, through a call object corresponding to the lexical scope of function f() ! [61] Modulo (%) paragraph; The % operator in JavaScript computes the remainder after truncating division, not the modulo. For example, -2 % 3 is -2, but -2 modulo 3 is 1. To compute the modulo in general, you need to write something like function modulo(x, y) { var k = x % y; return (k != 0 && (k > 0 ^ y > 0) && isFinite(y)) ? k + y : k; } instead. It should also be noted that % remainder is different from the IEEE floating-point remainder after *rounding* division (e.g. Java's Math.IEEEremainder), even though % operates on IEEE floating-point numbers. [62] explanation of ++ and --; The explanation of ++ and -- should be clarified regarding the automatic conversion to a number. Take the following example: var x="0"; var y=x++; It is not clear from the text in the book whether the type of y will be string or number. The book says "..evaluates to the unincremented value of that operand." It could be argued that the unincremented value of x has type string, but on my browser (Opera) y is of type number. This seems counterintuitive and deserves mentioning in the book. (63) 4th dot from bottom; Instead of "String.localeCompare()" in normal font the book should contain String.localeCompare() without surrounding doublequotes in constant width font as it does on page 66 2nd paragraph from bottom. {67} First section (5.5.2), first paragraph; In the discussion of the "in" operator, no mention is made of which versions of JavaScript support this syntax. At the least, it fails in IE 5.1 for Macintosh, where the sample code produces syntax errors. For example, var point = { x:1, y:1 }; var has_x_coord = "x" in point; produces the error: Expected ';' meaning a semicolon is expected after the quoted "x" in the second line (character 21). That is, Explorer 5.1 doesn't understand this construct at all. (Simply testing for "point.x" does work, but it's not the same thing.) IE does understand the "for (var x in point)" syntax, but that's not the same thing, either. In general, all the operators discussed in this chapter are treated as if they've been permanent features of the core language since the beginning, which in this case appears not to be true. Classes, objects, and properties get rated by the language level at which they're supported; but if there's any discussion of support for operators, I couldn't find it. (67) 5.5.3 section; The instanceof operator is not valid in many current versions of JavaScript, just like the in operator that a trouble report has already been filed for. I agree that the omission of when various operators of core JS were implemented is a serious problem with the book. It has cost me hours of time when I discover that something you say works, doesn't in N4, for example. [70] Section 5.8 Bitwise Operators; The explanation of the conversion from IEEE floating point numbers to 32-bit integers is not complete. Sometimes this conversion is signed, and sometimes it is unsigned. For example, 0xFFFFFFFF >> 0 is -1, but 0xFFFFFFFF >>> 0 is 0xFFFFFFFF, even though accordin g to the explanation of the >> and >>> operators they should return the same result because there are no one or zero bits shifted i n from the left. This distinction is important in JavaScript because unlike in C, C++, or Java, the final result of bitwise operato rs is a floating point number, meaning that -1 and 0xFFFFFFFF really are totally different values. (85) example at top of page; Javascript permits omission of semicolons when statements are on separate lines, but this is considered bad practice. The statement following 'default:' should really be terminated with a semicolon. (89) 2nd Paragraph, 3rd line; "leftthand" should be "left hand" [96] code fragment ; Try block must enclose throw statement. [96] second paragraph, beginning "When"; Using Netscape 6.2, an exception will not be thrown unless the offending code is enclosed in a try block. And the try block must be immediately followed by one of catch; catch, finally; or finally. {114} 2nd code sample; The code example near the bottom of p.114 has the following code snippet: var new_years_eve = new Date(2000, 11, 31); //Represents December 31, 2000 this creates a date object representing November 31, 2000 since November is the 11th month of the year. Should read: var new_years_eve = new Date(2000, 12, 31); {132} 1st full paragraph, last sentence; "JavaScript objects are much more like Perl arrays" should be "JavaScript objects are much more like Perl hashes". Perl has both arrays (indexed by integer, just like arrays in JavaScript) and hashes (indexed by String, just like objects in JavaScript). Hashes were called associative arrays before Perl 5. (134) 12th line from bottom of page; "typeof operator (which returns either "Object" or "Function"" should be "typeof operator (which returns either "object" or "function"" [136] last paragraph of 8.7.4; The paragraph says "the valueOf() method can in some circumstances, take priority over the toString() method when convertig an object to a string." There is one example but this is not enough. As this is an important pitfall, more explanation about what these "some circumstances" are is needed. [141] 2nd to last paragraph; Setting the length property is not the only way to shorten an array. The pop() and shift() methods both shorten an array, and the splice() method can also shorten an array. (149) Table 10-1 description for \cX; The description for \cX includes for example, \c] is equivalent to the newline character \n According to ECMA-262, "\c" must be followed by an ASCII letter ('a' to 'z' or 'A' to 'Z'). The "\c]" in the description should be replaced with "\cj" or "\cJ". {155} Perl RegExp Features Not Supported in JavaScript section; There are at least two additional flags allowed in Perl s/// regexes that are not supported directly in JavaScript: e and o. Even though the e flag is not supported, the String.replace() method does an equivalent operation when a function is used as the second argument. And although o is not a valid flag, generating a RegExp object from a string expression once and using it multiple times gives the same result. The study function and the \c, \N, \p, \P, \X, and \C escape sequences are also not supported. {155} End of Section 10.1 - Defining Regular Expressions; The end of the section on regex syntax should include a precedence table: high repetition a*, b+, c?, d{2,4} concatenation ab low alternation a|b {157} Last paragraph; The line "So in the previous code, the value of the result.index property would be 21,..." is incorrect - the value of result.index is 22. To confirm this, simply run the example with the following line added to the end: alert(result.index); [174] 3rd paragraph, 6th line; {{The Javascript code of the returned function is always the same}} I think this is not true. because.. a[0] is makefunc(0), so a[0]=function(){return 0}, a[1]=function(){return 1}, and a[2]=function(){return 2}. therefore 1st line of last paragraph may become {{The results of this code may be NOT surprising}} [195] last paragraph and example; The test for existance is not valid under certain circumstances. After some experimentation I realized that there is a difference between an undeclared variable and an undefined variable. As the attached example shows you can detect an undefined variable but not an undeclared variable with the variable == null test. existance tests

Existance tests

if frames[1] on page 195 has not been declared then the if test doesn't work. You have the same problem on page 389 with the opener if test. What is particularly bad about all these tests is that javascript (in IE 5.5) stops executing and the existance test far from preventing problems actually creates some serious new problems because subsequent necessary code is not executed. [214] Example 13-5; The function parses the querystring on comma instead of ampersand, making it useless for seperating out query string parameters. By changing the split character to "&" it works fine: function getArgs() { var args = new Object() var query = location.search.substring(1) // Get query string. var pairs = query.split("&") // Break at ampersand. for(var i = 0; i < pairs.length; i++) { var pos = pairs[i].indexOf('=') // Look for "name=value". if (pos == -1) continue // If not found, skip. var argname = pairs[i].substring(0,pos) // Extract the name. var value = pairs[i].substring(pos+1) // Extract the value. args[argname] = decodeURIComponent(value) // Store as a property. } return args // Return the object. } // getArgs() {242} bottom of 242 to top of 243; This is not in response to a typo error but to a problem in the use of the _ToggleButton_click() function in the ToggleButton class on pages 242-43. This function presently calls the programmer supplied optional onclick function after reversing 'checked' and swapping images: this.checked = !this.checked; this.image.src = ToggleButton.imagenames[this.checked+this.highlighted*2]; if (this.onclick) this.onclick(this.checked); This works as long as the viewer has the option to turn all choices on or off, but when the viewer can make only one choice, as in radio buttons, the simplest solution is to supply a function to _ToggleButton_click() which calls the onlick handler for the currently checked item so as to turn it off (uncheck it). For example, I want to give a viewer the choice of three different font sizes to accomodate different browsers and resolutions. So I supply the following onclick code to the constructor for the 3 fonts, where font9, font10, and font11 are my variable names for your tb1, tb2, tb3 (on page 243): font9 onlclick: "if(font10.checked)font10.click(); if (font11.checked)font11.click()" font10 onclick: "if(font9.checked)font9.click(); if(font11.checked).font11.click(); font11 onlick: "if(font9.checked)font9.click(); if(font10.checked)font10.click();" In other words, each onclick handler must turn off whichever other selection is checked. So, when we call the optional onclick function it will in turn call the onclick handler for the previously selected item which will now set to false the checked flag which has just now been set to true on the most recently selected item. So, if the most recent selection is font10 and the previous selection was font9, when font10 calls its onclick handler, the font10 handler will call the font9 handler which will now turn off font10. The solution is simply to call the optional handler first: if (this.onclick) this.onclick(this.checked); this.checked = !this.checked; this.image.src = ToggleButton.imagenames[this.checked+this.highlighted*2]; (It's only by first unchecking all of the items that the recursion comes to an end.) Your 3rd edition was much used and thumbed through and I'm very happy to have the 4th for which I've been eagerly waiting ever since the release of Netscape 6. {265} Example 15-2
; The verify function on page 264 includes the following: if(if (e.numeric || (e.min != null) || (e.max != null)){ ... The property e.numeric unlike e.optional is not defined and trivialized due to the above relational or condition. Section 15.4's 2nd paragraph on page 263 highlights this numeric check. To correct this, the following statem on page 265 should be corrected. Change from: this.phonenumber.optional = true; Change To: this.phonenumber.numeric = true; {268} 1st code example and following paragraph in Section 16.2; This code and the accompanying explanation use the deprecated escape() and unescape() methods. These should be updated to the proper encodeURIComponent() and decodeURIComponent() methods as explained on page 472. {271} Line 11 from the bottom; This change also needs to be done to the 16-1.html file in the jscript4_examples.zip file you can download. cookieval += prop + ':' + escape(this[prop]); should be: cookieval += prop + '=' + escape(this[prop]); {272} Line 19 from the bottom; This change also needs to be done to the 16-1.html file in the jscript4_examples.zip file you can download. a[i] = a[i].split(':'); should be: a[i] = a[i].split('='); -------------------------------------------------------------------------------- The code works by itself. I notice that when you mix javaScript code with vbscript code in a .asp page there are some funny results. Below is the results I found. -------------------------------------------------------------------------------- If I set some cookies in VBSCRIPT like so: Response.Cookies("myvar")("var1")="vbexpl1" Response.Cookies("myvar")("var2")="vbexpl2" Response.Cookies("myvar").Expires="May 10,2002" Response.Cookies("myvar").Path = "/" Then I change the values with JAVASCRIPT like so: var oCookie = new Cookie(document, "myvar", 240, "/"); // First, try to read data stored in the cookie. If the cookie is not // defined, or if it doesn't contain the data we need, then query the // user for that data. oCookie.load(); // Store value entered on FORM oCookie.var1 = "jsexpl1" oCookie.var2 = "jsexpl2" // Store the cookie values, even if they were already stored, so that the // expiration date will be reset to 10 days from this most recent visit. // Also, store them again to save the updated visits state variable. oCookie.store(); The resulting cookie.txt file for Netscape 4.7 looks like this: (NOTICE the :undefined stuff) # Netscape HTTP Cookie File # http://www.netscape.com/newsref/std/cookie_spec.html # This is a generated file! Do not edit. kcookie.netscape.com FALSE / FALSE 4294967295 kcookie w2d059 FALSE / FALSE 1012228498 myvar var2=vbexpl2:undefined&var1=vbexpl1:undefined&var1:jsexpl1&var2:jse xpl2 -------------------------------------------------------------------------------- If I make the 2 changes above then this is the result of the cookie.txt file. -------------------------------------------------------------------------------- The resulting cookie.txt file for Netscape 4.7 looks like this: # Netscape HTTP Cookie File # http://www.netscape.com/newsref/std/cookie_spec.html # This is a generated file! Do not edit. kcookie.netscape.com FALSE / FALSE 4294967295 kcookie w2d059 FALSE / FALSE 1012227153 myvar var2=jsexpl2&var1=jsexpl1 -------------------------------------------------------------------------------- I have 6 example modules that you can run to demonstrait this problem if you would like me to send them to you let me know. -------------------------------------------------------------------------------- (287) last paragraph on page, third last line; The words "If this convenience property" probably should be "If this convenient property". [295] lines 5 to 9 in example 17-7; The following statement doesn't seem to work in Internet Explorer 6.0.2800.1106.xpsp1.020828-1920, although I don't get any error message on the statement: debug.box.setAttribute("style", "background-color: white; " + "font-family: monospace; " + "border: solid black 3px; " + "padding: 10px;"); I had to use the following statements instead: debug.box.style.setAttribute("backgroundColor", "white"); debug.box.style.setAttribute("fontFamily", "monospace"); debug.box.style.setAttribute("border", "solid black 3px"); debug.box.style.setAttribute("padding", "10px"); [298] Whole example; Example 17-8 automatically generating a table of contents I have tried this example using Internet Explorer 5.0 and 6.0 and it doesn't seem to work. It appears that the named anchors are not being correctly inserted into the document. (i.e. TOC and SECTxxx) The same code works correctly using Netscape 6.2. [301] Example 17-9; I am trying to load an XML into an HTML page using this example. I found that it worked fine with Explorer 5.5 (always) and with Netscape 6.2 (only locally). Once you upload the page to the Web, Netscape refuses to load the XML. [301] Example 17-9; Refreshing a page that contains the code in this example with Internet Explorer will cause a memory leak. See Microsoft Knowledge Base Article - 830555. {324} Last code sample (after 5th full paragraph); I'm uncertain as to whether this is an error or an intended "mistake," as it could be read either way -- depending on whether you take the example in the context of the preceeding discussion or in the context of the subsequent discussion. In any case, I think that in the "style" attribute of the
tag, the author really meant to say: top: 10px; instead of: right: 10px; (326) Figure 18-1; The Child Content Area is labelled: Chid Content Area {326} 1st paragraph; In the discussion of Windows IE and the box model, the author notes that "the width and height attributes incorrectly include an element's border and padding (but not its margins)." But in the next sentence, the width and height are said to include the border and *margin*. I think the sentence should read: "For example, if you set the width of an element to 100 pixels and place *10 pixels of padding* and a 5-pixel border on the left and right, the content area ends up being only 70 pixels wide in these buggy versions of Internet Explorer." [336] Example 18-3; This example will not work with IE6.x (haven't tried earlier versions. The bars render below the chart. It does work with netscape. {335} Example 18-3; Example 18-3 does not work correctly with IE version 6. (The bars display below and last bar overruns right margin of surrounding box.) It does work with Firefox. The following code works with IE version 6. /** * BarChart.js: * This file defines makeBarChart(), a function that creates a bar chart to * display the numbers from the data[] array. The chart is a block element * inserted at the current end of the document. The overall size of the chart * is specified by the optional width and height arguments, which include the * space required for the chart borders and internal padding. The optional * barcolor argument specifies the color of the bars. The function returns the * chart element it creates, so the caller can further manipulate it by * setting a margin size, for example. * * Import this function into an HTML file with code like this: * * Use this function in an HTML file with code like this: * makeBarChart([1,4,9,16,25], 300, 150, "yellow"); **/ function makeBarChart(data, width, height, barcolor) { // Provide default values for the optional arguments if (!width) width = 500; if (!height) height = 350; if (!barcolor) barcolor = "blue"; // Now create an element to hold the chart. Note that we make the chart // relatively positioned so that can have absolutely positioned children, // but it still appears in the normal element flow. var chart = document.createElement("DIV"); chart.style.position = "relative"; // Set relative positioning chart.style.width = width + "px"; // Set the chart width chart.style.height = height + "px"; // Set the chart height chart.style.border = "solid black 2px"; // Give it a border chart.style.paddingLeft = "10px"; // Add padding on the left chart.style.paddingRight = "10px"; // and on the right chart.style.paddingTop = "10px"; // and on the top chart.style.paddingBottom = "0px"; // but not on the bottom chart.style.backgroundColor = "white"; // Make chart background white // // The width and height arguments specify the overall size of the // generated chart. We have to subtract the border and padding // sizes from this to get the size of the element we create. width -= 24; // subtract 10px padding and 2px border left and right height -= 14; // Subtract 10px top padding and 2px top and bottom border // Compute the width of each bar var barwidth = Math.floor(width/data.length); // Find largest number in data[]. Note clever use of Function.apply() var maxdata = Math.max.apply(this, data); // The scaling factor for the chart: scale*data[i] gives height of a bar var scale = height/maxdata; // Now loop through the data array and create a bar for each datum for(var i = 0; i < data.length; i++) { var bar = document.createElement("div"); // Create div for bar var barheight = data[i] * scale; // Compute height of bar bar.style.position = "absolute"; // Set bar position and size bar.style.left = (barwidth*i+1+10)+"px"; // Add bar border & chart pad bar.style.top = height-barheight+10+"px";// Add chart padding bar.style.width = (barwidth-2) + "px"; // -2 for the bar border bar.style.height = (barheight-1) + "px"; // -1 for the bar top border bar.style.border = "solid black 1px"; // Bar border style bar.style.backgroundColor = barcolor; // Bar color bar.style.fontSize = "1px"; // IE bug workaround chart.appendChild(bar); // Add bar to chart } // Now add the chart we've built to the document body document.body.appendChild(chart); // Finally, return the chart element so the caller can manipulate it return chart; } Note: "width -= 24;" and "height -= 14;" moved. It seems this is the correct logic and that Microsoft is actually handling the code correctly. (376) line 6; The line contains the example statement e.initEvent("click", "true", "true"); The second and third arguments should be booleans. The statement should be e.initEvent("click", true, true); What is in the book works because a nonempty string in a boolean context is treated as a boolean value of true. However, the example statement e.initEvent("click", "false", "true"); would not work as expected, unless the reader expected the string value of "false" to be treated as a boolean value of true. [380] Example 19-3; The given example for dragging in the IE Event Model does not work fully with IE (tested with IE 5.5 and 6.0). Dragging works fine for text, but if you try dragging images, it does not work correctly. What happens is that if you click on an image to drag, after you move the image about 4 pixels, a "circle with a cross-out through it" appears, and the image stops moving. Upon releasing the mouse button, the image then "snaps" to the mouse position, and is not "dropped" until the user clicks again. (402) second bullet, second sentence; Current text reads: "A script cannot register event listeners within for or capture events for documents loaded..." It should read: "A script cannot register event listeners within, or capture events for, documents loaded..." or: "A script cannot register event listeners for, or capture events for, documents loaded..." (404) Final paragraph, sentence 2; "Also, the details of how it is done have change between Netscape 4 and Netscape 6. It should be either: ...change... or ...have changed... {445} Very top; "Date()" called as a function returns a string with the current date and time in it, not a Date object as "new Date()" would. It does however ignore any arguments passed to it, as stated. (Tested in IE6.0.2600 and Netscape 6.2.3 in Win 98.) [470] second code fragment; I have been using Netscape 6.2 under Windows 2000. The first line has a syntax error, which is caught by the interpreter before runtime, and thus cannot cause a catchable runtime error. An alternative way of coding that line which will cause a runtime error is: try { eval(" &*(&/* an error is thrown here */")} The spirit of the example might, however, be better illustrated by: try {var x = phony_function()} which will throw a reference error. [470] first code fragment; throw must be enclosed in a try block. (480) Global Functions section; The encodeURI, encodeURIComponent, and isNaN methods are missing parentheses. {480} Global Functions Section; The escape() and unescape() methods should be marked as deprecated. {484} Math Static Functions; Math.max and Math.min can take any number of arguments, not just two. [491] Math.random() Returns; The number returned by Math.random() is between 0.0 inclusive and 1.0 exclusive (greater than or equal to zero and less than one). The most common use is to generate a random integer between 0 and n-1, which is written as Math.floor(n * Math.random()) (501) last two lines; "This object is not supported" should be "This argument is not supported". (506) Object.toLocaleString() Synopsis; The Synopsis of toLocaleString() shows toString() instead. (506) 2nd line; "modified to match the IE 5.5" should be "modified to match the specification and IE 5.5". {508} Code example near bottom of page; The use of the Function() constructor should be changed to a function literal as explained on the top of page 476 (509) parseFloat() Description, lines 3-4; "the function the not-a-number value NaN" should be "the function returns the not-a-number value NaN" {517} RegExp.test() Description; The description of how RegExp.test() works is not correct when the regex is global; it begins searching the string at the lastIndex position of the regex instead of the beginning of the string. {530} 7th paragraph, just above Bugs section; Return of parenthesized subexpressions does not work in IE 6.0. Version tested on: Version: 6.0.2800.1106.xpsp2.030422-1633IC Update Versions:; SP1; Q822925; Q828750 Microsoft (R) VM for Java, 5.0 Release 5.0.0.3810 var text = "hello world" IN PRINT: text.split((/(<[^>]*>)/) // Returns[ "hello", "", "world", "",""] SHOULD READ: text.split(/(<[^>]*>)/) // Returns[ "hello", "word" ] (574) Form.target Description, 1st paragraph; The first word of the sentence is not capitalized. It reads: "target is a read/write..." Should be: "Target is a read/write..." {580} Properties, offset*; The proporties offsetHeight, offsetLeft, offsetParent, offsetTop and offsetWidth are not only supported by IE4+ as noted in the book, but also by Netscape 6+. I reported this bug yesterday too, but was not sure if they were supported by N6+ or only by N6.1+. I have now investigated this, and they are supported by Netscape 6.0 and up. As another comment, I miss information regarding proporties like clientHeight/clientWidth/ clientLeft/clientTop and scrollHeight/scrollWidth/scrollLeft/scrollTop. These are not W3C standard (but neither are the offset* proporties). At the time of writing, the client* and scroll* proporties are only supported by IE(4+?) and Mozilla 0.9.6+ (and some of the "small" browsers like Konqueror, Opera and Ice), but since recent builds of Mozilla is now supporting this proporties, I guess we can expect support in the forthcomming Netscape versions too (Netscape 6.3+). {584} last 3 lines; In the HTMLElement.ondblclick description there is a mention of Netscape 4 event model. Is the ondblclick event even supported in Netscape 4? The tests I have performed with Netscape 4.7 seem to show that the event is not recognized by the browser. If this is true then the assertion about Netscape 4.7 implementing JavaScript 1.2 and ondblclick being a JavaScript 1.2 feature does not hold. [669] Window.onload section; The window.onload handler is specified in all lower-case throughout the manual. However, when testing it this way in both Internet Explorer and Netscape, an error is generated. Changing the handler to read window.onLoad (with a capital L) fixes this problem globally. Case is not an issue when specified as an HTML attribute, such as , but it appears to be when written as part of a block of JavaScript code. (673) 12th entry; 'innerWidth' is incorrectly listed twice in the list of 'Window Features'. The second instance should read 'outerWidth' instead. [721] section 'method' at page 721 or page 555; At page 301 in example 17.9 the method document.load(URL) is used. But I cannot find this method or even an explanation of this method in the reference part (part IV or V) of the book.