Saitta web Site

My First Ajax Node



» Front Page » My First Ajax Node
Support This Project

This Howto demonstrates the use of Ajax and creation of dynamic html field with Scriptacolous and Prototype (libraries already used by ATK).

Before starting to analize the code have a look at Visual Demo.

You can scroll and double click on the post-it image to create a new field, drag the field already created, double click on the stamp to active Ajax.

Since this is a demo, it doesn't store anything, but you can easily understand what is the objective of the demo and view the visual design, the drop capability of Scriptacolous and also the creation on the fly of new fields.

We use this CSS to hide Ajax updater image

Web.css

 
#loading {
    display:none;
}
 

This is the core javascript. It has several objectives:

Web.js

 /* 
 * This file is part of the FSdocu distribution. 
 * Detailed copyright and licensing information can be found 
 * in the doc/COPYRIGHT and doc/LICENSE files which should be 
 * included in the distribution. 
 * 
 * @package docu 
 * 
 * @author Fabio Saitta <fabio@saitta.it> 
 * 
 * @copyright (c)2000-2004 http://www.saitta.it 
 * @license http://www.opensource.org/licenses/sleepycat.php 
 * 
 * @version $Revision: 0.99 $ 
 * $Id: web.js,v 0.99 2006/11/07 15:48:00 fabio Exp $ 
 */ 
 
 
fsc=0;
 
function fs_add(element)
{ 
if(fsc==0) {
 Droppables.add('ar_image', {onDrop:fs_drop});
 el1=document.getElementById("fs_timbro"); 
 };
fsc=fsc+1;
var newdiv=document.createElement("div");
var newtext=document.createTextNode("Campo"+fsc);
newdiv.appendChild(newtext);
newdiv.id="fs_div"+fsc;
newdiv.alt="campo"+fsc;
newdiv.style.textAlign="center";
newdiv.style.color="#ffffff";
newdiv.style.backgroundColor="#7f9f50";
newdiv.style.fontFamily="Lucida Grande, Verdana, Arial, Helvetica, sans serif";  
newdiv.style.fontSize="11px";
newdiv.style.width="70px";
newdiv.style.position="absolute";
newdiv.style.top=(el1.offsetTop)+"px";
newdiv.style.left=(el1.offsetLeft+85)+"px";
el=document.body; 
el.appendChild(newdiv);
new Draggable("fs_div"+fsc);
}
 
function fs_pos(name,x,y)
{ 
if(fsc==0) {
 Droppables.add('ar_image', {onDrop:fs_drop});
 el1=document.getElementById("fs_timbro"); 
 };
fsc=fsc+1;
var newdiv=document.createElement("div");
var newtext=document.createTextNode(name);
newdiv.appendChild(newtext);
newdiv.id="fs_div"+fsc;
newdiv.alt=name;
newdiv.style.textAlign="center";
newdiv.style.color="#ffffff";
newdiv.style.backgroundColor="#7f9f50";
newdiv.style.fontFamily="Lucida Grande, Verdana, Arial, Helvetica, sans serif";  
newdiv.style.fontSize="11px";
newdiv.style.width="70px";
newdiv.style.position="absolute";
newdiv.style.top=(x)+"px";
newdiv.style.left=(y)+"px";
el=document.body; 
el.appendChild(newdiv);
new Draggable("fs_div"+fsc);
}
 
function showResponse (originalRequest) {
        $('loading').style.display = "none";
}
function showLoad () {
        $('loading').style.display = "inline";
}
 
 
function fs_drop(element,droppableElement)
{ 
}

Class.FSfield.inc

<?php 
 /* 
 * This file is part of the FSdocu distribution. 
 * Detailed copyright and licensing information can be found 
 * in the doc/COPYRIGHT and doc/LICENSE files which should be 
 * included in the distribution. 
 * 
 * @package docu 
 * 
 * @author Fabio Saitta <fabio@saitta.it> 
 * 
 * @copyright (c)2000-2004 http://www.saitta.it 
 * @license http://www.opensource.org/licenses/sleepycat.php 
 * 
 * @version $Revision: 0.99 $ 
 * $Id: class.Fsfield.inc,v 0.99 2006/11/07 15:48:00 fabio Exp $ 
 */ 
 
useattrib("atknumberattribute");
useattrib("atkcurrencyattribute");
useattrib("atkFileAttribute");
useattrib("atkboolattribute");
userelation("atkmanytoonerelation");

 
   class FSfield extends atkNode 
  { 
    function FSfield() 
    { 
      $this->atkNode('FSfield',NF_ADD_LINK|NF_ADDAFTERADD); 
      $this->add(new atkAttribute("id" ,AF_NO_QUOTES |AF_AUTOKEY));
      $this->add(new atkAttribute("descri" ,AF_SEARCH),"Registro");
      $this->add(new atkNumberAttribute("xcord" ,AF_SEARCH),"Registro");
      $this->add(new atkNumberAttribute("ycord" ,AF_SEARCH),"Registro");
      $this->add(new atkManyToOneRelation("image","image.FSimage",AF_OBLIGATORY|AF_NO_QUOTES|AF_SEARCHABLE),"Registro");
      $this->setTable('fs_field');
      $this->setSecurityAlias("image.FSimage");
    } 
    
    function descriptor_def()

    {
            return "[descri]";
    }    
  } 
?>

class FSImage creates a thumbnail of form image (jpeg, gif or png) and shows it in Recordlist mode

main class load prototype.js and scriptaculous.js as well as web.js and web.css

Function editPage:

Action ajaxupdate:

class.FSImage.inc

<?php 
 /* 
 * This file is part of the FSdocu distribution. 
 * Detailed copyright and licensing information can be found 
 * in the doc/COPYRIGHT and doc/LICENSE files which should be 
 * included in the distribution. 
 * 
 * @package docu 
 * 
 * @author Fabio Saitta <fabio@saitta.it> 
 * 
 * @copyright (c)2000-2004 http://www.saitta.it 
 * @license http://www.opensource.org/licenses/sleepycat.php 
 * 
 * @version $Revision: 0.99 $ 
 * $Id: class.Fsimage.inc,v 0.99 2006/11/07 15:48:00 fabio Exp $ 
 */ 
userelation("atkOneToManyRelation");
useattrib("atknumberattribute");
useattrib("atkcurrencyattribute");
useattrib("atkFileAttribute");
useattrib("atkboolattribute");

 
  class sepiaAttribute extends atkFileAttribute
  {
   // By overriding this method, we can do processing on the uploaded image.
   // The path and filename of the image are passed as parameters.
   function processFile($path, $filename)

   {
     // Include the image class we downloaded. By using the 'moduleDir' method, we
     // ensure that our module works regardless of where it is installed.
    
        $dest_width=100;
        $dest_height=100; 
         $ext = substr( $filename, strrpos( $filename, '.' ) + 1 );
        if ( $ext == 'jpg' || $ext == 'jpeg' ) $src = imagecreatefromjpeg( $path.$filename ) or die( 'Cannot load input JPEG image' );
        else if ( $ext == 'gif' ) $src = imagecreatefromgif( $path.$filename ) or die( 'Cannot load input GIF image' );
        else if ( $ext == 'png' ) $src = imagecreatefrompng( $path.$filename ) or die( 'Cannot load input PNG image' );
        else die( 'Unsupported source file format' );
        list($width, $height) = getimagesize($path.$filename);
    $dst = imagecreatetruecolor($dest_width, $dest_height);
    imagecopyresampled($dst, $src, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height);
    $thumb = "thumb_".$filename;
    imagepng($dst, $path.$thumb);
    imagedestroy();
     }

   function display($record, $mode="")
   {
     // In recodlists, show the thumbnail instead of the larger image.
     if ($mode=="list")

     {
       // use the thumb_... version of the image
       return '<img src="'.$this->m_url."thumb_".$record[$this->fieldName()]["orgfilename"].'">';
     }

     return parent::display($record, $mode);
   }
  }
 
 
  class FSimage extends atkNode 
  { 
    function FSimage() 
     { 
      $this->atkNode('FSimage',NF_ADD_LINK|NF_ADDAFTERADD); 
      $page = &$this->getPage();
      $page->register_script(atkconfig("atkroot")."atk/javascript/prototype/prototype.js");
      $page->register_script(atkconfig("atkroot")."atk/javascript/scriptaculous/scriptaculous.js");
      $page->register_script(moduleDir("image")."web.js");
      $page->register_style(moduleDir("image")."web.css");
      $this->add(new atkAttribute("id" ,AF_NO_QUOTES |AF_AUTOKEY));
          $this->add(new sepiaAttribute("image", "../docu/"),"Registro");
      $this->add(new atkOneToManyRelation("dettagli", "image.FSfield", "image"),"Registro");
          $this->add(new atkAttribute("descri", AF_OBLIGATORY),"Registro");
      $this->setTable('fs_image');
     } 
    
    function editPage(&$handler, $record, $locked=false)

     {
      global $g_sessionManager;        
      $g_sessionManager->stackVar("reg_id",$record['id']);
      $content= '<img src="/docu/postit.jpg" id="fs_postit" ondblclick="fs_add(this)" alt="Crea Campo">';
      $content.= '<img src="/docu/timbro.jpg" id="fs_timbro" ondblclick="fs_salva(this)" alt="Salva Campi">';
      $content.= '<img id="loading" src="/docu/Loading.gif" alt"Loading...">';
      $content.= '<div id="zipResult"></div>';
      $content.=chr(13).'<script type="text/javascript">'.chr(13);
      // ora mi prendo tutti i campi del file

          $g_db = &$this->getDb(); 
      $query = "SELECT descri,xcord,ycord FROM fs_field where image=".$record["id"]; 
      $g_db->query($query, $offset, $limit);
      while ($g_db->next_record())

       {
       $result = $g_db->m_record;
       $content.='fs_pos("'.$result["descri"].'",'.$result["xcord"].','.$result["ycord"].");".chr(13);
       };
          // creo la parte di update ajax

          $content.= chr(13).'function fs_salva(element)';
          $content.= chr(13).'{';
          $content.= chr(13).'var url="dispatch.php";';
      $content.= chr(13).'for (i = 1; i <= fsc; i++)';
      $content.= chr(13).'{';
      $content.= chr(13).'el=document.getElementById("fs_div"+i);';
      $content.= chr(13).'if (el != undefined)';
      $content.= chr(13).'{';
      $content.= chr(13).'var pars   = "atknodetype=image.FSimage&atkaction=ajaxupdate&atklevel=2&atkprevlevel=1&atkstackid='.atkStackID().'&field=" + el.alt + "&x=" + el.style.top+ "&y=" + el.style.left;';
      $content.= chr(13).'var myAjax = new Ajax.Updater({success: "zipResult"}, url, {method: "get", parameters: pars, onLoading: showLoad, onComplete: showResponse} );';
      $content.= chr(13).'}}}';
      $content.='</script>'.chr(13);
          return $page = $handler->editPage($record, $locked).$content;
     }

 
    function descriptor_def()
     {
            return "[descri]";
     }    
   
    function action_ajaxupdate()

//   function action_ajaxupdate($field="",$x=0,$y=0)
     {
      global $g_sessionManager,$_GET;
      $field = htmlspecialchars($_GET['field']);
      // attenzione px

      $x = htmlspecialchars($_GET['x']);
      $y = htmlspecialchars($_GET['y']);
      $x = substr($x,0,strpos($x, 'px'));
      $y = substr($y,0,strpos($y, 'px'));
      $reg_id=$g_sessionManager->stackVar("reg_id");
      // id,field,x,y creare un sql

      // verifico se esiste faccio un update
      // se non esiste faccio un insert
      $g_db = &$this->getDb(); 
      $query = 'SELECT * FROM fs_field WHERE descri="'.$field.'" and image = '.$reg_id; 
      $g_db->query($query, $offset, $limit);
      // attenzione al primo record ???

      if ($g_db->next_record())
       // faccio update 
       $query = 'update fs_field set xcord='.$x.',ycord='.$y.' WHERE descri="'.$field.'" and image = '.$reg_id; 
      else

              // faccio insert
       $query = 'insert into fs_field (image,descri,xcord,ycord) values ('.$reg_id.',"'.$field.'",'.$x.','.$y.')'; 
      $g_db->query($query, $offset, $limit);
      return(true);
     } 
   } 

?>

So when you display the full image:

When you double-click on post-it image :

When you double-click on stamp image:

Action ajaxupdate is called from Ajax and:

module.inc

<?php 
 /* 
 * This file is part of the FSdocu distribution. 
 * Detailed copyright and licensing information can be found 
 * in the doc/COPYRIGHT and doc/LICENSE files which should be 
 * included in the distribution. 
 * 
 * @package docu 
 * 
 * @author Fabio Saitta <fabio@saitta.it> 
 * 
 * @copyright (c)2000-2004 http://www.saitta.it 
 * @license http://www.opensource.org/licenses/sleepycat.php 
 * 
 * @version $Revision: 0.99 $ 
 * $Id: class.module.inc,v 0.99 2006/11/07 15:48:00 fabio Exp $ 
 */ 
 
  global $config_atkroot;
   
  require_once($config_atkroot."atk/atktools.inc");
  
  class mod_image extends atkModule 
  { 

 
          function getMenuItems() 
    { 
          menuitem("image");
          menuitem("image", dispatch_url("image.FSimage", "admin"), "image");
          menuitem("field", dispatch_url("image.FSfield", "admin"), "image");
    } 
          function getNodes() 
    { 
      registerNode("image.FSimage",array("admin","add","edit","delete","stampa","ajaxupdate"));
    }

    function getDescription()
    {
      return "Gestione Documentazione";
    }
  } 
?>

Valid XHTML 1.0!Valid CSS!SourceForge.net Logo