The end of JavaScript hassle ?
68I'm sure you like that your web pages show their rich content the way you conceived it whatever navigator is used.
I found myself doing different page versions because I wanted to reach IE as well as firefox and safari.
I had some ambitious objectives because I always try to write web pages that behave like client-server aplications.
Needless to say this can be rather frustrating and time consuming. And in the end I often found I had written three different sites, one for each navigator...
And one day, I discovered Adobe Flex.
It works with the Adobe plugin flash player, wich is available for almost all operating systems.
The good thing is this plugin takes care of script interpretation in a completely independent way from the current navigator.
You don't need anymore to embed HTML generation in you PHP pages, or use HTML templates to avoid this.
User interface building and data access are completely separated things in Flex. Designer and programmer get better defined boundary territories even if they are the same person.
Let's illustrate the point with an example :
It will be a classical ComboBox containig names, that displays the postal address of the selected item in a text box :
PHP & MySql, HTML & JavaScript
<?php
// call the function at the bottom of the script
$link = connectusPlease();
// place request in a string variable.
// It's a join between two tables. One contains names
// the other addresses. The latter references names.
$cQuery = 'select n.fname, a.street, a.zip, a.city, a.country, a.telephone';
$cQuery .= ' from names n, addresses a where n.r_no = a.nameref order by fname';
// these two arrays hold values
// that will be visible across the script
$aNames = array();
$aAddresses = array();
// send request and obtain dataset
$dset = mysql_query($cQuery,$link)
or die('Invalid request ' . mysql_error());
// populate both arrays
for($i=0;$i<mysql_num_rows($dset);$i++){
$oRow = mysql_fetch_object($dset);
$aNames[$i] = $oRow->fname;
$aAddresses[$i] = $oRow->street."\\n".$oRow->zip." ".$oRow->city."\\n".$oRow->country."\\ntelephone : ".$oRow->telephone;
}
?>
<!-- Here, navigator DOM will get an equivalent array to $aAddresses, aElements for use under javaScript-->
<script language="javascript">
var aElements = Array();
<?php
for($i=0;$i<count($aAddresses);$i++){
$oRow = mysql_fetch_object($dset);
?>
aElements[<?php echo $i;?>] = "<?php echo $aAddresses[$i];?>";
<?php
}
?>
</script>
<!-- we then generate the ComboBox from $aNames array which will have a trigger onchange-->
<p style="font-family: Arial, Helvetica, sans-serif;font-size: 12px;">
select a name : <select id="names" style="font-Size:10px;color:#800000" onchange="displayAddress();">
<?php
for($i=0;$i<count($aNames);$i++){
?>
<option value="<?php echo $i;?>"><?php echo $aNames[$i];?></option>
<?php
}
?>
</select>
</p>
<p>
<!-- TextArea tag, empty for the moment
<textarea id="address" style="font-Size:12px;color:#000080;width:200px;height:80px;overflow:auto;">
</textarea>
-->
<!-- javascript holding textarea filling as the page is loaded and the ComboBox trigger function-->
<script language="javascript">
var cb = document.getElementById("names");
var ta = document.getElementById("address");
// textarea load values
cb.value=0;
displayAddress();
function displayAddress(){
ta.value = aElements[cb.value];
}
</script>
<?php
// polite connection function
function connectusPlease(){
// connecting verbose...
$database='sample';
$WhatHost='localhost';
$WhatUser='zampano';
$WhatPsw='zampano';
//1 - Connection !
$link = mysql_connect($WhatHost, $WhatUser,$WhatPsw)
or die("Impossible de se connecter (mysql_connect): " . mysql_error());
if(!$link){exit('connection failed...');}
//2 - Selection !
mysql_select_db ( $database, $link)
or die("Requête invalide : (use) database=$database" . mysql_error());
$query="use $database" ;
mysql_query($query,$link)
or die("Requête invalide : (use) database=$database" . mysql_error());
return $link;
}
?>
Now, let's have a look at the Flex solution
PHP & MySql, Flex
<?xml version="1.0" encoding="iso-8859-1"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns="*"
layout="absolute"
verticalAlign="top"
horizontalAlign="center"
backgroundGradientColors="[#FFFFFF, #FFFFFF]"
backgroundGradientAlphas="[1.0, 1.0]"
color="#000080" width="604"
creationComplete="init()" horizontalScrollPolicy="off" verticalScrollPolicy="auto" height="546">
<mx:RemoteObject id="zAdr" fault="faultHandler(event)" showBusyCursor="true" source="Cursor" destination="amfphp">
<mx:method name="getAddresses" result="gotAddresses(event)" />
</mx:RemoteObject>
<mx:Fade id="fadeIn" duration="150" alphaFrom="0.0" alphaTo="1.0" target="{address}"/>
<mx:Fade id="fadeOut" duration="200" alphaFrom="1.0" alphaTo="0.0" target="{address}" effectEnd="fadeIn.play();"/>
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
[Bindable] private var nAddresses:ArrayCollection;
private function init():void{
zAdr.getOperation('getAddresses').send();
}
private function faultHandler (event:FaultEvent):void {
// Deal with event.faultstring, etc.
Alert.show( event.fault.faultCode+'\n'+event.fault.faultDetail+'\n'+event.fault.faultString);
}
private function gotAddresses(e:ResultEvent):void{
var result:*=e.result;
nAddresses = result;
address.text = nAddresses[0].street + "\n" + nAddresses[0].zip +
" " + nAddresses[0].city + "\n" + nAddresses[0].country + "\ntelephone : " + nAddresses[0].telephone;
}
private function setAdr():void{
fadeOut.play();
address.text = names.selectedItem.street + "\n" + names.selectedItem.zip +
" " + names.selectedItem.city + "\n" + names.selectedItem.country + "\ntelephone : " + names.selectedItem.telephone;
}
]]>
</mx:Script>
<mx:ComboBox width="142" top="13" left="112" id="names" dataProvider="{nAddresses}" selectedIndex="0" editable="true" enabled="true" labelField="fname" color="#800000" change="setAdr();"></mx:ComboBox>
<mx:Label text="select a name :" width="101" top="15" left="10"/>
<mx:Style>
@font-face {
src: url("file://c:/windows/fonts/verdana.ttf") ;
fontFamily: Verdana;
fontStyle: normal ;
fontWeight: normal ;
advancedAntiAliasing: true;
}
</mx:Style>
<mx:Panel x="10" y="43" width="244" height="123" layout="absolute" title="Address" id="apanel" color="#800000">
<mx:TextArea width="223" height="82" id="address" wordWrap="true" editable="false" enabled="true" fontFamily="Verdana" x="0" y="1" color="#000080" borderStyle="none"/>
</mx:Panel>
</mx:Application>
and the source code
Let's comment :
I do about the same thing that was done using PHP & JavaScript.
One difference is that the necessary code is much shorter and... there's no JavaScript.
It consists of XML tags for object declaration and Action script for programming behaviours.
I even added a fancy fading effect without worrying about targeted navigators, using just two lines of coding.
You can embbed assets as fonts for instance as you see in the code above
one good thing is you have a GUI to place you objects on you page and all DOM is accessible to your script.
They call it Adobe Flex Builder
Adobe sells it, but it's worth trying (you got a 30 day free trial). After that, you can choose between buying it or crack it.
Otherwise, if you write your tags in a text editor, the compiler to make a swf out of your source code is free.
I've just declared my page objects : the ComboBox, a textBox and a panel to hold it, by doing a drag and drop operation.
Then, I just affected their properties.
Concerning database requests :
You have to define a gateway, that is the channel manager between your program and the http server.
Then you define a remote object, whicht in this case sets the method "getAddresses" to be invoked by your query in you PHP class, and two functions :
One is triggered in case of failure "faultHandler". The other one "gotAddresses", in case of success, which we expect is more frequently sollicitated. This latter fills one "Array Collection" with the PHP dataset that you return directly from your PHP program.
A binded variable {nAddresses} collects the return result and populates the ComboBox.
"Cursor" is the name of my PHP class (source file).
"destination" holds the name of the gateway
I think this is simply great !
This is my remote channel object
<mx:RemoteObject id="zAdr" fault="faultHandler(event)" showBusyCursor="true" source="Cursor" destination="amfphp">
<mx:method name="getAddresses" result="gotAddresses(event)" />
</mx:RemoteObject>
This is my PHP method in "Cursor" class
function getAddresses(){
$cQuery = 'select n.fname, a.street, a.zip, a.city, a.country, a.telephone';
$cQuery .= ' from names n, addresses a where n.r_no = a.nameref order by fname';
return $this->getCursor($cQuery);
}
this returns a data ResultSet.
Conclusion
You can easily replace your PHP classes by Java classes using openamf which provides an identical gateway. All this is open source. And your UI remains untouched.
This is about all I had to say by now about this development framework.
I hope you enjoyed and that you feel like trying this tool.
Launch a Google search on flex builder to download and start learning.
PrintShare it! — Rate it: up down flag this hub
Comments
so, there's some hope left.
thank you.
besides, there are garbage collectors nowdays.
hehehe











aguasilver says:
3 weeks ago
Zampano, I gotta say that's a great hub, even if I do need a translator to read it, let alone understand it, no that's wrong, I understand it and if I downloaded flex and kept your hub open besides me.... I'd still end up with garbage!
But I love the hub, and if you can think like this, I respect you!