Widget Support

By orqi

NB: It’s a work in progress. . To add this you need: -

  • The Widget Controller
  • .htaccess Changes
  • The Widget Container Front-End Component
  • A _widgets directory
  • Your First Widget

Widget Controller

The widget controller is basically a standard controller that then mimics the Loader class and loads the widget screens. It also provides a little support for Ajax links, so that you can put anchor links in your widgets and the response will come back to calling widget only.

// ================================================================================= //		

class WidgetController extends Controller
{
	// ============================================================================= //

	function All() {}
	function Input() {}
	function Delete() {}

	// ============================================================================= //

	function Run()
	{
		// expecting parameters: -
		//
		//	$this->get['widget'] = 'raketu'
		//	$this->get['screen'] = 'home';
		//
		// this widget would be available on the following URL: -
		//
		//	http://www.blah.com/widget/raketu/home.html

		// basically what do we have to do ...
		//
		//	1. get the widget's controller
		require_once "_widgets/" . $this->get['widget'] . "/Controller.php";
		//	2. get the widget 'screen' - basically this is the same as
		//	   running a regular command in Orqi.
		$controller_name = $this->get['widget'] . 'Controller';
		$action_name = $this->get['screen'];

		$widget_controller = new $controller_name();
		$widget_controller->Initialise($this->config, $this->session, $this->get, $this->post, $this->files);
		$widget_controller->$action_name();
	}

	// ============================================================================= //

	function LoadWidget($widget_name='', $screen='', $sendtoscreen=true)
	{
		if (!$sendtoscreen) ob_start();

		switch (true)
		{
			case file_exists("_widgets/" . $widget_name . "/_" . $screen . ".php"):
				require "_widgets/" . $widget_name . "/_" . $screen . ".php";
				break;

			default:
				echo "<p>" . $widget_name . "'s' " . $screen . " screen is missing.</p>";
				break;
		}

		if (!$sendtoscreen)
		{
			$return_html = ob_get_contents();
			ob_end_clean();
			return $return_html;
		}
		else return false;
	}

	// ============================================================================= //

	function MakeWidgetLink($widget='', $screen='', $params='', $secure='')
	{
		if (empty($widget) || empty($screen)) return $this->config->app['location'] . '/';
		else
		{
			if ($this->config->app['mod_rewrite'] == false)
			{
				$site_text = (empty($this->config->app['default'])) ? "" : "site=" . $this->config->app['default'] . "&";
				$link_text = $this->config->app['location'] . "/index.php?" . $site_text . "object=widget&action=run&widget=" . $widget . "&screen=" . $screen;
				$separator = "&";
			}
			else
			{
				$site_text = (empty($this->config->app['default'])) ? "" : $this->config->app['default'] . "/";
				$link_text = $this->config->app['location'] . '/' . $site_text ."widget/" . $widget . "/" . $screen . "." . $this->config->app['extension'];
				$separator = "?";
			}

			if ($this->config->app['ssl'] == true && (!empty($_SERVER['HTTPS']) || $secure == true))
			{
				$link_text = str_replace('http:', 'https:', $link_text);
			}

			if (!empty($params)) $link_text .= $separator . $params;
			return "javascript: rh_" . $widget . ".LoadPart('widget_" . $widget . "', '" . $link_text . "');";
		}
	}

	// ============================================================================= //
}

// ================================================================================= //

.htaccess Changes

Put this line in your .htaccess file. You can get by without mod_rewrite, but I’d really recommend it as the urls can get proper tricky.

RewriteRule ^widget/(.*)/(.*).html$ index.php?object=widget&action=run&widget=$1&screen=$2&%{QUERY_STRING} [L]

The Widget Container Front-End Component

This is a work in progress very much meaning I’m not particularly happy with it’s state, but at least it is working. It will load a div with a specified ID and then give you a slice of supporting javascript that will wait for and process ajax instructions on that specified ID only.

<?
	// param1: is the name of the widget
	$separator = "?";
	$extra_parameters = "";

	if (!empty($param2))
	{
		$extra_parameters .= $separator . "param1=" . $param2;
		$separator = "&";
	}
	if (!empty($param3)) $extra_parameters .= $separator . "param2=" . $param3;
?>

<script>
	var ResponseHandlerFor_<?=$param1?> = function()
	{
		this.FillWidget = function(request)
		{
			$('widget_<?=$param1?>').innerHTML = request.responseText;
		}

		this.Oopslol = function()
		{
			$('widget_<?=$param1?>').innerHTML = "<h3>ooops.</h3><p>there was an error.</p>";
		}

		this.PreLoader = function(element_id)
		{
			$(element_id).innerHTML += "<p><img src='/_img/loading_animation.gif'></p>";
			return false;
		}

		this.LoadPart = function(element_id, url)
		{
			this.PreLoader(element_id);
			new Ajax.Request(url, {method:'get', onComplete:rh_<?=$param1?>.FillWidget, onFailure:rh_<?=$param1?>.Oopslol});
			return false;
		}

		this.PostForm = function(submit_form)
		{
			$(submit_form).request({onComplete:rh_<?=$param1?>.FillWidget, onFailure:rh_<?=$param1?>.Oopslol});
			$('widget_<?=$param1?>').innerHTML = "<h2>LOADING</h2><p>Please wait ...</p><p><img src='/_img/loading_animation.gif'></p>";
		}

		this.OnLoadHandler = function()
		{
			this.LoadPart('widget_<?=$param1?>', '/widget/<?=$param1?>/home.html<?=$extra_parameters?>');
		}
	}

	var rh_<?=$param1?> = new ResponseHandlerFor_<?=$param1?>();
</script>
<div class="widget" id="widget_<?=$param1?>" style="margin: 0px 5px 5px 0px; float: left; width: 300px; border: 1px dotted #ccc;"></div>
<script>rh_<?=$param1?>.OnLoadHandler();</script>

A _widgets directory

Create a directory called “_widgets” in your project root. It’s that simple.

Scriptaculous

Ah, yes. Without scriptaculous none of the AJAX stuff will work. Probably best to download it and put it in your “_js” directory. You can include scriptaculous site wide in your _HeadTag.php component.

<script src="<?=$this->config->resource['js']?>/scriptaculous.js" type="text/javascript" language="javascript" charset="utf-8"></script>

Your own widget

Please see the article entitled “Your First Widget” for more information.

Tags: ,

Leave a Reply