Widgets, Lightbox and Ajax

article_Cool-Sexy-Ajax.jpg

PHPDevShell offers and exceptional powerful way to make your website or application as fluent as possible with the use of powerful Ajax calls. It is made very simple and you will be able to do an ajax call, create a widget or lightbox popup within minutes.

 

 

The greatest of it all is, you create any of the above exactly like you would create any other controller, you dont need to be an expert in Javascript, you just need to code in PHP and call it via an ajax method you choose (we have an easy to use build in ajax call via Jquery too). So in the end, your ajax page could look like any other controller, the system will strip out HTML thats not needed.. Make sure you understand how to create a normal controller before you continue with this tutorial.
It is important to note that the ExamplePlugin shipped with PHPDevShell has examples of all that is discussed below.

Different Menu/Node Ajax Types

We will be looking at the different node types available first, they are very simple to use and generally gets the job done within minutes.

When any Widget, HTML Ajax or Lightbox is called and you did not set its correct menu permissions, it will not show.

(9) HTML Ajax Widget Module (Bordered)

The widget node type creates a nice mini page inside an existing page, which is generally bordered and themed like your main theme. Widgets can be seen as the side blocks/modules of a normal web page.

First we will be creating the controller (plugins/ExamplePlugin/controllers/widgets/simple-widget.php) for the widget, even if you have a widget type you can still use the exact same MVC structure as with any other node.

class widget extends PHPDS_controller
{
	/**
	 * Execute Controller
	 * @author Jason Schoeman
	 */
	public function execute()
	{
		// Load views plugin.
		$view = $this->factory('views');
		
		// Lets do something silly with this widget... like show a logged in as and logout link.
		$name = $this->configuration['user_display_name'];
		$logout_page = $this->navigation->buildURL('3682403894', 'logout=1');
		
		// Receiving some extra data, this is used, 
		// meaning whatever you pass as the source url for the ajax call
		// can be captures like here.
		$data = $this->GET('data');
		$moredata = $this->GET('moredata');
		
		// Pass vars to the view.
		$view->set('name', $name);
		$view->set('moredata', $moredata );
		$view->set('data', $data );
		$view->set('logout_page', $logout_page);
		
		// Output to view.
		$view->show();
	}
}

return 'widget';

If you understand how to create normal controllers above should be a breeze, you should also note that the idea is for you to add models normally too, so queries can be done like with normal nodes or the way you prefer. Lets create the view (plugins/ExamplePlugin/views/widgets/simple-widget.tpl) now for the controller above;

You are logged in as, {$name}

I have received passed data from main controller: {$data}, more data: {$moredata}. Widgets are used to create mini applications inside a main web page.

Obviously all web elements is available. Widgets are created the exact same way as normal nodes.

Now we are done with a basic application for PHPDevShell, you should note that this might as well be a normal plugin menu type (1) which could run as a normal page, this is how perfectly similar they are.

Calling it from the main controller via Ajax

PHPDevShell offers a few standard ways to call ajax without the need to use any javascript, you could of-coarse use your own, but most of the times the generic calls will do just fine. So in the next step we will be looking at calling it from our main controller to display it in a main page. For this you will need the menu id for the widget created above (find this under the menu manager).

Now from the page where you want to display the widget within, just add the following php string in your controller. Note that you can call multiple widgets.

// @field1 The menu id (widget) you want to call (make sure permissions is set).
// @field2 The element id that should be replace with the widget.
// @field3 Get data you would like to submit with the ajax request to be captured in your widget controller.
$this->template->requestWidget('2282118247', 'widget1', 'data=Hello World&moredata=Foobar');

Wow, we are almost there, now we just need to add a div tag with our widget1 id so the system knows where to place the widget.

	

This side we call a widget through ajax :D

(10) HTML Ajax Call (Styled)

This menu type is the same as a widget in all regards, except it does not draw any borders or widget like styling. It is styled and is used to request html ajax. It is developed exactly the same way as you would create a widget, except it is called with;

$this->template->requestAjax('1821693117', 'ajax1', 'data=FooBar');

(11) HTML Ajax Lightbox (Overlay)

Will load request a popup overlay ajax html lightbox to display content in. It is created exactly like a normal widget or page but is called with;

$lightboxurl = $this->template->requestLightbox('1133107805', 'lightbox', 'data=Lightbox Foobar');

The HTML will look slightly different, lets use the url to create the lightbox link.

Click here to see lightbox in action

(12) RAW Ajax Call (Json, XML, text, etc.) (PHPDevShell V3.1.4+)

This is also created like any other controller or menu item (except we need to set the header type for the data it will return), except it does not style anything and is meant for calling raw data. There is no included php method to call this type of node. Because it is returns purely what the developer outputs in his controller and excludes all styling an html. It is also a lighter call as it skips the whole template engine. Lets create a live searchbox for instance, we wall add the javascript in our main controller and call the raw ajax node type remotely, which in turns does a quick query and returns the results.

Lets look at how a simple Raw Ajax node type controller could look and can be used for a live search field;

class ajax extends PHPDS_controller
{
	/**
	 * Execute Controller
	 * @author Jason Schoeman
	 */
	public function execute()
	{
		// We need to tell jquery what data type we will be sending back.
		PU_silentHeader("Content-Type: application/json");

		// Lets play around with RAW ajax.
		// In this example we will do a simple query to check if we have any data requested.
		if ($this->G('term')) {
			$data = $this->db->invokeQuery('ExamplePlugin_menuAjaxQuery', $this->G('term'));
			// Ok lets loop it and create a json string.
			if (! empty($data)) {
				$json = '';
				foreach ($data as $name) {
					$json[] = array('name'=>$name['menu_name']);
				}
				print $this->G("callback") . "(" . json_encode($json) . ")";
			} else {
				print '()';
			}
		} else {
			print '()';
		}
	}
}

return 'ajax';
It is important to remember that you will need to write your own Javascript to call a Raw Ajax node type, this is too specialized to have a generic PHP function for.

a Full working example of above is in the Example Plugin.

Using Ajax by calling same controller

At some point you might not need to call ajax data from another node, you might have some small ajax call which could be written in the same controller as the where it is being called from, PHPDevShell makes it possible to be calling the same controller and having ajax data in a specialized viaAjax method, only when ajax is called.

When the same controller is called using ajax, PHPDevShell is smart enough not to load the execute() method of the original controller but to skip this completely and load a viaAjax() methods which in turn is used to eco ajax data.

This smart Ajax technology can be used for three different things:

  • dynamically loading a page or part of a page to inject the responded HTML into the DOM using the same controller.
  • calling the same controller and getting JSON/XML as an answer
  • call a PHP function from a JavaScript

Of course all three involve using JavaScript, but PHPDevShell tries to make as painless as possible.

Dynamic HTML loading

Let's study this example:

in our page, we have two blocs which should be refreshed with ajax; the content is created by 3 methods: makePage() creates the whole page, and makeBlock1() and makeBlock2() fill the blocs content.

The first step is straightforward:

class myPage extends PHPDS_controller 
{

            public function makePage() {
                /* fill the page content */
                $this->makeBlock1();
                $this->makeBlock2();
            }

            public function makeBlock1() {
                /* fill the content of the first block */
            }

            public function makeBlock2() {
                /* fill the content of the second block */
            }

            public function execute() {
                $this->makePage();
            }

}

So, when the user requests "myPage.html" in the traditional the whole page is created and sent back for the browser to display.

Now, how can I easily load only one block? Let's say I configured my javascript to request "myPage.html?block=1" to fetch the first bloc and "myPage.html?block=2". In normal cases if we had to load the the same page execute() would run, but because PHPDevShell is smart and you call the exact same page, but this time with ajax, the viaAjax() method will be called and execute() will be ignored. So now we just have to add a new method to my class:

class myPage extends PHPDS_controller 
{
	public function makePage() {
		/* fill the page content */
		$this->makeBlock1();
		$this->makeBlock2();
	}

	public function makeBlock1() {
		/* fill the content of the first block */
	}

	public function makeBlock2() {
		/* fill the content of the second block */
	}

	public function execute() {
		$this->makePage();
	}

	// This method will be called only when an ajax call is automatically detected.
	public function viaAjax()
	{
    		switch ($this->GET('block')) {
        	case 1: makeBlock1(); break;
        	case 2: makeBlock2(); break;
    	}

	return false;
}

That's all. When the page is called via ajax, the method is called. Based on the GET parameter, I just output the content of the corresponding block. I could have done that in the main method (execute() ), but it could have been called via traditional method, and I want to be sure the blocks can be fetched only by ajax.

JSON's return

Ajax can also be used to retrieve raw data, i.e. not HTML. Usually, the data is encoded in either JSON or XML. The script is then seen as a function with parameters and a result.
Implementing this with PHPDevShell is very easy; let's pretend we want to implement "multiply a by b":

public function viaAjax()
{
    $a = intval($this->GET('a'));
    $b = intval($this->GET('b'));

    return ($a * $b); // it will be automatically json-encoded
}

Note that the data is explicitly encoded to json; it will be then send back to the browser as such (no template). If the browser adds a special header "HTTP_X_REQUESTED_TYPE", the result will be automatically encoded.

Remember to check out the examples in the ExamplePlugin that is shipped with PHPDevShell, it contains all these examples in one plugin to examine and see it in action.

PHPDevShell © 2010 - All rights reserved.