Programmation PHP/Exemples/MiniCMS/Ajaxification
L'ajaxification à implémenter côté serveur et client permet une plus grande souplesse d'interaction entre la vue et le backend. Le séquencement du contenu en flux offre une plus grande réactivité.
Pour ce faire :
Dans le template des owners, on implémente la couche AJAX suivante, "topScript" nourrit le début de document et "bottomScript" l'exécution de fin de document.
<script id="topScript" number="">
<![CDATA[
var $ = function() {};
// object access
$.prototype.oa = {
tab:new Array(),
getNodesById:function(pDom, pId)
/**
getNodes by id function
*/
{
if(pDom.getElementsByTagName)
{
all = pDom.getElementsByTagName("*");
for(g=0; g<all.length; g++)
{
if( all[g].getAttribute
&& all[g].getAttribute("id")
== pId )
{
this.tab.push(all[g]);
}
}
return this.tab;
}
},
getNodesWithId:function(pDom, pId)
/**
getNodes by id function
*/
{
if(pDom.getElementsByTagName)
{
var reg=new RegExp("("+pId+")","g");
all = pDom.getElementsByTagName("*");
for(g=0; g<all.length; g++)
{
if( all[g].getAttribute &&
reg.test(all[g].getAttribute("id")) )
{
this.tab.push(all[g]);
}
}
return this.tab;
}
},
each:function() // pAction
/**
TODO
*/
{
for(var i=0; i<this.tab.length; i++)
{
//
}
}
}
$.prototype.Remote = {
getConnector: function()
{
var connectionObject = null;
if (window.XMLHttpRequest)
{
connectionObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
connectionObject = new ActiveXObject('Microsoft.XMLHTTP');
}
return connectionObject;
},
configureConnector: function(connector, callback)
{
connector.onreadystatechange = function()
{
if (connector.readyState == 4)
{
if (connector.status == 200)
{
callback.call(connector, {
text: connector.responseText,
xml: connector.responseXML
});
}
}
}
},
load: function(request)
{
var url = request.url || "";
var callback = request.callback || function() {};
var connector = this.getConnector();
if (connector) {
this.configureConnector(connector, callback);
connector.open("GET", url, true);
connector.send("");
}
},
save: function(request) {
var url = request.url || "";
var callback = request.callback || function() {};
var data = request.data || "";
var connector = this.getConnector();
if (connector)
{
this.configureConnector(connector, callback);
connector.open("POST", url, true);
connector.
setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
connector.
setRequestHeader("Content-length", data.length);
connector.
setRequestHeader("Connection", "close");
connector.
send(data);
}
}
}
]]>
</script>
<script id="endScript" number="">
<![CDATA[
$ = new $();
function segment(pStr)
/**
segment the callback
*/
{
var reg=new RegExp("~@~+", "g");
return pStr.split(reg);
}
function feedContent()
/**
feed the content of the page by tag expr and Id
*/
{
var ctc = $.oa.getNodesWithId(document.body,"id");
for(var i=0; i < ctc.length ; i++ )
{
//
$.Remote.save({
url: "./main.php",
data: "qry=1&id="+ctc[i].id+"&name=Ben&surname=Abdell",
callback: function(response)
{
var nfo = segment( response.text );
document.getElementById( nfo[0] ).innerHTML = nfo[1];
}
});
}
}
]]>
</script>
On teste sur un segment du body. Par convention, le container à nourrir porte l'id composé "id:idDuContainer".
<page id="standard">
<![CDATA[
<table width="100%" border="0" id="table1">
<tr><td>
<div id="id:topContent"/>
</td></tr>
<tr><td>
<div id="id:mainContent"/>
</td></tr>
<tr><td>
<div id="id:bottomContent"/>
</td></tr>
</table>
]]>
</page>
Un test sur la page "standard" donne en output pour l'appel ajax :
$.Remote.save({
url: "./main.php",
data: "qry=1&id="+ctc[i].id+"&name=Ben&surname=Aldell",
callback: function(response)
{
var nfo = segment( response.text );
document.getElementById( nfo[0] ).innerHTML = nfo[1];
}
});
=> le résultat suivant
<table id="table1" width="100%" border="0">
<tbody>
<tr>
<td>
<div id="id:topContent">id:topContent / Ben Aldell</div>
</td>
</tr>
<tr>
<td>
<div id="id:mainContent">id:mainContent / Ben Aldell</div>
</td>
</tr>
<tr>
<td>
<div id="id:bottomContent">id:bottomContent / Ben Aldell</div>
</td>
</tr>
</tbody>
</table>
On est nominal pour l'ajaxification de la complétion du contenu côté client.
Implémentation des contrôleurs côté serveur
[modifier | modifier le wikicode]- Common.inc.php :
<?php
/*
common application functiunalities
would be fine to merge all request to requestForData
*/
require_once CLA . "/utilities.class.php";
require_once CLA . "/dataManager.class.php";
require_once CLA . "/templateControler.class.php";
function requestForLayout($pTerm,$pOwner="Root",$pTemplate="default")
{
$tmp = new templateControler(array("path"=>"./Owners/" . $pOwner . "/Templates/" . $pTemplate . ".xml"));
$node = $tmp->getNode('//page[@id="' . $pTerm . '"]');
return $node[0]->nodeValue;
}
function requestForData($pTerm)
{
$_lst = explode("|",$pTerm) ;
$_manager = new dataManager();
$_manager->data['path'] = $_manager->data['root'] . "Root/Contents/" . $_lst[0] . ".xml";
$_document = $_manager->initialize();
if ($_lst[1])
$_manager->data['query_1'] = array("attribute"=>"number", "value"=>$_lst[1]);
if($_lst[2])
$_manager->data['query_2'] = array("attribute"=>"id", "value"=>$_lst[2]);
$res = dataManager::getContentByData(
dataManager::getContentByData($_document, $_manager->data['query_1']),
$_manager->data['query_2']
);
$node = isset($_lst[3]) ? $_lst[3] : "content";
$str = $res->getElementsByTagName($node);
return $str->item(0)->nodeValue;
}
- Responder.inc.php :
<?php
//
$_ = explode(":",$_REQUEST['id']);
$_content = "";
switch( true )
/**
* content type switcher
*/
{
case ($_[0] == "lay") :
// template request
$_content = requestForLayout($_[1]);
break;
case ($_[0] == "data") :
// data request
$_content = requestForData($_[1]);
break;
}
# OUTPUT
echo $_REQUEST['id'] . "~@~" . $_[1] . "~@~" . $_content;
Auto complétion du layout
[modifier | modifier le wikicode]On implémente feedLayout pour auto compléter et chercher les fragments sur le template pour l'injecter sur les encres
<script id="endScript" number="">
<![CDATA[
$ = new $();
function segment(pStr)
/**
*/
{
var reg=new RegExp("~@~+", "g");
return pStr.split(reg);
}
function isToFeed()
/**
check is still to feed
*/
{
return (set = $.oa.getNodesWithId(document.body,"lay") )?set:false;
}
function feedLayout()
/**
feed the layout
*/
{
var ctc = $.oa.getNodesWithId(document.body,"lay");
if(ctc[0])
$.Remote.save({
url: "./main.php",
data: "qry=1&id="+ctc[0].id,
callback: function(response)
{
var nfo = segment( response.text );
var node = document.getElementById( nfo[0] );
node.innerHTML = nfo[2];
node.id = nfo[1];
$.oa.tab = new Array();
feedContent();
}
});
}
function feedContent()
/**
feed the content of the page by tag expr and Id
*/
{
feedLayout();
//feedData();
}
]]>
</script>
Auto complétion des données
[modifier | modifier le wikicode] <script id="endScript" ...>
// ...
function feedData()
/**
feed the data
*/
{
var ctc = $.oa.getNodesWithId(document.body,"data");
if(ctc[0])
$.Remote.save({
url: "./main.php",
data: "qry=1&id="+ctc[0].id+"&request=1",
callback: function(response)
{
var nfo = segment(response.text);
var node = document.getElementById(nfo[0]);
node.innerHTML = nfo[2];
node.id = nfo[1];
$.oa.tab = new Array();
feedContent();
}
});
}
function feedContent()
/**
feed the content of the page by tag expr and Id
*/
{
feedLayout();
feedData();
}
</script>
Test de réactivité de la couche ajax
[modifier | modifier le wikicode]La fonction feedContent se charge de charger les flux sur la page en provenance du template et des champs de données.
Le template étant :
<page id="standard">
<![CDATA[
<div id="lay:frameContent" class="toFeed">
</div>
]]>
</page>
<page id="_frameContent">
<![CDATA[
<table width="100%" border="0" id="table1">
<tr><td>
<div id="lay:topContent" />
</td></tr>
<tr><td>
<div id="lay:mainContent" />
</td></tr>
<tr><td>
<div id="lay:bottomContent" />
</td></tr>
</table>
]]>
</page>
<page id="topContent">
<![CDATA[
<table width="100%" border="1" cellpadding="0" cellspacing="0">
<tr>
<td width="40%">
<div id="lay:loginPane" >:: loginPane ::</div>
</td>
<td width="60%">
<div>My Tiny CMS</div>
<div id="lay:menuPane" >:: menuPane ::</div>
</td>
</tr>
</table>
]]>
</page>
<page id="loginPane">
<![CDATA[
<div>
<div>
<input id="iUsr" type="text" value=" " /><br/>
<input id="iPwd" type="text" value=" " />
</div>
</div>
]]>
</page>
<page id="menuPane">
<![CDATA[
<div> :: menuPane - new :: </div>
]]>
</page>
<page id="mainContent">
<![CDATA[
<div id="data:1|1|title">content</div>
<div id="data:1|2|table">content</div>
<div id="data:1|3|bottom">content</div>
]]>
</page>
<page id="bottomContent">
<![CDATA[
<table width="100%" border="1" cellpadding="0" cellspacing="0">
<tr height="100"><td>
<div align="center"> THIS IS THE BOTTOM CONTENT</div>
</td></tr>
</table>
]]>
</page>
et le crop 1.xml :
<?xml version="1.0" encoding="UTF-8"?>
<crop id="test" number="1">
<topic>Cultiver son potager</topic>
<scope>légumes potager soupe</scope>
<fields>
<field number="1" id="title">
<subject>les légumes du potager</subject>
<content>
<![CDATA[
les légumes du potager
]]>
</content>
</field>
<field number="2" id="table">
<subject>table content</subject>
<content>
<![CDATA[
<table>
<tr>
<td>
le potagé contient :
</td>
<td>
<ul>
<li>une terre molle.</li>
<li>Parsemé ça et là, on Test carottes, </li>
<li>petits poids et potirons</li>
</ul>
</td>
</tr>
</table>
]]>
</content>
</field>
<field number="3" id="bottom">
<subject>this is the new subject</subject>
<content>
<![CDATA[
le potagé contient une terre molle2.
Parsemé ça et là, on trouve carottes, petits poids et potirons
]]>
</content>
</field>
</fields>
</crop>
On a pour rendu en sortie :