1

In the last line, I want the XML function to read the name of the button clicked and show the corresponding tag in the XML file (the tags in the XML file has the same names of the buttons), or instead I will have to make functions or if statements equal to the number of buttons I have! this does not make any sense to me!

stop();
import flash.events.MouseEvent;
import flash.events.Event;
import flash.net.URLLoader;
import flash.display.MovieClip;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
var myVar:String = new String();
//var myFrame:Array=new Array(26);
var words:Array =['Amon','Ahmos','Ramsis'];//the words

for (var j:int=0; j<words.length; j++)
{
    var word:MovieClip = CreatTextButton(words[j]);//loop in myDictionary and name each button with a different name
    addChild(word);
    word.x = 130;
    word.y = 16 + (j * 30);// to change the position of each word

    word.addEventListener(MouseEvent.CLICK,onWordClick);

    function CreatTextButton(label:String):MovieClip //creat buttons 
    {
        var txt:TextField = new TextField();
        txt.defaultTextFormat = new TextFormat('Calibri',20,0x000000);
        txt.text = label;
        txt.autoSize = TextFieldAutoSize.LEFT;
        txt.background = txt.border = true;
        txt.selectable = false;
        var btn:MovieClip = new MovieClip();
        btn.label=label;
        btn.mouseChildren = false;
        btn.addChild(txt);
        btn.buttonMode = true;
        myVar=label.valueOf();
        trace(myVar);
        return btn;
    }
    function onWordClick(event:MouseEvent)
    {
        var myLoader:URLLoader= new URLLoader();
        myLoader.load(new URLRequest("1.xml"));
        myLoader.addEventListener(Event.COMPLETE,loadXML);
        var label:String = event.currentTarget.label;
        trace(label);
    }
    function loadXML(e:Event)
        {
            var myxml:XML = new XML(e.target.data);
            mydata.text += String(myxml.label)+"\n";

        }
}

my XML is

<Pharaohs>

<Ahmos id='_1'>
    reigned c. 1539–14 bce and founder of the 18th dynasty
</Ahmos>

<Amon id='_2'>
     The chief deity of the Egyptian Empire
</Amon>

<Ramsis id='_3'>
    The third Pharaoh of the 19th dynasty
</Ramsis>

</Pharaohs>

Sorry for being so slow and stupid :D

Safwat Alshazly
  • 331
  • 4
  • 11
  • There's a lot of things that made your code hard to follow. Here's a few suggestions: 1. Don't put functions inside for loops, or functions inside other functions. 2. Name things more accurately, for example `myDictionary` is an array, not a dictionary, which is confusing. `getTextButton2` could be called `createTextButton`. `Vocabulary` could be called `onWordClick` or `loadVocabularyForWord` or something. `myVar` is particularly meaningless. 3. Use literals instead of the `new` keyword, ex: `var words:Array = []` 4. Scope things logically, your `myVar` doesn't need to be there. – Aaron Beall Feb 19 '16 at 17:50
  • @Aaron Thanx for ur reply, It seems that I have alot of of issues to fix, I did that staff about naming functions but I want to ask about putting the function inside the for loop or a function inside another, I think this is the only way to do what I want to do by this code, any suggestions? – Safwat Alshazly Feb 19 '16 at 18:01
  • It's certainly possible to write the functions outside the for loop. I'll add an answer... – Aaron Beall Feb 19 '16 at 18:09
  • Actually, can you first edit your question with an example of the XML data structure you are loading? – Aaron Beall Feb 19 '16 at 18:23

1 Answers1

0

You can use event.currentTarget to determine what button was clicked. And since you are using a dynamic MovieClip as a button you can assign the label as a property directly on the button when you create it: btn.label = label. Then from your button click handler you can determine the button text of the clicked button using event.currentTarget.label.

You can use this label string value in an E4X filter expression to extract the node in your XML with a matching name() value. For example, if your XML looks like this:

<Pharoahs>
    <Amon>Some text about Amon</Amon>
    <Ahmos>All about Ahmos</Ahmos>
    <Ramsis>This is Ramsis</Ramsis>
</Pharoahs>

You can extract an XML node whose name matches the button label like this:

var label:String = event.currentTarget.label;
var node:XML = xml.children().(name() == label)[0];

Note that naming the XML nodes the same as your words is probably not a good idea, as there are many limitations to how you can name an XML node that do not apply to strings in general. For example spaces would be a problem, certain characters are not allowed, case sensitivity can present a challenge, etc. Instead you can use an attribute (ex <pharoah name="Amon"> or a child node (ex <pharoah><name>Amon</name></pharoah>) as a key for each XML node. This makes the XML lookup a bit easier as well: xml.pharoah.(@name == label) or xml.pharoah.(name == label) respectively.

Also note that you don't need to re-load the XML every time a button is clicked. It probably makes more sense to pre-load the XML, then show the buttons, and each click only needs to lookup the data in the XML object.


Putting it all together and with a few small code improvements:

  • Renamed various things to be more meaningful.
  • Moved all the functions out of the for loop and other functions.
  • Load the XML first and only once, then render the list, and the resulting click handler is much simpler.

Result:

const listOrigin:Point = new Point(130, 16);
const listItemSpacing:Number = 30;
const xmlPath:String = "1.xml";

var pharoahs:Array = ['Amon', 'Ahmos', 'Ramsis'];
var pharoahsXML:XML;

// First load your XML
loadXML();

function loadXML():void {
    var urlLoader:URLLoader = new URLLoader();
    urlLoader.load(new URLRequest(xmlPath));
    urlLoader.addEventListener(Event.COMPLETE, loadXMLComplete);
}

function loadXMLComplete(e:Event) {
    pharoahsXML = new XML(e.target.data);

    // Render your buttons after the XML is loaded
    renderPharoahsButtons();
}

function renderPharoahsButtons():void {
    for (var i:int = 0; i < pharoahs.length; i++) {
        var btn:MovieClip = createTextButton(pharoahs[i]);
        btn.x = listOrigin.x;
        btn.y = listOrigin.y + (i * listItemSpacing);
        addChild(btn);

        btn.addEventListener(MouseEvent.CLICK, pharoahButtonClick);
    }
}

function createTextButton(label:String):MovieClip {
    var txt:TextField = new TextField();
    txt.defaultTextFormat = new TextFormat('Calibri', 20, 0x000000);
    txt.text = label;
    txt.autoSize = TextFieldAutoSize.LEFT;
    txt.background = txt.border = true;
    txt.selectable = false;

    var btn:MovieClip = new MovieClip();
    btn.mouseChildren = false;
    btn.buttonMode = true;
    btn.addChild(txt);

    btn.label = label; // Store the button label for reference

    return btn;
}

function pharoahButtonClick(e:MouseEvent):void {
    // When a button is clicked is the label to extract the XML node
    var label:String = e.currentTarget.label;
    var pharoah:XML = pharoahsXML.children().(name() == currentPharoah)[0];
    pharoahText.text += pharoah + "\n";
}
Aaron Beall
  • 49,769
  • 26
  • 85
  • 103
  • that label variable helped me actually to get the name of the button clicked, but It is still a problem to pass this value in the label to the XML handler, it seems that I have to give him the name of the XML tag, I can't give him the variable (label) as a substitution like this `var myxml:XML = new XML(e.target.data); mydata.text += String(myxml.label)` – Safwat Alshazly Feb 19 '16 at 20:11
  • `myxml.label` is not what I suggested to do above. I suggested you use `children().(name() == label)` to find the XML node whose name matches the label. Post your XML in your question. – Aaron Beall Feb 19 '16 at 20:20
  • Here is my XML ` reigned c. 1539–14 bce and founder of the 18th dynasty The chief deity of the Egyptian Empire The third Pharaoh of the 19th dynasty ` I tried to use `children().(name() == label)` but still no use – Safwat Alshazly Feb 19 '16 at 20:33
  • Please post it in *in your question*, as well as the code you've tried now. – Aaron Beall Feb 19 '16 at 20:34
  • I edited the question with the last I did, u can check it now. thanx – Safwat Alshazly Feb 19 '16 at 20:59
  • Is `` your root XML node? The structure of your XML is important in order to query it properly. You need to select the parent node property, so that `children()` selects the right nodes. – Aaron Beall Feb 19 '16 at 21:25
  • Yes it is my Root Node I edited the Question again to include it in the XML Code – Safwat Alshazly Feb 19 '16 at 21:30
  • In that case `xml.children().(name() == label)` should work, assuming `label` is "Ahmos", etc. – Aaron Beall Feb 19 '16 at 21:30
  • When I try that, this erroe is generated `ReferenceError: Error #1065: Variable label is not defined. at Glossary_fla::MainTimeline/loadXML() at flash.events::EventDispatcher/dispatchEventFunction() at flash.events::EventDispatcher/dispatchEvent() at flash.net::URLLoader/onComplete()` – Safwat Alshazly Feb 19 '16 at 21:35
  • Where's your `label`? It needs to be a variable you have access to. I just updated my answer with complete code, take a look and see if it makes more sense. I really don't think you need to be loading your XML every time, though. – Aaron Beall Feb 19 '16 at 21:42
  • This actually worked! Thanx alot for ur patience I am speechless – Safwat Alshazly Feb 19 '16 at 21:50
  • Just updated my code with a few small improvements listed in bullets. If this helped please don't forget to mark it as answered. ;) – Aaron Beall Feb 19 '16 at 23:38