Events and Listeners

  • Overview

    JR5 has a concept loosely titled 'events and listeners'.

    When a module creator feels like a point is reached in their code where the data accumulated can be safely altered without breaking their module, the module creator can choose to put in an 'event'.

    By doing this they are essentially saying "Hey world, if anyone wants to change or add anything in here, nows your chance."

    Other modules can then listen for this event to happen and receive the data, alter it, then give it back.
  • Firing an event

    Perhaps an easy way to understand it is to look at an example. This example is from the jrEmbed module.

    The jrEmbed module allows any other modules to add their stuff into the text editor for the members of the site to use.

    eg: the jrEmbed module allows the jrAudio module to make audio files available to be put into anywhere the tinyMCE text editor is used.

    * same for video (via the jrVideo module)
    * same for images (via the jrGallery module)
    ......

    It does this with events and listeners.

    The following piece of code is from the jrEmbed module at the point where its firing the event:
    // Get tabs from active modules
    
    $_data = array(
        'tabs'           => array(),
        'ready_function' => ''
    );
    $_data['tabs'] = jrCore_trigger_event('jrEmbed', 'tinymce_popup', $_data['tabs']);
  • What is happening there is:
    * first an empty array is created
    * that empty array is passed out with the event 'tinymce_popup'
    * modules that want to opt-in to adding that functionality to the tinymce editor, set a listener.
    * when the array arrives back at the end of the function its full with modules that want to put tabs in to the editor.

    jrEmbed now has an array that was empty but is now full. It uses that array full of modules to add each module to system.

    The result of that empty array being passed around allows jrEmbed to construct this popup:
  • screenshot of all the modules that have a jrEmbed listener
  • Registering an event

    If your module is going to fire an event, it needs to register it.

    This is done in you modules _init() function in the include.php file (see 'Creating a Module' for more info)

    The registration code the jrEmbed_init() function looks like this
    /**
     * init
     */
    function jrEmbed_init()
    {
    
        //allow other modules to define tabs on the jamroom tinymce media popup
    
        jrCore_register_event_trigger('jrEmbed', 'tinymce_popup', 'Fired in the tinymce popup to allow modules to define tabs for media insertion');
        jrCore_register_event_trigger('jrEmbed', 'output_html', 'Fired from the jrEmbed_embed modifier in templates. Modules should replace their tag with actual media.');
    
    //...other stuff
    
    }
    
  • You can see in the function above that there are 2 registered events. The first one has the description 'Fired in the tinymce popup to allow modules to define tabs for media insertion', and that is the one that we see in the code a few blocks above.

    The second one is fired when the actual output of html is displayed to the user viewing the screen.

    So the jrEmbed module:
    * first fires an event to get all the tabs to embed stuff from modules.
    * second fires an event to get the stuff the modules have embedded.
  • Listening for an Event

    Listening for an event is also done by registering it in your modules _init() function.

    Below is the code from the jrAudio modules _init() function.

    We can see that it registers a listener for both of the events that the jrEmbed module fires:
    /**
     * init
     */
    function jrAudio_init()
    {
        //listen for jrEmbed
    
        jrCore_register_event_listener('jrEmbed','tinymce_popup','jrAudio_tinymce_popup_listener');
        jrCore_register_event_listener('jrEmbed','output_html','jrAudio_output_html_listener');
    
    //...other stuff
    
    }
  • The third parameter in the functions is the name of the function to fire when this event happens.

    So in the case of the 'tinymce_popup' event, the jrAudio module wants to fire the jrAudio_tinymce_popup_listener() function.

    The default naming convention is (your module name)_(event name)_listener although you can call your function whatever you want.

    When a listener comes in with data it should be setup with these parameters:
    function jrAudio_tinymce_popup_listener($_data,$_user,$_conf,$_args,$event)
    {
        //do your stuff.......
    
    
        //then return the data
    
        return $_data;
    }
  • You will be able to access all the data in the arrays that come in.

    This is what they are all for:
    $_data //is the array that the event sent out
    $_user //is the user looking at the screen
    $_conf //is the global configuration array
    $_args //is extra data that the listener doesn't want back but could be useful.
    $event //(string) the name of the event firing.

    Use the available data to do what you need to do, then return the $_data array ( Very important! )
  • If you do not return the $_data array, things will break!
  • What code to add?

    Since every module is doing something differently, what comes in on the $_data array will be different in each case.

    So what you need to add or change will be different in each case.

    Probably the first step is to check out the modules docs to see how it wants additions added (if its specifically asking for additions like the jrEmbed module does).

    Otherwise look at other modules also listening for the same event and see how they are setup.

    The way I like to do it is to setup my listener, and create the function that fires with just an empty structure and return the $_data.

    Then set a break point in my debugger on the
    return $_data;

    and make the function fire.

    This will show me what I have to work with.

    (see 'setting up a debugging environment' for more details)
  • An Example in action

    youtube
    A video of 2 modules being built that show 'Events' and 'Listeners' in use

Tags