/*
 * Description : Javascript Validation Library
 * Version     : 0.0.17
 * Author      : Le Quoc Viet (vietlq85@gmail.com)
 * License     : BSD
 * Copyright (c) 2007, Le Quoc Viet
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the SimpleIT nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Le Quoc Viet ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Le Quoc Viet BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

var SJ = {};
SJ.version = '0.0.19';
SJ.verHex = '000013';
SJ.imgPath = 'js/';
SJ.validImg = SJ.imgPath + 'good.gif';
SJ.invalidImg = SJ.imgPath + 'bad.gif';
    
SJ.$ = function (id) {
    if(id.length < 1) return null;
    return document.getElementById(id);
}

SJ.addEvent = function ( obj, type, fn )
{
    if ( obj.attachEvent ) {
        obj['e'+type+fn] = fn;
        
        obj[type+fn] = function() {
            obj['e'+type+fn]( window.event );
        }
        
        obj.attachEvent( 'on'+type, obj[type+fn] );
    }
    else {
        obj.addEventListener( type, fn, false );
    }
}

SJ.remEvent = function ( obj, type, fn )
{
    if ( obj.detachEvent ) {
        obj.detachEvent( 'on'+type, obj[type+fn] );
        obj[type+fn] = null;
    }
    else {
        obj.removeEventListener( type, fn, false );
    }
}

SJ.init = function() {
    var img = document.createElement('img');
    img.style.display = 'none';
    img.style.visibility = 'hidden';
    img.id = 'validImg';
    img.src = this.validImg;
    document.body.appendChild(img);
    
    img = document.createElement('img');
    img.style.display = 'none';
    img.style.visibility = 'hidden';
    img.id = 'invalidImg';
    img.src = this.invalidImg;
    document.body.appendChild(img);
};

/**
 * Returns the absolute X and Y positions of an object.
 * @param {HTMLObject} obj HTML Object.
 * @return {Object} Returns an accessor with .x and .y values.
 */
function getXY(obj)
{
  var curleft = 0;
  var curtop = obj.offsetHeight + 5;
  var border;
  if (obj.offsetParent)
  {
    do
    {
      // XXX: If the element is position: relative we have to add borderWidth
      if (getStyle(obj, 'position') == 'relative')
      {
        if (border = _pub.getStyle(obj, 'border-top-width')) curtop += parseInt(border);
        if (border = _pub.getStyle(obj, 'border-left-width')) curleft += parseInt(border);
      }
      curleft += obj.offsetLeft;
      curtop += obj.offsetTop;
    }
    while (obj = obj.offsetParent)
  }
  else if (obj.x)
  {
    curleft += obj.x;
    curtop += obj.y;
  }
  return {'x': curleft, 'y': curtop};
}
/**
 * Returns the specified computed style on an object.
 * @param {HTMLObject} obj HTML Object
 * @param {String} styleProp Property name.
 * @return {Mixed} Computed style on object.
 */
function getStyle(obj, styleProp)
{
    if (obj.currentStyle)
        return obj.currentStyle[styleProp];
    else if (window.getComputedStyle)
        return document.defaultView.getComputedStyle(obj,null).getPropertyValue(styleProp);
    else
        return null;
}

SJ.add = function(inputID, valueRule) {
    var inputObj = SJ.$(inputID);
    var diplayValid;
    var img;
    var inputRule;
    
    if(inputObj == null) return false;
    
    inputRule = SJ.$(inputID + '_valueRule');
    if(inputRule != null) {
        inputRule.parentNode.removeChild(inputRule);
    }
    inputRule = document.createElement('input');
    inputRule.type = 'hidden';
    inputRule.id = inputID + '_valueRule';
    inputRule.value = valueRule;
    inputObj.parentNode.insertBefore(inputRule, inputObj.nextSibling);
    
    diplayValid = SJ.$(inputID + '_VValidate');
    if(diplayValid != null) {
        diplayValid.parentNode.removeChild(diplayValid);
    }
    
    diplayValid = document.createElement('span');
    diplayValid.id = inputID + '_VValidate';
    diplayValid.name = inputID + '_VValidate';
    diplayValid.style.visibility = 'hidden';
    diplayValid.style.position = 'absolute';
    diplayValid.style.width = '16px';
    diplayValid.style.height = '16px';
    //diplayValid.style.marginTop = '0px';
    // http://www.davidcramer.net/code/84/get-offsets-xy-for-an-object-javascript.html
    // http://www.robertnyman.com/js/getStyle.js
    var _xyz_ = 0;
    var _abc_ = 0;
    _xyz_ += parseInt(getStyle(inputObj, 'margin-top'));
    _abc_ += inputObj.offsetHeight;
    _abc_ -= 16;
    _abc_ += parseInt(getStyle(inputObj, 'padding-top'));
    //_abc_ += parseInt(getStyle(inputObj, 'padding-bottom'));
    _abc_ += parseInt(getStyle(inputObj, 'border-top-width'));
    //_abc_ += parseInt(getStyle(inputObj, 'border-bottom-width'));
    //alert('_abc_ = ' + _abc_)
    _abc_ /= 2;
    _xyz_ += _abc_;
    _xyz_ -= 2;
    //alert('_xyz_ = ' + _xyz_)
    diplayValid.style.marginTop = _xyz_ + 'px';
    //diplayValid.style.marginLeft = '-16px';
    //diplayValid.style.marginLeft = parseInt(inputObj.style.marginLeft) + 4 + 'px';
    //diplayValid.style.marginLeft = parseInt(getStyle(inputObj, 'margin-left')) + 4 + 'px';
    diplayValid.style.marginLeft = 4 + 'px';
    
    img = document.createElement('img');
    img.style.width = '16px';
    img.style.height = '16px';
    img.style.border = '0';
    img.style.margin = '0';
    img.style.padding = '0';
    img.src = SJ.$('invalidImg').src;
    while (diplayValid.firstChild) {
        diplayValid.removeChild(diplayValid.firstChild);
    };
    diplayValid.appendChild(img);
    inputObj.parentNode.insertBefore(diplayValid, inputObj.nextSibling);
    
    SJ.addEvent(inputObj, 'change', this.validate);
    SJ.addEvent(inputObj, 'mouseup', this.validate);
    SJ.addEvent(inputObj, 'keyup', this.validate);
    SJ.addEvent(inputObj, 'mouseout', this.validate);
    SJ.addEvent(inputObj, 'mouseover', this.validate);
    SJ.addEvent(inputObj, 'click', this.validate);
    SJ.addEvent(inputObj, 'focus', this.validate);
    SJ.addEvent(inputObj, 'blur', this.validate);
    
    inputObj.focus();
    
    return 0;
};

SJ.validate = function() {
    var validPat;
    var isValid;
    var diplayValid;
    var img;
    var tempID = this.id;
    var valueRule = SJ.$(this.id + '_valueRule').value;
    var temp;
    
    //*
    temp = this.value;
    temp = temp.toString();
    temp = temp.replace(/^\s+|\s+$/g, '');
    
    valueRule = valueRule.replace(/^\s+|\s+$/g, '');
    valueRule = valueRule.toLowerCase();

    isValid = SJ.shortVal(tempID, valueRule);
    
    diplayValid = SJ.$(this.id + '_VValidate');
    img = document.createElement('img');
    
    img.style.width = '16px';
    img.style.height = '16px';
    img.src = (isValid) ? SJ.$('validImg').src : SJ.$('invalidImg').src;
    while (diplayValid.firstChild) {
        diplayValid.removeChild(diplayValid.firstChild);
    };
    diplayValid.appendChild(img);
    
    diplayValid.style.visibility = 'visible';
    //alert('done!');
    
    return 0;
};

SJ.shortVal = function(tempID, _valueRule) {
    var validPat;
    var isValid;
    var diplayValid;
    var img;
    //var tempID = this.id + '_valueRule';
    var valueRule = _valueRule; //SJ.$(this.id + '_valueRule').value;
    var temp;
    var inputObj = SJ.$(tempID);
    
    temp = inputObj.value;
    temp = temp.toString();
    temp = temp.replace(/^\s+|\s+$/g, '');
    
    valueRule = valueRule.replace(/^\s+|\s+$/g, '');
    valueRule = valueRule.toLowerCase();
    
    switch(valueRule) {
        case 'notnull' :
                validPat = /^([\s]+)?([^\s]+)(([\s]+)([^\s]+)){0,}([\s]+)?$/i;
        break;
        
        case 'some_text' :
                validPat = /^([\s]+)?([^\s]{2,})(([\s]+)([^\s]+)){0,}([\s]+)?$/i;
        break;
        
        case 'url' :
                validPat = /(^|[ \t\r\n])((http|https):\/\/(([A-Za-z0-9$_.+!*(),;/?:@&~=-])|%[A-Fa-f0-9]{2}){2,}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*(),;/?:@&~=%-]*))?([A-Za-z0-9$_+!*();/?:~-]))/i;
        break;
        
        case 'email' :
                validPat = /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|biz|info|name|aero|biz|info|jobs|museum)$/i;
        break;
        
        case 'sing_mobile' :
                validPat = /^((9|8)[0-9]{7})$/;
        break;
        
        case 'sing_phone' :
                validPat = /^((6|3|9|8)[0-9]{7})$/;
        break;
        
        default:
                return false;
    }
    
    if(valueRule == 'url') {
        var invalidUrl = '';
        
        invalidUrl = /^http(s?):\/\/www\.([a-z0-9]+)$/i;
        if( invalidUrl.test(temp) ) {
            return false;
        }
        
        invalidUrl = /^http(s?):\/\/([a-z0-9]+)$/i;
        if( invalidUrl.test(temp) ) {
            return false;
        }
    }
    
    isValid = validPat.test(temp);
    
    if(temp.length < 1) isValid = false;
    
    return isValid;
};
