ActionScript 3.0 Cookbook, First Edition by Joey Lott, Darron Schall, & Keith Peters The 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. 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 This page was updated June 24, 2008. UNCONFIRMED errors and comments from readers: {?} ?; Drag and drop code should be: public function drop( event:MouseEvent = null ):void { instead of public function drop( ):void { as the latter will fail if the mouse is dragged off the canvas while the former works perfectly. {All} Several locations; I noticed that throughout all the book there are three repeating mistakes: 1. import flash.util should be import flash.utils 2. In several places function's datatype is set to Void, it should be void, all lowercase. 3. DataFormat should be URLLoaderDataFormat. So far I have seen this in chapter 19 and 20. Text and sample code. [All] do a search; TextField.html = true; does not exist anymore and causes a compile-time error. Please remove all references in book. {xxiv} Hyperlink on 3d-to-last line; The as3cb code (from http://rightactionscript.com/ascb/) doesn't work under the latest version of Flex. I posted a patch to the code at http://vizsage.com/blog/2007/08/patches-to-as3-cookbook-code.html {2} 1st paragraph of 'Discussion', about halfway the page; ... or you can click on the New button in the top-right corner ... should be ... in the top-left corner ... [2] last alinea on the page; 'In the navigator view, you should now see a ExampleApplication project, which contains an empty bin folder ...' The bin folder that is created will contain 9 files: playerProductInstall.swf history.swf history.js history.htm ExampleApplication-debug.swf ExampleApplication-debug.html ExampleApplication.swf ExampleApplication.html AC_OETags.js also 'a ExampleApplication' should be 'an ExampleApplication' {4} 4th code example; The Metadata line may be wrong. [SWF(backgroundColor="#ffffff")] did not work in the Flex 2 IDE for me, but [SWF(backgroundColor=0xffffff)] did. ?6?: Paragraph 6; On this page the authors provide a primer for programming terms. What I still do not know is the definition of a sprite. The authors refer to a sprite a early as page 5. I've read Colin Mook's books and many others and I don't find sprite referenced. (12-13) Bottom of 12 and top of 13; The use of the following: onMouseDown onMouseUp onMouseMove causes a 1090: Migration error. If the above words are changed to something else, say: onMD onMU onMM the script works. [13] Second line from the top; In the code sample arrayOne is defined as new array("a","b","c"); the the erroneous line assigns the variable arrayOne to the undefined variable arrayTwo. 'arrayOne = arrayTwo;' The values should be reversed. This is a serious technical mistake since the target audience seems to be beginners/non-serious coders, and it is often tricky for novices to remember that = is an assignment operator that works in one direction, not the mathematical constraint. {13} code fragment at bottom; addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown) should be stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown) [30] last paragraph, last example; Chapter 1.6 last example has some error. This example didn't work on my PC, but I could find the reason. The following example shows a simple class that listens for the keyDown event and traces out the character code for that key. This also demonstrates how to use some of the data contained in the event object passed to the handler method. Note that keyboard events use the class KeyboardEvent. package { import flash.display.Sprite; import flash.events.KeyboardEvent; public class ExampleApplication extends Sprite { public function ExampleApplication( ) { stage.focus = this; addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); } private function onKeyDown(event:KeyboardEvent):void { trace("key down: " + event.charCode); } } } Solution: stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); (34) 3rd code example; not sure if this is a typo or an example...it reads: private function average(a:number, b:number, c:number):void{ trace("The average is " + (c + b + c)/3); } should it be this? "The average is " + (a + b + c)/3); [35] The code at the bottom of the page; I was unable to get the code snippet at the bottom of page 35 (defining and calling average()) to compile properly when I had the "strict" flag turned on. I would receive a "Incorrect number of arguments. Expected no more than 0." error. To get the code to compile properly, you either need to... a) Turn off the strict flag when compiling (which we're not really supposed to do) b) Use code that looks something like this... private function average(... myNums):Number { var sum:Number = 0; // Loop through each of the elements of the arguments array, and // add that value to sum. for (var i:int = 0; i < myNums.length; i++) { sum += myNums[i]; } // Then divide by the total number of arguments return sum / myNums.length; } This will take your arguments and shove them into a myNums array, which you can then access. Strangely, if you put your arguments into a myNums array, then try accessing them using "arguments", it doesn't seem to work. Go figure. [35] last paragraph; What if you wanted to allow a function to be called with any number of arguments? In ActionScript 2, you could do this simply by omitting any parameter list and referencing the arguments using the arguments object in the function. In ActionScript 3, having no parameter list means the function cannot be called with any arguments. Instead, you have to use a new parameter type known as (rest). This parameter goes at the end of your parameter list (or it can represent your entire parameter list) and indicates that any number of arguments can be used when calling the function. The (rest) parameter is written as argumentsArrayName where argumentsArrayName is the name of the array that will contain the arguments passed. http://www.senocular.com/flash/tutorials/as3withflashcs3/#functions (60) bottom - code listing; var os:String = System.capabilities.os.substr(0, 3); should read var os:String = System.Capabilities.os.substr(0, 3); Capabilities: initial cap {72} Figure 3-1; accessing.swf on otherdomain.com should be accessed.swf on otherdomain.com {77} Code sample at top of page; var pink : Color should be var pink : ColorTransform [83] This error is in the code sample; In using the NumberFormat class in Flash CS3, I get a bunch of compiler warnings: "Warning 3596: Duplicate variable definition." This is caused by reusing the same name for local variables. These warnings can be prevented by going into publishing settings and unchecking Warnings Mode in ActionScript 3 Settings, but this is not a great solution... {94} 3rd import in the code at the bottom of the page; This code has a compilation error. Instead of import flash.util.trace; should be import flash.utils.trace; {117-118}: 2nd code example; The letters/newLetters example in section 5.8 is incorrect. The last trace message will output "a,b,c", not "d,e,f". To correct the example change letters = ["d","e","f"]; to letters[0] = "d"; letters[1] = "e"; letters[2] = "f"; The same change should be made to the code example on page 118. [125] code; // of each element.cars.sortOn("year"); This line should be // of eath element. cars.sortOn("year"); Lack of line return. {128} 1st paragraph; In the text discussing custom compare functions, it says "If the [compare] function returns 0, then the current order [of the array] is preserved." This is not true. Array.sort() does not use a stable sorting algorithm and "equal" elements (as determined by the compare function returning 0) will not necessarily end up in the same position as before. An illustration: private function doCustomSort():void { var myArray:Array=[0, 1, 2, 3, 4, 5]; myArray.sort(customCompare); trace(myArray); } private function customCompare(a:Number, b:Number):int { return 0;//any input will be judged equal } The trace output is "3,1,2,0,4,5". {130} function randomSort; The function will in fact return a randomized array, but the return expression as written doesn't work: The statement: return Math.random() -.5 always returns 0. This works: (Math.round(Math.random()*2)-1) {138} First paragraph, 3rd line; "Other display object containers include Sprite, MovieClip and Shape." The text includes Shape as a display object container. Shape is a display object, not a display object container. {160} Mid-page: private function createTextField( downState:Boolean ):TextField; add: textField.height = textField.textHeight*1.25; without this line, everything seems fine. But if you take a better look, you will notice that the hitStateArea is much too big. Mouse reacts much to early. if you add trace(_text + " : " + textField.height); you can see, that the textField.height is automatically set to 100 an therefore the hitstateArea is expanded. So either you have to make the buttons much higher, or the textField smaller (164) second code example; addChild( loaderStatus ); should be: addChild( _loaderStatus); also - on next page: removeChild( loaderStatus ); should be: removeChild( _loaderStatus ) {169} 5th paragraph onwards; 1. Arguably not a mistake, but I am not sure you should have presented the list of mouse events in the form you have? You have listed the string literals of the event types rather than the names of their static properties. Best practice as described on page 10 of this book, and employed in the code sample (page 170), is to refer to the events by their static properties. e.g. In the list you describe the "mouseMove" event. But in the code on page 170 you correctly reference MouseEvent.MOUSE_MOVE . 2. In addition, an important omission in my opinion on the DOUBLE_CLICK event is that in order for this event to fire, the InteractiveObject must have its doubleClickEnabled property set to true. This is a special case and the only event-type in the list which requires an additional action before it can be used. It is not apparent to a new user coming to this list of events and expecting them all to fire as described. (I have the same criticism of the Adobe documentation). Highlighting that small piece of information in future publications will save your reader an hour or so of wondering why the double- click event isn't firing when all other events are working fine. {176} 5th paragraph; It seems that the dropTarget >IS< changing when leaving a display object. Maybe it was different in an earlier version, but I can't experience the effect that it is not. When I move over the right side of the white rectangle and then drop the rectangle, the white rectangle stays white, or whatever color it was before. {177} DraggableSprite class; the drop() function in the DraggableSprite.as file that you recommend in this chapter is missing the event:MouseEvent Argument. This is causing it to throw an ArgumentError when run. IT CURRENTLY READS: public function drop():void { // The mouse up indicated the drop, so remove the mouse up listener ... stage.removeEventListener( MouseEvent.MOUSE_UP, drop ); // ... and remove the mouse move listener stage.removeEventListener( MouseEvent.MOUSE_MOVE, handleDrag ); } BUT IT SHOULD READ: public function drop(event:MouseEvent):void { // The mouse up indicated the drop, so remove the mouse up listener ... stage.removeEventListener( MouseEvent.MOUSE_UP, drop ); // ... and remove the mouse move listener stage.removeEventListener( MouseEvent.MOUSE_MOVE, handleDrag ); } [181] first line of code; Not sure if you would class this as serious or minor. On the one hand it is minor error, but fundamentally affects the understanding of the whole of chapter 7. First instance of the issue appears on page 181. But the key incorrect descriptive is on pages 182 (definition of thickness) and 183 (para 4: minimal call). Essentially the line of code in question is: sampleSprite.graphics.lineStyle(); This is presented as the minimal call to enable lines to be drawn. However this is not correct. A thickness of line must be specified at least in order for a line to be drawn. Extract from Adobe Flex 2 Help... Class Graphics lineStyle () method ... thickness:Number ? An integer that indicates the thickness of the line in points; valid values are 0 to 255. If a number is not specified, or if the parameter is undefined, a line is not drawn. If a value of less than 0 is passed, the default is 0. The value 0 indicates hairline thickness; the maximum thickness is 255. If a value greater than 255 is passed, the default is 255. ... End extract The key quote: "If a number is not specified, or if the parameter is undefined, a line is not drawn." which contradicts the description of page 182 where 1 is presented as the default value. The following lines were tested on the Adobe Flash 9 preview... graphics.lineStyle( 1 ); graphics.drawCircle( 60, 60, 20 ); draws a circle, however in the following example nothing is drawn... graphics.lineStyle( 1 ); graphics.lineStyle( ); graphics.drawCircle( 60, 60, 20 ); The impact of this can be found on pages 181-186, 188-190, 194, 197, 198, 199, each of which present the errant line... sampleSprite.graphics.lineStyle(); (198) line 11 It is supposed to be: _loader.contentLoaderInfo.addEventListener(Event.COMPLETE.onImageLoad); instead of: _loader.contentLoaderInfo.addEventListener(Event.COMPELTE.onImageLoad); notice the "complete" and "compelte" [204] 8.4 Discussion Code Example; This code example is supposed to demonstrate how to load bitmaps. But the printed code doesn't work as is. You have to import the flash.display.Bitmap and flash.display.BitmapDataclasses to make it work. [229] 2nd and 3rd paragraph; "... the Textfield class is packaged in the flash.display package." is wrong and should be: "... the Textfield class is packaged in the flash.text package." also "With earlier versions of ActionScript, you construct a text field using the TextField constructor as follows: var field:TextField = new TextField();" is wrong (this is the new way) and should be: "With earlier versions of ActionScript, you construct a text field using the createTextField method of MovieClip as follows: MovieClip.createTextField(instanceName:String, depth:Number, x:Number, y:Number, width:Number, height:Number);" [231] last sentence on page; "... you can set the type property to the DYNAMIC constant of the flash.display.TextFieldType class:" is wrong and should be: "... you can set the type property to the DYNAMIC constant of the flash.text.TextFieldType class:" [232] Code for password; The code is incorrect. It says the code to make an input box display asterisks is: field.password = true; This is incorrect. It should be field.displayAsPassword = true; [243] 3rd line from top; "field.html = true" should be omitted. It no longer exists and produces a compile time error. {249} Second Sentence; Incorrect code: The setTextFormat code in the book lists the parameters in the wrong order. The book shows: field.setTextFormat(0,formatter) The correct corde is: field.setTextFormat(formatter,0) // Further down the page the book shows: field.setTextFormat(0,10,formatter); The correct code is field.setTextFormat(formatter,0,10); [258] Discussion subhead; "Both solutions to this problem require that you set the text field's html property to true: field.html = true;" is wrong and should be omitted. field.html = true; no longer exists and produces a compile-time error. htmlText can be assigned to a field now without first setting the removed property html to true. {265} Retrieving a List of System Fonts; TextField.fontList property seems not to exist {267} 2nd Line; This line should read color.color, not color.rgb. Using rgb causes a undefined property error. {267} End of second para.; should be ... " and alpha is on a scale from 0 to 1". (not 0 to 100) also, alphaOffset is on a scale from -255 to 255 (according to LiveDocs) ?331? "Example" column, first row; The example explains {n} like this: "Cre{2}l matches creel but not crel or creel" So it says it matches "creel", but not "creel", which (to my eyes) is the same string. [352] This error is in the code sample; In using the DateFormat class in Flash CS3, I get a bunch of compiler warnings: "Warning 3596: Duplicate variable definition." This is caused by reusing the same name for local variables. These warnings can be prevented by going into publishing settings and unchecking Warnings Mode in ActionScript 3 Settings, but this is not a great solution... {353}: Table at bottom; in the table (as in an example on the next page) it says 'd' means "Day of month (leading 0)", but in ascb/util/DateFormat.as there is written case "d": aFormatted.push(dDate.getDate()); break; so there won't be any leading 0. To fix this, change the code into: case "d": var nfFormatter:ascb.util.NumberFormat = new ascb.util.NumberFormat("00"); aFormatted.push(nfFormatter.format(dDate.getDate())); break; {360} 1 paragraph, line 5; import flash.display.TextField; incorrect class packages must be import flash.text.TextField; {366} Code Sample; _sound = new Sound(); should be var _sound = new Sound(); and soundFile = new URLRequest("song.mp3"); should be var soundFile = new URLRequest("song.mp3"); This code without a variable declaration generated compile errors. {374} 3rd paragraph, 3rd/4th lines; "...you can use addEventDispatcher..." should be "...you can use addEventListener..." [384] 3rd paragrph, code example; import flash.media.SoundMixer needs to be added to the list. [396] About the 3rd paragraph at the start of the code example; The incorrect code example says: import flash.display.TextField; import flash.display.TextFieldAutoSize; It should read: import flash.text.TextField; import flash.text.TextFieldAutoSize; The incorrect code throws errors due to the incorrect syntax. [396] First Code Block After Package; The import statements need to be changed as per the below: import flash.text.TextField; import flash.media.Video; import flash.net.NetConnection; import flash.net.NetStream; import flash.events.NetStatusEvent; import flash.text.TextFieldAutoSize; import flash.display.Sprite; import flash.events.Event; The current text reads: flash.display.TextField & flash.display.display.TextFieldAutoSize. This is incorrect. Each should read flash.text. The video display with text works now in Flex 2. It would be really nice if the authors could go over the code again and clean up these issues. What was working in August 06 might not be up to date. [396] client.onMetaData = onMetaData;; Error #2044: Unhandled AsyncErrorEvent:. text=Error #2095: flash.net.NetStream was unable to invoke callback onMetaData. error=ArgumentError: Error #1063: Argument count mismatch on Example/::onMetaData(). Expected 1, got 63. at Example$iinit() [396] Code on pages 396 - 397; The code for the video player with duration display does not work in Flash 9, even when copied and pasted directly from the A3CB .pdf to Flash 9. The code from the AS3 livedocs works just fine. I'm losing confidence in this text. [402] 16.10 - Pausing and Resuming Video; NetStream.pause() does not work how it is explained here. pause() no longer takes an argument, the relevant NetStream functions are: pause() close() play() resume() togglePause() {406} Code Example; line: import.flash.util.getTimer; should read: import.flash.utils.getTimer; [435-452] all of chapter 19; All DataFormat classes should be replaced with URLLoaderDataFormat classes. This pertains to all references of its constants BINARY, TEXT and VARIABLES. (437) Pages 437-439 don't really work.; I have been unsuccessful with Chapter 19: Sending and Loading Data using *any* of the code presented on pages 437-440. I think that something must have changed between the time the book was published and the public alpha of Flash 9. I *was successful* using the code from the Flash 9 livedocs. It would be nice if the website could indicate if anything has changed in AS 3 and provide updates if such is the case. {438} Code sample; 1. The third import should be : import flash.utils.* instead of import flash.util.trace 2. DataFormat.VARIABLES should be URLLoaderDataFormat.VARIABLES (438) handleHttpStatus function at bottom; An http status event firing does not necessarily mean that the load failed. A successful load still fires this event and event.status equals the default of 0. {439} Code sample ; 1. In the top of the page: 'Void' should be 'void' 2. The corresponding closing curly brace for the package is missing at the end of the sample. 3. All functions in this sample need an scope: private, public etc. The compiler sends a warning message. After the first paragraph: function handleComplete has two trace statements that need to be fixed: trace( "someText = " + data.someText ); trace( "someNumber = " + data.someNumber ); should be trace( "someText = " + loader.data.someText ); trace( "someNumber = " + loader.data.someNumber ); The loader qualifier is missing. [439] the examle for Loading Data ; Just want to submit a modified example of Loading Data. Hope this will help readers in future. package { import flash.display.Sprite; import flash.errors.*; import flash.net.*; import flash.utils.*; import flash.events.Event; import flash.text.TextField; public class Load extends Sprite{ public function Load(){ var loader:URLLoader=new URLLoader; loader.addEventListener(Event.COMPLETE, handleComplete); loader.dataFormat=URLLoaderDataFormat.VARIABLES; loader.load(new URLRequest("example.txt")); } public function handleComplete(event:Event):void{ var loader:URLLoader=URLLoader(event.target); var myText:TextField=new TextField(); addChild(myText); myText.width=600; myText.text="someText=" +loader.data.someText; } } } [442] 2nd line at top; loader.dataFormat = DataFormat.VARIABLES does not exist. Should be: loader.dataFormat = URLLoaderDataFormat.VARIABLES; (474) 2nd paragraph of Discussion; In the second sentence of the second paragraph, there's a spelling error on the last word (see below). To instruct the URLLoader to load the data as plain text, its dataFormat property must be set to DataFormat.Text. The last word should be: DataFormat.TEXT. http://safari.oreilly.com/0596526954/ID-I_0596526954_CHP_20_SECT_12 (475) script block line 9; loader.dataFormat = DataFormat.TEXT should be loader.dataFormat = URLLoaderDataFormat.TEXT; {480} 19.2; public class Example(){ ..... } should be public class Example{ ..... } {490} in the onWebServiceFault function; var fault:Fault = FaultEvent.fault; will throw errors, FaultEvent is the type of object, not its reference name. Should be: var fault:Fault = event.fault; [500 and 501] Towards bottom, p. 500--within code under step 1 of instruction. Top p. 501 under #6 instruction.; The LSO never updates because the code never changes its value. Hence the value remains at zero. This can be fixed by changing the 4th line of both code blocks to: //SUGGESTED REVISION: message_l_so.data.val = val+1; //ORIGINAL CODE: message_l_so.data.val = val;