/*-------------------------------------------------------
suggest.js
depends on prototype.js(http://prototype.conio.net/)
@reversion  V1.0.1(Modified 2007/12/10)
@version  V1.0(Modified 2007/04/20)
--------------------------------------------------------*/
/*
--------------------------------------------------------
suggest.js - Input Suggest
Version 1.4.0 (Update 2006/05/11)

- onozaty (http://www.enjoyxstudy.com)

Released under the Creative Commons License(Attribution 2.1 Japan):
 http://creativecommons.org/licenses/by/2.1/jp/

depends on prototype.js(http://prototype.conio.net/)

For details, see the web site:
 http://www.enjoyxstudy.com/javascript/suggest/

--------------------------------------------------------
*/
Util.createSuggest = function  ( id ,input, syncId, recommendArea, maskingArea, candidateList) {
	   if(this.instances == null) this.instances = new Array(); 	   
	   var instance = null;
  	   for (var i = 0; i < this.instances.length ; i++) {
  		    if( this.instances[i].id == id ){
  			return this.instances[i];
  			}
  		}
  		instance = new Util.Suggest(id ,input, syncId, recommendArea, maskingArea, candidateList);
  		this.instances.push(instance);	 
    },

Util.Suggest.prototype = {
  // options
  interval  : 1000,
  dispMax   : 5,
  minLength : 3,
  ignoreCase: true,
  // for English Site
  ignoreDup : true,
  highlight : true,
  color		: 'red',

  initialize: function ( id, input, syncId, recommendArea, maskingArea, candidateList) {
    this.id            = id;
    this.syncId	       = syncId; 
    this.syncObj	   = null; 
    // set parameter
    this.input         = $(input);
    this.maskingArea   = $(maskingArea);
    this.recommendArea = $(recommendArea);
    this.candidateList = candidateList;
    // recommendation list
    this.recommendList      = null;
    this.recommendIndexList = null;
    this.cursorPosition     = null;
    this.recommendAttrList  = null;
    // Event Timer
    this.timer              = null;
    // variable for backup! 
    this.inputValueBackup   = null;
    this.oldText            = null; 
    // this.getInputText();
	this.selectedText       = null;
	// item Tagname 
    this.itemTag		    = 'DIV';
    // regist event
	this.bindEvent();
	// refresh area
    this.clearRecommendArea();
  },
  nan:function(){
   	this.recommendList = null;
   	this.recommendIndexList = null;
  },
  bindEvent: function(){
    Event.observe(this.input, 'focus',    this.checker.bindAsEventListener(this),   false);
    Event.observe(this.input, 'blur',     this.blur.bindAsEventListener(this),      false);
   	if(window.opera){
   	    //Failed!! Why?
   		//Event.observe(this.input, 'keydown', this.keyevent.bindAsEventListener(this),  false);
   		Event._observeAndCache(this.input, 'keypress', this.keyevent.bindAsEventListener(this), false);
   	}else{
   		Event.observe(this.input, 'keypress', this.keyevent.bindAsEventListener(this),  false);
   	}
  },
  isModified: function(){
     return !(this.getInputText() == this.oldText);
  },
  setTimer:function (){
   	this.timer = setTimeout(this.checker.bind(this), this.interval);
  },
  checker: function() {
    if (this.isModified()) {
      this.backupInputValue();
      this.search();
    }
    if (this.timer) clearTimeout( this.timer );
    this.setTimer();
  },
  stopEvent: function(event){
    Event.stop(event);
  },
  rewindInputValue:function(){
    this.input.value = this.inputValueBackup;
    this.backupInputValue();
  },	
  backupInputValue:function(){
    this.oldText = this.getInputText();
  },
  keyevent: function(event) {
    if (!this.timer) {
      this.setTimer();
    }
    if ( event.keyCode == Event.KEY_UP || event.keyCode == Event.KEY_DOWN) {
      this.stopEvent(event);
      this.moveActiveList(event.keyCode);
      return false;
    } 
    if (this.recommendList) {
    	if (event.keyCode == Event.KEY_RETURN) {
    		this.stopEvent(event);
        	this.clearRecommendArea();
            this.syncInputText();
    	} else if (event.keyCode == Event.KEY_ESC) {
    		this.stopEvent(event);
        	this.clearRecommendArea();
        	this.rewindInputValue();
     	}
    }
  },
  search: function() {
    // clear 
    this.clearRecommendArea();
    // For English Site!!
   	var text = this.getInputText();
    if ( this.isEmpty(text) ) return;

    var patternWord = text.replace( /^(\s+)/g,"")
                          .replace( /(\s+)$/g,"")
                          .replace( /[-\(\)\.\,\\\/\`]/g," ")
                          .replace( /\'/g,"\\'+")
                          .replace( /\s+/g,"[\\s\\w\\-\\(\\)\\,\\.\\']*");

    if (patternWord == null || patternWord =="") return null;
    
    var pattern = null ;
    if (this.ignoreCase) {
      pattern = new RegExp(patternWord,"i");
    } else {
      pattern = new RegExp(patternWord,"m");
    }
    
    var resultList 	= new Array();
    var temp 		= null;

    this.recommendIndexList = new Array();
    this.recommendAttrList = new Array();

    for (var i = 0; i < this.candidateList.length; i++) {
      if ((temp = this.isMatch(this.candidateList[i][2]+this.candidateList[i][3], pattern)) != null) {
   		if(this.candidateList[i][1] == null || this.candidateList[i][1] == ""){
   			temp = '<table border="0" cellapan="0" cellpadding="0"><tr><td width="300">'+temp+'</td></tr></table>'
   		}else {
   			temp = '<td width="60"><img width="58" src="http://img.travel.rakuten.co.jp/image/imgr?no='
   			     + encodeURIComponent(this.candidateList[i][1])
   			     + '"></td><td width="240" valign="top">'
   			     + temp
   			     + '</td>';
   			temp = '<table border="0" cellapan="0" cellpadding="0"><tr>'+ temp;
   			temp = temp+'</tr></table>';
   		}
     	resultList.push(temp);
      	this.recommendIndexList.push(i); 
       	this.recommendAttrList.push(this.candidateList[i][0]);      	
        if ( resultList.length >= this.dispMax) break;
      }
    }
    if (resultList != 0){
      this.createRecommendArea(resultList);
      this.revealMask();
    }
  },
  isEmpty: function(element){
     if( element && element.length >= this.minLength) {
     	 return false;
   	 }
     return true;
  },
  resizeMask: function(){
    this.maskingArea.style.height = this.recommendArea.scrollHeight;
    this.maskingArea.style.width = this.recommendArea.scrollWidth + 1;
  },
  hideMask: function(){
  	this.maskingArea.style.display='none';
  	this.resizeMask();
  },
  revealMask: function(){
  	this.maskingArea.style.display='';
  	this.resizeMask(); 
  },
  clearRecommendArea: function() {
    this.recommendList = null;
    this.recommendArea.innerHTML = '';
    this.recommendArea.style.display = 'none';
   	this.hideMask();
    this.cursorPosition = null;
  },
  isMatch: function( value, pattern) {
    var pos = value.search(pattern);
    if (pos == -1 ) return null;
    if (this.highlight) {
      return value.replace(pattern, this.convertHighlight);
    } else {
      return value;
    }
  },
  convertHighlight:function (match){
  	return '<strong><font color=red>' + match + '</font></strong>';	
  },
  createRecommendArea: function(resultList) {
    this.recommendList = new Array();
    this.inputValueBackup = this.input.value;
	//header < area
	if(this.recommendAttrList != null && this.recommendAttrList[0]=="1" ){
    	var element = document.createElement(this.itemTag);
    	element.style.textAlign="left";
    	element.style.backgroundColor="#7DBA4E";
    	element.innerHTML = "<font size='2' color='#FFFFFF'> Area Infomation </font>";
		this.recommendArea.appendChild(element);
    }
    var headerFlag = false;
    for (var i = 0; i < resultList.length; i++) {
	  //header < hotel
      if(!headerFlag && this.recommendAttrList[i] == "0" ){
    	var element = document.createElement(this.itemTag);
    	element.style.textAlign="left";
    	element.style.backgroundColor="#7DBA4E";
    	element.innerHTML = "<font size='2' color='#FFFFFF'> Hotel Infomation </font>";
		this.recommendArea.appendChild(element);
		headerFlag = true;
      }
      var element = document.createElement(this.itemTag);
      element.style.cursor="pointer";
      element.innerHTML = resultList[i];
      this.recommendArea.appendChild(element);
      if ( this.recommendAttrList[i] == "1" ) {
   	  	Event.observe(element, 'mousedown', new Function('event', 'this.itemClick(event, ' + i + ');').bindAsEventListener(this), false);
   	  } else {
   	  	Event.observe(element, 'mousedown', new Function('event', 'this.displayHotelInfo(event, ' + i + ');').bindAsEventListener(this), false);
   	  }
      Event.observe(element, 'mouseover', new Function('event', 'this.itemOver(event, ' + i + ');').bindAsEventListener(this), false);
      Event.observe(element, 'mouseout' , new Function('event', 'this.itemOut(event, ' + i + ');').bindAsEventListener(this), false);

      this.recommendList.push(element);
    }
    // view all search results
    var element = document.createElement(this.itemTag);
    element.style.textAlign="right";
    element.style.backgroundColor="#7DBA4E";
    element.style.cursor="pointer";
    element.innerHTML = "<font size='2' color='#FFFFFF'> View all search results &gt;&gt&nbsp;</font>";
    this.recommendArea.appendChild(element);
    Event.observe(element, 'mousedown', new Function('event', 'this.searchAll(event, ' + i + ');').bindAsEventListener(this), false);
    this.recommendArea.style.display = 'block';
  },
  searchAll:function(event, index){
	this.rewindInputValue();
	$("keyword_search").submit();
  },
  displayHotelInfo:function(event,index){
   	window.location.href  = "http://web.travel.rakuten.co.jp/portal/my/info_page_e.Eng?f_no=" + encodeURIComponent(this.candidateList[this.recommendIndexList[index]][1]);
  },
  moveActiveList: function(keyCode) {
    if (!this.recommendList || this.recommendList.length == 0){
      return;
    }
    this.unactive();
    if (keyCode == Event.KEY_UP) {
      if (this.cursorPosition == null) {
        this.cursorPosition = this.recommendList.length -1;
      }else{
        this.cursorPosition--;
        if (this.cursorPosition < 0) {
          this.cursorPosition = null;
          this.rewindInputValue();
          return;
        }
      }
    }else{
      if (this.cursorPosition == null) {
        this.cursorPosition = 0;
      }else{
        this.cursorPosition++;
      }
      if (this.cursorPosition >= this.recommendList.length) {
        this.cursorPosition = null;
        this.rewindInputValue();
        return;
      }
    }
    this.active(this.cursorPosition);
  },
  active: function(index) {
    this.activeItem(this.recommendList[index]);
    this.setInputText(this.candidateList[this.recommendIndexList[index]][2]);
    this.oldText = this.getInputText();
    this.input.focus();
  },
  unactive: function() {
    if (this.recommendList != null 
        && this.recommendList.length > 0
        && this.cursorPosition != null) {
      this.unactiveItem(this.recommendList[this.cursorPosition]);
    }
  },
  blur: function(event) {
    this.unactive();
    this.backupInputValue();
    if (this.timer) clearTimeout(this.timer);
    setTimeout(this.clearRecommendArea.bind(this),500);
  },
  itemClick: function(event, index) {
   	this.unactive();
   	this.cursorPosition = index;
   	this.selectedText  = this.candidateList[this.recommendIndexList[index]][2];
   	this.active(index);
   	setTimeout(this.syncInputTextForClick.bind(this),100);
  },
  itemOver: function(event, index) {
    var element = Event.element(event);
    this.overItem(element);
  },
  itemOut: function(event, index) {

    var element = Event.element(event);

    if (!this.recommendList) return;

    if (index == this.cursorPosition) {
      this.activeItem(element);
    }else{
      this.unactiveItem(element);
    }
  },
  activeItem: function(element) {
    element.className = 'active_suggest';
  },
  unactiveItem: function(element) {
    while (element && element.tagName != this.itemTag){
      element  = this.getParentElement(element);
    }
    if (element)  element.className = '';
  },
  overItem: function(element) {
  	while (element && element.tagName != this.itemTag){
      element  = this.getParentElement(element);
    }
    if (element) element.className = 'over';
  },
  getParentElement:function(element){
    if(element){
  	  return element.parentElement;
  	}
  	return null;
  },
  getInputText: function() {
    return this.input.value;
  },
  setInputText: function(text) {
    this.input.value = text;
  },
  syncInputText: function() {
    this.oldText = this.input.value;
	if(this.getSyncObj()){
    	this.syncObj.setInputText(this.getInputText()) ; 
   	 	this.syncObj.backupInputValue() ;
	}
  },
  syncInputTextForClick: function() {
	if(this.getSyncObj()){
    	this.syncObj.setInputText(this.selectedText) ; 
   	 	this.syncObj.backupInputValue() ;
   	 	this.setInputText(this.selectedText) ;
   	 	this.backupInputValue() ;    
	}
  },
  getSyncObj:function(){
  	if(!this.syncObj || this.syncObj.id!=this.syncId){
		this.syncObj = Util.getInstance(this.syncId);
	} 
	return this.syncObj;
  },
  resetText:function(){
    this.input.value = "";
    this.oldText = "";
  },
  isSafari:function(){
  	ua=navigator.userAgent;
	return (ua.indexOf("Safari")!=-1)? true:false;
  }
}