2
votes

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.

3
you are comparing apples and oranges in your example. In flex you could change the CSS for all the buttons in one line also. What's the JQuery code for changing all the text in one line? - Gregor Kiddie
My bad, I'm new to Flex. Could you give an example of how you'd change the CSS for all buttons please? - Reado

3 Answers

3
votes

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.

1
votes

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.

0
votes

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)