Hi,
I have a program in which I am running a number of for loops which are doing a number of different things. I pull in data from an xml file and then step through that data to dynamically create arrays, populate the arrays, and create and modify movie clips.
The program I'm building is similar in scope to one I developed in Director many years ago, and in that environment we had to actually put breaks in using timers to ensure that the data would be processed and that the system wouldn't choke.
What I'm seeing with this flash version of the application is similar and I suspect the same. Basically, when navigating from the frame where the scripts are processed to the frame where the movie clips are displayed, there are times when it works perfectly and times when things are out of whack. I put in a 5 second delay (arbitrarily) to see if this would resolve the issue and on my system at least it does. But I need some advice on coming up with a real solution.
Any inofrmation you can give me about processing particularly as it relates to for loops and dynamic creation of elements (whether arrays or MCs) as well as making sure that everything is done woudl be greatly appreciated.
Best regards,
Chris McLaughlin
First thing to remember when dealing with Flash is that its architecture is based on frames.Flash is constantly moving from one to another even when there is only one frame. In the applications that are not relying on frames per se frame progression is used to refresh screen. Frame is not a "physical" entity but an interval between screen refreshes. In other words moving to the next frame is a scheduled screen refresh which DOES NOT take precedence over code.
This means that
1. scripts are executed on frame-by-frame basis
2. Flash WILL not move to another frame until ALL code on the current frame is executed.
For example, if the next frame is scheduled to in 100 ms but the code execution in the current frame takes 200ms - Flash will move to another frame ONLY in 200ms. This is why set frame rate is usually not the actual frame rate and is slower.
This is a bad news for applications that have bulky code and rely on frame rate animations. Especially this is true for timeline based animations.
In addition, default script execution timeout is 15 seconds that can be increased.
From performance optimization standpoint, I have a hard time to imagine an application that involves so much code in one frame that it chokes (even when thousands of objects are involved or thousands of loop iterations are performed). Perhaps, it can happen but, again, well thought out architecture will not allow for this kind of stuff to happen, especially because with AS3 event model one can easily pace out code execution.
Message was edited by: Andrei1
Hi Andrei,
First . . . thank you so much for your message.
I'm sure that there is something in the code architecture that's amiss. If you'd be kind enough to take a look and see if anything blatant jumps out at you I would be very grateful. I'm just not seeing it.
Here it is:
stop();
import flash.utils.*;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import fl.transitions.*;
import fl.transitions.easing.*;
import fl.transitions.Tween;
import fl.transitions.TweenEvent;
pageBlock_mc.mandatoryWarning_mc.visible = false;
sp1Mask_mc.height = 10;
scrollPane1_mc.mask = sp1Mask_mc;
//************************************************VARIABLES****************************************************
//******************************************************************** *******************************************
var tl:MovieClip = this;
var prd:int;
var seg:int;
var sld:int;
var ICPcontent:XML;
var productCount:Number;
var productName:String;
var segmentTitle:String;
var slideURL:String;
var productsArray:Array;
var AssuritySegmentsArray:Array;
var ComfortisSegmentsArray:Array;
var ComfortisMandatoryArray:Array;
var SWFsArray:Array;
var videosArray:Array;
var ReconcileSegmentsArray:Array;
var TrifexisSegmentsArray:Array;
var showArray:Array = new Array;
var tempArray:Array;
var subNum:Number = 1;
var textHeight:Number;
var xmlLoader:URLLoader = new URLLoader();
var whichMajorBucket:String;
var whichDeck:String;
var fct:String;
var segSlide:String
var breakTimer:Timer;
breakTimer = new Timer(500, 1);
breakTimer.addEventListener("timer", doNext);
function doNext(event:TimerEvent):void {
trace("DO NEXT TRIGGERED and fct = " + fct);
switch(fct) {
case "assurity":
trace("buildAssuritySlides()");
buildAssuritySlides();
break;
case "comfortis":
buildComfortisSlides();
break;
case "reconcile":
buildReconcileSlides();
break;
case "addListeners":
Object(this).startAssurity_btn.addEventListener(MouseEvent.M OUSE_DOWN, goToBuild);
Object(this).startComfortis_btn.addEventListener(MouseEvent. MOUSE_DOWN, goToBuild);
Object(this).startReconcile_btn.addEventListener(MouseEvent. MOUSE_DOWN, goToBuild);
Object(this).pickAssurityDeck_mc.core_btn.addEventListener(M ouseEvent.MOUSE_DOWN, goToBuild)
Object(this).pickAssurityDeck_mc.quickStart_btn.addEventList ener(MouseEvent.MOUSE_DOWN, goToBuild)
trace("last timer triggered");
fct = "ready?";
breakTimer = new Timer(5000, 1);
breakTimer.addEventListener("timer", doNext);
breakTimer.start();
break;
case "ready?":
Object(this).pageBlock_mc.visible = false;
break;
}
}
//******************************************************************** *******************************************
xmlLoader.addEventListener(Event.COMPLETE, loadContent);
xmlLoader.load(new URLRequest("data/elancoICP.xml")); // + "?" + Math.random())
//xmlLoader.load(new URLRequest("data/elancoICP.xml" + "?" + Math.random()));
function loadContent(e:Event):void {
XML.ignoreWhitespace = true;
ICPcontent = new XML(e.target.data);
productCount = ICPcontent.product.length()
trace("the product count = " + productCount);
productsArray = new Array;
for (var i:int = 0; i<productCount; i++){
productName = ICPcontent.product[i].productName.text();
productsArray.push(productName);
}
trace("productsArray = " + productsArray);
buildAssurity();
}
function buildAssurity(): void {
tempArray = new Array();
AssuritySegmentsArray = new Array();
for( var a:int = 0; a < ICPcontent.product[0].segmentName.length(); a++) {
segmentTitle = ICPcontent.product[0].segmentName[a].text();
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.text = segmentTitle;
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.autoSize = TextFieldAutoSize.CENTER
textHeight = scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.height
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.selectable = false;
if(textHeight < 35) {
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.y = 26;
} else {
if((textHeight > 22) && (textHeight < 50)) {
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.y = 17;
} else {
if(textHeight > 50){
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.y = 10;
}
}
}
subNum++;
AssuritySegmentsArray.push(segmentTitle);
tl["Assurity_" + segmentTitle + "_Array"] = new Array();
tl["Assurity_" + segmentTitle + "_Array"].name = "Assurity_" + segmentTitle + "_Array"
}
if(a == ICPcontent.product[0].segmentName.length()) {
buildComfortis();
}
}
function buildComfortis(): void {
ComfortisSegmentsArray = new Array();
for( var c:int = 0; c < ICPcontent.product[1].segmentName.length(); c++) {
segmentTitle = ICPcontent.product[1].segmentName[c].text();
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.text = segmentTitle;
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.autoSize = TextFieldAutoSize.CENTER
textHeight = scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.height
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.selectable = false;
if(textHeight < 35) {
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.y = 26;
} else {
if((textHeight > 22) && (textHeight < 50)) {
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.y = 17;
} else {
if(textHeight > 50){
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.y = 10;
}
}
}
subNum++;
ComfortisSegmentsArray.push(segmentTitle);
tl["Comfortis_" + segmentTitle + "_Array"] = new Array();
tl["Comfortis_" + segmentTitle + "_Array"].name = "Comfortis_" + segmentTitle + "_Array"
}
ComfortisMandatoryArray = new Array();
var mandatory:String;
for(var cm:int = 0; cm < ICPcontent.product[1].mandatorySlides.slide.length(); cm++) {
mandatory = ICPcontent.product[1].mandatorySlides.slide[cm].text();
ComfortisMandatoryArray.push(mandatory);
}
SWFsArray = new Array();
var SWF:String;
for(var s:int = 0; s < ICPcontent.product[1].SWFs.slide.length(); s++) {
SWF = ICPcontent.product[1].SWFs.slide[s].text();
SWFsArray.push(SWF);
}
videosArray = new Array();
var video:String;
for(var v:int = 0; v < ICPcontent.product[1].Videos.slide.length(); v++) {
video = ICPcontent.product[1].Videos.slide[v].text();
videosArray.push(video);
}
if(c == ICPcontent.product[1].segmentName.length()) {
buildReconcile();
}
function buildReconcile():void {
ReconcileSegmentsArray = new Array();
for( var r:int = 0; r < ICPcontent.product[2].segmentName.length(); r++) {
segmentTitle = ICPcontent.product[2].segmentName[r].text();
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.text = segmentTitle;
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.autoSize = TextFieldAutoSize.CENTER
textHeight = scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.height
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.selectable = false;
if(textHeight < 35) {
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.y = 26;
} else {
if((textHeight > 22) && (textHeight < 50)) {
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.y = 17;
} else {
if(textHeight > 50){
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf.y = 10;
}
}
}
subNum++;
ReconcileSegmentsArray.push(segmentTitle);
tl["Reconcile_" + segmentTitle + "_Array"] = new Array();
tl["Reconcile_" + segmentTitle + "_Array"].name = "Reconcile_" + segmentTitle + "_Array"
}
trace("assurity segments = " + AssuritySegmentsArray);
trace("comfortis segments = " + ComfortisSegmentsArray);
trace("reconcile segments = " + ReconcileSegmentsArray);
var sp1level:Number = scrollPane1_mc.numChildren - 1;
trace("sp1level = " + sp1level);
if(r == ICPcontent.product[2].segmentName.length()) {
fct = "assurity"
breakTimer.start();
}
}
}
function buildAssuritySlides(): void {
trace("buildAssuritySlides() triggered");
var aSegLength:Number = AssuritySegmentsArray.length-1;
var aSldLength:Number = ICPcontent.product[0].segmentSlides[aSegLength].slide.length()-1
trace("aSegLength = " + aSegLength + " & aSldLength = " + aSldLength);
for (seg = 0; seg < AssuritySegmentsArray.length; seg++) {
for (sld = 0; sld < ICPcontent.product[0].segmentSlides[seg].slide.length(); sld++) {
segSlide = String(ICPcontent.product[0].segmentSlides[seg].slide[sld].text());
tl["Assurity_" + String(AssuritySegmentsArray[seg]) + "_Array"].push(segSlide)
if(seg == aSegLength) {
trace("sld = " + String(sld))
if(sld == aSldLength) {
trace("IT DOES sld = 8");
fct = "comfortis";
breakTimer = new Timer(500, 1);
breakTimer.addEventListener("timer", doNext);
breakTimer.start();
}
}
}
}
}
function buildComfortisSlides(): void {
var cSegLength:Number = ComfortisSegmentsArray.length-1;
var cSldLength:Number = ICPcontent.product[1].segmentSlides[cSegLength].slide.length()-1
for (seg = 0; seg < ComfortisSegmentsArray.length; seg++) {
for (sld = 0; sld < ICPcontent.product[1].segmentSlides[seg].slide.length(); sld++) {
segSlide = String(ICPcontent.product[1].segmentSlides[seg].slide[sld].text());
tl["Comfortis_" + String(ComfortisSegmentsArray[seg]) + "_Array"].push(segSlide)
if(seg == cSegLength) {
if(sld == cSldLength) {
trace("IT DOES");
fct = "reconcile";
breakTimer = new Timer(500, 1);
breakTimer.addEventListener("timer", doNext);
breakTimer.start();
}
}
}
}
}
function buildReconcileSlides(): void {
var rSegLength:Number = ReconcileSegmentsArray.length-1;
var rSldLength:Number = ICPcontent.product[2].segmentSlides[rSegLength].slide.length()-1
for (seg = 0; seg < ReconcileSegmentsArray.length; seg++) {
for (sld = 0; sld < ICPcontent.product[2].segmentSlides[seg].slide.length(); sld++) {
segSlide = String(ICPcontent.product[2].segmentSlides[seg].slide[sld].text());
tl["Reconcile_" + String(ReconcileSegmentsArray[seg]) + "_Array"].push(segSlide)
if(seg == rSegLength) {
if(sld == rSldLength) {
trace("IT DOES");
fct = "addListeners";
breakTimer = new Timer(500, 1);
breakTimer.addEventListener("timer", doNext);
breakTimer.start();
}
}
}
}
}
function checkAslide(): void {
trace("checking the Comfortis Mode of Action slides")
trace ("array = " + tl["Comfortis_" + String(ComfortisSegmentsArray[0]) + "_Array"][0]);
}
function goToBuild(event:MouseEvent):void {
switch(event.target.name) {
case "startAssurity_btn":
// whichMajorBucket = "Assurity";
// if(pickAssurityDeck_mc.y == 275) {
// trace("it's hidden");
// var showTween:Tween = new Tween(pickAssurityDeck_mc, "y", Strong.easeOut, 275, 392, 1, true);
// } else {
// var hideTween:Tween = new Tween(pickAssurityDeck_mc, "y", Strong.easeOut, 392, 275, 1, true);
// }
break;
case "quickStart_btn":
//whichMajorBucket = "Assurity";
// whichDeck = String(AssuritySegmentsArray[0])
// gotoAndPlay("builder");
break;
case "core_btn":
//whichMajorBucket = "Assurity";
// whichDeck = String(AssuritySegmentsArray[1])
// gotoAndPlay("builder");
break;
case "startComfortis_btn":
whichMajorBucket = "Comfortis";
whichDeck = "Core";
gotoAndPlay("builder");
break;
case "startReconcile_btn":
//whichMajorBucket = "Reconcile";
// whichDeck = "Core";
// gotoAndPlay("builder");
break;
}
}
I looked at a part of your code and even a brief encounter uncovered huge number if inefficiencies. There are tons of redundancies, inefficient object referencing, unnecessary casting, undefined variables, etc.
Timer that you implemented has no sense and I believe introduces significant performance hits.
You are better off to start from scratch and post it here function by function in a logical manner that reflects the flow of your application.
Hi Andrei,
I had to step away. I apologize for the delay in responding.
Again, I thank you for your interest and messages.
Unfortunately, while your comments may be completely correct I am unsure where the various inefficiencies, object referencing casting etc. to which you refer arise, and starting over is simply not an option at this point.
I had hoped that at a glance you might see something that you could use as an example. But I understand and agree that 500 lines of code is a lot to look through and I'm afraid I'm still a novice when it comes to formatting it for proper display on this forum.
Thank you for trying to help. I truly appreciate your effort on my behalf.
Best regards,
Chris McLaughlin
"and starting over is simply not an option at this point."
I am sorry you feel this way because without revamping the code you have shown you will not attain decent performance.
Besides the code it feels like XML structure is not efficient as well - this is an impressions I got from how you parse XML. For the future references data structure is EXTREMELY important for application performance optimization.
In case you decide to rethink the architecture here is an example how you can improve your code. Note, I did not test the code - it is just a concept. In addition, this is just a partial improvement. You parsing routine should be rewritten altogether.
This code addresses the following inefficiencies:
You parse through the same entity at least two times when you can do it in a single loop. In this example you parse through ICPcontent.product[0] in buildAssurity() and then in buildAssuritySlides(). The drawback is that you introduce an extra loop and have to declare extra variables.On the other hand you reference the same entity numerous times through making Flash searching for them every time. For instance:
scrollPane1_mc["sub" + (a + 1) + "_mc"].text = segmentTitle;
scrollPane1_mc["sub" + (a + 1) + "_mc"].autoSize = TextFieldAutoSize.CENTER;
scrollPane1_mc["sub" + (a + 1) + "_mc"].selectable = false;
textHeight = scrollPane1_mc["sub" + (a + 1) + "_mc"].height;
Is much less efficient and much more cumbersome than:
var tf:TextField = scrollPane1_mc["sub" + (a + 1) + "_mc"].sbText_tf;
tf.text = segmentTitle;
tf.autoSize = TextFieldAutoSize.CENTER;
tf.selectable = false;
textHeight = tf.height;
Code below combines buildAssurity() and buildAssuritySlides() into a single processing unit. In this example extra conditional logic is removed and more streamlined references are introduced. Read comments:
function buildAssurity():void {
// keep reference for reusing
var xmlList:XMLList = ICPcontent.product[0];
// define reference so that Flash doesn't have to make an effort to read length of node
var len:int = xmlList.length();
// the same as len
var slideLen:int;
// create a single reference to text field so that you can reuse it
var tf:TextField;
// iterators
var s:int = 0;
for (var i:int = 0; i < len; i++) {
// you declare it in a higher scope, so for noe it is OK
segmentTitle = xmlList.segmentName[i].text();
// create array so that you can reference it
var segArray:Array = [];
slideLen = xmlList.segmentSlides[i].slide.length();
for (s = 0; s < slideLen; s++) {
segSlide = xmlList.segmentSlides[i].slide[s].text();
segArray.push(segSlide)
}
// assign Array value to whatever
// by the way, why is MovieClip designed to hold array?
tl["Assurity_" + segmentTitle + "_Array"] = segArray;
// THIS PART MAKES NO SENSE BECAUSE ARRAY HAS NO NAME PROPERTY
tl["Assurity_" + segmentTitle + "_Array"].name = "Assurity_" + segmentTitle + "_Array";
// deal with text field
tf = scrollPane1_mc["sub" + (i + 1) + "_mc"].sbText_tf;
tf.text = segmentTitle;
tf.autoSize = TextFieldAutoSize.CENTER;
tf.selectable = false;
textHeight = tf.height;
// this is exactly what it was without unneeded extra conditionals
if(textHeight < 35) {
tf.y = 26;
}
else if ((textHeight > 22) && (textHeight < 50)) {
tf.y = 17;
}
else {
tf.y = 10;
}
}
}
The same can be done with buildComfortis() and buildComfortisSlides() as well as buildReconcile() and buildComfortisSlides().
As a matter of fact these three redundancies (six methods) are so similar that they can (and should) be combined into a single method which will reduce code and processing time in half.
" I'm afraid I'm still a novice when it comes to formatting it for proper display on this forum."
Sorry but it takes only a couple of clicks (arrow next to smiley >> your highlight choice).
In addition, you owe it to yourself to make code readable, right?
Hi Andrei,
First I agree that making the code readable is essential. Thank you for showing me the light.
As you may have guessed I'm working under unrealistic time constraints which always (or almost always) leads to sloppy code.
Second, after thinking about your email I realized that the problem wasn't with the code being executed on that frame. Much of the redundancies to which you refer were added as an attempt to solve the issue I was seeing. I thought that perhaps things were stepping on top of each other and went back in and broke it into smaller and smaller chunks and when that didn’t solve it I began putting the timed breaks in between.
All of which was making it less and less efficient, but as I still had the problem and was narrowly focusing on the frame one script . . . well I couldn't see the forest for the trees.
When I stepped away, and was thinking about what you wrote, it didn't take long to realize that the problem I was seeing had nothing to do with the scripts on that frame, and of course that's when I found the real problem.
So anyway a BIG thank you for your advice, and also for your examples which confirm that restoring the code to its prior form is a good first step.
There are also some additional things you have suggested that I hadn't thought of but could make life easier.
If you're interested I'll keep you posted (with proper formatting).
Thanks,
Chris
Yes, I thought about it more and even with all the inefficiencies of the presented code it looks like the bottleneck is elsewhere. What frame 1 code does it is just XML parsing which is a fast process event with huge XMLs.
I suspect that you need to look into something that happens after XML is parsed. What happens? Do you load images? How many?
Also, it looks like you have a lot of hardcoded objects on timeline or in other clips on timeline. Is it true?
In addition, it seems that objects in teh application are linked to XML values. In other words there are as many objects as values in XML. Is this assumption also true?
Hi Andrei,
I have a lot of hardcoded objects, and yes XML values are used to govern pretty much everything.
Originally, I was doing everything dynamically but it just wasn't fast enough. I can't remember if I tried just eliminating the external images (thumbnails) or did that and the holder MCs simultaneously, but I saw a huge increase in speed as a result of one or both and didn't look back.
The thumbnails are of course there to provide access to larger images, or SWFs and those are all created dynamically. After the XML is parsed I navigate to a frame in which the thumbnails are shown. Again that happens instantly. The problem occurs with the movie clips that contain the text fields these are all created in that frame 1 script that you saw, and I'm simply instantiating a new class; modifying the text in its pre-existing text field, adding it to a movie clip on the stage, and positioning it.
The latter is where the problem creeps in. The display objects all start at the same position relative to another object on the stage and then I use the tween class to move them to their new position -- creating a vertical accordion effect. So the problem is in there somewhere and my guess is it will take a lot less time to fix it than to restore the frame 1 script. Also, if I had to I could live without the effect. My guess is that the problem as to do with using the same tween variable for each repositioning. I can easily create those variables dynamically but you know . . . sometimes you cut corners.
What I was seeing (occasionally) was all of the clips in their original positions, and reasoned that their instantiation which happens in that frame one script was the issue.
Again many thanks.
Chris
If the problems you have are related to the project you describe in the thread, it doesn't matter if it is AIR or is targeted for the web. AS3 is AS3 is AS3 anywhere. I feel your application has design problems and, of course, I cannot be more specific because I did not see is.
Also, frankly, I am not a fan of timeline coding and avoid it like plague precisely for the code manageability/performance issues. So, I am not sure I will be willing to help beyond specific code pieces and architecture advise.
Thanks to Andrei's excellent analysis I realized I was barking up the wrong tree so to speak and that the problems I was seeing had to do with a different script entirely and that I was infact decreasing the efficiency of my code in my effort to slow it down. Flash is amazingly fast when it comes to creating new objects and it's good to keep that in mind as it's unlikely that even large numbers of dynamic object creations will be the culprit.
Chris,
You did not go into details of your entire application but it feels like it is just a slide show (or, at least, a part of it is a slide show). Slide shows are done millions of times and, it appears, is the first application the majority of Flash developers start with. I am saying it because it is a pretty simple application and even with hundreds of images it performs well.It shouldn't be more than 50KB (without external images, of course).
I am writing this to encourage you to revamp the thing. It may feel terrifying but the truth is that in 90% of cases difficulties grow like a snowball because architecture was never thought out and what people often do is just jumping into coding. There is no a good remedy for a sub-par design. Code re-factoring and bottleneck chasing takes 100 times longer than coding from scratch.
Believe it or not, writing of a good, well architected applications is just 15% of an effort and takes very little time as a matter of fact. Good programming is not as much about knowledge of libraries as about an ability to come up with top level language-independent concepts.
AS3, even if it is done on timeline, offers great ways to write OO applications with reusable code and objects. This is, in many ways, a key to good software performance.
So, what do you say?
One more thing.
Actually your code is pretty cool conceptually. You are attempting to split functionality into smaller pieces to decrease the load on application per unit of time. There are whole frameworks written around this concept.
Nevertheless, again, it just feels like an overkill in this particular case mainly because there are more streamlined ways to deal with payload in AS3. Especially as far as Timer is concerned (Timer is quite an unreliable thing despite the first notion that is one is in control of time). In particular, AS3 events model offers a huge advantage.
Hi Andrei,
The code revamp is mostly done. As I mentioned, once I understood that the problem had nothing to do with the code being processed in that frame I went back and restored the original code. And I fully intend to explore your recommendations when time allows to see if this makes sense. As it is I run two functions: one that builds the arrays and a second that builds the objects once the arrays are built. I can see based on your example that it could all be done within a single function, and that there are some other inefficiencies I could do away with.
Believe it or not I am not a beginner. I says this sheepishly because I recognize that there are still lots of stupid things I do especially when writing under the gun so to speak. I started out writing in open script (tool book) in the 90s, then moved to Lingo (Director) then to Director and AS2, then made the leap to AS3 and now it's AS3 with Air. The whole idea of breaking the code down came from my experience working in Director where we did have to break the code to keep the system from locking up. I looked at that code the other day and it made me dizzy.
Unfortunately, I have clients who are asking for things in impossibly short time frames and I know that it will be a week or two before the deliverable is updated. So I try to meet their deadline and then plan to improve the code along the way.
But I say yes, I will revamp and provide the improved code block though not until after Wednesday- the deadline.
Finally, it is a slide show essentially. A slide show with some fancy features geared toward the needs of a highly regulated industry.
Best,
Chris
Hi Andrei,
Here is how I reformatted. How does it look:
function loadContent(e:Event):void {
trace("load content
triggered");
productsArray = new Array;
tempArray = new
Array();
AssuritySegmentsArray = new Array();
ComfortisSegmentsArray =
new Array();
ReconcileSegmentsArray = new Array();
XML.ignoreWhitespace = true;
ICPcontent = new XML(e.target.data);
productCount = ICPcontent.product.length()
trace("the product count
= " + productCount);
for (prd = 0; prd<productCount;
prd++){
//Assign XML Child to XML Object -- Not XMLList
var
products:XML = ICPcontent.product[prd]
trace("product name = " +
ICPcontent.product[prd].productName.text());
trace("product name retrived
from products XML = " + products.productName.text())
var len:int =
products.length();
var segLen:int;
var sldLen:int;
var
tf:TextField;
productName = products.productName.text()
trace("prd = " +
prd + " productName = " + productName);
productsArray.push(productName);
segLen =
products.segmentName.length();
for( seg = 0; seg < segLen; seg++)
{
segmentTitle = products.segmentName[seg].text();
tf =
scrollPane1_mc["sub" + subNum + "_mc"].sbText_tf
tf.text =
segmentTitle;
tf.autoSize = TextFieldAutoSize.CENTER
textHeight =
tf.height
tf.selectable = false;
if(textHeight < 35)
{
tf.y = 26;
} else if((textHeight > 22) &&
(textHeight < 50)) {
tf.y = 17;
} else {
tf.y =
10;
}
//Push the segment titles into
Arrays;
//create arrays to hold segment slides;
//add slides to
arrays
sldLen =
products.segmentSlides[seg].slide.length()
//tl is a variable
that refeers to the top level
// the equivalent of using
this[productName + "SegmentsArray"]
//allows reference to and dynamic
creation of Arrays that can
//be accessed
tl[productName +
"SegmentsArray"].push(segmentTitle);
tl[productName + "_" + segmentTitle
+ "_Array"] = new Array();
for (sld = 0; sld < sldLen; sld++)
{
segSlide =
String(products.segmentSlides[seg].slide[sld].text());
tl[productName +
"_" + segmentTitle +
"_Array"].push(segSlide)
}
}
subNum++
}
}
How does it work?
Here are some little improvements. I commented them:
function loadContent(e:Event):void {
trace("load content triggered");
productsArray = new Array();
tempArray = new Array();
AssuritySegmentsArray = new Array();
ComfortisSegmentsArray = new Array();
ReconcileSegmentsArray = new Array();
// this is set to true by default
//XML.ignoreWhitespace = true;
ICPcontent = new XML(e.target.data);
productCount = ICPcontent.product.length();
// declare iterators and length before loop
var segLen:int;
var sldLen:int;
var tf:TextField;
var products:XML;
trace("the product count = " + productCount);
for (prd = 0; prd < productCount; prd++) {
//Assign XML Child to XML Object -- Not XMLList
products = ICPcontent.product[prd];
trace("product name = " + ICPcontent.product[prd].productName.text());
trace("product name retrived from products XML = " + products.productName.text())
productName = products.productName.text()
trace("prd = " + prd + " productName = " + productName);
productsArray.push(productName);
segLen = products.segmentName.length();
for( seg = 0; seg < segLen; seg++) {
segmentTitle = products.segmentName[seg].text();
// I understand prd = subNum
tf = scrollPane1_mc["sub" + prd + "_mc"].sbText_tf
tf.text = segmentTitle;
tf.autoSize = TextFieldAutoSize.CENTER
textHeight = tf.height
tf.selectable = false;
if(textHeight < 35) {
tf.y = 26;
} else if((textHeight > 22) && (textHeight < 50)) {
tf.y = 17;
} else {
tf.y = 10;
}
//Push the segment titles into Arrays;
//create arrays to hold segment slides;
//add slides to arrays
sldLen = products.segmentSlides[seg].slide.length();
//tl is a variable that refeers to the top level
// the equivalent of using this[productName + "SegmentsArray"]
//allows reference to and dynamic creation of Arrays that can
//be accessed
tl[productName + "SegmentsArray"].push(segmentTitle);
tl[productName + "_" + segmentTitle + "_Array"] = new Array();
for (sld = 0; sld < sldLen; sld++) {
tl[productName + "_" + segmentTitle + "_Array"].push(String(products.segmentSlides[seg].slide[sld].text()))
}
}
// prd = subNum?
//subNum++
}
}
Hi Andrei,
It works great.
With respect to prd == subNum, well they don't, but they probably should. The objects referred to by subNum exist on the stage. I can't remember but this may have been a first attempt to deal with the issue I was seeing (that I learned had nothing to do with this script), or it may have been planned to work around the issues that arise with respect to targeting dynamically created objects (this.getChildByName) . . .
So instead of dynamically creating those objects and then assigning text to their pre-existing text fields, I am simply assigning the text. A common thing that I do still is create objects with a numerical identifiers in which the numbering starts with 1. And I am always then going back and putting in some small correction for that like subNum. I did this in another place where everything was being created dynamically and generating all kinds of errors and mistakes and eventually wised up. There's nothing wrong with starting with 0. Habits once ingrained are difficult to break I intend to break this one.
Thanks again for your interest in this and your suggestions.
Best,
Chris
North America
Europe, Middle East and Africa
Asia Pacific