Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Guest rdas

prependURL basepath gotcha

Recommended Posts

This morning I came across an issue regarding the use of prependURLs() that I thought I'd share. (I'm not sure if this qualifies as a problem, such that the functionality should be changed, or whether it's simply a question of convention.)

 

The Problem:

The topmost LoaderMax instance does not apply prependURLs to auto-generated child Loaders. This is unintuitive, as prependURLs specifically takes a 'includeNested' parameter, which suggests that all nested loaders should have this applied.

 

In the following example, the XMLLoader that loads "config.xml" will have it's url correctly prepended ("http://foo/config.xml") however, any child loaders that are generated by XMLLoader (ie. content specified within config.xml) will not have the basepath applied, even though the topmost Loader instance has prependURLs applied:

 

var basepath:String = "http://foo/";
var myLoader = new LoaderMax({name:"mainQueue" });
myLoader.append( new XMLLoader("config.xml", {name:"configXML" }));
myLoader.prependURLs( basepath, true );
myLoader.load();

 

The Solution:

When using prependURLs() with LoaderMax, it must be applied on onComplete, otherwise auto-generated child loaders will not have their URLs prepended.

 

var basepath:String = "http://foo/";
...
var myLoader = new LoaderMax({ name:"mainQueue", onComplete:completeHandler });
myLoader.append( new XMLLoader("config.xml", {name:"configXML" }));
myLoader.prependURLs( basepath, true );
myLoader.load();

...

private function completeHandler( event:LoaderEvent ):void {
myLoader.prependURLs( basepath, true );
}

 

Suggested Behavior:

A load queue whose prependURLs method has been called should apply the new string whenever any loaders are added to it. If loaders are only handled locally, each loader object should check to see if it has a parent loader, and if so, whether prependURLs has been called on it, recursively up the tree.

Link to comment
Share on other sites

I actually thought a lot about this scenario when I originally created prependURLs() and I decided that the current behavior would be better because:

 

1) It provides a better level of control - What if I want to create a queue of ImageLoaders that have a baseURL but then later on I want to be able to add other loaders to the queue? If prependURLs() was ever used on the parent LoaderMax and I implemented the feature as you're recommending, it would mess up the URLs in those other loaders. I could never add children unless they use the same prepended URL. That limits flexibility a lot.

 

2) It is more consistent with the method name - I chose "prependURLs()" method instead of implementing a "baseURL" property or something like that because I wanted to convey that the method performs an action once on the existing children of the LoaderMax instance. It's not meant to be a value that perpetually gets added to all future loaders that are added to the LoaderMax instance. Methods typically perform an action and then finish.

 

Of course it wouldn't be terribly difficult to add logic to XMLLoader so that it remembers if prependURLs() was ever called on its parent and if so, it waits until all the XML is loaded and parsed and then prepends the URL to all child loaders, but that still feels like it would be inconsistent because it's performing actions on loaders that don't exist yet (not what you'd expect a method to do). Plus it seems far more common to just define your prependURLs inside your XML if you want that behavior.

 

If folks want to chime in on this, I'm all ears. I'm pretty firm on the current behavior but I'd consider adding the queued functionality to XMLLoader if there's enough demand. The other inconsistency that'd bring up, though, is "why would that work in XMLLoader and not in SWFLoader which can also have nested loaders?" It obviously wouldn't make much sense to have that behavior in SWFLoader (in fact, I think it could cause problems for some developers) but it'd be an inconsistency nonetheless. The current implementation seems clean and consistent. And like you said, there's already a solution for the problem you faced (prepending the URLs in an onComplete or onInit).

Link to comment
Share on other sites

I agree with you completely. I posted my message as I spent a little time discovering the solution (prepending on complete) so I thought it might save someone some time in future with the same issue :)

Link to comment
Share on other sites

  • 1 month later...

I'm having a bit of trouble with this.

I have a config xml that contains XMLLoader nodes with their load attribute set to true.

Inside the children I have a few ImageLoader nodes that are also set load.

 

Is there any way to add a basepath that will run throughout the entire structure?

My employers have a system in place that needs to publish one file that will work both internally and for the client. To do that they generally have a var at that checks certain parameters and modifies the basepath. I'm trying to phase out their loader (which is quite convoluted and often fails) with LoaderMax. So far it's been going pretty well, except for this one feature.

 

I tried prepending the basepath in the onComplete as the previous poster had suggested but since this is an action that needs to happen before it completes it does not work.

 

Any suggestions?

Link to comment
Share on other sites

Could you provide at least some code snippets so I can better understand the structure and your goal? Are you saying you have many XML files and you want to set a base path in one that would get applied to all the others? Did you know you can wrap your loader nodes in a node that has a prependURLs="" attribute and it'll get applied to all the sub-nodes?

 

Once you post sample code (or better yet, an FLA and supporting XML docs), I'll be able to give you a better answer. I can't think of much that you can't do with LoaderMax, so I'm confident there's a solution.

Link to comment
Share on other sites

Here's the loading code I'm using:

var loader:LoaderMaX = new LoaderMax({name:"mainLoader", onComplete:onLoadComplete, onProgress:onLoadProgress});
loader.append( new SelfLoader(this));
loader.append( new XMLLoader(mainXMLPath, {name:"xml/application.xml"}));
loader.append( new XMLLoader(gamesXMLPath, {name:"xml/games.xml"}));

if ( useAlternatePath )
{
loader.prependURLs("../", true);
}

loader.load();

 

The following is the sample content of my the games.xml file:

<?xml version="1.0"?>




 

This then loads a separate XML file for each page... which is generally in the format:

<?xml version="1.0"?>

Title goes here
20

…

 

As you can probably see I'm trying to load all of the content (down to the images in the game1.xml & game2.xml files). Since the location is changed based on logic within the code I'd want to modify all of the base paths, but not hard code the append into the XML.

If you still need a sample FLA I can whip one up for you.

Link to comment
Share on other sites

My current solution is to add an onRawLoad callback that does the following:

 

public function onRawLoadComplete(e:LoaderEvent):void
{
if ( useAlternatePath )
{	
	var loaders:XMLList = XML(e.target.content)..*.(localName() == "ImageLoader" || localName() == "XMLLoader");
	for each(var loader:XML in loaders)
		loader.@url = "../" + loader.@url;
}
}

 

It seems to be holding up for now though if there's a more straightforward way of performing this function I'd love to know about it. :)

Link to comment
Share on other sites

Ah, okay, I see. Good news: I just uploaded an updated version of XMLLoader that recognizes 2 new special properties: prependURLs and recursivePrependURLs. They're identical except that the recursivePrependURLs will affect all XML documents that are loaded by the XMLLoader's doc as deeply as they go. In other words, if the XMLLoader loads doc1.xml which has an node that loads doc2.xml which also has an node that loads doc3.xml, ALL of the URLs in ALL of the docs will be prepended.

 

I've updated the ASDocs, so check those for a more detailed description. It should make things a lot easier for you. Please let me know if it serves you well.

 

Get the updated class(es) at

Link to comment
Share on other sites

Wow, thanks for the quick update!

 

Unfortunately, for my particular situation I'm still stuck using the onRawLoad event. Since this only works on XMLLoaders my lower level ImageLoaders are left with incorrect urls.

Link to comment
Share on other sites

Wow, thanks for the quick update!

 

Unfortunately, for my particular situation I'm still stuck using the onRawLoad event. Since this only works on XMLLoaders my lower level ImageLoaders are left with incorrect urls.

I'm confused - why would they be left with incorrect urls? Are you using recursivePrependURLs? That should apply the change to ALL urls, even the ones nested in xml docs loaded by the xml doc as deeply as they go.

Link to comment
Share on other sites

Is that supposed to prepend the URL of even the ImageLoader classes within the XML?

Currently it doesn't seem to be doing that. I'll give it another go and double check the errors I was getting, but I believe it wasn't touching the URLs of the deepest nested ImageLoader nodes. Honestly I may be doing something wrong here.

Link to comment
Share on other sites

Yeah, it should affect ALL LoaderMax-related loaders, but don't forget to activate() the loader types that you want XMLLoader to recognize. For example:

 

LoaderMax.activate([imageLoader, SWFLoader]);

 

You did remove your RAW_LOAD code before you did the recursivePrependURLs test, right? If not, you'd be duplicating the prepend stuff.

 

According to my tests, it did indeed correctly affect all loaders in deeply-nested XML documents that were sub- sub- sub-loads. If you're having trouble, please post a sample FLA (with support files) that I can publish and see on my end. I'm sure we can get it worked out.

Link to comment
Share on other sites

Ahh I see where the error is.

 

I'm using the URL to access the content of the image loader (since each document has a thumbnail with the name of "thumb"). While the image has been loaded it's url hasn't been modified. I just need to track whether I've modified my paths and manually add in the prepending string when I'm accessing the content.

 

So, for example the following:

var imagePath:String = pageXML.ImageLoader.(@name=="thumb").@url;
var image:Bitmap = LoaderMax.getLoader( imagePath ).rawContent;

 

will now become:

var basePath:String = (useAlternatePath)?"../":"";
var imagePath:String = pageXML.ImageLoader.(@name=="thumb").@url;
var image:Bitmap = LoaderMax.getLoader( basePath + imagePath).rawContent;

Link to comment
Share on other sites

  • 4 weeks later...

i can't get

mainQue = new LoaderMax({name:"mainItemsQue",recursivePrependURLs:debugging, onComplete:mQcompleteHandler, onError:mQerrorHandler, onChildProgress:progressHandler});

to work

 

i want to us the string debugging, which holds "../" to test on my local machine, and make the string empty when i publish

Link to comment
Share on other sites

problem solved

 

mainQue = new LoaderMax({name:"mainItemsQue",onComplete:mQcompleteHandler, onError:mQerrorHandler, onChildProgress:progressHandler});
mainQue.append(new XMLLoader(debugging + "xml/main.xml", {name:"mainXML",recursivePrependURLs:debugging}) );

 

had the recursivePrependURLs in the LoaderMax definition in the first place.

Link to comment
Share on other sites

  • 2 years later...

Hi,

 

I can't get recursivePrependURLs to work for me. I have additional XMLLoaders in an xml file I'm loading. The main xml file is getting loaded but none of its children are, their URLs are not being updated.

 

var relativePath:String = "/";

 

LoaderMax.activate([xmlLoader]);

var queue:LoaderMax = new LoaderMax({name:"mainQueue", onComplete:loadFilesComplete});

var xmlLoader:XMLLoader = new XMLLoader("assets/xml/config.xml", new XMLLoaderVars().name("configXML").recursivePrependURLs(relativePath));

queue.append( xmlLoader );

queue.prependURLs(relativePath);

queue.load();

 

and here is my xml:

<config>
<settings stageWidth="800" stageHeight="600" />
<XMLLoader name="tips and hints XML" url="assets/xml/tips_and_hints.xml" load="true" estimatedBytes="10" />
<XMLLoader name="items" url="assets/xml/items.xml" load="true" estimatedBytes="10" />
<XMLLoader name="careers" url="assets/xml/careers.xml" load="true" estimatedBytes="10" />
<XMLLoader name="origin comic" url="assets/xml/origin-comic.xml" load="true" estimatedBytes="10" />
</config>
 
Am I doing something wrong?
 
Cheers
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×