Client-Server event binding is what makes Raxan truly special. Imagine never having to write a single line of JavaScript code in order to receive an Ajax notification when a user clicked on a button. Imagine being able to bind your server-side event handler to just about any HTML tag inside your web page. The possibilities are endless when you realize that you have total control over every DOM element inside your client's web browser.
Sending data to and from the server requires very little or no JavaScript coding when an event is triggered within a browser. In fact, it is very straightforward to configure your web pages to receive an server-side event notifications from the client .
The simplest way to do this is to use the xt-bind extended attribute to listen to events being triggered from the client.
Usage:
xt-bind="type, callback, serialize, autoDisable, autoToggle"
Note: Comma separate CSS selectors (e.g .class1, .class2, .classN) are currently not supported when using the xt-bind attribute. They can however be used with the bind() method.
Usage Examples:
xt-bind="click, showDetails" - makes a synchronous call to the server
xt-bind="#click, showDetails" - makes an asynchronous call to the server
- The following will disable the current element, toggle the "#loader" element and serialize
- the all "form" elements before making an asynchronous post back to the server
xt-bind="#click,editUser,form,true,#loader"
Working example:
<?php
require_once('raxan/pdi/autostart.php');
class MyPage extends RaxanWebPage {
// callback function
protected function buttonClick($e) {
// select the #msg element and set html to hello world
$this->msg->html('Hello World');
}
}
?>
<form name="form1" action="" method="post">
<input id="mybutton" type="button" value="Click Me" xt-bind="click,buttonClick" />
<div id="msg" />
</form>
Event delegates are special events that are used to bind an event handler to a dynamic set of elements. This eliminates the need of having to individually bind each element to an event handler whenever the set is updated.
To do this you can use either the xt-delagate extended attribute or the
Usage:
xt-delegate="selector type, callback, serialize, autoDisable, autoToggle"
Note: See xt-bind for a descrition of the other parameters
Usage Example:
xt-delegate="a.edit click, editRecord" - delegates a.edit click event
Working Example:
<?php
require_once('raxan/pdi/autostart.php');
class NewPage extends RaxanWebPage {
protected function doSomething($e) {
$i = $e->intval(); // get the integer value for the event
$this->panel->text('You have clicked item #'.$i);
}
}
?>
<ul xt-delegate="li a click,doSomething">
<li><a href="#1">Item 1</a></li>
<li><a href="#2">Item 2</a></li>
<li><a href="#3">Item 3</a></li>
<li><a href="#4">Item 4</a></li>
</ul>
<div id="panel"></div>
The above will delegate the click event for all a.edit elements within for the current <ul> element. Newly added items that matches the a.edit selector item will be automatically bounded to the click event handler.
There are times when you will need to periodically update an element on a web page with content from the server without any user intervention. This task would normally require a developer write JavaScript code to periodically poll the server for updates.
Raxan eliminates the need to have to manage your own client-side updates with the xt-autoupdate extended attribute:
Usage:
xt-autoupdate = "true" - Default mode. Enable automatic updates during ajax calls
xt-autoupdate = "seconds, callback, repeat, serialize, autotoggle" - enable timeouts
Note: Setting xt-autoupdate="true" will automatically cause the element to be updated during ajax calls. This is similar to calling the updateClient() method.
Usage Examples:
xt-autoupdate = "true" - enable automatic updates during ajax calls
xt-autoupdate = "5000,update,true" - updates every 5 seconds (repeatedly)
- The following will asynchronously updates the element every
- 15 seconds (repeatedly) and toggles #loader during updates
xt-autoupdate = "#15000,update,true,,#loader"
Working Example:
<?php
require_once('raxan/pdi/autostart.php');
class NewPage extends RaxanWebPage {
protected function doSomething($e) {
$this->msgbox->text('A message from your server');
}
}
?>
<a href="#" xt-bind="#click,doSomething">Click Here</a>
<div id="msgbox" xt-autoupdate="true"></div>
It's possible to have the browser display your event response within a new window of frame. To do this, you can use the target or formtarget attribute to set the window where the results will be displayed when the user triggers an event.
Example:
<a href="#" target="_blank" xt-bind="click,popup">New Window</a>
<input type="button" name="button1" id="button1" value="New Window" formtarget="_blank" xt-bind="click,popup" />
<div target="_blank" xt-bind="click,popup">New Window</div>
Target values:
Note: Target window will only work for full-page events.
The bind() method provides you with more options when compared to the xt-bind attribute. With the bind() and delegate() method you can use various event callback options:
Bind Function name to event. Call a user-defined function. Example:
<?php
$this->button1->bind('click', 'My_Function_Name');
?>
Bind Page Method name to event. Call a method on the current page. Example:
<?php
$this->button1->bind('click', '.My_Page_Method');
?>
Event callbacks are handled directly from the Page controller. When you bind an event using '.callback' the framework will automatically look for the method on the page controller instance. In this case the method can be protected or public. The '.callback' format is only a shortcut to array($this, 'callback').
Bind Object method to event:
<?php
$this->button1->bind('click',array($object, 'method_name'));
?>
When binding an event to a method that's external to the page controller, you will have to use the array($object, 'method_name') format. In this case method_name() must be a public method since it will be called from the page controller.
Bind Anonymous functions to event. This only works on PHP 5.3 and higher:
<?php
$this->button1->bind('click',function($e){
// do something here
});
?>
The bind() method can be configured to submit selected form content to the server or hide/show elements before or after an event is triggered:
<?php
$this->button1->bind('#click',array(
'callback' => '.auto_search',
'autoDisable' => true, // disable the button during event call to server
'autoToggle' => 'img#pre', // show pre loader
'serialize' => 'form :input' // serialize and post form inputs back to the server
));
?>
As stated above, the delegate() method is similar to the bind() method with the exception that it takes an additional css selector as the first parameter:
<?php
// delegate the click event for all a.edit element within list1
$this->list1->delegate('a.edit', '#click', '.editRecord');
?>
Note: Event bindings must done before or during page load.
When the event handler is called, an instance of the RaxanWebPageEvent object is passed as the first parameter with the following properties:
Available methods:
When an event is trigger a value is submit to the event handler. This can be useful when you want to carry out an action based on the returned value.
To do this you can either assign the value when binding the event to the DOM element:
<?php
protected function _init() {
$this->button1->bind('click',array(
'callback'=>'.eventHandler',
'value' => '12345'
));
}
protected function eventHandler($e) {
// retrieve event value from the $e object
$value = $e->value();
// retrieve and sanitize event value
$value = $e->intVal();
/* do something here */
}
?>
Or set the value using one of the following methods:
If the element is an anchor tag, then add the value after the url "#" (hash):
<a href="#10" xt-bind="clic,changePage">Next Page</a>
If the element is a form element then the content of the "value" attribute will be sent back to the server as the event value
<select name="select1" id="select1" xt-bind="change,doSomething">
<option value="1">Item 1</option>
<option value="2">Item 2</option>
</select>
To set the event value on any element (including the above), you can use the "data-event-value" attribute or add the value to the "class" attribute. When using the class attribute you must first add the "v:" prefix to the value as shown below:
<button id="btn1"
class="v:12345"
xt-bind="click,showMessage">Submit</button>
Or use the data-event-value attribute as follows:
<button id="btn2"
data-event-value="12345"
xt-bind="click,showMessage">Show Message</button>
Note: Adding values to the class attribute has being deprecated. Use the data-event-value attribute.
In addition to the the data-event-value attribute there are two other attributes that can be assigned to an element:
data-event-view - This is used to determine the view to loaded when the server-side event is being triggered.
<button id="btn1"
data-event-view="page"
xt-bind="click,changeView" >Next Page</button>
data-event-confirm - This is used to display a confirmation dialog before then event is triggered.
<button id="btn1"
data-event-confirm="Are you sure you want to delete this records?"
xt-bind="click,deleteRow">Delete Record</button>
When the button is clicked, the value of the data-event-confirm attribute will be displayed as a confirmation popup before the request is sent to the server.
There are times when you need to create special events for a page in order to execute a specific task. To do this you can you the registerEvent() method.
The following will register an event for the current page and bind the event to a callback handler:
<?php
protected function _init() {
// registers a custom event
$this->registerEvent('custom-event','.myEventHandler');
}
?>
Note: Events must be registered before or during page load.
Server-side events can be triggered by using the framework's API, client-side scripts, form submits or hyperlinks.
Events can be triggered from a url or form by submitting special name/value pairs to the server via a POST or a GET method.
Here's a list of some of the name/value pairs that are used when making a GET request:
Before you can trigger the event from a url you will have to either 1) bind the event as a global event using the @global keyword or 2) pass a special token to the server along with the event request. Use the Raxan::$postBackToken property to retrieve the current token value.
Here's an example using @global:
<?php
class NewPage extends RaxanWebPage {
protected function _init() {
// register editorder event as a global event
$this->registerEvent('editorder@global','.editOrder');
}
protected function editOrder($e) {
$v = $e->intVal(); // get event value
/* do something here */
}
}
?>
<a href="order.php?_e[target]=page&_e[type]=editorder&_e[value]=1234">Click here</a>
The example above will register the editorder event as a global event so that it can be triggered from any url. This will also override the need for passing the token to the event.
Another solution is to let the framework handle the request gracefully. This is useful when JavaScript is not enabled inside the web browser:
<?php
protected function _config() {
$this->degradable = true; //enables degradable mode if JavaScript is not available
}
protected function _init() {
$this->button1->bind('click','.editOrder');
}
?>
<a id="button1" href="#1234">Edit Order</a>
In the above example, the framework will automatically generate the necessary code to trigger the event when JavaScript is not available.
Note: Raxan has a built-in security feature that helps to prevent Cross-Site Request Forgery (CSRF). Each event request must be accompanied with a valid token id. This token is unique to the user's active browser session and will be destroyed once the browser is closed. To bypass this security check you must append the @global to the event name when binding to or registering the event.
In addition to hyperlinks, you can programmatically trigger a server-side event by using either the Raxan.dispatchEvent() method or manually triggering the event on the browser's DOM element:
<script type="text/javascript">
function dispatchEventExamples() {
// manually trigger button1 click event
$('#button1').trigger('click'); // this will also trigger the click event on the server
// trigger button1 click event (normal post back)
Raxan.dispatchEvent({
type: 'click', // event name
target: 'button1' // target element
})
// explicitly trigger button1 click event via ajax
Raxan.dispatchEvent({
type: '#click', // event name
target: 'button1'
})
// implicitly trigger click event via ajax by adding a callback function
Raxan.dispatchEvent({
type: 'click', // event name
target: 'button1',
complete: function(result,success){
if (!success) return;
if (result=='ok') alert('Task completed');
}
})
// trigger button2 "click" event on another page
Raxan.dispatchEvent({
type: 'click', // event name
target: 'button2',
url: 'another-page.php' // page url where event is registered
})
// passing a value to the event
Raxan.dispatchEvent({
type: 'click', // event name
target: 'button1',
value: 'This is a messge from the browser',
complete: function(result,success){
if (!success) return;
// do something here
}
})
// serialize form elements
Raxan.dispatchEvent({
type: 'click', // event name
target: 'button1',
serialize: '#form1', // css selector
complete: function(result,success){
if (!success) {
// handle error
alert('Error while connecting to server');
return true; // let the Raxan know that we that the error was handled
}
// do something here
}
})
}
</script>
To trigger a custom (registered) event from the client, use the dispatchEvent() method as shown below:
<script type="text/javascript">
function dispatchEventExamples() {
// trigger "custom" event (normal post back)
Raxan.dispatchEvent('custom-event');
// implicitly trigger "custom" event via ajax by passing a callback function
Raxan.dispatchEvent('custom-event',function(result,success){
if (!success) return;
// do something
});
// passing a value to the custom event
Raxan.dispatchEvent('custom-event',value,function(result,success){
if (!success) return;
// do something
});
}
</script>
The dispatchEvent() method is primarily to use to invoke custom (registered) events. See Client-Server Introduction for more information.
It's possible to intercept and prevent a server-side event from being triggered by listening to special events on the target element. This feature can be useful when you need to perform an action before or after the event has been triggered.
To do this you can use one or more of the following client-side events:
This event is invoked before and after an event notification is sent to the server. This can be useful when you want to validate form data or toggle special pre-loader elements:
<script type="text/javascript">
Raxan.ready(function(){
$('#buton1').bind('togglecontent',function(e,mode){
if (mode=='on') { // before server-side event execution
var valid = true;
// code to validate form data
if (!valid) return false; // return false to cancel event execution
// show pre-loader
$('#preloader').show();
}
else if (mode=='off') { // after server-side event execution
// hide pre-loader
$('#preloader').hide();
// get data returned from server-side event handler
var result = e.serverResult;
// do something with result
}
})
})
</script>
Note: If the "autotoggle" selector option or parameter was assigned to the element on the server, then the "autotoggle" elements will be toggled before this event is invokded.
This event is invoked before and after an event notification is sent to the server.
<script type="text/javascript">
Raxan.ready(function(){
$('#buton1').bind('disablecontent',function(e,mode){
if (mode=='on') { // before server-side event execution
var valid = true;
// code to validate form data
if (!valid) return false; // return false to cancel event execution
// disable form elements
$('#form :input').attr('disabled','disabled');
}
else if (mode=='off') { // after server-side event execution
// enable form elements
$('#form :input').removeAttr('disabled');
// get data returned from server-side event handler
var result = e.serverResult;
// do something with result
}
})
})
</script>
Note: If the "autodisable" selector option or parameter was assigned to the element on the server, then the "autodisable" elements will be disabled/enabled before this event is invokded.
This event is invoked before an event notification is sent to the server. The event handler must return a 2D array containing data to be submitted to the server.
<script type="text/javascript">
Raxan.ready(function(){
$('#buton1').bind('serializecontent',function(e){
var data = $('#form').serializeArray();
// add additional data to be submitted to server
data[data.length] = {name:'any-name', value:'any-value'}
return data;
})
})
</script>
Note: If the "serialize" selector option or parameter was assigned to the element on the server, then the data from the "serialize" elements will be merged with data returned from the serializecontent event.
Up Next: Server-Side Templates