views:

74

answers:

3

In my example below I have several objects. I want to change the label of all objects in one go, without calling each element by id. I know how to do this in HTML, but not in Flex.

// HTML
<div class="text" id="text1">SomeText</div>
<div class="text" id="text2">SomeText</div>
<div class="text" id="text3">SomeText</div>

// jQuery
$(".text").css("color", "#333333");

This is how I would usually set the color of 3 objects to grey in one line.

// Flex
<s:Button id="button1" label="Button 1"/>
<s:Button id="button2" label="Button 2"/>
<s:Button id="button3" label="Button 3"/>

// AS3
button1.label = 'Something else';
button2.label = 'Something else';
button3.label = 'Something else';

Is there any way I can change the labels of all 3 buttons with a single line of code similar to the jQuery example? Thanks in advance.

A: 

I don't know of any selector of the css3/jquery type for flex. But a workaround will be to use an array of buttons instead of many buttons variables and then just iterate through all of them (button[i] instead of buttoni)

cripox
+2  A: 

I'm pretty sure the answer is no, with a caveat.

Keep in mind that JQuery is a framework that hides the complexity of what it is doing. ( A lot of frameworks do that including the flex Framework ). In Flex, I can create a DataGrid in one line of code. However, there are thousands of lines of code, and multiple classes already written that allow me to do that. I suspect the same is true for a lot of JQuery functionality.

there is no reason you can't encapsulate that functionality to make the change and then call it with one line of code.

www.Flextras.com
+1  A: 

As @www.Flextras.com pointed out - you can write a class to do this.

I'd encourage you to consider an alternative approach however, as looping through the children looking for a specific property is quite slow. That said - it does make for an interesting coding challenge.

Here's a class & example that should acheive what you're after.

package com.mangofactory.util
{
    import flash.display.DisplayObject;

    import mx.core.UIComponent;

    /**
     * Utility class to set a given property of all matching children on a target.
     * Named to act as an operator, rather than a class (hence no captial letter)
     *
     * eg.,  on(someTarget).of(SomeClass).someProperty = someValue;
     * */
    public class on
    {
        private var root:UIComponent;
        private var requiredPropertyName:String;
        private var requiredType:Class;

        public function on(root:UIComponent)
        {
            this.root = root;
        }
        /**
         * Returns a list of targets which match the defined criteria.
         * Note - the root component is also evaluated
         * */
        private function get targets():void
        {
            var result:Array = [];
            if (matches(root))
            {
                result.push(root);
            }
            for (var i:int = 0; i < root.numChildren; i++)
            {
                var child:DisplayObject = root.getChildAt(i);
                if (matches(child))
                    result.push(child);
            }
        }
        /**
         * Returns true if the target param matches the defined criteria.
         * If a propertyName has been given (by calling 'having') that is checked first.
         * Otherwise, the type is checked against the value passed calling ('of')
         * */
        private function matches(target:Object):Boolean
        {
            if (requiredPropertyName && target.hasOwnProperty(requiredPropertyName))
                return true;
            if (requiredType && target is requiredType)
                return true;
            return false;

        }
        public function having(propertyName:String):PropertyCatcher
        {
            this.requiredPropertyName = propertyName;
        }
        public function setOnTargets(propertyName:*,value:*):void
        {
            for each (var matchedTarget:Object in targets)
            {
                if (matchedTarget.hasOwnProperty(propertyName))
                    matchedTarget[propertyName] = value;
            }
        }
        public function of(type:Class):PropertyCatcher
        {
            this.requiredType = type;
        }
    }
}
import com.mangofactory.util.on;

import flash.utils.Proxy;
import flash.utils.flash_proxy;
use namespace flash_proxy;

dynamic class PropertyCatcher() extends Proxy
{
    private var callbackTarget:on;
    public function PropertyCatcher(callbackTarget:on)
    {
        this.callbackTarget = callbackTarget;
    }
    override flash_proxy function setProperty(name:*, value:*):void {
        callbackTarget.setOnTargets(name,value);
    }
}

And an example:

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009" 
           xmlns:s="library://ns.adobe.com/flex/spark" 
           xmlns:mx="library://ns.adobe.com/flex/mx">
    <s:Button />
    <s:Button />
    <s:Button />
    <mx:Canvas  />
    <fx:Script>
        <![CDATA[
            public function doTest():void
            {
                // Sets the label of all Buttons to "Hello World" 
                on(this).of(Button).label = "Hello World";
                // Sets the visible property of all children which declare a "alpha" property to false.
                on(this).having("alpha").visible = false;
            }
        ]]>
    </fx:Script>
</mx:Canvas>

Note - I haven't tested this, but in theory it should work.

Marty Pitt