As you know, I'm a designer not a programmer. I write solid AS code, but in the quest to move to more "programmery oop" I built three classes for this example.
My question is what did I do wrong and how can I fix it?
Class Stats loads XML for use in a Stats MC. Class RSS loads XML for use in an RSS MC. Class LoadXML loads the actual XML for both classes above and gets the filename from Stats or RSS. LoadXML has reporting functions built into it.
If I do the parsing and splitting of the XML Object in Stats and RSS to send the info to the appropriate text fields in the constructor function, they are of course not available yet because LoadXML isn't finishing the onLoad function. I tried having Stats and RSS extend LoadXML, but that was worse.
How do I get Stats and RSS to WAIT for LoadXML to run it's course before Stats and RSS try to separate the pieces they need?
If I don't get this right, I'm going back to having Stats and RSS load the XML themselves, but I'm trying to be better and this one has caught me. I want to use LoadXML because it does the full error check and messaging and I don't want to have that twice.
No idea about good and bad OOP but heres some possible approaches..
You can have a loadXML class with a custom event which contains the loaded xml and Stats and RSS can listen to and use the info
_stats = new Stats(txtfields1); _Rss = new RSS(txtfields2); _loadXML = new loadXML( url ); addEventListener( LoadXMLEvent.LOADED, parse ) _loadXML.start();
private function parse( e: LoadXMLEvent ) {
_Rss.parse( e.xmlData ); _stats.parse( e.xmlData );
}
Or you could override a parseXML method ie see one of my earlier postshttp://www.twelvestone.com/forum_thread/view/38544?offset=11
But a friend said that in a Moock lecture he said something along the lines of if it works why refactor, we often waste time changing code that already works fine.
So, LoadXML controls RSS and Stats not the other way around where Stats calls LoadXML and then RSS callsXML?
I like what you've done there and I can see where that would work. In mine though I should have been more clear.....whoops. I realized my mistake. RSS and Stats each have a different url to call. So, I have RSS, then Stats calling LoadXML but I have no idea how to return the object and how to wait for the LoadXML.onData or onLoad function.
Prob posted them before but if your using as2 then these might be usefull and if you look at constructs it may answer your quest
import net.justinfront.XmlNodeToObjArray;
class net.justinfront.ConfigLoader {
private var configInfo: Object = {};
private var fileName: String = '';
private var buildXML: XML;
private var startFunction: Function;
public function ConfigLoader( fileName_: String )
{
fileName = fileName_;
}
public function set onLoadInit( func: Function ):Void
{
//start loading XML when call back set!
startFunction = func;
loadXML();
}
private function loadXML()
{
trace( 'load ' + fileName );
XML.prototype.ignoreWhite = true;
var here:ConfigLoader = this;
buildXML = new XML();
buildXML.onLoad = function( ok )
{
trace('loaded')
here.onLoad(ok);
}
var temp:XML = new XML();
temp.sendAndLoad( fileName, buildXML );
}
private function onLoad( ok )
{
if( ok )
{
trace( 'loaded XML' );
configInfo = ( new XmlNodeToObjArray( buildXML, true, true, fileName) ).instance;
startFunction( configInfo )
} else {
trace('!!! file not found !!!');
}
}
}
import com.dynamicflash.utils.Delegate;
class net.justinfront.XmlNodeToObjArray {
var inputNode: XMLNode;
var obj: Object;
var addName: Boolean;
var outPutTxt: Boolean;
var updateProgress: Function;
var txt: String = "";
var xmlString: String = "";
var place: MovieClip;
var _name: String = "my XML Parser";
var author: String = "jlm at justinfront dot net"
var nom: String;
public function XmlNodeToObjArray(_inputNode:XMLNode, _addName:Boolean, _outPutTxt:Boolean, _nom: String )
{
addName = _addName || false;
outPutTxt = _outPutTxt || false;
inputNode = _inputNode;
nom = _nom || 'xmlObj';
init();
}
private function init()
{
var theNode = inputNode;//.childNodes[0];
obj = {};
if( addName ){
obj._name = nom;
obj.toString = Delegate.create( this, returnFileName )
obj.toXML=function(){
return ".childNodes[0]";
}
}
["ASSetPropFlags"](obj,['toString','_name','attributes'],1,1);
getChildren(theNode, 0, obj, ".childNodes[0]");
if(outPutTxt)
{
trace(txt);
}
}
private function returnFileName()
{
return '('+nom+')'
}
private function getChildren(place:XMLNode, lev:Number, mother:Object, xmlMother:String) {
if (place.hasChildNodes()) {
var i:Number;
var anodeName:String;
var anode:XMLNode;
var temp:Object;
var tempAtt:Object;
var atts:String;
var last_anode:String='';
var counter:Number=0;
var oldTemp:Object;
for (i=0; i<place.childNodes.length; i++) {
anode = place.childNodes[i];
anodeName = anode.nodeName;
if (anodeName == null) {
if (outPutTxt) {
txt += mother+".textValue"+" = "+anode.nodeValue+"\n";
}/*
temp = (mother[anodeName]={});
temp.toXML=function(){
return xmlMother+".childNodes["+String(i)+"].nodeValue";
}
(["ASSetPropFlags"])(temp,['toXML'],1,1);
*/
mother.textValue = cast(anode.nodeValue);
break;
} else {
if (addName) {
if(anodeName == last_anode && last_anode != ""){
last_anode = anodeName;
if(!( (mother[anodeName]) instanceof Array)){
//trace("creating and array"+anodeName);
oldTemp = temp;
temp = (mother[anodeName]=[]);
counter=0;
temp=(mother[anodeName][counter]=oldTemp);
temp._name=anodeName+"["+counter+"]";
counter++;
}
temp=(mother[anodeName][counter]={});
temp._name=anodeName+"["+counter+"]";
counter++;
} else {
last_anode = anodeName;
temp = (mother[anodeName]={});
temp._name = anodeName;
}
temp.toString = function() {
return mother+"."+this._name;
};
temp.toXML=function(){
return xmlMother+".childNodes["+String(i)+"]";
}
//if(place.attributes.length) length check
temp.attributes={};
tempAtt=temp.attributes;
for(atts in anode.attributes){
tempAtt[atts]=cast(anode.attributes[atts]);
tempAtt[atts]._name=atts;
tempAtt[atts].toString=function(){
return mother+"."+atts;
};
tempAtt[atts].toXML=function(){
trace('test info '+xmlMother+".childNodes["+i+"].attributes."+atts)
return xmlMother+".childNodes["+i+"].attributes."+atts;
}
//hide properties from for loops
(["ASSetPropFlags"])(tempAtt[atts],['toString','_name','toXML'],1,1);
}
//hide properties from for loops
(["ASSetPropFlags"])(temp,['toString','_name','attributes','toXML'],1,1);
getChildren(place.childNodes[i], lev+1, temp, temp.toXML());
} else {
temp.attributes={};
tempAtt=temp.attributes;
for(atts in anode.attributes){
tempAtt[atts]=cast(anode.attributes[atts]);
}
//hide properties from for loops
(["ASSetPropFlags"])(temp,['attributes'],1,1);
getChildren(place.childNodes[i], lev+1, mother[anodeName]={});
}
}
}
}
}
public function get instance():Object{
return obj;
}
// returns the most appropriate type
private function cast( str: String ): Object
{
if( str.toLowerCase() == 'true' )
{
return true
}
if( str.toLowerCase() == 'false' )
{
return false
}
var num=Number(str);
if( isNaN( str ) )
{
return str
}else {
return num
}
}
}
In as3 the link shows how to do the onLoad equivalant
_stats = new Stats(txtfields1); _Rss = new RSS(txtfields2); _loadStats = new loadXML( _urlStats ); _loadRSS = new loadXML( _urlRSS );
_loadStats.addEventListener( LoadXMLEvent.LOADED, _stats.parse ) _loadRSS.addEventListener( LoadXMLEvent.LOADED, _Rss.parse )
_loadStats.start() _loadRSS.start();
.. maybe?
_loadStats.addEventListener( LoadXMLEvent.LOADED, _stats.parse ) _loadRSS.addEventListener( LoadXMLEvent.LOADED, _Rss.parse )
This is what I'm looking for. Thank you.
And just so I'M clear, parse is the function within the _stats and _Rss classes, correct?
yer