/* AJAX db

 Delphi Tquery -hez hasonló adatbázis elérés
        Rekord szintű adatátvitellel, háttér kiszolgálon lévő
        query result munkatáblával.

 Required PHP5, ajaxdb_srv.php háttér kiszolgáló
 Szerző : Fogler Tibor   foglert@robitbt.hu
          2009.01.17
 Licensz: GNU/GPL

 igényelt külső js: ajax.js
 igényelt html tag: <input id="ajaxWait" readonly="readonly" style="...." />

 a Tquery, Tdatabase objektumok csak legfelső szintü globális
 változók lehetnek.

 segéd rutinok:
   $(name), w(txt), setFormValue(ctrl,value), getFormValue(ctrl), 
   setSelected(sel,value), addOption(sel,value,label)
 objektumok, propertyk és metodusok
   Tfield
     name,value,type,displayLabel,displayWidth,visible,align
   Tdatabase
     host,dbName,user,psw,active
     connect(),disConnect(), connected()
   Tquery   
     id,db,
	 sql,  // limit -et, offset -et nem tartalmazhat, ezeket property-ben kell megadni #__ megengedett
     recordCount,eof,bof,active,state,fields,
	 records,bufferTop,BUFFERSIZE,tmpId,recNo
	 open(),close(),first(),last(),next(),previos(),getBookmark(),gotoBookmark(BM),
	 fieldByName(fieldName),execSql(),
	 makeInsertSql(tableName),
	 makeUpdateSql(tableName,idName),
	 makeDeleteSql(tableName,idName)
     beforeOpen(),beforeClose(),afterOpen(),afterScroll()
   }
*/
// -------------- KONFIGURÁCIÓ ------------------------------------
serverUrl = 'ajaxdb_srv.php';  // csak a hivóval azonos domain -en lehet!
dbpre = 'jos_'; // adatbázis táblák előtagja
// -------------- KONFIGURÁCIÓ vége--------------------------------

alLeft = 0;
alRight = 1;

dsClosed = 0;
dsBrowse = 1;
dsInsert = 2;
dsEdit = 3;

ftString = 0;
ftInteger = 1;
ftFloat = 2;
ftdate = 3;
ftBoolean = 4;

lastError = '';

ajax = new Tajax();

function $(name) {
  return document.getElementById(name);
}
function w(txt) {
  document.write(name);
}
function setSelected(sel,value) {
  var i = 0;
  for (i=0; i<sel.options.length; i++) {
    if (sel.options[i].value == value)
	   sel.selectedIndex = i;
  }
}
function addOption(sel,value,label) {
  var y=document.createElement('option');
  y.text=label;
  y.value=value;
  try {
    sel.add(y,null); // standards compliant
  } catch(ex) {
    sel.add(y); // IE only
  }
}
function setFormValue(ctrl,value) {
  if (ctrl.checked != undefined)
     ctrl.checked = ((value=='I') | (value=='X') | (value == 'x'));
  else {
     if (ctrl.value != undefined)
       ctrl.value = value;
     if (ctrl.selectedIndex != undefined)
       setSelected(ctrl,value);
  }	   
}
function getFormValue(ctrl) {
  result = '';
  if (ctrl.value != undefined)
     result = ctrl.value;
  if (ctrl.checked != undefined) {
    if (ctrl.checked)
	   result = ctrl.value;
	else
       result = '';	
  }
  if (ctrl.selectedIndex != undefined)
    result = ctrl.options[ctrl.selectedIndex].value;
  return result;
}
function Tdatabase() {
  this.host = '';
  this.dbName = '';
  this.user = '';
  this.psw = '';
  this.active = false;
  this.connect = function() {this.active = true;}
  this.disConnect = function() {this.active = false;}
  this.connected = function() {return this.active;}
}
function Tfield() {
   this.name = '';
   this.value = '';
   this.type = ftString;
   this.displayLabel = '';
   this.displayWidth = '';
   this.visible = true;
   this.align = alLeft;
}

function Tquery(id,db) {
   // public vars
   this.id = id;
   this.db = db; //Tdatabase
   this.sql = '';  // limit -et, offset -et nem tartalmazhat, ezeket property-ben kell megadni
   this.recordCount = 0;
   this.eof = true;
   this.bof = true;
   this.active = false;
   this.state = dsClosed;
   this.fields = new Array();  // of Tfield
   this.records = new Array(); // of Array of Tfield
   this.bufferTop = -1;        // a records buffer első eleme ezt a rekordot tartalmazza
   this.BUFFERSIZE = 50;       // records max. mérete
   // private vars
   this.tmpId = -1;
   this.recNo = -1;
   this.open = function() {
     this.sql = this.sql.replace(/#__/gi,dbpre);
     this.beforeOpen();
     ajax.setPost('act','open');
     ajax.setPost('sql', this.sql);
     //ajax.setPost('host', this.db.host);
     //ajax.setPost('dbName', this.db.dbName);
     //ajax.setPost('user', this.db.user);
     //ajax.setPost('psw', this.db.psw);
     ajax.asyncron = false;
     ajax.send(serverUrl,ajaxResponse,this.id);
     // responseban: tmpId, lastError, recordCount, recno,  beállítása, fileds array létrehozása feltöltése
     this.state = dsBrowse;
     this.active = true;
     if (this.recNo >= this.recordCount) this.eof = true;
     if (this.recNo <= 0) this.bof = true;
     this.afterScroll();
     this.afterOpen();
   } // open
   this.close = function() {
     this.beforeClose();
     ajax.setPost('act','close' );
     ajax.setPost('id',this.tmpId);
     ajax.asyncron = false;
     ajax.send(serverUrl,ajaxResponse,this.id);
     this.state = dsClosed;
     this.eof = true;
     this.bof = true;
   } // close
   this.execSql = function() {
     this.sql = this.sql.replace(/#__/gi,dbpre);
     ajax.setPost('act','open' );
     ajax.setPost('sql', this.sql);
     //ajax.setPost('host', this.db.host);
     //ajax.setPost('dbName', this.db.dbName);
     //ajax.setPost('user', this.db.user);
     //ajax.setPost('psw', this.db.psw);
     ajax.asyncron = false;
     ajax.send(serverUrl,ajaxResponse,this.id);
     // response -ban lastError beállítása
   } // execSql
   this.first = function() {
     if (this.state == dsBrowse) {
        this.recNo = 0;
        this.getRecord();
        if (this.recNo >= this.recordCount) this.eof = true;
        if (this.recNo <= 0) this.bof = true;
        this.afterScroll();
     }
   }
   this.last = function() {
     if (this.state == dsBrowse) {
        this.recNo = this.recordCount - 1;
        this.getRecord();
        if (this.recNo >= this.recordCount) this.eof = true;
        if (this.recNo <= 0) this.bof = true;
        this.afterScroll();
     }
   }
   this.next = function() {
     if (this.state == dsBrowse) {
        this.recNo = this.recNo + 1;
        if (this.recNo < this.recordCount)
           this.getRecord();
        if (this.recNo >= this.recordCount) this.eof = true;
        if (this.recNo <= 0) this.bof = true;
        this.afterScroll();
     }
   }
   this.previos = function() {
     if (this.state == dsBrowse) {
        this.recNo = this.recNo - 1;
        if (this.recNo >= 0)
           this.getRecord();
        if (this.recNo >= this.recordCount) this.eof = true;
        if (this.recNo <= 0) this.bof = true;
        this.afterScroll();
     }
   }
   this.getBookmark  = function() {
     if (this.state == dsBrowse) {
        return this.recNo;
     } else {
        return -1;
     }
   }
   this.gotoBookmark = function(BM) {
     if (this.state == dsBrowse) {
        if ((BM >= 0) & (BM < this.recordCount)) {
          this.recNo = BM;
          this.getRecord();
          if (this.recNo >= this.recordCount) this.eof = true;
          if (this.recNo <= 0) this.bof = true;
          this.afterScroll();
        }
     }
   }
   // esemény kezelők
   this.beforeOpen = function() {
   }
   this.beforeClose = function() {
   }
   this.afterOpen = function() {
   }
   this.afterScroll = function() {
   }
   this.fieldByName = function(name) {
     var ki = -1;
     for (i=0; i<this.fields.length; i++) {
       if (this.fields.name[i] == name) ki = i;
     }
     if (i >= 0)
       return this.fields[i];
     else
       return false;
   }
   function putToForm() {
      var i = 0;
	  for (i=0; i<this.fields.length; i++) {
	    w = $(this.fields[i].name);
		if (w) {
		  setFormValue(w,this.fields[i].value);
		}
	  }
   }
   function makeInsertSql(tableName) {
      var i = 0;
	  var fieldNames = new Array();
	  var fieldValues = new Array();
	  var result = '';
	  for (i=0; i<this.fields.length; i++) {
	    w = $(this.fields[i].name);
		if (w) {
		  fieldNames.push(this.fields[i].name);
		  fieldValues.push(getFormValue(w));
		}
	  }
	  result = 'insert into '+tableName+' (';
      for (i=0; i<fieldNames.length; i++) {
	    if (i == fieldNames.length - 1)
		  result += fieldNames[i]+') values(';
		else
		  result += fieldNames[i]+',';
	  }	  
      for (i=0; i<fieldValues.length; i++) {
	    if (i == fieldValues.length - 1)
		  result += '"'+fieldValues[i]+'")';
		else
		  result += '"'+fieldValues[i]+'",';
	  }	  
	  return result;
   }
   function makeUpdateSql(tableName,idName) {
      var i = 0;
	  var fieldNames = new Array();
	  var fieldValues = new Array();
	  var result = '';
	  var idValue = '';
	  var w = 0;
	  for (i=0; i<this.fields.length; i++) {
	    w = $(this.fields[i].name);
		if (w) {
		  fieldNames.push(this.fields[i].name);
		  fieldValues.push(getFormValue(w));
		}
	  }
	  result = 'update '+tableName+' set ';
      for (i=0; i<fieldNames.length; i++) {
	    if (i == fieldNames.length - 1)
		  result += fieldNames[i]+'="'+fieldValues[i]+'"';
		else
		  result += fieldNames[i]+'="'+fieldValues[i]+'",';
	  }	  
	  w = $(idName);
	  if (w)
	    idValue = getFormValue(w);
	  else
        idValue = '';	  
	  return result + ' where '+idName+'="'+idValue+'"';
   }
   function makeDeleteSql(tableName,idName) {
	  var idValue = '';
	  var w = 0;
	  w = $(idName);
	  if (w)
	    idValue = getFormValue(w);
	  else
        idValue = '';	  
	  return 'delete from '+tableName+' where '+idName+'="'+idValue+'"';
   }
   // private
   this.getRecord = function() {
      if (this.state = dsBrowse) {
         if ((this.recNo >= 0) & (this.recNo < this.recordCount)) {
           if ((this.recNo >= this.bufferTop) &
               (this.recNo < (this.bufferTop + this.records.length))) {
             this.fields = this.records[this.recNo - this.bufferTop];
           } else {
             ajax.setPost('act','getRecord');
             ajax.setPost('id',this.tmpId);
             ajax.setPost('recNo',this.recNo);
             ajax.setPost('recCount',this.BUFFERSIZE);
             ajax.asyncron = false;
             ajax.send(serverUrl,ajaxResponse,this.id);
           }
         }
      }
   } // getRecord
} // Tquery

function ajaxResponse(HTTPrequest,extrapar) {
  //DBG alert('ajaxdb.ajaxResponse '+HTTPrequest.responseText);
  var q = 0;
  eval('q = '+extrapar+';');

  var xml = HTTPrequest.responseXML;
  var node = xml.firstChild;
  var node2 = xml.firstChild;
  var field = null;
  var j = 0;
  while (node) {
    //DBG alert('node feldolgozo '+node.nodeName);
    if (node.nodeName=='result') {
       // lastError, recordCount kiolvasása
       for (j = 0; j < node.attributes.length; j++) {
         if (node.attributes[j].nodeName == 'id') q.tmpId = node.attributes[j].nodeValue;
         if (node.attributes[j].nodeName == 'recordCount') q.recordCount = node.attributes[j].nodeValue;
         if (node.attributes[j].nodeName == 'status') lastError = node.attributes[j].nodeValue;
         if (node.attributes[j].nodeName == 'recNo') q.recNo = node.attributes[j].nodeValue;
       }
       q.fields = new Array();
       q.records = new Array();
       q.bufferTop = -1;
       node = node.firstChild;  // record tag
       while (node) {
         node2 = node.firstChild;  // field tag
         while (node2) {
            q.bufferTop = q.recNo;
            //DBG alert('mezo feldolgozo '+node.nodeName);
            q.records.push(new Array());
            r = q.records[q.records.length - 1]
            r.push(new Tfield());
            field = r[r.length - 1];
            field.name = node2.nodeName;
            if (node2.firstChild) {
               field.value = node2.firstChild.nodeValue.replace(/_LE_/gi,'<');
			   field.value = field.value.replace(/_GT_/gi,'>');
            } else
               field.value = '';
            node2 = node2.nextSibling;
         }
         node = node.nextSibling;
       }
       q.fields = q.records[0];
    } else if (node.nodeName=='xml') {
       node = node.firstChild;
    } else {
      node = node.nextSibling;
    }
  }
}

