var addEvent = (window.addEventListener) ?
   (function(elm, type, event) {
      elm.addEventListener(type, event, false);
   }) : (window.attachEvent) ?
   (function(elm, type, event) {
      elm.attachEvent('on'+type, event);
   }) :
   (function(elm, type, event) {
      elm['on'+type] = event;
   }) ;

var Position = {
   offset: function(elm) {
      var pos = {};
      pos.x = this.getOffset('Left', elm);
      pos.y = this.getOffset('Top', elm);
      return pos;
   },

   getOffset: function(prop, el) {
      if(!el.offsetParent || el.offsetParent.tagName.toLowerCase() == "body")
         return el['offset'+prop];
      else
         return el['offset'+prop]+ this.getOffset(prop, el.offsetParent);
   }
};


var Validator = {
   check: function(field, label, reg, extra) {
      var response;
      var rule = this.rule;
      rule.field = field;
      rule.value = field.value;
      rule.extra = extra;
      if(!reg || !reg.match(/^!/))
         response = rule.input();

      if(reg && !response && rule.value != '') {
         reg = reg.replace(/^!/, '');

         var mode = reg.split(/\s+/);
         for(var i = 0, m; m = mode[i]; i++) {
            m = m.replace(/([\d\-]+)?$/, '');
            response = rule[m](RegExp.$1);
            if(response) break;
         }
      }

      if(response)
      {
         this.baloon.open(field, response.replace('@label@', label));
      }
   },

   submit: function(form) {
      this.allclose(form);
      var btns = new Array;

      for(var i = 0, f; f = form[i]; i++) {
         if(f.onblur)
            f.onblur();
         if(f.type == 'submit')
            btns.push(f);
      }

      for(var i = 0, f, z; f = form[i]; i++) {
         if(f._validbaloon && f._validbaloon.visible()) {
            while(z = btns.shift())
               this.baloon.open(z, this.rule.submit());
            return false;
         }
      }

      return true;
   },
   
   customCheck: function(field, formClientId) {
      if(document.getElementById(formClientId) == null)
         return true;

      var form = document.getElementById(formClientId);
      this.allclose(form);
      var btns = new Array;

      for(var i = 0, f; f = form[i]; i++) {
         if(f.onblur)
            f.onblur();
//         if(f.type == 'submit')
//            btns.push(f);
      }

      for(var i = 0, f; f = form[i]; i++){
         if(f._validbaloon && f._validbaloon.visible()) {
            this.baloon.open(field, this.rule.submit2(), true);
            if(document.getElementById("GrjBaloon"))
                document.getElementById("GrjBaloon").style.display="block";
            return false;
         }
      }
      
      return true;
   },

   submitBaloonClose: function() {
      if(document.getElementById("GrjBaloon"))
         document.getElementById("GrjBaloon").style.display="none";
   },

   allclose: function(form) {
      for(var i = 0, f; f = form[i]; i++)
         if(f._validbaloon) f._validbaloon.close();
   }
};

Validator.baloon = {
   index: 0,

   open: function(field, msg) {
      open(field, msg, false);
   },

   open: function(field, msg, idFlg) {
      if(!field._validbaloon) {
         var obj = new this.element(field);
         obj.create(idFlg);
         field._validbaloon = obj;
         if(field.type == 'radio' || field.type == 'checkbox') {
            for(var i = 0, e; e = field.form[field.name][i]; i++)
               addEvent(e, 'focus', function() { obj.close(); });
         }
      }

      field._validbaloon.show(msg);
   },

   element: function() {
      this.initialize.apply(this, arguments);
   }
};

Validator.baloon.element.prototype = {
   initialize: function(field) {
      this.parent = Validator.baloon;
      this.field = field;
   },

   create: function() {
      create(false);
   },

   create: function(idFlg) {
      var field  = this.field;

      var box = document.createElement('div');
      box.className = 'baloon';

      var offset = Position.offset(field);
      var top  = offset.y - 25;
      var left = offset.x - 20 + field.offsetWidth;
      box.style.top  = top +'px';
      box.style.left = left+'px';

      var self = this;
      addEvent(box, 'click', function() { self.toTop(); });

      var bindClose = function() { self.close(); };
      var link = document.createElement('a');
//      link.appendChild(document.createTextNode('X'));
      link.setAttribute('href', 'javascript:void(0);');
      addEvent(link, 'click', bindClose);
      addEvent(field, 'focus', bindClose);

      var msg = document.createElement('span');
      var div = document.createElement('div');
      if(idFlg)
      {
         div.id="GrjBaloon";
         div.setAttribute("id","GrjBaloon");
      }
      div.appendChild(link);
      div.appendChild(msg);
      box.appendChild(div);

	  var toji = document.createElement('div');
      toji.className = 'toji';
	  box.appendChild(toji);

      document.body.appendChild(box);
      this.box = box;
      this.msg = msg;
   },

   show: function(msg) {
      var field = this.field;
      this.msg.innerHTML  = msg;

      this.box.style.display = '';
      this.toTop();

      if(field.type != 'radio' && field.type != 'checkbox') {
         var colors = new Array('#FF6666', '#FFAAAA', '#FF6666', '#FFAAAA');
         window.setTimeout(function() {
            if(colors.length > 0) {
               field.style.backgroundColor = colors.shift();
               window.setTimeout(arguments.callee, 70);
            }
         }, 10);
      }
   },

   close: function() {
      this.box.style.display = 'none';
      this.field.style.backgroundColor = '';
   },

   visible: function() {
      return (this.box.style.display == '');
   },

   toTop: function() {
      this.box.style.zIndex = ++ this.parent.index;
   }
};

Validator.rule = {
   msg: null,

   submit: function() {
      return this.msg.submit;
   },

   input: function() {
      if(this.field.type == 'radio' || this.field.type == 'checkbox') {
         for(var i = 0, e; e = this.field.form[this.field.name][i]; i++)
            if(e.checked) return;
         return this.msg.noselect;
      } else if(this.value == '')
         return (this.field.type == 'select-one') ? this.msg.noselect : this.msg.noinput;
   },

   mail: function() {
      if(!this.value.match(/^[\x01-\x7F]+@((([-a-z0-9]+\.)*[a-z]+)|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))$/))
         return this.msg.mail;
   },

   equal: function() {
      var val = document.getElementById(this.extra).value;
      if( val && this.value != val )
//      if(this.field.form[this.extra].value && this.value != this.field.form[this.extra].value)
         return this.msg.unequal;
   },

   alphabet: function() {
      if(!this.value.match(/^[a-zA-Z\-\d]+$/))
         return this.msg.alphabet;
   },

   kana: function() {
      for(var i = 0;i < this.value.length;i++) {
         if(this.value.charAt(i) == ' ' || this.value.charAt(i) == '\u3000') continue;
         if(this.value.charAt(i) < '\u30A1' || this.value.charAt(i) > '\u30F6')
            return this.msg.kana;
      }
   },

   hkana: function() {
      var repText = this.value.replace("　","");
      txt = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォャュョッー、。「」゛゜ ";
      for(var i = 0;i < repText.length;i++) {
         if(txt.indexOf(repText.charAt(i),0) >= 0 )
            continue;
         else
            return this.msg.hkana;
      }
   },

   kanaAll: function() {
      for(var i = 0;i < this.value.length;i++) {
         if( (this.value.charAt(i) == ' ' || this.value.charAt(i) == '\u3000' || this.value.charAt(i) == '\u30FC')||	// スペース、全角長音
             (this.value.charAt(i) >= '\u30A1' && this.value.charAt(i) <= '\u30F4')||	// 全角カタカナ
             (this.value.charAt(i) >= '\u3041' && this.value.charAt(i) <= '\u3093')||	// 全角ひらがな
             (this.value.charAt(i) >= '\uFF61' && this.value.charAt(i) <= '\uFF9F') ) continue;	// 半角カタカナ
         return this.msg.kanaAll;
      }
   },
   
   count: function(arg) {
      return this._range(arg, this.value.length, this.msg.count);
   },

   num: function(arg) {
      if(!this.value.match(/^[\d]+$/))
         return this.msg.num.nonumber;

      return this._range(arg, parseInt(this.value), this.msg.num);
   },

   zip: function(arg) {
      if(!this.value.match(/^[0-9０-９]{1,3}[−\-]{0,1}[0-9０-９]{1,4}$/))
         return this.msg.zip.nonumber;
   },

   kugiri: function(arg) {
	lines = this.value.split(/(\-)+\r\n/g);
	if (lines.length > 12) {
		return this.msg.kugiri.too_big;
	}
	for (var i=0; i<lines.length; i++) {
		text = lines[i].split(/\r\n/g);
		for (var j=0; j<text.length; j++) {
			if (text[j].length > 25) {
				return this.msg.kugiri.nonumber;
			}
		}
	}
   },


   numAll: function(arg) {
      if(!this.value.match(/^[\d０-９]+$/))		// 半角、全角数字
         return this.msg.num.nonumberAll;

      return this._range(arg, parseInt(this.value), this.msg.num);
   },

   check: function(arg) {
      var value = 0;
      for(var i = 0, e; e = this.field.form[this.field.name][i]; i++)
         if(e.checked) value += 1;

      return this._range(arg, value, this.msg.check);
   },

   // 生年月日（年）
   birthDateY: function() {
	var year = this._zenToHankakuNum(this.value);
	if(year.length == 4 && (year.charAt(0) == '1' || year.charAt(0) == '2'))
		return;

	return this.msg.BirthDateY;
   },

   _range: function(range, value, msg) {
      if(!range) return;

      var result = '';
      var c = (" "+range).split(/\-/);
      var min = parseInt(c[0]) || 0;
      var max = parseInt(c[1]) || 0;

      if(value != min && /^\d+$/.test(range))
         result = msg.unequal;
      else if(min == 0 && value > max)
         result = msg.too_big;
      else if(max == 0 && value < min)
         result = msg.too_small;
      else if(min > 0 && max > 0 && (value < min || value > max))
         result = msg.outofrange;

      return result.replace(/%1/g, min).replace(/%2/g, max);
   },

	_zenToHankakuNum: function(numText)
	{
		han = "0123456789";
		zen = "０１２３４５６７８９";
		str = "";
		for (i=0; i<numText.length; i++)
		{
			c = numText.charAt(i);
			n = zen.indexOf(c,0);
			if (n >= 0) c = han.charAt(n);
			str += c;
		}
		return str;
	},

   // お名前
   NameKanji: function(arg) {
      return this.msg.NameKanji;
   },

   // フリガナ
   NameKana: function(arg) {
      return this.msg.NameKana;
   },

   // 郵便番号（上3桁）
   Zip1: function(arg) {
      return this.msg.Zip1;
   },

   // 郵便番号（上4桁）
   Zip2: function(arg) {
      return this.msg.Zip1;
   },

   // 地名・番地・番号
   Add3: function(arg) {
      return this.msg.Add3;
   },

   // 建物名・号室など
   Add4: function(arg) {
      return this.msg.Add4;
   },

   // 電話番号
   TelNo: function(arg) {
      return this.msg.TelNo;
   },

   // 携帯電話
   MobileTelNo: function(arg) {
      return this.msg.MobileTelNo;
   },

   // 性別
   Sex: function(arg) {
      return this.msg.Sex;
   },

   // 生年月日（月）
   BirthDateM: function(arg) {
      return this.msg.BirthDateM;
   },

   // 生年月日（日）
   BirthDateD: function(arg) {
      return this.msg.BirthDateD;
   },

   // Fax
   FaxNo: function(arg) {
      return this.msg.FaxNo;
   },

   // PCメールアドレス
   PcMail: function(arg) {
      return this.msg.PcMail;
   },

   // パスワード
   Password: function(arg) {
      return this.msg.Password;
   },

   // パスワード（確認）
   PasswordConfirm: function(arg) {
      return this.msg.PasswordConfirm;
   },

   // 確認ボタン
   submit2: function() {
      return this.msg.Button;
   },

   CreditName: function() {
      if(!this.value.match(/^[a-zA-Z\-\d ]+$/))
         return this.msg.alphabet;
   }
};

Validator.lang = {
   ja: {
      noselect:   '\u5FC5\u9808\u9078\u629E\u9805\u76EE\u3067\u3059',
//      noinput:    '\u5FC5\u9808\u5165\u529B\u9805\u76EE\u3067\u3059',
      noinput:    '@label@\u304C\u5165\u529B\u3055\u308C\u3066\u3044\u307E\u305B\u3093',
      unequal:    '\u5165\u529B\u5185\u5BB9\u304C\u7570\u306A\u3063\u3066\u3044\u307E\u3059',

      submit:     '\u5165\u529B\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059\u3002',
      mail:       '\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306E\u5F62\u5F0F\u306B\u8AA4\u308A\u304C\u3042\u308A\u307E\u3059',
      alphabet:   '\u534A\u89D2\u82F1\u6570\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      kana:       '\u5168\u89D2\u30AB\u30BF\u30AB\u30CA\u3067\u5165\u529B\u3057\u3066\u4E0B\u3055\u3044\u3002',
      hkana:       '\u534A\u89D2\u30AB\u30CA\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      kanaAll:    '\u30AB\u30CA\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',

      count: {
         unequal:    '%1'+'\u6587\u5B57\u3067\u5165\u529B\u3057\u3066\u4E0B\u3055\u3044\u3002',
         too_big:    '%2'+'\u6587\u5B57\u4EE5\u5185\u3067\u5165\u529B\u3057\u3066\u4E0B\u3055\u3044\u3002',
         too_small:  '%1'+'\u6587\u5B57\u4EE5\u4E0A\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
         outofrange: '%1'+'\u304B\u3089'+'%2'+'\u6587\u5B57\u306E\u9593\u3067\u5165\u529B\u3057\u3066\u4E0B\u3055\u3044\u3002'
      },

      num: {
         nonumber:   '\u534A\u89D2\u6570\u5B57\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',	// 半角数字
         nonumberAll: '\u6570\u5B57\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',	// 数字で
         unequal:    '%1'+'\u3068\u5165\u529B\u3057\u3066\u4E0B\u3055\u3044\u3002',
         too_big:    '%2'+'\u4EE5\u4E0B\u306E\u5024\u3092\u5165\u529B\u3057\u3066\u4E0B\u3055\u3044\u3002',
         too_small:  '%1'+'\u4EE5\u4E0A\u306E\u5024\u3092\u5165\u529B\u3057\u3066\u4E0B\u3055\u3044\u3002',
         outofrange: '%1'+'\u304B\u3089'+'%2'+'\u306E\u9593\u3067\u5165\u529B\u3057\u3066\u4E0B\u3055\u3044\u3002'
      },

      zip: {
         nonumber:   '〒番号は正しく入力してください'
      },

      kugiri: {
         nonumber:   '宛先は１行25文字以内で入力してください',
         too_big:   'データが多すぎます'
      },

      check: {
         unequal:    '\u30C1\u30A7\u30C3\u30AF\u306F'+'%1'+'\u500B\u3057\u3066\u4E0B\u3055\u3044\u3002',
         too_big:    '\u30C1\u30A7\u30C3\u30AF\u306F'+'%2'+'\u500B\u307E\u3067\u3067\u3059\u3002',
         too_small:  '\u30C1\u30A7\u30C3\u30AF\u306F'+'%1'+'\u500B\u4EE5\u4E0A\u3057\u3066\u4E0B\u3055\u3044\u3002',
         outofrange: '\u30C1\u30A7\u30C3\u30AF\u306F'+'%1'+'\u500B\u304B\u3089'+'%2'+'\u500B\u307E\u3067\u3067\u3059\u3002'
      },

      NameKanji:     '\u300C\u304A\u540D\u524D\u300D\u3092\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      NameKana:      '\u300C\uFF8C\uFF98\uFF76\uFF9E\uFF85\u300D\u3092\u534A\u89D2\u30AB\u30CA\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      Zip1:          '\u300C\u90F5\u4FBF\u756A\u53F7\uFF08\u4E0A3\u6841\uFF09\u300D\u3092\u534A\u89D2\u6570\u5B57\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      Zip2:          '\u300C\u90F5\u4FBF\u756A\u53F7\uFF08\u4E0B3\u6841\uFF09\u300D\u3092\u534A\u89D2\u6570\u5B57\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      Add3:          '\u300C\u5730\u540D\u30FB\u756A\u5730\u30FB\u756A\u53F7\u300D\u3092\u5165\u529B\u304F\u3060\u3055\u3044\u3000\u4F8B\uFF09\u4E0A\u5927\u5D0E3\uFF0D5\uFF0D8',
      Add4:          '\u300C\u5EFA\u7269\u540D\u30FB\u53F7\u5BA4\u306A\u3069\u300D\u3092\u5165\u529B\u304F\u3060\u3055\u3044\u3000\u4F8B\uFF09\u30A2\u30AF\u30ED\u30B9\u76EE\u9ED2\u30BF\u30EF\u30FC3F',
      TelNo:         '\u300C\u96FB\u8A71\u756A\u53F7\u300D\u3092\u534A\u89D2\u6570\u5B57\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044\u3000\u4F8B\uFF090312345678',
      MobileTelNo:   '\u300C\u643A\u5E2F\u96FB\u8A71\u300D\u3092\u534A\u89D2\u6570\u5B57\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044\u3000\u4F8B\uFF090312345678',
      FaxNo:         '\u300CFAX\u300D\u3092\u534A\u89D2\u6570\u5B57\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044\u3000\u4F8B\uFF090312345678',
      Sex:           '\u300C\u6027\u5225\u300D\u3092\u3054\u9078\u629E\u304F\u3060\u3055\u3044',
      BirthDateY:    '\u897F\u66A6\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      BirthDateM:    '\u300C\u751F\u5E74\u6708\u65E5\uFF08\u6708\uFF09\u300D\u3092\u3054\u9078\u629E\u304F\u3060\u3055\u3044',
      BirthDateD:    '\u300C\u751F\u5E74\u6708\u65E5\uFF08\u65E5\uFF09\u300D\u3092\u3054\u9078\u629E\u304F\u3060\u3055\u3044',
      PcMail:        '\u300CPC\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u300D\u3092\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      PcMailConfirm: '\u300CPC\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u300D\u3092\u518D\u5EA6\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      Password:      '\u300C\u30D1\u30B9\u30EF\u30FC\u30C9\u300D\u3092\u534A\u89D2\u82F1\u65706\u5B57\u4EE5\u4E0A\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      PasswordConfirm:'\u300C\u30D1\u30B9\u30EF\u30FC\u30C9\u300D\u3092\u534A\u89D2\u82F1\u65706\u5B57\u4EE5\u4E0A\u3067\u3054\u5165\u529B\u304F\u3060\u3055\u3044',
      Button:        '\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059\u3002\u5165\u529B\u9805\u76EE\u3092\u3054\u78BA\u8A8D\u304F\u3060\u3055\u3044\u3002'
   }
};

Validator.rule.msg = Validator.lang.ja;



