Gyroscope / Adding a Record

So far we've been creating landlord and property records in the database. Next we'll create interfaces for adding them directly in the application. First we need a trigger to invoke a form for adding a new landlord record.

In listlandlords.inc.php after the search box add the following link:

<div style="padding:5px 0;">
  <a onclick="addtab('newlandlord','New Landlord','newlandlord');">
      <img src="imgs/addrec.gif"> add landlord
  </a>
</div>

Remember the first parameter in the addtab function is the key of the tab. In this case, we have a fixed value. This means we can have only one New Landlord form at any moment, which is suiting.

Next is the switch - no surprise here:

case 'newlandlord':
  include 'icl/newlandlord.inc.php';
  newlandlord();
break;

To create newlandlord.inc.php, we can conveniently copy and paste the code from showlandlord.inc.php with a few modifications:

<?php
  function newlandlord($llid=null){
  if (!isset($llid)) $llid=GETVAL('llid');
  $llid='new';
  global $db;
?>
<div class="section">
<?
  $query="select * from landlords, persons
  where landlords.personid=persons.personid
  and landlords.llid=$llid ";
  $rs=sql_query($query,$db);
  $myrow=sql_fetch_array($rs);
  $fname=$myrow['fname'];
  $lname=$myrow['lname'];

?>
<table>
<tr><td>Firstname:</td>
<td><input id="llfname_<?echo $llid;?>" value="<?echo $fname;?>">
</td></tr>
<tr><td>Lastname:</td>
<td><input id="lllname_<?echo $llid;?>" value="<?echo $lname;?>">
</td></tr>
<tr><td></td>
<td>
<button onclick="addlandlord('<?echo $llid;?>');">
  Add Landlord
</button>
</td></tr>
</table>
</div>
<?
}//func

And here's the cleaned-up version:

<?php
function newlandlord(){
  $llid='new';
  global $db;
?>
<div class="section">
<table>
<tr><td>Firstname:</td>
<td><input id="llfname_<?echo $llid;?>">
</td></tr>
<tr><td>Lastname:</td>
<td><input id="lllname_<?echo $llid;?>">
</td></tr>
<tr><td></td>
<td>
<button onclick="addlandlord();">
  Add Landlord
</button>
</td></tr>
</table>
</div>
<?
}//func

Remember to leave out the one-to-many sections such as phone numbers or properties in the new record form. Once the record is created, the user will see the detail view where associated data can then be added.

On the JavaScript side, we can also reuse updatelandlord:

addlandlord=function(llid){
  var llid='new';
  var ofname=gid('llfname_'+llid).value;
  var olname=gid('lllname_'+llid).value;
  fname=encodeHTML(ofname);
  lname=encodeHTML(olname);

  reloadtab('landlord_'+llid,
    ofname+' '+olname,
    'updatelandlord&llid='+llid+'&fname='+fname+'&lname='+lname,
    function(){
      if (document.viewindex==0)
      showview(0);
    }
  );

}
Note that we cannot use ajxpgn, addtab or reloadtab (unless you're using V3.2 or greater) to inject the view of the new record into a pre-defined container, as we've been doing with updating records before. This is because the containers require a unique ID, which is assigned by the database.

The solution is to send a request to add the record. Get the new record's ID from the response and open a new tab while closing the New Landlord tab.

addlandlord=function(llid){
  var llid='new';
  var ofname=gid('llfname_'+llid).value;
  var olname=gid('lllname_'+llid).value;
  fname=encodeHTML(ofname);
  lname=encodeHTML(olname);
 
  var res=ajxb(document.appsettings.codepage+
  '?cmd=addlandlord&fname='+fname+'&lname='+lname);
 
  var llid=parseInt(res,10);
  if (res!=llid) {
  alert('oops, something went wrong');
  return;
  }

  closetab('newlandlord');
  showlandlord(llid,ofname+' '+olname);
  if (document.viewindex==0)
  showview(0);
}
The bolded lines in the above code ensure the response is a numeric value. The server response should not contain any extra white spaces.

Next we add the switch clause:

case 'addlandlord':
  include 'icl/addlandlord.inc.php';
  addlandlord();
break;

and implement the handler:

<?php
function addlandlord(){
  $fname=GETSTR('fname');
  $lname=GETSTR('lname');
  global $db;

  $query="insert into landlords (fname,lname) values ('$fname', '$lname')";
  $rs=sql_query($query,$db);

  $llid=sql_insert_id($db,$rs);
  echo $llid;
  die();
}

The die statement instantly terminates the script, eliminating all potential white spaces.

Starting Version 3.2, we can write the JavaScript handler for creating a new landlord record in a simpler and more robust manner:

addlandlord=function(){
  var ofname=gid('llfname_new').value;
  var olname=gid('lllname_new').value;
  fname=encodeHTML(ofname);
  lname=encodeHTML(olname);

  reloadtab('newlandlord',
    'addlandlord&fname='+fname+'&lname='+lname,
    function(req){
      var llid=req.responsetText;
      if (llid!=parseInt(llid,10)){
        alert('oops, something went wrong');
        return;
      }

      reloadtab('newlandlord',ofname+' '+olname,
      'showlandlord&llid='+llid,null,null,
      {newkey:'landlord_'+llid});

      if (document.viewindex==0) showview(0);1
    }, null
  );
}

1 Starting v4.6, use
if (document.viewindex==0) reajxpgn('landlordlist','lv0');
Compare the above code with the previous listing. The first AJAX call creates a new record on the server side. It was initiated by the ajxb function, which blocks the execution until server response. Once the return value is validated, the original tab is closed and a new tab is added by calling the addtab function.

The new version uses reloadtab function for the initial call. We may take advantage of the data parameter to deal with lengthy POST fields such as a description.

The reloadtab function ensures that only one request is sent. Subsequent requests are ignored until the arrival of the first response. This feature is only available starting 3.2.

In the callback function we could use the old fashioned "close tab, open new tab" sequence. Or we could simply "rekey and reload" the tab, though the process of closing and opening is noticeable clumsy.

Sync Listview Content in Context

When a record is added, updated or deleted, the associated list view should be synchronized. Before v4.6, we used the following line to detect whether the list view is visible, and if so, reload the list view:
if (document.viewindex==0) showview(0);
The issue with the previous approach is that the view index alone does not identify the state of the list view. It is possible that the user is looking at the second page of the list, or that the list is bearing a search keyword. Page- and keyword specific content is loaded in a sub container of the list view; in this case, "landlordlist".



Starting v4.6, Gyroscope sports an enhanced version of NanoJS. Each time ajxpgn is called, the target container stores how it is loaded for a future replay. The new reajxpgn function replays in the first ajax container first; if the container doesn't have reload parameters set, then it falls back to a secondary loader:
if (document.viewindex==0) reajxpgn('landlordlist','lv0');
Why are the reload parameters not always loaded for the landlordlist container? When a container is loaded with ajxpgn, its reload params are guaranteed to be set. However, when the list view lv0 is first loaded, the landlordlist is loaded as part of the injected content. The second parameter in the reajxpgn function falls back to the main loader, offering the same behavior as showview in previous versions of Gyroscope.

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
Chat Now!
First Name*:
Last Name*:
Email: optional