Detail View / Pivoting Records
Some related records such as phone numbers can be displayed directly in the
landlord view. Other more complex records, such as properties, are better
displayed in their own tabs.
In
showlandlord.inc.php, add a properties section:
<?
include 'icl/listlandlordproperties.inc.php';
//...
?>
<div class="sectionheader">Properties</div>
<div id="landlordproperties_<?echo $llid;?>">
<?listlandlordproperties($llid);?>
</div>
Now create a "properties" database table for storage:
prid auto increment, primary key, unsigned integer
llid unsigned integer
addr varchar(255)
city varchar(255)
Enter a few test data and display them in
listlandlordproperties.inc.php:
<?php
function listlandlordproperties($llid=null){
if (!isset($llid)) $llid=GETVAL('llid');
global $db;
$query="select * from properties where llid=$llid";
$rs=sql_query($query,$db);
while ($myrow=sql_fetch_array($rs)){
$prid=$myrow['prid'];
$addr=$myrow['addr'];
$dbaddr=str_replace("'","\'",$addr);
?>
<div>
<a onclick="ajxjs(self.showproperty,'properties.js';
showproperty(<?echo $prid;?>,'<?echo $dbaddr;?>');"
><?echo $addr;?></a>
</div>
<?
}//while
}
The call to
ajxjs in the above function loads
properties.js only if the function
showproperty hasn't been globally defined. Since the function will soon been
defined in
properties.js, the JavaScript file is loaded only once, on-demand.
Now let's start
properties.js:
showproperty=function(prid,addr){
addtab('property_'+prid,addr,'showproperty&prid='+prid);
}
The next step is naturally to implement the server-side handlers.
In
myservices.php:
case 'showproperty':
include 'icl/showproperty.inc.php';
showproperty();
break;
In icl/showproperty.inc.php:
<?php
function showproperty($prid=null){
if (!isset($prid)) $prid=GETVAL('prid');
global $db;
$query="select * from properties,landlords
where properties.llid=landlords.llid
and prid=$prid order by addr";
$rs=sql_query($query,$db);
$myrow=sql_fetch_array($rs);
$addr=$myrow['addr'];
$llname=$myrow['fname'].' '.$myrow['lname'];
$llid=$myrow['llid'];
$dbllname=str_replace("'","\'",$llname);
?>
<div class="section">
<table>
<tr><td>
Landlord:
</td><td>
<a onclick="
ajxjs(self.showlandlord,'landlords.js');
showlandlord(<?echo $llid;?>,'<?echo $dbllname;?>');
">
<?echo $llname;?>
</a>
</td></tr>
<tr><td>
Address:
</td><td>
<input id="propertyaddr_<?echo $prid;?>"
value="<?echo $addr;?>">
</td></tr>
<tr><td></td><td>
<button
onclick="updateproperty(<?echo $prid;?>,<?echo $llid;?>);">
Save Changes
</button>
</td></tr>
</table>
</div>
<?
}
The bolded lines in the above code provide a pivoting point to the landlord
view from the property view.
Next, let's implement the "Save Changes" button. There're only two more
steps to go.
In
properties.js:
updateproperty=function(prid,llid){
var oaddr=gid('propertyaddr_'+prid).value;
var addr=encodeHTML(oaddr);
reloadtab('property_'+prid, oaddr,
'updateproperty&prid='+prid+'&addr='+addr,
function(){
ajxpgn(landlordproperties_'+llid,document.appsettings.codepage+
'?cmd=listlandlordproperties&llid='+llid);
if (document.viewindex==1) showview(1);
} //function
); //reloadtab
}
You may have noticed that the landlord ID is passed to the function even
though we only need the property ID to update the record. When we generate
the code to call the updateproperty function we already had access to llid.
This is a freebie. In the callback function we detect the existence of a
landlord-property list. If such container is already loaded, we'll reload the
updated version, so that an address change in the property view is reflected in
the landlord-property list as well.
In theory, we should also modify the updatelandlord JavaScript function so
that all the related property tabs are also reloaded. This process could get
complicated because the client-side knows which tabs are open, and we only
need to reload open tabs; but the server knows which property records are
associated with the said landlord. In a one-to-many relationship, having the
server returning a full list of records for the client to detect and reload would
be extremely inefficient. A more elegant solution is to get the client to send
the tabs for the server to build a pre-filter. In most cases, it's okay for the
pivoting link to be out-dated as long as the tab and list information stay
current.
For the curious minds, here's how to get the property ids that are
open in tabs:
propertylist=function(){
var keys=document.tabkeys;
var ids=[];
for (var i=0;i<keys.length;i++){
var id=keys[i].replace(/property_(\d+)/g,"$1");
if (parseInt(id,10)==id) ids.push(id);
}
return ids.join(',');
}
Writing the server-side handler for updating a property record is left as an
exercise. The process is identical to the previous examples. Remember to
piggy-back the showproperty function.
If you've been following the code and trying it on your machine, you may
have noticed that when you update a property record, the property list in side the landlord view displays
either an error or becomes blank. This is because
listlandlordproperties isn't recognized by the main switch:
case 'listlandlordproperties":
include 'icl/listlandlordproperties.inc.php';
listlandlordproperties();
break;
case 'slv1':
include 'listproperties.inc.php';
listproperties();
break;
As a final step, we add an entry point to list the properties directly in
index.php:
<acronym title="Properties">
<a href=#
onmouseover="hintstatus('Properties',this);"
onclick="showview(1);">
<img src="imgs/properties.gif">
</a>
</acronym>