Including modifiers when extending nodes
|
ATK Howto: Including modifiers when extending nodes
|
This howto explains how you can include modifiers when you extend a node.
All modifiers added to a node will be run in the node's init function. Which modifiers that runs however, depends on the m_type of a node, which will be different for any node that extends it. In order to have the modifiers run, some changes has to be made in the extended nodes init node.
An example init_node:
#loading { display:none; }
This is the core javascript. It has several objectives:
- fs_add creates a new graphical field (DIV) that the user might move on the form image (used to add new Javascript DIV Field)
- fs_pos creates and arranges field (DIV) position over the form image (used to create Javascript DIV Field from DB informations)
- showResponse hides Ajax Updater
- showLoad shows Ajax Updater
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:
- stores key value in reg_id session variable for insert or update new field value later on.
- Creates two new little images (icons) postit and stamp and attach double click event to them.
- Creates a new little image for ajax activity and hide it.
- Calls several time function fs_pos to arrange the position of all the field already stored in DB.
- Defines fs_salva (field save) to store or update field position (you can move the field dragging them all over the form). Fs_salva is dynamic because has to store stackID value used for retrieve reg_id session variable. Call Ajax to save fields position
Action ajaxupdate:
- decodes field name, x position and y position
- retrieves master-detail key id from reg_id session variable
- verify if detail record exists
- if yes call sql update to modify it
- if no call sql insert to create it
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:
- All the fields (master-detail) are retrieved from DB
- Master key is stored in a session variable
- A dynamic javascript function is created and:
- Create a position draggable DIV for any of the fields over the image
- Attach a function to double-click event of Stampa image
When you double-click on post-it image :
- A new field is created
- You can drag it all over the image
- The new field is not stored on DB
When you double-click on stamp image:
- You loop on all the field (attention you loop on javascript DIV not on DB)
- For any of fields you call a Ajax updater function that fires Action ajaxupdate with proper parameters
- ATK information like ATKstack, ATKLevel, ATKPreviouslevel are passed to Dispatch.php ATK PHP file
- Ajax work-in-progress image is displayed
- When Ajax function called is completed work-in-progress image is hided
Action ajaxupdate is called from Ajax and:
- decodes field name, x position and y position (passed by GET parameters)
- retrieves master-detail key id from reg_id session variable
- verify if detail record exists
- if yes call sql update to modify it
- if no call sql insert to create it
--Saitta 13:07, 10 November 2006 (CEST)