how could I traverse through children of a UIComponent Class in flex - apache-flex

I am dynamically creating a UI component based on XML templates stored in database. Now I want to access one of the child component of this UIComponent Class. I dont see any children property in this class? How could I possibly traverse through each child comppnent of this class and set its properties according to some logic in code(which I could not do in templates itself).
Basically what I want to do is something like this:
var cover:UICoomponent = generateScreen()
for each(var obj:UIComponent in cover.children){
if (obj.id =="myComponent"){
obj.SomProperty = "SomeValue";
}
}
Any help will be greatly appreciated. Thanks.

Use numChildren:
var cover:UICoomponent = generateScreen()
for (var i:int = 0; i < cover.numChildren; i++)
{
var obj:UIComposer = cover.getChildAt(i) as UIComponent;
if (obj.id =="myComponent") {
obj.SomProperty = "SomeValue";
}
}
Update: Traverse recursively
function findChild(childId:String,container:DisplayObjectContainer=null):UIComponent
{
container ||= this;
for (var i:int = 0; i < container.numChildren; i++)
{
var obj:UIComponent = container.getChildAt(i) as UIComponent;
if (obj.id == childId)
return obj;
if (obj is DisplayObjectContainer)
{
// search for children
child = findChild(childId,obj as DispalyObjectContainer);
if (child)
return child;
}
}
}
Usage:
var child:UIComponent = findChild("myComponent");
child.someProperty="SomeValue";
I haven't compiled this - but you get the general idea.

Related

creating a Placemarks that can be hidden

I have been trying to create a Placemark that I can hide and show (like turning visibility on and off) on demand (on click)... I am using this to make the placemark:
function placemark(lat, long, name, url, iconsrc){
var placemark = ge.createPlacemark(name);
ge.getFeatures().appendChild(placemark);
placemark.setName(name);
// Create style map for placemark
var icon = ge.createIcon('');
if(iconsrc == "0")
icon.setHref('http://maps.google.com/mapfiles/kml/paddle/red-circle.png');
else{
icon.setHref(iconsrc);
}
var style = ge.createStyle('');
style.getIconStyle().setIcon(icon);
if(iconsrc != "0")
style.getIconStyle().setScale(2.5);
placemark.setStyleSelector(style);
// Create point
var point = ge.createPoint('');
point.setLatitude(lat);
point.setLongitude(long);
//point.setAltitudeMode(1500);
placemark.setGeometry(point);
google.earth.addEventListener(placemark, 'click', function(event) {
// Prevent the default balloon from popping up.
event.preventDefault();
var balloon = ge.createHtmlStringBalloon('');
balloon.setFeature(placemark); // optional
balloon.setContentString(
'<iframe src="'+ url +'" frameborder="0"></iframe>');
ge.setBalloon(balloon);
});
}
I have tried everything... from this:
function hidePlacemark(name){
var children = ge.getFeatures().getChildNodes();
for(var i = 0; i < children.getLength(); i++) {
var child = children.item(i);
if(child.getType() == 'KmlPlacemark') {
if(child.getId()== name)
child.setVisibility(false);
}
}
}
to using this ge.getFeatures().removeChild(child);
can anyone point me to the right direction on creating a function that will allow me to turn the visibility on/off on demand please.
Your hidePlacemark function is missing some {} in your final IF statement
if(child.getId()== name)
you have
function hidePlacemark(name){
var children = ge.getFeatures().getChildNodes();
for(var i = 0; i < children.getLength(); i++) {
var child = children.item(i);
if(child.getType() == 'KmlPlacemark') {
if(child.getId()== name)
child.setVisibility(false);
}
}
}
make it
function hidePlacemark(name){
var children = ge.getFeatures().getChildNodes();
for(var i = 0; i < children.getLength(); i++) {
var child = children.item(i);
if(child.getType() == 'KmlPlacemark') {
if(child.getId()== name) {
child.setVisibility(false);
}
}
}
}
HOWEVER ------- you are better off doing this as it is much faster as you don't need to loop through ALL your placemarks
function hidePlacemark(name) {
var placemark = ge.getElementById(name);
placemark.setVisibility(false);
}
I think the plain ge.getFeatures().removeChild(placemark); works.
I played with this GooglePlayground, and just added the following code to line 8 (that is empty in this GooglePlayground Sample):
addSampleButton('Hide Placemark', function(){
ge.getFeatures().removeChild(placemark);
});
Clicking the button Hide Placemark hides the placemark like a charm here. Any chances your problem is somewhere else in your code?

get all the descendants Elements(controls) of VBox(container) in flex?

can we get all the elements and all the descendants of those elements in a
VBox
?
lets say i have Vobx, in which a grid is added.. and in grid there are many texinput controls.. i want to access all the descendants which are
Grid,GridRow,GridItem,TextInput
.. how to do that ?
You'll have to write a recursive function that traverses the hierarchy of components. There is no built-in method to access children below the first level of a container.
Something like:
function traceDisplayObject(object:DisplayObject):void {
trace("Object: " + object);
if (object is Container) {
var container:Container = Container(object);
var numChildren:uint = container.numChildren;
for (var i:uint = 0; i<numChildren; i++) {
traceDisplayObject(container.getChildAt(i));
}
}
}
traceDisplayObject(myVBox);

How to access children of children recursively?

I have a Canvas which has many components inside it and those again, have many components inside them.
getChildren() returns only the top level children. What is the best way to retrieve all the children (children of children of children and so on).
Well, I sorta know how to do this by iterating through the children, but the code is really messy. I'd prefer to use a nice recursive function. Has anyone written this before? Or is there a Util class to do this?
private function recuse(display : DisplayObjectContainer) : void {
if(display) {
for (var i : int = 0;i < _display.numChildren;i++) {
var child : DisplayObject = display.getChildAt(i);
trace(child.name);
if(child is DisplayObjectContainer) {
recuse(DisplayObjectContainer(child));
}
}
}
}
Try something likely (note you can return the lists recursively if you want to gather all the references to the top level iteration)
function inspect(object:DisplayObject):void
{
if(object is DisplayObjectContainer)
{
var casted:DisplayObjectContainer = object as DisplayObjectContainer
trace("DisplayObjectContainer ", casted.name)
for(var depth:int = 0; depth < casted.numChildren;depth++)
{
inspect(casted.getChildAt(depth))
}
}else{
trace("DisplayObject", object.name );
}
}
inspect(this)
function theCallbackFunction(obj:DisplayObject):void
{
trace(obj.name);
}
//Visit the children first.
//Deep most objects will be visited first and so on.
//stage is visited at the end.
//Uses recursion
function depthFirst(obj:DisplayObject, func:Function):void
{
if(!(obj instanceof DisplayObjectContainer))
{
func(obj);
return;
}
var p:DisplayObjectContainer = DisplayObjectContainer(obj);
var len:Number = p.numChildren;
for(var i:Number = 0; i < len; i++)
{
var child:DisplayObject = p.getChildAt(i);
depthFirst(child, func);
}
func(obj);
}
//Visit the siblings first.
//stage is visited first, then its children, then the grand children and so on
//No recursion.
function breadthFirst(obj:DisplayObject, func:Function):void
{
var q:Array = [];
q.push(obj);
var p:DisplayObjectContainer;
var i:Number, len:Number;
while(q.length != 0)
{
var child:DisplayObject = queue.shift();
func(child);
if(!(child instanceof DisplayObjectContainer))
continue;
p = DisplayObjectContainer(child);
len = p.numChildren;
for(i = 0; i < len; i++)
q.push(p.getChildAt(i));
}
}
depthFirst(this.stage, theCallbackFunction);
breadthFirst(this.stage, theCallbackFunction);

How to prevent tree items from being dragged into themselves?

I have a flex tree with dragMoveEnabled = true. I want to find out, when an item is dragged into itself or it's children. I'd like to use DragManager.showFeedback(DragManager.NONE) in the tree's onDragOver handler, but can't find out how get this to work. I'm using an ArrayCollection of nested objects as dataSource for the tree.
private function onDragOver(event:DragEvent):void {
event.preventDefault();
event.currentTarget.hideDropFeedback(event);
var index:int = tree.calculateDropIndex(event);
tree.selectedIndex = index;
var subCategory:CategoryVO = CategoryVO(tree.selectedItem);
var currentCategory:CategoryVO = subCategory;
while(currentCategory.parent != 0) {
if (currentCategory.parent == _draggedItem.id) {
DragManager.showFeedback(DragManager.NONE);
return;
}
currentCategory = tree.getParentItem(currentCategory);
if (currentCategory == null) {
break;
}
DragManager.showFeedback(DragManager.MOVE);
tree.showDropFeedback(event);
}
That's how I solved it.
_draggedItem holds the currently dragged item, set in the tree's onDragEnter handler. CategoryVO is the value object I use.
can you do something like:
if(event.currentTarget == event.target){
//item is being dropped on itself
}

How to access mxml (Flex) DOM elements?

Is there a way to access the DOM-Elements of a mxml file in a way that you can in JS (e.g. using Prototype or jQuery)?
I need to know if a top-level element has a child (sub-sub-...-childs) with a certain id.
In JS (using prototype) it would be something like:
$('tabs').select('[id="something"]');
Any ideas?
Depending on what you're trying to do, Bifff might be the answer. Think of it as "JQuery for Flex": https://github.com/seanhess/bifff/wiki
You can recursively search through the structure. Something like this (Might not be the most efficient in your case):
private function hasChild(node:UIComponent, target:String):Boolean
{
if(node.id == target)
{
return true;
}
else
{
var hasTarget:Boolean = false;
for(var i:int = 0; i < node.numChildren; i++)
{
hasTarget = hasTarget || hasChild(node.getChildAt(i));
}
return hasTarget;
}
}

Resources