Scroll

Modules, part 1: Vertical Menu

What is module? 


Modules are the elements of Moto websites that have the internal logic, properties and their own Control Panel. Modules may use the files to save the data or the services to work with databases, etc... These characteristics differ them from all other objects including slots.

The sample modules are Info modules (news, articles, RSS, etc...). Rich content modules (modules that include the number of objects or other modules), Gallery Modules, Music Player, Form Management Module, Media Player, etc...

Moto CMS has built-in and external Modules. Built-in Modules do not require loading and appear on the page right away. External Module is represented by the separate file that loads on the page in a runtime.

There are two types of the Modules - system and non-system. System modules do not have Control Panels - Menu and Rich content module. The other modules have Control Panels loading into Moto CMS Control Panel when being edited.

Also modules fall under Content and Non-Content ones. Content modules are displayed in the Quick Content editing window, e.g. news, galleries, music player. Media player is an example of Non-content module. This option is to be defined by the developer of the template and depends on the requirements of the client.

Vertical Menu

Step 1: Creating MainMenu class

We create a new layer in the website.fla and make it Guide. It is a temporary layer used only for the process of creating the module. When the module is created, we'll delete the layer and its content - everything necessary will be in the library.

1_layer.png


Let's draw some rectangle with Shape tool.

2_shape.png


Then we convert this shape to a Movie Clip. Let's name it MainMenu.

3_convert_to_movieclip.png


Inside of this Movie Clip we convert the shape once more - it will be the button holder. Let's name it menuHolder.

4_convert_once_more.png


and give it the same instance name.

5_instance_name.png


Then we delete a shape inside of the menuHolder Movie Clip. In the MainMenu Movie Clip we create a new layer and add the Menu Module Preview component from the library.

6_menu_preview.png


6_menu_preview2.png


We do it to make the menu visible without or with the empty data provider. We put it in the zero coordinates and give it an instance name preview.

7_instance_name.png


Let's move the MainMenu Movie Clip to the Modules folder in the library. Also we create a folder named MainMenu Assetsand place the menuHolder MovieClip there.

8_library.png


Now let's set the linkage properties for the MainMenu Movie Clip. Class: MainMenu, Base Class: modules.MainMenu.

10_mainMenu_linkage.png


As the class is not created, an error may appear. So, let's create a class with this name (MainMenu) in the modules package. We inherit DynamicMotoMenu for this class:

com.moto.template.modules.menu.DynamicMotoMenu.

package modules 
{
    import com.moto.template.modules.menu.DynamicMotoMenu;
 
    public class MainMenu extends DynamicMotoMenu
    {
 
        public function MainMenu() 
        {
            super();
 
        }
 
    }
 
}

Now let's open the structure.xml and describe the menu with the help of this block in the <modules> section:

        <module id="5" type="dynamicMenu"   librarySymbolLinkage="MainMenu" resizable="false"   smallIcon="images/modules/menu_small_icon.png"   icon="images/modules/menu_icon.png">
            <name><![CDATA[Main menu]]></name>
            <template alpha="1" width="200" height="52">
                <data>
                    <menu/>
                    <itemRenderer>MainMenuItemRenderer</itemRenderer>
                    <dropDown>false</dropDown>                    
                </data>
            </template>
        </module>

librarySymbolLinkage="MainMenu" - the linkage name of the MainMenu Movie Clip.
resizable="false" - states whether there is the logic of resizing; we set it false because it won't be resized manually at the beginning, the size will be set atomatically.
<itemRenderer>MainMenuItemRenderer</itemRenderer> - an item of menu button visualization.
<dropDown>false</dropDown> - states whether there is the dropdown submenu; we set it false because we won't use it yet.
  
 

Step 2: Creating MainMenuItemRenderer class

Let's create the item renderer. We create a shape, convert it to a Movie Clip. Name and the Class name will be the same: MainMenuItemRenderer. Base class: modules.MainMenuItemRenderer.

11_item_renderer.png


Now we have to create a class for this renderer in the modules package. It will be inherited from AbstractMenuItemRenderer:

Base class:com.moto.template.modules.menu.AbstractMenuItemRen derer.

package modules 
{
    import com.moto.template.modules.menu.AbstractMenuItemRenderer;
 
    public class MainMenuItemRenderer extends AbstractMenuItemRenderer
    {
 
        public function MainMenuItemRenderer() 
        {
            super();
 
        }    
 
    }
 
}

Then we go inside of the MainMenuItemRenderer Movie Clip, delete shape and create a text field there. We make it single line, set zero coordinates and give an instance name: _txt.

12_label.png


In our example it will be placed just in a Movie Clip, but for making a more advanced animation it should be placed in a holder.

Important: do not embed fonts!
It's better to set Tahoma font by default - other formatting will be made by html.

We move the MainMenuItemRendererMovie Clip to the MainMenuAssets folder.

13_move_to_folder.png
 
   
 

Step 3: Creating the basic code

 

We have to inherit the MovieClip class for both classes that we have created so that the menu is displayed right:

import flash.display.MovieClip;

Also, as the text field is not converted into the Movie Clip, we have to inherit the TextField class for the MainMenuItemRenderer class:

import flash.text.TextField;

Now we should add an error handler to the MainMenu class constructor. The event of successful initialization:

addEventListener(INITIALIZATION_COMPLETE, _initializationHandler);

And the event of initialization error:

addEventListener(INITIALIZATION_ERROR, _initializationHandler);

        public function MainMenu() 
        {
            super();
 
            addEventListener(INITIALIZATION_COMPLETE, _initializationHandler);
            addEventListener(INITIALIZATION_ERROR, _initializationHandler);
        }

Then we add a method of event handling. We will handle both events in one method with the switch by the event type.

        private function _initializationHandler(event:Event):void
        {
            switch (event.type)
            {
                case INITIALIZATION_COMPLETE:                
 
                    break;                    
 
                case INITIALIZATION_ERROR:
 
                    break;
            }
        }

Also it can be done with two different methods.

It's also necessary to inherit the Event class:

import flash.events.Event;

As we have added a preview to our module, we should make it invisible when there is a data provider.
Let's take the elements by their instance names and assign the new variables to them:

 
     public class MainMenu extends DynamicMotoMenu
    {
        private var _preview:MovieClip;
        private var _menuHolder:MovieClip;
 
        public function MainMenu() 
        {
            super();
 
            _preview = this["preview"];
            _menuHolder = this["menuHolder"];

And we have to specify the holder for menu elements:

itemsArranger.target = _menuHolder;

        public function MainMenu() 
        {
            super();
 
            _preview = this["preview"];
            _menuHolder = this["menuHolder"];
 
            addEventListener(INITIALIZATION_COMPLETE, _initializationHandler);
            addEventListener(INITIALIZATION_ERROR, _initializationHandler);
 
            itemsArranger.target = _menuHolder;
        }

In case of initialization error we set:

                case INITIALIZATION_ERROR:
                    _preview.visible = limitedMode;
                    break;

limitedMode states where the module is loaded - in the control panel or in the template. If it's loaded in the control panel limitedMode=true, in the template limitedMode=false. So, if you add a module to the stage and don't fill it with any data, it won't be displayed on the site.

In case of successful initialization we handle the preview visibility too:

                case INITIALIZATION_COMPLETE:                
                    _preview.visible = (menuItemsData.length || !limitedMode)?false:true;
                    break;

menuItemsData is a list of buttons, without rendering.

The MainMenu class that we have at this stage:

package modules 
{
    import com.moto.template.modules.menu.DynamicMotoMenu;
    import flash.display.MovieClip;
    import flash.events.Event;
 
    public class MainMenu extends DynamicMotoMenu
    {
        private var _preview:MovieClip;
        private var _menuHolder:MovieClip;
 
        public function MainMenu() 
        {
            super();
 
            _preview = this["preview"];
            _menuHolder = this["menuHolder"];
 
            addEventListener(INITIALIZATION_COMPLETE, _initializationHandler);
            addEventListener(INITIALIZATION_ERROR, _initializationHandler);
 
            itemsArranger.target = _menuHolder;
        }
 
        private function _initializationHandler(event:Event):void
        {
            switch (event.type)
            {
                case INITIALIZATION_COMPLETE:                
 
                    //Hide preview
                    _preview.visible = (menuItemsData.length || !limitedMode)?false:true;
                    setSize(width, height);
                    break;                    
 
                case INITIALIZATION_ERROR:
 
                    // Show menu in the control panel
                    _preview.visible = limitedMode;
                    break;
            }
        }
    }
}

And the MainMenuItemRenderer class:

package modules 
{
    import com.moto.template.modules.menu.AbstractMenuItemRenderer;
    import flash.display.MovieClip;
    import flash.text.TextField;
 
    public class MainMenuItemRenderer extends AbstractMenuItemRenderer
    {
 
        public function MainMenuItemRenderer() 
        {
            super();
 
        }    
 
    }
 
}

Now we can compile our project.
      

Step 4: Vertical arrangement of items

We see that our buttons are arranged in a row by default, but we can arrange it another way. We add to the MainMenu class constructor:

itemsArranger.orientation = OrientationEnum.COLUMNS;

You can also set OrientationEnum.ROWS (it's the default value) to make the horizontal menu. But we make a vertical menu so we set OrientationEnum.COLUMNS.

It's necessary to import OrientationEnum:

import com.moto.template.common.view.OrientationEnum;

Also we can set the interval between the buttons.

itemsArranger.verticalSpacing = 10;

Also you can set

itemsArranger.horizontalSpacing = 10;

instead of verticalSpacing if you create the horizontal menu. We set verticalSpacing because we make the vertical menu.
The spacing is set depending on the design. We set 10 for the test.

Now the MainMenu class constructor will be:

        public function MainMenu() 
        {
            super();
 
            _preview = this["preview"];
            _menuHolder = this["menuHolder"];
 
            addEventListener(INITIALIZATION_COMPLETE, _initializationHandler);
            addEventListener(INITIALIZATION_ERROR, _initializationHandler);
 
            itemsArranger.orientation = OrientationEnum.COLUMNS;
            itemsArranger.verticalSpacing = 10;
            itemsArranger.target = _menuHolder;
        }

When we compile the project we will see that the buttons are arranged in the column now with a spacing equal 10 pixels.

5.png
   
 

Step 5: Making the correct labels display

we also can notice that the button labels don't conform to labels that we have set in the control panel. So now we will make the data display in the button. For this we have to override the updateRenderer method in the MainMenuItemRenderer class. It's necessary to call super().

        override public function updateRenderer(data:Object):void 
        {
            super.updateRenderer(data);
 
        }

We create a new variable

private var _textField:TextField;

and with its help we refer to the button's text field (in the MainMenuItemRenderer class constructor):

_textField = this ["_txt"];

Also we set auto size for the text field with the left alignment of the text:

_textField.autoSize = TextFieldAutoSize.LEFT;

        private var _textField:TextField;
 
        public function MainMenuItemRenderer() 
        {
            super();
            _textField = this["_txt"];
            _textField.autoSize = TextFieldAutoSize.LEFT;
        }

We shouldn't forget to import TextFieldAutoSize:

import flash.text.TextFieldAutoSize;

Then we have to get the labels (Label1, Label2 etc.) that are set in the control panel. We get property from the object and convert it to String (in the updateRenderer method):

_textField.htmlText = menuItemVO.getPropertyValueByID(1);

Value is the button label that we set in the control panel - Label1, Label2 etc. The property ID is its number in the property list. Label is the default property with ID=1.

And then we get the "embedFonts" parameter from the object of the same property and convert it to Boolean to verify whether the fonts are embedded for this field:

_textField.embedFonts = MotoUtils.convertToBoolean(menuItemVO.getPropertyB yID(1).getParameter("embedFonts"));

        override public function updateRenderer(data:Object):void 
        {
            super.updateRenderer(data);
 
            _textField.htmlText = String(menuItemVO.getPropertyValueByID(1));
            _textField.embedFonts = MotoUtils.convertToBoolean(menuItemVO.getPropertyByID(1).getParameter("embedFonts"));
        }

We should import the MotoUtils class:

import com.moto.template.common.utils.MotoUtils;

Now we can compile the project and see that the menu buttons are labeled as we set in the control panel:

6.png

The MainMenu class that we have at the moment:

package modules 
{
    import com.moto.template.common.view.OrientationEnum;
    import com.moto.template.modules.menu.DynamicMotoMenu;
    import flash.display.MovieClip;
    import flash.events.Event;
 
    public class MainMenu extends DynamicMotoMenu
    {
        private var _preview:MovieClip;
        private var _menuHolder:MovieClip;
 
        public function MainMenu() 
        {
            super();
 
            _preview = this["preview"];
            _menuHolder = this["menuHolder"];
 
            addEventListener(INITIALIZATION_COMPLETE, _initializationHandler);
            addEventListener(INITIALIZATION_ERROR, _initializationHandler);
 
            itemsArranger.orientation = OrientationEnum.COLUMNS;
            itemsArranger.verticalSpacing = 10;
        }
 
        private function _initializationHandler(event:Event):void
        {
            switch (event.type)
            {
                case INITIALIZATION_COMPLETE:                
 
                    //Hide preview
                    _preview.visible = (menuItemsData.length || !limitedMode)?false:true;
                    setSize(width, height);
                    break;                    
 
                case INITIALIZATION_ERROR:
 
                    // Show menu in the control panel
                    _preview.visible = limitedMode;
                    break;
            }
        }
    }
}

and the MainMenuItemRenderer class:

package modules 
{
    import com.moto.template.common.utils.MotoUtils;
    import com.moto.template.modules.menu.AbstractMenuItemRenderer;
    import flash.display.MovieClip;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
 
    public class MainMenuItemRenderer extends AbstractMenuItemRenderer
    {
        private var _textField:TextField;
 
        public function MainMenuItemRenderer() 
        {
            super();
            _textField = this["_txt"];
            _textField.autoSize = TextFieldAutoSize.LEFT;
        }    
 
        override public function updateRenderer(data:Object):void 
        {
            super.updateRenderer(data);
 
            _textField.htmlText = String(menuItemVO.getPropertyValueByID(1));
            _textField.embedFonts = MotoUtils.convertToBoolean(menuItemVO.getPropertyByID(1).getParameter("embedFonts"));
        }
 
    }
 
}
Have more questions? Submit a request

Comments