PHP Classes
Icontem

File: DBNavigator.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Michele Castellucci  >  DBNavigator  >  DBNavigator.php  
File: DBNavigator.php
Role: Class source
Content type: text/plain
Description: Main class
Class: DBNavigator
Browse and edit data stored in a MySQL database
 

Contents

Class file image Download
<?php

/** @author Michele Castellucci <ghiaccio84@gmail.com>  */



/** This class allows to manage the operation on a MYSQL database, building a graphic interface
  * in automatic manner (a way like to phpMyAdmin) with a * great range of configurations. <br />
  * 
  * Essentially, the data an object DBNavigator can work on, are indicated with a normal query SQL.
  * Throught a <b> testual scanning of the query</b>, are pointed out the involved tables, the data types
  * of the selected fields and the eventual relations between fields of differentes tables (joined by JOIN).
  *
  * Other information which are not directly locatabled by the databes structure can be pointed out
  * by using {@link setMailField()} , {@link setFileField()} , {@link setImageField()} ,
  * {@link setPasswordField()},  {@link setNumericStringField()} and  {@link setMonthYearField()} methods.
  * <br /><br /> 
  * 
  * The HTML contents automatically generated can be graphically personalized by creating
  * your own papers in CSS style and associating
  * the styles using function {@link setTableRowStyle()} , {@link setTableCellStyle()}, {@link setTableBorderStyles()} 
  * ,{@link addTableContainer()} and {@link setClassForFormInput()}	.
  * <br /><br />
  * 
  * You can choose to open the AJAX form through the {@link useAjax()} method to obtain improvements in the graphic interface
  * related to utilization and speed.
  * <br /><br />
  *
  * The interaction main functionality with DBNavigator database are:
  * <ul>
  *
  * <li> <b>INSERTION/EDITING</b><br /><br />
  * an appropriate form HTML is automatically built including all the necessary  validations
  * of the fields both the server side and the client side (javascript).<br /><br />
  *
  * It is possible to use DBNavigator simply for a single insertion through {@link go_only_for_form()} method
  * (EX: forum registration).
  *
  * Specifying a rescue path, is managed the memorization of generic files or images.
  * Moreover, in the case of image alterations, is automatically shown a preview inside the form.
  *
  * In the case of password, the form will include the additional input for the re-typing. 
  * Those passwords will be memorized using the MD5 coding.
  *
  *  Gaining access to the object{@link HTMLForm} member of DBNavigator through the method {@link getEditForm()}, 
  *  it is possible <b>to further personalize ulteriormente the form HTML</b>.<br /> 
  *  For example you can add to the form a simple  anti-hacking verifying code(<b>immagine CAPTCHA</b>)<br />
  *  otherwise to replace the format HTML of default with another as long as that you will incorporate that format in a class PHP 
  *  that will extend the  abstact class {@link TextEditorContainer} (see the method {@link getEditForm()} for further details).<br /><br />
  *
  * Simultaneus alterations made by some  users are blocked through a simple workings of <b>mutua esclusione</b> on the record.
  *  <br /><br />
  *
  *	 MYSQL FIEDS ON HTML EDIT INTERFACE<br /><br />
  *  Here it is a mapping between MySql fields and HTML inputs binded in an automatic way during the building process of edit interface:<br /><br />
  *  <ul>
  *  <li>CHAR/VARCHAR : text input. On this field can be used
  *						{@link setMailField()} , {@link setFileField()} , {@link setImageField()} ,
  * 				    {@link setPasswordField()},  {@link setNumericStringField()}.</li>
  *  <li>DATE : 3 select input (day, month, year). On this field can be used {@link setMonthYearField()}</li>
  *  <li>INT/BIGINT : text input with validation check about integer number format</li>
  *  <li>DOUBLE : text input with validation check about double number format</li>
  *  <li>ENUM : radio input or select input if there are many possible values</li>
  *  <li>SET : checkboxes or select input with multiple choose if there are many possible values</li>
  *  <li>TEXT/TINYTEXT : textarea input</li>
  *  <li>MEDIUMTEXT/LONGTEXT : HTML formatter. See {@link getEditForm()} to change the default.</li>
  *  <li>EXTERNAL KEYS WITH INTEGER TYPE: select input that allow to choose one record of the externat table</li>
  *  </ul>
  *  <br /><br />
  *  
  *  </li>
  *
  * <li> <b>DISPLAYING </b><br /><br />
  * the subject matter of the selected field is shown through an HTML table or in a way completely definable by the class user.
  * 
  * You can choose to enable or not the possibility to insert ({@link canInsert()}), alterate ({@link canEdit()}) 
  * or eliminate elements. In this case the necessary interface is added to the table.
  *
  * Using the standard table visualization, it is possible to add special additional line through functions
  * {@link addDataCol()}, {@link addLinkCol()}, {@link addFreeCol()} and {@link addSwitchCol()}.<br /> 
  * It is important the function {@link addLinkCol()} to allow to link every record to an inside page where are managed data related
  * to that single record. Typical is the example where the inside page uses another DBNavigator to manage data memorized in the database
  * in relation 1 a n.
  *
  * In table form, the web page user can order data in growing or  decreasing form for each visualized field.
  * The default disposition has not to be indicated in the query but through the {@link setDefaultOrd()} method.
  * <br /><br /> 
  * </li>
  *
  * <li> <b>SPECIAL ACTIONS </b><br /><br />
  * Through the form {@link canMultipleEditDelete()} can be enabled the possibility to make special actions.<br />
  * These actions are based on the general table of visualization, which will include the checkbox (checkbox) for an underwhole selection
  * of the visualized elements.<br /><br />
  *
  * The <b>elimination of the party</b>  allows to eliminate in a single step all the selected.<br />
  * The <b>modification sequential</b> allows to alterate one by one the selected elements,
  * without choosing the following one at each modification.<br />
  * The <b>modification simultaneous</b> is very special action which allows to alterate only some fields selected by the user.
  * The alteration of these fields is made on the elements previously selected.
  * <br /><br />
  * </li>
  *
  * <li> <b>DATA SEARCHS</b><br /><br />
  * 
  * The class owns a mechanism which allows to define some fields such as searching fields using
  * the method {@link setSearchField()}.<br /><br />
  *
  * Using the information proceeds from the <b>textual scanning of the initial query</b>, is
  * automatically set up the graphic interface in the way to let the user make a search
  * with the suitable checks, based on the type of the field to be searched.<br /><br />
  * 
  * For researches on textual fields, the search field is furnished with a useful system of automatic auto-finishing
  * based on Ajax (<b>AJAX based auto-complete suggestions</b>).<br />
  * this way are suggested the texts limited in the database to make researches easier and faster.    *  <br /><br />
  *
  * Another additional functionality is related to the exportation of data which can be applied to the entire set of data or
  * to an underwhole locked up by researching criteria.<br />
  * Data can be exported in CSV format simple or in format
  * <b>XML compatible with the browsing by Microsoft Excel ed OpenOffice Calc</b>.
  *
  * </li>
  * </ul>
  *   
  *  <br /><br />
  *  <b>REQUIRED METHODS</b><br /><br />
  *  The class is started up with the method {@link go()} or with {@link go_only_for_form()}<br /><br />
  *
  *  The compulsory and necessary method to be recalled is {@link setPrimaryTable()}.<br />
  *  For the method {@link go()} is <b>compulsory to recall</b> also methods {@link setDefaultOrd()} and {@link setRowName()}.<br /> 
  *	 Besides if you use methods {@link setImageField()} and/or {@link setFileField()} is compulsory to recall {@link setFilePath()}.
  *
  *	<br /><br /><b>MIND OUT!</b> ________________________________________________________________<br />
  * The class need a PHP version 5 configurated within <b>magic_quotes_gpc = On</b>.<br />
  * If you can't have it, try <code>ini_set("magic_quotes_gpc" , "On");</code> 
  * in every script that is expected to do some database modification using DBNavigator.<br />
  * ________________________________________________________________________________<br /><br /><br />
  *
  * 
  *
  * <br /><br />*************************** <b>ITALIAN DOC.</b>***************************<br />
  *
  *
  * Questa classe consente di gestire le operazioni su di un database MYSQL, costruendo un'intefaccia grafica 
  * in modo automatico (in modo simile a phpMyAdmin) con 	una  vasta gamma di configurazioni.<br />
  *
  * Fondamentalmente, i dati su cui può lavorare un oggetto DBNavigator, vengono indicati tramite una normale query SQL.
  * Attraverso una <b>scansione testuale della query</b>, vengono rilevate le tabelle coinvolte, i tipi dei 
  * dati dei campi selezionati e le eventuali relazioni tra i campi di tabelle diverse (unite da un JOIN).
  *
  * Altre informazioni non reperibili direttamente dalla struttura del database possono essere indicate 
  * tramite i metodi {@link setMailField()} , {@link setFileField()} , {@link setImageField()} ,
  * {@link setPasswordField()},  {@link setNumericStringField()} e  {@link setMonthYearField()}.
  * <br /><br />
  *
  * I contenuti HTML generati automaticamente possono essere personalizzati graficamente tramite creando 
  * i propri fogli di stile CSS ed associando 
  * gli stili tramite le funzioni {@link setTableRowStyle()} , {@link setTableCellStyle()}, {@link setTableBorderStyles()} 
  * ,{@link addTableContainer()} e {@link setClassForFormInput()}	.
  * <br /><br />
  *	
  *	Si può scegliere di attivare la modalità AJAX attraverso il metodo {@link useAjax()} per ottenere miglioramenti dell'interfaccia grafica 
  * in termini di usabilità e velocità.
  * <br /><br />
  *
  * Le funzionalità principali di interazione con il database di DBNavigator sono:
  * <br /><br />
  * <ul>
  *
  * <li> <b>INSERIMENTO/MODIFICA</b><br /><br />
  *  viene costruito automaticamente un form HTML appropriato con incluse le necessarie validazioni 
  *  dei campi sia lato server che lato client (javascript).<br /><br />
  *  
  *	 E' possibile usare	DBNavigator semplicemente per un inserimento singolo attraverso il metodo {@link go_only_for_form()} 
  *  (ES: registrazione ad un forum).<br /><br />
  *
  *  Specificando un path di salvataggio, viene gestita la memorizzazione di file generici o immagini.
  *  Inoltre nel caso di modifiche ad immagini, viene automaticamente mostrata una preview all'interno del form.<br /><br />
  *
  *	 Nel caso di password, il form conterrà l'input aggiuntivo per la ri-digitazione. Tali passord verranno memorizzate 
  *  utilizzando la codifica MD5.<br /><br />
  *
  *  Accedendo all'oggetto {@link HTMLForm} membro di DBNavigator tramite il metodo {@link getEditForm()}, 
  *  è possibile <b>personalizzare ulteriormente il form HTML</b>.<br /> 
  *  Ad esempio si può aggiungere al form un semplice codice di verifica anti-hacking (<b>immagine CAPTCHA</b>)<br />
  *  oppure sostituire il formattatore HTML di default con un altro a patto che si inglobi tale formattatore in una classe PHP 
  *  che estenda la classe astratta {@link TextEditorContainer} (si veda il metodo {@link getEditForm()} per ulteriori dettagli).<br /><br />
  *
  *  Modifiche simultanee da parte di più utenti vengono bloccate attraverso un semplice meccanismo di <b>mutua esclusione</b> sui record.
  *  <br /><br />
  *
  *	 CAMPI MYSQL SU INTERFACCIA HTML DI MODIFICA<br /><br />
  *  Ecco una corrispondenza tra i campi MySql ed i controlli HTML automaticamente associati nella costruzione dell'interfaccia di modifica:<br /><br />
  *  <ul>
  *  <li>CHAR/VARCHAR : text input. Su questo tipo di campo è possibile usare 
  *						{@link setMailField()} , {@link setFileField()} , {@link setImageField()} ,
  * 				    {@link setPasswordField()},  {@link setNumericStringField()}.</li>
  *  <li>DATE : 3 select input (giorno,mese,anno). Su questo tipo di campo è possibile usare {@link setMonthYearField()}</li>
  *  <li>INT/BIGINT : text input con validazione di controllo per il formato numero intero</li>
  *  <li>DOUBLE : text input con validazione di controllo per il formato numero con virgola</li>
  *  <li>ENUM : radio input oppure select input se i valori possibili sono molti</li>
  *  <li>SET : checkboxes oppure select input a scelta multipla se i valori possibili sono molti</li>
  *  <li>TEXT/TINYTEXT : textarea input</li>
  *  <li>MEDIUMTEXT/LONGTEXT : formattatore HTML. Vedere {@link getEditForm()} per cambiare qullo di default </li>
  *  <li>CHIAVI ESTERNE DI TIPO NUMERICO: select input che consentira di scegliere uno dei record della tabella esterna</li>
  *  </ul>
  *
  *	 <br /><br />	 
  *  </li>
  *
  *
  * <li> <b>VISUALIZZAZIONE </b><br /><br />
  * Viene mostrato il contenuto dei campi selezionati attraverso una tabella HTML oppure 
  * in maniera completamente definibile dall'utente della classe.<br /><br />
  *  
  * Si può scegliere di abilitare o meno la possibilità di inserire ({@link canInsert()}), modificare({@link canEdit()}) 
  * o eliminare ({@link canDelete()}) elementi. In questo caso viene aggiunta alla tabella l'interfaccia necessaria.<br /><br />
  * 
  * Usando la visualizzazione tabellare standard, è possibile aggiungere delle colonne speciali aggiuntive tramite le funzioni
  * {@link addDataCol()}, {@link addLinkCol()}, {@link addFreeCol()} e {@link addSwitchCol()}.<br />
  * E' importante la funzione {@link addLinkCol()} per permettere di linkare ogni record ad una pagina interna in cui si gestiscono dati relativi 
  * a quel singolo record. Tipico è esempio in cui la pagina interna usa un altro DBNavigator per poter gestire dati memorizzati nel database
  * in relazione 1 a n.<br /><br />
  *
  *
  * In modalità tabellare, l'utente della pagina web ha la possibilità di ordinare i dati in modalità crescente o decescente per ogni campo visualizzato.
  * L'ordinamento di default non deve essere indicato nella query ma attraverso il metodo {@link setDefaultOrd()}
  * <br /><br />
  * </li>
  *
  * <li> <b>AZIONI SPECIALI </b><br /><br />
  * Tramite il metodo {@link canMultipleEditDelete()} può essere abilitata la possibilità di compiere azioni di speciali.<br />
  * Queste azioni si basano sulla tabella generale di visualizzazione, che conterrà delle caselle di scelta (checkbox) per la selezione di un sottoinsieme
  * degli elementi visualizzati.<br /><br />
  *
  * L' <b>eliminazione di gruppo</b> permette di eliminare in solo passo tutti gli elementi selezionati.<br />
  * La <b>modifica sequenziale</b> permette di modificare uno alla volta gli elementi selezionati, 
  * senza dover scegliere il successivo ad ogni modifica.<br />
  * La<b> modifica simultanea</b> è un'azione molto particolare che permette di modificare solo alcuni campi scelti dall'utente. 
  * La modifica di questi campi viene effettuata sugli elementi selezionati in precedenza.
  * <br /><br />
  * </li>
  *
  * <li> <b>RICERCHE TRA I DATI</b><br /><br />
  * 
  * La classe possiede un meccanismo che permette di definire alcuni campi  come campi di ricerca utilizzando
  * il metodo {@link setSearchField()}.<br /><br />
  *
  * Utilizzando le informazioni ricavate dalla <b>scansione testuale della query</b> iniziale, viene 
  * predisposta automaticamente l'interfaccia grafica in modo tale da consentire all'utente di effettuare una ricerca 
  * con gli adeguati controlli, in base al tipo di campo da ricercare.<br /><br />
  *
  * Per ricerche su campi testuali, il campo di ricerca viene corredato da un'utile sistema di auto-completamento automatico 
  * basato su Ajax (<b>AJAX based auto-complete suggestions</b>).<br />
  * Vengono così suggeriti i testi che sono contenuti nel database per facilitare e velocizzare le ricerche.    *  <br /><br />
  *
  * Un'altra funzionalità aggiuntiva riguarda l'esportazione dei dati che può essere applicata all'intero set di dati oppure 
  * ad un sottoinsieme vincolato da parametri di ricerca.<br />
  * I dati possono essere esportati in formato CSV semplice oppure in formato 
  * <b>XML compatibile per la lettura da parte di Microsoft Excel ed OpenOffice Calc</b>.
  *
  * </li>
  * </ul>
  *
  *  <br /><br />
  *  <b>METODI NECESSARI</b><br /><br />
  *  La classe viene attivata col metodo {@link go()} oppure con {@link go_only_for_form()}<br /><br />
  *
  *  Il metodo obbligatoriamente necessario da richiamare è {@link setPrimaryTable()}.<br />
  *  Per il metodo {@link go()} è <b>obbligario richiamare</b> anche i metodi {@link setDefaultOrd()} e {@link setRowName()}.<br /> 
  *	 Inoltre se si usano i metodi {@link setImageField()} e/o {@link setFileField()} è obbligatorio richiamare {@link setFilePath()}.
  *  
  *
  *
  *	<br /><br /><b>NOTA IMPORTANTE</b> ____________________________________________________________<br />
  * La classe ha bisogno di PHP versione 5 configurata con <b>magic_quotes_gpc = On</b>.<br />
  * If you can't have it, try <code>ini_set("magic_quotes_gpc" , "On");</code> 
  * in every script that is expected to do some database modification using DBNavigator.
  * _________________________________________________________________________________<br /><br /><br /> 
  *   
  *  @author Michele Castellucci <ghiaccio84@gmail.com> 
  */	
		
	

class DBNavigator
{


	/// ------ INSTANCE VARIABLES  ------ ///


	/** La query SQL di costruzione della classe
	  * @var string */ 
	private $query="";
	
	/** Il nome della tabella principale tra quelle presenti nella query SQL di costruzione
	  * @see setPrimaryTable
	  * @var string */ 
	private $originalPrimaryTable="";
	
	/** Il nome dell'alias della tabella principale
	  * @see setPrimaryTable
	  * @var string */ 
	private $primaryTable="";
	
	/**  Il nome della chiave primaria della tabella principale 
	  *  @var string */ 
	private $originalPrimaryKey="";
	
	/**  Il nome dell'alias (definito dalla query) della chiave primaria della tabella principale 
	  *  @var string */ 
	private $primaryKey="";
	
	/**  Il nome generico singolare di ogni riga della tabella
	  *  @see setRowName()
	  *  @var string */ 
	private $rowName="";
	
	/**  Informazioni sull'ordinamento: ordinamento di default, ordinamento corrente, desc corrente
	  *  da applicare alla query
	  *  @see setDefaultOrd()
	  *  @var string */ 
	private $orderInfo=array();
	
	/**  Contiene le definizioni dei campi della/e tabella/e richiamate dalla query
	  *  @see scanTable()
	  *  @var array */ 
	private $field=array();
	
	/**  Contiene informazioni sui campi di altre tabelle collegati alla tabella principale
	  *  @see scanTable()
	  *  @var array */ 
	private $externalData=array();
	
	/**  Contiene i nomi dei campi della tabella principale impostati come indirizzi email.
	  *  A tali campi verrà applicata una validazione Javascript e PHP nel form generato in fase di modifica/inserimento
	  *  @see setMailField()
	  *  @var array */
	private $mailField=array();
	
	/**  Contiene i nomi dei campi della tabella principale impostati come password.
	  *  A tali campi verrà applicata una validazione Javascript e PHP nel form generato in fase di modifica/inserimento
	  *  @see setPasswordField()
	  *  @var array */
	private $passwordField=array();
	
	/**  Contiene i nomi dei campi della tabella principale impostati come immagini
	  *  A tali campi verrà applicata una validazione Javascript e PHP nel form generato in fase di modifica/inserimento
	  *  Essa consente in particolare di inserire solo file GIF, JPG, PNG
	  *  @see setPhotoField()
	  *  @var array */
	private $photoField=array('_Resize_'=>"","_KeepOriginal_"=>"");
	
	/**  Contiene i nomi dei campi della tabella principale impostati come file
	  *  A tali campi verrà applicata una validazione Javascript e PHP nel form generato in fase di modifica/inserimento
	  *  @see setPhotoField()
	  *  @var array */
	private $fileField=array();
	
	/**  Contiene il percorso relativo della directory in cui salvare immagini e file
	  *  @see setFilePath()
	  *  @var string */
	private $filePath="";
	
	/**  Contiene il codice esadecimale del colore da applicare come sfondo all'intestazione della tabella di visualizzazione dei dati
	  *  @see setTableRowStyle()
	  *  @var string */
	private $tableHeaderCSS="";
	
	/**  Contiene il codice esadecimale del colore da applicare come sfondo al corpo della tabella di visualizzazione dei dati
	  *  @see setTableRowStyle() 
	  *  @var string */
	private $tableRowContentCSS="";
	
	/**  Valore di margin (cellspacing) della tabella di visualizzazione dati
	  *  @see setTableCellSpacing() 
	  *  @var int */
	private $tableCS=3;
	
	/**  Indica se mostrare o meno la chiave primaria della tabella principale
	  *  @see hidePrimaryKey()
	  *  @var boolean */ 
	private $hidePrimaryKey=false;
	
	/** Indica se e' consentito eliminare record dalla tabella
      * Questa variabile può essere un array che indica gli id dei record di cui è consentita l'eliminazione	
	  * @see canDelete(),canEditDelete(),canMultipleEditDelete(),canInsert()
	  * @var boolean */ 
	private $canDelete=false;
	
	/** Indica se e' consentito modificare record dalla tabella
      * Questa variabile può essere un array che indica gli id dei record di cui è consentita la modifica
	  * @see canDelete(),canEditDelete(),canMultipleEditDelete(),canInsert()
	  * @var boolean */ 
	private $canEdit=false;
	
	/** Indica se e' consentito inserire record nella tabella
	  * @see canDelete(),canEditDelete(),canMultipleEditDelete(),canInsert()
	  * @var boolean */ 
	private $canInsert=false;
	
	
	/** Indica se e' consentito visualizzare i record dalla tabella per la stampa
	  * Se abilitata, viene stampato aggiunto un tasto che apre una nuova finestra contenente i soli dati del record. 
	  * @see canEdit(),canEditDelete()
	  * @var boolean */ 
	private $canViewForPrint=false;
	
	
	/**  Contiene un array contenente i nomi delle 4 classi del foglio di stile da applicare a link e celle della tabella
	  *  1) classe CSS per le celle 'normali' contenenti dati
	  *  2) classe CSS per le celle contenenti i tasti di modifica/insermento
	  *  3) classe CSS per le celle della prima riga della tabella contenenti le intestazioni
	  *  4) classe CSS per le celle contenenti i link aggiunti tramite  {@link addLinkCol()}
	  *  @see setTableStyle() 
	  *  @var array */
	private $style=array('TD'=>'','fieldLink'=>'','headerTD'=>'','editDeleteTD'=>'');

	
	/**  Contiene i nomi (gia' inseriti nel tag: class="nome_classe") delle classi del foglio di stile da applicare a link e celle della tabella.
	  *  @see setTableStyle(),$style 
	  *  @var array */
	private $classTag=array('TD'=>'','fieldLink'=>'','headerTD'=>'','editDeleteTD'=>'');
	
	/**  Contiene un array dove ogni elemento è un array contenete informazioni sulle colonne link aggiuntive 
	  *  stampate nella tabella di visualizzazione dati aggiunte con {@link addLinkCol()}.
	  *  Ad esempio se il link apre una nuova pagina, mantiene gli argomenti GET o viene determinato solo su determinate condizioni
	  *  @see addDataCol(),addLinkCol(),addFreeCol(),addSwitchCol()
	  *  @var array */ 
	private $linkCol=array();

	/**  Contiene un array dove ogni elemento corrisponde ad un attributo che ha due possibili valori
	  *  Ogni elemento corrispondente all'attributo possiede a sua volta informazioni sulle due immagini da associare ai due valori sull'interfaccia.
	  *  @see addDataCol(),addLinkCol(),addFreeCol(),addSwitchCol()
	  *  @var array */ 
	private $switchCol=array();
	
	/**  Contiene un array dove ogni elemento è un array contenente informazioni sulle colonne di dati aggiuntive 
	  *  stampate nella tabella di visualizzazione dati aggiunte con {@link addDataCol()}.
	  *  @see addDataCol(),addLinkCol(),addFreeCol(),addSwitchCol()
	  *  @var array */ 
	private $dataCol=array();
	
	/**  Contiene un array dove ogni elemento è un array contenente informazioni sulle colonne "libere" aggiuntive 
	  *  stampate nella tabella di visualizzazione dati aggiunte con {@link addFreeCol()}.
	  *  @see addDataCol(),addLinkCol(),addFreeCol(),addSwitchCol()
	  *  @var array */ 
	private $freeCol=array();
	
	/**  Contiene i nomi dei campi da rimuovere nel form di inserimento/modifica.
	  *  tali campi non potranno quindi essere modificati/inseriti
	  *  @see removeInput()
	  *  @var array */ 
	private $removeInput=array();
	
	/**  Contiene i nomi dei campi da rimuovere nella tabella di visualizzazione dati standard
	  *  tali campi non saranno visibili in visualizzazione ma potranno essere modificati/inseriti
	  *  @see removeDisplaying()
	  *  @var array */ 
	private $removeDisplaying=array();
	
	/**  Contiene la lista dei campi definiti come campi di ricerca
	  *  @see setSearchField()
	  *  @var array */ 
	private $searchField=array();
	
	/**  Indica se il form di ricerca è stato stampato o meno
	  *  @see search_form()
	  *  @var boolean */ 
	private $search_form_printed=false;
	
	/**  Contiene informazioni sulla cancellazione di righe ricorsiva e linkata ad un'altra tabella
	  *  @see setDeleteRecursive()
	  *  @var array */ 
	private $deleteRecursive=array();
	
	/**  Contiene una istanza della classe HTMLForm che costruisce il form di inserimento/modifica dei record
	  *  @see DBNavigator(),buildForm()
	  *  @var HTMLForm */ 
	private $editForm;
	
	/**  Contiene i 3 nomi delle classi del foglio di stile da associare agli input dell' HTMLForm
	  *  1) classe CSS per textbox/select 
	  *  2) classe CSS per pulsanti 
	  *  3) classe CSS per textarea e textarea con iframe 
	  *  @see setClassForFormInput()
	  *  @var array */ 
	private $classForFormInput=array("inputs"=>"mini","buttons"=>"mini_btn","textareas"=>"mini_txa");
	
	/**  Contiene l'intestazione indicata manualmente del form di inserimento/modifica
	  *  @see setFormHeading()
	  *  @var string */ 
	private $formHeading="";
	
	/**  Indica se visualizzare tutti i record su una pagina (senza paginazione) o meno
	  *  @see showAllElements()
	  *  @var boolean */ 
	private $showAll=false;
	
	/**  Contiene il percorso delle immagini da usare nella visualizzazione tabellare per i tasti (nuovo,stampa,modifica,elimina)
	  *  e degli script (javascript) necessari per la classe.
	  *  @see setImagesAndScriptsPath(), DBNavigator()
	  *  @var string */ 
	private $imagesAndScriptsPath="";
	
	/**  Indica se è stato già richiamato il metodo scanTable (deve essere richiamato una volta sola)
	  *  @see scanTable()
	  *  @var boolean */ 
	private $tableScanned=false;
	
	/**  Contiene i due valori percentuali della dimensione delle 2 colonne del form di inserimento/modifica
	  *  @see setFormWidth()
	  *  @var array */ 
	private $formWidth=array();
	
	/**  Contiene il numero di righe della tabella considerando anche gli eventuali parametri di ricerca correnti
	  *  @see get_rowsNum(), set_rowsNum()
	  *  @var int */ 
	private $rowsNum;
	
	/**  Contiene le stringhe di testo usate all'interno della classe nella lingua impostata  
	  *  @see setLanguage()
	  *  @var array */ 
	private $lang=array();
	

	/**  Indica il numero di caratteri oltre il quale tagliare il valore di un campo nella visualizzazione tabellare
	  *  @see setTextCutLength()
	  *  @var int */ 	
	private $cutLength=150;

	/**  Indica il numero di default di record per pagina da visualizzare
	  *  @see setResultsPerPage()
	  *  @var int */ 		
	private $resultsPerPage=10;

	/**  Indica se visualizzare record senza effettuare una ricerca
	  *  @see setViewResultWithoutSearch()
	  *  @var boolean */ 		
	private $viewResults=true;

	/**  Indica se visualizzare tutte le opzioni degli input SELECT nel form di ricerca 
	  *  indipendentemente dalla presenza del database di record con quei valori
	  *  @see setViewAllSearchOptions()
	  *  @var boolean */ 	
	private $viewAllSearchOptions=false;

	/**  Raccoglie il codice Javascript che sarà inseritò all'interno del metodo window.onload 
	  *  @var string */ 		
	private $JS_onLoad="";

	/**  Indica se utilizzare la tecnologia AJAX per la navigazione (ordinamento/modifica/inserimento)
	  *  @see useAjax()
	  *  @var boolean */ 		
	private $useAjax=false;				
	
	/** Indica se e' consentita la modifica multipla e la mofica contemporanea dei record 
	  * @see canDelete(),canEditDelete(),canMultipleEditDelete(),canInsert()
	  * @var boolean */ 			
	private $canMultipleEditDelete=true;

	/** Contiene un array di due elementi di cui il primo è la data più bassa disponibile, il secondo la più alta
	  * Le date sono selezionabili nel form di inserimento/modifica per i campi definiti DATE nella tabella del database
	  * @see setDateInterval
	  * @var array */ 				
	private $dateInterval=array();

	/** Contiene un array di due elementi corrispondenti al path assoluto (elemento con chiave 'absolute') 
	  * e relativo (elemento con chiave 'relative') dal quale la textarea HTML (con IFRAME) cerca le immagini da inserire sulla textarea stessa.
	  * @see setHTMLTextareaParams()
	  * @var array */ 			
	private $HTMLTextareaParams=array();


	/** Contiene tutte le condizioni (indicate manualmente) per cui una riga deve essere evidenziata
	  * La condizione è una stringa contenente un'espressione booleana PHP.
	  * @see setHighlighting()
	  * @var array */ 		 	
	private $highlighting=array();
	
	/** Contiene le impostazioni riguardanti gli input radio
	  * @see setRadioSettings()
	  * @var array */ 		 	
	private $radioSettings=array('maxOptions'=>8,'maxOptionsInOneLine'=>3);

	/** Contiene le impostazioni riguardanti le checkbox
	  * @see setCheckboxesSettings()
	  * @var array */ 		 	
	private $checkboxesSettings=array('maxCheckboxes'=>10,'multipleSelectSize'=>15);		

	/** Contiene il nome della funzione aggiuntiva da eseguire alla cancellazione di un record
	  * @see setExtraDeletingFunction()
	  * @var string */ 		 	
	private $extraDeletingFunction='';		
	
	/** Contiene la massima dimensione espressa in pixel che una immagine può avere, per altezza o larghezza, nella visualizzazione generale dei dati
	  * @see setImageScaleDimension()
	  * @var int */ 		 		
	private $imageScaleDim=70;

	/** Contiene un nome che descriva il set di dati considerato
	  * @see setDatasetName()
	  * @var String */ 		 		
	private $datasetName="";

	/** Contiene i valori relativi all'abilitazione/disabilitazione degli elementi appartenenti all'interfaccia di navigazione tra pagine.
	  * @see setPageBrowsing()
	  * @var array */ 	
	private $pageBrowsingConfig=array('bylink'=>true,'byselect'=>true,'selectrpp'=>true,'navigationPanelCSS'=>'');

	/** Contiene i nomi delle classi css che sono abbinati ai div contenitori esterni della tabella di visualizzazione generale dei dati
	  * @see addTableContainer()
	  * @var array */ 	
	private $tableContainer=array();


	/** Contiene i nomi delle classi css che sono abbinati alla celle esterne della tabella (ai bordi)
	  * @see setTableBorderStyles()
	  * @var array */ 	
	private $tableBorderStyle=array();

	/** Contiene un oggetto TextEditorContainer che rappresenta il formattatore di testo HTML usato nei form
	  * @see HTMLForm.setHTMLtextEditor()
	  * @var TextEditorContainer */ 	
	private $HTMLtextEditor=false;
	
	/** Indica se mostrare le preview delle immagini nella tabella generale.  
      * @var boolean */	
	private $imageIcon=false;
	
	
	
	  /// -------------------------------   ///
	 /// ------ INSTANCE METHODS  ------  ///
	/// ------------------------------- ///
	
	/** @return string the name of the table definded as primary <br /><br />ITALIAN:<br /> il nome della tabella definita come primaria */
	function getPrimaryTable() { return $this->originalPrimaryTable; }


	/** Enables or closes down the visualization of the elements belonging to the interface of navigation between pages 
	  * 
	  * <br /><br />ITALIAN:<br /> 
	  * Abilita o disabilità la visualizzazione degli elementi appartenenti all'interfaccia di navigazione tra pagine.
	  *
	  * @param bool enables the navigation between pages like a link for each page 
	  *             <br /><br />ITALIAN:<br /> abilita la navigazione tra pagine sotto forma di link per ogni pagina
	  *
	  * @param bool enables the navigation between pages like a square of selection containing all the pages to jump to 
	  *             <br /><br />ITALIAN:<br /> abilita la navigazione tra pagine sotto forma di una casella di selezione contenente tutte le pagine a cui saltare
	  *
	  * @param bool if true enables the selection of results for pages 
	  *             <br /><br />ITALIAN:<br /> abilita la selezione di risultati per pagine
	  *
	  * @param string is the name of the class CSS for the container of all  navigation checks 
	  *               <br /><br />ITALIAN:<br /> nome della classe CSS per il contenitore di tutti i controlli di navigazione
	  */ 	
	function setPageBrowsingConfig($bylink,$byselect,$selectrpp,$navigationPanelCSS='')
	{
		$this->pageBrowsingConfig=array('bylink'=>$bylink,'byselect'=>$byselect,'selectrpp'=>$selectrpp,'navigationPanelCSS'=>$navigationPanelCSS);	
	}
	


	/** Comes back the class that builds the form HTML.<br />
	  * This method can be used to modify the behaviour of that object.<br />
	  * For example you can add a CAPCTHA code<br />
	  * <code> $DBNavigator->getEditForm()->addVerificationCode().</code> <br />
	  * or modify the class wich builds the test format
	  * <code> $DBNavigator->getEditForm()->setHTMLtextEditor(new MY_HTML_FORMATTER_CLASS()).</code> <br />
	  * MY_HTML_FORMATTER_CLASS must upgrade the interface {@link TextEditorContainer} 
	  *
	  * <br /><br />ITALIAN:<br /> 
	  * Ritorna la classe che costruisce il form HTML.<br />
	  * Questo metodo può essere usato per modificare il comportamento di tale oggetto.<br />
	  * Ad esempio si può aggiungere un codice CAPCTHA:<br />
	  * <code> $DBNavigator->getEditForm()->addVerificationCode().</code> <br />
	  *	o modificare la classe che costruisce il formattatore testi HTML :<br />
	  * <code> $DBNavigator->getEditForm()->setHTMLtextEditor(new MY_HTML_FORMATTER_CLASS()).</code> <br />
	  * MY_HTML_FORMATTER_CLASS deve implementare l'interfaccia {@link TextEditorContainer} 
	  * 
	  * @see HTMLForm::setHTMLtextEditor(), TextEditorContainer*/ 	
	function getEditForm() 
	{
		return $this->editForm;
	}


	/** Sets up the names of CSS classes to combine to outside cells of the table of data visualization.
	  * This allows to realize a border graphically elaborated to the general table of data.
	  *
	  * <br /><br />ITALIAN:<br /> 
	  * Imposta i nomi delle classi css da abbinare alle celle esterne della tabella di visualizzazione dati. 
	  * Questo consente di realizzare un bordo graficamente elaborato alla tabella generale dei dati.
	  *
	  * @param string CSS class for the left superior corner cell of the table of data visualization 
	  *				  <br /><br />ITALIAN:<br /> classe CSS per la cella dell' angolo superiore sinistro della tabella di visualizzazione dati.
	  *					  
	  * @param string CSS class for cells of the superior corner of the table of data visualization 
	  *               <br /><br />ITALIAN:<br />classe CSS per le celle del bordo superiore della tabella di visualizzazione dati.
	  *
	  * @param string CSS class for the right superior corner cell of the table of data visualization 
	  * 			  <br /><br />ITALIAN:<br /> per la cella dell' angolo superiore destro della tabella di visualizzazione dati.
	  *
	  * @param string CSS class for right border cells of the table of data visualization 
	  * 			  <br /><br />ITALIAN:<br /> per le celle del bordo destro della tabella di visualizzazione dati.
	  *
	  * @param string CSS class for the right inferior corner cell of the table of data visualization 
	  * 	          <br /><br />ITALIAN:<br /> per la cella dell' angolo inferiore destro della tabella di visualizzazione dati.
	  *
	  * @param string CSS class for inferior berder cells of the table of data visualization 
	  *				  <br /><br />ITALIAN:<br /> per le celle del bordo inferiore della tabella di visualizzazione dati.
	  *
	  * @param string CSS class for the left inferior border cell of the table of data visualization 
	  *				  <br /><br />ITALIAN:<br /> per la cella dell' angolo inferiore sinistro della tabella di visualizzazione dati.
	  *
	  * @param string CSS class for left border cells of the table of data visualization 
	  *				  <br /><br />ITALIAN:<br /> per le celle del bordo sinistro della tabella di visualizzazione dati. 
	  */ 		
	function setTableBorderStyles($topsx,$top,$topdx,$dx,$botdx,$bot,$botsx,$sx)
	{
		$this->tableBorderStyle['topsx']=$topsx;
		$this->tableBorderStyle['top']=$top;
		$this->tableBorderStyle['topdx']=$topdx;
		$this->tableBorderStyle['dx']=$dx;
		$this->tableBorderStyle['botdx']=$botdx;
		$this->tableBorderStyle['bot']=$bot;
		$this->tableBorderStyle['botsx']=$botsx;
		$this->tableBorderStyle['sx']=$sx;
	}	   	



	/** Adds a div container for the table of general data visualization. 
	  * This container can be added to beauty purposes to apply with properties CSS.
	  *
	  * <br /><br />ITALIAN:<br /> 
	  * Aggiunge un div contenitore per la tabella di visualizzazione generali dei dati.
	  * Questo contenitore può essere aggiunto per finalità estetiche da applicare con proprietà CSS.
	  *  
	  * @param string the name of the CSS class to combine to div container. 
	  *			      <br /><br />ITALIAN:<br /> il nome della classe CSS da abbinare al div contenitore.
      */ 		
	function addTableContainer($cssclass)
	{
		$this->tableContainer[]=$cssclass;
	}	   		

	/** Enables or closes down the visualization of elements which compose the navigation interface related to the breakdown into pages of the elements 
	  *
	  * <br /><br />ITALIAN:<br /> 
	  * Abilita o disabilita la visualizzazione degli elementi che compongono l'interfaccia di navigazione relativa alla suddivisione in pagine degli elementi.
	  *
	  * @param boolean enables/closes down the visualization of page choice through link 
	  *				    <br /><br />ITALIAN:<br /> abilita/disabilita la visualizzazione della scelta pagine tramite link
	  *
	  * @param boolean enables/closes down the visualization of page choice through a selection square 
	  *                <br /><br />ITALIAN:<br /> abilita/disabilita la visualizzazione della scelta pagine tramite casella di selezione
	  *
	  * @param boolean enables/closes down the visualization of the choice of the number of results for page 
	  *                 <br /><br />ITALIAN:<br /> abilita/disabilita la visualizzazione della scelta del numero di risultati per pagina
      */ 		
	function setPageBrowsing($byselect,$bylink,$selectrpp)
	{
		$this->pageBrowsingConfig['byselect']=$byselect;
		$this->pageBrowsingConfig['bylink']=$bylink;
		$this->pageBrowsingConfig['selectrpp']=$selectrpp;
	}	   		


	/** Sets up a name which identify the data set considered.
	  * That value is actually used to build the {@link PageNavigator} embedded object.
	  *
	  * <br /><br />ITALIAN:<br />
	  * Imposta un nome identificativo del set di dati considerato. 
	  * Tale valore è attualmente utilizzato per la costruzione dell'oggetto interno {@link PageNavigator}.
	  *
	  * @param String name to identify, and for example students, products, invoices, books, etc. 
	  *				  <br /><br />ITALIAN:<br /> nome identificativo, ed esempio studenti, prodotti, fatture, libri ecc.
	  */ 		
	function setDatasetName($val){$this->datasetName=$val;}	   		


	/** 
	  * @param int represents the maxim pixel dimension with which an image is shownin preview in the table of visualization of general data <br />
	  *            The image is therefore  visualized in the way to be contained in a square box of this dimension: <br />
	  *            The biggest dimension of the image takes up the indicated value while the other one is proportionally browsed.
	  *
	  *			   <br /><br />ITALIAN:<br /> 
	  *			   rappresenta la massima dimensione in pixel con cui una immagine viene mostrata in preview nella tabella visualizzazione generale dei dati.<br />
	  *            L'immagine viene quindi visualizzata in modo da essere contenuta in un box quadrato di questa dimensione: <br />
	  *            la dimensione più grande dell'immagine assume il valore indicato mentre l'altra viene scalata in modo proporzionale. 
	  */ 		
	function setImageScaleDimension($val){$this->imageScaleDim=$val;}	   		


	/**  @param function the name of a function to be performed at the record cancellation and applied on the same record 
	  *				     This way to act is equivalent to a trigger SQL of type ON DELETE. <br />
	  *                  The function must accept a parameter conaining an associative array (obtained from mysql_fetch_array()) 
	  *                  containing the record fields to be deleted.
	  *					 <br /><br />ITALIAN:<br /> 
	  *					 il nome di una funzione da eseguire alla cancellazione di un record e applicata sul record stesso.<br />
	  *         		 Questo modo di agire è acquivalente ad un trigger SQL di tipo ON DELETE. <br />
	  *                  La funzione deve accettare un parametro contenente un array associativo (ricavato da mysql_fetch_array()) 
	  *					 contenente i campi del record da cancellare.
      */ 	
	function setExtraDeletingFunction($function){$this->extraDeletingFunction=$function;}	


	/**  @param boolean Enable or disable the using of Ajax technology for data browsing
	  *                 <br /><br />ITALIAN:<br /> Abilita o meno l'utilizzo della tecnologia AJAX per la navigazione tra i dati */ 	
	function useAjax($bool){$this->useAjax=$bool;}	

	/** Sets up the parameters to go to class {@link TextEditorContainer}.
	  *
	  * <br /><br />ITALIAN:<br /> 
	  * Imposta i parametri da passare alla classe {@link TextEditorContainer} (textarea HTML) 
	  *
	  * @param mixed it depends on the {@link TextEditorContainer} object used. See the doc. for default class (AdvTextarea): {@link Adv_TextArea::setParams()}
	  *              <br /><br />ITALIAN:<br /> 
	  *              dipende dall'oggetto {@link TextEditorContainer} usato. Vedere la doc. per la classe di default (AdvTextarea): {@link Adv_TextArea::setParams()}
	  *  
	  * @see Adv_TextArea::setParams(), TextEditorContainer::setParams()
	  */ 		
	function setHTMLTextareaParams($arr){ $this->HTMLTextareaParams=$arr; }


	/**  @param int number of default of elements for page to print in the  data visualization 
	  *            <br /><br />ITALIAN:<br /> numero di default di elementi per pagina da stampare nella visualizzazione dati  */ 	
	function setResultsPerPage($rpp) { $this->resultsPerPage=$rpp; }


	/**  @param string Name of the language to be used for the file texts shown by the class.<br />
	  *                italian and english texts are availavable. Values to be used are 'english' or 'italian' 
	  *                <br /><br />ITALIAN:<br /> 
	  *                Nome della lingua da usare per i di testo mostrati dalla classe.<br />
	  *                sono disponibili testi in italiano e inglese. I valori da usare sono 'english' o 'italian'. */ 	
	function setLanguage($lang)
	{
		$lang=strtolower($lang);		
		$this->lang['languageName']=$lang;

		if ($lang=='english')
		{
			$this->lang['selection']="Selection";
			$this->lang['edit']="Edit";
			$this->lang['delete']="Delete";
			$this->lang['print']="Print";
			$this->lang['reallyDelete']="Really delete this {$this->rowName} ?";
			$this->lang['insertNew']="Insert new {$this->rowName}";	
			$this->lang['searchOn']="Search for {$this->rowName} according to...";
			$this->lang['ifSelected']="If selected";
			$this->lang['selectAll']="Select all";
			$this->lang['unselectAll']="Unselect all";
			$this->lang['reallyDeleteMultiple']="Really delete selected objects ?";	
			$this->lang['editRecord']="Edit data {$this->rowName}";
			$this->lang['backToData']="Back to general data display";		
			$this->lang['editing']="Editing";
			$this->lang['of']="of";
			$this->lang['select']="Select";	
			$this->lang['errorSended']="Information about error have been sended via e-amil to the admin.";	
			$this->lang['errorFileConflict']="Selected file has a name used by another, rename it.";
			$this->lang['errorKeyConflict']="Inserted data is already present in the archive (value must be unique)";
			$this->lang['errorFormatConflict']="Inserted data isn't in the correct format";
			$this->lang['errorWrongVerCode']="Verify code is wrong";
			$this->lang['errorWrongPassword']="Old inserted value is not correct";	
			$this->lang['find']="Find";
			$this->lang['confirmData']="&nbsp;:: Confirm data ::&nbsp;";
			$this->lang['all']="All";
			$this->lang['noImage']="No image";
			$this->lang['noFile']="No file";
			$this->lang['current']="Current";		
			$this->lang['noResults']="No results";	
			$this->lang['errorFileTooBig']="Selected file is too big for upload";	
			$this->lang['from']="from";
			$this->lang['to']="to";
			$this->lang['goBack']="Go back";
			$this->lang['warningRecordOccupied']="Warning: another user (administrator) is modifying selected record.<br /><br />
												  Wait on this page for the automatic access to the record or"; 
			$this->lang['ascendingOrder']="Ascending order";
			$this->lang['descendantOrder']="Descendant order";
			$this->lang['multipleEditingHeading']="CONTEMPORARY EDITING FOR *** ELEMENTS";
			$this->lang['fieldEnablingControlHeading']="Uncheck fields that you don't want to edit for selected elements";
			$this->lang['errorAvailability']="One or more selected elements is assigned to another user, retry";
			$this->lang['recordHasBeenDeleted']="This element has been deleted";

			 									  				
		}else
		{
			$this->lang['selection']="Selezione";
			$this->lang['edit']="Modifica";
			$this->lang['delete']="Elimina";
			$this->lang['print']="Stampa";
			$this->lang['reallyDelete']="Eliminare veramente questo/a {$this->rowName} ?";
			$this->lang['insertNew']="Inserisci nuovo/a {$this->rowName}";	
			$this->lang['searchOn']="Ricerca {$this->rowName} in base a...";
			$this->lang['ifSelected']="Se selezionati";
			$this->lang['selectAll']="Seleziona tutti";
			$this->lang['unselectAll']="Deseleziona tutti";
			$this->lang['reallyDeleteMultiple']="Eliminare veramente gli oggetti selezionati ?";	
			$this->lang['editRecord']="Modifica dati {$this->rowName}";
			$this->lang['backToData']="Torna alla visualizzazione generale dei dati";
			$this->lang['editing']="Modifica";
			$this->lang['of']="di";
			$this->lang['select']="Selezionare";
			$this->lang['errorSended']="i dati relativi dell'errore sono stati inviati via mail all'amministratore.";	
			$this->lang['errorFileConflict']="Il file selezionato ha un nome utilizzato da un altro file, rinominarlo";
			$this->lang['errorKeyConflict']="il dato inserito è già presente nell'archivio (il valore deve essere univoco)";
			$this->lang['errorFormatConflict']="il dato inserito non è nel formato corretto";
			$this->lang['errorWrongVerCode']="Il codice di verifica è errato";
			$this->lang['errorWrongPassword']="il vecchio valore inserito non è corretto";			
			$this->lang['find']="Cerca";
			$this->lang['confirmData']="&nbsp;:: Conferma dati ::&nbsp;";		
			$this->lang['all']="Tutti";
			$this->lang['noImage']="Nessuna immagine";
			$this->lang['noFile']="Nessun file";
			$this->lang['current']="Corrente";
			$this->lang['noResults']="Nessun risultato";
			$this->lang['errorFileTooBig']="Il file selezionato è troppo grande per eseguire l'upload";
			$this->lang['from']="da";
			$this->lang['to']="a";
			$this->lang['goBack']="Torna indietro";
			$this->lang['warningRecordOccupied']="Attenzione: Un altro utente (amministratore) sta modificando il record selezionato.<br /><br />
												  Attendi su questa pagina l'accesso automatico al record oppure"; 
			$this->lang['ascendingOrder']="Ordine ascendente";
			$this->lang['descendantOrder']="Ordine discendente";
			$this->lang['multipleEditingHeading']="MODIFICA CONTEMPORANEA A *** ELEMENTI";
			$this->lang['fieldEnablingControlHeading']="Selezionare i campi che si desidera modificare per gli elementi selezionati";
			$this->lang['errorAvailability']="Uno o più dei record selezionati è assegnato ad un altro utente, ritentare";	
			$this->lang['recordHasBeenDeleted']="Questo elemento è stato eliminato";											  
		}
		$this->editForm->setLanguage($this->lang['languageName']);
	}

	  
	/**  Sets up a state which stated lined must be highlighted 
	  *  
	  * <br /><br />ITALIAN:<br /> 
	  * Imposta una condizione per cui determinate righe devono evidenziarsi
	  *
	  *  @param string boolean PHP expression which will be valuted through eval().<br /> 
	  *                In the expression you can refer to the field X of every record with {{{X}}}. For example "{{{status}}}=='active'"     
	  *                
	  *                <br /><br />ITALIAN:<br /> espressione booleana PHP che sarà valutata tramite eval(). <br />
	  *				   Nell'espressione ci si può riferire al campo X di ogni record con {{{X}}}. Ad esempio "{{{status}}}=='active'" 
	  *                This parameter is for example of type: 'class="foo" style="color:#F00"'       
	  *
	  *  @param string string containing the definition of the cells tag (their attributes) which containing 
      *                 data of the element founded to be highlighted in the table of data general visualization
	  *
	  *                <br /><br />ITALIAN:<br /> stringa contenente la definizione dei tag delle celle (i loro attributi) che contengono
	  *         	   i dati dell'elemento rilevato come da evidenziare nella tabella di visualizzazione genrale. 
	  *			       Questo paramentro è ad esempio del tipo: 'class="foo" style="color:#F00"'       
	  */ 	
	function setHighlighting($condition,$TDAttributes) { $this->highlighting[]=array('condition'=>$condition,'TDAttributes'=>$TDAttributes); }
	
	/**  @param string text of heading for the action of 'record modify' in thye table of data visualization 
	  *                <br /><br />ITALIAN:<br /> testo di intestazione per l'azione di 'modifica record' nella tabella di visualizzazione dei dati */
	function setEditColHeading($heading) {$this->lang['edit']=$heading;}
	
	/**  @param string text of heading for the action of 'delete record' in the table of data visualization 
	  *                <br /><br />ITALIAN:<br /> testo di intestazione per l'azione di 'elimina record' nella tabella di visualizzazione dei dati */
	function setDeleteColHeading($heading) {$this->lang['delete']=$heading;}
	
	/**  @param string text of heading for the action of 'print visualization' in the table of data visualization 
	  *         <br /><br />ITALIAN:<br /> testo di intestazione per l'azione di 'visualizzazione per la stampa' nella tabella di visualizzazione dei dati */
	function setPrintColHeading($heading) {$this->lang['print']=$heading;}
	
	/**  @param string text of heading for the action of 'record insertion' 
	  *         <br /><br />ITALIAN:<br /> testo di intestazione per l'azione di 'insermento record */
	function setInsertNewHeading($heading) {$this->lang['insertNew']=$heading;}
	
	/**  @param string text of heading for the box of data research 
	  *                <br /><br />ITALIAN:<br /> testo di intestazione per il box di ricerca dati */
	function setSearchHeading($searchHeading) {$this->lang['searchOn']=$searchHeading;}
	
	/**  @param string entry text shown when the research doesn't get results 
	  *                <br /><br />ITALIAN:<br /> testo sentinella mostrato quando la ricerca non produce risultati */
	function setNoResultString($str) {$this->lang['noResults']=$str;}
	
	/**  Sets up the heading keys of modification/elimination multiple of records in the table of data visualization 
	  *  <br /><br />ITALIAN:<br /> Imposta le intestazione dei tasti di modifica/eliminazione multipla dei record nella tabella di visualizzazione dei dati*/
	function setMultipleEditDeleteHeading($ifSelected,$selectAll,$unselectAll,$alertOnDelete) 
	{
		$this->lang['ifSelected']=$ifSelected;
		$this->lang['selectAll']=$selectAll;
		$this->lang['unselectAll']=$unselectAll;
		$this->lang['reallyDeleteMultiple']=$alertOnDelete;
	}

	/**  @param string text of heading for the action of selection in the table of data visualization 
	  *         <br /><br />ITALIAN:<br /> testo di intestazione per l'azione di selezione nella tabella di visualizzazione dei dati */
	function setActionColumnHeader($str) {$this->lang['actionColumnHeader']=$str;}
		
	
	
	
	/** Sets up the break of selectionable dates in the form of insertion/modification for the fields defined DATE in the table of database 
	  *  <br /><br />ITALIAN:<br /> Imposta l'intervallo di date selezionabili nel form di inserimento/modifica per i campi definiti DATE nella tabella del database
	  *
	  * @param int The lowest date which you want to make available <br /><br />ITALIAN:<br /> La data più bassa che si vuole rendere disponibile 
	  * @param int The higher date you want to make available <br /><br />ITALIAN:<br /> La data più alta che si vuole rendere disponibile  */ 	
	function setDateInterval($bottom,$top)
	{
		$bottomFirst=$bottom{0};
		if ($bottomFirst=="+")
		$this->dateInterval[0]=date("Y")+(int)(substr($bottom,1));
		else
		if ($bottomFirst=="-")
		$this->dateInterval[0]=date("Y")-(int)(substr($bottom,1));
		else
		$this->dateInterval[0]=$bottom;
	
		$topFirst=$top{0};
		if ($topFirst=="+")
		$this->dateInterval[1]=date("Y")+(int)(substr($top,1));
		else
		if ($topFirst=="-")
		$this->dateInterval[1]=date("Y")-(int)(substr($top,1));
		else
		$this->dateInterval[1]=$top;
		
	}
	
	/**  Sets up the two dimension in lenght percentual of the form of record insertion/modification .<br />  
	  *  The sum of the two values must be 100(%) 
	  *  
	  *  <br /><br />ITALIAN:<br /> 
	  *  Imposta le 2 dimensioni in percentuale di larghezza del form di inserimento/modifica record.<br />
	  *  La somma dei due valori deve essere 100(%)  
	  *
	  *  @param int 
	  *  @param int */
	function setFormWidth($w1,$w2) {$this->formWidth=array($w1,$w2);}
	
	/**  @param string text of the 'submit' key present in the formof insertion/modification 
					   <br /><br />ITALIAN:<br /> testo del tasto di 'submit' presente nei form di inserimento/modifica */
	function setConfirmFormMsg($m)
	{
		if ($m!="")
		{
			$this->lang['confirmData']=addslashes(str_replace(array("\r","\n")," ",$m)); //eliminate the return back from the beginning <br /><br />ITALIAN:<br /> elimina ritorni a capo
		}
	}


	/**  @param string alert message of confirmation for a record elimination 
	  *         <br /><br />ITALIAN:<br /> messaggio alert di conferma per l'eliminazione di un record */
	function setAlertOnDelete($alert)
	{
		if ($alert!="")
		{
			$this->lang['reallyDelete']=addslashes(str_replace(array("\r","\n")," ",$alert)); //eliminate the return back from the beginning <br /><br />ITALIAN:<br /> elimina ritorni a capo
		}
	}
	
	/**  Used to obtain a string which describes the actual state of  the class 
	  *  This can be useful to make printing actions or other ones in regard to the actual state of the class
	  *  For example <code> if ($OBJ->status=='inserting') echo 'inserting user message';</code>
	  *
	  *  <br /><br />ITALIAN:<br />
	  *  Serve ad ottenere una stringa che descrive lo stato attuale della classe.<br />
      *  Questo può essere utile per poter effettuare azioni di stampa o altro rispetto allo stato attuale della classe.<br />
	  *  Ad esempio <code> if ($OBJ->status=='inserting') echo 'inserting user message';</code>
	  *
	  *  @return string String containing one of these values: inserting, editing, deleting, editingMany, viewing
	  *                 <br /><br />ITALIAN:<br /> Stringa contenente uno di questi valori: inserting, editing, deleting, editingMany, viewing */
	function status()
	{
	
		$pm='_'.$this->originalPrimaryTable;
		
		if (isset($_GET['edit'.$pm]) && $_GET['edit'.$pm]=="") unset($_GET['edit'.$pm]);//get unused <br /><br />ITALIAN:<br /> inutilizzato
	
		if (isset($_GET['del'.$pm]))	return 'deleting';
	
		
		if (isset($_POST['edit'.$pm]) && $_POST['edit'.$pm]==='0') return 'inserting';
		if (isset($_POST['edit'.$pm]) && $_POST['edit'.$pm]==='1') return 'editing';
		
		if (isset($_GET['edit'.$pm]))
		{
			if ($_GET['edit'.$pm]==='0') return 'inserting';
							else return 'editing';	 
		}
		
		if (isset($_GET['action'.$pm]) && isset($_GET['selected'.$pm]) && count($_GET['selected'.$pm])!=0)
		{
			if ($_GET['action'.$pm]=='editMany') return 'editingMany';
			if ($_GET['action'.$pm]=='edit')     return 'editing';
			if ($_GET['action'.$pm]=='delete')   return 'deleting';
		}
		
		return 'viewing';
	}
	
	
	/** @param string name of the field set up as a password.<br />
	  * 			 The field will be published with two fields during the insertion phase (password repeat password)
	  * 			 and 3 fields during the modification phase (old password, new password, repeat new password). <br />
	  * 			 Besides all this data will be memorized usig the MD5 coding.	
	  *
	  *               <br /><br />ITALIAN:<br /> 
	  *   			  nome del campo impostato come una password.<br /> 
	  *               Il campo sarà editabile con 2 campi in fase di inserimento (password,ripeti password)
	  *               e 3 campi in fase di modifica (vecchia password,nuova password,ripeti nuova password).<br />
	  *                Inoltre questi dati saranno memorizzati usando la codifica MD5.
	  * 
	  */
	function setPasswordField($field) {$this->passwordField[$field]="yes";}
	
	/** @param boolean means if in the visualization table must be visualized all records without paging 
	  *        <br /><br />ITALIAN:<br /> indica se nella tabella di visualizzazione devono essere visualizzati TUTTI i record senza paginazione */ 
	function showAllElements($all=true) {$this->showAll=$all;}
	
	/** @param string heading of the insert/modification form  <br /><br />ITALIAN:<br /> intestazione del form di inserimento/modifica
	  * @param string text of the link on the way back to the table of general data visualization <br /><br />ITALIAN:<br /> testo del link di ritorno alla tabella di visualizzazione generale dei dati */
	function setFormHeading($heading,$backLink="")
	{
		$this->formHeading=$heading;
		$this->lang['backToData']=$backLink==""?$this->lang['backToData']:$backLink;
	}
	

	
	/** sets up a linked and/or recursive deletion for records.<br /><br /> 
	  * His effect can be equivalent to the integrity constraint ON DELETE CASCADE but this method will also delete files, stored in the server,
	  * wich are related to the deleted records.
	  *
	  * <br /><br />ITALIAN:<br />
	  * Imposta la cancellazione linkata e/o ricorsiva dei record.<br /><br />
	  * Il suo effetto può essere ecquivalente al vincolo di integrità referenziale ON DELETE CASCADE ma questo metodo eliminerà anche i file, memorizzati
	  * sul server, che sono collegati ai record eliminati.
	  *
	  *	@param string name of the field with which is considered the autojoin of the main table on itself.
	  *				  <br /><br />ITALIAN:<br />nome del campo con cui si considera l'autojoin della tabella principale su se stessa. 
	  *
	  * @param DBNavigator DBNavigator object where is a join between its own main table 
	  *                    and the main table of DBNavigator on which is recalled this method.
	  *                    For join is meant a join in the costruction query.
	  *					   <br /><br />ITALIAN:<br /> oggetto DBNavigator in cui c'è un join tra la propria tabella principale.
	  * 				   e la tabella principale del DBNavigator su cui si richiama questo metodo. 
	  *                    Per join si intende un join nelle query di costruzione. 
	  *					   
	  * @param string warning message to be visualized when you want to eliminate a record that will cause
	  *               the cancellation of other records because of the application of this method.
	  *               <br /><br />ITALIAN:<br />messaggio di avvertimento da visualizzare quando si vuole eliminare un record che provocherà
	  *               la cancellazione di altri record a causa dell'applicazione di questo metodo. 
	  */
	function setDeleteRecursive($chiave_collegata_a_se_stessa,$DBNavigator_esterno=false,$alert="")
	{
		if ($chiave_collegata_a_se_stessa) $this->deleteRecursive['key'][]=$chiave_collegata_a_se_stessa;
		if ($DBNavigator_esterno) $this->deleteRecursive['DBNavigator'][]=$DBNavigator_esterno;
		if ($alert!="") $this->setAlertOnDelete($alert);
	}
	
	/** @param string name of the field that won't be published in the form of insertion/modification
	  *               <br /><br />ITALIAN:<br /> nome del campo che non potrà essere editato nel form di inserimento/modifica.
	  * @see removeDisplaying() */
	function removeInput($inputName){$this->removeInput[$inputName]="yes";}
	
	/** 
	  * Sets up the fields of the table which musn't be shown in the general data visualization specifying the names.<br />
	  * This method accepts a VARIABLE NUMBER OF ARGUMENTS.
	  *
	  * <br /><br />ITALIAN:<br />
	  * Imposta i campi della tabella che non devono essere mostrati nella visualizzazione generale dei dati specificandone i nomi.<br />
	  * Questo metodo accetta un NUMERO VARIABILE DI ARGOMENTI.
	  */
	function removeDisplaying()
	{
		$arg=func_get_args();
		foreach ($arg as $val)
			if (is_string($val))
				$this->removeDisplaying[$val]="yes";
		
	}
	
	/** @param string name of the field that won't be published in the form multiple modification
	  *               <br /><br />ITALIAN:<br /> nome del campo che non potrà essere editato nel form di modifica multipla. .*/	
	function removeMultipleEditingInput($inputName){$this->removeMultipleEditingInput[$inputName]="yes";}
	
	
	/** 
	  * Set up fields to be search fields, giving their names.<br /><br /> 
	  *
	  * The first parameter is a  string like "tablename.fieldname" while the second (optional or to be left blank)
	  * is a string that specifies the name to be visualized in the search form of search fot that field.
	  * If indicated without the name of the table, the field will be considered relative to an aggregation sql like COUNT(*) AS fieldname
	  * and in researches will be insert between HAVING clauses.<br /><br/>
	  *
	  * This method accept a VARIABLE NUMBER OF ARGUMENTS: the two topics can be repeated in pair
	  * setSearchField(F1a,F1b,F2a,F2b,F3a,....)
      *
	  * <br /><br />ITALIAN:<br />
	  * Imposta i campi come campi di ricerca specificandone i nomi.<br /><br />
	  *
	  * Il primo parametro è una stringa del tipo "nometabella.nomecampo" mentre il secondo (opzionale o da lasciare vuoto) 
	  *	è una stringa che specifica il nome da visualizzare nel form di ricerca per tale campo il campo.
	  *	Se indicato senza il nome della tabella, il campo sarà considerato relativo ad una di aggregazione sql come COUNT(*) AS nomecampo
	  *	e nelle ricerche sarà inserito tra le clausole HAVING.<br /><br />
	  *	
	  * Questo metodo accetta un NUMERO VARIABILE DI ARGOMENTI: i due argomenti possono essere ripetuti a coppie 
	  * setSearchField(F1a,F1b,F2a,F2b,F3a,....)
	  *
   	  */
	function setSearchField()
	{
		$func_args=func_get_args();
		
		$i=$j=0;
		$bool=true;
		foreach ($func_args as $key=>$val) //costruisco l'array con i parametri della funzione
		{
			switch ($j)
			{
				case 0: $arg[$i]['fullField']=$val; break;
				case 1: $arg[$i]['alias']=$val; break;
				case 2: $arg[$i]['domainType']=$val; break;
				case 3: $arg[$i]['domainValue']=$val; break;								
			}
			
			$j++;
			if ($j==4) 
			{
				$i++; //indice dell'array di memorizzazione
				$j=0; //indice della scansione dei 4 settaggi
			}
			
		}
		

		foreach ($arg as $key=>$val)
		{				
			
			$exp=explode(".",$val['fullField']);
				
			if (count($exp)==1)//clause su funzioni di aggregazione sql come COUNT(*), CONCAT(.... 
			{
				$arg[$key]['field']=$exp[0]; 
				$arg[$key]['table']="Having";
			}else
			{
				$arg[$key]['table']=$exp[0]; //viene cambiato se presente alias
				$arg[$key]['field']=$exp[1];
			}	
			
			$arg[$key]['table_alias']=$arg[$key]['table']; 
				
		
			if (isset($val['alias']) && $val['alias']!="") $arg[$key]['field_alias']=$val['alias'];
			else
			//if (is_int(strpos($this->query," ".$fullField." AS "))) //CERCA l'[ALIAS DEL CAMPO] !!!!
			if (preg_match("/ {$val['fullField']} AS( |\\n|\\r|\\r\\n)/",$this->query,$pattern)!=false)
			{
				//$exp=explode(" ".$fullField." AS ",$this->query);
				$exp=explode($pattern[0],$this->query);
				$exp2=preg_split("/(,| ){1}/",$exp[1]);
				$arg[$key]['field_alias']=$exp2[0];	
			}
			else $arg[$key]['field_alias'] = $arg[$key]['field'];
		
			if (strpos($this->query," AS ".$arg[$key]['table']." ")!=false) //CERCA l'[ALIAS DELLA TABELLA] per modificare eventualmente table_alias!!!!
			{
				$exp=explode(" AS ".$arg[$key]['table']." ",$this->query);
				$exp2=explode(" ",$exp[0]);
				$arg[$key]['table']=$exp2[count($exp2)-1];						
			} //////////////////////////////////////////////////////////////////////////////////

		}
		
		/*/////////////////////N  O  T  E////////////////////////////////////////////////////////////
			
			Il formato di $fullField deve essere 
			- tabella.campo    
			- alias_tabella.campo
			
			ricavare l'alias DEL CAMPO serve solo a fini di visualizzazione in quanto 
			---> le condizioni where ed having nella query non si devono riferire all'alias di un campo 
				
		*/////////////////////////////////////////////////
		
		if (count($arg)==1)
		{
			$field=$arg[0]['field'];
			$field_alias=$arg[0]['field_alias'];
			$table=$arg[0]['table'];
			$table_alias=$arg[0]['table_alias'];
			$fullField=$arg[0]['fullField'];
			$domainType=$arg[0]['domainType'];
			$domainValue=$arg[0]['domainValue'];										
		}
		else
		for ($i=0; $i < count($arg) ; $i++)
		{
			$field[]=$arg[$i]['field'];
			$field_alias[]=$arg[$i]['field_alias'];
			$table[]=$arg[$i]['table'];
			$table_alias[]=$arg[$i]['table_alias'];
			$fullField[]=$arg[$i]['fullField'];
			$domainType[]=$arg[$i]['domainType'];
			$domainValue[]=$arg[$i]['domainValue'];									
		}
		
		$this->searchField[]=array('field'=>$field,'field_alias'=>$field_alias,'table'=>$table,'table_alias'=>$table_alias,'fullField'=>$fullField,
								   'domainType'=>$domainType,'domainValue'=>$domainValue);		
								   	
	}
	
	/** Removes all fields set up like researching fields
	  * <br /><br />ITALIAN:<br /> Rimuove tutti i campi impostati come campi di ricerca  */
	function clearSearchFields() {$this->searchField=array();}
	
	/** @param mixed String or string array where ther're no HTML entities 
	  *              <br /><br />ITALIAN:<br /> Stringa o array di stringhe in cui non ci sono entità HTML
	  * @return mixed the initial value with which the appropariate characters are replaced with HTML entities ('&amp;' , '&gt;' e '&lt;')
	  *               <br /><br />ITALIAN:<br /> Il valore iniziale in cui i caratteri appropriati vengono sostituiti da entità HTML ('&amp;' , '&gt;' e '&lt;') */
	private function convertSpecialChars($value)
	{	
		if (is_array($value))
		foreach($value as $key=>$val)
		{
			$value[$key]=str_replace("&","&amp;",$value[$key]);
			$value[$key]=str_replace(">","&gt;" ,$value[$key]);
			$value[$key]=str_replace("<","&lt;" ,$value[$key]);
		}
		else 
		{
			$value=str_replace("&","&amp;",$value);
			$value=str_replace(">","&gt;" ,$value);
			$value=str_replace("<","&lt;" ,$value);
		}
	
		return $value;
	
	}
	
	/**
      * Aggiunge una colonna nominata $colName alla tabella della visualizzazione generale dei dati.
	  * Tale colonna avrà come icona $image e linkerà alla pagina corrente se non specificato il parametro $page.	
	  *
	  * <br /><br />ITALIAN:<br />
	  * Adds a column named $colName at data general visualization table.
	  * That column will have as icon $image and will link at the current page if not specified the parameter $page.
	  *
	  *	@param string intestazione della colonna <br /><br />ITALIAN:<br /> heading of the column
	  *	@param string name of the GET parameter to which will be assigned the id of each record 
	  *               <br /><br />ITALIAN:<br /> nome del parametro GET a cui sarà assegnato l'id di ogni record
	  *	@param string  path of the icon image <br /><br />ITALIAN:<br />percorso dell'immagine icona
	  *	@param boolean indicates if the linked page will have to keep the sunbjects GET of the page
	  *                <br /><br />ITALIAN:<br /> indica se la pagina linkata dovrà mantenere gli argomenti GET della pagina.
	  *	@param boolean indicates if the linking page will have to open up in a new window. 
	  *                <br /><br />ITALIAN:<br /> indica se la pagina linkata dovrà aprirsi in una nuova finestra.
	  *	@param mixed string that indicates the linking page. false value indicates the current page 
	  *              <br /><br />ITALIAN:<br /> stringa indicante la pagina linkata. il valore false indica la pagina corrente 
	  *	@param string contains a booleana expression PHP that will be evalueted as condition of the visualization link. Works as {@link setHighlighting()} 
	  *               <br /><br />ITALIAN:<br /> 
	  *               contiene un'espressione booleana PHP che sarà valutata come condizione di visualizzazione del link. Funziona come {@link setHighlighting()}
	  *	@param array contains all field names of the selection SQL where to apply the link in the visualization table. 
	  *              <br /><br />ITALIAN:<br /> contiene tutti i nomi dei campi della selezione SQL a cui applicare il link nella tabella di visualizzazione.
	  */
	function addLinkCol($colName,$arg,$image,$keepGet='',$newWindow=false,$page='',$condition="",$fieldToLink=false)
	{
		if ($page=='') $page=$_SERVER['PHP_SELF'];
		$this->linkCol[]=array('colName'=>$colName,'arg'=>$arg,'image'=>$image,"keepGet"=>$keepGet,"newWindow"=>$newWindow,"page"=>$page,"condition"=>$condition
		,'fieldToLink'=>$fieldToLink);
	}

	/**
	  * Adds a column named $colName at data general visualization table.
	  * The column  corresponds to an attribute in two possible values and the interface will contain the link that will allow to change the value
	  * The link will be active on the image that is shown and that corresponds to the current value of the attribute
	  *
	  * <br /><br />ITALIAN:<br />
	  * Aggiunge una colonna nominata $colName alla tabella della visualizzazione generale dei dati.
	  * La colonna corrisponde ad un attributo a due possibili valori e l'interfaccia conterrà un link che permetterà di cambiarne il valore.
	  * Il link sarà attivo sull'immagine che viene mostrata e che corrisponde al valore corrente dell'attributo
      *
	  *	@param string name of the field of two values <br /><br />ITALIAN:<br /> nome del campo a due valori
	  *	@param string path of the image corresponding to the first value of the attribute
	  *               <br /><br />ITALIAN:<br /> path dell'immagine corrispondente al primo valore dell'attributo
	  *	@param string path of the image corresponding to the second value of the attribute
	  *               <br /><br />ITALIAN:<br /> path dell'immagine corrispondente al secondo valore dell'attributo
	  */  
	function addSwitchCol($colName,$image1,$image2)
	{
		$this->switchCol[$colName]=array('image1'=>$image1,'image2'=>$image2);
	}
	
	/** 
	  * Avoids to show the  contents of the field $field in the general visualization table.<br />
	  * At the place of the contents, is shown a state flage that is an image which simply indicates if the field
	  * is empty or not.
	  * The application in fields set up like images causes the not visualization of the preview.
	  *
	  * <br /><br />ITALIAN:<br />
	  * Evita di mostrare il contenuto del campo $field nella tabella di visualizzazione generale.<br />
	  * Al posto del contenuto, viene mostrato un indicatore di stato ovvero una immagine che segnala semplicemente se il campo 
	  * è vuoto oppure no.
	  * L'Applicazione a campi impostati come immagini ne causa la non visualizzazione della preview.
	  *
	  * @param string the path containing the image that indicates on the field there's an image (the field is full)
	  *               <br /><br />ITALIAN:<br /> il path contenente l'immagine che indica che sul campo è presente una immagine (il campo è pieno) 
	  * @param string the path containing the image that indicates on the field there's not an image (the field is empty)
	  *               <br /><br />ITALIAN:<br /> il path contenente l'immagine che indica che sul campo non è presente una immagine (il campo è vuoto)  
	  */
	function setFieldStatusIndicator($field,$on,$off)
	{
		$this->imageIcon[$field]=array('on'=>$on,'off'=>$off);
	}	
	
	/** 
	  * Adds a column named $colName at the data general visualization table.
	  * That column will have as contents the HTML contained in the parameter $content in which you'll can refer to the current id
	  * with the string '%current_row_id%'.
      *
	  * <br /><br />ITALIAN:<br />
	  * Aggiunge una colonna nominata $colName alla tabella della visualizzazione generale dei dati.
	  * Tale colonna avrà come contenuto l'HTML contenuto nel paramentro $content in cui ci si potrà riferire all'id corrente 
	  * con la stringa '%current_row_id%'.
	  *
	  *	@param string heading of the column  <br /><br />ITALIAN:<br /> intestazione della colonna
	  *	@param string HTML code (with eventual Javascript) of each cell. %current_row_id% is replaced with the id of each record 
	  *               <br /><br />ITALIAN:<br />codice HTML (con eventuale Javascript) di ogni cella. %current_row_id% viene sostituito dall'id di ogni record
	  */
	function addFreeCol($colName,$content)
	{
		$this->freeCol[]=array('colName'=>$colName,'content'=>$content);
	}
	
	/** 
	  * Adds a column named $colName at the data general visualization table.
	  * That column will contain the data got executing the query $query where will have to be present the string '%current_row_id%'
	  * indicating the id of the current record.
	  * That query could be the type defined as $type. Available types are:<br /><br />
	  *
	  * - LINKED_RECORDS simply performs the query which will tipically apply the join with other
	  * tables, unically visualizing the first selected field for each resulting string (lines separated by a back return)<br /><br />
	  *
	  * - RECURSIVE will execute the query in the resorting way through the method {@link query_ricorsiva()} counting the number
	  * of record resortively selected and visualizing that numeric value in the column.<br />
	  * This type of query is tipically used to count elements memorized in tree structures.<br /><br />
	  *
	  * - CALCULATION  asks that the subject query is an array. <br />
	  * In particular each element of that array will have to be an array of two elements with key 'operand' and 'query'.
	  * operand is a string of a character containing a mathematic operator of PHP (+,-,*,/),
	  *query is the query that will have to have a numeric field as first field (also here %current_row_id% will be replaced with the current id).
	  * The class will find the way to execute all the query contained in the array and to link together with their own operand operator. Visualizing the final result
	  * Notice: you can obtain the same result applying sub-queries (subqueries) to the select of initail query. 
	  *
	  *
	  * <br /><br />ITALIAN:<br />
      *
	  * Aggiunge una colonna nominata $colName alla tabella della visualizzazione generale dei dati.
	  * Tale colonna conterrà dei dati ottenuti eseguendo la query $query in cui dovrà essere presente la stringa '%current_row_id%'
	  * indicante l'id del record corrente.
	  * Tale query potrà essere del tipo definito in $type. I tipi disponibili sono:<br /><br />
	  *
	  * - LINKED_RECORDS esegue semplicemente la query che tipicamente applicherà dei join con altre
	  * tabelle, visualizzando unicamente il primo campo selezionato per ogni riga risultante (righe separate da un ritorno a capo)<br /><br />
	  *	  
	  * - RECURSIVE eseguira la query in modo ricorsivo tramite il metodo {@link query_ricorsiva()} contando il numero
	  * di record ricorsivamente selezionati e visualizzando tale valore numerico nella colonna.<br />
	  * Questo tipo di query è tipicamente usato per contare elementi memorizzati in strutture ad albero.<br /><br />
	  *
	  * - CALCULATION richiede che l'argomento query sia un array. <br />
	  * In particolare ogni elemento di tale array dovrà essere a sua volta una array di due elementi con chiavi 'operand' e 'query'. 
	  * operand è una stringa di un carattere contenente un'operatore matematico di PHP (+,-,*,/), 
	  * query è la query che dovra avere un campo numerico come primo campo (anche qui %current_row_id% sarà sostituito dall'id corrente).
	  * La classe fara in modo di eseguire tutte le query contenute nell'array e concatenarle con il loro operatore operand. Visualizzando il risultato finale
	  * Nota: si può ottenere lo stesso risultato applicando delle sotto-query (subqueries) alla select della query iniziale.
	  *	  
	  *	@param string heading of the column <br /><br />ITALIAN:<br /> intestazione della colonna
	  *	@param string query containing the string %current_row_id% which is replaced with the id of each record 
	  *               <br /><br />ITALIAN:<br /> query contenente la stringa %current_row_id% che viene sostituita dall'id di ogni record
	  *	@param string query type <br /><br />ITALIAN:<br /> tipo della query
	  */
	function addDataCol($colName,$query,$type)
	{
		$this->dataCol[]=array('colName'=>$colName,'query'=>$query,'type'=>strtoupper($type));
	}
	
	/** @param boolean Enables/closes down the possibility of multiple modifications/eliminations and contemporary modifications.<br />
	  *                That set is effectively relevant if  the modification and elimination is enabled trough {@link canEdit()} e {@link canDelete()}
	  *                <br /><br />ITALIAN:<br /> 
	  * 			   Abilita/disabilita la possibilità di modifiche/eliminazioni multiple e modifiche contemporanee.<br />
	  * 			   Tale impostazione ha effettivamente rilevanza se è abilitata la modificazione ed eliminazione tramite {@link canEdit()} e {@link canDelete()}
	  */
	function canMultipleEditDelete($apply){$this->canMultipleEditDelete=$apply;}

	/**  @param int number of the maximum characters to be visualized for each field in the general visualization table
	  *             <br /><br />ITALIAN:<br /> numero di caratteri massimi da visualizzare per ogni campo nella tabella di visualizzazione generale */	
	function setTextCutLength($cutLength=150){$this->cutLength=$cutLength;}


	/**  @param boolean indicates if the record visualization must happen even without any research. Default is true. 
	  *                 <br /><br />ITALIAN:<br /> indica se la visualizzazione dei record deve avvenire anche senza effettuare alcuna ricerca. Di default è true 
	  */
	function setViewResultWithoutSearch($bool){$this->viewResults=$bool;}

	/**  @param boolean indicates if visualize all the possible options in the input SELECT of the researching form
	  *                  independently from the presence of the record database with those values or without 
	  *                  <br /><br />ITALIAN:<br /> 
	  *					indica se visualizzare tutte le opzioni possibile negli input SELECT dei form di ricerca
	  *					indipendentemente dalla presenza del database di record con quei valori o meno
	  */	
	function setViewAllSearchOptions($bool){$this->viewAllSearchOptions=$bool;}
	
	/**  @param string path where you can find all the script and images requires from the class.
	  *                The path is searched automatically in pre-defined runs at the moment of an object installation of the class	
	  * 			   but if files are not in those paths, is necessary to recall this method.
	  *                <br /><br />ITALIAN:<br /> 
	  *                path in cui si trovano tutti gli script ed immagini richieste dalla classe.
	  *  			   Il path viene cercato automaticamente in dei percorsi predefiniti al momento dell'instanziazione di un oggetto della classe (nel costruttore)
	  *  			   ma se i file non si trovano in tali path, è necessario richiamare questo metodo. 
      */			
	function setImagesAndScriptsPath($path){ $this->imagesAndScriptsPath=$path; }


	/** 
	  * Sets up the maximum number of radio options that can have a fixed choice field as first paramenter, and
	  * the maximum number of radio options that can have in just one line, as second.
	  * A field which has a number of elements greater than the fisrt parameter, will be published with a select input (instead of radio).
	  * A field which has a number of elements greater than the second parameter, will be visualized with a radio option for each line.
	  *
	  * <br /><br />ITALIAN:<br />
	  * Imposta il numero massimo di opzioni radio che può avere un campo a scelta fissa come primo parametro, e 
	  * il numero massimo di opzioni radio che può avere su una sola riga, come secondo.
	  * Un campo che ha un numero di elementi maggiore del primo parametro, sarà editabile con una select input (anziche dei radio).
	  * Un campo che ha un numero di elementi maggiore del secondo parametro, sarà visualizzato con una opzione radio per riga.	
	  *
	  *
	  * @param int maximum number of options that can have a fixed choice field 
	  *            <br /><br />ITALIAN:<br /> numero massimo di opzioni che può avere un campo a scelta fissa
	  * @param int maximum number of options that can have an input radio in just one line
	  *            <br /><br />ITALIAN:<br /> numero massimo di opzioni che può avere un input radio su una sola riga
	  */ 		 	
	function setRadioSettings($maxOptions,$maxOptionsInOneLine=3)
	{
		$this->radioSettings['maxOptions']=$maxOptions;
		$this->radioSettings['maxOptionsInOneLine']=$maxOptionsInOneLine;
	}

	/**
	  * Sets up the maximum number of checkbox for a multiple choice field (SET) as a first parameter, and
	  * the dimension (number of elements) that will have the multiple choice select if the number of elements of the field exceeds
	  * the first parameter.
	  *
	  * <br /><br />ITALIAN:<br />
	  * Imposta il numero massimo di checkbox per un campo a scelta multipla (SET) come primo parametro, e
	  * la dimensione (numero di elementi) che dovrà avere la select a scelta multipla se il numero di elementi del campo supera
	  * il primo paramentro.
	  *
	  * @param int maximum number of checkbox that can have a multiple choice field
	  *            <br /><br />ITALIAN:<br /> numero massimo di checkbox che può avere un campo a scelta multipla
	  * @param int dimension (number of elements) that will have the multiple choice select which replaces the checkbox in the case of  excess
	  *            <br /><br />ITALIAN:<br /> dimensione (numero di elementi) che dovrà avere la select a scelta multipla che rimpiazza 
	  *            le checkbox in caso di eccedenza
	  */ 		
	function setCheckboxesSettings($maxCheckboxes,$multipleSelectSize) 
	{ 
		$this->checkboxesSettings['maxCheckboxes']=$maxCheckboxes;
		$this->checkboxesSettings['multipleSelectSize']=$multipleSelectSize;  
	}		
	
	
	/** 
	  * Accepts a query of construction of the object that must contain all necessary join with which will make the following elaborations.
	  * Besides creates a table called 'busy_records' which serves
	  * to manage the conflicts of mutual exclusion in the simultaneous record modifications. <br />
	  * That table is used for all instances DBNavigator.
	  *
	  * On edit mode, if the query have some join, an input will be added to associate one of the external table records. 
	  * The <b>first field</b> of the external table in the construction query will be displayied in the form for the
	  * the selection of one external record. 
	  *	  
	  * <br /><br />ITALIAN:<br />
	  * Accetta una query di costruzione dell'oggetto che deve comprendere tutti i join necessari con cui si faranno le successive elaborazioni. <br />
	  * Inoltre crea una tabella chiamata 'busy_records' che serve
	  * a gestire i conflitti di mutua esclusione sulle modifiche simultanee ai record. <br />
	  * Tale tabella è usata per tutte le istanze di DBNavigator.
	  *
	  * In modalità di modifica, se la query di costruzione presenta dei join, verrà inserito in input che permetta di associare uno dei record 
	  * della tabella esterna. Il campo visualizzato nel form per la selezione di quest'ultimo sarà <b>il primo campo</b> della tabella esterna
	  * presente nella query di costruzione. 
	  *
      * @param string Main query.<br />
      *	              WARNING, is assumed that the main query contains ALL the key words SQL
	  *				  in capital (SELECT,FROM,WHERE,HAVING,AS...) while in the internal subqueries (subqueries), if present,
	  *				  the key words must be all small letters. <br />
	  *				  besides is assumed that the query doesn't contain the clause ORDER BY,
	  *				  the regulation field must be set up trough the apposite method {@link setDefaultOrd()}
	  *				  
	  *				  <br /><br />ITALIAN:<br />
	  *			      query principale.<br />
	  *				  ATTENZIONE, si assume che la query principale contenga TUTTE le parole chiave SQL    
	  *               in maiuscolo (SELECT,FROM,WHERE,HAVING,AS...) mentre nelle sotto-query (subqueries) interne, se presenti, 
	  *               le parole chiave dovranno essere tutte minuscole. 
	  *				  Inoltre si assume che la query non contenga la clausola ORDER BY,
	  *				  il campo di ordinamento dovrà essere impostato tramite l'apposito metodo {@link setDefaultOrd()} 
	  *				  
	  */	
	function DBNavigator($query)
	{																						
		$this->setFormWidth(25,75);
		//se non esiste crea la tabella busy_records
		mysql_query("CREATE TABLE IF NOT EXISTS `busy_records` 
		(
		  `table_name` varchar(255) NOT NULL default '',
		  `record_id` varchar(255) NOT NULL default '',
		  `user_session_id` varchar(255) NOT NULL default '',
		  `expire_time` bigint(20) NOT NULL default '0'
		) ;");
	
		mysql_query("DELETE FROM busy_records WHERE expire_time<\"".strtotime("now")."\""); //elimina le ocupazioni 'scadute'
	
	
		//////////////
		if (file_exists('DBNavigator.js')) //cartella corrente dello script
		$this->imagesAndScriptsPath='./';
		else
		if (file_exists('classes/DBNavigator.js'))
		$this->imagesAndScriptsPath='classes/';
		else
		if (file_exists('DBNavigator/DBNavigator.js'))
		$this->imagesAndScriptsPath='DBNavigator/';
		else	
		if (file_exists('webedit/classes/DBNavigator.js'))
		$this->imagesAndScriptsPath='webedit/classes/';
		//else	
		//die ("Can't find Images and Javascript libraries path");
		
		
	
	
/*		$change=array(" on "," On "," oN ");//sostituisce on in maiuscolo
		$query=str_replace($change," ON ",$query);	
		
		$change=array(" as "," As "," aS ");//sostituisce as in maiuscolo
		$query=str_replace($change," AS ",$query);	*/
		
		
		//echo($query."<br><br>");
		//$query=preg_replace("/\(SELECT(.+)\)/","SUBSELECT",$query);	///è un casino...
		//die($query);		
				
/*		$pos=strpos(strtolower($query),"group by");
		if ($pos) //sostituisce il group by in maiuscolo
		{
			$first=substr($query,0,$pos);
			$second=substr($query,$pos+8);
			$query=$first."GROUP BY".$second;	
		}
		
	
		$pos=strpos(strtolower($query),"where");
		if ($pos) //sostituisce il where in maiuscolo
		{
			$first=substr($query,0,$pos);
			$second=substr($query,$pos+5);
			$query=$first."WHERE".$second;	
		}*/
		$this->query=$query;
		$this->dateInterval[0]=date("Y")-90;
		$this->dateInterval[1]=date("Y")+30;
		$this->editForm=new HTMLForm("x","x",25,75); //creo il form a "caso" :non esiste sovraccarico dei costruttori in php4

		$this->PP=new HTMLPostProcessor();
		
		$this->ajaxCall=false;
	
	
	}
	
	/** @param string name of a database table to be considered as the main between the present ones in the construction query of the object
	  *               <br /><br />ITALIAN:<br /> nome di una tabella del database da considerarsi come principale tra quelle presenti nella 
	  *               query di costruzione dell'oggetto */
	function setPrimaryTable($primaryTable) //NECESSARIA
	{
		///echo $this->query;
	
		$this->originalPrimaryTable=$primaryTable;
		$this->primaryTable=$primaryTable; 
	
		if (isset($_GET[$this->originalPrimaryTable.'_suggestField'])) $this->retrieveSuggestOptions();	
	
	
		if (isset($_GET['ajaxCall_'.$this->originalPrimaryTable]))
		{
			$this->ajaxCall=true;
			unset($_GET['ajaxCall_'.$this->originalPrimaryTable]);
	
			if (isset($_GET['manage_record_availability'])) //se c'è questo get allora è uno script di background che sta eseguendo il file
			$this->manage_record_availability_AjaxCall($_GET['manage_record_availability'],isset($_GET['bookRecord'])?true:false);	
			
		}
		else
		$this->ajaxCall=false;
		

		//***********ESECUZIONE SWITCH PRECEDENTI*******************
		if (isset($_GET["switch_field_{$this->originalPrimaryTable}"]))
		{
/*		die("UPDATE {$this->originalPrimaryTable} 
							SET ".$_GET["switch_field_{$this->originalPrimaryTable}"]."=".$_GET["switch_value_{$this->originalPrimaryTable}"]."
							WHERE id=".$_GET["switch_id_{$this->originalPrimaryTable}"]);*/
			mysql_query("UPDATE {$this->originalPrimaryTable} 
							SET ".$_GET["switch_field_{$this->originalPrimaryTable}"]."=".$_GET["switch_value_{$this->originalPrimaryTable}"]."
							WHERE id=".$_GET["switch_id_{$this->originalPrimaryTable}"]) or die(mysql_error());
			
			unset($_GET["switch_id_{$this->originalPrimaryTable}"]);	
			unset($_GET["switch_field_{$this->originalPrimaryTable}"]);
			unset($_GET["switch_value_{$this->originalPrimaryTable}"]);															
		}			
		
		$result=mysql_query("SHOW FULL FIELDS FROM ".$this->originalPrimaryTable);
		while($row=mysql_fetch_array($result))
		{
			switch($row['Comment'])
			{
				case 'mail': $this->setMailField($row['Field']); break;
				case 'numericString': $this->setNumericStringField($row['Field']); break;
				case 'file': $this->setFileField($row['Field']); break; //non usato qui xkè c'è il campo nella tab di configurazione
				//case 'photo': $DBN->setFileField($row['Field']); break;
				case 'DATE_MY': $this->setMonthYearField($row['Field']); break;
			}
		} 	
		
				
	}  

	/**
	  * Method which serves exclusively for the AJAX script of background that questions the database to have a list of suggestions
	  * in the form textbox of research and in the one of contemporaneus modification in more records
	  *
	  * <br /><br />ITALIAN:<br />
	  * Metodo che serve esclusivamente per lo script AJAX di background che interroga il database per avere una lista di suggerimenti
	  * nelle textbox del form di ricerca ed in quello della modifica contemporanea a più record 
	  */
	  
	private function retrieveSuggestOptions()
	{
		ob_end_clean();
	
		$output=array();
		
		if (strlen($_GET[$this->originalPrimaryTable.'_suggestText'])>0)
		{
			$num_suggestions=ceil(8/count($_GET[$this->originalPrimaryTable.'_suggestField']));
			
			foreach($_GET[$this->originalPrimaryTable.'_suggestField'] as $field)
			{
				$_GET[$this->originalPrimaryTable.'_suggestText']=
				$this->convertSpecialChars(str_replace(array("%","_"),array("\%","\_"),addslashes($_GET[$this->originalPrimaryTable.'_suggestText'])));
				
				$query="SELECT {$this->originalPrimaryTable}.{$field} ".substr($this->query,strpos($this->query,"FROM"));
				
				if (strpos($query,"GROUP BY")!==false)
				{
					$query=substr($query,0,strpos($query,"GROUP BY"))." GROUP BY ".$field;
				}
				else
				{
					$query.=" GROUP BY {$field} ";
				}
				
				$query=$this->addWhereConditionToQuery($query,"{$this->originalPrimaryTable}.{$field} LIKE \"".$_GET[$this->originalPrimaryTable.'_suggestText']."%\"")
													   ." ORDER BY {$this->originalPrimaryTable}.{$field} LIMIT 0,{$num_suggestions}";
			
				//echo $query;
				
				$result=mysql_query($query) or die(mysql_error()."<br />".$query);
				while ($row=mysql_fetch_array($result))
				$output[]=$row[$field];
	
			}
			sort($output);//ordina i risultati
		}
		
		die(implode("-###-",$output));
	}

	/** @param string contents of the clause ORDER BY to be added at the main query to order data
	  *               <br /><br />ITALIAN:<br /> contenuto della clausola ORDER BY da aggiungere alla query principale per ordinare i dati */
	function setDefaultOrd($defaultOrd) {$this->orderInfo['defaultOrd']=$defaultOrd;}          //NECESSARIA
	
	/** @param string generic name with which to refer to record.<br /> Example: insert new BOOK, modify BOOK.
	  *               <br /><br />ITALIAN:<br /> nome generico con cui ci si riferisce ai record.<br />Esempio: Inserisci nuovo LIBRO, Modifica LIBRO. 
	  */
	function setRowName($rowName) 																//NECESSARIA
	{
		$this->rowName=$rowName;
	}                      

	/** @param boolean indicates if to show or not the primary key of the main table in the data visualization table.
	  *                <br /><br />ITALIAN:<br /> Indica se mostrare o meno la chiave primaria della tabella principale nella tabella di visualizzazione dei dati.
	  */
	function hidePrimaryKey($boolean) {$this->hidePrimaryKey=$boolean;}           

	/** @param string name of the field of the main table considered as containing an email address. <br />
	  * 			  In the modification/insertion form will be apply a validation that verifies the right format of the typed values.
	  *
	  * 			  <br /><br />ITALIAN:<br />
	  * 			  nome del campo della tabella principale considerato come contenente un indirizzo email. <br />
	  * 			  Nei form di modifica/inserimento verrà applicata una validazione che verifica il formato corretto dei valori digitati. 
	  */
	function setMailField($field) {$this->mailField[$field]="yes";}


	/** @param string name of the field in the main table considered as containing an information month-year.<br />
	  * 			  In the modification/insertion form will be created an interface that will allow to insert month and year trough selection cells.<br />
	  * 			  The indicated field must be like type DATE and the information on the day will be ignored.
	  *               <br /><br />ITALIAN:<br /> 
	  *               nome del campo della tabella principale considerato come contenente un'informazione mese-anno. <br />
	  *               Nei form di modifica/inserimento verrà creata una interfaccia che permetta di inserire mese ed anno tramite caselle di selezione.<br />
	  *               Il campo indicato deve essere di tipo DATE e l'informazione sul giorno verrà ignorata.
	  */
	function setMonthYearField($field) {$this->monthYearField[$field]="yes";}


	/** @param string name of the field of the main table considered as containing numeric strings
	  * 			  In the modification/insertion form will be apply then a validation that will allow to type just numbers
	  *               <br /><br />ITALIAN:<br /> 
	  *               nome del campo della tabella principale considerato come contenente stringhe numeriche.
	  *               Nei form di modifica/inserimento verrà quindi applicata una validazione che consente la digitazione di soli numeri.
	  */
	function setNumericStringField($field) {$this->numericStringField[$field]="yes";}


	/** @param mixed names of a field or an array of field names of tables where are memorized images names present in the filesystem of the server.<br />
	  * 			 In the modification/insertion form will be build an appropriate interface ( FILE input + image preview). <br />
	  * 			 The validation will allow the insertion of file of image type for the web ( GIF, JPEG, PNG ).
	  *              <br /><br />ITALIAN:<br /> 
	  *              nome di un campo o array di nomi di campo di tabelle in cui sono memorizzati nomi di immagini, presenti nel filesystem del server.<br />
	  * 		     Nei form di modifica/inserimento verrà costruita l'interfaccia appropriata ( FILE input + image preview). <br />
	  * 			 La validazione consentirà l'inserimento di file di tipo immagine per il web ( GIF, JPEG, PNG ).
	  *
	  *
	  * @param mixed the value false indicates that the image will not be reduced. <br />
	  *				 A numeric value indicates the size in pixel for which will happen the reduction.
	  *				 <br /><br />ITALIAN:<br /> 
	  *				 il valore false indica che l'immagine non verrà ridimensionata. <br />
	  * 			 Un valore numerico indica la dimensione in pixel per cui avverrà il redimensionamento. 					 
	  *				 
	  * @param boolean Indicates if the original image sent must be saved <br /><br />ITALIAN:<br /> Indica se l'immagine originale inviata deve essere salvata.
	  *
	  * @see setFileNameCriteria()
	  */
	function setImageField($field,$resizeImg=false,$keepOriginal=false) 
	{
		if (is_array($field))
			foreach ($field as $f)
				$this->photoField[$f]=false;
		else
			$this->photoField[$field]=false;
		//la chiave è rilevante, il valore dell'array potrebbe essere qualsiasi cosa
		
		$this->photoField['_Resize_']=$resizeImg;
		$this->photoField['_KeepOriginal_']=$keepOriginal;
		
		$this->PP->setResizeImageDimension($this->photoField['_Resize_']);
		$this->PP->keepOriginalImages($this->photoField['_KeepOriginal_']);
	
	}
	
	/** @see setImageField
	  * @deprecated */
	function setPhotoField($field,$resizeImg=false,$keepOriginal=false) { $this->setImageField($field,$resizeImg,$keepOriginal); }



	/** @param mixed name of a field or array of field names in tables where are memorized file names, present in the filesystem of the server.<br />
	  *              In the modification/insertion form will be build the appropriate interface ( FILE input ). <br />
	  *              <br /><br />ITALIAN:<br /> 
	  *              nome di un campo o array di nomi di campo di tabelle in cui sono memorizzati nomi di file, presenti nel filesystem del server.<br />
	  * 		     Nei form di modifica/inserimento verrà costruita l'interfaccia appropriata ( FILE input ). <br />
	  *
	  * @see setFileNameCriteria()
	  */
	function setFileField($field) 
	{
		if (is_array($field))
			foreach ($field as $f)
				$this->fileField[$f]=false;
		else
			$this->fileField[$field]=false;
	}



	/**
	  * Use this function is right just if there are specified the fields that refer to the files
	  * trough the functions {@link setFileField()} and {@link setImageField()}
	  *
	  * <br /><br />ITALIAN:<br />
	  * Usare questa funzione ha senso solo se si sono specificati i campi che si riferiscono ai file 
	  * tramite le funzioni {@link setFileField()} e {@link setImageField()}  
	  *
	  * @param string the saving path of all files managed by theinside of the filesystem of the server.
	  * 	          <br /><br />ITALIAN:<br /> 
	  *               il path di salvataggio di tutti i file gestiti all'interno del filesystem del server. 
	  *
	  *
	  * @see setFileNameCriteria()
	  */
	function setFilePath($path) 
	{
		$this->filePath=$path;
		$this->PP->setFileSavePath($path);
	} 
	

	/** @param string A symbolic string that represent the format to be used for file names while saving them into the server. Symbols are:<br />
	  *			      <b>*tb*</b> Main table name.<br />
	  *				  <b>*pk*</b> Primary key name in the main table.<br />
	  *				  <b>*cn*</b> Name of the field binded to the file to save.<br />
	  *				  <b>*fn*</b> Name of the original uploaded file.<br />
	  *				  <b>*ext*</b> Extension of the original uploaded file.<br /><br />
	  *				  
	  *				  Default is <b>*tb*_*pk*_*cn*.*ext*</b> which allow to upload as many file as you want without name conflicts.<br />
	  *				  Alternatively, to hold the original file name, use <b>*fn*.*ext*</b>
	  *
	  *  			  <br /><br />ITALIAN:<br /> 
	  *               una stringa simbolica che rappresenta il formato del nome del file da salvare. I simboli sono:<br />
	  *			      <b>*tb*</b> nome della tabella principale.<br />
	  *				  <b>*pk*</b> nome della chiave primaria nella tabella principale.<br />
	  *				  <b>*cn*</b> nome della campo della tabella principale associato al file da salvare.<br />
	  *				  <b>*fn*</b> nome del file originale.<br />
	  *				  <b>*ext*</b> estensione del file originale.<br /><br />
	  *				  
	  *				  L'impostazione di default è <b>*tb*_*pk*_*cn*.*ext*</b> in modo che non possano
	  *				  mai avvenire conflitti sui nomi dei file.<br />
	  *				  Alternativamente, per mantenere l'esatto nome originale del file, usare <b>*fn*.*ext*</b>
      *
	  * @see setFileField(), setImageField(),setFilePath() */
	function setFileNameCriteria($path) 
	{
		$this->PP->setFileNameCriteria($path);
	} 	
	
	
	/** @param string name of the CSS class to apply to the heading lines (tag TR) of the data visualization table
	  *               <br /><br />ITALIAN:<br /> nome della classe CSS da applicare alle righe (tag TR) di intestazione della tabella di visualizzazione dei dati 
	  * @param string name of the CSS class to apply to the internal lines in the data visualization table
	  *               <br /><br />ITALIAN:<br /> nome della classe CSS da applicare alle righe interne della tabella di visualizzazione dei dati  */	
	function setTableRowStyle($val1,$val2) 
	{
		$this->tableHeaderCSS=$val1; 
		$this->tableRowContentCSS=$val2; 
	}
	
	/** @param int  the 'cellspacing' of the data visualization table <br /><br />ITALIAN:<br /> il 'cellspacing' della tabella di visualizzazione dei dati */		
	function setTableCellSpacing($CS) {$this->tableCS=$CS;}
	
	/** @param int the 'cellpadding' of the data visualization table <br /><br />ITALIAN:<br /> il 'cellpadding' della tabella di visualizzazione dei dati */	
	function setTableCellPadding($CS) {$this->tableCP=$CS;}
	
	/** @param string name of the class CSS to apply to intern cells (tag TD) of the data visualization table
	  *               <br /><br />ITALIAN:<br /> 
	  *               nome della classe CSS da applicare alle celle interne (tag TD) della tabella di visualizzazione dei dati
	  * @param string name of the class CSS to apply to cells (tag TD) of the table which contains the buttons related to actions on each line
	  *               <br /><br />ITALIAN:<br />
	  *               nome della classe CSS da applicare alle celle (tag TD) della tabella che contengono i pulsanti relativi alle azioni su ogni riga
	  * @param string name of the class CSS to apply to heading cells (tag TD) of the data visualization table
	  *               <br /><br />ITALIAN:<br /> 
	  *               nome della classe CSS da applicare alle celle di intestazione (tag TD) della tabella di visualizzazione dei dati 
	  * @param string name of the class CSS to apply to links which are added inside the table, through the method {@link addLinkCol()}
	  *               <br /><br />ITALIAN:<br /> 
	  *               nome della classe CSS da applicare ai link, che vengono aggiunti all'interno della tabella, tramite il metodo  {@link addLinkCol()}
	  */		
	function setTableCellStyle($TD,$editDeleteTD,$headerTD,$fieldLink="") 
	{
		if ($TD) {$this->style['TD']=$TD; $this->classTag['TD']=" class=\"".$TD."\"";} 
		if ($editDeleteTD) {$this->style['editDeleteTD']=$editDeleteTD; $this->classTag['editDeleteTD']=" class=\"".$editDeleteTD."\"";} 
		if ($headerTD) {$this->style['headerTD']=$headerTD; $this->classTag['headerTD']=" class=\"".$headerTD."\"";} 
		if ($fieldLink) {$this->style['fieldLink']=$fieldLink; $this->classTag['fieldLink']=" class=\"".$fieldLink."\"";} 
	}
	
	/** @see setTableCellStyle()
	  * @deprecated */	
	function setTableStyle($TD,$editDeleteTD,$headerTD,$fieldLink="") { $this->setTableCellStyle($TD,$editDeleteTD,$headerTD,$fieldLink="");  }
	
	
	/** @param string name of the class CSS to apply to input of the form (tag INPUT).
	  * 			  <br /><br />ITALIAN:<br /> nome della classe CSS da applicare agli input dei form (tag INPUT). 
	  * @param string name of the class CSS to apply to form buttons. 
	  *               <br /><br />ITALIAN:<br /> nome della classe CSS da applicare ai pulsanti dei form.
	  * @param string name of the class CSS to apply to the simple textarea of the form 
	  *               <br /><br />ITALIAN:<br /> nome della classe CSS da applicare alle textarea semplici dei form (tag TEXTAREA).*/	
	function setClassForFormInput($forInputs,$forButtons="",$forTareas="")
	{
		$this->classForFormInput['inputs']=$forInputs;
		if ($forButtons) $this->classForFormInput['buttons']=$forButtons;
		if ($forTareas) $this->classForFormInput['textareas']=$forTareas;
	}	
	
	
	/** @param mixed Indicates if is allowed to eliminate record from the table (true/false)
	  *              or you can give an array of numeric id for which is allowed that action.
	  *               <br /><br />ITALIAN:<br /> 
	  *				 Indica se e' consentito eliminare record dalla tabella (true/false) 
	  *				 oppure si può fornire un array di id numerici per i quali è consentita tale azione. 
	  *				 
	  * @see canEditDelete(),canEdit(),canInsert() */
	function canDelete($boolean_or_id_array){$this->canDelete=$boolean_or_id_array;}
	
	/** @param mixed Indicates if is allowed to modify record from the table (true/false)
	  *              or you can give an array of numeric id for which is allowed that action.
	  *              <br /><br />ITALIAN:<br /> 
	  *              Indica se e' consentito modificare record dalla tabella (true/false)
	  *              oppure si può fornire un array di id numerici per i quali è consentita tale azione.
	  *
	  * @see canEditDelete(),canDelete(),canInsert() */
	function canEdit($boolean_or_id_array) {$this->canEdit=$boolean_or_id_array;}
	
	/** @param boolean Indicates if is allowed to insert record from the table (true/false)
	  *                <br /><br />ITALIAN:<br /> 
	  *                Indica se e' consentito inserire record dalla tabella (true/false) 
	  *
	  * @see canEditDelete(),canDelete(),canInsert() */
	function canInsert($boolean) {$this->canInsert=$boolean;}
	
	/** @param boolean Indicates if is allowed to eliminate and midify record from the table (true/false)
	  *                <br /><br />ITALIAN:<br /> 
	  *                Indica se e' consentito eliminare e modificare record dalla tabella (true/false) 
	  *
	  * @see canEditDelete(),canDelete(),canInsert() */
	function canEditDelete($boolean){$this->canEdit=$boolean;$this->canDelete=$boolean;}
	
	/** @param boolean Indicates if is allowed the exportation of data in format CSV and XML for Excel/OpenOffice
	  *                <br /><br />ITALIAN:<br /> 
	  *                Indica se e' consentita l'esportazione dei dati in formato CSV ed XML per Excel/OpenOffice 
	  */
	function canExport($boolean){$this->canExport=$boolean;}
	
	/** @param boolean Indicates if is allowed to singly visualize record of the table for printing
	  *                <br /><br />ITALIAN:<br />
	  *                Indica se e' consentito visualizzare singolarmente i record dalla tabella per la stampa
	  *
	  * @see canEditDelete(),canDelete() 
	  */
	function canViewForPrint($boolean) {$this->canViewForPrint=$boolean;}
	
	
	/** @param string an SQL query<br /><br />ITALIAN:<br />una query SQL 
	  * @param string an SQL boolean <br /><br />ITALIAN:<br />una condizione booleana SQL 
	  * @return string la query originaria con la condizione $cond aggiunta tra le clausola WHERE della query $query
	  *                <br /><br />ITALIAN:<br /> the originary query with the condition $cond added between the clause WHERE of the query $query
	  */	
	static function addWhereConditionToQuery($query,$cond="")
	{
		if ($cond=="") return $query;
				
				if (strstr(/*strtoupper(*/$query/*)*/,"WHERE"))
				{
					$where="AND"; 
					$exp=explode("WHERE",$query);			
					$query=$exp[0]." WHERE (".$exp[1]; //aggiunge la parentesi in tutto il where				
					$closeBracket=")"; //parentesi chiusa alla fine del where
				}
				else
				{
					$where="WHERE";
					$closeBracket="";			 
				}
				
				if (strpos($query,'GROUP BY'))
				{
					$exp=explode("GROUP BY",$query);			
					$exp[0].="{$closeBracket} $where $cond ";
					$query=implode("GROUP BY",$exp);
				}
				else 
				if (strpos($query,'ORDER BY'))
				{
					$exp=explode("ORDER BY",$query);			
					$exp[0].="{$closeBracket} $where $cond ";
					$query=implode("ORDER BY",$exp);
				}
				else 
				$query.="{$closeBracket} $where $cond ";
				
				return $query;
	}	

	/** @param string an SQL query<br /><br />ITALIAN:<br />una query SQL 
	  * @param string an SQL boolean <br /><br />ITALIAN:<br />una condizione booleana SQL 
	  * @return string la query originaria con la condizione $cond aggiunta tra le clausola HAVING della query $query
	  *                <br /><br />ITALIAN:<br /> the originary query with the condition $cond added between the clause HAVING of the query $query
	  */	
	static function addHavingConditionToQuery($query,$cond="")
	{
		if ($cond=="") return $query;
					
				if (strstr(/*strtoupper(*/$query/*)*/,"HAVING"))
				$where="AND"; 
				else 
				{
					$where="HAVING";
					if (!strpos($query,'GROUP BY')) //se non c'è il group by lo inserisce
					$query.=" GROUP BY {$this->primaryTable}.{$this->originalPrimaryKey} ";
				}	
					
				if (strpos($query,'ORDER BY'))
				{
					$exp=explode("ORDER BY",$query);			
					$exp[0].=" $where $cond ";
					$query=implode("ORDER BY",$exp);
				}
				else 				
			$query.=" $where $cond ";
					
				return $query;
	}		
	

	/** @param mixed the value true indicates if to insert the default image or is possible to indicate the path of another image
	  *              <br /><br />ITALIAN:<br /> 
	  *              il valore true indica se inserire l'immagine di default altrimenti è possibile indicare il path di un'altra immagine
	  * @param mixed the value true indicates if to use the default text as heading or is possible to indicate another text
	  *              <br /><br />ITALIAN:<br /> 
	  *              il valore true indica se usare il testo di default come intestazione altrimenti è possibile indicare un altro testo
	  * @return string the HTML code which includes the insertion button of a new element (made by an image and an heading)
	  *                <br /><br />ITALIAN:<br /> 
	  *                il codice HTML che comprende il tasto di inserimento di un nuovo elemento (costituito da immagine più didascalia)  
	  */		
	function printAddRowButton($image=true,$heading=true)
	{
		//echo $this->status();
		
		if ($this->status()!='viewing' && !$this->useAjax) return false;
		
		if (!$this->canInsert) return false;	
		
		if ($image===true) $image=$this->imagesAndScriptsPath."new.gif";		
		if ($heading===true) $heading=$this->lang['insertNew'];
		
		
		if ($this->useAjax)
		$href="javascript:DBN_{$this->originalPrimaryTable}.buildForm(0,'')";
		else
		$href="{$_SERVER['PHP_SELF']}?".buildQueryString("del_".$this->originalPrimaryTable,"edit_".$this->originalPrimaryTable)."&amp;edit_{$this->originalPrimaryTable}=0#{$this->originalPrimaryTable}_anchor";
		
		return "<a href=\"{$href}\"><img style=\"vertical-align:middle;border:none;\" src=\"".$image."\" alt=\"\" title=\"{$this->lang['insertNew']}\" /> {$heading}</a>";
	}

	/** @param mixed the value true indicates if to insert the default image or is possible to indicate the path of another image
	  *              <br /><br />ITALIAN:<br /> 
	  *              il valore true indica se inserire l'immagine di default altrimenti è possibile indicare il path di un'altra immagine
	  * @param mixed the value true indicates if to use the default text as heading or is possible to indicate another text
	  *              <br /><br />ITALIAN:<br /> 
	  *              il valore true indica se usare il testo di default come intestazione altrimenti è possibile indicare un altro testo
	  * @return string the HTML code which includes the exportation button in CSV format (made by an image and an heading)
	  *                <br /><br />ITALIAN:<br /> 
	  *                il codice HTML che comprende il tasto di esportazione dati in formato CSV (costituito da immagine più didascalia) 
	  */			
	function printCsvDownloadButton($image=true,$heading=true)
	{
		//echo $this->status();
		
		if ($this->status()!='viewing' && !$this->useAjax) return false;
			
		if (!$this->canExport) return false;	
			
		if ($image===true) $image=$this->imagesAndScriptsPath."csv.gif";
		if ($heading===true) $heading="Download ".str_replace("_"," ",$this->originalPrimaryTable)." CSV";
		
		
		return "
		<a href=\"javascript:location.href=DBN_{$this->originalPrimaryTable}.getAjaxUrl()+'&csv_{$this->originalPrimaryTable}';\">
		<img style=\"vertical-align:middle;border:none;\" src=\"".$image."\" alt=\"\" title=\"{$heading}\" />
		{$heading}
		</a>";

	}

	/** @param mixed the value true indicates if to insert the default image or is possible to indicate the path of another image
	  *              <br /><br />ITALIAN:<br /> 
	  *              il valore true indica se inserire l'immagine di default altrimenti è possibile indicare il path di un'altra immagine
	  * @param mixed the value true indicates if to use the default text as heading or is possible to indicate another text
	  *              <br /><br />ITALIAN:<br /> 
	  *              il valore true indica se usare il testo di default come intestazione altrimenti è possibile indicare un altro testo
	  * @return string the HTML code which includes the exportation button in XML format (made by an image and an heading)
	  *                <br /><br />ITALIAN:<br /> 
	  *                il codice HTML che comprende il tasto di esportazione dati in formato XML (costituito da immagine più didascalia) 	  
      */				
	function printExcelXmlDownloadButton($image=true,$heading=true)
	{
		//echo $this->status();
		
		if ($this->status()!='viewing' && !$this->useAjax) return false;
			
		if (!$this->canExport) return false;	
			
		if ($image===true) $image=$this->imagesAndScriptsPath."excel_xml.gif";
		if ($heading===true) $heading="Download ".str_replace("_"," ",$this->originalPrimaryTable)." XML for Excel/OpenOffice";
		
		return "
		<a href=\"javascript:location.href=DBN_{$this->originalPrimaryTable}.getAjaxUrl()+'&excel_xml_{$this->originalPrimaryTable}';\">
		<img style=\"vertical-align:middle;border:none;\" src=\"".$image."\" alt=\"\" title=\"{$heading}\" />
		{$heading}
		</a>";

	}	
	
	
	private function delete_autoJoinedRows_recursive($id,$autoJoinKey)
	{	
			$query="SELECT * FROM {$this->originalPrimaryTable} WHERE {$autoJoinKey}='$id'";
			$result=mysql_query($query) or die ("ERRORE ELIMINAZIONE RICORSIVA: {$query}");
			while ($row=mysql_fetch_array($result))  //seleziona le categorie figlie dirette
			{
				$this->delete($row['id'],true);		
			}			
	}
	
	private function delete_linkedTableRows($id,&$linkedDBN)
	{	
			$linkedDBN->scanTable();
	
			foreach($linkedDBN->externalJoin as $ed) //cerca la chiave collegata alla tabella da cui cancellare ricorsivamente
			{
				foreach($ed as $value) //cerca la chiave collegata alla tabella da cui cancellare ricorsivamente
				if ($ed['ex_table']==$this->originalPrimaryTable)
				{
					$chiave_esterna=$ed['externalKey'];			
					break 2;
				}
				
			}
			

			//print_r($linkedDBN->externalData);

			if (!isset($chiave_esterna)) die("Errata nella cancellazione linkata - non è stata trovata la chiave esterna");
			
			//die(print_r($this->deleteRecursive['DBNavigator']->externalData,true)."<br>$chiave_esterna");
					
			$query="SELECT * FROM {$linkedDBN->primaryTable} WHERE $chiave_esterna='$id'"; 
			//die($query);
			$result=mysql_query($query) or die ("QUERY errata per la cancellazione linkata: ".$query);
			while ($row=mysql_fetch_array($result))
			{
				$linkedDBN->delete($row[$linkedDBN->originalPrimaryKey],true);
			}
				
	}
	
	private function delete($id,$recursiveCall=false)
	{
	
		if ($this->manage_record_availability($id,false)==false) //risolve la cancellazione di un record che sta subendo modifiche
		return false;
						
		if ($recursiveCall)
		$result=mysql_query("SELECT * FROM {$this->originalPrimaryTable} WHERE {$this->originalPrimaryKey}='{$id}'");
		else
		$result=mysql_query($this->addWhereConditionToQuery($this->query," {$this->primaryTable}.{$this->originalPrimaryKey}='{$id}'"));
		
		
		
		if (mysql_num_rows($result)>0)
		{	
			$this->deleteRow($id); //cancella i dati e i file della riga corrente
			
			if (isset($this->deleteRecursive['key']) && is_array($this->deleteRecursive['key']))
			foreach($this->deleteRecursive['key'] as $autoJoinKey)
			$this->delete_autoJoinedRows_recursive($id,$autoJoinKey);
	
			if (isset($this->deleteRecursive['DBNavigator']) && is_array($this->deleteRecursive['DBNavigator']))
			foreach($this->deleteRecursive['DBNavigator'] as $linkedDBN)
			$this->delete_linkedTableRows($id,$linkedDBN);
					
		}
		
		return true;
		
			
	
	}
	
	private function deleteRow($id)
	{	
				$query="SELECT * FROM {$this->originalPrimaryTable} WHERE {$this->originalPrimaryKey}='$id'";
				$result=mysql_query($query);
				$row=mysql_fetch_array($result);
				
				
				if ($this->extraDeletingFunction!='') {$f=$this->extraDeletingFunction; $f($row);}
	
				foreach ($this->photoField as $field=>$bool)
				{ 
					if ($field=="_Resize_" || $field=="_KeepOriginal_") continue; ////da sistemare......? parametri delle immagini nello stesso array
					
						
					if (file_exists($this->filePath."/".$row[$field]) && $row[$field]!="")
						unlink($this->filePath."/".$row[$field]);
					
					if (file_exists($this->filePath."/small_".$row[$field]))				
						unlink($this->filePath."/small_".$row[$field]);
				}	
				
				foreach ($this->fileField as $field=>$bool)
				{ 					
					if (file_exists($this->filePath."/".$row[$field]) && $row[$field]!="")
						unlink($this->filePath."/".$row[$field]);
					
					if (file_exists($this->filePath."/small_".$row[$field]))				
						unlink($this->filePath."/small_".$row[$field]);
				}
				
				$query="delete from {$this->originalPrimaryTable} where {$this->originalPrimaryKey}='$id'";
				mysql_query($query) or die('Eliminazione fallita');
				
				
	}
	
	
	
	private function scanTable() 		//OTTIENE I DATI DELLE COLONNE DELLA QUERY////////////////////////////////
	{
		if ($this->tableScanned==true) return false; else $this->tableScanned=true;

	
		////ricerca alias della tabella
		if (strstr($this->query," ".$this->primaryTable." AS ")) 
		{
			
			$exp=explode(" ".$this->primaryTable." AS ",$this->query);
			$exp=explode(" ",$exp[1]);

			$this->primaryTable=trim($exp[0]); //inserimento dell'alias
			
		}////////////////////////////	
		

/*			$result=mysql_query("SELECT * FROM {$this->originalPrimaryTable}");
			
			$i=0;

			while ($i < mysql_num_fields($result))//Ricerca chiave primaria
			{
				$field = mysql_fetch_field($result);
				if ($field->primary_key==1)	
				{
					
					$this->primaryKey=$field->name; 
					$this->originalPrimaryKey=$field->name;
					break;
				}
			}	*/


		$field_result=mysql_query("SHOW FIELDS FROM $this->originalPrimaryTable");
		$index_result=mysql_query("SHOW INDEX  FROM {$this->originalPrimaryTable}");
		

		//die($this->query);
		$result=mysql_query($this->query." LIMIT 0,1") or die("<strong>QUERY :</strong><br />".$this->query."<br /><b>ERRORE :</b><br />".mysql_error());

		//echo mysql_field_type($result,1);
		
		$i=0;
		while ($i < mysql_num_fields($result))
		{
			
			$field = mysql_fetch_field($result);
			/*echo "<pre>".print_r($field,true)."</pre>";*/
			$field->def=$field->name;
			//echo $this->query;
			
			
			if (preg_match("/ AS {$field->name}( |\\n|\\r|\\r\\n|,)/",$this->query,$pattern)!=false)
			{
				//print_r($pattern);
				$pos=strpos($this->query,$pattern[0]);
				
				
				$temp=str_replace(array("\n","\r"),"",substr($this->query,0,$pos)); //dall'inizio fino al nome del campo

				$commaPos=strrpos($temp,",");
				$pointPos=strrpos($temp,".");
				$spacePos=strrpos($temp," ");
				$max=max($commaPos,$pointPos,$spacePos);
				switch($max)
				{
					case $commaPos: $field->name=substr($temp,$commaPos+1); break;
					case $pointPos: $field->name=substr($temp,$pointPos+1); break;
					case $spacePos: $field->name=substr($temp,$spacePos+1); break;
				}
				
/*						ADESSO IL RICONOSCIMENTO DELLA PRIMARY E' DOPO			
				if ($this->primaryKey==$field->name && $field->table==$this->primaryTable) //correzione nel caso si sia dato l'alias alla chiave primaria 		
				{
					$this->primaryKey=$field->def;		//alias
					$this->originalPrimaryKey=$field->name; //nome campo
				}
				*/
			}
			
			
			
			//-----------------Ricerca chiave primaria-------------------	
			//notare che Field->table può essere l'alias della tabella
			//
			if ($this->primaryKey=='' && $field->table==$this->primaryTable) 
			//if ($field->primary_key==1) //non affidabile con query con join
			{
				mysql_data_seek($index_result,0); 
				while ($idx=mysql_fetch_array($index_result))
				{
					if ($idx['Column_name']==$field->name && $idx['Table']==$this->originalPrimaryTable)
					{
						$this->primaryKey=$field->def; 
						$this->originalPrimaryKey=$field->name;
						break;
					}
				}
			}	
			//-------------------------------------------------------------			
							
								
			
			mysql_data_seek($field_result,0);  //settaggio preciso di field->type creato DA mysql_fetch_field A query SHOW FIELDS from... 
											//corrispondenza mysql_f_fields/query : string/enum('x','y') , blob/text-longtext , double/real , string/varchar(xx)
			while ($row_field=mysql_fetch_array($field_result))
			{
				if (
					 $row_field['Field']==$field->name && 
					 (    substr($row_field['Type'],0,4)=="enum" || $field->type=='blob' || substr($row_field['Type'],0,3)=="set" 
					   || substr($row_field['Type'],0,7)=="varchar"  )
				   )
				   {
				   		$field->type=$row_field['Type'];
						break;
				   }	  						
			}
			$field->type=str_replace("varchar","string",$field->type); //al posto di varchar(100) si mette string(100);
			//echo $field->name." - ".$field->type."<br />";
			
			
		  //////////////////////////////////////////////////////////////////////////

/*			echo "<pre>";
		print_r($field);
		echo "</pre>";	*/
												
				 if (isset($this->fileField[$field->name]))              $field->not_null=array($field->not_null==1,REGEXP_FILE);					
			else if (isset($this->photoField[$field->name]))             $field->not_null=array($field->not_null==1,REGEXP_IMAGE);															
			else if (isset($this->mailField[$field->name]))              $field->not_null=array($field->not_null==1,REGEXP_EMAIL);					
			else if (isset($this->numericStringField[$field->name]))     $field->not_null=array($field->not_null==1,REGEXP_NUMSTRING);
			else if ($field->type=="int")                                $field->not_null=array($field->not_null==1,REGEXP_NUMINT);					
			else if ($field->type=="real")                               $field->not_null=array($field->not_null==1,REGEXP_NUMREAL);
			
			else if ($field->not_null==1)
			{
				if ($field->type=="date") $field->not_null=REGEXP_DATE;
				else					  $field->not_null=REGEXP_NOTNULL; //tutti gli altri casi (anche i non contemplati)
				// string tinytext text mediumtext longtext enum set
			}
			else $field->not_null=false;
								

			// se  $field->table!=$this->primaryTable allora la validazione viene impostata direttamente in buildForm!!!
			
			if (isset($this->passwordField[$field->name])) {$field->type="password";}


		
			$this->field[]=$field;
			//if ($field->primary_key==1 && $field->table==$this->primaryTable) $this->primaryKey=$field->name;
			//if ($_GET['ord']==$field->name) $ord=$field->table.".".$field->name;
			if ($field->table!='' && $field->table!=$this->primaryTable) $externalData[]=array("table"=>$field->table,"field"=>$field->name,"alias"=>$field->def);


			$i++;
		}
		
		if ($this->primaryKey=='') die('CHIAVE PRIMARIA NON TROVATA - '.$this->query); 

	
		//cerca le chiavi secondarie per collegare gli id delle tabelle collegate alla principale con i campi della query 	
	
		//preg_match_all("{((ON .+\..+=.+\..+( OR .+\..+=.+\..+)+)|(ON .+\..+=.+\..+))( |\)|$)}U",$this->query,$join,PREG_SET_ORDER);	
		preg_match_all("{ON .+\..+\s?=\s?.+\..+( |\)|$|\s)}U",$this->query,$join,PREG_SET_ORDER);
	
	
		
/*		echo "<br /><pre>";
		print_r($join);	
	echo "</pre><br />";
	
		echo "<br /><pre>";
		print_r($externalData);	
	echo "</pre><br />";*/
	
		foreach ($join as $clause)
		{
			
			$clause[0]=substr($clause[0],3,strlen($clause[0])); //elimina 'ON '
	
			
			$last_char=substr($clause[0],strlen($clause[0])-1,1);
			if ($last_char==" " || $last_char==")") 
			{
				$clause[0]=substr($clause[0],0,strlen($clause[0])-1);  //elimina l'ultimo carattere se parentesi o spazio
			}
			//echo "'".$clause[0]."'<---<hr>";
			
			
			$link=explode("=",$clause[0]);
			$exp=explode(".",$link[0]);
			$table_link1=trim($exp[0]); $field_link1=trim($exp[1]);
			$exp=explode(".",$link[1]);
			$table_link2=trim($exp[0]); $field_link2=trim($exp[1]);	
			
			
			if ($table_link1==$this->primaryTable)
			{
				$ex_table=$table_link2;
				$ex_primaryKey=$field_link2;
				$externalKey=$field_link1;
			}
			else
			if ($table_link2==$this->primaryTable)
			{
				$ex_table=$table_link1;
				$ex_primaryKey=$field_link1;
				$externalKey=$field_link2;		
			}
			else continue; //(?)
	
			if (isset($externalData) && is_array($externalData))
			foreach($externalData as $key=>$val)
			{ 
	
				if ($val['table']==$ex_table)			
				{
	
					$this->externalData[]=array("ex_table"=>$val['table'],"ex_field"=>$val['field'],"ex_alias"=>$val['alias'],"ex_primaryKey"=>$ex_primaryKey,"externalKey"=>$externalKey);

		
					foreach($externalData as $key2=>$val2) //elimina altri campi collegati della stessa tabella! (perchè tanto vale solo il primo in modifica)
					{
						if ($val2['table']==$ex_table) unset($externalData[$key2]);
					}
					unset($externalData[$key]);
					break;
				}
			}
			
			///così si possono effettuare cancellazioni linkate senza selezionare alcun campo della tabella collegato nel select della query
			$this->externalJoin[]=array("ex_table"=>$ex_table,"ex_primaryKey"=>$ex_primaryKey,"externalKey"=>$externalKey);			
			///
			
		}
		//print_r($this->externalJoin);


		//----------------------------------settaggio dei tipi (domini) dei parametri di ricerca e delle intestazioni
		foreach($this->searchField as $key=>$data)
		{
			
			if ( (!isset($data['domainType']) || $data['domainType']=='') && !is_array($data['field']) ) //se non indicato manualmente viene rilevato il dominio
			{
				$domainType='';
				$domainValue='';
					
				if ($data['table']==$this->originalPrimaryTable)
				{
																		  //metto nell'array associativo i dati dei campi di ogni tabella interessata 
					if (!isset($tableDesc[$data['table']]))				  //ogni volta che ne trovo una, la chiave è il nome del campo
					{
						$result=mysql_query("DESCRIBE {$data['table']}");
						while($row=mysql_fetch_array($result)) 
						{
							$tableDesc[$data['table']][$row['Field']]=$row;
						}
					}					
				
					if (isset($tableDesc[$data['table']][$data['field']]) )//campo semplice della tabella in questione.... 																						
					{

						$FieldType=$tableDesc[$data['table']][$data['field']]['Type'];
				
						if (strstr($FieldType,"enum") || strstr($FieldType,"set") ) //guarda se è enum
						{
							$domainType='list';
							$domainValue=$this->getEnumSetValue($FieldType);							
						}
						
						if (strstr($FieldType,"date")) //guarda se è una data
						{
							$domainType='date';
							$domainValue=array(""=>"Tutte le date");
							
							$result=mysql_query("SELECT {$data['field']} FROM {$this->originalPrimaryTable} GROUP BY {$data['field']}");
							while ($row=mysql_fetch_array($result))
							{
								$exp=explode("-",$row[$data['field']]);
								$domainValue[$row[$data['field']]]=$exp[2]."/".$exp[1]."/".$exp[0];
							}
						}
						if (   strstr($FieldType,"bigint") || strstr($FieldType,"int") 
							|| strstr($FieldType,"float")  || strstr($FieldType,"double")  )  //guarda se è un numero
						{
							$domainType='numeric';
							$domainValue=false;   //non utilizzato..	
						}
						//else .....domainType==''....text!
					}								

				}
				else 
				if ($data['table']!=$this->originalPrimaryTable && $data['table']!="Having") // @------ TABELLA ESTERNA			
				{
					$domainType='list';
					$domainValue=array();																			
																							
					if ($this->viewAllSearchOptions)
					{
						$q="SELECT {$data['field']} FROM {$data['table']} ORDER BY {$data['field']}";				
					}
					else
					{
						$from=strstr($this->query,"FROM");
						$group_by_pos=strpos($from,"GROUP BY");
						if ($group_by_pos)	$from=substr($from,0,$group_by_pos);
					
						$q="SELECT {$data['table_alias']}.{$data['field']} $from ORDER BY {$data['table_alias']}.{$data['field']}";				
					}

					//echo $q."<hr>";
					$result=mysql_query($q) or print ("<br /><br />errore query della select per la ricerca : <br /><br /> 
																	QUERY:<br /> ".$q."<br /><br />ERRORE:<br /> ".mysql_error()."<br />");						
					while ($row=mysql_fetch_array($result))
					if ($row[$data['field']]) $domainValue[$row[$data['field']]]=$row[$data['field']];
					

				}					
				else // x default campi definiti come risultato di funzioni (nella clausola having della query) vengono interfacciate con ricerca numerica				
				if ($data['table']=="Having")
				{
					$domainType='numeric';
					$domainValue=false;   //non utilizzato..		
									
				}						
				// altri casi....credo non ci siano....se non rientra nei casi sopra, l'interfaccia è di testo libero
							
				$this->searchField[$key]['domainType']=$domainType;
				$this->searchField[$key]['domainValue']=$domainValue;
			
			}


			////////////// solo qui viene cercato e memorizzato il valore (value) assunto da ogni campo di ricerca ///////////////////////				
			///*************************** settaggio della tipologia del campo di ricerca (1234) usato solo per costruire la query ******************
			if (!is_array($data['field'])) //ricerca 'normale'
			{
				
				$get_index=$data['table_alias']."_".$data['field']."_src_".$this->originalPrimaryTable;
			
				
				if (isset($_GET[$get_index]) )
				{
					if (is_array($_GET[$get_index])) 
					{
						$data['value']=array();
						
						foreach($_GET[$get_index] as $multiple=>$val)
							$data['value'][]=trim(stripslashes($val));
						$this->searchField[$key]['tipo_ricerca']='1'; //ricerca vincolata (select o radio)			
					}
					else 
					if (	 substr(trim(stripslashes($_GET[$get_index])),0,1)=='"' 
						  && substr(trim(stripslashes($_GET[$get_index])),strlen(trim(stripslashes($_GET[$get_index])))-1,1)=='"'   )						
					{			
						$data['value']=trim(stripslashes($_GET[$get_index]));
						$this->searchField[$key]['tipo_ricerca']='2'; //ricerca libera di una FRASE con - davanti								
					}
					else 
					{ 
						$data['value']=isset($_GET[$get_index])?trim(stripslashes($_GET[$get_index])):"";
						
						$this->searchField[$key]['tipo_ricerca']='3';  //ricerca libera con una parola
					
						/*in questo ramo rientra anche la ricerca di un campo aggregato che viene cercato nella whery con un like (considerato testo semplice)*/
					
					}					
				
				}					
				else if (isset($_GET[$get_index."_start"]) ) //&& isset($_GET[$get_index."_end"])) ------ se c'è start c'è end
				{ 
					$data['value']['start']=$data['value']['end']="";
	
					if (is_numeric($_GET[$get_index."_start"]) || preg_match("/^\d{4}-\d{2}-\d{2}$/",$_GET[$get_index."_start"]))
						$data['value']['start']=trim($_GET[$get_index."_start"]);
	
					if (is_numeric($_GET[$get_index."_end"]) || preg_match("/^\d{4}-\d{2}-\d{2}$/",$_GET[$get_index."_end"]))
						$data['value']['end']=trim($_GET[$get_index."_end"]);
					
					$this->searchField[$key]['tipo_ricerca']='4';  //ricerca numerica (...intervalli)
				}	
				else 
					continue; ////nessuna ricerca ancora effettuata																
		
			}
			else // //più campi di ricerca con un unico testo
			{
				$get_index="";
				foreach ($data['field'] as $val)
				$get_index.=$val."_";
				 
				$get_index.="src_".$this->originalPrimaryTable;
				$data['value']=isset($_GET[$get_index])?trim(stripslashes($_GET[$get_index])):"";
				
				$this->searchField[$key]['tipo_ricerca']='3';					
			}	
			
	
			
			

			if (is_array($data['value']))
			{				
				foreach ($data['value'] as $k=>$v)		 
					$data['value'][$k]=addslashes($this->convertSpecialChars($v));		
			}
			else
				$data['value']=addslashes($this->convertSpecialChars($data['value']));
			
			$this->searchField[$key]['value']=$data['value']; // SALVATAGGIO FINALE !
			
			// MEMO: il value è utilizzato per costruire il form di ricerca (necessario stripslashes) e per fare le condizioni della query SQL			
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////			

		}
	
	
	}
	
	private function form_error_handling($error_code,$error_field)
	{
		$error_field_2=str_replace("_"," ",ucfirst($error_field));
	
		switch ($error_code)
		{
			
			case 'availability_error': //in realtà questo errore non si dovrebbe verificare MAI perchè ci sono le prenotazioni dei record modificati simultaneamente
					echo "<strong style=\"color:#F00\">{$this->lang['errorAvailability']}</strong>";
					break;
			case 'query_error':
				
				mail("ghiaccio84@gmail.com","DBN debug: ".$_SERVER['HTTP_HOST']
				,$error_field."<br />".$_SERVER['PHP_SELF']."<br /><br /><br /><pre>".print_r($_GET,true)."</pre><br /><hr /><pre>".print_r($_POST,true)."</pre><br /><hr />
				<pre>".print_r($_FILES,true)."</pre>"
				,"Content-Type: text/html; charset=utf-8\r\n");
				
				$showed_error= "Query error: $error_field <br />{$this->lang['errorSended']}";  //mail for debug
							   echo $showed_error; break;		
						
			case 'file_conflict':$showed_error= "$error_field_2: {$this->lang['errorFileConflict']}";	
							$this->editForm->setFocused($error_field,$showed_error); break;		
			
			case 'key_conflict':    $showed_error= "$error_field_2: {$this->lang['errorKeyConflict']}";		
							$this->editForm->setFocused($error_field,$showed_error); break;		
	
			case 'format_conflict':$showed_error= "$error_field_2: {$this->lang['errorFormatConflict']}";	
							$this->editForm->setFocused($error_field,$showed_error); break;	
							
			case 'wrong_vercode':$showed_error= "$error_field_2: {$this->lang['errorWrongVerCode']}";	
							$this->editForm->setFocused($error_field,$showed_error); break;		
									
			case 'wrong_pwd':$showed_error= "$error_field_2: {$this->lang['errorWrongPassword']}"; 
						$this->editForm->setFocused($error_field."_old",$showed_error);	break;
						
			case 'file_too_big':$showed_error= "$error_field_2: {$this->lang['errorFileTooBig']}"; 
						$this->editForm->setFocused($error_field,$showed_error);	break;					
		}
		//echo $this->formHeading['heading']." <em>...errore</em>";
	}
	
	private function manage_record_availability_AjaxCall($id,$bookRecord)
	{
		if (!is_array($id)) //metodo buildform AJAX
		{
			if ($this->manage_record_availability($id,$bookRecord)==true)		
			{
				die('!!!!!!');
			}
			else
			die('');
		}else //metodo delete_, multipleDelete AJAX
		{
			$occupied=false;
			
			foreach($id as $i)
			if (!$this->manage_record_availability($i,$bookRecord)) 
			$occupied=$i;
			//die('!!!!!!'.$i);
			
			if ($occupied===false)
			die('!!!!!!');
			
			//die('!!!!!!'.$occupied);
		}	
	}
	
	private function commonAjaxFunctions()
	{
	
		return "
		<script type=\"text/javascript\" src=\"{$this->imagesAndScriptsPath}autosuggest.js\"></script>
		<script type=\"text/javascript\" src=\"{$this->imagesAndScriptsPath}zxml.js\"></script>
		<script type=\"text/javascript\" src=\"{$this->imagesAndScriptsPath}DBNavigator.js\"></script>
		<script type=\"text/javascript\">
		<!--
		
		var imagesAndScriptsPath='{$this->imagesAndScriptsPath}';
	
		var DBN_{$this->originalPrimaryTable}=new DBNavigator('DBN_{$this->originalPrimaryTable}','{$this->originalPrimaryTable}');
		
		-->
		</script>
		";
	
	}
	
   /** 
	 * This is the special function that runs the execution of DBNavigator in the way of sinlge insertion or single modification.<br /><br />
	 * It must be recalled after the methods of configuration set...and that arouses the printing of the adeguate form HTML.
	 * Storing data/files at the moment of the form completion by the user, is managed automatically
	 * reproducing a confirmation page.
	 *
	 *  <br /><br />ITALIAN:<br />
	 *  Questa è la speciale funzione che avvia l'esecuzione di DBNavigator in modalità di singolo inserimento o singola modifica.<br /><br />
	 *  Deve essere richiamata dopo i metodi di configurazione set...  e provoca la stampa dell'adeguato form HTML.
	 *  Il salvataggio dei dati/files al momento del completamento del form da parte dell'utente, viene gestito automaticamente
	 *  riportando una pagina di conferma.
	 *
	 *  @param int the numeric id of the record to be modified or zero (false) if that is an insertion
	 *             <br /><br />ITALIAN:<br />
	 *             l'id numerico del record da modificare oppure zero (false) se si tratta di un inserimento 
	 *             
	 *  @param string the text HTML to visualize in the confirmation page following the form completion
	 *                <br /><br />ITALIAN:<br /> 
	 *                il testo HTML da visualizzare nella pagina di conferma successiva al completamento del form 
	 *
	 *  @param function name of a function php without paramenters that is recalled after the insertion or the modification
	 *                  (empty string if you don't want to use any function).<br />
	 *                  The use of this functionality has an impact similar to the one of a trigger SQL of type AFTER UPDATE/INSERT. <br />
	 *                  <br /><br />ITALIAN:<br />
	 *                  nome di una funzione php senza paramentri che viene richiamata dopo l'inserimento o la modifica 
	 *					(stringa vuota se non si vuole usare alcuna funzione).<br />
	 *					 L'uso di questa funzionalità ha un effetto simile a quello di un trigger SQL di tipo AFTER UPDATE/INSERT. <br />	
	 *
	 *   	   
	 *  @param array makes up a data structure which serves to make substitutions in the code HTML generated by the class.<br />
	 *               The array must be associative: each element has KEY equal to the text to be replaced and equal VALUE to the text of replacement.<br />
	 *               Like key you can also use a text which will contain a regular expression causing the substitution of text parts
	 *               in match with the expression ( parsed by preg_replace() ). 
	 *               <br /><br />ITALIAN:<br /> 
	 *               costituisce una struttura dati che serve ad effettuare delle sostituzioni nel codice HTML generato dalla classe.<br /> 
	 *               L'array deve essere associativo: ogni elemento ha CHIAVE uguale al testo da sostituire e VALORE uguale al testo di rimpiazzo.<br /> 
	 *				 Come chiave si può anche usare un testo che contenga una regular espression causando la sostituzione delle parti di testo
	 *				 in match con l'espressione ( valutata dalla funzione preg_replace() ). 
	 */
	function go_only_for_form($id,$successMsg="Inserimento/modifiche effettuato/e",$after_query_function="",$replace_array=null)
	{
		$this->main($after_query_function,true);
			
		if (!$this->ajaxCall) 
			echo $this->commonAjaxFunctions()."<div id=\"{$this->originalPrimaryTable}_form_anchor\">"; //ancora
		else 
			ob_end_clean();	
		
		//print_r($_POST);
		//print_r($_FILES);
	
		if (isset($_GET['success_'.$this->originalPrimaryTable]))
		echo $successMsg;
	
		if (!isset($_GET['success_'.$this->originalPrimaryTable]))
		echo $this->buildForm($id,$replace_array,false);
	
		if ($this->ajaxCall) die('');
		else
		echo "<script type=\"text/javascript\">
			  <!--	
					if (typeof(window.onload)=='function')
					{					
						var oldonload_2_{$this->originalPrimaryTable}=window.onload;
						
						window.onload=function()
												{
													document.onmousemove=handlemousemove;
													{$this->JS_onLoad}
													oldonload_2_{$this->originalPrimaryTable}();
												}		
	
					}
					else
					window.onload=function()
											{
												document.onmousemove=handlemousemove;
												{$this->JS_onLoad}
	
											}			
			  -->
			  </script>";
	
		echo "</div>"; //fine ancora	
		
	}	
	
	
	private function main($after_query_function="",$onlyForm=false)
	{
		if (!isset($this->lang['languageName'])) $this->setLanguage("italian"); //lingua predefinita
		
		//echo $this->status();
		
		$this->scanTable();
		//print_r($_GET);
		//print_r($_FILES);	
	
		if (isset($_POST["frm_{$this->originalPrimaryTable}_submit"]))
		{	
		
			foreach($this->passwordField as $field=>$unused) //GESTIONE DELLLE PASSWORDS
			if (!$this->managePassword($field))
			{
				$password_error=$field;
				break; 
			}
			
			$availability_error=false;
			if (is_array($_POST[$this->originalPrimaryKey]))//in go_only_for_form non c'è modifica multipla
			{		
				
				foreach($_POST[$this->originalPrimaryKey] as $id)
				{
					if (!$this->canEdit || (is_array($this->canEdit) && !in_array($id,$this->canEdit) ) )
					{
						$availability_error=true;
						break;
					}
					
				   if (!$this->manage_record_availability($id,false)) //al primo record che è in modifica da qualche altro, ferma la MODIFICA e prenota la modifica per il record
				   {
						
						$availability_error=true;	
						break;
				   }
				}
			}//////////////////////////////////////////////////////////////////////////
	
			if (!isset($password_error) && $availability_error!=true) //inserisce solo senza errore di password (altrimenti MODIFICA il record)
			{	
				$esitoPP=$this->PP->act($this->originalPrimaryTable,"frm_{$this->originalPrimaryTable}_submit",$this->originalPrimaryKey);
			}
			
			if (isset($password_error) || $esitoPP!=1 || $availability_error==true) //errore
			{
				if (isset($password_error))
				{
					$error_code='wrong_pwd';
					$error_field=$password_error;
				}else if ($esitoPP!=1) //0 non può essere perchè c'è un if all'inizio che controlla il submit_button
				{			
					$error_code=$esitoPP[0];
					$error_field=$esitoPP[1];
				}else if ($availability_error) //in go_only_for_form non c'è modifica multipla
				{
					$error_code="availability_error";
					$error_field="";
				}
				$this->form_error_handling($error_code,$error_field);
			}				
			else 
			{
				if ($after_query_function!="") 
				{
					//if (is_callable(array($after_query_function,'doIt'),true))  //passato un oggetto
					//if (is_callable($after_query_function,false))
					
					if (is_object($after_query_function))  //passato un oggetto
						$after_query_function->doIt();   //si richiama il metodo doIt();
					else 
						$after_query_function();
					
				}
				
				if ($onlyForm) 
				die("<script type=\"text/javascript\">location.href=('".$_SERVER['PHP_SELF']."?".html_entity_decode(buildQueryString())."&success_{$this->originalPrimaryTable}#{$this->originalPrimaryTable}_form_anchor');</script>"); 
	
	
				if (isset($_GET["selected_".$this->originalPrimaryTable]))//elimina il get del record modificato
				{
					if ($_GET["action_".$this->originalPrimaryTable]=='edit')
					{
						array_shift($_GET["selected_".$this->originalPrimaryTable]);			
						if (count($_GET["selected_".$this->originalPrimaryTable])==0) 
						{
							unset($_GET["sellen_".$this->originalPrimaryTable]);
							unset($_GET["action_".$this->originalPrimaryTable]);
							unset($_GET["selected_".$this->originalPrimaryTable]);
						}
					}
					else 
					if ($_GET["action_".$this->originalPrimaryTable]=='editMany')
					{
						unset($_GET["sellen_".$this->originalPrimaryTable]);
						unset($_GET["action_".$this->originalPrimaryTable]);
						unset($_GET["selected_".$this->originalPrimaryTable]);
					}
					else if ($_GET["action_".$this->originalPrimaryTable]=='del')
					$_GET["del_".$this->originalPrimaryTable]=array_shift($_GET["selected_".$this->originalPrimaryTable]);		//?? non serve?			

					echo "<script type=\"text/javascript\">location.href=(\"".$_SERVER['PHP_SELF']."?".html_entity_decode(buildQueryString())."#{$this->originalPrimaryTable}_anchor\");</script>"; 
	
				}else
				{
					unset($_GET["sellen_".$this->originalPrimaryTable]);
					unset($_GET["action_".$this->originalPrimaryTable]);							
					echo "<script type=\"text/javascript\">location.href=(\"".$_SERVER['PHP_SELF']."?".html_entity_decode(buildQueryString('edit_'.$this->originalPrimaryTable))."#{$this->originalPrimaryTable}_anchor\");</script>"; 
				
				}
			}
			
		}	
	}
	
	
   /** 
	 * This is the special function that runs the execution of DBNavigator in full mode.<br /><br />
	 * It must be recalled after the methods of configuration set...and arouses the visualization af the whole interface of
	 * research, modification, insertion, ecc. and the automatic management of all the correspondent actions.
	 *
	 *  <br /><br />ITALIAN:<br />
	 *  Questa è la speciale funzione che avvia l'esecuzione di DBNavigator in modalità di singolo inserimento o singola modifica.<br /><br />
	 *  Deve essere richiamata dopo i metodi di configurazione set...   e provoca la visualizzazione di tutta l'interfaccia di 
	 *  ricerca, modifica, inserimento ecc. e la gestione automatica di tutte le azioni corrispondenti.
	 *
	 *  @param function name of a function php without paramenters that is recalled after the insertion or the modification
	 *                  (empty string if you don't want to use any function).<br />
	 *                  The use of this functionality has an impact similar to the one of a trigger SQL of type AFTER UPDATE/INSERT. <br />
	 *                  <br /><br />ITALIAN:<br />
	 *                  nome di una funzione php senza paramentri che viene richiamata dopo l'inserimento o la modifica 
	 *					(stringa vuota se non si vuole usare alcuna funzione).<br />
	 *					 L'uso di questa funzionalità ha un effetto simile a quello di un trigger SQL di tipo AFTER UPDATE/INSERT. <br />
	 *
	 *  @param boolean  indicates if to print the navigation interface even over the table  between the pages where are divided records.
	 *                  By default that interface is printed just under the table of elements visualization.
	 *                  <br /><br />ITALIAN:<br /> 
	 *                  indica se stampare anche sopra la tabella l'interfaccia di navigazione tra le pagine su cui sono suddivisi i record.
	 *                  Di default tale interfaccia è stampata solo sotto la tabella di visualizzazione elementi.
	 *
	 *  @param function name of a functione to be used for data visualization. If you specify that function, that will be used to show
	 *                  the data instead of the default table.<br />
	 *                  The function must accept a paramenter that represents the set of data gived by mysql_query().
	 *                  The set of data already contains just the elements to visualize on the current page therefore you don't have to worry about
	 *                  paging elements on many HTML pages, which is anyway automatically managed by the class.
	 *                  Inside the function it is possible to tell as global the instance variable of DBNavigator object and invoke
	 *                  on that methods {@link getEditLink()} and {@link getDeleteLink()} that allow you to get HTML code about
	 *                  links of insertion/modification on each record of data set. 
	 *                  <br /><br />ITALIAN:<br /> 
	 *                  nome di una funzione da usare per la visualizzazione dei dati. Se si specifica tale funzione, essa verrà usata per mostrare 
	 *                  i dati invece della tabella di default.<br />
	 *					La funzione deve accettare un parametro che rappresenta il set di dati restituito da mysql_query(). 
	 *					Il set di dati contiene già i soli elementi da visualizzare sulla pagina corrente quindi non ci si deve preoccupare della 
	 *					paginazione degli elementi sulle varie pagine HTML, questo verrà comunque gestita automaticamente dalla classe. 
	 *					All'interno della funzione è possibile dichiarare come global la variabile di istanza dell'oggetto DBNavigator e richiamare 
	 *					su di essa i metodi {@link getEditLink()} e {@link getDeleteLink()} che permettono di ottenere il codice HTML relativo 
	 *					ai link di inserimento/modifica su ogni record del set di dati. 
	 *
	 *
	 *  @param array makes up a data structure which serves to make substitutions in the code HTML generated by the class.<br />
	 *               The array must be associative: each element has KEY equal to the text to be replaced and equal VALUE to the text of replacement.<br />
	 *               Like key you can also use a text which will contain a regular expression causing the substitution of text parts
	 *               in match with the expression ( parsed by preg_replace() ). 
	 *               <br /><br />ITALIAN:<br /> 
	 *               costituisce una struttura dati che serve ad effettuare delle sostituzioni nel codice HTML generato dalla classe.<br /> 
	 *               L'array deve essere associativo: ogni elemento ha CHIAVE uguale al testo da sostituire e VALORE uguale al testo di rimpiazzo.<br /> 
	 *				 Come chiave si può anche usare un testo che contenga una regular espression causando la sostituzione delle parti di testo
	 *				 in match con l'espressione ( valutata dalla funzione preg_replace() ). 
	 *	 
	 *  @see getEditLink(), getDeleteLink()
	 *
	 */	
	function go($after_query_function="",$PageNavigator_on_top=false,$viewing_data_function="",$replace_array=null)
	{
		$this->main($after_query_function,false);
		
		if (!$this->ajaxCall) 
		echo $this->commonAjaxFunctions()."<div id=\"{$this->originalPrimaryTable}_anchor\">"; //ancora
		else ob_end_clean();
		
		if (isset($_GET['csv_'.$this->originalPrimaryTable]) ) $this->export("CSV");
		else
		if (isset($_GET['excel_xml_'.$this->originalPrimaryTable]) ) $this->export("EXCEL_XML");
		else
		if (isset($_GET['view_'.$this->originalPrimaryTable]) )  
		{	
			$id=$_GET['view_'.$this->originalPrimaryTable];
			$row=mysql_fetch_array(mysql_query($this->addWhereConditionToQuery($this->query,"{$this->originalPrimaryTable}.{$this->originalPrimaryKey}='{$id}'")));
			if ($row)
			{
				ob_end_clean();
				die( $this->viewForPrint($id));
			}
			else $this->printTable($replace_array,$PageNavigator_on_top,$viewing_data_function);
					
		}
		else
		if (
			(isset($_GET['edit_'.$this->originalPrimaryTable]) && $_GET['edit_'.$this->originalPrimaryTable]!="")  
			||
			(isset($_GET['action_'.$this->originalPrimaryTable]) && $_GET['action_'.$this->originalPrimaryTable]=="edit" 
			 && count($_GET['selected_'.$this->originalPrimaryTable])>0)
			)  
		{	
	
			$head_str="";
			if (isset($_GET["action_".$this->originalPrimaryTable]))
			{
				$head_str="<span style=\"color:#FF0000;font-weight:bolder;\">
								{$this->lang['editing']} {$this->rowName} ".($_GET["sellen_".$this->originalPrimaryTable]-count($_GET["selected_".$this->originalPrimaryTable])+1)."
								{$this->lang['of']} ".$_GET["sellen_".$this->originalPrimaryTable]
						 ."</span><br /><br />"	;	
				
				$id=$_GET["selected_".$this->originalPrimaryTable][0];
										
			}
			else $id=$_GET['edit_'.$this->originalPrimaryTable];

			$row=mysql_fetch_array(mysql_query($this->addWhereConditionToQuery($this->query,"{$this->primaryTable}.{$this->originalPrimaryKey}='{$id}'")));
			
			if (
				 ( $row && ($this->canEdit===true || (is_array($this->canEdit) && in_array($row[$this->primaryKey],$this->canEdit)) ) ) 
				 || 
				 (!$row && $id==0 && $this->canInsert) 
			   ) // se è un inserimento...fragile(si assume che lo zero non verrà mai usato come chiave primaria) 
			echo $head_str.$this->buildForm($id,$replace_array,true);		
			else
			{
				if (!$row)
				{
					echo $head_str;
					
					echo "<script type=\"text/javascript\">
							<!--
								alert(\"{$this->lang['recordHasBeenDeleted']}\");
								";
		
					if (isset($_GET["action_".$this->originalPrimaryTable])) //selezione
					{
						if ($this->useAjax)
						{
							echo "  DBN_{$this->originalPrimaryTable}.selectionInfoGet=DBN_{$this->originalPrimaryTable}.selectionInfoGet.replace(
											new RegExp(\"selected_{$this->originalPrimaryTable}((%5B|\\\\[)\\\\d*(\\\\]|%5D))?=?{$id}($|&|#)\",\"g\"),'');
									DBN_{$this->originalPrimaryTable}.reloadPage();";	
						}
						else
						{
							array_shift($_GET["selected_".$this->originalPrimaryTable]);
							if (count($_GET["selected_".$this->originalPrimaryTable])==0)
							{
								unset($_GET["sellen_".$this->originalPrimaryTable]);
								unset($_GET["action_".$this->originalPrimaryTable]);		
							}	
							echo "	location.href=('".$_SERVER['PHP_SELF']."?".html_entity_decode(buildQueryString())."');";
						}
					}
					else //singolo
					{
						unset($_GET['edit_'.$this->originalPrimaryTable]);
					}
					
					echo "
							-->
						</script>"; 	
				}	
					
				if ($row || !isset($_GET["action_".$this->originalPrimaryTable])) //esegue con la selezione singola di record inesistenti e con la modifica di record
																				 //senza i privilegi necessari
				$this->printTable($replace_array,$PageNavigator_on_top,$viewing_data_function);
			
			}
			//die("Azione non consentita");
		}
		else if (isset($_GET["action_".$this->originalPrimaryTable]) && $_GET["action_".$this->originalPrimaryTable]=='editMany' && isset($_GET["selected_".$this->originalPrimaryTable])) 
		{
			
			$id=array();
			
			if ( is_array($this->canEdit) ) //impostazione id con i permessi
			{
				foreach($_GET["selected_".$this->originalPrimaryTable] as $sel)
				{
					if (in_array($sel,$this->canEdit) ) $id[]=$sel; 
				}
			}
			else	
			if ( $this->canEdit===true )
			$id=$_GET["selected_".$this->originalPrimaryTable];
			
			if ( count($id)==0 ) //nessun id autorizzato
			$this->printTable($replace_array,$PageNavigator_on_top,$viewing_data_function);
			else
			{ 
				echo $this->buildForm($id,$replace_array,true);
			}
		}
		else if (
					isset($_GET['del_'.$this->originalPrimaryTable]) 
					|| 
					(isset($_GET["action_".$this->originalPrimaryTable]) && $_GET["action_".$this->originalPrimaryTable]=='delete' && isset($_GET["selected_".$this->originalPrimaryTable]))
				)
		{
			$occupiedId='';
			$id=array();
			
			if (isset($_GET["selected_".$this->originalPrimaryTable]))
			$sel=$_GET["selected_".$this->originalPrimaryTable];
			else
			$sel=array($_GET['del_'.$this->originalPrimaryTable]);
			
			foreach($sel as $selected)
			{
				if ($this->canDelete===true || (is_array($this->canDelete) && in_array($selected,$this->canDelete) ) )
				{
				   if (!$this->manage_record_availability($selected,true)) //al primo record che è in modifica da qualche altro, ferma la cancellazione e prenota la modifica per il record
				   $occupiedId=";DBN_{$this->originalPrimaryTable}.manage_record_availability_for_editing({$selected},false)"; //uno a caso
				
				   $id[]=$selected;
				}
			}
		
		
			if (!$occupiedId)
			{
				foreach($id as $ids) $this->delete($ids); //eliminazione, andrà a successo di sicuro dopo la verifica e la prenotazione
				
				echo "
				<script type=\"text/javascript\">
				<!--
						DBN_{$this->originalPrimaryTable}.selectionInfoGet=''; //caso particolare
				-->
				</script>";
				
				if ($this->useAjax)
				{
					unset($_GET['selected_'.$this->originalPrimaryTable]);
					unset($_GET['action_'.$this->originalPrimaryTable]);
					unset($_GET['del_'.$this->originalPrimaryTable]);
					unset($_GET['selected_'.$this->originalPrimaryTable]);
					$this->printTable($replace_array,$PageNavigator_on_top,$viewing_data_function);
				}
				else
				echo "<script type=\"text/javascript\">location.href=('".$_SERVER['PHP_SELF']."?"
				.html_entity_decode(buildQueryString('selected_'.$this->originalPrimaryTable,"action_".$this->originalPrimaryTable,"sellen_".$this->originalPrimaryTable,'del_'.$this->originalPrimaryTable))."');</script>"; 		
			}
			else
			{
				$getAppend="";
				$selinfoget="&action_{$this->originalPrimaryTable}=delete";
				foreach($id as $ids) 
				{
					$getAppend.="&manage_record_availability[]=".$ids;
					$selinfoget.="&del_{$this->originalPrimaryTable}[]=".$ids;
				}						
				
				
				if ($this->useAjax)
				$href="javascript:DBN_{$this->originalPrimaryTable}.printTable()";
				else
				{
					$qs=buildQueryString("del_{$this->originalPrimaryTable}",'edit_'.$this->originalPrimaryTable,"action_{$this->originalPrimaryTable}","sellen_{$this->originalPrimaryTable}","selected_{$this->originalPrimaryTable}");
					$href=$_SERVER['PHP_SELF']."?$qs#{$this->originalPrimaryTable}_anchor";
				}
				
				//se ce n'è uno occupato termina qui
				echo "
				<script type=\"text/javascript\">
				<!--
					DBN_{$this->originalPrimaryTable}.checkAvailability=setInterval(\"DBN_{$this->originalPrimaryTable}.createHttpRequest2('&bookRecord{$getAppend}',function(){}){$occupiedId}\",3000); // rifa il controllo dopo 7 secondi																
				-->
				</script>
				<br /><div style=\"cursor:wait;font-weight:bolder;border:1px solid #FF0000;padding:3%\">
								{$this->lang['warningRecordOccupied']}
								<a href=\"{$href}\">&raquo; {$this->lang['goBack']}</a> 
								</div><br />";				
			}	
		}
		else
		{
			$this->printTable($replace_array,$PageNavigator_on_top,$viewing_data_function);
		}
		
		if ($this->ajaxCall) die('');
		else
		echo "<script type=\"text/javascript\">
			  <!--	
					if (typeof(window.onload)=='function')
					{					
						var oldonload_1_{$this->originalPrimaryTable}=window.onload;
						
						window.onload=function()
												{
													document.onmousemove=handlemousemove;
													{$this->JS_onLoad}
													oldonload_1_{$this->originalPrimaryTable}();
												}		
	
					}
					else
					window.onload=function()
											{
												document.onmousemove=handlemousemove;
												{$this->JS_onLoad}
	
											}			
			  -->
			  </script>";
		
		echo "</div>"; //fine ancora
	}
	
	private function query_ricorsiva($id,$query) //conta i nodi del sottoalbero partendo da $id
	{
		$result=mysql_query(str_replace("%current_row_id%",$id,$query)); 
		$count=0;
		while ($row=mysql_fetch_array($result))
		{
			$count++;
			$return=$this->query_ricorsiva($row[0],$query); //assume che l'id della tabella della query sia il primo campo (0)
			$count+=$return;
		}
		return $count;
	}
		
	/** 
	  * This method allows to obtain the code HTML relative to the form of elements research.<br />
	  * The form is automatically printed at the recall of function {@link go()} while
	  * if you recall this method the automatic print won't be executed.
	  *
	  * Naturally the form can be obtained if there are defined the searching fields
	  * through the method {@link setSearchField()}.<br />
      *
	  * <br /><br />ITALIAN:<br />
      *	Questo metodo permette di ottenere il codice HTML relativo al form di ricerca elementi.<br />
	  * Il form viene automaticamente stampato al richiamo della funzione {@link go()} mentre
	  *	se si richiama questo metodo la stampa automatica non viene eseguita.<br /><br />
	  *	
	  * Naturalmente il form può essere ottenuto se sono stati definiti dei campi di ricerca 
	  *	tramite il metodo {@link setSearchField()}.<br />
	  * 
	  * @param boolean indicates if to print the heading fields of the form over the checks instead of beside
	  *                <br /><br />ITALIAN:<br /> 
	  *                indica se stampare le intestazioni dei campi del form sopra i controlli invece che a fianco 
	  *	@return string the HTML code relative to the form of elements research. <br /><br />ITALIAN:<br /> il codice HTML relativo al form di ricerca elementi.
	  */		
	function search_form($new_line=false)
	{
		
		$this->scanTable();		
		$print="";
		$JS="";
	
		if (count($this->searchField)>0)///////FORM DI RICERCA///////////////////////////////////////
		{		
			$print.= "<script type=\"text/Javascript\" src=\"{$this->imagesAndScriptsPath}autosuggest.js\"></script>
						<div style=\"width:100%;\" id=\"{$this->originalPrimaryTable}_search_form\"><fieldset style=\"padding:5px;\">
						<legend><em>{$this->lang['searchOn']}</em></legend>";
			
			$horizontal_space=$new_line?8:12;
			$HF=new HTMLForm("src_{$this->originalPrimaryTable}",$_SERVER['PHP_SELF']."#".$this->originalPrimaryTable."_anchor",25,75,"Form di ricerca ".$this->rowName,"get",$horizontal_space,$new_line);	
			
			if ($this->HTMLtextEditor!=false) 
				$HF->setHTMLTextEditor($this->HTMLtextEditor);
			
			$HF->setLanguage($this->lang['languageName']);
			
			foreach($_GET as $name=>$value) //parametri vari
			{
				if ( 
					   strstr($name,"_src_".$this->originalPrimaryTable) 
				  	|| strstr($name,"src_".$this->originalPrimaryTable."_submit") 
				  	|| $name=="ord_".$this->originalPrimaryTable 
				  	|| $name=="desc_".$this->originalPrimaryTable 
				  	|| $name=="Page_".$this->originalPrimaryTable 
				  	|| $name=="fieldList" 
				   )
						continue; 
			
				$HF->addInput("hidden",$name,stripslashes($value));
			}
			
			
			foreach($this->searchField as $key=>$data)
			{
					
				//////sulla
				if (is_array($data['value']))
				{				
					foreach ($data['value'] as $k=>$v)		 
						$data['value'][$k]=stripslashes($v);		
				}
				else
					$data['value']=stripslashes($data['value']);
		
				// ************************************************************************************************

				if (is_array($data['field_alias']))
				{
					$heading=array();
					
					foreach ($data['field_alias'] as $val)
					$heading[]=str_replace("_"," ",ucfirst($val));
					
					$heading=implode(",<br />",$heading);
				}
				else
				$heading=str_replace("_"," ",ucfirst($data['field_alias']));

				if (is_array($data['field'])) //NUOVO CASO PARTICOLARE : PIU' CAMPI DI RICERCA x un testo solo 
												// è il primo if xkè qui l'interfaccia diventa una textbox indipendentemente dai campi !
				{
					$inputName=implode("_",$data['field'])."_src_".$this->originalPrimaryTable;
					$JS.= "
						   new AutoSuggestControl('{$this->originalPrimaryTable}',document.getElementById(\"{$inputName}\"),new Array('".implode("','",$data['field'])."'));";
													
					$HF->addInput("text",$inputName,$data['value'],$heading,false,null,false,$this->classForFormInput['inputs']);		
												
				}
				else	
			    
				////////////////////////////////////////////////////////// AGGIUNTA degli INPUT di interfaccia nel form ri ricerca ///////
				
				if ($data['domainType']=='list') // @ RADIO o SELECT (con selezione multipla)
				{				
					$numValues=count($data['domainValue']);

					if ($numValues==0 || $numValues==1)
					{
						$type='select';
						$data['domainValue']=array(''=>"<em>{$this->lang['noResults']}</em>"); 
						$param=''; 
					}
					else 
					if ($numValues==2) 
					{
						$type='radio';
						$data['domainValue']=array_merge(array(''=>"<em>{$this->lang['all']}</em>"), $data['domainValue']); 
						$param=true; //radio su una sola riga
					}
					else //per consentire scelte multiple di ricerca sul campo
					{
						$type='select';
						$data['domainValue']=array_merge(array(''=>"&raquo; {$this->lang['all']}"), $data['domainValue']); 
												
						if ($numValues<8)
							$param=$numValues;
						else
							$param=8;
					}
					
					$HF->addInput($type,"{$data['table_alias']}_{$data['field']}_src_".$this->originalPrimaryTable,$data['domainValue'],
								  $heading,$param,$data['value'],false,$this->classForFormInput['inputs']);


				}
				else if ($data['domainType']=='date') // @------ INTERVALLO DATE! -- ricerca intervalli con input aggiunto 'manualmente' (senz addinput() di htmlform)
				{
/*					$HF->addInput("select","{$data['table_alias']}_{$data['field']}_src_".$this->originalPrimaryTable,$data['domainValue'],$heading,true,$data['value'],false,$this->classForFormInput['inputs']);
					*/					

					$inputs="					
					<label for=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_start\">
						<strong>{$heading}</strong> {$this->lang['from']} 
					</label>
					
					<select class=\"{$this->classForFormInput['inputs']}\"
					   	   id=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_start\" 
						   name=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_start\">";
					
						
/*						//come caso tab esterna con opzioni limitate
						$from=strstr($this->query,"FROM");
						$group_by_pos=strpos($from,"GROUP BY");
						if ($group_by_pos)	$from=substr($from,0,$group_by_pos);
					
						$q="SELECT min({$data['table_alias']}.{$data['field']}) AS min, max({$data['table_alias']}.{$data['field']}) AS max $from";		
						mysql_query($q) or die ('errore selezione estremi date'.mysql_error());
						$row=mysql_fetch_array($result);
						
						$min=explode("-",$min); $min=$min[0];
						$max=explode("-",$max); $max=$max[0];
					
						$date=dateArray($min,$max); 
		
						foreach	 ($date as $k=>$v)
						{
							$inputs.="<option value=\"{$k}\" ".($current_start==$k?"selected=\"selected\"":"").">{$v}</option>
							";
						} 
						............................iniziato, non continuato. Per una selezione tra due date specificando gg mm aaaa sono necessari
						6 input, cioè 6 get! proviamo con 2 */
					
					$current_start=isset($data['value']['start'])?$data['value']['start']:false;
						   
					foreach	 ($data['domainValue'] as $k=>$v)
					{
						$inputs.="<option value=\"{$k}\" ".($current_start==$k?"selected=\"selected\"":"").">{$v}</option>
						";
					}  
						    
					$inputs.="
					</select>						
						   
					<label for=\"{$data['table_alias']}_{$data['field']}_src_".$this->originalPrimaryTable."_end\"> 
						{$this->lang['to']} 
					</label>
					
					<select class=\"{$this->classForFormInput['inputs']}\"
					   	   id=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_end\" 
						   name=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_end\">";

					$current_end=isset($data['value']['end'])?$data['value']['end']:false;
						   
					foreach	 ($data['domainValue'] as $k=>$v)
					{
						$inputs.="<option value=\"{$k}\" ".($current_end==$k?"selected=\"selected\"":"").">{$v}</option>
						";
					}  
						    
					$inputs.="
					</select>";	

					
					$HF->addExternalContent($inputs);

				}
				else 
				if ($data['domainType']=='numeric') /////@------ numero - ricerca intervalli con input aggiunto 'manualmente' (senz addinput() di htmlform)
				{
					$HF->addExternalContent("					
					<label for=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_start\">
						<strong>{$heading}</strong> {$this->lang['from']} 
					</label>
					
					<input style=\"width:70px;\" class=\"{$this->classForFormInput['inputs']}\" type=\"text\" 
						   id=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_start\" 
						   name=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_start\" 
						   value=\"".(isset($data['value']['start'])?$data['value']['start']:"")."\" /> 
						   
					<label for=\"{$data['table_alias']}_{$data['field']}_src_".$this->originalPrimaryTable."_end\"> 
						{$this->lang['to']} 
					</label>
					
					<input style=\"width:70px;\" class=\"{$this->classForFormInput['inputs']}\" type=\"text\" 
						   id=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_end\"
						   name=\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}_end\"
						   value=\"".(isset($data['value']['end'])?$data['value']['end']:"")."\" /> 
					");

				}
				else // @------ dato semplice - textbox
				{ 
					if ($data['table']!="Having") //!!!!!!! Non ci sono suggerimenti ai campi generati da funzioni di aggregazione
						$JS.= "
						   new AutoSuggestControl('{$this->originalPrimaryTable}',document.getElementById(\"{$data['table_alias']}_{$data['field']}_src_{$this->originalPrimaryTable}\"),'{$data['field']}');";
				
					$HF->addInput("text","{$data['table_alias']}_{$data['field']}_src_".$this->originalPrimaryTable,$data['value'],
								   $heading,false,null,false,$this->classForFormInput['inputs']);						
				}
			}
			
								$form_string = $HF->buildForm($this->lang['find'],$this->classForFormInput['buttons']);	
			if ($this->useAjax)	$form_string = str_replace("validateFunction_src_{$this->originalPrimaryTable}()","DBN_{$this->originalPrimaryTable}.search_()",$form_string);	
					   $print.= $form_string;	
			
			
			$print.= "</fieldset></div>";	
			
		}		//END FORM DI RICERCA///////////////////////////////////////////////////
	
		
		$this->search_form_printed=true;
		
		if ($this->ajaxCall)  $JS="<script type=\"text/javascript\"><!-- {$JS} --></script>";
		else {$this->JS_onLoad=$JS; $JS="";}		 
		
		return $print.$JS;
	}		
	
	private function get_queryWithSearchConditions()
	{		

			/////////////--- print_r($this->searchField);	///// DEBUGGGGGGGGGGGGGGGGGGGGGGGGG		


			
			foreach($this->searchField as $x)
			{
				// controllo valori vuoti
				if (   (is_array($x['value']) && implode('',$x['value'])=="")   ||   $x['value']==""   ) continue;	

				//(ri)trasformo in array anche i parameteri dei campi di ricerca 'singoli' - field_alias non necessario
				//.......ridondante		
				if (!is_array($x['field']))
				{
					$x['field']=array($x['field']);
					$x['field_alias']=array($x['field_alias']);
					$x['table']=array($x['table']);
					$x['table_alias']=array($x['table_alias']);
					$x['domainType']=array($x['domainType']);
					$x['domainValue']=array($x['domainValue']);
					$x['fullField']=array($x['fullField']);

				}				
				//print_r($x);
			
				$current_condition=array();																

				//per ogni campo coinvolto in una condizione di ricerca esegue il codice sotto: i dati generali (tipo,value) sono direttamente su $x
				//mentre i sottocompi sono nell'array $x['field']
				for ( $k=0 ; $k < count($x['field']) ; $k++ )  ///potevo contare anche qualcos'altro
				{
				
					$first_condition_for_search_field=true;
					

					//I CAMPI su funzioni aggregate seguono lo stesso trattamento degli altri
						switch ($x['tipo_ricerca'])
						{
							case "1": //tante parole 'vincolate'
										$or=array();
								
										foreach($x['value'] as $multiple=>$val)
										{
											if ($val=="") continue;

/*											$val_escape=str_replace(array("%","_"),array("\%","\_"),$val);
											
											$or[]=" (
														{$x['fullField'][$k]} LIKE \"{$val_escape},%\" 
														OR 
														{$x['fullField'][$k]} LIKE \"%,{$val_escape},%\"
														OR 
														{$x['fullField'][$k]} LIKE \"%,{$val_escape}\"
														OR
														{$x['fullField'][$k]} = \"{$val}\"
	
													) "; 
*/

											$val=ereg_replace('(\?|\.|\[|\]|\(|\)|\||\{|\}|\$|\^|\*)','\\\\\\0',$val);

											$val=str_replace("\\\\","\\\\\\\\",$val); //magic_quote aggiunge gli slash quindi da 1 sono 2bs che devono diventare 4bs
											
											//$val=str_replace(array('?','\\','.','[',']','(',')','|','{','}','$','^','*'),
											//		 		   array('\\\\?','\\\\\\','\\\\.','\\\\[','\\\\]','\\\\(','\\\\)','\\\\|','\\\\{','\\\\}','\\\\$','\\\\^','\\\\*'),$val);
											//echo $val;	
											
											$or[]=" {$x['fullField'][$k]} REGEXP \"^(.*,)?{$val}(,.*)?$\" ";
													
											//le condizioni sono per ricerche su SET (il campo ha tanti valori, separati da virgola)
											//solo l'ultima condizione è anche per ENUM e tab esterne (oltre che a soliti campi SET con un valore singolo)
										}
								
							
										if (is_array($or) && count($or)>0) $current_condition[]=implode(" OR ",$or);
										break;
										
							case "2": //frase (viene distinto dal caso 3 xkè + racchiusa tra virgolette doppie (ricordarsi deli slash) )
										
										$value=substr($x['value'],2,strlen($x['value'])-4);//
							
										$current_condition[]="{$x['fullField'][$k]} =\"".$value."\"";
										break;
																		
							case "3": // tante parole 'libere' 
								
										$founded=false;
										
										$word=preg_split("/[^\\w'\"]/",stripslashes($x['value']),-1,PREG_SPLIT_NO_EMPTY);
										//print_r($word);
										$atLeastOneLongWord=false;
										foreach ($word as $w) if (strlen($w)>3) {$atLeastOneLongWord=true;break;}
										//if (strlen($x['value'])>3)										
										if ($atLeastOneLongWord && $x['table'][$k]!='Having')  
										{
											
											$result=mysql_query("DESCRIBE {$this->originalPrimaryTable}");
											while ($row=mysql_fetch_array($result))
											{
												if ($row['Field']==$x['field'][$k] && $row['Key']=='MUL') //cerca l'indice FULLTEXT
												{
													
													
									
												
													$current_condition[]="MATCH({$x['fullField'][$k]}) AGAINST (\"{$x['value']}\")";
													//ordina in base alla rilevanza dei risultati
													
													if (isset($this->orderInfo['currentOrd']))
													$this->orderInfo['currentOrd'].=", MATCH({$x['fullField'][$k]}) AGAINST (\"{$x['value']}\") DESC";
													else
													$this->orderInfo['currentOrd']=" MATCH({$x['fullField'][$k]}) AGAINST (\"{$x['value']}\") DESC";
													
													$this->orderInfo['currentDesc']="";
													$founded=true;
													break;
												}
											}
										}
										
										if (!$founded)//campo non fulltext, oppure tutte parole <= 3
										{
											$or=array();
											$i=0;
											
											$x['value']=str_replace(array("%","_"),array("\%","\_"),$x['value']);
											
											if ( 
												 (strpos($x['value']," ")==0 && strlen($x['value'])<3) //una parola < di 3 caratteri													
												 || 													
												 $atLeastOneLongWord==false //frasi senza parole >3
											   ) 
											{
		
												$or[]=" {$x['fullField'][$k]} LIKE \"{$x['value']}%\" "; //solo record che iniziano con..parola%
												$cicli=0;
											}
											else 
											if (strpos($x['value']," ")==0) // una parola > 3 caratteri
												$cicli=1; // like %parola% - cerca internamente al campo 
											else 
												$cicli=2; // LIKE %par1%par2%par3% OR LIKE %par1%par2% OR LIKE %par1% OR LIKE %par2%par3% OR LIKE %par3%
											
											for($j=0;$j<$cicli;$j++)//scansione avanti e indietro
											{
												$data_value=explode(" ",$x['value']);
												
												while(count($data_value)>0)//cicla finche l'array è pieno
												{											
													$or[$i]=" {$x['fullField'][$k]} LIKE \"";
													foreach($data_value as $key=>$val)
													{
														$or[$i].="%{$val}"; //con spazi o senza? - con gli spazi non trova i codici
													}
													$or[$i].="%\" ";
													$i++;
													
													//eliminazione elemento dall'array
													if ($j==0)//indietro
													array_pop ($data_value);
													else      //in avanti
													array_shift($data_value);
													
												}
		
											}
											
											if (is_array($or) && count($or)>0) $current_condition[]=implode(" OR ",$or);
											
											//				print_r($or);											 
										}
										
										break;	
							case "4": //intervalli numerici
										
										$exp=array();
										if (isset($x['value']['start']) && $x['value']['start']!="") $exp[]="{$x['fullField'][$k]}>=\"{$x['value']['start']}\"";
										if (isset($x['value']['end'])   && $x['value']['end']!="")   $exp[]="{$x['fullField'][$k]}<=\"{$x['value']['end']}\"";
										
										
										$current_condition[]=implode(" AND ",$exp);
										break;									
						}									
					
				}//end foreach 2
					
						
				if (count($current_condition)>0) //scelta della condizione messa su WHERE o su HAVING
				{
					$textual_current_condition=" (".implode(" OR ",$current_condition).") ";

					$allHaving=true;
					foreach($x['table'] as $val)
						if ($val!="Having")
						{
							$allHaving=false;
							break;
						}
	
					if ($allHaving)
					{
						$having_condition=isset($having_condition)?$having_condition." AND ".$textual_current_condition:$textual_current_condition;	
						
					}
					else
						$where_condition=isset($where_condition)?$where_condition." AND ".$textual_current_condition:$textual_current_condition;	
				}
				//echo $where_condition;	
	
			}// end foreach 1
				
							
			$query=$this->query;
			
			if (isset($where_condition)) 	
			$query=$this->addWhereConditionToQuery($query,$where_condition);
			
			if (isset($having_condition)) 
			$query=$this->addHavingConditionToQuery($query,$having_condition);
			
			
			/////////////--- echo $query;	///// DEBUGGGGGGGGGGGGGGGGGGGGGGGGG		
			
			
			return $query;
	}		
	
	/** @return int the number of rows resulting from the construction query of the object with the actual research parameters
	  *             <br /><br />ITALIAN:<br /> 
	  *             il numero di righe risultante dalla chiamata alla query di costruzione dell'oggetto con gli attuali parametri di ricerca.	
	  */
	function get_rowsNum()
	{
		$this->scanTable();
		$this->set_rowsNum();
		return $this->rowsNum;
	}

	/** @return string the construction query of the object with the actual research parameters 
	  *                <br /><br />ITALIAN:<br />la query di costruzione dell'oggetto con gli attuali parametri di ricerca.*/	
	function getFullQuery()
	{
		$this->scanTable();
		$this->set_rowsNum();
		return $this->query;
	}
	
	private function set_rowsNum()
	{
		if (!$this->rowsNum)
		{
			$this->query=$this->get_queryWithSearchConditions();
			
			///*******************AGGIUNTA CONDIZIONI ALLA QUERY E ORDINAMENTO*************************
			if (!isset($_GET['ord_'.$this->originalPrimaryTable]) && !isset($this->orderInfo['currentOrd']))
			{
				$ordinamento=explode(",",$this->orderInfo['defaultOrd']);
				if (count($ordinamento)>1) //se si ordina per più colonne ordina brutalmente
				{
					$this->orderInfo['currentOrd']=$this->orderInfo['defaultOrd'];
					$this->orderInfo['currentDesc']="";
				}else
				{			
					$exp=explode(" ",$this->orderInfo['defaultOrd']);
	
					$this->orderInfo['currentOrd']=$exp[0];					
					$this->orderInfo['currentDesc']=isset($exp[1])?strtoupper($exp[1]):""; //da ricontrollare per spazi ecc.....
				}			
			}
			else if (isset($_GET['ord_'.$this->originalPrimaryTable]))//l'ordinamento dei GET prevale sull'ordinamento della ricerca(impostato da get_queryWithSearchConditions)
			{
				
				$this->orderInfo['currentOrd']=isset($_GET['ord_'.$this->originalPrimaryTable])?$_GET['ord_'.$this->originalPrimaryTable]:"";
				$this->orderInfo['currentDesc']=isset($_GET['desc_'.$this->originalPrimaryTable])?$_GET['desc_'.$this->originalPrimaryTable]:"";
				
			}
			else if(isset($this->orderInfo['currentOrd']))
			{
	
				$this->orderInfo['currentOrd']=substr($this->orderInfo['currentOrd'],1);
			}
	
		
		
			$this->query.=" ORDER BY {$this->orderInfo['currentOrd']} {$this->orderInfo['currentDesc']} , {$this->primaryTable}.{$this->originalPrimaryKey}";//ordina anche per id nel caso ci siano match di rilevanza uguali
	
			
			//echo $this->query;
	
			//DA MODIFICARE PER LE PRESTAZIONI !!!!!!!!DANGER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			if (strstr($this->query,"HAVING")===false)
			{
				$from=substr($this->query,strpos($this->query,"FROM"));
				
				$gbpos=strpos($from,"GROUP BY");
				$obpos=strpos($from,"ORDER BY");
				
	
				
				$count_query="SELECT COUNT(DISTINCT {$this->primaryTable}.{$this->originalPrimaryKey}) AS cnt ";
	
				if ($gbpos===false && $obpos===false && $lmpos===false)
				$count_query.=$from;
				else if	(is_int($gbpos))	
				$count_query.=substr($from,0,$gbpos);
				else if	(is_int($obpos))	
				$count_query.=substr($from,0,$obpos);
				else if	(is_int($lmpos))	
				$count_query.=substr($from,0,$lmpos);
				
				$row=mysql_fetch_array(mysql_query($count_query)) or die("ERRORE QUERY CONTEGGIO RISULTATI: ".$count_query."<br /><br />".mysql_error());
				
				//echo $count_query;
				
				$rowsNum=$row['cnt'];		
				//echo $count_query."<br>";
				//echo $this->query;
				$this->rowsNum=$rowsNum;
	
			}
			else 
			$this->rowsNum=mysql_num_rows(mysql_query($this->query));
	
			////////////////////////////////////		
			
		}
	}
	
	/**  @param int id of a record<br /><br />ITALIAN:<br /> id di un record 
	  *  @return string the HTML code of the button/link relative to the interface starting of element modification
	  *                 <br /><br />ITALIAN:<br /> 
	  *                 il codice HTML del tasto/link relativo all'attivazione dell'interfaccia di modifica dell'elemento 
	  *  @see go()  
	  */
	function getEditLink($id)
	{
	
		if ($this->useAjax)
		$href="javascript:DBN_{$this->originalPrimaryTable}.buildForm({$id},'')";
		else
		$href="{$_SERVER['PHP_SELF']}?edit_{$this->originalPrimaryTable}={$id}".buildQueryString("del_".$this->originalPrimaryTable,"edit_".$this->originalPrimaryTable)."#{$this->originalPrimaryTable}_anchor";
	
	
		if ($this->canEdit===true || (is_array($this->canEdit) && in_array($id,$this->canEdit)))  
		return "<a href=\"{$href}\"><img src=\"".$this->imagesAndScriptsPath."edit.png\" alt=\"Modifica dati {$this->rowName} {$id}\" title=\"Modifica dati {$this->rowName}\" style=\"border:0px;vertical-align:baseline;margin:4px\" /></a>";
		else return "";
	
	}

	/**  @param int id of a record<br /><br />ITALIAN:<br /> id di un record 
	  *  @return string the HTML code of the button/link relative to starting of the element elimination procedure
	  *                 <br /><br />ITALIAN:<br /> 
	  *                 il codice HTML del tasto/link relativo all'attivazione della procedura di eliminazione dell'elemento
	  *  @see go()  */
	function getDeleteLink($id)
	{
	
		if ($this->useAjax)
		$href="javascript:DBN_{$this->originalPrimaryTable}.delete_({$id})";
		else
		$href="{$_SERVER['PHP_SELF']}?del_{$this->originalPrimaryTable}={$id}".buildQueryString("del_".$this->originalPrimaryTable,"edit_".$this->originalPrimaryTable)."#{$this->originalPrimaryTable}_anchor";
	
	
		if ($this->canDelete===true || (is_array($this->canDelete) && in_array($id,$this->canDelete)))  
		return "<a onclick=\"return confirm('{$this->lang['reallyDelete']}')\" onkeypress=\"if (this.event.keyCode!=13) return false; else return confirm('{$this->lang['reallyDelete']}')\"
				href=\"{$href}\"><img src=\"".$this->imagesAndScriptsPath."delete.png\" alt=\"Elimina {$this->rowName} {$id}\" title=\"Elimina {$this->rowName}\" style=\"border:0px;vertical-align:baseline;margin:4px\" /></a>";
		else return "";					
	
	}
	
	private function isConditionSatisfied($condition,$row)
	{
		if ($condition=="") return true;
		
		//condizione semplicissima su un campo se è 0 o no //vecchio modo
		if (strpos($condition,"{{{")===false)
		{
			if ($row[$condition]<=0) return false; else return true;   
		}
		
		//condizione su una stringa da valutare tramite eval e contenente + condizioni....nome campo indicato con {{{nome_campo}}}
		if (is_int(strpos($condition,"{{{")))
		{
			preg_match_all( "/{{{([^}]+)}}}/", $condition, $field , PREG_PATTERN_ORDER );
	
			foreach($field[1] as $f)
			$condition=str_replace("{{{".$f."}}}",'$row[\''.$f.'\']',$condition);
			
			
			eval('$condition_passed=(boolean)('.$condition.');');
			if ($condition_passed) return true;	else return false;
		
		}
		
	}
	

	private function getLinkColLink($col,$row,$text)
	{
		if ($this->isConditionSatisfied($col['condition'],$row))
		{	
			if ($col['keepGet']!='') $qs=buildQueryString($col['arg']); else $qs="";
			
			$col['page']=strpos($col['page'],"?")===false?$col['page']."?":$col['page'];
			
			if ($col['newWindow'])
			$script="onkeypress=\"if (this.event.keyCode==13) window.open(this.href); return false;\" onclick=\"window.open(this.href); return false;\"";
			else
			$script="";
			
			return "<a {$this->classTag['fieldLink']} {$script} href=\"{$col['page']}&amp;{$col['arg']}={$row[$this->primaryKey]}$qs#{$this->originalPrimaryTable}_anchor\" >".$text."</a>";

		}
		else return false;
	}	
	
	
	private function printTable($replace_array=null,$PageNavigator_on_top=false,$viewing_data_function="")
	{		
			
		$print="";

		if ($this->search_form_printed==false && count($this->searchField)>0) $print.="<div style=\"width:40%\">".$this->search_form()."</div>";


		$rowsNum=$this->get_rowsNum();	
		
		
		if (!$this->viewResults)
		{
			if (isset($_GET["src_{$this->originalPrimaryTable}_submit"])) $this->viewResults=true; //controllo che ci sia il get del tasto del form di ricerca
			else
			foreach ($this->searchField as $v) //controllo che ci sia un GET di ricerca
			if (is_array($v['field']))
			{
				$idx="";
				foreach ($v['field'] as $v2)
				$idx.=$v2."_";
				if (isset($_GET["{$idx}src_{$this->originalPrimaryTable}"])) 
				{
					
					$this->viewResults=true;
					break;
				}
			}else if (isset($_GET["{$v['table_alias']}_{$v['field']}_src_{$this->originalPrimaryTable}"]))
			{
				
				$this->viewResults=true;
				break;		
			}
		}
		
		if (!$this->viewResults) 
		{
			$print=$this->brutalTextReplace($replace_array,$print);
			echo $print;		
			return false;
		}
		
		
		//print( $this->query); //DEBUGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
				
		//echo $rowsNum;
	
		if ($rowsNum!=0)
		{

			$navigation='';
			if (!$this->showAll)
			{ 
				$PN=new pageNavigator($rowsNum,$this->originalPrimaryTable,$this->classForFormInput['inputs'],$this->resultsPerPage,$this->datasetName);
				$this->query.=$PN->getLimit();
				
				$PN->setlanguage($this->lang['languageName']);
				$PN->setImagesPath($this->imagesAndScriptsPath);
				
				if ($this->pageBrowsingConfig['byselect']==true)			
					$nav1=$PN->show_page_browsing(false);
				
				if ($this->pageBrowsingConfig['bylink']==true)			
					$nav2=$PN->show_page_browsing(true);
				
				if ($this->pageBrowsingConfig['selectrpp']==true)			
					$rpp=$PN->show_RPP_browsing();
				
				if ($nav1 || $nav2 || $rpp)
				{
					$navigation.= "<br />";
					$navigation.= "<div class=\"".$this->pageBrowsingConfig['navigationPanelCSS']."\" id=\"{$this->originalPrimaryTable}_navigation_bottom\">";
					$navigation.= $nav1 ? $nav1."<br />" : "";
					$navigation.= $nav2 ? $nav2."<br />" : "";
					$navigation.= $rpp;			
					$navigation.= "</div>";
				}
			}
			
			if ($PageNavigator_on_top) $print.=$navigation; //NAVIGAZIONE IN UNA VARIABILE	
	

			//print( $this->query); //DEBUGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
			
			$result=mysql_query($this->query) or die ($this->query." : <br /><br />".mysql_error());
											   			
	
			if ($viewing_data_function=="")
			{

				$multipleContext = $this->canMultipleEditDelete==true  && 
								   (  
									 ($this->canEdit===true || is_array($this->canEdit)) 
									 || 
									 ($this->canDelete===true || is_array($this->canDelete))
								   );
				
				//**************************************INTESTAZIONE TABELLA*********************
				

				
				
				if ($multipleContext)
				{
					$print.="<form method=\"get\" action=\"{$_SERVER['PHP_SELF']}\" id=\"frm_select_{$this->originalPrimaryTable}\">";
					foreach($_GET as $name=>$value) //parametri vari
					{
						if (strstr($name,"selected_".$this->originalPrimaryTable) || strstr($name,"action_".$this->originalPrimaryTable) || strstr($name,"sellen_".$this->originalPrimaryTable))
						continue; 
						 
						if (is_array($value))
						foreach($value as $val)
						$print.= "<input type=\"hidden\" name=\"{$name}[]\" value=\"".stripslashes($val)."\" />";
						else
						$print.= "<input type=\"hidden\" name=\"$name\" value=\"".stripslashes($value)."\" />";
					}
				}
				
				
				$cont="";
				foreach($this->tableContainer as $css)
				{
				
					$cont="<div class=\"".$css."\">".$cont; //i div applicati in lista dal primo impostato fino all'ultimo
				}
				$print.=$cont;
								
				
				
				
				$print.= "<table border=\"0\"  cellpadding=\"{$this->tableCP}\" cellspacing=\"{$this->tableCS}\" 
				           style=\"width:100%;\" summary=\"Tabella riepilogativa di ogni {$this->rowName}\">";		



				
				
				$temp=array();
								
				if ($this->canEdit===true || is_array($this->canEdit)) 
					$temp[]=$this->lang['edit'];
				
				if ($this->canDelete===true || is_array($this->canDelete))
					$temp[]=$this->lang['delete'];

				if ($multipleContext) 
					$temp[]=$this->lang['selection'];
					
				
				
				$headerrow="";
				
				if (count($temp)==0) //non si possono fare azioni
				{	
					$columns=0;
					$NOACTION=true;
				}
				else
				{
					if (!isset($this->lang['actionColumnHeader']))
						$actionColumnHeader=strtolower(implode(" / ",$temp));	
					else 
						$actionColumnHeader=$this->lang['actionColumnHeader'];
		
					$headerrow.= "<td{$this->classTag['headerTD']}>".$actionColumnHeader."</td>"; //colonna di intestazione seleziona/modifica/elimina
					$columns=1;

				}
				
	

				
				foreach ($this->field as $current_field)
				{
					
					if ($this->hidePrimaryKey==true && $current_field->def==$this->primaryKey && $current_field->table==$this->originalPrimaryTable) continue; //nasconde la chiave primaria
					
					if ($current_field->type=='password') continue; //non mostra le password
														
					if (isset($this->removeDisplaying[$current_field->name])) continue; //Salto per i dati Indicati manualmente
					
					$columns++;
					
					$headerrow.= "<td{$this->classTag['headerTD']}>";
					
					///////////////
					$show="<strong>".ucfirst(str_replace("_"," ",$current_field->def))."</strong>";
					//////////////
					
				
					
					if ($this->useAjax)
					{
						$href_1="javascript:DBN_{$this->originalPrimaryTable}.set_order('{$current_field->def}',true)";
						$href_2="javascript:DBN_{$this->originalPrimaryTable}.set_order('{$current_field->def}',false)";
					}
					else
					{
						$href_1="{$_SERVER['PHP_SELF']}?ord_{$this->originalPrimaryTable}={$current_field->def}&amp;desc_{$this->originalPrimaryTable}".buildQueryString("ord_".$this->originalPrimaryTable,"desc_".$this->originalPrimaryTable,"edit_".$this->originalPrimaryTable,"del_".$this->originalPrimaryTable)."#{$this->originalPrimaryTable}_anchor";
						$href_2="{$_SERVER['PHP_SELF']}?ord_{$this->originalPrimaryTable}={$current_field->def}&amp;desc_{$this->originalPrimaryTable}=DESC".buildQueryString("ord_".$this->originalPrimaryTable,"desc_".$this->originalPrimaryTable,"edit_".$this->originalPrimaryTable,"del_".$this->originalPrimaryTable)."#{$this->originalPrimaryTable}_anchor";

					}

					$headerrow.=$show." ";// $show."<br />"; ////



				  //link di ordinamento disattivati per default...
					$asc_atagopen="<a href=\"{$href_1}\">";
					$asc_atagclose="</a>";
					$asc_im_postfix="off";
					$desc_atagopen="<a href=\"{$href_2}\">";
					$desc_atagclose="</a>";
					$desc_im_postfix="off";

					
					if ($current_field->def==$this->orderInfo['currentOrd'])  //colonna ordinata
					{	
						//....modifica solo le variabili del campo ordinato (o asc o desc)
						if ($this->orderInfo['currentDesc']=="DESC") 
						{
							$desc_atagopen="";
							$desc_atagclose="";
							$desc_im_postfix="on";
						}
						else // ASC
						{
							$asc_atagopen="";
							$asc_atagclose="";
							$asc_im_postfix="on";
						}
						

					}

					$headerrow.= $asc_atagopen."<img style=\"vertical-align:bottom;border:none;\" src=\"{$this->imagesAndScriptsPath}asc_{$asc_im_postfix}.gif\"  alt=\"{$this->lang['ascendingOrder']}\" title=\"{$this->lang['ascendingOrder']}\" />". $asc_atagclose.
								$desc_atagopen."<img style=\"vertical-align:bottom;border:none;\" src=\"{$this->imagesAndScriptsPath}desc_{$desc_im_postfix}.gif\"  alt=\"{$this->lang['descendantOrder']}\" title=\"{$this->lang['descendantOrder']}\" />". $desc_atagclose;



					//////////////////////////////////////
									
					$headerrow.= "</td>";
					
				}
				
				foreach ($this->dataCol as $col) {$columns++; $headerrow.= "<td{$this->classTag['headerTD']}>{$col['colName']}</td>";} //stampa colonne aggiuntive
				if ($this->canViewForPrint) {$columns++; $headerrow.= "<td{$this->classTag['headerTD']}>{$this->lang['print']}</td>";}
				foreach ($this->linkCol as $col) {$columns++; $headerrow.= "<td{$this->classTag['headerTD']}>{$col['colName']}</td>";} //stampa colonne aggiuntive
				foreach ($this->freeCol as $col) {$columns++; $headerrow.= "<td{$this->classTag['headerTD']}>{$col['colName']}</td>";} //stampa colonne aggiuntive
	
				////////////////--------------------------------------------------------------------------------------------------
				
				
				$print.= "<tr class=\"{$this->tableHeaderCSS}\">";

				
				if (count($this->tableBorderStyle)>0) // ..riga dedicata alle celle del bordo
				{
					$print.= "
								<td class=\"".$this->tableBorderStyle['topsx']."\"></td>
								{$headerrow}
								<td class=\"".$this->tableBorderStyle['topdx']."\"></td>
							  
							";
				}
				else
					$print.= "{$headerrow}";
							
				
				
				$print.= "</tr>";
				
				
				//**************************************TABELLA*********************				   					


				while ($row=mysql_fetch_array($result))
				{					
					
					$print.= "<tr class=\"{$this->tableRowContentCSS}\">"; 
					
					
					// ..celle del bordo
					// ..celle del bordo
					if (count($this->tableBorderStyle)>0) // ..riga dedicata alle celle del bordo
						$print.= "<td class=\"".$this->tableBorderStyle['sx']."\"></td>";	
				


					//SETTAGGIO EVIDENZIAZIONE RIGHE 
					$openTD="<td{$this->classTag['TD']}>";
					$openEditDeleteTD="<td{$this->classTag['editDeleteTD']}>";					
					foreach ($this->highlighting as $hl)
					if ($this->isConditionSatisfied($hl['condition'],$row))
					{
						$openTD=$openEditDeleteTD="<td {$hl['TDAttributes']}>";
						break;
					}
					
					
					if (!$NOACTION ) $print.= $openEditDeleteTD; //-----------colonna coi link modifica/elimina/selezione


					if ($multipleContext)
					{
					
						$print.="<label for=\"selected_{$this->primaryTable}_{$row[$this->primaryKey]}\"></label>".
						        "<input id=\"selected_{$this->primaryTable}_{$row[$this->primaryKey]}\" type=\"checkbox\" 
									   name=\"selected_{$this->primaryTable}[]\" value=\"{$row[$this->primaryKey]}\" style=\"margin:4px\" /> ";
						
					}	
					
					if ($this->canEdit===true || is_array($this->canEdit))
					{							
						$editLink=$this->getEditLink($row[$this->primaryKey]);
						if ($editLink!="") 
							$print.=$editLink;		
					}
					
					if ($this->canDelete===true || is_array($this->canDelete))
					{
						$deleteLink=$this->getDeleteLink($row[$this->primaryKey]);
						if ($deleteLink!="") 
							$print.=$deleteLink;

					}

										
					$print.= "</td>"; //-----------------------------fine colonna

	
					foreach ($this->field as $current_field) //per ogni colonna
					{
						if ($this->hidePrimaryKey==true && $current_field->def==$this->primaryKey && $current_field->table==$this->originalPrimaryTable) continue; //nasconde la chiave primaria	
						
						if ($current_field->type=='password') continue; //non mostra le password
						
						if (isset($this->removeDisplaying[$current_field->name])) continue; //Salto per i dati Indicati manualmente

						
						$print.=$openTD;
						

						$fieldText='';
												
						$TYPE=explode("(",$current_field->type);//serve per identificare gli ENUM
						
						
						///....................VISUALIZZAZIONE VALORI --- variabile $fieldText ...................................................
						
						
						if (is_array($this->imageIcon[$current_field->name])) //preview dell'immagine sulla tabella	
						{
							if ($row[$current_field->name]=='')
								$fieldText="<img src=\"".$this->imageIcon[$current_field->name]['off']."\" alt=\"\" style=\"border:none\" />";						
							else
							{
								$fieldText="<img src=\"".$this->imageIcon[$current_field->name]['on']."\" alt=\"\" style=\"border:none\" />";							
							
								//caso di file...stesso controllo fatto sotto
								if (isset($this->fileField[$current_field->name]) && $current_field->table==$this->originalPrimaryTable )
									$fieldText="<a href=\"{$this->filePath}/{$row[$current_field->name]}\" >".$fieldText."</a>";
							
							}
							
											



						}
						else if (isset($this->switchCol[$current_field->name])) //------ campo impostato come SWITCH (a 2 valori)
						{
									
							$value=array();
							foreach($this->getEnumSetValue($current_field->type) as $val=>$val2)
							{
								$value[]=$val;
							}// l'array value contenente i valori ordininati

							

							$is_on  = $row[$current_field->name]==$value[0] ? "1" : "2" ;	
							$is_off = $row[$current_field->name]==$value[0] ? "2" : "1" ;	
							
							$fieldText="<a href=\"{$_SERVER['PHP_SELF']}?switch_field_{$this->originalPrimaryTable}=".$current_field->name.
										 "&amp;switch_id_{$this->originalPrimaryTable}=".$row["id"].
										 "&amp;switch_value_{$this->originalPrimaryTable}=".$is_off. //uso del valore indice
										 "&amp;".buildQueryString("del_".$this->originalPrimaryTable,"edit_".$this->originalPrimaryTable).
										 "#{$this->originalPrimaryTable}_anchor\">";
							
							$current_value_image = $this->switchCol[$current_field->name]['image'.$is_on];
							
							
							if (file_exists($current_value_image))
								$fieldText.="<img style=\"vertical-align:top;border:none;\" src=\"".$current_value_image
											."\" alt=\"".$row[$current_field->name]."\" title=\"".$row[$current_field->name]."\" />";
							else
								$fieldText.=$row[$current_field->name];
								
								
							$fieldText.="</a>";
													
						
						}
						else						
						switch($TYPE[0])
						{	
							case "date":
									$exp=explode("-",$row[$current_field->def]);
									if (isset($this->monthYearField[$current_field->name]))
										$fieldText= "{$exp[1]}/{$exp[0]}";
									else
										$fieldText= "{$exp[2]}/{$exp[1]}/{$exp[0]}";
									
									break;
							case "datetime":
									$exp=explode(" ",$row[$current_field->def]);
									$exp2=explode("-",$exp[0]);
	
									$fieldText= "{$exp2[2]}/{$exp2[1]}/{$exp2[0]} {$exp[1]}";
									break;								
/*							case"real":
							case"int":
							case"enum":
							case"blob":	
							case"string":*/
							default: //tanto è uguale!
									 if (isset($this->photoField[$current_field->name]) && $current_field->table==$this->originalPrimaryTable)
									 {
										if ($row[$current_field->name]!="")
										{
												
											if ($this->photoField['_Resize_']) $small="small_"; else $small="";
											
											$fname=$this->filePath."/$small".$row[$current_field->name];
											
											if (file_exists($fname))
											{
												if (!is_array($this->imageIcon[$current_field->name])) //preview dell'immagine sulla tabella
													$fieldText= "<img src=\"".$fname."\" alt=\"\"
																	  style=\"".getImageResizedValues($fname,$this->imageScaleDim,$this->imageScaleDim)."\"  />";
												else//array
													$fieldText= "<img src=\"".$this->imageIcon[$current_field->name]['on']."\" alt=\"\" />";
												
											}
											else 
												$fieldText=$fname." :immagine non trovata";
										} 
										else 
										{
											if (!is_array($this->imageIcon)) //preview dell'immagine sulla tabella
												$fieldText="<em>{$this->lang['noImage']}</em>";
											else
												$fieldText= "<img src=\"".$this->imageIcon[$current_field->name]['off']."\" alt=\"\" />";
										}	
									 }
									 else if (isset($this->fileField[$current_field->name]) && $current_field->table==$this->originalPrimaryTable )
									 {
										if ($row[$current_field->name]!="")
										{
											$fieldText="<a href=\"{$this->filePath}/{$row[$current_field->name]}\" onclick=\"\">{$row[$current_field->name]}</a>";
										}
										else $fieldText="<em>{$this->lang['noFile']}</em>";
										
									 }else 	
									 {
										$fieldText=$row[$current_field->def];
										
										if (is_numeric($this->cutLength)) //taglia il testo troppo lungo eliminando i tag
										{									 										
											$fieldText=str_replace("<br />","_!_",$fieldText); 
											$fieldText=elimina_ogni_tag($fieldText);
											$fieldText=str_replace("_!_","<br />",$fieldText); 
													
			
											 
											if (strlen($fieldText)>$this->cutLength) //evitare di tagliare a meta i tags
											{
												///EVITA DI TAGLIARE UN TAG (br) A META' /////
												$cut_end=$this->cutLength;
												for($i=$this->cutLength;$i<strlen($fieldText);$i++) //cerca > dal punto in cui si taglia alla fine
												{
													if ($fieldText{$i}==">") 					   //se lo trova
													{
														for($j=$this->cutLength;$j>0;$j--) 		   //cerca < dal punto in cui si taglia fino all'inizio 
														{
															if ($fieldText{$j}=="<") 			   //se lo trova(si xkè c'è solo BR)taglia fino a lì
															{
																$cut_end=$j;
																break;
															}													
														}
														break;
													}
												}
												/////////////////////////////////////////////
												$fieldText=substr($fieldText,0,$cut_end)."<br /><strong>...[continua]</strong>";
											}
										}
										
										
									}	
										
										
										
						}


					

	
						$linkTag=false;
						
						foreach ($this->linkCol as $col)  //mette il link aggiuntivo ai campi indicati
						if (is_array($col['fieldToLink']))
						foreach ($col['fieldToLink'] as $colonna)
						{
							if ($current_field->def!=$colonna) continue;
			
							$linkTag=$this->getLinkColLink($col,$row,$fieldText);
							
							break;					
						}
						
						$print .= $linkTag ? $linkTag : $fieldText;
						
						
						
						
						$print.="</td>";
					}
					
					foreach ($this->dataCol as $col)
					{
						unset($data);
						
						switch ($col['type'])
						{
							case "RECURSIVE":	   
												    $data=$this->query_ricorsiva($row[$this->primaryKey],$col['query']); 
													break;
							case "LINKED_RECORDS": 
													$linked_result=mysql_query(str_replace("%current_row_id%",$row[$this->primaryKey],$col['query']));
													
													$data='';													
													while($linked_row=mysql_fetch_array($linked_result))
													{
														$data.="&bull; ".$linked_row[0]."<br />";//un campo solo..
													}
													break;	
							case "CALCULATION":		
													$data=0;
													foreach ($col['query'] as $q)
													{
														if (!mysql_query(str_replace("%current_row_id%",$row[$this->primaryKey],$q['query']))) echo (mysql_error());
														$tot=mysql_fetch_array(mysql_query(str_replace("%current_row_id%",$row[$this->primaryKey],$q['query'])));																									
														eval('$data=$data '.$q['operand'].'$tot[0];');	//il primo campo 
													}											
													
													break;
						}
						
						$print.=$openTD."{$data}</td>";
					}			
					
					$query_string=buildQueryString("edit_".$this->originalPrimaryTable,"del_".$this->originalPrimaryTable);			
					
					if ($this->canViewForPrint)
					{
					
						$print.= $openEditDeleteTD."<a href=\"{$_SERVER['PHP_SELF']}?view_{$this->originalPrimaryTable}={$row[$this->primaryKey]}$query_string#{$this->originalPrimaryTable}_anchor\"
						onclick=\"window.open(this.href);return false;\" onkeypress=\"if (this.event.keyCode==13) {window.open(this.href);return false;} else return false;\" >
					<img src=\"".$this->imagesAndScriptsPath."print.gif\" alt=\"Visualizza dati {$this->rowName} {$row[$this->primaryKey]}\" title=\"Visualizza dati {$this->rowName}\" style=\"border:0px\" /></a>
					</td>";
						
					}



					
					foreach ($this->linkCol as $col)
					{
						$print.= $openEditDeleteTD;
						
						$text=file_exists($col['image'])?"<img style=\"vertical-align:top;border:none;\" src=\"{$col['image']}\" alt=\"{$col['colName']}  {$this->rowName} {$row[$this->primaryKey]}\" title=\"{$col['colName']}\" />":"{$col['colName']}  {$this->rowName}";
						
						$print.=$this->getLinkColLink($col,$row,$text);	
		
						$print.= "</td>";
					
					}	
					foreach ($this->freeCol as $col)
					{
						$print.= $openEditDeleteTD.str_replace("%current_row_id%",$row[$this->primaryKey],$col['content'])."</td>";					
					}						


					// ..celle del bordo
					if (count($this->tableBorderStyle)>0) // ..riga dedicata alle celle del bordo
						$print.= "<td class=\"".$this->tableBorderStyle['dx']."\"></td>";	


										
					$print.= "</tr>";
					//$print.="<tr><td colspan=\"3\"><div style=\"visibility:visible\" id=\"form_div_{$row[$this->primaryKey]}\">".$this->buildForm($row[$this->primaryKey])."</div></td></tr>";
	
				} //end while


				if (count($this->tableBorderStyle)>0) // ..riga dedicata alle celle del bordo
				{
					$print.= "<tr>
								<td colspan=\"1\" class=\"".$this->tableBorderStyle['botsx']."\"></td>
								<td colspan=\"".$columns."\" class=\"".$this->tableBorderStyle['bot']."\"></td>
								<td colspan=\"1\" class=\"".$this->tableBorderStyle['botdx']."\"></td>
							  </tr>	
							";
				}

	
				$print.= "</table>";			
				
				
				foreach($this->tableContainer as $css)
				{
					$print.="</div>";
				}

				
				
				
				if ($multipleContext)
				{
					$print.= "
					
					
					<script type=\"text/javascript\">
					<!--
						setCheckBoxes_{$this->originalPrimaryTable}=function(val)
						{
							cb=document.forms['frm_select_{$this->originalPrimaryTable}'].elements['selected_{$this->originalPrimaryTable}[]'];
							if (typeof(cb.length)=='undefined')//solo una checkbox presente..non è un array
							cb.checked=val;
							else
							for (var i=0;i<cb.length;i++)
							cb[i].checked=val;
						}
						
						setSellen_{$this->originalPrimaryTable}=function (action)
						{
							cb=document.forms['frm_select_{$this->originalPrimaryTable}'].elements['selected_{$this->originalPrimaryTable}[]'];
							len=0;
							if (typeof(cb.length)=='undefined') //solo una checkbox presente..non è un array
							{
								if (action=='edit')
								{
									cb.checked=false;
									document.getElementById('edit_{$this->originalPrimaryTable}').value=cb.value;
								}
								len=1;
							}
							else
							{
								firstFounded=false;
								for (var i=0;i<cb.length;i++)
								{
									if (cb[i].checked==true)
									{
										len++;
										if (!firstFounded && action=='edit') //deseleziono la checkbox e imposto l'edit_ primarytable
										{
											cb[i].checked=false;
											document.getElementById('edit_{$this->originalPrimaryTable}').value=cb[i].value;
											firstFounded=true;
										}
									}
								}
							}
							document.getElementById('sellen_{$this->originalPrimaryTable}').value=len;						
						}

						getSelected_{$this->originalPrimaryTable}=function (action)
						{
							
							result=new Object();
							result.selected=Array();
							j=0;
							
							cb=document.forms['frm_select_{$this->originalPrimaryTable}'].elements['selected_{$this->originalPrimaryTable}[]'];

							len=0;
							//solo una checkbox presente..non è un array (se c'è un solo elemento nella tabella cb.value contiene l'unico id...però cb.checked è falso)
							if (typeof(cb.length)=='undefined' && typeof(cb.value)!='undefined' && cb.checked==true) 
							{
								result.selected[0]=cb.value;
							}
							else
							{
								firstFounded=false;
								for (var i=0;i<cb.length;i++)
								{
									if (cb[i].checked==true)
									{
										result.selected[j++]=cb[i].value;

									}
								}
							}

							result.action=action;
							return result;						
						}						
					-->
					</script>
					&nbsp;&nbsp;<img style=\"margin-top:10px\" src=\"".$this->imagesAndScriptsPath."puntini_orizz.png\" alt=\"\" />{$this->lang['ifSelected']} 
					
					<input type=\"hidden\" id=\"edit_{$this->originalPrimaryTable}\" name=\"edit_{$this->originalPrimaryTable}\" />
					<input type=\"hidden\" id=\"sellen_{$this->originalPrimaryTable}\" name=\"sellen_{$this->originalPrimaryTable}\" value=\"\" />";
				

					if ($this->canEdit===true || is_array($this->canEdit))
					{
						if ($this->useAjax)
						{
							$onclickKeyPress="
							onclick=\"var data=getSelected_{$this->originalPrimaryTable}('edit'); if (data.selected.length>0) DBN_{$this->originalPrimaryTable}.multipleOperation(data)\" 
							onkeypress=\"var data=getSelected_{$this->originalPrimaryTable}('edit'); if (data.selected.length>0 && this.event.keyCode==13) DBN_{$this->originalPrimaryTable}.multipleOperation(data)\"";

						}
						else
						{
							$qs="{$_SERVER['PHP_SELF']}?".buildQueryString("selected_".$this->originalPrimaryTable,"action_".$this->originalPrimaryTable,"sellen_".$this->originalPrimaryTable);
							$onclickKeyPress="
							onclick=\"var data=getSelected_{$this->originalPrimaryTable}('edit'); if (data.selected.length>0) location.href='{$qs}'+DBN_{$this->originalPrimaryTable}.getMultipleOperationParams(data)\" 
							onkeypress=\"var data=getSelected_{$this->originalPrimaryTable}('edit'); if (data.selected.length>0 && this.event.keyCode==13) location.href='{$qs}'+DBN_{$this->originalPrimaryTable}.getMultipleOperationParams(data)\"";
						}


										
						$print.= "
						<label for=\"action_{$this->originalPrimaryTable}_1\"></label>
						<button type=\"button\" {$onclickKeyPress}>
							<img src=\"".$this->imagesAndScriptsPath."edit.png\" alt=\"{$this->lang['edit']}\" />
						</button> ";
						
						if ($this->useAjax)
						{
							$onclickKeyPress="
							onclick=\"var data=getSelected_{$this->originalPrimaryTable}('editMany'); if (data.selected.length>0) DBN_{$this->originalPrimaryTable}.multipleOperation(data)\" 
							onkeypress=\"var data=getSelected_{$this->originalPrimaryTable}('editMany'); if (data.selected.length>0 && this.event.keyCode==13) DBN_{$this->originalPrimaryTable}.multipleOperation(data)\"";

						}
						else
						{
							$qs="{$_SERVER['PHP_SELF']}?".buildQueryString("selected_".$this->originalPrimaryTable,"action_".$this->originalPrimaryTable,"sellen_".$this->originalPrimaryTable);
							$onclickKeyPress="
							onclick=\"var data=getSelected_{$this->originalPrimaryTable}('editMany'); if (data.selected.length>0) location.href='{$qs}'+DBN_{$this->originalPrimaryTable}.getMultipleOperationParams(data)\" 
							onkeypress=\"var data=getSelected_{$this->originalPrimaryTable}('editMany'); if (data.selected.length>0 && this.event.keyCode==13) location.href='{$qs}'+DBN_{$this->originalPrimaryTable}.getMultipleOperationParams(data)\"";
						}
						
						
						$print.= "
						<label for=\"action_{$this->originalPrimaryTable}_3\"></label>
						<button type=\"button\" {$onclickKeyPress}\">
							<img src=\"".$this->imagesAndScriptsPath."editMany.gif\" alt=\"\" />
						</button> ";
						
						
					}

					
					if ($this->canDelete===true || is_array($this->canDelete))
					{
					
						if ($this->useAjax)
						{
							$onclickKeyPress="
							onclick=\"var data=getSelected_{$this->originalPrimaryTable}('delete'); if (data.selected.length>0 && confirm('{$this->lang['reallyDeleteMultiple']}')) DBN_{$this->originalPrimaryTable}.multipleOperation(data)\" 
							onkeypress=\"var data=getSelected_{$this->originalPrimaryTable}('delete'); if (data.selected.length>0 && confirm('{$this->lang['reallyDeleteMultiple']}') && this.event.keyCode==13) DBN_{$this->originalPrimaryTable}.multipleOperation(data)\"";

						}
						else
						{
							$qs="{$_SERVER['PHP_SELF']}?".buildQueryString("selected_".$this->originalPrimaryTable,"action_".$this->originalPrimaryTable,"sellen_".$this->originalPrimaryTable);
							$onclickKeyPress="
							onclick=\"var data=getSelected_{$this->originalPrimaryTable}('delete'); if (data.selected.length>0 && confirm('{$this->lang['reallyDeleteMultiple']}')) location.href='{$qs}'+DBN_{$this->originalPrimaryTable}.getMultipleOperationParams(data)\" 
							onkeypress=\"var data=getSelected_{$this->originalPrimaryTable}('delete'); if (data.selected.length>0 && confirm('{$this->lang['reallyDeleteMultiple']}') && this.event.keyCode==13) location.href='{$qs}'+DBN_{$this->originalPrimaryTable}.getMultipleOperationParams(data)\"";
						}
						
						
						$print.= "
						<label for=\"action_{$this->originalPrimaryTable}_3\"></label>
						<button type=\"button\" {$onclickKeyPress}\">
							<img src=\"".$this->imagesAndScriptsPath."delete.png\" alt=\"\" />
						</button> ";
						
											
					/*
					if ($this->canDelete===true || is_array($this->canDelete))
					$print.= "					
					 <label for=\"action_{$this->originalPrimaryTable}_2\"></label>
					<button type=\"submit\" name=\"action_{$this->originalPrimaryTable}\" id=\"action_{$this->originalPrimaryTable}_2\" value=\"delete\" 
					onclick=\"setSellen_{$this->originalPrimaryTable}(this.value);return confirm('{$this->lang['reallyDeleteMultiple']}')\" onkeypress=\"if (this.event.keyCode==13) {setSellen_{$this->originalPrimaryTable}(this.value);return confirm('{$this->lang['reallyDeleteMultiple']}');} else return false;\">
						<img src=\"".$this->imagesAndScriptsPath."delete.png\" alt=\"{$this->lang['edit']}\" />
					</button> ";
					*/
					}
					
					$print.= "	
					<a href=\"javascript:setCheckBoxes_{$this->originalPrimaryTable}(true)\">{$this->lang['selectAll']}</a> | 
					<a href=\"javascript:setCheckBoxes_{$this->originalPrimaryTable}(false)\">{$this->lang['unselectAll']}</a>
					</form>	
					";
					
				}
					
			}
			else
			{
			 	$print.=$viewing_data_function($result);
			}
			
			$print.=$navigation; //NAVIGAZIONE IN UNA VARIABILE			
			
		}
		else
		$print.= "<span style=\"font-size:13px;font-weight:bolder\"><em>- {$this->lang['noResults']}</em></span>";
		
		

		$print=$this->brutalTextReplace($replace_array,$print);
		
		echo $print;
	}
	
	private function brutalTextReplace($replace_array,$text) 
	{
		if (!is_array($replace_array)) return $text;																	
		
		foreach($replace_array as $search=>$replace) 														
		{
			if ($search{0}=='/' && $search{strlen($search)-1}=='/')
				$text = preg_replace($search,$replace,$text); 						
			else
				$text =  str_replace($search,$replace,$text); 						
		}
		
		return $text;		
	}
	
	private function manage_record_availability($id,$bookRecord)	
	{
		//session_start();
		//ob_end_clean();
		$row=mysql_fetch_array(mysql_query("SELECT * FROM busy_records WHERE table_name=\"{$this->originalPrimaryTable}\" AND record_id=\"{$id}\""));
		
		if ($row)
		{
			if ($row['user_session_id']==session_id()) //se il record è occupato dal client allora aggiorna l'expire_date
			{  
				mysql_query("UPDATE busy_records SET expire_time=\"".strtotime("+7 seconds")."\"  
				WHERE table_name=\"{$this->originalPrimaryTable}\" AND record_id=\"{$id}\" AND user_session_id=\"".session_id()."\"");		
				
				return true;
			}
			else 
			//die(print_r($row,true)); 
			return false;
		}
		else
		{
			if ($bookRecord)
			mysql_query("INSERT INTO busy_records(table_name,record_id,user_session_id,expire_time)
			VALUES (\"{$this->originalPrimaryTable}\",\"{$id}\",\"".session_id()."\",\"".strtotime("+7 seconds")."\")");
		
			return true;
		}
		
	}
		
	private function buildForm($id=null,$replace_array=null,$show_back_link=true)
	{

		//print_r($this->field);
		//print_r($this->externalData);
		$print="";
		
		$fieldEnablingControl="";


		$qs=buildQueryString("del_{$this->originalPrimaryTable}");//il del lo tolgo perchè si può accedere qui anche se si voleva eliminare un record usato
		$form_target=$_SERVER['PHP_SELF']."?$qs#{$this->originalPrimaryTable}_anchor";
	
		if ($show_back_link)
		{ 
			if ($this->useAjax) $back_href="javascript:DBN_{$this->originalPrimaryTable}.printTable()";
			else
			{
				$qs=buildQueryString("del_{$this->originalPrimaryTable}",'edit_'.$this->originalPrimaryTable,"action_{$this->originalPrimaryTable}","sellen_{$this->originalPrimaryTable}","selected_{$this->originalPrimaryTable}");
				$back_href=$_SERVER['PHP_SELF']."?$qs#{$this->originalPrimaryTable}_anchor";
			}
		}
		
		
		if (!is_array($id))
		{
		
			$row=mysql_fetch_array(mysql_query($this->addWhereConditionToQuery($this->query,"{$this->primaryTable}.{$this->originalPrimaryKey}='$id'")));
	
			//$print.= $this->addWhereConditionToQuery($this->query,"{$this->primaryTable}.{$this->primaryKey}='$id'");
			if ($row) //Modalità modifica
			{
				if ($this->manage_record_availability($id,true)==false)
				{
					return "<br /><div style=\"cursor:wait;font-weight:bolder;border:1px solid #FF0000;padding:3%\">
					{$this->lang['warningRecordOccupied']}
					<a href=\"".($show_back_link?$back_href:"javascript:history.back();")."\">&raquo; {$this->lang['goBack']}</a> 
					</div><br />
					
					<script type=\"text/javascript\">
					<!--
						DBN_{$this->originalPrimaryTable}.checkAvailability=setInterval(\"DBN_{$this->originalPrimaryTable}.manage_record_availability_for_editing($id,false)\",3000); // rifa il controllo dopo 7 secondi					
					-->
					</script>
					";
				}else
				{
				
					$print.="
					<script type=\"text/javascript\">
					<!--
						DBN_{$this->originalPrimaryTable}.checkAvailability=setInterval(\"DBN_{$this->originalPrimaryTable}.manage_record_availability_for_editing($id,true)\",3000); // rifa il controllo dopo 7 secondi																
					-->
					</script>
					";
				}

				
				$edit=1;			
		
				$formHeading=$this->lang['editRecord'];//." $id";
							
				
				if (is_array($this->photoField) || is_array($this->fileField)) //formattazione div contenitore per le immagini (e file)
				{
	
					foreach ($this->photoField as $field=>$bool)
					{ 
						if ($field=="_Resize_" || $field=="_KeepOriginal_") continue; ////da sistemare......? parametri delle immagini nello stesso array
						if ($row[$field]!="")
						{			
							if (!isset($div_flag)) //stampa il div una volta sola , solo se c'è qualcosa 
							{
								$print.= "<div style=\"position:relative;float:right;border:1px solid #000000;width:20%;padding:6px 0px 6px 6px;margin:10px 0px\">";
								$div_flag=true;
							}
							else $print.="<br /><br />";
								
							$print.="<strong>".$this->lang['current']." ".str_replace("_"," ",ucfirst($field))."</strong><br />";	
							
							
							
							if (  intval($this->photoField['_Resize_'])!=0 && $this->photoField['_KeepOriginal_']) //origin.+miniatura: crea il link per l'originale
							{
								
								$print.="<a href=\"{$this->filePath}/{$row[$field]}\" onclick=\"window.open(this.href);return false;\">";
								$print.="<img src=\"{$this->filePath}/small_{$row[$field]}\" style=\"".getImageResizedValues($this->filePath."/".$row[$field],130,130)
								.";border:none\" alt=\"{$row[$field]}\" /><br />".$row[$field]."</a><br /><br />";
														
							} else //solo immagine O solo miniatura
							{
								$pre= $this->photoField['_KeepOriginal_'] ? "" : "small_" ;
									
								$print.="<img src=\"{$this->filePath}/{$pre}{$row[$field]}\" 
											  style=\"".getImageResizedValues($this->filePath."/".$pre.$row[$field],130,130)."\" 
											  alt=\"{$pre}{$row[$field]}\" /><br />".str_replace("_"," ",ucfirst($row[$field]));
							}
							

							
							$this->photoField[$field]=true; ///
						}
					}
	
					foreach ($this->fileField as $field=>$bool)
					{ 
						if ($row[$field]!="")
						{
							if (!isset($div_flag))  //stampa il div una volta sola , solo se c'è qualcosa 
							{
								$print.= "<div style=\"position:relative;float:right;border:1px solid #000000;width:20%;padding:6px 0px 6px 6px;margin:10px 0px\">";
								$div_flag=true;
							}
							else $print.="<br /><br />";					
							
							$print.="<strong>".$this->lang['current']." ".str_replace("_"," ",ucfirst($field))."</strong>
							<a href=\"{$this->filePath}/{$row[$field]}\" onclick=\"window.open(this.href);return false;\"><strong>".
							str_replace("_"," ",ucfirst($row[$field]))."</strong></a><br /><br />";
							$this->fileField[$field]=true; ///
						}
					}
					if (isset($div_flag)) {
											$print.="</div>";
											$this->formWidth[1]-=25;
										  }
				}
			} else //INSERIMENTO
			{

				$edit=0; 
				
				$formHeading=$this->lang['insertNew'];
				
			}
		
		}
		else  //array di id
		{
			$edit=1; 
			
			$formHeading="<strong>".str_replace("***","<span style=\"color:#F00\">".count($id)."</span>",$this->lang['multipleEditingHeading'])."</strong>";
			
			$occupiedId=false;
			$jsArray=array();
			foreach($id as $ids)
			if ($this->manage_record_availability($ids,true)==false) 
			{
				$occupiedId=true;//un record occupato
			}
			
				
			//questa funzione mantiene la prenotazione dei record trovati disponibili, ed eventualmente chiama la funzione per ristampare il form
			//quando quello occupato diventa libero
			$print.="
			<script type=\"text/javascript\">
			<!--
				DBN_{$this->originalPrimaryTable}.checkAvailability=setInterval(\"DBN_{$this->originalPrimaryTable}.manage_record_availability_for_editing([".implode(',',$id)."],".($occupiedId?'false':'true').")\",3000); // rifa il controllo dopo 7 secondi																
			-->
			</script>
			";
			
			//se ce n'è uno occupato termina qui
			if ($occupiedId)
			return $print."<br /><div style=\"cursor:wait;font-weight:bolder;border:1px solid #FF0000;padding:3%\">
							{$this->lang['warningRecordOccupied']}
							<a href=\"".($show_back_link?$back_href:"javascript:history.back();")."\">&raquo; {$this->lang['goBack']}</a> 
							</div><br />";


		}
		///////////////Reinserimento valori nel form//////////////////
		///*************** S E M P R E !!!!!!!! ***************
		
		foreach ($_POST as $name=>$value) 
		{
			

			if (substr($name,strlen($name)-4,4)=="_ifr")
				$name=substr($name,0,strlen($name)-4);
			else
				$value=$this->convertSpecialChars($value);
			
			if (substr($name,strlen($name)-4,4)=="_day") {$data_generica=$value;continue;}
			if (substr($name,strlen($name)-4,4)=="_mon") {$data_generica=$value."-".$data_generica;continue;}
			if (substr($name,strlen($name)-4,4)=="_yea") {$value=$value."-".$data_generica; $name=substr($name,0,strlen($name)-4);}
					
				//campi della tabella principale
			foreach ($this->field as $current_field)
			{
				if ($current_field->name==$name)// || $current_field->def==$name)
				{
					//$row[$current_field->name]=stripslashes($value);
					if (is_array($value))
					$row[$current_field->def]=implode(",",$value);
					else
					$row[$current_field->def]=stripslashes($value);				
					continue 2;
				}
					
			}//end foreach
				
			//campi collegati
			foreach ($this->externalData as $ed)
			{
				$chiave=$ed["ex_primaryKey"];
				$chiave_esterna=$ed["externalKey"];
				$alias=$ed["ex_alias"];
					
				if ($chiave_esterna==$name)
				{
						$row[$chiave_esterna]=stripslashes($value); //???
						$row[$alias]=stripslashes($value);				
						continue 2;
				}
					
			}//end foreach				
				
		}//end foreach principale
		//print_r($_POST);
		//print_r($row);
		//print_r($this->externalData);
		/////////////////////////////////////////
		
///INTESTAZIONI FORM
			$print.="<div>";
			
			if ($this->formHeading=="")
			$print.= "<span style=\"font-size:18px;font-weight:bolder\">$formHeading</span>";
			else
			$print.= $this->formHeading;
			
			
			if ($show_back_link==true)
			$print.= "<h3><a href=\"$back_href\">".$this->lang['backToData']."</a></h3>";
			
			$print.="</div>";
//////////////
		
		$this->editForm->defineParams("frm_{$this->originalPrimaryTable}",$form_target,$this->formWidth[0],$this->formWidth[1],strip_tags($formHeading));		
			
			
		$this->editForm->addInput("hidden","edit_".$this->originalPrimaryTable,$edit);	
		

		//print_r($this->externalData);
		//print_r($this->field);

		foreach ($this->field as $current_field)
		{
			
			if (isset($this->removeInput[$current_field->name])) continue; //Salto per gli hiddenInput Indicati manualmente
			

			if (!isset($row[$current_field->def])) $row[$current_field->def]=''; //Evita i notice di indici di array non esistenti
																				//NB: ->def contiene sempre il nome dell'indice giusto(alias o nome se non c'è alias)
			//echo $current_field->name." - ".$current_field->def."<br />";


			if (is_array($id) && isset($this->removeMultipleEditingInput[$current_field->def])) continue; //
			
			$maxlength=explode("(",$current_field->type); //eg. field.type='string(100)'
			$maxlength=substr($maxlength[1],0,-1);
			
			if ($current_field->name==$this->originalPrimaryKey) 
			{
				$TYPE=explode("(",$current_field->type);
				if ($TYPE[0]=='string' && $edit==0) //se la chiave primaria è una stringa la fa modificare solo in inserimento -- NON TESTATO E COMPLETO
				$this->editForm->addInput("text",$this->originalPrimaryKey,$row[$current_field->name],ucfirst(str_replace("_"," ",$current_field->def))
				                          ,$maxlength,false,$current_field->not_null,$this->classForFormInput[inputs]); 
				else //altrimenti se si è in modifica aggiunge un hidden
				{
					if (!is_array($id))	
					$this->editForm->addInput("hidden",$this->originalPrimaryKey,$id);
					else
					foreach ($id as $i) //array di input per gli id
						$this->editForm->addInput("hidden",$this->originalPrimaryKey."[]",$i);	

				}
				
				
				continue;
			} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			
			if ($current_field->table!=$this->primaryTable ) //**CAMPI COLLEGATI A TABELLE ESTERNE
			{
			
			
				////////////////////CONTROLLO ESISTENZA CAMPO COLLEGATO
				$founded=false;
				foreach($this->externalData as $key=>$val)
				{
					if ($val['ex_table']==$current_field->table && $val['ex_field']==$current_field->name && $val['ex_alias']==$current_field->def)
					{
						$founded=$key;
						break;
					}
						
				}
				if ($founded===false) continue;  //se non esiste il collegamento salta...
				
				//if (!isset($this->externalData[$current_field->table.".".$current_field->name])) continue; //se non esiste il collegamento salta...
			
				////////////////////////////////////////////////////
			
				
				if (strpos($this->query," AS ".$current_field->table." ")!=false)  //CERCA l'[ALIAS DELLA TABELLA] !!!!
				{
					$exp=explode(" AS ".$current_field->table." ",$this->query);
					$exp2=explode(" ",$exp[0]);	
					$table=$exp2[(count($exp2)-1)];
				}
				else $table=$current_field->table;
				
				//$dato_principale=$current_field->name;
				$dato_principale=$current_field->name;
				
				//echo $dato_principale;
				$chiave=$this->externalData[$founded]["ex_primaryKey"];
				$chiave_esterna=$this->externalData[$founded]["externalKey"];
				$alias=$this->externalData[$founded]["ex_alias"];
				
				$alias_show=ucfirst(str_replace("_"," ",$alias));
				
				if (isset($this->removeInput[$chiave_esterna])) continue; //Salto per gli hiddenInput Indicati manualmente
				
				$result_esterna=mysql_query("SELECT * FROM $table ORDER BY {$chiave}"); 

				
				//print_r($this->externalData);
				
				
				$value=array(""=>$this->lang['select']." ".$alias_show);
				
				$selected="";

				while ($row_esterna=mysql_fetch_array($result_esterna))
				{
					//$print.= $row[$dato_principale];
					$value[$row_esterna[$chiave]]=$row_esterna[$dato_principale];
					//echo "\$value[{$row_esterna[$chiave]}]=\$row_esterna[{$dato_principale}]";
								
					//echo "<br />if (\$row[{$alias}(\$alias)]==\$row_esterna[{$dato_principale}(\$dato_principale) oppure {$chiave}(\$chiave)]) \$selected=\$row_esterna[{$chiave}(\$chiave)]<br />";
					if ($row[$alias]==$row_esterna[$dato_principale]) $selected=$row_esterna[$chiave]; //?? ci dovrebbe essere solo il controllo sotto?
					if ($row[$alias]==$row_esterna[$chiave]) $selected=$row_esterna[$chiave]; //per il POST		
					//if ($row[$chiave_esterna]==$row_esterna[$chiave]) $selected=$row_esterna[$chiave]; //per il POST

				}		
				
				
				$dati_chiave_esterna=mysql_fetch_field(mysql_query("Select $chiave_esterna FROM $this->originalPrimaryTable"));
				$validate=$dati_chiave_esterna->not_null==1?REGEXP_NOTNULL:false; //maremma troia! gliel'assegna qui stocazzo di validazione
				
				$added=$this->editForm->addInput("select",$chiave_esterna,$value,$alias_show,false,$selected,$validate,$this->classForFormInput['inputs']);			
				
				if (is_array($id) && $added) $fieldEnablingControl.= $this->getFieldEnablingControl('SELECT',$chiave_esterna,$alias_show);
				
			}
			else //*****CAMPI DELLA TABELLA PRINCIPALE
			{
			
				if (is_array($id)) ///i campi univoci non si modificano per + record
				{
					$describe=mysql_query("DESCRIBE ".$this->originalPrimaryTable);  	
					while ($describe_field=mysql_fetch_array($describe))
					if ($describe_field['Field']==$current_field->name && $describe_field['Key']=="UNI") continue 2; //..
				}

			 		
				$TYPE=explode("(",$current_field->type);//serve per identificare gli ENUM -- prima era l'explode con ('

				switch($TYPE[0])
				{	
					case "password":if (is_array($id)) break;
									
									if ($edit==0)
									$this->editForm->addInsertPasswordInputs($current_field->name,ucfirst(str_replace("_"," ",$current_field->def)),$this->classForFormInput['inputs']);
									else
									$this->editForm->addChangePasswordInputs($current_field->name,ucfirst(str_replace("_"," ",$current_field->def)),$this->classForFormInput['inputs']);
									break;
					case "date":

									if (isset($this->monthYearField[$current_field->name]))
										$t="DATE_MY";
									else
										$t="DATE";	
										

									$added=$this->editForm->addInput($t,"$current_field->name",array($this->dateInterval[0],$this->dateInterval[1]),ucfirst(str_replace("_"," ",$current_field->def)),true,$row[$current_field->def],$current_field->not_null,$this->classForFormInput['inputs']);

									if (is_array($id) && $added) 
										$fieldEnablingControl.= $this->getFieldEnablingControl('DATE',$current_field->name,$current_field->def);

															
								break;
					case"string":
					case"int": 		//print_r($current_field);			
					case"real":	
								
								if (isset($this->photoField[$current_field->name]) || isset($this->fileField[$current_field->name]))
								{
									if (is_array($id)) break; //foto non modificate in modo multiplo
									
									if (
										(isset($this->photoField[$current_field->name]) && $this->photoField[$current_field->name]==true)
										|| 
										(isset($this->fileField[$current_field->name]) && $this->fileField[$current_field->name]==true)
										)
									{
										if ($current_field->not_null[0]==true) $bool=false; else {$bool=true;} //do' la possibilità di eliminare il file 
																											//solo se non è un campo obbligatorio
										$current_field->not_null[0]=false; //in ogni caso, una volta che il file è stato caricato, non gli assegno
																			//una validazione obbligatoria nel form 
										
									} else
									$bool=false;

										
									$this->editForm->addInput("file",$current_field->name,$row[$current_field->def],ucfirst(str_replace("_"," ",$current_field->def)),$bool,false,$current_field->not_null,$this->classForFormInput['inputs']);
								}
								else 
								{
								
									$added=$this->editForm->addInput("text",$current_field->name,$row[$current_field->def]
																	 ,ucfirst(str_replace("_"," ",$current_field->def)),$maxlength,false,$current_field->not_null
																	 ,$this->classForFormInput['inputs']);

									if (is_array($id)  && $added) 
									{
										$JS= "
										new AutoSuggestControl('{$this->originalPrimaryTable}',document.getElementById(\"{$current_field->name}\"),\"{$current_field->name}\");
										";

										if ($this->ajaxCall) $print.="<script type=\"text/javascript\"><!-- {$JS} --></script>";
										else $this->JS_onLoad.=$JS;									
										
										$fieldEnablingControl.= $this->getFieldEnablingControl('TEXT',$current_field->name,$current_field->def);
									}
								}
								
								break;
																	
					case "longtext": 
					case "mediumtext": 
									
									$added=$this->editForm->addInput("textarea",$current_field->name,$row[$current_field->def]
										  ,ucfirst(str_replace("_"," ",$current_field->def)),$this->HTMLTextareaParams,false,$current_field->not_null
										  ,$this->classForFormInput['textareas']); 

									if (is_array($id) && $added)
										$fieldEnablingControl.= $this->getFieldEnablingControl('HTML_TEXTAREA',$current_field->name,$current_field->def);

								break;		 
					
					case "text": 
					case "tinytext":   
									
									$added=$this->editForm->addInput("textarea",$current_field->name,$row[$current_field->def]
										  ,ucfirst(str_replace("_"," ",$current_field->def)),false,false,$current_field->not_null
										  ,$this->classForFormInput['textareas']); 		 

									if (is_array($id) && $added)
										$fieldEnablingControl.= $this->getFieldEnablingControl('TEXTAREA',$current_field->name,$current_field->def);	
									
								break;
					
					case"enum": 
								$heading=ucfirst(str_replace("_"," ",$current_field->def));								
								
								$value=$this->getEnumSetValue($current_field->type);
																				
								if (count($value)>$this->radioSettings['maxOptionsInOneLine']) $bool=false; else $bool=true; //su una riga o no
								
								if (count($value)>$this->radioSettings['maxOptions']) 
								{
									$type="SELECT";
									$value=array_merge(array(''=>$this->lang['select']." ".$heading), $value); //aggiungo l'intestazione
								}
								else 
								{
									$type="RADIO";									
								}
																						
								$added=$this->editForm->addInput($type,$current_field->name,$value,$heading,$bool,$row[$current_field->def]
									  ,$current_field->not_null,$this->classForFormInput['inputs']); 
								
								if (is_array($id) && $added) 
									$fieldEnablingControl.= $this->getFieldEnablingControl($type,$current_field->name,$current_field->def);										
																	
								break;		 
					
					case"set" :	
								$heading=ucfirst(str_replace("_"," ",$current_field->def));
								
								$value=$this->getEnumSetValue($current_field->type);
								
								
								if (count($value)>$this->checkboxesSettings['maxCheckboxes'])
								{
									$type="SELECT";
									/////////////$value=array_merge(array(''=>$this->lang['select']." ".$heading), $value); //aggiungo l'intestazione
									$bool=$this->checkboxesSettings['multipleSelectSize'];
								}
								else 
								{
									$type="CHECKBOX";	
									$bool=false;								
								}								

								$added=$this->editForm->addInput($type,$current_field->name,$value,$heading,$bool,explode(",",$row[$current_field->def])
									  ,$current_field->not_null,$this->classForFormInput['inputs']); 
									  								
								if (is_array($id) && $added) 
									$fieldEnablingControl.= $this->getFieldEnablingControl($type,$current_field->name,$current_field->def,count($value));																									
								
								break;		 
				
				}//end switch
			}//end if
		} //end foreach
		
		
		if ($fieldEnablingControl!="") //intestazione
			$print.="<div style=\"border-top:1px solid #DDD;border-bottom:1px solid #DDD;padding:6px 0px;
								  margin-bottom:6px;font-weight:bolder;font-size:larger;font-style:italic\">
						{$this->lang['fieldEnablingControlHeading']}</div>";
			
		
		$editForm_string = $this->editForm->buildForm($this->lang['confirmData'],$this->classForFormInput['buttons']);		
		$editForm_string = $this->brutalTextReplace($replace_array,$editForm_string);

		if ($this->useAjax)
			$editForm_string=str_replace("<form ","<form onsubmit=\"document.getElementById('img_loading_dbn').style.display='block'\"",$editForm_string);
		
		$print.= $editForm_string;

		if ($fieldEnablingControl!="") //codice javascript ---deve essere messo DOPO il form altrimenti la rilevazione
			$print.=$fieldEnablingControl; // dello stato della textarea HTML non riesce perchè deve ancora inizializzarsi

	
		return $print;
	}	
	
	//serve per identificare i valori dell'ENUM/SET
	private function getEnumSetValue($typeDefinition)
	{
		$start_cut=strpos($typeDefinition,"('")+2;
		$value=substr($typeDefinition,$start_cut,-2);
		
		$temp=explode("','",$value);
		$value=array();	
		foreach($temp as $v)
		{
			$v=str_replace(array("''","\\\\",),array("'","\\"),$v);
			$value[$v]=ucfirst($v);
		}	
		return $value;							
	}

	private function getFieldEnablingControl($type,$name,$heading,$length=null)
	{
		$JSDisable="";
		
		if ($this->ajaxCall) $JSDisable="change_{$name}_status();";
		else $this->JS_onLoad.="
									change_{$name}_status();
								";		
			
		//stato: abilitato. link per disabilitare la modifica sul campo																								
		$enableCode="											
							a.style.color='#C00';
							a.innerHTML='[ <img style=\"border:0px\" src=\"".$this->imagesAndScriptsPath."delete.png\" /> DO NOT Edit ]&nbsp;&nbsp;&nbsp;';
													   ";
		
		//stato: disabilitato. link per abilitare la modifica sul campo																
		$disableCode="																								
							a.style.color='#060';
							a.innerHTML='[ <img style=\"border:0px\" src=\"".$this->imagesAndScriptsPath."edit.png\" /> EDIT ]&nbsp;&nbsp;&nbsp;' ;
																							
													  ";
	
													
		switch(strtoupper($type))
		{
			case 'DATE':		
								$JSFunctionBody="
												var el1=document.getElementById('frm_{$this->originalPrimaryTable}').{$name}_day; 
												var el2=document.getElementById('frm_{$this->originalPrimaryTable}').{$name}_mon;
												var el3=document.getElementById('frm_{$this->originalPrimaryTable}').{$name}_yea;
												
												container = el1.parentNode.parentNode.previousSibling.previousSibling;	
												
												//alert(container.innerHTML);
												
												
												if (el1.style.display=='none')
												{
													el1.disabled=false;
													el2.disabled=false;
													el3.disabled=false;
													
													el1.style.display='block';
													el2.style.display='block';
													el3.style.display='block';
													
													
													{$enableCode}
													
												}
												else
												{
													el1.disabled=true;
													el2.disabled=true;
													el3.disabled=true;
													
													el1.style.display='none';
													el2.style.display='none';
													el3.style.display='none';
													
													{$disableCode}

													
												}
										";	
								break;	
								
			case 'HTML_TEXTAREA':
								$JSFunctionBody="
												if (document.all)
												{
													var elDoc = window.document.frames('{$name}').document;
													var el = window.document.frames('{$name}');
												}
												else
												{
													var elDoc = document.getElementById('{$name}').contentDocument;										
													var el = document.getElementById('{$name}');										
												}
												
												container = el.parentNode;	
//alert(el.parentNode.getElementsByTagName('div')[0].innerHTML);
												
												if (elDoc.designMode=='off')
												{
													elDoc.designMode='on';
													el.style.height='auto';
													//el.parentNode.getElementsByTagName('div')[0].style.visibility='visible';
													{$enableCode}
													
												}
												else
												{
													elDoc.designMode='off';
													el.style.height='0px';
													///el.parentNode.getElementsByTagName('div')[0].style.visibility='hidden';
													{$disableCode}
													
												}
										";	
								break;	
			case 'TEXTAREA':																		
							$JSFunctionBody= "
											var el=document.getElementById('frm_{$this->originalPrimaryTable}').{$name}; 
											
											container = el.parentNode;	
																							
											if (el.style.display=='none')
											{
												el.disabled=false;
												el.style.display='block';

												//aggiungo all'input che indica i campi da modificare
												
												{$enableCode}
												
											}
											else
											{						
												el.disabled=true;																		
												el.style.display='none';

												
												{$disableCode}																																
											}											
									";
							
							break;	
															
			case 'TEXT':
			case 'SELECT':																		
							$JSFunctionBody= "
											var el=document.getElementById('frm_{$this->originalPrimaryTable}').{$name}; 
											
											container = el.parentNode.previousSibling.previousSibling;	
																							
											if (el.style.display=='none')
											{
												el.disabled=false;
												el.style.display='block';

												//aggiungo all'input che indica i campi da modificare
												
												{$enableCode}
												
											}
											else
											{						
												el.disabled=true;																		
												el.style.display='none';

												
												{$disableCode}																																
											}											
									";
							
							break;	
							
												
			case 'RADIO':
						$JSFunctionBody="
											var el=document.getElementById('frm_{$this->originalPrimaryTable}').{$name}; 
									
											container = el[0].parentNode.parentNode.parentNode.childNodes[1];	
											
									
											if (el[0].disabled==true)
											{
												
												for (i=0;i<el.length;i++) el[i].disabled=false;
												
												el[0].parentNode.parentNode.style.visibility='visible';
												{$enableCode}										
											}
											else
											{
												
												for (i=0;i<el.length;i++) el[i].disabled=true;

												el[0].parentNode.parentNode.style.visibility='hidden';
												{$disableCode}	
											}
									";
						break;
						
			case 'CHECKBOX':
						$JSFunctionBody="
											var el=document.getElementById('frm_{$this->originalPrimaryTable}').elements['{$name}[0]']; 


											container = el.parentNode.parentNode.parentNode.childNodes[1];	

											
											if (el.disabled==true)
											{
												for (i=0;i<{$length};i++) 
													document.getElementById('frm_{$this->originalPrimaryTable}').elements['{$name}['+i+']'].disabled=false;
												
												el.parentNode.parentNode.style.visibility='visible';
												{$enableCode}			
											}
											else
											{
												for (i=0;i<{$length};i++) 
													document.getElementById('frm_{$this->originalPrimaryTable}').elements['{$name}['+i+']'].disabled=true;
													
												el.parentNode.parentNode.style.visibility='hidden';
												{$disableCode}		
											}										
									";
						break;
		}

		return "
				<script type=\"text/javascript\">
					<!--
						change_{$name}_status=function()
						{
							fieldList=document.getElementById('frm_{$this->originalPrimaryTable}').fieldList;
							
							if (fieldList.value.indexOf('{$name}')!=-1) //rimuovo dall'input che indica i campi da modificare
							{
								exp=fieldList.value.split(',');
								for (i=0;i<exp.length;i++)
								if (exp[i]=='{$name}')
								{
									temp=exp[exp.length-1];
									exp[exp.length-1]=exp[i];
									exp[i]=temp;
									exp.pop();
									temp=true;
									break;
								}
								fieldList.value=exp.join(',');
								
							}
							else //da riaggiungere il nome nella field List
								fieldList.value+=',{$name}';
							
							//alert(fieldList.value);						
							
							var a=document.createElement('a');	//il nuovo elemento link che fa lo switch...
							
							{$JSFunctionBody}
		
							a.style.fontWeight='Bold';
							a.style.textDecoration='none';
							a.href='javascript:change_{$name}_status()';

														
							div=document.createElement('div');
							div.appendChild(a); 
							old = container.replaceChild(div,container.firstChild);
							
		
							if ( old.innerHTML.indexOf('<a')==0) //c'è il link come primo elemento
								div.appendChild(old.lastChild);	
							else 								//prima sostituzione ...metto l'etichetta in fondo
								div.appendChild(old);	
						}
						{$JSDisable}
						
					-->
					</script>

					";			
		
		
	}	
	
	private function viewForPrint($id=null)
	{
		$print="";

		
		$row=mysql_fetch_array(mysql_query($this->addWhereConditionToQuery($this->query,"{$this->primaryTable}.{$this->originalPrimaryKey}='$id'")));

		//$print.= $this->addWhereConditionToQuery($this->query,"{$this->primaryTable}.{$this->primaryKey}='$id'");
		if ($row) //Modalità modifica
		{
			
			
			if (is_array($this->photoField) || is_array($this->fileField)) //formattazione div contenitore per le immagini (e file)
			{

				foreach ($this->photoField as $field=>$bool)
				{ 
					if ($field=="_Resize_" || $field=="_KeepOriginal_") continue; ////da sistemare......? parametri delle immagini nello stesso array
					if ($row[$field]!="")
					{			
						if (!isset($div_flag)) //stampa il div una volta sola , solo se c'è qualcosa 
						{
							$print.= "<div style=\"position:relative;float:right;border:1px solid #000000;width:47%;padding:2% 0% 2% 2%\">";
				 			$div_flag=true;
						}
							
						if (!$this->photoField['_Resize_']) $small=""; else $small="small_";
						$print.="<h4>".ucfirst($field)." corrente</h4>";
						if ($small=="small_") $print.="<a href=\"{$this->filePath}/{$row[$field]}\" onclick=\"window.open(this.href);return false;\">";
						$print.="<img src=\"{$this->filePath}/$small{$row[$field]}\" alt=\"{$row[$field]}\" /><br />".$row[$field];
						if ($small=="small_") $print.="</a>";
						$this->photoField[$field]=true; ///
					}
				}

				foreach ($this->fileField as $field=>$bool)
				{ 
					if ($row[$field]!="")
					{
						if (!isset($div_flag))  //stampa il div una volta sola , solo se c'è qualcosa 
						{
							$print.= "<div style=\"position:relative;float:right;border:1px solid #000000;width:47%;overflow:scroll;padding:2% 0% 2% 2%\">";
				 			$div_flag=true;
						}					
						$print.="<h3>".ucfirst($field)." corrente</h3>
						<a href=\"{$this->filePath}/{$row[$field]}\" onclick=\"window.open(this.href);return false;\"><strong>{$row[$field]}</strong></a>";
						$this->fileField[$field]=true; ///
					}
				}
				if (isset($div_flag)) $print.="</div><div style=\"position:relative;float:left;width:50%\">";
			}
		} else 
		{
			die('Id errato');
		}

		$print.="
		<div style=\"font-size:15px;font-family:Arial,Verdana,sans serif\">
		<span style=\"font-size:20px\">Visualizzazione dati {$this->rowName} $id</span><br /><br />
		";


		foreach ($this->field as $current_field)
		{
			 		$TYPE=explode("(",$current_field->type);//serve per identificare gli ENUM

					switch($TYPE[0])
					{	
						case "password":$data="<em>( informazione codificata )</em>";break;
						case "date":$data=data_europea($row[$current_field->def]);break;
						case "datetime":$data=data_ora_europea($row[$current_field->def]);break;
						default:$data=$row[$current_field->def];
					}
					
					if ($data=="") $data="<em>( informazione non presente )</em>";
						
					$print.="<span style=\"font-weight:bolder;color:#000088\"><em>".ucfirst(str_replace("_"," ",$current_field->def))." : </em></span>".$data."<br /><br />";
						

		} //end foreach
		

		if (isset($div_flag))  //formattazione tabella contenitore
		{
			$print.="</div>";
		}		

		return $print."</div>";
	}	
		

	private function export($type)
	{
		 
		$validField=array();
		
		foreach ($this->field as $current_field)
		{
			if (isset($this->passwordField[$current_field->def])) continue;		
			if (isset($this->photoField[$current_field->def])) continue;					
			if (isset($this->fileField[$current_field->def])) continue;	
			if ($this->hidePrimaryKey && $current_field->def==$this->originalPrimaryKey) continue;	
			
			$list[] = strtoupper(str_replace("_"," ",$current_field->def));
			$validField[] = $current_field ;			
						
		} //end foreach


		
		
		
		$result=mysql_query($this->getFullQuery()) or die ('errore query generazione CSV '.mysql_error());
		
		
		
		
		$data=array();
		$data[0]=$list;
		
		while ($row=mysql_fetch_array($result))
		{
			$data[count($data)]=array();
			
			foreach ($validField as $field)
			{
				
									
				$TYPE=explode("(",$field->type);//serve per identificare gli ENUM

				switch($TYPE[0])
				{	
					case "date":$temp=data_europea($row[$field->def]);break;
					case "datetime":$temp=data_ora_europea($row[$field->def]);break;
					default:$temp=$row[$field->def];
				}
				
				$data[count($data)-1][]=trim(
											strip_tags(str_replace(array("<br />","<br>","<BR />","<BR>","\r","\n","&nbsp;"),array(" "," "," "," "," "," "," "),$temp))
											);			
	
			} //end foreach
			
			

		}
		
		//ob_end_clean(); //l'url col quale si accede a questo codice comprende il get che attiva la modalità ajax e cancella il buffer già nella funzione go()
		
		$filename=$this->originalPrimaryTable."__".date("d_m_Y")."__".date("H_i_s");
		
		$print="";
		
		if ($type=='CSV')
		{	
			header('Content-Type: application/vnd.ms-excel; charset=utf-8');
			header("Content-Disposition: attachment; filename=\"{$filename}.txt\"");		
				
			foreach($data as $row)
			{
				foreach ($row as $key=>$data)
				$row[$key]=html_entity_decode(str_replace('"','""',$row[$key])); //escape di " con " ("")
				
				$print.='"'.implode('","' , $row)."\"\r\n";					
			}
		}
		else
		{
		
			header('Content-Type: application/vnd.ms-excel; charset=utf-8');
			header("Content-Disposition: attachment; filename=\"{$filename}.xml\"");		
		
			// è IMPORTANTE che <?xml parta al primo carattere del file sennò OO non lo vede 
			$print.="<?xml version=\"1.0\" encoding=\"UTF-8\"?>
			
			<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\" >			
				<ss:Worksheet ss:Name=\"".$this->originalPrimaryTable."\">			
					<Table ss:ExpandedColumnCount=\"".count($validField)."\">";
			
					foreach($data as $row)
					{
						$print.='
								<Row>
								';
						
						foreach ($row as $key=>$data)
						{
							if (preg_match("/^\d+((\.|,)\d+)?$/",$row[$key]))
							{
								$datatype='Number';
								$row[$key]=str_replace(',','.',$row[$key]); //la virgola non è interpretata nei numeri.
							}
							else 
							{
								$datatype='String';
								$row[$key]=preg_replace('/(&)(([^a]|$)|a([^m]|$)|am([^p]|$)|amp([^;]|$))/','$1amp;$2',$row[$key]); //per compatib.,sostit. & con &amp;
								//considerare l'uso di <![CDATA[BROWNIES<> & CO.]]> invece di BROWNIES&gt;&lt; &amp; CO.
							}
							$print.="<Cell>
										<Data ss:Type=\"".$datatype."\">".$row[$key]."</Data>
									 </Cell>";							 
						}
						
						$print.='
								</Row>
								';
						
					}
			
			$print.='			
					</Table>
				</ss:Worksheet>
			</Workbook>';
		
		}

		die( $print );
	}	
			
	



	private function managePassword($field)
	{
	
			//unset($_POST[$field."_retyped"]);
			
			$old_password=isset($_POST[$field."_old"])?$_POST[$field."_old"]:"";
			unset($_POST[$field."_old"]);
			
			$new_password=isset($_POST[$field])?$_POST[$field]:"";
			unset($_POST[$field]);
	
			if ($field && $new_password!='')
			{
				if ($_POST['edit_'.$this->originalPrimaryTable]==='1')// fase di modifica dati
				{
					
					$row=mysql_fetch_array(mysql_query("SELECT {$field} FROM {$this->originalPrimaryTable} WHERE $this->originalPrimaryKey=\"".$_POST[$this->originalPrimaryKey]."\""));
					if ( md5($old_password)==$row[$field] || /*password vuota*/($old_password=='' && $row[$field]=='') )
					{
						$_POST[$field]=md5($new_password);
						return true;
					}
					else 
					{
						return false;
					}
				}else $_POST[$field]=md5($new_password); //fase di inserimento dati
			}
			
			return true;
	}
	
	

	
	
}

?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products