Slip Sliding Away

According to the ‘What should I write about next’ poll, it seems you’d like to learn some ‘Advanced’ widgetry. Well in this post we will. But it’s not really ‘Advanced advanced’. That is to say, not overly complicated, or hard to get your head around. Oh no. As advanced goes this is pretty easy. It’s the many ways you can apply this feature that makes it advanced.

I’ve probably toted just about every feature I’ve written about as being ‘the most powerful widget feature ever!’ (I mean would you really read an article that started: “This feature is kinda soggy and flat, but here’s how it works anyway”) This one however, is the real deal. Seriously. In the future I think at least half of the widgets worth their salt will use this feature in some form or another.

What is it?

1
getSlideObjectByName();

Oh be afraid. Be very afraid.

What does this do?

It allows you to get a reference to an object on the Captivate Slide (like a caption, highlight box, image, shape, click area, so on). What good is that? Well, once you have that ‘reference’ you can do pretty much anything you like to that object. Move it, scale it, rotate it, tween it, filter it, (cough) drag it. You could even make a full physics simulation with captions and highlight boxes bouncing around the stage.

“Sounds like a blast” You say. Well, maybe not out loud, because people will look at you weird for talking to your computer.

“BUT” You add, “What do I have to do to get this ‘reference’?”

Easy. You just need to know that object’s name.

“How would I know that objects name? We’ve never been introduced.”

Quite easy my friend. Inside Captivate select the object, and go to the Properties panel. You will see its name listed under “Item Name”.

ItemName2BINGO! If we want to access this text caption at runtime, all we need to do is pass the string “manicTextCaption” into the getSlideObjectByName() method, and it will return us the reference to that caption.

1
getSlideObjectByName("manicTextCaption");

To make things easier for us, we’ll store that reference in a variable for safe keeping. A Sprite or MovieClip variable should see you right.

1
var soonToBeRotatedCaption:Sprite = getSlideObjectByName("manicTextCaption");

So, all together, if we wanted to make a widget that rotated the manicTextCaption –90 degrees, here’s what it would look like.

1
2
3
4
5
6
7
8
9
10
11
12
13
package  {

    import flash.display.Sprite;
    import widgetfactory.StaticWidget;

    public class ManicTextFieldRotator extends StaticWidget {
        override protected function enterRuntime():void
        {
            var soonToBeRotatedCaption:Sprite = getSlideObjectByName("manicTextCaption");
            soonToBeRotatedCaption.rotation = -90;
        }
    }
}

CaptionRotated 

(Note: In Captivate, the 0,0 point is in the top left of every object, not the centre. So when you rotate an object, it will pivot around the object’s top left corner, not its centre.)

Now if you’re selling your widget to a wide audience then you’re not going to know what names they give their slide objects. But as you saw, the name is just a string value. So what you can do is provide an input text field in the Properties Dialog interface where the Captivate Author can type the name they gave the object. The widget saves that name to properties, and then plugs that property into the getSlideObjectByName() method at runtime.

And the best part is that I’ve already done a tutorial on creating that type of interface in the eSeminar I did with Allen Partridge. So I don’t have to show you how to do that here!

Why is this so great?

Because I hate writing the same thing over and over again.

Oh, you were talking about the getSlideObject thing-o weren’t you?

Because this means the Properties Dialog is not the only place where you can customise the widget. Captivate becomes the widget’s design environment. Do you remember when widgets first came out Adobe said: “If you want to customise the appearance of the widget. Open up its fla file and start breaking stuff!” With this feature employed, if the Captivate Author wanted to provide a custom background to their Course Complete certificate widget, they’d just drag said image onto the same slide as the widget and type its name into the Properties Dialog interface! The Captivate Author could provide images the up, over, and down state of a button widget (pretty savvy he would be too). Why not go all out!? A fully customisable playbar widget! AND THEN WE SHALL TAKE OVER THE WORLD!!!!

MUAHAHAHAHAHAAAHAHAH!

See. Powerful.

Currently, getSlideObjectByName() will only return a reference to an object that is on the same slide as the widget. In the next version of WidgetFactory (5.1), getSlideObjectByName() will have a second parameter that will take the number, or label, of the slide you’re trying to find the object on. This will be an optional parameter, and will default to the widget’s slide.

Before I leave off, I’d like to give you another cool example widget. Here’s the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package  {

    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.events.MouseEvent;
    import flash.filters.GlowFilter;
    import fl.controls.TextInput;
    import fl.controls.Button;
    import widgetfactory.StaticWidget;

    public class RuntimeDragger extends StaticWidget {

        // The space between the edges
        private const PADDING:int = 5;

        // UI
        private var message:TextField;
        private var textInput:TextInput;

        // The object on slide that we are currently interacting with.
        private var activeSlideObject:Sprite;

        // The starting location of the active object
        private var orgX:Number;
        private var orgY:Number;

        override protected function enterRuntime():void
        {
            ///// Create feed back text field
            message = new TextField();
            addChild(message);
            message.autoSize = TextFieldAutoSize.CENTER;
            message.text = "Write the name of the object you want to access.";
            message.x = PADDING;
            message.y = PADDING;

            ///// Create field to write slide object name
            textInput = new TextInput();
            addChild(textInput);
            textInput.width = message.width;
            textInput.x = PADDING;
            // Position under message text field
            textInput.y = message.y + message.height + 5;
            // Default to choosing the highlight box
            textInput.text = "highlightBox";

            ///// Button to click to start dragging a different object
            var startDragButton:Button = new Button();
            addChild(startDragButton);
            startDragButton.width = textInput.width / 2;
            // Centered to text input field
            startDragButton.x = textInput.width / 2 - startDragButton.width / 2 + PADDING;
            // Position under text input field
            startDragButton.y = textInput.y + textInput.height + 5;
            startDragButton.label = "Start Dragging";
            startDragButton.addEventListener(MouseEvent.CLICK, onButtonClick);

            // Simulate a click to start default behaviour.
            onButtonClick();
        }

        private function onButtonClick(e:MouseEvent = null):void
        {
            if (activeSlideObject != null) { // If we have been dragging something before the new object
                // Return it to its starting position
                activeSlideObject.x = orgX;
                activeSlideObject.y = orgY;

                // Stop dragging behaviour.
                activeSlideObject.removeEventListener(MouseEvent.MOUSE_DOWN, onDown);
                onUp();

                // Remove indicators that you can drag this object.
                activeSlideObject.filters = [];
                activeSlideObject.mouseEnabled = false;
            }

            // The object that we've written in the text input field will become draggable
            activeSlideObject = getSlideObjectByName(textInput.text);

            if (activeSlideObject == null) { // If the user didn't write the name correctly
                message.text = "Could not find an object by the name of: " + textInput.text;
            } else { // User did write the name correctly

                // Reset message
                message.text = "Write the name of the object you want to access.";

                // Start dragging behaviour
                activeSlideObject.addEventListener(MouseEvent.MOUSE_DOWN, onDown);

                // Save new object's starting position.
                orgX = activeSlideObject.x;
                orgY = activeSlideObject.y;

                // Create visual indicators that you can now drag this object.
                activeSlideObject.filters = [new GlowFilter(0xFF0000)];
                activeSlideObject.mouseEnabled = true;

            }
        }

        // On mouse down start dragging.
        private function onDown(e:MouseEvent):void
        {
            activeSlideObject.startDrag();
            stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
        }

        // On mouse up stop dragging.
        private function onUp(e:MouseEvent = null):void
        {
            activeSlideObject.stopDrag();
            stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
        }
    }
}

Write the name of one of the objects on slide in the input field and click the ‘Start Dragging’ button to… Well… Start dragging the object around. The name of the button is: ‘button’ the name of the highlight box is: ‘highlightBox’, the name of the caption is… Guess.

Get Adobe Flash player

Download the widget here!

Challenge: Can you drag the widget?

This entry was posted in Widgets and tagged , , , , , , . Bookmark the permalink.

14 Responses to Slip Sliding Away

  1. Pingback: Tweets that mention Slip Sliding Away | The Widget King -- Topsy.com

  2. Stanley says:

    Hi,
    this is a fantastic tool! One question though. I can manipulate x, y, scale, filters and many other properties of captions and buttons but I seeemingly cannot influence object VISIBILITY. When I use “mySlideObject.visible=false” (or “true”), the visibility remains as it was setup in the Captivate (by checking/unchecking the “visible” mark in the object properties).
    Before I start looking for workarounds (zero alpha, XY off the screen etc.), am I missing something?

    Many thanks in advance!

    • Tristan says:

      Yes, Captivate is indeed tied in closely with the visible value. Personally when I want to make a slide object invisible I set the alpha to 0. However, if you really want to keep with the visibility property, then try out this:

      parent.parent.SetVisible(false);

      This is the function that Captivate uses when it wants to show an hide the widget. Pass in true, and the widget will appear, pass in false and it will disappear.

      • Rob Linser says:

        I cannot get a graphic to hide or show. i use
        var slideCompletionGraphic = getSlideObjectByName(“complete_section_graphic_1″ );

        slideCompletionGraphic .visible = false; //does not work
        slideCompletionGraphic .alpha = 0; //kind of works… the graphic hides… but when i do slideCompletionGraphic .alpha = 100; it does not come back… i can move the objects x and y just fine… any thoughts?

        • Tristan says:

          Try calling hideItem() or hideitem() (The capitalization differs depending on what type of object you’ve got) on slideCompletionGraphic. If you want to show it later you can call showItem() or showitem().

  3. Vilu says:

    Hi, Tristan
    I am programming agnostic, only an instructional designer. I want to replace a background in the certificate widget (Captivate 5, windows) with a custom one, could you please guide me how to do that with what you suggest here?

    • Tristan says:

      Hi Vilu,

      Although the code for the Certificate widget is available in the Captivate source files, the widget was not built with WidgetFactory, so getSlideObjectByName() feature in the above article is not available.

      If you’re looking for a project to learn to program with then a certificate widget might be a little too complicated for that.

      Don’t worry though, a Certificate widget is on our ‘ToDo’ list.

  4. Majeed says:

    Hi,

    I need a code on how to reposition the closed caption using Actionscript 3.0. how to create or how to access the closed caption from widget. please help. thanks.

    • Tristan says:

      Hi Majeed,

      cpVariables.cpCC_mc should get you access to the closed captioning MovieClip. You can use the x and y properties of that object to change the position of the CC box.

      var closedCaptions:MovieClip = cpVariables.cpCC_mc;
      closedCaptions.x = 10;
      closedCaptions.y = 100;

  5. Jarad says:

    Hi Tristan,

    What would you recommend to access a text entry box on a slide to change its multi-line or restrict the number of characters it can hold?

    Thanks in advance!

    • Tristan says:

      Grabbing the Text Entry Box with getSlideObjectByName(), and then accessing its EditField_txt property should get you to the Text Entry Box’s TextField object. From there you can change it like you would a normal TextField object.

  6. Sajeela says:

    Hi Tristan,

    I’m pretty new to the whole Captivate thing and have problems with the TOC menu in Captivate 5.5. For some reason there is no multiline capability for the text! Am I missing something? Is there a widget for this?

    • Tristan says:

      Hi Sajeela,

      In ActionScript the programmer must specify that a text field has multiline capabilities, text fields do not come with multiline by default. However, most likely the reason why the TOC text fields are not multiline is because if they were, then some TOC items would be taller than others and different code would be needed to make each TOC chapter stack correctly. At this time I am not aware of any widget that changes this behaviour.

      Tristan,

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>