views:

293

answers:

3

alt text

Hi everyone, I'm creating a tabbed navigation from an XML file. However for some reason my loop only creates textfields for the active tab and the last tab (in this case the 4th tab).

> You can preview my Flash here. < (I turned textfield borders on)

My Issues:
1. The Active Tab (light colored tab) does not size correctly based on the width of the textfield
2. My loop for some reason skips the 2 middle tabs, but correctly sets the 4th tab.

XML Tab titles:

  • This is first tab
  • 2nd Tab
  • The 3rd Tab
  • The 4th and last tab

It seems that the 2nd and 3rd tabs get sized correctly, but as you see further below, I get an error when trying to trace out the text of the 2nd and 3rd tab.

♥ Update: Added entire TabMenu class in hopes of getting this resolved :) I now believe this is where my problem lies:

// tabNamer creates the active & default textfields
tabNamer(tabNameActive,  Fonts.ActiveTabText,  tabData[0].id); // for ActiveTab
tabNamer(tabNameDefault, Fonts.DefaultTabText, tabData[i].id); // for DefaultTabs

tabNamer is a function containing just a textField, and I believe I keep overriding the last textField made, this is why only the 4th and last textField shows text. Is there a way to dynamically name my textFeilds are I loop?

TabMenu.as (Entire Class)

package com.leongaban.TEN.ui
{
import flash.display.DisplayObject;
import flash.display.LineScaleMode;
import flash.display.JointStyle;
import flash.display.MovieClip;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.Shape;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.events.TimerEvent;

import com.leongaban.TEN.ui.*;
import com.leongaban.TEN.Global;
import com.leongaban.TEN.model.*;

public class TabMenu extends Sprite
{

    private const position    :Number    = 0;

    private var tabNameDefault:TextField = new TextField();
    private var tabNameActive :TextField = new TextField();
    private var backing       :Shape     = new Shape();
    private var tabData       :Array     = [];
    private var tabArray      :Array     = [];
    private var bgColor       :uint      = 0xF6F6F6; //0xE8E7E7;
    private var borderColor   :uint      = 0xCCCCCC;
    private var borderSize    :uint      = 1;
    private var sizeW         :uint;
    private var sizeH         :uint;
    private var topShadow     :MovieClip;
    private var tileShadow    :MovieClip;
    private var sideShadowL   :MovieClip;
    private var sideShadowR   :MovieClip;


    public function TabMenu():void
    {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }

    private function init(e:Event = null):void {

        removeEventListener(Event.ADDED_TO_STAGE, init);

        addChild(backing);
        addChild(topShadow);
    }

    public function drawTabMenu(w, h, color, videoHDiff, ypos):void
    {           
        for (var i in Global.xml..tab) {
            tabData.push( {
                           id:Global.xml..tab[i].@id, 
                           video:Global.xml..tab[i].vid, 
                           title:Global.xml..tab[i].title} );

            //trace("TAB TITLES: "+tabData[i].id);
        }
        //trace("FIRST TAB DATA : "+tabData[0].id[0]+"\n"+tabData[0].video);

        sizeW = w;
        sizeH = h;

        topShadow = new EmptyMov();
        tileShadow = new TileShadow();
        sideShadowL = new SideShadowL();
        sideShadowR = new SideShadowR();
        sideShadowR.x = (sizeW-16) - sideShadowR.width;

        tileShadow.width = sizeW-16;

        topShadow.addChild(tileShadow);
        topShadow.addChild(sideShadowL);
        topShadow.addChild(sideShadowR);

        backing.graphics.beginFill(bgColor);
        backing.graphics.lineStyle(borderSize, borderColor);
        backing.graphics.drawRect(position, position, sizeW-17, videoHDiff);
        backing.graphics.endFill();
        backing.y = tileShadow.height - 1;


        //DRAW THE TABS -------------
        for (i in tabData) 
        {
            //trace("TAB TITLES: "+tabData[i].id);

            var tab    :MovieClip = new TabDefault();
            var active :MovieClip = new TabActive();

            tabArray.push(tab);
            //tab.video = tabData[i].video;
            //tab.title = tabData[i].title;
            tab.addChild(active); // add active tab movieclip to default tab movieclip

            // tabNamer creates the active & default textfields
            tabNamer(tabNameActive,  Fonts.ActiveTabText,  tabData[0].id); // for ActiveTab
            tabNamer(tabNameDefault, Fonts.DefaultTabText, tabData[i].id); // for DefaultTabs

            i < 1 ? active.visible = true : active.visible = false;
            //i < 1 ? tab.addChild(tabNameActive) : tab.addChild(tabNameDefault);
            i < 1 ? tabArray[0].addChild(tabNameActive) : tabArray[i].addChildAt(tabNameDefault,2);

            //tabArray[i].addChildAt(tabNameDefault,2);
            //tab.addChild(tabNameDefault);
            //if (i < 1) { tab.addChild(tabNameActive) }

            trace("i = "+i);
            trace("tabArray["+i+"].getChildAt(2) = "+tabArray[i].getChildAt(2).text);
            trace("tabNameDefault.text = "+tabNameDefault.text);

            // resize the tab background to textfield
            tab.y      =         topShadow.y + 5;
            //     if first size to active textfield + 10    : if not size to default textfield + 10
            tab.width  = i < 1 ? tabNameActive.width + 10    : tabNameDefault.width + 10;
            tab.x      = i < 1 ? 10                          : tabArray[(i-1)].x + (tabArray[(i-1)].width + 3);
            //tab.active = i < 1 ? tab.active = true           : tab.active = false;

            topShadow.addChild(tab);

            tab.mouseChildren = false;
            tab.buttonMode    = true;
            tab.addEventListener(MouseEvent.CLICK, tabClick);
        }

        // set default thumbnails here
        //trace("tabData[0].id : "+tabData[0].id.@id+"\r");
        //trace("tabData[0].video: "+"\r"+tabData[0].video+"\r");
        //trace("tabData[0].titles : "+tabData[0].titles+"\r");
    }

    private function tabNamer(textfield, textFormat, tabText):void
    {
        //trace("TabNamer called");
        textfield.defaultTextFormat = textFormat;
        textfield.border            = false;
        textfield.embedFonts        = false;
        textfield.gridFitType       = "SUBPIXEL";
        textfield.sharpness         = 100;
        textfield.antiAliasType     = flash.text.AntiAliasType.ADVANCED;
        textfield.autoSize          = TextFieldAutoSize.CENTER;
        textfield.selectable        = false;
        textfield.mouseEnabled      = false;
        textfield.x                 = 10;
        textfield.y                 = 4;
        textfield.text              = tabText;
    }

    private function tabClick(e:MouseEvent = null):void
    {
        for (var i in tabArray) {
                //tabArray[i].active = false;
                tabArray[i].getChildAt(1).visible = false;
        }

        //e.target.active = true;
        e.target.getChildAt(1).visible = true;
        trace("Text for button clicked: "+e.target.getChildAt(2).text+"\r");

        //trace("THUMBNAILS FOR TAB: " + e.target.video);
        // pass the video data to the thumbnail class
    }

}

}



tabNamer function

private function tabNamer(textfield, textFormat, tabText):void
{
    //trace("TabNamer called");
    textfield.defaultTextFormat = textFormat;
    textfield.border            = true;
    textfield.embedFonts        = false;
    textfield.gridFitType       = "SUBPIXEL";
    textfield.sharpness         = 100;
    textfield.antiAliasType     = flash.text.AntiAliasType.ADVANCED;
    textfield.autoSize          = TextFieldAutoSize.CENTER;
    textfield.selectable        = false;
    textfield.mouseEnabled      = false;
    textfield.x                 = 10;
    textfield.y                 = 4;
    textfield.text              = tabText;
}



tabClick function

private function tabClick(e:MouseEvent = null):void
    {
        for (var i in tabArray) {
                //tabArray[i].active = false;
                tabArray[i].getChildAt(1).visible = false;
        }

        //e.target.active = true;
        e.target.getChildAt(1).visible = true;
        trace("Text for button clicked: "+e.target.getChildAt(2).text+"\r");

        //trace("THUMBNAILS FOR TAB: " + e.target.video);
        // pass the video data to the thumbnail class
    }



These are the traces from the create tabs function (class function)

i = 0
tabArray[0].getChildAt(2) = This is first tab
tabNameDefault.text = This is first tab
i = 1
tabArray[1].getChildAt(2) = 2nd Tab
tabNameDefault.text = 2nd Tab
i = 2
tabArray[2].getChildAt(2) = The 3rd Tab
tabNameDefault.text = The 3rd Tab
i = 3
tabArray[3].getChildAt(2) = The 4th and last tab
tabNameDefault.text = The 4th and last tab



These are the traces I get when I click the tabs (I'm trying to find the 2nd & 3rd textfields)

//Clicked Tab 1
Text for button clicked: This is first tab

//Clicked Tab 2
RangeError: Error #2006: The supplied index is out of bounds.
at flash.display::DisplayObjectContainer/getChildAt()
at com.leongaban.ui::TabMenu/tabClick()

//Clicked Tab 3
RangeError: Error #2006: The supplied index is out of bounds.
at flash.display::DisplayObjectContainer/getChildAt()
at com.leongaban.ui::TabMenu/tabClick()

//Clicked Tab 4
Text for button clicked: The 4th and last tab



Been raking my brain over this all day :( hoping for any advice, tips or dude that's why! :)

+1  A: 

It looks to me like your problem is reusing the TextField tabNameDefault. Here's what your code is doing:

  1. Set the text of tabNameActive and tabNameDefault to the first tab's data
  2. Add tabNameActive as a child of the first tab
  3. Set the text of tabNameActive and tabNameDefault to the second tab's data
  4. Add tabNameDefault as a child of the second tab
  5. Set the text of tabNameActive and tabNameDefaultto the third tab's data
  6. Add tabNameDefault as a child of the third tab. This removes it from the second tab.
  7. Set the text of tabNameActive and tabNameDefaultto the fourth tab's data
  8. Add tabNameDefault as a child of the fourth tab, removing it from the third tab.
Selene
thx, trying to fix this right now, thinking I may need another array to handle just the textfields
Leon
how can I create dynamically named textFields? That way I don't overrride the last one with the same name?
Leon
A: 

You haven't shown all of the code. Specifically, I don't see anywhere that is creating the textfields. My guess is you only create two textfields (tabNameActive and tabNameDefault). There should be something like 'new TextField()' somewhere inside your for loop that creates the tabs.

Please fix the code indentation, it's very hard to read with it all over the place. Also I recommend against using the a?b:c construct where it's not necessary, especially in cases where you are using it to perform statements instead of expressions.

davr
This is the line that creates the textFields: tabNamer(tabNameActive, Fonts.ActiveTabText, tabData[0].id); I call the tabNamer function
Leon
+1  A: 

The problem is that you are reusing the TextField. tabNameActive is referencing the same Text field through out the loop.

My guess is that your textfield 'tabNameActive' is on the stage. If that's the case, you need to do the following:

1) Delete the tabNameActive from the stage

2) Go to your library and find the the tabNameActive. Right-click and click properties. Check "Export on first frame".

3) A window shows up. Now give a class identifier "TabNameActiveClass".

4) Go back to your code. Within the for loop, add this below the variable declarations.

var tab:MovieClip = new TabDefault();
var active:MovieClip = new TabActive();
var tabNameActive:TabNameActiveClass = new TabNameActiveClass();

This should work.

Recap: Basically, you make your text as a class and make different instance of it in the loop. Right now, you are just reusing the instance and it basically gets moved from tab 1 to 4 during creation.

EDTIED in response to comments below:

Remove from your class definition:

private var tabNameDefault:TextField = new TextField();
private var tabNameActive :TextField = new TextField();

Then add with your loop:

var tab:MovieClip = new TabDefault();
var active:MovieClip = new TabActive();
var tabNameActive:TextField = new TextField();
var tabNameDefault:TextField = new TextField();
JONYC
Hey JONYC, my textfield is dynamically created, I don't have a textfield movieclip in my library... but are you suggesting I do that instead of what I'm trying now?
Leon
Yes... well.. first of all. Where is 'tabNameActive' created?
JONYC
Either way works, as long as you do a new TextFieldActiveClass() from the library or new TextField()...
JONYC
tabNameActive is just a textField object, my tabNamer function contains the textField code, I pass (textField name(which I think is the problem, not sure how to generate new names there), the font style and the text that goes in them)
Leon
Is it possible to provide a bit more code written out? I have to be able to dynamically name/create new textFields... I'm hoping that is the only problem
Leon
ok... see edited portion above
JONYC
AH! Yes! Works now :D thanks!!
Leon