Currently working on and revising an AIR application written in Flex, I needed to be able to control the instance of an object within Actionscript by referencing it's ID.
Here's the scenario.
I have created a list within FLEX containing parent and child checkboxes. I wanted to be able to control the toggle display (true or false) of the child checkboxes based upon the click action of the parent - if I de-selected the parent, all children should also be set to false and vice versa.
Here is the snippet of code used to create the list:
public function createCheckBoxDisplay():void { var masterCount:int; for(masterCount=0;masterCount<masterSlideArray.length;masterCount++) { var chapterNumber:int = masterCount+1; var chapterTitle:String = masterSlideArray[masterCount][0].toString(); // get the items and create the output for the chapter slide selection edit var slideCLVert:VBox = new VBox(); slideCLVert.name = 'vertBox' + masterCount; var chapterTitleCheckBox:CheckBox = new CheckBox(); chapterTitleCheckBox.id = masterCount.toString(); chapterTitleCheckBox.addEventListener(MouseEvent.CLICK, chapterCheckBoxValue); // check to see if we can pre-populate the master checkbox based on the slide selections var slideInt:int; var slideCheckNumber:int = 0; for(slideInt=0;slideInt<masterSlideArray[masterCount][1].length;slideInt++) { if(masterSlideArray[masterCount][1][slideInt].showSlide == 'true') { slideCheckNumber = slideCheckNumber+1; } } // if the number of 'child' check boxes selected equals the total number of children // select the main chapter checkbox if (masterSlideArray[masterCount][1].length == slideCheckNumber) { chapterTitleCheckBox.selected = true; } var chapterTitleLabel:Label = new Label(); var titleHBox:HBox = new HBox(); titleHBox.name = 'TitleHBox' + masterCount; chapterTitleLabel.text = 'Chapter ' + chapterNumber + ': ' + chapterTitle; titleHBox.addChild(chapterTitleCheckBox); titleHBox.addChild(chapterTitleLabel); // add the titleHBox to the VBox slideCLVert.addChild(titleHBox); // get the children from the array for(slideInt=0;slideInt<masterSlideArray[masterCount][1].length;slideInt++) { var slideNumber:int = slideInt+1; var slideHBox:HBox = new HBox(); slideHBox.name = 'slideHBox' + masterCount + '_' + slideInt; var clCheckBox:CheckBox = new CheckBox(); clCheckBox.id = masterCount + '_' + slideInt; clCheckBox.name = 'slideCheckBox' + masterCount + '_' + slideInt; clCheckBox.addEventListener(MouseEvent.CLICK, changeCheckBoxValue); if(masterSlideArray[masterCount][1][slideInt].showSlide == 'true') { clCheckBox.selected = true; } var clSlideName:Label = new Label(); clSlideName.text = 'Slide ' + slideNumber; var slideSpacer:Spacer = new Spacer(); slideSpacer.width = 20; slideHBox.addChild(slideSpacer); slideHBox.addChild(clCheckBox); slideHBox.addChild(clSlideName); slideCLVert.addChild(slideHBox); } selectionBox.addChild(slideCLVert); } var commitButton:Button = new Button(); commitButton.label = 'Save Changes'; commitButton.addEventListener(MouseEvent.CLICK, saveChanges); var buttonHBox:HBox = new HBox(); buttonHBox.addChild(commitButton); selectionBox.addChild(buttonHBox); }
It loops through two arrays (master and child) and creates the form fields required to display all options, formatting the display output using HBox and VBox components.
The onclick event for the master checkboxes was sending the correct details through that I needed to create the ID's for the children to change their value. As I continued my search, I found out that AS and FLEX do not have a function such as getElementByID. Damn them. This would have been perfect.
So, the only option was to write a new one.
The onClick event was calling the following function, that was sending through the master ID as one of the parameters, and was using the returned value to create an instance of the checkbox to change the value.
var thisCheckBox:CheckBox = getChildById(selectionBox,chapterID,slideInt);
Here's the getChildById function:
private function getChildById(g:Box, parentID:int, childID:int):CheckBox {
for each (var gr:VBox in g.getChildren()) {
for each (var gi:HBox in gr.getChildren()) {
if(gi.name == 'slideHBox' + parentID + '_' + childID ) {
var thisRootTarget:DisplayObjectContainer = gi;
var giCount:int; for(giCount=0;giCount<thisRootTarget.numChildren;giCount++) {
if (gi.getChildAt(giCount) is CheckBox) {
return CheckBox(gi.getChildAt(giCount));
}
}
}
}
}
return null;
}
It's a relatively simple function. This is tailored to suit my needs for this purpose as it references the tupes of display components I used to build to display, but you can edit and amend it to work for you quite easily.
Looping through the children in the main container, it continues looping through until it finds the child checkboxes within the correct parent HBox (slideHBox). Once found, this object is transformed to a rootTarget variable, and the number of children is then counted. The names of the children are then returned to the calling function, and the value of the boxes are set as required.
It may look a bit complex (or not) and I know that my description of what's going on here needs some major work (apologies for that), but I wanted to place it here for two reasons: 1) my own reference, and 2) you never know, someone somewhere might find this useful.