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>

Table of Content

Our Services

Targeted Crawlers

Crawlers for content extraction, restoration and competitive intelligence gathering.

Learn More

Gyroscope™ ERP Solutions

Fully integrated enterprise solutions for rapid and steady growth.

Learn More

E-Commerce

Self-updating websites with product catalog and payment processing.

Learn More