0 Content
1 Introduction
2 Examples
2.1 Basic examples, single file
2.2 Basic examples, multiple files
2.3 Displaying the loading progress
2.4 Using targetspecific listeners
2.5 Errorhandling
2.6 Queuemanagement
2.7 Miscellanous
3 API
3.1 Constructor
3.2 Static constants
3.3 Loading and observing targets
3.4 Managing the queue
3.5 Managing listeners
3.6 Events
3.7 Configuration
3.8 Getters, getting information about the loading process
4 FAQ
5 Donations
6 Bugs
7 Support
8 History
9 Status and copyright
10 License For Use
1 Introduction
As Colin Moock, the author of Actionscript - The Definitive Guide stated lately: Preloading still is a major problem for a lot of flashers. The different interfaces to the different filetypes (SWF, XML, Text, Sound), the asynchronous behaviour of the loading process and the uncomplete errorhandling alltogether make preloading really hard to handle. This is why Colin started a petition and proposed a new interface for preloading.
The LoaderClass is based on Colin's interface proposal. Some changes and additions had to be made, because of practical implications.
If you find the class useful and want to support further development, don't forget to donate.
2 Examples
2.1 Basic examples, single file
back
2.1.1 Loading a swf into a MovieClip given by its targetpath
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
myLoader.load("target_mc", "myMovie.swf");
back
2.1.2 Loading a swf into a MovieClip given by reference
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
myLoader.load( _root.mc.holder, "myMovie.swf");
back
2.1.3 Loading a swf into a level
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
myLoader.load( 3, "myMovie.swf");
back
2.1.4 Loading a swf into a created MovieClip
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
var mc = createEmptyMovieClip("myClip_mc", 1);
myLoader.load( mc, "myMovie.swf");
back
2.1.5 Loading a xml file
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
x = new XML();
myLoader.load( x, "myXML.xml");
back
2.1.6 Loading a textfile
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
lv = new LoadVars();
myLoader.load( lv, "myText.txt");
back
2.1.7 Loading a sound
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
snd = new Sound();
myLoader.load( snd, "mySound.mp3");
back
2.1.8 Loading a streaming sound
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
snd = new Sound();
// the additional parameter (1)
// is passed to Sound.load
myLoader.load( snd, "mySound.mp3", null, 1);
back
2.2 Basic examples, multiple files
When loading multiple files, the LoaderClass puts all of the requests into an internal queue and executes one by one.
back
2.2.1 Loading multiple swfs into created MovieClips
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
for( var i=0; i<10; i++){
var mc = createEmptyMovieClip("mc" + i, i);
var url = "movie" + i + ".swf";
myLoader.load( mc, url);
}
back
2.2.2 Loading multiple files of mixed type
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
myLoader.load("target_mc", "myMovie.swf");
myLoader.load( _root.mc.holder, "myMovie.swf");
myLoader.load( 3, "myMovie.swf");
x = new XML();
myLoader.load( x, "myXML.xml");
lv = new LoadVars();
myLoader.load( lv, "myText.txt");
snd = new Sound();
myLoader.load( snd, "mySound.mp3");
back
2.3 Displaying the loading progress
To display the progress you can add a listener object to the loader. The listener object provides methods to handle the events raised by the loader.
back
2.3.1 Using a simple bar
We use a simple bar, which is scaled horizontally, to show the loading progress. Since the scale of a MovieClip is a percentage value, we can directly assign the percentage of the loaded bytes.
Create a bar, place it on stage, name it bar_mc and set it to _xscale = 100.
#include "com.qlod.LoaderClass.as"
bar_mc.onLoadProgress = function( loaderObj){
this._xscale = loaderObj.getPercent();
}
myLoader = new com.qlod.LoaderClass();
myLoader.addListener( bar_mc);
myLoader.load("target_mc", "myMovie.swf");
back
2.3.2 Using a dynamic TextField
We use a dynamic TextField to display the percentage, the bytesLoaded and the total number of bytes.
Create a dynamic TextField and set its instancename to progress_txt.
#include "com.qlod.LoaderClass.as"
progress_txt.onLoadProgress = function( loaderObj){
this.text = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}
myLoader = new com.qlod.LoaderClass();
myLoader.addListener( progress_txt);
myLoader.load("target_mc", "myMovie.swf");
back
2.3.3 Using multiple listeners, eg. a bar and a dynamic TextField
We can use as much listener objects as we like. The following example sports both of the above listeners at once.
#include "com.qlod.LoaderClass.as"
progress_txt.onLoadProgress = function( loaderObj){
this.progress_txt = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}
bar_mc.onLoadProgress = function( loaderObj){
this._xscale = loaderObj.getPercent();
}
myLoader = new com.qlod.LoaderClass();
myLoader.addListener( bar_mc);
myLoader.addListener( progress_txt);
myLoader.load("target_mc", "myMovie.swf");
back
2.4 Using targetspecific listeners
Sometimes you need a listener which listens to one specific loading process and not to all of them. This can be achieved by using the listener object as an additional parameter to load. The listener is automatically added when loading of the target starts and removed, after loading of the target is completed. The following example uses a plain object to handle the events.
back
2.4.1 Simple targetspecific listeners
#include "com.qlod.LoaderClass.as"
myListener_obj = new Object();
myListener_obj.onLoadStart = function( loaderObj){
trace("Loading of " + loaderObj.getTarget() + " has started");
}
myListener_obj.onLoadProgress = function( loaderObj){
trace("Percentage: " + loaderObj.getPercent());
}
myListener_obj.onLoadComplete = function( success, loaderObj){
trace("Loading of " + loaderObj.getTarget() + " is completed");
_root.gotoAndPlay("introduction");
}
myLoader = new com.qlod.LoaderClass();
myLoader.load("target_mc", "myMovie.swf", myListener_obj);
back
2.4.2 Advanced targetspecific listeners
The following example creates a page of thumbnails where every thumbnail shows its own loading bar.
#include "com.qlod.LoaderClass.as"
myLoader = new com.qlod.LoaderClass();
var depth = 0;
var rows = 4;
var cols = 5;
for( var i=0; i<rows; i++){
for( var j=0; j<cols; j++){
++depth;
//
var thumbnail_mc = createEmptyMovieClip("thumbnail_mc" + depth, depth);
//
var bar_mc = thumbnail_mc.createEmptyMovieClip("bar_mc", 0);
bar_mc.onLoadProgress = function( loaderObj){
this.clear();
this.lineStyle(0, 0xff0000);
this.lineTo( loaderObj.getPercent(), 0);
}
bar_mc.onLoadComplete = function( success, loaderObj){
this.removeMovieClip();
}
//
var img_mc = thumbnail_mc.createEmptyMovieClip("img_mc", 1);
//
myLoader.load( img_mc, "img" + depth + ".jpg", bar_mc);
}
}
back
2.5 Errorhandling
Some times a file cannot be loaded because the server is down, the url is incorrect or the file simply doesn't exist. The LoaderClass raises a onTimeout-event if this happens. Handling of this event works the same way as handling the other events. Here is a simple example:
#include "com.qlod.LoaderClass.as"
myErrorHandler_obj = new Object();
myErrorHandler_obj.onTimeout = function( loaderObj){
trace("Timeout-Error: The file " + loaderObj.getUrl() + " could not be loaded.");
}
myLoader = new com.qlod.LoaderClass();
myLoader.addListener( myErrorHandler_obj);
myLoader.load("target_mc", "notExistent.swf");
back
The default timeout interval is 10 (ten) seconds. You can change it through a call to myLoader.setTimeoutMs( newLengthMs).
2.6 Queuemanagement
Think about a system consisting of a menue, which loads different swfs into a content area. If the user chooses an entry, the menue sends a request to our loader and the loader loads the swf into the content MovieClip. If the swfs are big enough, there is a chance, that the user suddenly wants to visit another area than the currently loading one. To handle this, we need a notion of "breaking" the current loading process. The LoaderClass provides three methods for this:
- clear() – removes all entries from the queue
- removeCurrent() - removes just the currently loading entry
- remove( id) – removes the entry idenitfied by id. The id has been returned by the former call to load.
Create a mc named content_mc and two other mcs, named button1_mc and button2_mc.
#include "com.qlod.LoaderClass.as"
myLoader = new LoaderClass();
function loadContent( url){
myLoader.clear();
myLoader.load( content_mc, url);
}
button1_mc.onRelease = function(){
loadContent("movie1.swf");
}
button2_mc.onRelease = function(){
loadContent("movie2.swf");
}
back
2.7 Miscellanous
back
2.7.1 Delaying the progress events
Sometimes loading happens so fast, that you can't see and control your loading animation. The following example shows you how to set the minimum number of steps your preloader shows.
Create a dynamic TextField and set its instancename to progress_txt.
#include "com.qlod.LoaderClass.as"
progress_txt.onLoadProgress = function( loaderObj){
this.progress_txt = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}
myLoader = new com.qlod.LoaderClass();
// show 5 steps at least
myLoader.setMinSteps( 5);
myLoader.addListener( progress_txt);
myLoader.load("target_mc", "myMovie.swf");
If you delay the progress events, special care is needed, because your loaded movie starts playing automatically. A common approach is to add an empty frame to the loaded movie with just a stop action in it. Then you are able / have to start the movie explicitely in your onLoadComplete-handler (or later). If you don't want to change the movie, you can also set its alpha to zero onLoadStart and to 100 onLoadComplete. If your movie has more than one frame, you also have to take care of the correct frame.
back
2.7.2 Observing the main timeline
If you wish to watch the main timeline loading, you can use observe instead of load.
Create a dynamic TextField and set its instancename to progress_txt.
#include "com.qlod.LoaderClass.as"
progress_txt.onLoadProgress = function( loaderObj){
this.progress_txt = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}
myLoader = new com.qlod.LoaderClass();
// show 5 steps at least
myLoader.setMinSteps( 5);
myLoader.addListener( progress_txt);
myLoader.observe(this);
back
3 API
3.1 Constructor
Creates an instance of the loader class.
- MyLoader = new com.qlod.LoaderClass( [piTimeOutMs [, piIntervalMs [, piMinSteps]]]);
-
- param piTimeoutMs
- integer, optional, specifies the milliseconds until a timeoutError is raised, default 10000
- param piIntervalMs
- integer, optional, specifies the length of the interval which checks the loadingprogress, default 100
- param piMinSteps
- integer, optional, specifies the number of minimum steps, the loadingprocess is divided into, default 1
back
3.2 Static constants
- com.qlod.LoaderClass .DEFAULT_TIMEOUT_MS
- If setTimeoutMs() is called without a valid parameter, this value is taken instead
- com.qlod.LoaderClass .DEFAULT_INTERVAL_MS
- If setIntervalMs() is called without a valid parameter, this value is taken instead
- com.qlod.LoaderClass .DEFAULT_MIN_STEPS
- If setMinSteps() is called without a valid parameter, this value is taken instead
back
3.3 Loading and observing targets
3.3.1 Loading
- id = myLoader.load( pLoc, psUrl [, poListener [, pAdditionalParameter ]]])
- Start loading the swf at url into the given location loc.
- param pLoc
- integer || string || object, specifies the level, path or object to load into
- param psUrl
- string, specifies the url to load from
- param poListener
- object, specifies a listener solely for this item. This listener is added automatically if the loading of the item starts and removed automatically, if the loading is completed.
- param pAdditionalParameter
- this and any more parameters are transparently passed to the load method of the item, e.g. you can use it to pass a stream parameter to a call of sound.load
- return integer
- returns an unique id
back
3.3.2 Observing
- Id = myLoader.observe( pLoc [, psUrl [, poListener]] )
- Start observing the given location loc. This works the same as load, but the thing to observe
is already loading. You can use it to preload the main timeline for example.
- param pLoc
- integer || string || object, specifies the level, path or object to load into
- param psUrl
- string, optional, specifies the url which is loaded from. If the url is not a string, the property pLoc._url is taken instead.
- param poListener
- object, specifies a listener solely for this item. This listener is added automatically if the loading of the item starts and removed automatically, if the loading is completed.
- return integer
- returns an unique id
back
3.4 Managing the queue
3.4.1 Clearing the queue completely
- myLoader.clear()
- Clear the queue and stop the current loading process
back
3.4.2 Remove a specific item
- myLoader.remove( pId)
- Remove the item with the given id ( which was previously returned by load or observe)
- param pId
- integer, specifies the item to remove from the loading queue
back
3.4.3 Remove the current item
- myLoader.removeCurrent()
- Stop the currently loading item and head on to the next in the queue (if any)
back
3.5 Managing listeners
3.5.1 Adding listeners
- myLoader.addListener( pObj)
- Add a listener object to our listeners list.
- param pObj
- object, the listener object handles the events raised by the loader
back
3.5.2 Removing listeners
- myLoader.removeListener( pObj)
- Remove a listener object from our listeners list.
- param pObj
- object, the listener object to remove
back
3.6 Events
The following events are raised by the LoaderClass.
3.6.1 onQueueStart
- yourListener.onQueueStart( pLoaderObj)
- This event is fired when loading of the items in the queue starts.
- param pLoaderObj
- LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.
back
3.6.2 onQueueStop
- yourListener.onQueueStop( pLoaderObj)
- This event is fired when the queue exhausts.
- param pLoaderObj
- LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.
back
3.6.3 onLoadStart
- yourListener.onLoadStart( pLoaderObj)
- This event is fired when loading starts.
- param pLoaderObj
- LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.
back
3.6.4 onLoadComplete
- yourListener.onLoadComplete( pSuccess, pLoaderObj)
- This event is fired when loading is completed.
- param pSuccess
- Boolean, true if loading succeded, false otherwise
- param pLoaderObj
- LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.
back
3.6.5 onLoadProgress
- yourListener.onLoadProgress( pLoaderObj)
- This event is fired on every interval while the item is loading
- param pLoaderObj
- LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.
back
3.6.6 onLoadTimeout
- yourListener.onLoadTimeout( pLoaderObj)
- This event is fired, when the webserver doesn't start sending within the timeout interval.
- param pLoaderObj
- LoaderClass, the current LoaderClass instance. You can retrieve all the infos you need using the appropriate getter.
3.7 Configuration
3.7.1 setTimeoutMs
- myLoader.setTimeoutMs( [piMilliseconds])
- Sets the actual length of the timeout. If the timeoutMs is not a number, the defaultvalue is set.
- param piMilliseconds
- integer, optional, specifies the new length of the timeout in milliseconds
- return integer
- returns the current value
back
3.7.2 getTimeoutMs
- myLoader.getTimeoutMs()
- Returns the actual length of the timeout interval
- return integer
- returns the current value in milliseconds
back
3.7.3 disableTimeout
- myLoader.disableTimeout()
- Completely disable timeout handling
back
3.7.4 enableTimeout
- myLoader.enableTimeout()
- Enable timeouthandling. Timeouthandling is enabled by default.
back
3.7.5 setIntervalMs
- myLoader.setIntervalMs( [piMilliseconds])
- Sets the actual length of the checkinterval. If the intervalMs is not a number, the default value is set
- param piMilliseconds
- integer, optional, specifies the new length of the interval in milliseconds
- return integer
- returns the current value
back
3.7.6 getIntervalMs
- myLoader.getIntervalMs()
- Returns the actual length of the checkinterval.
- return integer
back
3.7.7 setMinSteps
- myLoader.setMinSteps( [piMinSteps])
- Sets the minimum number of steps. Every preloading process takes at least this much steps. If the piMinSteps is not a number, the default value is set.
- param piMinSteps
- integer, optional, specifies the new iMinSteps
- return integer
- returns the current value
back
3.7.8 getMinSteps
- myLoader.getMinSteps()
- Returns the actual value of minSteps
- return integer
3.8 Getters, getting information about the loading process
Inside your eventhandlers you can use the following methods to retrieve the information you need. Here is a small example which uses getPercent, getBytesLoaded and getBytesTotal to display some information in a dynamix TextField.
#include "com.qlod.LoaderClass.as"
progress_txt.onLoadProgress = function( loaderObj){
this.progress_txt = loaderObj.getPercent() + " - " + loaderObj.getBytesLoaded() + " - " + loaderObj.getBytesTotal();
}
myLoader = new com.qlod.LoaderClass();
myLoader.addListener( progress_txt);
myLoader.observe(this);
back
3.8.1 isLoading
- loaderObj.isLoading()
- returns true if the loader is loading
- return boolean
back
3.8.2 getBytesLoaded
- loaderObj.getBytesLoaded()
- returns the current bytes loaded or 0
- return integer >= 0
back
3.8.3 getBytesTotal
- loaderObj.getBytesTotal()
- returns the current bytes total or 1
- return integer >= 1
back
3.8.4 getKBLoaded
- loaderObj.getKBLoaded()
- returns the current bytes loaded or 0 in KB
- return integer >= 0
back
3.8.5 getKBTotal
- loaderObj.getKBTotal()
- returns the current bytes total or 1 in KB
- return integer >= 1
back
3.8.6 getPercent
- loaderObj.getPercent()
- returns the relation of loaded and total bytes in percent
- return integer >= 0
back
3.8.7 getDuration
- loaderObj.getDuration()
- returns the current duration of the loading process in milliseconds
- return integer >= 0
back
3.8.8 getSpeed
- loaderObj.getSpeed()
- returns the current downloadrate in bytes/second
- return integer >= 0
back
3.8.9 getEstimatedTotalTime
- loaderObj.getEstimatedTotalTime()
- returns the estimated total download time for the current item in seconds
- return integer >= 0
back
3.8.10 getTarget
- loaderObj.getTarget()
- returns the current target. If the target is a MovieClip, the targetpath is returned, otherwise the object is returned
- return string | object
back
3.8.11 getTargetObj
- loaderObj.getTargetObj()
- returns the current target as object
- return object
back
3.8.12 getUrl
- loaderObj.getUrl()
- returns the url of the current loading process
- return string
back
4 FAQ
What are the frequently asked questions ?
back
5 Donations
There have been 23 donations between 5 and 15 $ yet. Are you no. 24 ? Donate to paypal@helpqlodhelp.com.
You can also use the direct link to paypal
back
6 Bugs
Please send bugs / possible improvements with detailed descriptions to components@helpqlodhelp.com
back
7 Support
We provide professional scripting support and freelancing programming services at reasonable rates. Contact us for the details at components@helpqlodhelp.com
back
8 History
- 04/24/2003 v0.1
- published
- 04/24/2003 v0.2
- Ms-bug removed
- did some refactoring into smaller functions
- added getPercentLoaded and getBytesPerSecond
- 04/24/2003 v0.3
- added parameters to constructor
- added NO_INIT ( inheritance guard) to constructor
- added getters/setters for timeOutMs
- added getters/setters for intervalMs
- moved default-settings into the setters
- 04/24/2003 v0.4
- added defaultProperties to the prototype
- 04/25/2003 v0.5
- added some documentation in javadoc style
- 04/26/2003 v0.6
- refactored locToTarget into smaller functions
- added errorhandling for invalid location parameter
- added watch to allow for watching already loading timelines
- added example for using watch
- 04/26/2003 v0.7
- removed bug with sequential loading
- added support for waitUntil-function
- 04/26/2003 v0.8
- added onLoadTimeout event and example code
- removed kb and bps parameters from onLoadProgress,
- added milliseconds parameter to onLoadProgress
- 04/29/2003 v0.9
- changed some things to make the class more universal
- now movieclips, xml, loadvars and sound can be loaded with the same interface
- changed classname MovieClipLoader to Loader
- changed methodname loadClip to load
- changed methodname watchClip to watch
- added locIsLoadable-method
- changed locToTarget to allow for target objects
- 05/01/2003 v0.9a
- added transparent queueing
- added events onQueueStart
- added events onQueueStop
- added method isLoading
- 05/04/2003 v0.9b
- changed default value for bytesTotal to 1, to make calculating percentage easier
- 05/04/2003 v0.9c
- moved the waitUntil-function into the class and removed it from the interface
- 05/05/2003 v0.9d
- renamed internal method checkProgress to sendProgress
- added call to broadcastProgress at the beginning of the loading process ( to reset displays)
- added property minSteps, with default, getters and setters
- removed getPercentLoaded and getBytesPerSecond
- changed defaultIntervalMs to 100 to make animations smoother
- changed defaultTimeoutMs to 10000, to make errorhandling faster
- renamed watch to observe
- 05/05/2003 v0.9e
- added praefixes to variables
- renamed Loader to LoaderClass
- renamed sendProgress to broadcastProgress
- added checkIntGreaterZero
- 05/07/2003 v0.9f
- corrected minStep-bug
- 05/07/2003 v0.9g
- corrected currentStep-bug
- 05/09/2003 v0.9h
- corrected initialisation of funcWaitUntil
- changed timeout to work with an interval, which is probably less time consuming
- observe now retrieves the url from the object, if no url is given
- 05/09/2003 v0.9i
- corrected some minor FlashDoc inconsistencies
- 05/16/2003 v0.9jbeta
-
- added switch and constants to allow for changing the parameterstyle of the callbacks
- added getters for bytesLoaded, bytesTotal, kbLoaded, kbTotal, percent
- added getters for time, speed, estimatedTotalTime, target, url, targetObj
- added switch to enable/disable Timeout
- 05/17/2003 v0.9jbeta1
-
- changed default properties to static constants
- added check for object to observe
- moved the api to the beginning of the file
- 05/18/2003 v0.9jbeta2
-
- delete o
- removed bug in locIsPath, now movieClips are rejected
- added locIsMovieClip, now movieClips are recognized
- 05/18/2003 v0.9k
- moved beta to alpha because of latest corrections
- 05/18/2003 v0.9l
- bug in getStepPercent removed
- 05/30/2003 v0.9mb
- added support for additional parameters to load
- 05/31/2003 v0.9mb1
- added getStepKBLoaded
- 06/01/2003 v0.9mb2
- added clear, remove, removeCurrent
- 06/01/2003 v0.9mb3
- added namespace
- moved class to com.qlod Domain
- removed the ..Step.. methods
- removed the paramStyle switch
- corrected the docs of onLoadComplete
- corrected the example code
- 06/03/2003 v0.9mb4
- changed getTime to getDuration
- 06/05/2003 v0.9mb5
- added support for specific listeners
- 06/13/2003 v1.0
- Added this documentation
- removed api and history from as-file
- 06/16/2003 v1.01
- removed additional parameter bug
- removed namespace bug
- added doc for additional parameters (see load)
- 08/07/2003 v1.02
- removed a bug with targetspecific listeners
- added LoaderItemClass
- added support for "late" targets, allow to use a string point to a target, which doesn't exist yet
8 Status
Written and copyright held by Ralf Bokelberg and Colin Moock.
Last change: June, Friday 13th, 2003
9 License For Use
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
back