tmVisualControlsPlugin
Overview
This plugin wraps up tag helper functions as control objects, so that they can be painted in a template. Event listeners can be attached to these controls, to handle events on the server or to produce unobtrusive javascript which handles events on the client browser. In the particular case, where an ajax event listener is attached to a control, javascript is generated to post data back to a server. The tmAjax module processes the incoming request and produces a response for any changes made to the controls on the page.
The page manager and mediator classes are important concepts in this plugin. A control must be associated with only one mediator. A mediator collects controls together with a common purpose and provides each control with a unique id across the web page. A mediator must be associated with only one page manager. The page manager (singleton design pattern) is responsible for storing each mediator's data in the session. Ajax requests are handled by the web page manager, which retrieves the named mediator from the session and dispatches the named event for the named control.
The objective of this plugin is to enable the developer to focus on writing php event handlers which deal with the objects in the model of the web application, rather than creating a multitude of partial templates to support ajax interactions.
This plugin has been designed with flexibility in mind, so that others will be inspired to extend the number of control classes. An implementation of controls for the Yahoo YUI would be a nice addition.
Javascript patch
This plugin requires prototype.js and json.js to work. However, json.js causes a problem with prototype 1.5.0, unless you add a conditional statement at line 915 in prototype.js as follows
for (var name in headers)
+ if (typeof headers[name] != 'function')
this.transport.setRequestHeader(name, headers[name]);
Installation
To install the plugin for a symfony project, the usual process is to use the symfony command line:
$ php symfony plugin-install http://plugins.symfony-project.com/tmVisualControlsPlugin
Alternatively, if you don't have PEAR installed, you can download the latest package attached to this plugin's wiki page and extract it under your project's plugins/ directory.
Enable the tmAjax module in your settings.yml
all:
.settings:
enabled_modules: [tmAjax](default,)
Enable the visual controls filter in filters.yml
# generally, you will want to insert your own filters here
visualcontrols:
class: tmVisualControlsFilter
Clear the cache
symfony cc
Optionally add the following rule to routing.yml
tm_visual_controls_ajax:
url: /ajax
param: {module: tmAjax, action: callback}
You can customize the url parameter of the route.
The default route is automatically registered by the plugin, when the tmAjax module is enabled.
Customise some script and session variables in app.yml (optional)
all:
tm_visual_controls_plugin:
file: %sEventHandler.php
namespace : visual/controls/plugin
ajax_function: handleAjaxEvent
mediator_property: mediator
You're done. Now you can play with some examples.
Examples
These examples only utilise the tmButton control, but you can experiment with the other controls in lib/controls/tmStandard.php and lib/controls/tmExtended.php. The paint() method permits a control's html to be output anywhere in a template in a similar manner to a tag helper function.
Simple Example
For a simple "hello world" example, where a message box is displayed when the user clicks a button, create a new ajax module and an example action. Put the following code in the exampleSuccess template :
<?php
$manager=tmWebPageManager::getInstance(sfContext::getInstance()->getUser());
$mediator=new tmWebMediator('main_mediator',$manager);
$button=new tmButton('button_one',$mediator,'click me');
$handler=new tmMessageEventHandler('','"Hello World"');
$listener=new tmJavascriptEventListener(tmClientEventListener::CLICK,$handler);
$button->addListener($listener);
echo $button->paint();
View the page in your favourite web browser and click the button.
Ajax Example
The example above can be altered to make the button call back to the server. In this case, you need to create an ajax event listener, which requires both a client event handler and a server event handler.
<?php
$manager=tmWebPageManager::getInstance(sfContext::getInstance()->getUser());
$mediator=new tmWebMediator('main_mediator',$manager);
$button=new tmButton('button_one',$mediator,'click me');
$clientHandler=new tmAjaxEventHandler($manager);
$serverHandler=new tmServerEventHandlerForContext(sfContext::getInstance(),'handleClick');
$listener=new tmAjaxEventListener(tmClientEventListener::CLICK,$clientHandler,$serverHandler);
$button->addListener($listener);
echo $button->paint();
Next you need to create the file /modules/ajax/lib/exampleEventHandler.php to define the server function handleClick.
<?php
function handleClick($ASender, &$AParameterArray)
{
$red = rand(0, 255);
$green = rand(0, 255);
$blue = rand(0, 255);
$ASender->setStyle('background-color',sprintf('#%X%X%X',$red,$green,$blue));
$ASender->setCaption(date(DATE_RSS));
}
So, just by introducing an ajax listener and implementing the server event handler, you've got a working client/server application that randomly changes the button's colour when clicked.
There's nothing to stop you attaching both listeners to the same button. Try it!
Finally, you can pass additional arguments to tmAjaxEventHandler::__construct() to tell the browser to execute custom javascripts on loading/completing the ajax request, and specify whether the request 'gets' or 'posts' back to the server.
TODO
- add validators
- connect controls to model object properties
Changelog
1.0.0
- Remove dependence on json.php
- Allow image control to output raw url as source
- Ajax events need hard coded lib directory. Ajax routing now configured by router onload event.
- Branch from 1.0.2