Using requestAction & custom layouts to add XHR functionality
5 : Full, final code listing
This tutorial outlines a method for creating or modifying Cake apps that work swiftly for XHR(XmlHTTPRequest)-enabled clients and degrade well to non-XHR/AJAX (even javascript disabled) clients. The guidance provided here will be most suitable to newly converted Bakers. It simply outlines some of Cake's many flexible features and shows how using them in combination can bring rapid returns.
models/calendar.php
controllers/calendar_controller.php
views/calendar/index.thtml
views/calendar/calendarnavigation.thtml
views/calendar/singlecalendar.thtml
views/calendar/generatecalendar.thtml
views/layouts/default.thtml
views/calendar/calendardynamic.thtml
views/calendar/calendarnavigationdynamic.thtml
Model Class:
<?php class Calendar extends AppModel {
var $name = 't1';
}?>
controllers/calendar_controller.php
Controller Class:
<?php class CalendarController extends AppController {
function index() {
}
function calendarnavigation($chooseYear=null,$chooseMonth=null) {
$this->layout = 'calendarnavigationdynamic';
$y = ($chooseYear)?(int)$chooseYear:date("Y",mktime());
$m = ($chooseMonth)?(int)$chooseMonth:date("n",mktime());
$this->set('calYearInt', $y);
$this->set('calMonthInt', $m);
}
function generatecalendar($chooseYear=null,$chooseMonth=null) {
// Create defaults for Year and Month
$y = ($chooseYear)?(int)$chooseYear:date("Y",mktime());
$m = ($chooseMonth)?(int)$chooseMonth:date("n",mktime());
$this->set('calYearInt', $y);
$this->set('calMonthInt', $m);
$this->set('calendar', $this->requestAction('/Calendar/singlecalendar/'.$y.'/'.$m, array('return')));
$this->set('calendarnavigation', $this->requestAction('/Calendar/calendarnavigation/'.$y.'/'.$m , array('return')));
}
function singlecalendar($chooseYear=null,$chooseMonth=null ) {
$this->layout = 'calendardynamic';
$y = ($chooseYear)?(int)$chooseYear:date("Y",mktime());
$m = ($chooseMonth)?(int)$chooseMonth:date("n",mktime());
$this->set('calYearInt', $y);
$this->set('calMonthInt', $m);
}
}?>
Views
views/calendar/index.thtml
View Template:
<h1>Calendar Index</h1><br />
<p>non-XHR, non javascript: <a href="/calendar/generatecalendar">Click this link to go to the Calendar Page</a></p>
<br />
<p>XHR/AJAX,javascript: <a href="#" id="calendarGen">Click this link to load The XHR Calendar</a></p>
<br />
<p>Download: <a href="/addingXHR.rar">Right-click->save this link to download the example files</a></p>
<br />
<br />
<div style="font-weight:bold;font-size:120%;padding3px;">This is the Calendar Nav Div ↓ </div>
<div id="calendarNavDiv" style="border:1px solid black;margin-top:.1em;">
The Calendar Navigation will load here
</div>
<br /><br />
<div style="font-weight:bold;font-size:120%;padding3px;">This is the Calendar Div ↓ </div>
<div id="calendarDiv" style="border:1px solid black;margin-top:.1em;">
The Calendar will load here
</div>
<script type="text/javascript">
$('calendarGen').addEvent('click', function(e) {
e = new Event(e).stop();
var url = "/calendar/singlecalendar";
new Ajax(url, {
method: 'get',
onRequest: function(){
$('calendarDiv').setStyle('border','12px solid red');
},
onSuccess: function(){
$('calendarDiv').setStyle('border','1px dotted blue');
},
update: $('calendarDiv')
}).request();
});
$('calendarGen').addEvent('click', function(e) {
e = new Event(e).stop();
var url = "/calendar/calendarnavigation";
/**
* The simple way for an Ajax request, use onRequest/onComplete/onFailure
* to do add your own Ajax depended code.
*/
new Ajax(url, {
method: 'get',
evalScripts: true,
onRequest: function(){
$('calendarNavDiv').setStyle('border','12px solid red');
},
onSuccess: function(){
$('calendarNavDiv').setStyle('border','1px dotted blue');
},
update: $('calendarNavDiv')
}).request();
});
</script>
views/calendar/calendarnavigation.thtml
View Template:
<?php
$calMonthInt = (strlen($calMonthInt) ==1)?"0".$calMonthInt :$calMonthInt ;
$YYYYMM = $calYearInt.'-'.$calMonthInt.'';
$firstDayOfMonthUnixTimestamp = strtotime($YYYYMM);
$viewingMonth = date("F",$firstDayOfMonthUnixTimestamp);
$viewingYear = date("Y",$firstDayOfMonthUnixTimestamp);
//next month
$nextMonthText = date('F Y',strtotime("+1 months",$firstDayOfMonthUnixTimestamp)).">>";
// previous month
$previousMonthText = "<<".date('F Y',strtotime("-1 months",$firstDayOfMonthUnixTimestamp));
//next month link
$nextMonthLink = "/calendar/generatecalendar/".date('Y\/m',strtotime("+1 months",$firstDayOfMonthUnixTimestamp));
// previous month link
$previousMonthLink = "/calendar/generatecalendar/".date('Y\/m',strtotime("-1 months",$firstDayOfMonthUnixTimestamp));
?>
<div id="calendar_navigation" style="text-align:center;">
<?php echo $html->link($previousMonthText,$previousMonthLink); ?>
<?php echo $viewingMonth ?> <?php echo $viewingYear ?>
<?php echo $html->link($nextMonthText,$nextMonthLink); ?>
</div>
views/calendar/singlecalendar.thtml
View Template:
<?php
$calMonthInt = (strlen($calMonthInt) ==1)?"0".$calMonthInt :$calMonthInt ;
$YYYYMM = $calYearInt.'-'.$calMonthInt.'';
$firstDayOfMonthUnixTimestamp = strtotime($YYYYMM);
$viewingMonth = date("F",$firstDayOfMonthUnixTimestamp);
$viewingYear = date("Y",$firstDayOfMonthUnixTimestamp);
echo "this is the Calendar for <h2>".$viewingMonth. "</h2><h3>". $viewingYear."</h3><br />";
?>
views/calendar/generatecalendar.thtml
View Template:
<h1>Calendar Non-XHR</h1><br />
<p><a href="/calendar/">Return to Calendar home</a></p><br />
<div style="padding:1em;border:2px solid green;">
<?php echo $calendarnavigation; ?>
</div>
<br />
<div style="padding:1em;border:2px solid green;">
<?php echo $calendar; ?>
</div>
Layouts
views/layouts/default.thtml
View Template:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head><title><?php echo $title_for_layout ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="/js/mootools.v1.1.js"></script>
</head>
<body>
<div id="outermost">
<div id="outermostInner">
<div id="content">
<div id="contentPad">
<?php echo $content_for_layout ?>
</div>
</div>
<div style="margin-top:20px;font-size:80%;color:#fff;">
<?php
echo " ".date("M d Y H:i",mktime()) .", timezone: ".date(" \G\M\T O",mktime()) ."";
?>
</div>
</div>
</div>
</body></html>
views/calendar/calendardynamic.thtml
View Template:
<div style="background-color:#fff;padding:2em;">
<?php echo $content_for_layout ?>
</div>
views/calendar/calendarnavigationdynamic.thtml
View Template:
<div id="calendar_navigation" style="background-color:#e0e0e0;padding:2em;">
<?php echo $content_for_layout ?>
</div>
<script type="text/javascript">
$$('#calendar_navigation a').each(function(el){
var url = el.getProperty('href');
url = url.replace(/generatecalendar/,'singlecalendar');
el.addEvent('click', function(e) {
e = new Event(e).stop();
e.preventDefault();
new Ajax(url, {
method: 'get',
onRequest: function(){
$('calendarDiv').setStyle('border','12px solid red');
},
onSuccess: function(){
$('calendarDiv').setStyle('border','1px dotted blue');
UpdateNav(url);
},
update: $('calendarDiv')
}).request();
//
function UpdateNav(url) {
url = url.replace(/singlecalendar/,'calendarnavigation');
new Ajax(url, {
method: 'get',
evalScripts: true,
onRequest: function(){
$('calendarNavDiv').setStyle('border','12px solid red');
},
onSuccess: function(){
$('calendarNavDiv').setStyle('border','1px dotted blue');
},
update: $('calendarNavDiv')
}).request();
}
});
});
</script>
Latest Comments