Tutorial: Object Oriented Website Programming the Xajax Way

Introduction:


Before we get started, there are a few things you should know about this tutorial.

1) It is intended to show the basic layout of a xajax version 0.5 enabled script as well
    as some of the new features available in xajax 0.5
2) It is not intended to teach the basics of using PHP, nor is it intended to be an
    introduction to xajax.
3) The layout / format of the code examples may, at first, appear to be unusual; however,
    this is because the code samples you are seeing are extracted directly from the source
    of this page. You are not reading a copy of the code, but in fact, the actual code
    used in this page.
4) Some of the design concepts shown below may be foreign to PHP developers who are
    used to writing HTML by hand. This tutorial uses object oriented programming techniques
    that produce HTML via a collection of control objects.
    

Typical xajax startup:

xajax is a collection of php and javascript classes that work together to provide remote procedure call style functionality between the php server and javascript enabled browser. The setup is straightforward, simply include the php code at the top of your php script, instantiate the xajax object, configure, register the functions you want available and then call xajax to process the request. xajax will determine if the request is for the initial page (HTML) or a request to execute one of the registered functions and take appropriate action.

include('../xajax_setup.php');



Register functions to be called asynchronously:

For security reasons, it is best to expose only those functions which are needed by the page. Each of these functions will need to return a xajaxResponse object. The xajaxResponse object will contain response commands that will be executed by the javascript library on the browser.

$requestGetTime = $xajax->register(XAJAX_FUNCTION, 'getTime');

$requestOnSelect = $xajax->register(XAJAX_FUNCTION, 'onSelect');

$requestOnSubmit = $xajax->register(XAJAX_EVENT, 'onSubmit');
$xajax->register(XAJAX_EVENT_HANDLER, 'onSubmit', 'validateInput');
$xajax->register(XAJAX_EVENT_HANDLER, 'onSubmit', 'saveData');

$requestShowTable = $xajax->register(XAJAX_FUNCTION, 'showTable');

// Note: $requestGetTime, $requestOnSelect and $requestOnSubmit will be explained
// later.

Process request if necessary:

This is where the real 'magic' occurs... xajax takes care of business. Everything prior to this line will be executed each time the script is called, whether it is a request for the initial page or for a xajax enabled function request. The code after this function is only called when the initial page is loaded. Note, however, that registered functions CAN be declared after the processRequest statement and php will still find them and execute them when a xajax request is processed.
$xajax->processRequest();

HTML control library:

The xajax HTML control library is a collection of PHP classes which can be used to construct a segment or entire page of HTML. The library contains (or soon will contain) a control for each HTML tag. In addition, classes can be built to produce common sequences of tags, so that the sequence can be easily reused from page to page or even within the same page. Sophisticated controls, requiring both HTML and Javascript support, can employ xajax plugins to handle the coordination between the server and client sides. The clsDocument class is the root container of a page. It contains a single clsDocType object as well as a single clsHTML object. The clsDocType object is used to define the HTML or XHTML version that is to be used for this document. The clsHTML object contains the markup for the page itself. The clsHead object should contain a reference to the main $xajax object, which is used to output the xajax core javascript. The clsHead can also contain any number of clsStyle and clsScript objects as well as a single clsTitle object. The clsBody object can contain any number of control objects. Each control has the ability to validate it's attributes and children tags. Many controls already contain validation code to help detect common coding errors. By catching these errors early and providing detailed error information, the control library helps the xajax programmer spend less time tracking down errors.
//include $sCoreFolder . '/xajaxControl.inc.php';
//
//$sControlsFolder = dirname(__FILE__) . '/xajax_controls';
//
//// for this document, we will use the following controls
//$aControls = array(
//    '/document.inc.php',
//    '/doctype.inc.php',
//    '/html.inc.php',
//    '/head.inc.php',
//    '/body.inc.php',
//    '/break.inc.php',
//    '/div.inc.php',
//    '/literal.inc.php',
//    '/label.inc.php',
//    '/anchor.inc.php',
//    '/select.inc.php',
//    '/form.inc.php',
//    '/input.inc.php'
//    );
    
//foreach ($aControls as $sControl)
//    include $sControlsFolder . $sControl;

Output the initial HTML for the page:

While this method appears to involve more code than simply typing out the HTML directly, there are many benefits that will be realized upon further inspection. First, by generating the HTML in a controlled, object oriented manner, the control library has the opportunity to validate the structure and attributes of the output. In addition, the control library attempts to format the output so it is more readable and easier to debug. Last, complex control sequences can be constructed once, then reused in a variety of places without having to copy, paste and modify the HTML (which is cumbersome and more error prone). An entire page of HTML with supporting javascript (aka xajax requests) can be generated using the xajax HTML control library as shown here.
$objDocument = new clsDocument(array(
    'children' => array(
        new clsDocType('HTML', '4.01', 'STRICT'),
        new clsHTML(array(
            'children' => array(
                new clsHead(array(
                    'xajax' => $xajax,
                    'child' => new clsStyle(array(
                        'attributes' => array(
                            'type' => 'text/css'
                            ),
                        'children' => $aStyle
                        ))
                    )),
                new clsBody(array(
                    'children' => $aSections
                    ))
                )
            ))
        )
    ));


$objContent =array();

$objContent=  $aSections;


include("../layout.inc.php");

//$objDocument->printHTML();

The anchor control (aka Link):

Now, let us construct a control, assign a xajax request to it's onclick event and try it out. Earlier, a xajax function was registered, which produced a xajaxRequest object: $requestGetTime = $xajax->register(XAJAX_FUNCTION, 'getTime'); Now, we will construct an Anchor control, assign our xajaxRequest object to the Anchor's onclick event and place the Anchor control in the heirarchy of the page. A DIV control is also constructed in a similar manner and placed directly after the Anchor control. These controls will be rendered to the browser when the Document object is printed (shown above).
    new clsAnchor(array(
        'event' => array('onclick', $requestGetTime, array(
            array(0, XAJAX_QUOTED_VALUE, 'anchor_output')
            )),
        'child' => new clsLiteral('Show time()')
        )),
    new clsDiv(array(
        'attributes' => array(
            'id' => 'anchor_output'
            )
        ))
function getTime($sDestination)
{
    $objResponse = new xajaxResponse();
    
    $sTime = time();
    $objResponse->assign($sDestination, 'innerHTML', $sTime);

    return $objResponse;
}

Select and Option controls:

In the following example, a SELECT control is constructed and populated with three OPTION controls. An event is linked up and two parameters are specified. The first parameter will send the value of the SELECT control. The second parameter is the name of the control to receive the output from the function. In fact, the second parameter is simply the ID of the control where the data will be put. The function will generate a response command, instructing xajax where to put the data, and the data itself.
    new clsSelect(array(
        'attributes' => array(
            'id' => 'input_select'
            ),
        'event' => array('onchange', $requestOnSelect, array(
            array(0, XAJAX_INPUT_VALUE, 'input_select'),
            array(1, XAJAX_QUOTED_VALUE, 'select_output')
            )),
        'children' => array(
            new clsOption(array(
                'attributes' => array('value' => ''),
                'child' => new clsLiteral('- choose an option -')
                )),
            new clsOption(array(
                'attributes' => array('value' => 'One'),
                'child' => new clsLiteral('One')
                )),
            new clsOption(array(
                'attributes' => array('value' => 'Two'),
                'child' => new clsLiteral('Two')
                )),
            new clsOption(array(
                'attributes' => array('value' => 'Three'),
                'child' => new clsLiteral('Three')
                ))
            )
        )),
    new clsDiv(array(
        'attributes' => array(
            'id' => 'select_output'
            )
        ))
function onSelect($sSelect, $sDestination)
{
    $objResponse = new xajaxResponse();
    
    $objResponse->assign($sDestination, 'innerHTML', 'You selected: ' . $sSelect);

    return $objResponse;
}

Building forms:

Below, I've included the script that generates the following form. First, you'll notice the parent DIV that will contain the form and form elements. Next, we include the form as a child of the DIV; other controls could follow the form, however, in this example, the form is the only child. The form is given the ID attribute value of 'tutorial_2d_form' which will be used as a parameter to the $requestOnSubmit. Using a special parameter type XAJAX_FORM_VALUES, we can specify that all the form elements should be sent as an array to our xajax enabled function. In this example, I also send a string value 'tutorial_2d_output' which is the ID of the DIV that is to receive the output from the onSubmit function that will be called when the user clicks the submit button at the end of the form. A variety of INPUT controls are shown for example.
    new clsForm(array(
        'attributes' => array(
            'id' => 'forms_form'
            ),
        'event' => array('onsubmit', $requestOnSubmit, array(
            array(0, XAJAX_FORM_VALUES, 'forms_form'),
            array(1, XAJAX_QUOTED_VALUE, 'forms_output')
            )),
        'children' => array(
            new clsDiv(array(
                'child' => new clsInputWithLabel('Text: ', 'left', array(
                    'attributes' => array(
                        'type' => 'text',
                        'id' => 'input_text',
                        'name' => 'input_text',
                        'value' => 'Some text value'
                        )
                    ))
                )),
            new clsDiv(array(
                'child' => new clsInputWithLabel('Checkbox ', 'right', array(
                    'attributes' => array(
                        'type' => 'checkbox',
                        'id' => 'input_checkbox',
                        'name' => 'input_checkbox'
                        )
                    ))
                )),
            new clsDiv(array(
                'children' => array(
                    new clsLiteral('Radio: '),
                    new clsInputWithLabel('Yes ', 'right', array(
                        'attributes' => array(
                            'type' => 'radio',
                            'id' => 'input_radio_yes',
                            'name' => 'input_radio',
                            'value' => 'yes'
                            )
                        )),
                    new clsInputWithLabel('No ', 'right', array(
                        'attributes' => array(
                            'type' => 'radio',
                            'id' => 'input_radio_no',
                            'name' => 'input_radio',
                            'value' => 'no'
                            )
                        ))
                    )
                )),
            new clsDiv(array(
                'child' => new clsInput(array(
                    'attributes' => array(
                        'type' => 'submit',
                        'id' => 'input_submit',
                        'name' => 'input_submit',
                        'value' => 'Send Form'
                        )
                    ))
                ))
            )
        )),
    new clsDiv(array(
        'attributes' => array(
            'id' => 'forms_output'
            )
        ))
Radio:
$bValidated = false;

function validateInput($aFormValues)
{
    global $bValidated;
    
    $objResponse = new xajaxResponse();

    if ('yes' == $aFormValues['input_radio'])
        $bValidated = true;
    else
        $bValidated = false;
    
    return $objResponse;
}

function saveData($aFormValues, $sDestination)
{
    global $bValidated;
    
    $objResponse = new xajaxResponse();
    
    if ($bValidated) {
        $objResponse->assign(
            $sDestination, 
            'innerHTML', 
            'Data saved: ' . print_r($aFormValues, true)
            );
    } else {
        $objResponse->assign(
            $sDestination, 
            'innerHTML', 
            'Data NOT saved: ' . print_r($aFormValues, true)
            );
    }
    
    return $objResponse;
}

Returning HTML asynchronously:

The xajax HTML control library can be used to generate the HTML and associated javascript for xajax response commands as well. Simply instantiate and configure the controls as you normally would, but leave off the clsDocument, clsHTML and clsBody tags as those are only needed when building the initial page. Here you will see the code for a check box control that triggers a xajax event request. The event was registered above and has two event handlers which are also shown below.
    new clsInputWithLabel('Show table', 'right', array(
        'attributes' => array(
            'type' => 'checkbox',
            'id' => 'show_table_checkbox',
            'name' => 'show_table_checkbox'
            ),
        'event' => array('onclick', $requestShowTable, array(
            array(0, XAJAX_CHECKED_VALUE, 'show_table_checkbox'),
            array(1, XAJAX_QUOTED_VALUE, 'show_table_output')
            ), '', '; return true;')
        )),
    new clsDiv(array(
        'attributes' => array(
            'id' => 'show_table_output'
            )
        ))
function showTable($sChecked, $sDestination)
{
    // Even though a couple of these files are included above, you should note that they are
    // included AFTER the $xajax->processRequest(); statement.  This means that they will not
    // be included when xajax is answering a request... so, we must include them here...
    // inside this request handler.
    //
    //include '../xajax_core/xajaxControl.inc.php';
    //include '../xajax_controls/table.inc.php';
    //include '../xajax_controls/literal.inc.php';
    
    $objResponse = new xajaxResponse();
    
    if ('true' == $sChecked)
    {
        $aData = array(
            array('Mr. John Smith', '443 Millspur Avenue', '994399-1'),
            array('Ms. Betty Baker', '222 Town Square Court', '333225-0'),
            array('Mrs. Alice Woodworth', '2248 West Cloud Street Apt#2', '99210-01')
            );
        
        // Construct a table object, then use the array $aData to populate it.
        //
        $objTable = new clsTable(array(
            'attributes' => array(
                'style' => 'border: 1px solid #777777; border-collapse: collapse;'
                ),
            'child' => new clsTableHeader(array(
                'child' => new clsTableRow(array(
                    'attributes' => array(
                        'style' => 'background-color: #cccccc;'
                        ),
                    'children' => array(
                        new clsTableCell(array('child' => new clsLiteral('Name'))),
                        new clsTableCell(array('child' => new clsLiteral('Street'))),
                        new clsTableCell(array('child' => new clsLiteral('Account #')))
                        )
                    ))
                ))
            ));
        
        // Supply the data for the rows.
        $objTable->addRows($aData);
        
        // Return the HTML to the browser.
        $objResponse->assign($sDestination, 'innerHTML', $objTable->getHTML());
    } else {
        $objResponse->clear($sDestination, 'innerHTML');
    }
    
    return $objResponse;
}

Using the xajaxRequest object:

The xajaxRequest class is used by xajax to store a reference to a registered function, event or the methods of a callable object. Once a xajax enabled function, method or event is registered, xajax generates an instance of the xajaxRequest class, which you can store and use later in your script. The xajaxRequest object stores the information needed, including parameter values that you provide, then generates the javascript upon request. You can set parameter values by calling ->setParameter(...) or by passing the parameter settings to the xajax HTML control when you call it's ->setEvent(...) method. To output the javascript for the request, you can call the ->getScript(); function directly or simply link the request to a xajax HTML control using ->setEvent(...); and the xajax HTML control will extract the javascript from the request and include it in the HTML output.
$requestMyFunction = $xajax->register(XAJAX_FUNCTION, 'myFunction');

// Set the first parameter once, this value does not change.
// XAJAX_QUOTED_VALUE means that the text I provide will have quotes surrounding
// it in the resulting javascript.

$requestMyFunction->setParameter(0, XAJAX_QUOTED_VALUE, 'first parameter value');

// Assign this request to the onclick event of an anchor tag.  Pass a second parameter
// declaration to the anchor control so we are sure the parameter value will be as specified
// at the time the anchor generates the javascript.

$anchorClickMe->setEvent('onclick', $requestMyFunction, array(
    array(1, XAJAX_QUOTED_VALUE, 'second parameter for click me link')
    );

// Also, assign this request to the onchange event of a select control.  In this example,
// the value of the select control will be passed as the second parameter to our request.
// XAJAX_INPUT_VALUE tells xajax to generate the javascript necessary to obtain the
// current value of the specified control when the request is initiated.

$selectName->setEvent('onchange', $requestMyFunction, array(
    array(1, XAJAX_INPUT_VALUE, $selectName->getAttribute('id'))
    ));

// NOTE: Calling $requestMyFunction->getScript(); at this point would yield a piece of 
// javascript that calls xajax_myFunction with ONLY ONE PARAMETER as the second parameter
// specified in the last two ->setEvent calls has not been applied!
//
// It is important to realize that the xajax HTML control class will apply the parameter
// settings at the time the javascript is produced for that event handler.
//
// Setting a value for the second parameter explicitly is possible, but you must remember
// that the $anchorClickMe and $selectName controls will overwrite that parameter setting
// when they generate their event handler javascript.

$requestMyFunction->setParameter(1, XAJAX_JS_VALUE, 'xajax.$("someDiv").innerHTML');

// XAJAX_JS_VALUE instructs the request object to treat the supplied value as javascript.
// In other words, the value will NOT have quotes around it.  Therefore, the browser will
// attempt to evaluate that parameter as if it were a javascript variable or function call.

// Other type specifiers are as follows: XAJAX_FORM_VALUES and XAJAX_CHECKED_VALUE.  The
// first instructs the request to return the form values for the specified form and the 
// second instructs the request to return the checked state of the specified check box or
// radio button.