/*
 +-----------------------------------------------------------------------+
 | M@il.go.th Login library                                              |
 |                                                                       |
 | This file is part of the M@il.go.th                                   |
 | Copyright (C) 2005-2008, MICT, - Thailand                             |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Surapun Prasit - RDDI                                         |
 |         Government Information Technology Services(GITS)              |
 +-----------------------------------------------------------------------+
 
 varsion 0.2.5
 $Id: 081029
*/

var layer_objects = new Array();
var KSearch_callback = new Array();

// find a value in a specific array and returns the index
function find_in_array()
  {
  var args = find_in_array.arguments;
  if(!args.length) return -1;

  var haystack = typeof(args[0])=='object' ? args[0] : args.length>1 && typeof(args[1])=='object' ? args[1] : new Array();
  var needle = typeof(args[0])!='object' ? args[0] : args.length>1 && typeof(args[1])!='object' ? args[1] : '';
  var nocase = args.length==3 ? args[2] : false;

  if(!haystack.length) return -1;

  for(var i=0; i<haystack.length; i++)
    if(nocase && haystack[i].toLowerCase()==needle.toLowerCase())
      return i;
    else if(haystack[i]==needle)
      return i;

  return -1;
  }

// get any type of html objects by id/name
function find_object(id, d)
  {
  var n, f, obj, e;
  if(!d) d = document;

  if(d.getElementsByName && (e = d.getElementsByName(id)))
    obj = e[0];
  if(!obj && d.getElementById)
    obj = d.getElementById(id);
  if(!obj && d.all)
    obj = d.all[id];

  if(!obj && d.images.length)
    obj = d.images[id];

  if(!obj && d.forms.length)
    for(f=0; f<d.forms.length; f++)
      {
      if(d.forms[f].name == id)
        obj = d.forms[f];
      else if(d.forms[f].elements[id])
        obj = d.forms[f].elements[id];
      }

  if(!obj && d.layers)
    {
    if(d.layers[id]) obj = d.layers[id];
    for(n=0; !obj && n<d.layers.length; n++)
      obj = find_object(id, d.layers[n].document);
    }

  return obj;
  }

// return the absolute position of an object within the document
function get_object_pos(obj, relative)
  {
  if(typeof(obj)=='string')
    obj = find_object(obj);

  if(!obj) return {x:0, y:0};

  var iX = (bw.layers) ? obj.x : obj.offsetLeft;
  var iY = (bw.layers) ? obj.y : obj.offsetTop;

  if(!relative && (bw.ie || bw.mz))
    {
    var elm = obj.offsetParent;
    while(elm && elm!=null)
      {
      iX += elm.offsetLeft - (elm.parentNode && elm.parentNode.scrollLeft ? elm.parentNode.scrollLeft : 0);
      iY += elm.offsetTop - (elm.parentNode && elm.parentNode.scrollTop ? elm.parentNode.scrollTop : 0);
      elm = elm.offsetParent;
      }
    }

  return {x:iX, y:iY};
  }
function layer(id, attributes)
  {
  this.name = id;
  
  // create a new layer in the current document
  this.create = function(arg)
    {
    var l = (arg.x) ? arg.x : 0;
    var t = (arg.y) ? arg.y : 0;
    var w = arg.width;
    var h = arg.height;
    var z = arg.zindex;
    var vis = arg.vis;
    var parent = arg.parent;
    var obj;

    obj = document.createElement('DIV');

    with(obj)
      {
      id = this.name;
      with(style)
        {
	position = 'absolute';
        visibility = (vis) ? (vis==2) ? 'inherit' : 'visible' : 'hidden';
        left = l+'px';
        top = t+'px';
        if (w)
	  width = w.toString().match(/\%$/) ? w : w+'px';
        if (h)
	  height = h.toString().match(/\%$/) ? h : h+'px';
        if(z) zIndex = z;
	}
      }

    if (parent)
      parent.appendChild(obj);
    else
      document.body.appendChild(obj);

    this.elm = obj;
    };


  // create new layer
  if(attributes!=null)
    {
    this.create(attributes);
    this.name = this.elm.id;
    }
  else  // just refer to the object
    this.elm = document.getElementById(id);


  if(!this.elm)
    return false;


  // ********* layer object properties *********

  this.css = this.elm.style;
  this.event = this.elm;
  this.width = this.elm.offsetWidth;
  this.height = this.elm.offsetHeight;
  this.x = parseInt(this.elm.offsetLeft);
  this.y = parseInt(this.elm.offsetTop);
  this.visible = (this.css.visibility=='visible' || this.css.visibility=='show' || this.css.visibility=='inherit') ? true : false;

  this.id = layer_objects.length;
  this.obj = 'layer_objects['+this.id+']';
  layer_objects[this.id] = this;


  // ********* layer object methods *********


  // move the layer to a specific position
  this.move = function(x, y)
    {
    this.x = x;
    this.y = y;
    this.css.left = Math.round(this.x)+'px';
    this.css.top = Math.round(this.y)+'px';
    }

  // move the layer for a specific step
  this.shift = function(x,y)
    {
    x = Math.round(x*100)/100;
    y = Math.round(y*100)/100;
    this.move(this.x+x, this.y+y);
    }


  // change the layers width and height
  this.resize = function(w,h)
    {
    this.css.width  = w+'px';
    this.css.height = h+'px';
    this.width = w;
    this.height = h;
    }


  // cut the layer (top,width,height,left)
  this.clip = function(t,w,h,l)
    {
    this.css.clip='rect('+t+' '+w+' '+h+' '+l+')';
    this.clip_height = h;
    this.clip_width = w;
    }


  // show or hide the layer
  this.show = function(a)
    {
    if(a==1)
      {
      this.css.visibility = 'visible';
      this.visible = true;
      }
    else if(a==2)
      {
      this.css.visibility = 'inherit';
      this.visible = true;
      }
    else
      {
      this.css.visibility = 'hidden';
      this.visible = false;
      }
    }


  // write new content into a Layer
  this.write = function(cont)
    {
    this.elm.innerHTML = cont;
    }


  // set the given color to the layer background
  this.set_bgcolor = function(c)
    {
    if(!c || c=='#')
      c = 'transparent';

    this.css.backgroundColor = c;
    }


  // set the opacity of a layer to the given ammount (in %)
  this.set_opacity = function(v)
    {
    if(!bw.opacity)
      return;

    var op = v<=1 ? Math.round(v*100) : parseInt(v);

    if(bw.ie)
      this.css.filter = 'alpha(opacity:'+op+')';
    else if(bw.safari)
      {
      this.css.opacity = op/100;
      this.css.KhtmlOpacity = op/100;
      }
    else if(bw.mz)
      this.css.MozOpacity = op/100;
    }
  }
  /*********************************************************/
  /*********     keyboard live-search methods      *********/
  /*********************************************************/
var SHIFT_KEY = true;
var CTRL_KEY = true;

function KSearch(){
  this.env = new Array();
	

  this.add_env = function(name,obj)
  {
    this.env[name] = obj;
  };
  /**
   *  returns the event key code
   **/
  this.get_keycode = function(e)
  {
    e = e || window.event;
      return e && e.keyCode ? e.keyCode : (e && e.which ? e.which : 0);
  };
 /**
  * Prevent event propagation and bubbeling
  **/
  this.cancel = function(evt)
  {
    var e = evt ? evt : window.event;
    if (e.preventDefault)
      e.preventDefault();
    if (e.stopPropagation)
      e.stopPropagation();
    e.cancelBubble = true;
    e.returnValue = false;
    return false;
  };

  this.get_modifier = function(e)
  {
    var opcode = 0;
    e = e || window.event;

    if (bw.mac && e)
    {
       opcode += (e.metaKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
       return opcode;    
    }
    if (e)
    {
       opcode += (e.ctrlKey && CONTROL_KEY) + (e.shiftKey && SHIFT_KEY);
      return opcode;
    }
  };

  this.init_address_input_events = function(obj)
  {
		KSearch_callback[obj.id] = this;
    var handler = function(e) { KSearch_callback[this.id].ksearch_keypress(e,this); };
    var handler2 = function(e) { KSearch_callback[this.id].ksearch_blur(e,this); };
		
		this.env.object = obj;
    
    if (obj.addEventListener)
    {
			var inp_event;
			if( bw.safari )  inp_event = 'keydown';
			else if( bw.mz ) inp_event = 'keyup';
			else             inp_event = 'keypress';
			
      obj.addEventListener(inp_event, handler, false);
      obj.addEventListener('blur', handler2, false);
    }
    else
    {
      obj.onkeydown = handler;
      obj.onblur = handler2;
    }

    obj.setAttribute('autocomplete', 'off');       
  };

  this.get_caret_pos = function(obj)
  {
    if (typeof(obj.selectionEnd)!='undefined')
       return obj.selectionEnd;

    else if (document.selection && document.selection.createRange)
    {
       var range = document.selection.createRange();
       if (range.parentElement()!=obj)
          return 0;

       var gm = range.duplicate();
       if (obj.tagName=='TEXTAREA')
          gm.moveToElementText(obj);
       else
          gm.expand('textedit');
    
       gm.setEndPoint('EndToStart', range);
       var p = gm.text.length;
       return p<=obj.value.length ? p : -1;
    }
    else
      return obj.value.length;
  };
  
	this.highlight_item = function(dir){
        highlight = document.getElementById('rcmksearchSelected');
        if (!highlight)
          highlight = this.ksearch_pane.ul.firstChild;
        
        switch( dir ){
					case 1 : next = highlight.previousSibling; break;
					case 0 : next = highlight.nextSibling; break;
					case -1 :
					default : next = this.mOverItem; break;
				}
        
				if (highlight && next)
          {
          highlight.removeAttribute('id');
          this.set_classname(highlight, 'selected', false);
          }
        if (next)
          {
          next.setAttribute('id', 'rcmksearchSelected');
          this.set_classname(next, 'selected', true);
          this.ksearch_selected = next._rcm_id;
          }
	}
	
  // handler for keyboard events on address-fields
  this.ksearch_keypress = function(e,obj)
  {
    if (typeof(this.env.listItem)!='object' || !this.env.listItem.length)
      return true;
    if (this.ksearch_timer)
      clearTimeout(this.ksearch_timer);

    var highlight;
    var key = this.get_keycode(e);
    var mod = this.get_modifier(e);
    
    if( this.env.separator!=null && this.env.separator!=''){
			if (this.env.object.value.match(this.env.separator.char.value) == null && 
					!( key == this.env.separator.char.key && mod == this.env.separator.char.mod ) )
				return true;
		}

    this.ksearch_input = obj;
    switch (key)
      {
      case 38:  // key up
      case 40:  // key down
        if (!this.ksearch_pane)
          break;
          
        var dir = key==38 ? 1 : 0;
				this.highlight_item(dir);
				return this.cancel(e);
      case 9:  // tab
        if(mod == SHIFT_KEY)
          break;

      case 13:  // enter     
        if (this.ksearch_selected===null || !this.ksearch_input || !this.ksearch_value)
          break;

        // insert selected address and hide ksearch pane
        this.insert_listItem(this.ksearch_selected);
        this.ksearch_hide();

        return this.cancel(e);

      case 27:  // escape
        this.ksearch_hide();
        break;

      }

    // start timer
    this.ksearch_timer = window.setTimeout( "KSearch_callback['"+obj.id+"'].ksearch_get_results()" , 200);
    
    return true;
  };


  this.insert_listItem = function(id)
  {
    if (!this.env.listItem[id] || !this.ksearch_input)
      return;
    
    // get cursor pos
    var inp_value = this.ksearch_input.value.toLowerCase();
    var cpos = this.get_caret_pos(this.ksearch_input);
    var p = inp_value.lastIndexOf(this.ksearch_value, cpos);
    
    // replace search string with full address
    var pre = this.ksearch_input.value.substring(0, p);
    var end = this.ksearch_input.value.substring(p+this.ksearch_value.length, this.ksearch_input.value.length);
    var insert  = this.env.listItem[id].label;
    this.ksearch_input.value = pre + insert + end;
    
    // set caret to insert pos
    cpos = p+insert.length;
    if (this.ksearch_input.setSelectionRange)
      this.ksearch_input.setSelectionRange(cpos, cpos);
		eval(this.env.onchange+'(this.env.listItem[id]);')
  };

  // address search processor
  this.ksearch_get_results = function()
  {
    var inp_value = this.ksearch_input ? this.ksearch_input.value : null;
    if (inp_value===null)
      return;

    // get string from current cursor pos to last comma
    var cpos = this.get_caret_pos(this.ksearch_input);
    var p = -1;
    if( this.env.separator!=null && this.env.separator!='')
      inp_value.lastIndexOf(this.env.separator.value, cpos-1);
    var q = inp_value.substring(p+1, cpos);

    // trim query string
    q = q.replace(/(^\s+|\s+$)/g, '').toLowerCase();

    if ( !q.length || q==this.ksearch_value ){
      if (!q.length && this.ksearch_pane && this.ksearch_pane.visible)
        this.ksearch_pane.show(0);

      return false;
    }

    this.ksearch_value = q;
    
    // start searching the contact list
    var a_results = new Array();
    var a_result_ids = new Array();
    var c=0;

/*	var _default = new jscookie();
	if( this.env._default != null && this.env._default.cookie != null && this.env._default.cookie != '' ) 
    _default = _default.read(this.env.default.cookie);
	else
		_default = null;
		
  if( _default != null ){
      a_results[c] = _default;
	  this.env.listItem.cook = _default;
	  a_result_ids[c++] = 'cook';
	}
	else*/ _default = "";

	for (var i=0; i<this.env.listItem.length; i++)
    {
      if ( ( q=="" || this.env.listItem[i].label.toLowerCase().match(q)!=null ) && this.env.listItem[i] != _default )
      {
        a_results[c] = this.env.listItem[i].label;
        a_result_ids[c++] = i;
        
        if (c==15)  // limit search results
          break;
      }
    }

    // display search results
    if (c && a_results.length)
      {
      var p, ul, li;
      
      // create results pane if not present
      if (!this.ksearch_pane)
      {
        ul = document.createElement('UL');
        this.ksearch_pane = new layer('rcmKSearchpane_'+this.ksearch_input.id, {vis:0, zindex:30000});
        this.ksearch_pane.elm.appendChild(ul);
        this.ksearch_pane.ul = ul;
      }
      else
        ul = this.ksearch_pane.ul;

      // remove all search results
      ul.innerHTML = '';
      
			eval("var onLiMouseOver = function(){ KSearch_callback['"+this.ksearch_input.id+"'].mOverItem = this; KSearch_callback['"+this.ksearch_input.id+"'].highlight_item(-1); }");
			eval("var onLiClick = function(){ var ks = KSearch_callback['"+this.ksearch_input.id+"']; if (ks.ksearch_selected===null || !ks.ksearch_input || !ks.ksearch_value) return;  ks.insert_listItem(ks.ksearch_selected); ks.ksearch_hide(); }");
				
      // add each result line to list
      for (i=0; i<a_results.length; i++)
      {
        li = document.createElement('LI');
        li.innerHTML = a_results[i].replace(/</, '&lt;').replace(/>/, '&gt;');
        li._rcm_id = a_result_ids[i];
				li.className = 'ksearch';
				li.ownerKsearch = this;
				li.onmouseover = onLiMouseOver;
				li.onclicked = function(){ 
					alert("clicked"); 
					};//onLiClick;
        ul.appendChild(li);
      }

      // check if last selected item is still in result list
      if (this.ksearch_selected!==null)
      {
        p = find_in_array(this.ksearch_selected, a_result_ids);
        if (p>=0 && ul.childNodes)
        {
          ul.childNodes[p].setAttribute('id', 'rcmksearchSelected');
          this.set_classname(ul.childNodes[p], 'selected', true);
        }
        else
          this.ksearch_selected = null;
      }
      
      // if no item selected, select the first one
      if (this.ksearch_selected===null)
      {
        ul.firstChild.setAttribute('id', 'rcmksearchSelected');
        this.set_classname(ul.firstChild, 'selected', true);
        this.ksearch_selected = a_result_ids[0];
      }

      // move the results pane right under the input box and make it visible
      var pos = get_object_pos(this.ksearch_input);
      this.ksearch_pane.move(pos.x, pos.y+this.ksearch_input.offsetHeight);
      this.ksearch_pane.show(1); 
    }
    // hide results pane
    else
      this.ksearch_hide();
  };


  // set/unset a specific class name
  this.set_classname = function(obj, classname, set)
    {
    var reg = new RegExp('\s*'+classname, 'i');
    if (!set && obj.className.match(reg))
      obj.className = obj.className.replace(reg, '');
    else if (set && !obj.className.match(reg))
      obj.className += ' '+classname;
    };

  this.ksearch_blur = function(e, obj)
  {
    if (this.ksearch_timer)
      clearTimeout(this.ksearch_timer);

    this.ksearch_value = '';      
    
    this.ksearch_hide();
  };


  this.ksearch_hide = function()
  {
    this.ksearch_selected = null;
    
    if (this.ksearch_pane)
      this.ksearch_pane.show(0);    
  };
}
