LoaderMax Tips & Tricks

Although LoaderMax is intended to simplify loading in AS3, its rich feature set might make it a little intimidating at first. Most developers aren’t using it to its full potential. In addition to listing some tips and tricks here, I’ll also try to clear up a few common misperceptions. The list should grow over time, so keep checking back to learn more. If you have any tips to share, please do so in the comments section below. To get notified when new tips are added, feel free to follow @greensock on Twitter and make sure you sign up for a free GreenSock account. For some tweening tips & tricks, click here.

1) SWFLoader and ImageLoader “content” vs. “rawContent”

Need to reference the root of a subloaded swf? Or the Bitmap that was loaded with an ImageLoader? Make sure you use the loader’s “rawContent” instead of “content”. In general, it’s always best to use a loader’s “content” but for SWFLoaders and ImageLoaders, “content” refers to a ContentDisplay Sprite that gets created immediately and serves as a wrapper for the raw content. A SWFLoader will put the subloaded swf’s root into the ContentDisplay. Likewise, an ImageLoader puts the Bitmap into its ContentDisplay. Why? So that you don’t have to wait for the raw content to load before putting it into the display list or adding event listeners (rollovers/outs/clicks), etc. The rawContent could be an Image, a MovieClip, a Loader, or a Video, so the ContentDisplay wrapper also provides a consistent type of object across all of those loaders. And ContentDisplay provides some nifty resizing and cropping functionality. So in general, you should always use the “content” unless you must directly access the raw content of a SWFLoader or ImageLoader. Here’s an example for a SWFLoader that loads a swf whose root document class has a “myCustomFunction()” method that we can call:

var loader:SWFLoader = new SWFLoader("child.swf", {onComplete:onLoadSWF, width:200, height:100});
addChild(loader.content); //add the ContentDisplay to the display list even before raw content is loaded.
loader.load();

function onLoadSWF(event:LoaderEvent):void {
	var mc:MovieClip = loader.rawContent; //the root of the child swf
	mc.myCustomFunction();
}

2) Feel free to use standalone loaders

If, for example, you just want to load a single swf file, there’s no need to wrap the SWFLoader in a LoaderMax.

//this is perfectly acceptable:
var loader:SWFLoader = new SWFLoader("child.swf", {onComplete:completeHandler});
loader.load();

//you do NOT need to do this (although it works fine):
var queue:LoaderMax = new LoaderMax({onComplete:completeHandler});
queue.append( new SWFLoader("child.swf") );
queue.load();

The primary benefit of putting a loader into a LoaderMax is when you have multiple loaders – the LoaderMax handles managing the order in which they load and reporting on their progress as a whole.

3) Define your loaders in XML for easy updates

Did you know that XMLLoader automatically looks at the XML file it loads and tries to find LoaderMax-related data? It creates the corresponding instances for you and optionally starts loading them too. So, for example, let’s define some XML that loads 2 images automatically:

<?xml version="1.0" encoding="iso-8859-1"?>
<data>
	<ImageLoader url="1.jpg" name="image1" load="true" />
	<ImageLoader url="2.jpg" name="image2" load="true" />
</data>

The ActionScript to load the XML and images would look like:

LoaderMax.activate([ImageLoader]); //only necessary once - allows XMLLoader to recognize ImageLoader nodes inside the XML

var loader:XMLLoader = new XMLLoader("data.xml", {onComplete:completeHandler, estimatedBytes:50000});
loader.load();

function completeHandler(event:LoaderEvent):void {
    var image1:Bitmap = LoaderMax.getLoader("image1").rawContent;
	var image2:Bitmap = LoaderMax.getLoader("image2").rawContent;
}

But let’s take it a step further and create two LoaderMax nodes in the XML, one that loads immedaitely and one that doesn’t. Let’s also set more of the options on the ImageLoaders to make things easier once we get it into ActionScript and let’s utilize the prependURLs attribute so that we can make switching to another server very simple:

<?xml version="1.0" encoding="iso-8859-1"?>
<data>
    <LoaderMax name="queue1" prependURLs="http://www.greensock.com/assets/images/" load="true">
	    <ImageLoader url="1.jpg" name="image1" width="200" height="150" scaleMode="proportionalInside" alpha="0" />
	    <ImageLoader url="2.jpg" name="image2" width="400" height="300" scaleMode="proportionalOutside" crop="true" />
    </LoaderMax>
	<LoaderMax name="queue2" prependURLs="http://www.greensock.com/assets/" load="false">
	    <SWFLoader url="swf/child.swf" name="child" autoPlay="false" />
	    <VideoLoader url="video/video.flv" name="video" width="400" height="300" scaleMode="stretch" autoPlay="false" />
    </LoaderMax>
</data>

Now in ActionScript, the XMLLoader will automatically parse all the loaders but it will only load the FIRST LoaderMax contents because its “load” attribute was set to “true”. Then, when the XMLLoader completes, we know that our images are loaded, but then we want to load the SECOND LoaderMax’s contents (a swf and a video) in the background, so we’d do:

LoaderMax.activate([ImageLoader, SWFLoader, VideoLoader]);
var loader:XMLLoader = new XMLLoader("data.xml", {onComplete:completeHandler, estimatedBytes:50000});
loader.load();

function completeHandler(event:LoaderEvent):void {
    trace("XML and queue1 loaded!");
    addChild( LoaderMax.getContent("image1") );
	addChild( LoaderMax.getContent("image2") );

	//grab the LoaderMax named "queue2" that was defined in the XML and start loading it now
	var queue2:LoaderMax = LoaderMax.getLoader("queue2");
	queue2.addEventListener(LoaderEvent.COMPLETE, queue2CompleteHandler);
	queue2.load();
}

function queue2CompleteHandler(event:LoaderEvent):void {
    trace("queue2 loaded!");
}

Note: your XML file can contain other non-LoaderMax-related data too.

4) Easy preloader progress bars: scaleX = progress

Build your preloader’s progress bar so that its native size is exactly what it should be when loading finishes (100%) and then just use the LoaderMax “progress” property and assign it to your progress bar’s scaleX, like this:

var queue:LoaderMax = new LoaderMax({onProgress:progressHandler});
//...append various loaders...
queue.load();

function progressHandler(event:LoaderEvent):void {
    myProgressBar.scaleX = event.target.progress;
}

5) Estimate bandwidth and/or how much time is left

Every loader has a “loadTime” property that tells you how many seconds elapsed while the loader was loading. So to estimate bandwidth, you can use loadTime and bytesLoaded like this:

var kbps:Number = (loader.bytesLoaded / loader.loadTime) / 1024;

And to estimate how many more seconds it will take to finish loading, you can do this:

var secondsLeft:Number = ((1 / loader.progress) - 1) * loader.loadTime;

6) Fit a video/image/swf into an area

It’s pretty common to have a particular area into which your image/video/swf must fit when it loads. For example, maybe you have a grid of thumbnails and the native size of each image file may not be consistent or predictable. No problem. Just set the width and height properties of your ImageLoader/SWFLoader/VideoLoader and it will scale the content to fit into that size.

var loader:ImageLoader = new ImageLoader("1.jpg", {width:200, height:100, container:this});
  	

By default it will fit the content exactly (stretching if necessary), but if you prefer that the content scales proportionally to fit inside the area, simply set the scaleMode to “proportionalInside”. In that case, there may be extra space vertically or horizontally, so you can control the alignment inside the area with the “hAlign” and “vAlign” special properties (they’re both “center” by default). You can even fill the area in with a color using the “bgColor” special property. Here’s an example that loads an image into a 200×100 area with a red (0xFF0000) background, scaling it proportionally to fit inside and positioning the area at the coordinates x:50, y:70:

var loader:ImageLoader = new ImageLoader("1.jpg", {width:200, height:100, scaleMode:"proportionalInside", bgColor:0xFF0000, container:this, x:50, y:70});
	

The other nice thing is that the ContentDisplay object (a Sprite) into which the image will be loaded is created immediately, so you can position it on the stage wherever you want, add MouseEvent listeners, etc. even before (or while) it loads. For example, to add a CLICK listener to the image that’s loading in the example above, we’d simply do:

loader.content.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(event:MouseEvent):void {
    trace("clicked image associated with loader: " + event.currentTarget.loader);
}

Bonus tip: If you’d like to change the area’s size into which the content is scaled to fit (after you create the loader), you can alter the ContentDisplay’s “fitWidth” and/or “fitHeight” properties.

7) Crop a video/image/swf within an area

Imagine a background image that you’d like to fill an area with, scaling it proportionally to fill, but instead of fitting all the pixels INSIDE the area, you want to allow them to spill out so that there is no empty space vertically or horizontally. No problem. Set the width and height properties of the loader and set the scaleMode to “proportionalOutside”. Then set the “crop” special property to true in order to slice off the overspill, like:

var loader:ImageLoader = new ImageLoader("1.jpg", {width:200, height:100, scaleMode:"proportionalOutside", crop:true, container:this, x:50, y:70});
	

8) “progress” vs. “rawProgress” – what’s the difference?

All loaders have a “progress” property that reports the bytesLoaded / bytesTotal ratio, but LoaderMax instances also have a more crude “rawProgress” that grants all child loaders equal weight in the calculation and doesn’t concern itself with file size at all. “rawProgress” can be useful in certain scenarios like if you’re getting a progress bar that “jumps” (see tip 9) or when you want to skip file size audits and also avoid defining estimatedBytes values for your loaders. In the interactive demo below, you can see how the “progress” and “rawProgress” values compare in various scenarios. Notice how “rawProgress” never jumps but it does change the speed at which it moves based on the size of the file that’s loading. Click load() and see how smooth and accurate the “progress” bar is. Then try changing the estimatedBytes to inaccurate values or deleteing them altogether to see how it works when you omit estimatedBytes on child loaders. Uncheck the “auditSize” checkbox too in order to watch what happens when you turn file size audits off. For a more full explaination of what causes the “jumping” in the “progress” property, see tip 9.

9) Avoid a jerky progress bar

Ever seen a progress bar that appears to suddenly jerk forwards or backwards unexpectedly? It doesn’t happen on individual loaders, but it can happen on a LoaderMax instance that is reporting the overall progress of multiple loaders (its children) in very particular scenarios. First let me explain the cause and then I’ll get to the solution.

In order to accurately calculate the overall progress of a group of loaders, it’s important to know the total file size (bytesTotal) of each child loader. But if some files haven’t started loading yet, how could we possibly know their sizes? LoaderMax tackles that challenge in two ways: First, it recognizes an “estimatedBytes” special property that you can optionally define when you create your loader(s) like this:

new ImageLoader("1.jpg", {estimatedBytes:26000});

If you define an estimatedBytes value for a loader, LoaderMax uses that in its “progress” calculations until the file starts loading at which point it swaps in the accurate bytesTotal. If your estimatedBytes value was very inaccurate, though, you’ll see that jerking behavior in the “progress” value when the size is corrected. If you underestimated the value quite a bit, the progress will jump backward at that point. If you overestimate, it will jump forward.

The other way LoaderMax tackles the challenge of accurately calculating progress is by auditing the real files. By default, when a LoaderMax begins loading it checks all of its child loaders and if it finds any that don’t have an “estimatedBytes” defined, it will quickly open up a URLStream for each one just long enough to determine the bytesTotal from the server at which point it terminates the connection and moves on to the next file. Once the auditing process is complete, the LoaderMax will begin loading the full files in the correct order. The great thing about the file audits is that they make progress reporting VERY accurate with minimal hassle for you. The down side is that it costs a little extra time initially. You can, of course, turn auditing off by passing auditSize:false into your LoaderMax’s vars parameter or set the default globally with the static defaultAuditSize property like this:

//turns auditing off for only this instance:
var queue:LoaderMax = new LoaderMax({auditSize:false});

//changes the default auditSize to false for all LoaderMax instances created after this point
LoaderMax.defaultAuditSize = false;

A default file size value (bytesTotal) of 20,000 bytes will be used initially for all loaders that don’t have an estimatedBytes defined. But again, this value will be corrected as soon as the file starts loading or is audited.

Phew! So now you understand the problem. Let’s get to the solution. Actually, there are several solutions to choose from:

  • Minimal hassle, very accurate, slight delay (default): omit estimatedBytes from all (or some) of your loaders and let LoaderMax audit their size.
  • Moderate hassle, accuracy varies, no delay: define an estimatedBytes value for your loaders in order to skip auditing and get maximum performance. The “progress” accuracy completely depends on your estimatedBytes values. The more you underestimate, the more the “progress” will jump backward when the real size is determined. Overestimating will cause it to jump forward.
  • Minimal hassle, very inaccurate, no delay: turn auditing off in the LoaderMax instance by passing auditSize:false in the vars object (or set the static LoaderMax.defaultAuditSize = false). This will use a default size of 20,000 bytes for files that don’t have an “estimatedBytes” defined. The “progress” value will jump each time a child loader begins loading. If you don’t plan on reporting the overall progress, this option is perfectly acceptable.
  • Minimal hassle, somewhat accurate, no delay: turn auditing off in the LoaderMax instance but instead of using the LoaderMax’s “progress”, use its “rawProgress”. As illustrated above in tip 8, rawProgress never jumps but it varies the speed at which it moves based on the size of the file that’s loading. If you plan to only use “rawProgress”, there is no reason to audit file sizes because “rawProgress” has nothing to do with bytesTotal – all child loaders are given equal weight in the calculation regardless of their file size. So a 20MB video would have the same relative weight in the calculation as a 15kb XML file.

10) Why are there 2 requests for each file?

One of the more common questions has to do with why 2 server requests are made for each file. This actually only happens on loaders that do not have an estimatedBytes value defined and auditSize wasn’t set to false on the parent LoaderMax. The “extra” request is simply the file size audit which greatly improves the accuracy of the LoaderMax’s “progress” value. Please read the more full explanation in tip 9.

11) Integrate the root swf into a LoaderMax’s progress

Let’s say you’ve got a large swf file that also loads a bunch of external assets and you’d like to report the overall loading progress of EVERYTHING (including the root swf). The SelfLoader class allows exactly that:

var queue:LoaderMax = new LoaderMax({onProgress:progressHandler, onComplete:completeHandler});
queue.append( new SelfLoader(this) ); //just to include the root swf in the progress calculations
queue.append( ...append your other loaders... );
queue.load();

12) parse() an entire array of URLs

Sometimes it’s convenient to be able to simply throw a bunch of URLs at LoaderMax and have it figure out what types of loaders are necessary and create them for you, wrapping them all in a parent LoaderMax queue. That’s what parse() is for:

var urls:Array = ["1.jpg","video.flv","child.swf","audio.mp3"];

//activate the types of loaders so that parse() can recognize the appropriate extensions (only necessary once)
LoaderMax.activate([ImageLoader, VideoLoader, SWFLoader, MP3Loader]);

var queue:LoaderMax = LoaderMax.parse(urls, {onComplete:completeHandler}, {autoPlay:false});
queue.prependURLs("http://www.greensock.com/assets/"); //saves us from having to include this in every URL in the array, and makes switching servers very easy.
queue.load();

Then you can use LoaderMax.getLoader() or LoaderMax.getContent() to get the loader or content associated with a particular URL. For example, in the completeHandler, we could get the video, add it to the stage, and start playing it like this:

function completeHandler(event:LoaderEvent):void {
    var video:VideoLoader = LoaderMax.getLoader("http://www.greensock.com/assets/video.flv");
	addChild( video.content );
	video.playVideo();
}

13) Get code hinting and strict data typing

If you don’t mind a little extra file size and slightly longer code, you can use the various data classes in the com.greensock.loading.data package to define the vars object that you pass into the constructor instead of a generic {} object. These data classes (like LoaderMaxVars, SWFLoaderVars, ImageLoaderVars, etc.) deliver some yummy code hinting so that you don’t have to refer to the docs so much to remember the various special properties that are available. And of course this technique also gives you strict data typing for improved debugging. For example:

//using a variable (long syntax)
var config:LoaderMaxVars = new LoaderMaxVars();
config.name("queue1");
config.onComplete(completeHandler);
config.onProgress(progressHandler);
config.maxConnections(1);
var queue:LoaderMax = new LoaderMax(config);

Or you can do things inline with chaining (very convenient)

//chaining (much shorter syntax)
var queue:LoaderMax = new LoaderMax(new LoaderMaxVars().name("queue1").onComplete(completeHandler).onProgress(progressHandler).maxConnections(1));

Got a tip or trick?

Post it in the comments section below. If you have a question, it’s typically best to post it in the forums at http://forums.greensock.com

  • Twitter
  • Facebook
  • Digg
  • StumbleUpon
  • del.icio.us
  • Yahoo! Buzz
  • Google Bookmarks
  • RSS

Comments (13) RSS

Posted by Patrick Mullady on October 12, 2010

I’M FIRST?! :)
THIS IS A JACKPOT! This is a fantastic set of tricks/tips. I’m especially fond of #8 and #9…Thanks again Jack!

Posted by David on October 13, 2010

Yeahh ! Thank you for these tips & Tricks ! Greensocks Rocks !

Posted by BramVD on October 14, 2010

Excellent idea, these tips! Great job, keep on increasing these tips and tricks because they are very helpful

Posted by Ogy on October 14, 2010

Great stuff Jack! Keep it up :)

Posted by kwaik on October 15, 2010

Great tips, THANKS~~~~!

Posted by DJ Girish on October 18, 2010

Thanks. I have always been interested in learning loaderMax. Thank you for posting the tips.

Posted by chris on October 24, 2010

Wow, awesome work man. These examples REALLY help. Love the preloader example. Keep it up and thanks again.

Posted by eco_bach on November 7, 2010

Jack, great work of course. Minor criticism as there is often confusion about bytes and bits.

var kbps:Number = (loader.bytesLoaded / loader.loadTime) / 1024;

techincially shouldn’t it be kBps, to indicate Bytes , not Bits?
So to determine kilobits take the above calculation and multiply by 8. Am I correct here?

Posted by Jack on November 8, 2010

eco_bach, sure, I suppose if you want kilobits instead of kilobytes that would be accurate but I assumed most people would be concerned about bytes since that’s what everything else is measured with in LoaderMax (bytesLoaded, bytesTotal, etc.)

It’s also a little confusing because of the whole camel case thing (you capitalized “B” to indicate bytes but it looks kinda weird with only that being capitalized).

Anyway, thanks for chiming in and clarifying.

Posted by DonMoir on March 17, 2011

Hi,

I think there is a general problem with flash loading a child SWF that tries to access external files. So flash thinks child is in same path as parent and a file reference not given as a full URL in the child will fail.

I tried your loader very simply and was wondering if you have found anyway around this ? So path for child SWF external files should be same path at which SWF was loaded from.

Thanks,

Don

Posted by Jack on March 17, 2011

Correct, DonMoir, Flash always treats relative URLs as relative to the root/parent swf (actually, for HTML pages, it’s relative to the HTML page itself). That’s just a Flash thing and has nothing to do with LoaderMax. Oh, and the one exception (which I’d consider an Adobe bug) is that NetStreams are relative to the child swf. Of course one solution is to simply use absolute URLs (like ones that start with http://).

Posted by DonMoir on March 17, 2011

Thanks for responding Jack. LoaderMax is a nice package and very easy to use but with Flash of course there are just some things that irritate the hell out of you.

The SWF files are being run on the local file system and can come from anywhere so its not possible for me to fix the URL by any normal means that I have found.

Another problem I am looking for a solution for is when a child SWF attempts to access the stage in its document class constructor. In this case stage will be null and then error.

Posted by Jack on March 17, 2011

DonMoir, these are questions that are better suited for the forums at http://forums.greensock.com. That topic has been covered a few times there actually. Just make sure you define a “container” for your SWFLoader (or manually addChild() its content before you load()) so that the stage isn’t null. Or put some conditional logic in your constructor to delay processing of your stage-related code until it is added to the stage (wait for the ADDED_TO_STAGE event to be dispatched). And for the record, this isn’t a LoaderMax-related thing – you’d run into the same issue with Adobe’s Loader. Oh, and make sure you’re using the latest version of LoaderMax.

To download the code, you must agree to the following license:

Copyright 2006-2012, GreenSock, Inc.

"NO CHARGE" NON-EXCLUSIVE SOFTWARE LICENSE AGREEMENT
-----------------------------------------------------------------------------
PLAIN ENGLISH SUMMARY:

  1. You may use the code at no charge in commercial or non-commercial web sites, games, components, applications, and other software as long as end users are not charged a fee of any kind to use your product or gain access to any part of it. If your client pays you a one-time fee to create the site/product, that's perfectly fine and qualifies under the "no charge" license. If end users are charged a usage/access/license fee, please sign up for a corporate Club GreenSock membership which comes with a special commercial license granting you permission to do so. See http://www.greensock.com/club/ for details.
  2. Use at your own risk. No warranties are offered.
  3. Please respect the copyright.

-----------------------------------------------------------------------------

LEGALESE:

This is a legal agreement between you (either an individual or a single entity) and GreenSock, Inc. ("GREENSOCK") for the proprietary GreenSock ActionScript code known as TweenLite, TweenMax, TweenNano, TimelineLite, TimelineMax, LoaderMax, and other code that is available for download at http://www.greensock.com (this code and documentation, as well as any updates which may at GREENSOCK's sole discretion be provided to you from time to time, are referred to in this Agreement as "PROGRAM") By downloading, copying, or otherwise using the PROGRAM, you agree to the terms and conditions of this Agreement. If you do not agree to the terms and conditions of this Agreement, please do not download or use the PROGRAM.

I. LICENSE
A. Subject to the terms and conditions of this Agreement, GREENSOCK hereby grants you a non-exclusive, worldwide, non-transferable right to use the PROGRAM in web sites, games, components and other software applications for which the end user is NOT charged any fees. If you would like to use the code in a commercially licensed software product for which end users are charged a fee (either for usage or access), simply sign up for a corporate Club GreenSock membership at http://www.greensock.com/club/.

II. LIMITATION OF LICENSE AND RESTRICTIONS
A. You agree that you will not disclose, sell, rent, or license the PROGRAM's source code or any derivative works thereof to any third party without the prior written consent of GREENSOCK. Derivative works are defined as modifications that add substantive functionality to the PROGRAM and do not include bug fixes or other minor modifications required to operate the PROGRAM as originally intended. Distribution of the source code as part of your Work Product is acceptable so long as the recipients agree to the terms of this Agreement. You agree not to modify or delete GREENSOCK'S existing copyright notice located in the source code.

B. You may use, duplicate, and distribute the compiled object code as embedded in a Work Product created by you, either for your own use or for distribution to a third party so long as end users of the Work Product are not charged a fee for usage of or access to any portion of the Work Product. Please see http://www.greensock.com/licensing/ for descriptions of Work Products that qualify for the "No Charge" license.

III. CONSIDERATION
A. The license rights granted to you under this Agreement are at no charge, but only in the following circumstances: If on your own behalf or on behalf of a third party you incorporate the PROGRAM into a web site, game, software application, program or any component thereof (collectively, "Work Product"), which in the case of a web site, must be accessible to internet users without payment of a fee of any kind, and in the case of a software application, game, program or component, neither you nor anyone to whom you distribute the Work Product charges a user a fee of any kind to use such Work Product or application, game, program or component into which such Work Product is embedded. The foregoing shall apply regardless of whether you are paid to create such Work Product.

B. In the event your intended use of the PROGRAM does not meet the criteria for the "no charge" license rights set forth in the immediately preceding paragraph, then you are not licensed to use the PROGRAM under this Agreement and must license the PROGRAM under GREENSOCK'S separate fee-based Software License Agreement which is granted to corporate Club GreenSock members (see http://www.greensock.com/club/ for details).

IV. TITLE AND OWNERSHIP
A. The PROGRAM is licensed, not sold, and is protected by copyright laws and international treaty provisions. You acknowledge that no title to the intellectual property in the PROGRAM is transferred to you. You further acknowledge that title and full ownership rights to the PROGRAM, including all intellectual property rights therein, will remain the exclusive property of GREENSOCK and you will not acquire any rights to the PROGRAM except as expressly set forth in this Agreement. You agree that any copies of the PROGRAM you make will contain the same proprietary notices which appear on and in the PROGRAM. You agree that GREENSOCK may identify you as a licensee unless you make a written request otherwise. GREENSOCK hereby grants to you the right to disclose that your product, game, software application, component, or other Work Product makes use of GREENSOCK code (for example, "Powered by TweenLite").

V. DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY
A. THE PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. GREENSOCK DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED IN THE PROGRAM WILL MEET YOUR REQUIREMENTS OR THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. GREENSOCK shall not be liable for special, indirect, incidental, or consequential damages with respect to any claim on account of or arising from this Agreement or use of the PROGRAM, even if GREENSOCK has been or is hereafter advised of the possibility of such damages. Because some states do not allow certain exclusions or limitations on implied warranties or of liability for consequential or incidental damages, the above exclusions may not apply to you. In no event, however, will GREENSOCK be liable to you, under any theory of recovery, in an amount in excess of $250. Notwithstanding anything else in this agreement, you agree to indemnify GREENSOCK, its assignees, and licensees, and hold each of them harmless from and against any and all claims, demands, losses, damages, liabilities, costs, and expenses, including legal fees arising out of or resulting from any negligent act or omission by you.

B. GREENSOCK may, at its sole discretion, provide support services related to the PROGRAM, but has no obligation to do so.

VI. TERMINATION
If you at any time fail to abide by the terms of this Agreement, GREENSOCK shall have the right to immediately terminate the license granted herein, require the return or destruction of all copies of the PROGRAM from you and certification in writing as to such return or destruction, and pursue any other legal or equitable remedies available.

VII. MISCELLANEOUS
A. This Agreement shall be construed in accordance with the laws of the State of Illinois. In the event of any dispute between you and GREENSOCK with respect to this Agreement, we both agree that if we cannot resolve the dispute in good faith discussion, either of us may submit the dispute for resolution to arbitration with the American Arbitration Association before a single arbitrator using the AAA Rules for Commercial Arbitration. The arbitrator's decision is final and can be enforced in any court with jurisdiction over such matters.

B. This agreement represents the complete and exclusive statement of the agreement between GREENSOCK and you and supersedes all prior agreements, proposals, representations and other communications, verbal or written, between them with respect to use of the program. This agreement may be modified only with the mutual written approval of authorized representatives of the parties.

C. The terms and conditions of this Agreement shall prevail notwithstanding any different, conflicting, or additional terms or conditions which may appear in any purchase order or other document submitted by you. You agree that such additional or inconsistent terms are deemed rejected by GREENSOCK.

D. GREENSOCK and you agree that any xerographically or electronically reproduced copy of this Agreement shall have the same legal force and effect as any copy bearing original signatures of the parties.

I'd like to learn how to get bonus plugins, update notifications, SVN access, and more.
To continue, you must agree to the following license: