/**
 * お問い合わせJS
 *
 * @author Tsue Shogo
 * @version
 *	1.0.0	2018/06/30(土) 20:31	新規作成
 *	1.1.0	2018/07/19(木) 22:41	クラス分け
 *	1.2.0	2018/07/21(土) 09:09	確認画面対応
 *	1.3.0	2018/07/25(水) 09:51	URL追加
 *	1.4.0	2018/07/25(水) 11:14	show,hide追加
 *	1.5.0	2018/08/22(水) 15:49	disabledはやはり無しにする
 */
(function() {
	//////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * コントローラ
	 *
	 * @var Object
	 */
	var Controller = {
		/**
		 * パラメータ
		 *
		 * @var Object
		 */
		params: {
			// バリデーションの対象となるフォーム
			blurForms: {},
			// バリデーションのエラーが表示中のバリデーショングループ
			errorValiGroups: {}
		},
		/**
		 * イベント
		 *
		 * @var Object
		 */
		events: {
			".toZenkaku": {
				change: "changeToZenkaku"
			},
			".toHankaku": {
				change: "changeToHankaku"
			},
			".toHiragana": {
				change: "changeToHiragana"
			},
			".toKatakana": {
				change: "changeToKatakana"
			},
			".zip2addrBtn": {
				click: "clickZip2AddrBtn"
			},
			".validateForm input,.validateForm select,.validateForm textarea": {
				blur: "blurInputSelectTextarea"
			},
			".validateForm input[type=hidden],.validateForm input[type=checkbox],.validateForm input[type=radio]": {
				change: "blurInputSelectTextarea"
			},
			body: {
				dragover: "dropBody",
				dragleave: "dropBody",
				drop: "dropBody"
			},
			".drop_area": {
				dragover: "dragoverDropArea",
				dragleave: "dragleaveDropArea",
				drop: "dropDropArea"
			},
			".filehide": {
				change: "changeFilehide"
			},
			".submitBtn": {
				click: "clickSubmitBtn"
			},
			".showHide": {
				change: "changeShowHide",
				click: "changeShowHide"
			}
		},
		/**
		 * 初期実行
		 *
		 * @return void
		 */
		init: function() {
			var _this = this;
			// 確認画面リダイレクト
			if ($(".validateForm").data("emptyform")) {
				if (Object.keys(_POST).length === 0) {
					location.href = $(".validateForm").data("emptyform");
					return false;
				}
			}
			// MAP取得
			$.ajax({
				url: "/wp-content/themes/qracian/json/contact_map.json",
				type: "get",
				cache: false,
				dataType: "json",
				success: function(data) {
					Map = data;
					// プルダウン生成
					_this.mapToForm();
					// リクエストデータをフォームに反映する
					_this.requestToForm();
					// 郵便番号処理
					$.getScript("/wp-content/themes/qracian/js/lib/ajaxzip3.js");
					// カレンダー
					$.getScript("/wp-content/themes/qracian/js/lib/jquery.datetimepicker.js", function() {
						$(".datepicker").each(function() {
							$(this).datetimepicker({
								lang: "ja",
								timepicker: false,
								format: "Y/m/d"
							});
						});
					});
				},
				error: function(e) {
					console.log("エラーが発生しました。MAPを読み込めません。", e);
				}
			});
		},
		/**
		 * [event] toZenkakuを変更
		 *
		 * @param object	event
		 * @param object	target
		 */
		changeToZenkaku: function(event, target) {
			$(target).val(Calibrator.toZenkaku($(target).val()));
		},
		/**
		 * [event] toHankakuを変更
		 *
		 * @param object	event
		 * @param object	target
		 */
		changeToHankaku: function(event, target) {
			$(target).val(Calibrator.toHankaku($(target).val()));
		},
		/**
		 * [event] toHiraganaを変更
		 *
		 * @param object	event
		 * @param object	target
		 */
		changeToHiragana: function(event, target) {
			$(target).val(Calibrator.toHiragana($(target).val()));
		},
		/**
		 * [event] toKatakanaを変更
		 *
		 * @param object	event
		 * @param object	target
		 */
		changeToKatakana: function(event, target) {
			$(target).val(Calibrator.toKatakana($(target).val()));
		},
		/**
		 * [event] 住所検索をクリック
		 *
		 * @param object	event
		 * @param object	target
		 */
		clickZip2AddrBtn: function(event, target) {
			var zip1 = $(target).data("zip1");
			var zip2 = $(target).data("zip2");
			var pref = $(target).data("pref");
			var addr = $(target).data("addr");
			var area = $(target).data("area");
			var strt = $(target).data("strt");
			AjaxZip3.zip2addr(zip1, zip2, pref, addr, area, strt);
		},
		/**
		 * [event] フォーム離脱
		 *
		 * @param object	event
		 * @param object	target
		 */
		blurInputSelectTextarea: function(event, target) {
			// 離脱リストに追加
			var name = $(target).attr("name");
			if (name) {
				this.params.blurForms[name] = true;
			}
			// トリミング
			if ($(target).val()) {
				$(target).val(
					$(target)
						.val()
						.trim()
				);
			}
			// バリデーション
			this.validate();
		},
		/**
		 * [event] bodyにドロップ
		 *
		 * @param object	event
		 * @param object	target
		 */
		dropBody: function(event, target) {
			// イベントキャンセル
			event.preventDefault();
		},
		/**
		 * [event] drop_areaドラッグ開始
		 *
		 * @param object	event
		 * @param object	target
		 */
		dragoverDropArea: function(event, target) {
			// イベントキャンセル
			event.preventDefault();
			// class付加
			$(target).addClass("filehover");
		},
		/**
		 * [event] drop_areaドラッグ終了
		 *
		 * @param object	event
		 * @param object	target
		 */
		dragleaveDropArea: function(event, target) {
			// イベントキャンセル
			event.preventDefault();
			// class削除
			$(target).removeClass("filehover");
		},
		/**
		 * [event] drop_areaにドロップ
		 *
		 * @param object	event
		 * @param object	target
		 */
		dropDropArea: function(event, target) {
			// イベントキャンセル
			event.preventDefault();
			// class削除
			$(target).removeClass("filehover");
			// name取得
			var name = $(target).data("name");
			// ファイル取得
			var file = typeof event.originalEvent !== "undefined" && typeof event.originalEvent.dataTransfer !== "undefined" && typeof event.originalEvent.dataTransfer.files !== "undefined" && typeof event.originalEvent.dataTransfer.files[0] !== "undefined" ? event.originalEvent.dataTransfer.files[0] : null;
			// ファイルをフォームにセット
			this.setFile(name, file);
		},
		/**
		 * [event] ファイル選択ボタン
		 *
		 * @param object	event
		 * @param object	target
		 */
		changeFilehide: function(event, target) {
			// name取得
			var name = $(target).attr("name");
			// ファイル取得
			var file = typeof event.target !== "undefined" && typeof event.target.files !== "undefined" && typeof event.target.files[0] !== "undefined" ? event.target.files[0] : null;
			// ファイルをフォームにセット
			this.setFile(name, file);
		},
		/**
		 * [event] showHide変更
		 *
		 * @param object	event
		 * @param object	target
		 */
		changeShowHide: function(event, target) {
			var name = $(target).attr("name");
			this.updateShowHide(name);
		},
		/**
		 * [event] 送信ボタン押下
		 *
		 * @param object	event
		 * @param object	target
		 */
		clickSubmitBtn: function(event, target) {
			// バリデーション
			if (this.validate(true)) {
				// 2重送信不可に
				$(target).prop("disabled", true);
				// 送信先変更
				if ($(target).data("action")) {
					$(".validateForm").attr("action", $(target).data("action"));
				}
				// Ajax通信
				if ($(target).data("send")) {
					var innerHtml = $(target).html();
					$(target).html('<span class="loading"></span>');
					$.ajax({
						url: $(target).data("send"),
						cache: false,
						type: "post",
						dataType: "json",
						data: _POST,
						success: function(data) {
							$(".validateForm").submit();
						},
						error: function(e) {
							alert("通信エラーが発生しました。");
							$(target).prop("disabled", false);
							$(target).html(innerHtml);
							console.log(e);
						}
					});
				} else {
					// 送信
					$(".validateForm").submit();
				}
			} else {
				// エラー
				$(".error:visible").each(function() {
					var pos = $(this)
						.parent()
						.position();
					var marginTop = $(".main").css("margin-top");
					marginTop = marginTop.match("px") ? marginTop.split("px").join("") * 1 : 0;
					var navHeight = $("#nav").height();
					$("body,html").animate(
						{
							scrollTop: pos.top - marginTop - navHeight
						},
						800
					);
					return false;
				});
			}
		},
		/**
		 * ファイルをセットする
		 *
		 * @var string name
		 * @var object file
		 * @return
		 */
		setFile: function(name, file) {
			var _this = this;
			// 初期準備
			var $fileData = $('input[name="' + name + '_file_data"]');
			var $fileName = $('input[name="' + name + '_file_name"]');
			var $fileSize = $('input[name="' + name + '_file_size"]');
			var $fileType = $('input[name="' + name + '_file_type"]');
			var $filePrev = $('[data-preview="' + name + '"]');
			var $fileMesg = $('[data-message="' + name + '"]');
			// 初期実行
			$fileData.val("");
			$fileName.val("");
			$fileSize.val("");
			$fileType.val("");
			$filePrev.html("");
			$fileMesg.html("");
			// ファイル取得失敗時
			if (typeof file !== "object" || file === null) {
				return;
			}
			// ファイルリーダー
			var fileReader = new FileReader();
			// イベント - 開始時
			fileReader.onloadstart = function(e) {
				// メッセージ表示
				$fileMesg.html("読み込み中です。");
			};
			// イベント - ロード時
			fileReader.onprogress = function(e) {
				if (e.lengthComputable) {
					// メッセージ表示
					var percentLoaded = Math.round((e.loaded / e.total) * 100);
					if (percentLoaded < 100) {
						$fileMesg.html("読み込み中です。(" + percentLoaded + "%)");
					}
				}
			};
			// イベント - 終了時
			fileReader.onloadend = function(e) {};
			// イベント - 完了時
			fileReader.onload = function(e) {
				// 画像ファイルの場合はリサイズ処理
				if (file.type && file.type.match(/image/)) {
					$.ajax({
						url: "/form-control/reception/convert/image.json",
						type: "post",
						cache: false,
						dataType: "json",
						data: {
							data_uri: e.target.result,
							name: file.name,
							output: file.name,
							maxLength: 1200
						},
						success: function(data) {
							if (data.result === "success") {
								// フォーム更新
								$fileData.val(data.data_uri).blur();
								$fileName.val(data.name).blur();
								$fileSize.val(data.size).blur();
								$fileType.val(data.type).blur();
								// プレビュー
								_this.fileFormToPreview(name);
							}
						}
					});
				} else {
					// フォーム更新
					$fileData.val(e.target.result).blur();
					$fileName.val(file.name).blur();
					$fileSize.val(file.size).blur();
					$fileType.val(file.type ? file.type : "-").blur();
					// プレビュー
					_this.fileFormToPreview(name);
				}
			};
			// 読み込み開始
			fileReader.readAsDataURL(file);
		},
		/**
		 * プルダウン生成
		 *
		 * @return void
		 */
		mapToForm: function() {
			var _this = this;
			// プルダウン
			$("select.mapSelect").each(function() {
				var mapKey = $(this).data("map");
				var html = '<option value="">選択してください</option>';
				if (typeof Map[mapKey] !== "undefined") {
					Object.keys(Map[mapKey]).forEach(function(id) {
						var name = Map[mapKey][id];
						if (!name.match(/^\*/)) {
							html += '<option value="' + id + '">' + name + "</option>";
						}
					});
				}
				$(this).html(html);
			});
			// ラジオボタン
			$(".mapRadio").each(function() {
				var mapKey = $(this).data("map");
				var formName = $(this).data("name");
				var valigroup = $(this).attr("data-valigroup");
				var valirule = $(this).attr("data-valirule");
				var addClass = $(this).attr("data-class");
				var html = "";
				html += '<input type="hidden" name="' + formName + '" value="" class="radio_default">';
				if (typeof Map[mapKey] !== "undefined") {
					Object.keys(Map[mapKey]).forEach(function(id) {
						var name = Map[mapKey][id];
						if (!name.match(/^\*/)) {
							html += '<div class="radio-unit">';
							html += '<input type="radio" name="' + formName + '" value="' + id + '" class="radio-input ' + (addClass ? addClass : "") + '" id="' + formName + "_radio_input_" + id + '" data-valigroup="' + valigroup + '" data-valirule="' + valirule + '">';
							html += '<label for="' + formName + "_radio_input_" + id + '">' + name + "</label>";
							html += "</div>";
						}
					});
				}
				$(this).html(html);
			});
		},
		/**
		 * 表示・非表示の切り替え
		 *
		 * @param string	name
		 * @return void
		 */
		updateShowHide: function(name) {
			if (name) {
				var $target = $('[name="' + name + '"]:not(.radio_default)');
				var val = null;
				if ($target.attr("type") === "radio" || $target.attr("type") === "checkbox") {
					val = $('[name="' + name + '"]:checked').val();
				} else {
					val = $target.val();
				}
				if (val === null || typeof val === "undefined") {
					val = "";
				}
				// 非表示反映
				$(".hide-" + name + "-all").hide();
				if (val) {
					$(".hide-" + name + "-" + val).hide();
				} else {
					$(".hide-" + name).hide();
				}
				// 表示反映
				$(".show-" + name + "-all").show();
				if (val) {
					$(".show-" + name + "-" + val).show();
				} else {
					$(".show-" + name).show();
				}
			} else {
				var _this = this;
				$(".showHide").each(function() {
					var name = $(this).attr("name");
					_this.updateShowHide(name);
				});
			}
		},
		/**
		 * リクエストデータをフォームに反映する
		 *
		 * @return void
		 */
		requestToForm: function() {
			var _this = this;
			// 1周目
			Object.keys(_POST).forEach(function(key) {
				var val = _POST[key];
				// フォームに反映
				var $target = $('[name="' + key + '"]:not(.radio_default)');
				if ($target.attr("type") === "checkbox" || $target.attr("type") === "radio" || $target.data("radio_hidden") == 1) {
					$target.prop("checked", false);
					$('[name="' + key + '"][value="' + val + '"]').prop("checked", true);
				} else if ($target.attr("type") === "file") {
					// スルー。一旦hiddenにも値を入れる。
				} else {
					// ※確認画面の場合は全てhidden
					$target.val(val);
				}
			});
			// 2周目
			Object.keys(_POST).forEach(function(key) {
				var val = _POST[key];
				// プレビューに反映
				var $target = $('[name="' + key + '"]:not(.radio_default)');
				var type = $target.data("type");
				if (type) {
					// 確認画面の場合
					var $confirm = $('[data-confirm="' + key + '"]');
					switch (type) {
						case "checkbox":
						case "radio":
						case "select":
							var html = Map[$target.data("map")][val];
							$confirm.html(html);
							break;
						case "file":
							_this.fileFormToPreview(key);
							break;
						case "textarea":
							// 改行を付ける
							var html = val;
							$confirm.html(html.split("\n").join("<br>"));
							break;
						default:
							var html = val;
							if ($target.data("calibrator")) {
								html = Calibrator[$target.data("calibrator")](html);
							}
							$confirm.html(html);
					}
					// 表示と非表示
					if (val !== "") {
						$('[data-notempty="' + key + '"]').show();
						$('[data-empty="' + key + '"]').hide();
					} else {
						$('[data-notempty="' + key + '"]').hide();
						$('[data-empty="' + key + '"]').show();
					}
				} else {
					// 確認画面でない場合
					if ($target.attr("type") === "file") {
						_this.fileFormToPreview(key);
					}
				}
			});
			$(window).trigger("requestToForm");
			// 表示・非表示の切り替え
			this.updateShowHide();
		},
		/**
		 * ファイル内容をプレビュー
		 *
		 * @param string	name
		 * @return void
		 */
		fileFormToPreview: function(name) {
			if (typeof name !== "undefined") {
				var $fileData = $('input[name="' + name + '_file_data"]');
				var $fileName = $('input[name="' + name + '_file_name"]');
				var $fileSize = $('input[name="' + name + '_file_size"]');
				var $fileType = $('input[name="' + name + '_file_type"]');
				var $filePrev = $('[data-preview="' + name + '"]');
				var $fileMesg = $('[data-message="' + name + '"]');
				// プレビュー
				var html = "";
				$filePrev.html(html).hide();
				$fileData.trigger("preview");
				if ($fileType.val().match(/image/)) {
					// 画像ファイルの場合
					html = '<img src="' + $fileData.val() + '" class="preview_image">';
					$filePrev.html(html).show();
				} else if ($fileType.val().match(/pdf/)) {
					// PDFファイルの場合
					$.ajax({
						url: "/form-control/reception/convert/pdf.json",
						type: "post",
						cache: false,
						dataType: "json",
						data: {
							data_uri: $fileData.val(),
							name: $fileName.val(),
							output: "preview.jpg"
						},
						success: function(data) {
							if (data.result === "success") {
								html = '<img src="' + data.data_uri + '" class="preview_image"><div class="preview_comment">※PDFの1ページ目のみをプレビューしています。</div>';
								$filePrev.html(html).show();
							}
						}
					});
				}
				// ファイルサイズ
				var fileSize = $fileSize.val();
				var mes = "";
				if (fileSize) {
					var sizeStr = Calibrator.addSubUnit(fileSize, "B");
					if ($fileType.val().match(/pdf/)) {
						mes += '<img src="/wp-content/themes/qracian/images/common/icon_pdf.png" class="icon" style="width: 22px;">';
					}
					mes += $fileName.val();
					mes += " (" + sizeStr + ")";
				}
				$fileMesg.html(mes);
			} else {
				var _this = this;
				$("input[type=file]").each(function() {
					var name = $(this).attr("name");
					_this.fileFormToPreview(name);
				});
			}
		},
		/**
		 * バリデーション
		 *
		 * @param bool forceFlag
		 * @return bool
		 */
		validate: function(forceFlag) {
			var _this = this;
			// 強制的に全てのフォームを対象にする
			if (forceFlag) {
				$(".validateForm input,.validateForm select,.validateForm textarea").each(function() {
					var name = $(this).attr("name");
					if (name) {
						_this.params.blurForms[name] = true;
					}
				});
			}
			// 対象のフォームに対してバリデーションする
			var resultAll = true;
			var messages = {};
			Object.keys(this.params.blurForms).forEach(function(name) {
				// 対象の情報取得
				var $target = $('[name="' + name + '"]:not(.radio_default)');
				var val;
				if ($target.attr("type") === "checkbox" || $target.attr("type") === "radio") {
					val = $('[name="' + name + '"]:checked').val();
				} else {
					val = $target.val();
				}
				if (typeof val === "undefined") {
					val = "";
				}
				var valiGroup = $target.data("valigroup");
				var valiRule = $target.data("valirule");
				if (typeof valiRule === "string" && valiRule !== "") {
					valiRule = valiRule.split("'").join('"');
					valiRule = JSON.parse(valiRule);
				} else {
					valiRule = {};
				}
				// バリデーションでループ
				var resultForm = true;
				Object.keys(valiRule).forEach(function(ruleName) {
					var rule = valiRule[ruleName];
					var resultRule = Checker[ruleName](val, rule);
					if (!resultRule) {
						resultForm = false;
						resultAll = false;
						if (typeof messages[valiGroup] === "undefined") {
							messages[valiGroup] = rule.mes;
						}
					}
				});
			});
			// メッセージの表示
			Object.keys(messages).forEach(function(valiGroup) {
				var message = messages[valiGroup];
				// メッセージターゲット
				var $err = $('.error[data-valigroup="' + valiGroup + '"]');
				$err.html(message);
				if (!$err.is(":visible")) {
					$err.slideDown();
				}
				_this.params.errorValiGroups[valiGroup] = message;
			});
			// メッセージの非表示
			Object.keys(this.params.errorValiGroups).forEach(function(valiGroup) {
				if (typeof messages[valiGroup] === "undefined") {
					var $err = $('.error[data-valigroup="' + valiGroup + '"]');
					$err.slideUp();
				}
			});
			// ボタンのdisabled変更
			//$('.submitBtn').prop('disabled', Object.keys(messages).length > 0);
			console.log(messages);
			return resultAll;
		}
	};
	//////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * チェッカー
	 *
	 * @var object
	 */
	var Checker = {
		/**
		 * 必須チェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		notEmpty: function(val, rule) {
			if (typeof rule.cond !== "undefined") {
				var ret = true;
				Object.keys(rule.cond).forEach(function(name) {
					// nameから対象取得
					var $target = $('[name="' + name + '"]:not(.radio_default)');
					var type = $target.attr("type");
					if (type === "checkbox" || type === "radio") {
						$target = $('[name="' + name + '"]:checked');
					}
					var val = $target.val();
					if (val === null || typeof val === "undefined") {
						val = "";
					}
					if (rule.cond[name] != val) {
						ret = false;
					}
				});
				if (ret) {
					return val !== "";
				} else {
					return true;
				}
			} else {
				if (val === null || typeof val === "undefined") {
					val = "";
				}
				return val !== "";
			}
		},
		/**
		 * 長さチェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		length: function(val, rule) {
			var ret = true;
			if (val === "") {
				return ret;
			}
			var len = val.length;
			if (typeof rule.min !== "undefined") {
				// 最小長さチェック
				if (len < rule.min) {
					ret = false;
				}
			}
			if (typeof rule.max !== "undefined") {
				// 最大長さチェック
				if (len > rule.max) {
					ret = false;
				}
			}
			return ret;
		},
		/**
		 * 数値チェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		between: function(val, rule) {
			var ret = true;
			if (val === "") {
				return ret;
			}
			val = val * 1;
			if (typeof rule.min !== "undefined") {
				// 最小長さチェック
				if (val < rule.min) {
					ret = false;
				}
			}
			if (typeof rule.max !== "undefined") {
				// 最大長さチェック
				if (val > rule.max) {
					ret = false;
				}
			}
			return ret;
		},
		/**
		 * 全角ひらがなチェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		zenHiragana: function(val, rule) {
			var ret = val.match(/^([ぁ-ん]|ー)*$/) ? true : false;
			return ret;
		},
		/**
		 * 全角カタカナチェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		zenKatakana: function(val, rule) {
			if (typeof rule !== "undefined" && typeof rule.allowSpace !== "undefined" && rule.allowSpace) {
				return val.match(/^([ァ-ン]|ー|－|\s)*$/) ? true : false;
			} else {
				return val.match(/^([ァ-ン]|ー|－)*$/) ? true : false;
			}
		},
		/**
		 * 全角チェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		zenkaku: function(val, rule) {
			var ret = val.match(/^([０-９Ａ-ｚぁ-んァ-ン－一-龥ー。、？＋　\n])*$/) ? true : false;
			return ret;
		},
		/**
		 * 半角チェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		hankaku: function(val, rule) {
			var ret = val.match(/^([0-9a-zA-Zｧ-ﾝﾞﾟ\-.\x20\n])*$/) ? true : false;
			return ret;
		},
		/**
		 * 半角英数チェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		hanEisu: function(val, rule) {
			var ret = val.match(/^([0-9a-zA-Z])*$/) ? true : false;
			return ret;
		},
		/**
		 * 半角数チェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		hanSu: function(val, rule) {
			var ret = val.match(/^([0-9\.-])*$/) ? true : false;
			return ret;
		},
		/**
		 * メールアドレスチェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		email: function(val, rule) {
			if (val === "") {
				return true;
			}
			var ret = val.match(/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/) ? true : false;
			return ret;
		},
		/**
		 * URLチェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		url: function(val, rule) {
			if (val === "") {
				return true;
			}
			var ret = val.match(/(https?:\/\/[\w\-\.\/\?\,\#\:\u3000-\u30FE\u4E00-\u9FA0\uFF01-\uFFE3]+)/) ? true : false;
			return ret;
		},
		/**
		 * 日付チェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		date: function(val, rule) {
			var dateVal = date("Y/m/d", strtotime(val));
			var ret = dateVal === val ? true : false;
			return ret;
		},
		/**
		 * 同一チェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		equal: function(val, rule) {
			var ret = val === $('[name="' + rule.name + '"]:not(.radio_default)').val() ? true : false;
			return ret;
		},
		/**
		 * MAPチェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		map: function(val, rule) {
			if (val === "") {
				return true;
			}
			var map = typeof rule.map !== "undefined" && typeof Map[rule.map] !== "undefined" ? Map[rule.map] : {};
			var ret = typeof map[val] !== "undefined" ? true : false;
			return ret;
		},
		/**
		 * ファイルタイプチェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		filetype: function(val, rule) {
			if (val === "") {
				return true;
			}
			var ret = false;
			rule.types.forEach(function(type) {
				if (val.match(type)) {
					ret = true;
				}
			});
			return ret;
		},
		/**
		 * ファイルサイズチェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		filesize: function(val, rule) {
			var ret = val <= rule.limit;
			return ret;
		},
		/**
		 * 過去日付チェック
		 *
		 * @param mixed		val
		 * @param object	rule
		 * @return bool
		 */
		notPast: function(val, rule) {
			if (val === "") {
				return true;
			}
			return strtotime(val) >= strtotime(date("Y-m-d"));
		}
	};
	//////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * 校正
	 *
	 * @var Object
	 */
	var Calibrator = {
		/**
		 * 半角に変換する
		 *
		 * @param string	str
		 * @return string
		 */
		toHankaku: function(str) {
			str = str.replace(/[Ａ-Ｚａ-ｚ０-９]/g, function(s) {
				return String.fromCharCode(s.charCodeAt(0) - 0xfee0);
			});
			str = this.toKatakana(str);
			Object.keys(Map.kana).forEach(function(zenkana) {
				var hankana = Map.kana[zenkana];
				str = str.split(zenkana).join(hankana);
			});
			return str;
		},
		/**
		 * 全角に変換する
		 *
		 * @param string	str
		 * @return string
		 */
		toZenkaku: function(str) {
			str = str.replace(/[A-Za-z0-9]/g, function(s) {
				return String.fromCharCode(s.charCodeAt(0) + 0xfee0);
			});
			Object.keys(Map.kana).forEach(function(zenkana) {
				var hankana = Map.kana[zenkana];
				str = str.split(hankana).join(zenkana);
			});
			return str;
		},
		/**
		 * ひらがなに変換する
		 *
		 * @param string	str
		 * @return string
		 */
		toHiragana: function(str) {
			Object.keys(Map.kana).forEach(function(zenkana) {
				var hankana = Map.kana[zenkana];
				str = str.split(hankana).join(zenkana);
			});
			str = str.replace(/[\u30a1-\u30f6]/g, function(match) {
				var chr = match.charCodeAt(0) - 0x60;
				return String.fromCharCode(chr);
			});
			return str;
		},
		/**
		 * カタカナに変換する
		 *
		 * @param string	str
		 * @return string
		 */
		toKatakana: function(str) {
			Object.keys(Map.kana).forEach(function(zenkana) {
				var hankana = Map.kana[zenkana];
				str = str.split(hankana).join(zenkana);
			});
			str = str.replace(/[\u3041-\u3096]/g, function(match) {
				var chr = match.charCodeAt(0) + 0x60;
				return String.fromCharCode(chr);
			});
			return str;
		},
		/**
		 * 補助単位を付ける
		 *
		 * @param int	num
		 * @param string	unit
		 * @return string
		 */
		addSubUnit: function(num, unit) {
			if (num < 1000) {
				return num + "" + unit;
			} else if (num < 1000000) {
				return Math.round(num / 10) / 100 + "K" + unit;
			} else if (num < 1000000000) {
				return Math.round(num / 10000) / 100 + "M" + unit;
			} else {
				return Math.round(num / 10000000) / 100 + "G" + unit;
			}
		},
		/**
		 * 3桁区切りでカンマを付ける
		 *
		 * @param int	num
		 * @return string
		 */
		numberFormat: function(num) {
			return num.toString().replace(/(\d+?)(?=(?:\d{3})+$)/g, function(x) {
				return x + ",";
			});
		}
	};
	//////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * マップ
	 *
	 * @var Object
	 * @link /wp-content/themes/qracian/json/contact_map.json
	 */
	var Map = {};
	//////////////////////////////////////////////////////////////////////////////////////////
	jQuery(function($) {
		// 初期実行
		Controller.init();
		// イベント登録
		Object.keys(Controller.events).forEach(function(selector) {
			var events = Controller.events[selector];
			Object.keys(events).forEach(function(event) {
				var func = events[event];
				$(document).on(event, selector, function(eve) {
					Controller[func](eve, this);
				});
			});
		});
	});
})();

$(function(){
  var hidefield = $(".contact_form .slide_field");
  hidefield.hide();
  $(".contact_form h3.click_trigger").on('click',function(){
    $(this).next().slideToggle();
		$(this).toggleClass('open');
  });
});