var Smart = {
  version : "0.5",
  emptyFunction : function(){},
  isInitialize : false,
  init : function(){
      /*****
      Patch for IE, because he HTMLElement are not 
      considered as an javascript object. What 
      Gecko's browser does
      *****/
    if (!this.isInitialize){
      if(document.all){
        extend("form");
        extend("input");
        extend("textarea");
        extend("select");
      }
  
      extendWith("form", SmartForm);
      extendWith("input", SmartField);
      extendWith("textarea", SmartField);
      extendWith("select", SmartField);
    }
    
    this.isInitialize = true;
    
    function extend(tag){
      var tags = document.getElementsByTagName(tag);
      if (tags.length > 0 && !tags[0].extend){
        for (var i = 0; i < tags.length; i++){
          tags[i].extend = function(object){
            for (property in object) {
              this[property] = object[property];
            }
          }
        }
      }
    }
    
    function extendWith(tag, object){
      var forms = document.getElementsByTagName(tag);  
      for(var index = 0; index < forms.length; index++){
        forms[index].extend(object);
      }
    }
  }
}

function addEvent(obj, evType, fn, useCapture){
	if (obj.addEventListener) {
		obj.addEventListener(evType, fn, useCapture);
		return true;
	} else if (obj.attachEvent) {
		var r = obj.attachEvent("on"+evType, fn);
		return r;
	} else {
		return false;
	}
}

addEvent(window, "load", Smart.init, true);


var DateCompareToResult = {
	NOT_A_DATE: -1,
	EQUALS : 0,
	LESS_THAN : 1,
	GREATER_THAN : 2
}

Object.extend = function(destination, source) {
  for (property in source) {
    destination[property] = source[property];
  }
  return destination;
}

Object.prototype.extend = function(object) {
  return Object.extend.apply(this, [this, object]);
}

Object.prototype.clone = function (deep) {
  var objectClone = new this.constructor();
  for (var property in this)
    if (!deep)
      objectClone[property] = this[property];
    else if (typeof this[property] == 'object')
      objectClone[property] = this[property].clone(deep);
    else
      objectClone[property] = this[property];
  return objectClone;
}

Date.prototype.compareTo = function(toCompare){
	var result = 0;
	
	if(toCompare.constructor != Date){
		result = -1;
	}
	if (result >= 0){
		if(this < toCompare){ result = 1; }
		else if(this > toCompare) { result = 2 }
		else { result = 0; }
	}
  return result;
}	
	
Date.prototype.toInternationalDateString = function(){
	return this.getFullYear() + "-" + _leadZero(this.getMonth() + 1) + "-" + _leadZero(this.getDate());
	
	function _leadZero(v,length) {
		if (typeof(length) != "number") { length = 2; }
		v = new String(v);

		for (var i = v.length; i < length; i++){
			v = "0" + v;
		}
		return v;
	}
}

Number.prototype.isPositive = function(){
	return (this >= 0) ? true : false;
}
	
Number.prototype.isNegative = function(){
	return (this < 0) ? true : false;
}
	
Function.prototype.bind = function(object) {
  var __method = this;
  return function() {
    __method.apply(object, arguments);
  }
}

String.prototype.isEmail = function(){ return true; }
String.prototype.isZipCode = function(){ return true; }
String.prototype.isPostalCode = function(){ return true; }
String.prototype.isNAS = function(){ return true; }
String.prototype.leadZero = function(len){ return this; }


/****************************
	Smart Framework Objects
*****************************/

var Class = {
  create: function() {
    return function() { 
      this.initialize.apply(this, arguments);
    }
  }
}

var SmartForm = {
  serialize: function(obj){
	o = (obj)?obj.obj:this;
	
	var elements = (obj)?SmartForm.getElements(o):this.getElements();
	
   
    if (elements.length > 0 && !elements[0].serialize){
      if(obj){SmartForm.init(o)}else{this.init()};
    }
    var queryComponents = new Array();
    

    for (var i = 0; i < elements.length; i++) {
      var queryComponent = elements[i].serialize();
      if (queryComponent != ""){
        queryComponents.push(queryComponent);
      }
    }
    
    return queryComponents.join('&');
  },
  
  getElements: function(obj){
    var elements = new Array();
    o=(obj)?obj:this;
   
 	for (tagName in SmartForm.Element.Serializers) {
      var tagElements = o.getElementsByTagName(tagName);
      for (var i = 0; i < tagElements.length; i++){
        elements.push(tagElements[i]);
      }
    }
    return elements;
  },
  
  getFields: function(typeName, name){
    var inputs = this.getElementsByTagName('input');
    
    if (!typeName && !name){ return inputs; }
    
    var matchingInputs = new Array();
    
    for (var i = 0; i < inputs.length; i++){
      var input = inputs[i];
      if((typeName && input.type == typeName) || (name && input.name == name)){
        matchingInputs.push(input);
      }
    }
    return matchingInputs;
  },
  
  disable: function(){
    var elements = this.getElements();
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.blur();
      element.disabled = "true";
    }
  },
  
  enable: function(){
    var elements = this.getElements();
    for (var i = 0; i < elements.length; i++) {
      elements[i].disabled = "";
    }
  },
  
  focusFirstElement: function(){
    var elements = this.getElements();
    if (elements.length > 0 && !elements[0].serialize){
      this.init();
    }
    
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      if (element.type != 'hidden' && !element.disabled) {
        element.activate();
        break;
      }
    }
  },
  
  init: function(obj){
   var elements = (obj)?SmartForm.getElements(o):this.getElements();
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.extend(SmartField);
    }
  }
}

var SmartField = {
  serialize: function(){
    return SmartForm.Element.Serializers[this.tagName.toLowerCase()](this);
  },
  
  clear: function() { 
    this.value = ""; 
  },
  
  activate: function() {
    this.enable();
    this.focus();
    this.select();
  },
  
  disable: function(){
      this.disabled = "true";
  },
  
  enable: function(){
      this.disabled = "";    
  },
  
  selectedValue : function(){
  	if (this.type.toLowerCase() == "select-one"){
  		return this.options[this.selectedIndex].value;
  	}
  	else {
  		var selectedValues = new Array();
  		for (var i = 0; i < this.options.length; i++){
  			var opt = this.options[i];
  			if (opt.selected){
					selectedValues.push(opt.value);
				}
  		}
  		return selectedValues;
  	}
  },
  
  selectedText : function(){
  	if (this.type.toLowerCase() == "select-one"){
  		return this.options[this.selectedIndex].text;
  	}
  	else {
  		var selectedValues = new Array();
  		for (var i = 0; i < this.options.length; i++){
  			var opt = this.options[i];
  			if (opt.selected){
					selectedValues.push(opt.text);
				}
  		}
  		return selectedValues;
  	}
  }
}

SmartForm.Element = new Object();
SmartForm.Element.Serializers = {
  input: function(element) {
    switch (element.type.toLowerCase()) {
      case 'submit':
      case 'hidden':
      case 'password':
      case 'text':
        return SmartForm.Element.Serializers.textarea(element);
      case 'checkbox':  
      case 'radio':
        return SmartForm.Element.Serializers.inputSelector(element);
    }
    return new String("");
  },

  inputSelector: function(element) {
    if (element.checked)
      return (new String("")).concat(encodeURIComponent(element.name), "=", encodeURIComponent(element.value));
  },

  textarea: function(element) {
    return (new String("")).concat(encodeURIComponent(element.name), "=", encodeURIComponent(element.value));
  },

  select: function(element) {
    var value = new String("");
    if (element.type == "select-one") {
      var index = element.selectedIndex;
      if (index >= 0){
        value = element.options[index].value /*|| element.options[index].text*/;
      }
    } else {
      value = new Array();
      for (var i = 0; i < element.length; i++) {
        var opt = element.options[i];
        if (opt.selected) {
          value.push(opt.value/* || opt.text*/);
        }
      }
    }
    return (new String("")).concat(encodeURIComponent(element.name), "=", value);
  }
}

var SmartAjax = {}
SmartAjax.Request = Class.create();
SmartAjax.Request.Events = ["Uninitialized", "Loading", "Loaded", "Interactive", "Complete"];

SmartAjax.Request.prototype = {
    setOptions : function(options){
        this.options = {method : "post", asynchronous : true, parameters : ""}.extend(options || {});
    },
    
    responseIsSuccess: function() {
      return this.xmlHttp.status == undefined
          || this.xmlHttp.status == 0 
          || (this.xmlHttp.status >= 200 && this.xmlHttp.status < 300);
    },
  
    responseIsFailure: function() {
      return !this.responseIsSuccess();
    },
    
    initialize: function(url, options) {
        this.xmlHttp = new XMLHttpRequest();
        this.setOptions(options);
        if (url){ this.request(url); }
      },

    request : function (url){
      var parameters = this.options.parameters || "";
      if (parameters.length > 0) parameters += "&_=";
      
      try{
        if (this.options.method == "get"){
          url += "?" + parameters;
        }          

        this.xmlHttp.open(this.options.method, url, this.options.asynchronous);
        
        if (this.options.asynchronous) {
          this.xmlHttp.onreadystatechange = this.onStateChange.bind(this);
          setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
        }
        
        this.setRequestHeaders();

        var body = this.options.postBody ? this.options.postBody : parameters;
        this.xmlHttp.send(this.options.method == "post" ? body : null);
      }
      catch(ee){}
    },
    
    setRequestHeaders: function() {
      var requestHeaders = [
        {key: "X-Requested-With", value: "XMLHttpRequest"},
        {key: "X-Smart-Version", value : Smart.version}];

      if (this.options.method == "post") {
        requestHeaders.push({key: "Content-type", value: "application/x-www-form-urlencoded"});

        /* Force "Connection: close" for Mozilla browsers to work around
         * a bug where XMLHttpReqeuest sends an incorrect Content-length
         * header. See Mozilla Bugzilla #246651. 
         */
        if (this.xmlHttp.overrideMimeType){
          requestHeaders.push({key:"Connection", value:"close"});
        }
      }

      if (this.options.requestHeaders){
        requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
      } 

      for (var i = 0; i < requestHeaders.length; i++){
        this.xmlHttp.setRequestHeader(requestHeaders[i].key, requestHeaders[i].value);
      }
    },
    
    onStateChange : function (){
      var readyState = this.xmlHttp.readyState;
      if (readyState != 1){
        this.respondToReadyState(this.xmlHttp.readyState);
      }
     },
     
    respondToReadyState : function (readyState){
      var event = SmartAjax.Request.Events[readyState];

      if (event == "Complete"){
        (this.options['on' + this.xmlHttp.status]
         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
         || Smart.emptyFunction)(this.xmlHttp);
      }
    
      (this.options['on' + event] || Smart.emptyFunction)(this.xmlHttp);
      
      /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
      if (event == "Complete"){
        this.xmlHttp.onreadystatechange = Smart.emptyFunction; 
      }
    }
}

var SmartMessage = new Object();
SmartMessage.defaultOptions = {
  messageTimeout : 5000,
  domId : "SmartMessage",
  domIdContent : "SmartMessageContent",
  position : "center",
  adjX : 0,
  adjY : 0,
  posX : 0,
  posY : 0,
  scrollTop:false,
  onError:"center"
}
/* Changed here Added adjX and adjY */
SmartMessage.extend({  
	HTMLElement : null,
  timeout : null,
  display: function(message, options){
  	var displayOptions = SmartMessage.defaultOptions.clone();
    displayOptions.extend(options || {});

    clearTimeout(this.timeout);
    if (this.HTMLElement){
      document.body.removeChild(this.HTMLElement); 
    }

    var container = document.createElement("div");
    var content = document.createElement("div");    
	  container.style.position = "relative";
    container.id = displayOptions.domId;  
    content.style.position = "relative";
    content.id = displayOptions.domIdContent;
    // Pop width speficified here
    if(options.width)
    {
    	content.style.width = options.width + "px";
    }
    content.innerHTML = message;
	  content.style.zIndex = 2;
    container.appendChild(content);      

	  if(content.innerHTML.toLowerCase().indexOf("<error>") != -1){
	  	avoidGoodPopUp = true;
	  }
	  else{
	  	avoidGoodPopUp = false;
	  }
	 	 		
    	this.HTMLElement = document.body.appendChild(container);
	
		getCenter = false;
		getFixed = false;
	
		if (displayOptions.position == "center" && !avoidGoodPopUp){
			getCenter = true;
			cancelScroll = false;
		}
	
	/* Added */
	if(displayOptions.position == "fixed" && !avoidGoodPopUp)
	{
		getFixed = true;
		cancelScroll = false;
	}
	
	if (displayOptions.onError == "center" && avoidGoodPopUp){
		
		getCenter = true;
		cancelScroll = true;
	}
	
	/* Added */
	if(displayOptions.onError == "fixed" && avoidGoodPopUp)
	{
		getFixed = true;
		cancelScroll = false;
	}

	if(getCenter)
	{
		this.HTMLElement.style.position = "absolute";
		/* Changed here Added displayOptions.adjX and displayOptions.adjY */
		this.HTMLElement.style.left = ((document.body.clientWidth - this.HTMLElement.offsetWidth) / 2) + displayOptions.adjX + "px";
		this.HTMLElement.style.top = (document.body.scrollTop + (document.body.clientHeight / 2) - (this.HTMLElement.offsetHeight /2)) + displayOptions.adjY + "px";
	}
	
	if(getFixed)
	{
		this.HTMLElement.style.position = "absolute";
		this.HTMLElement.style.zIndex = 3000;
		this.HTMLElement.style.left = displayOptions.posX + "px";
		this.HTMLElement.style.top = displayOptions.posY + "px";
	}
	
	if(displayOptions.scrollTop&&!cancelScroll)
	{
		document.body.scrollTop = 0;
	}	
	
    if (displayOptions.messageTimeout > 0){
      this.timeout = setTimeout("SmartMessage.hide()", displayOptions.messageTimeout);
    }
      
      /****************************************
      	Patch for Internet Explorer;
      	He display html SELECT in front of 
      	a div, to avoid that just put an iframe
      	behind the DIV.
      *****************************************/
      if (document.all){ 
      	var iframe = document.createElement("iframe");
      	  iframe.style.position = "absolute";
      	  iframe.src = "/blank.html";
	      iframe.style.top = 0;
	      iframe.style.left = 0;
	      iframe.style.zIndex = 1;
	      iframe.style.width = content.offsetWidth + "px";
	      iframe.style.height = content.offsetHeight + "px"; 
      	this.HTMLElement.appendChild(iframe)
      }
      
  },

  hide : function(){
    clearTimeout(this.timeout);
    if(this.HTMLElement){      
      document.body.removeChild(this.HTMLElement); 
      this.HTMLElement = null; 
    }
  }
})

/*************************************************
	Creation of cross-browser object
	 - window.showModalDialog for Gecko
	 - XMLHttpRequest object for Internet Explorer
**************************************************/

if (!Array.prototype.push) {
  Array.prototype.push = function() {
		var startLength = this.length;
		for (var i = 0; i < arguments.length; i++)
      this[startLength + i] = arguments[i];
	  return this.length;
  }
}

if(typeof(XMLHttpRequest) == 'undefined'){
 	var XMLHttpRequest = function(){
		var request = null;
		try{
			request = new ActiveXObject('Msxml2.XMLHTTP');
		}
		catch(e){
			try{
				request = new ActiveXObject('Microsoft.XMLHTTP');
			} catch(ee){}
		}
		return request;
	}
}

if (typeof(window.showModalDialog) == "undefined"){
	window.showModalDialog = function(url,arguments,features){
		return window.open(url, arguments, toOpenParam(features));
		function toOpenParam(features){
			var args = features.split(";");
			var optName = new Array();
			optName["dialogWidth"] = "width";
			optName["dialogHeight"] = "height";
			optName["dialogTop"] = "top";
			optName["dialogLeft"] = "left";
			optName["status"] = "status";
			optName["resizable"] = "resizable";
			optName["scroll"] = "scrollbars";
			var openParam = new Array();
			for(var i = 0; i < args.length; i++){
				var arg = args[i].split(":");
				if (optName[arg[0]] != "undefined"){
					openParam[i] = optName[arg[0]].concat("=", arg[1]);
				}
			}			
			openParam[openParam.length] = "modal=yes";
			return openParam.join(",");
		}
	}
}

window.location.getParameter = function(key){
	var search = this.search.substring(1,this.search.length);
	var params = search.split("&");
	var value = new String("");
	for (var i = 0; i < params.length; i++){
		var param = params[i].split("=");
		if (param[0].toLowerCase() == key.toLowerCase()){
			value = param[1];
			break;
		}
	}
	return value;
}

window.location.searchWithoutKeys = function(keys){
	var search = this.search.substring(1,this.search.length);
	var params = search.split("&");
	var result = new Array();
	for(var i = 0; i < params.length; i++){
			var paramFound = false;

			for(var j = 0; j < keys.length; j++){
				if (params[i].search(keys[j])){
					paramFound = true;
					break;
				}
			}
			
			if(paramFound){
				result.push(params[i]);	
			}
	}	
	
	return "?" + result.join("&");
}

document.getFirstParent = function(object,tagName){
	var parentElement = object;
	do{
		parentElement = parentElement.parentNode;
	}while(tagName && parentElement.tagName.toLowerCase() != tagName.toLowerCase())
	
	return parentElement;
}
