
/*
 todo
 現在フォーカスが当たっているインスタンスを保持しておく >> キーボードでの操作を有効に
 input要素にフォーカスがあったとき、ほかの候補ウィンドウを閉じる必要がある。
*/


/**
 * KeywordSuggestion
 *
 * キーワード検索する際のインクリメント検索の補助
 * @param Element inputelement 入力されるinput要素
 * @author Yoshihiro Saito <saito_yoshihiro@probsc.jp>
 */
 
var KeywordSuggestion = function(inputelement, placeholder) {
	
	var owner = this;
	
	// jQuery必須
	if (!jQuery) {
		alert('このライブラリはjQueryが必須です。');
		return false;
	}
	
	// input要素限定
	if (!inputelement || !inputelement.nodeName || inputelement.nodeName.toLowerCase() != 'input') {
		alert('キーワード候補を出力できるのはinput要素のみです。');
		return false;
	}
	
	if (!placeholder) {
		placeholder = inputelement;
	}
	
	// ブラウザ側の機能を外す
	inputelement.setAttribute('autocomplete', 'off');
	placeholder.setAttribute('autocomplete', 'off');
	if (inputelement.autocomplete) {
		window.console.log('autocompleteプロパティがある');
		inputelement.autocomplete = false;
	} else {
		window.console.log('autocompleteプロパティがない');
	}
	if (placeholder.autocomplete)
		placeholder.autocomplete = false; 
	
	// プロパティの設定
	this.container = $(inputelement);
	this.placeholder = $(placeholder);
	this.suggestionList = [];
	this.suggestionWindow = null;
	this.selectedList = null;
	this.id = KeywordSuggestion.getNextId();
	
	// 初期化
	this.container.keyup(function(eventObj){
		owner.createSuggestionWindow();
		// キーによって処理を分ける
		switch (eventObj.keyCode) {
			// ↑ キー
			case KeywordSuggestion.KEY_UP:
				if (!owner.suggestionWindow)
					KeywordSuggestion.search(owner);
				owner.selectPrev();
				break;
			// ↓ キー
			case KeywordSuggestion.KEY_DOWN:
				if ($('ul.keywords li').length==0) {
					KeywordSuggestion.search(owner);
				} else {
					owner.selectNext();
				}
				break;
			// Enter キー
			case KeywordSuggestion.KEY_ENTER:
				owner.placeholder.val(owner.suggestionList[owner.selectedList]);
				if (owner.selectedList!=null)
					owner.removeSuggestionWindow();
				break;
			// ESCキー
			case KeywordSuggestion.KEY_ESC:
				owner.removeSuggestionWindow();
				break;
			// その他・検索を行い、結果を返す
			default:
				KeywordSuggestion.search(owner);
				break;
		}
	});
	this.container.blur(function(){
		setTimeout(function(){
			owner.removeSuggestionWindow();
		}, 100);
	});
	
	KeywordSuggestion.windows[this.id] = KeywordSuggestion.windows;
};


/**
 * 定数の設定
 */
KeywordSuggestion.KEY_UP    = 38;
KeywordSuggestion.KEY_DOWN  = 40;
KeywordSuggestion.KEY_ENTER = 13;
KeywordSuggestion.KEY_ESC   = 27;

/**
 * クラスプロパティ
 */
KeywordSuggestion.suggestionWindowTopOffset = 7;
KeywordSuggestion.focusWindow = null;
KeywordSuggestion.windows = [];		// インスタンスが作成されたときにこれにリストを入れておく
KeywordSuggestion.sequence = 0;
KeywordSuggestion.searchFunction = function(){return []};


/**
 * 提案キーワードを設定
 * 
 * @param Array keywords 配列
 * @param string remarks 備考
 */
KeywordSuggestion.prototype.setKeywords = function(keywords, remarks) {
	var owner = this;
	this.suggestionList = keywords;
	this.selectedList = null;
	$('li', this.suggestionWindow).remove();
	for (var i=0; i<keywords.length; i++) {
		$('ul', this.suggestionWindow).append('<li><a href="javascript:void(0);">'+keywords[i]+'</a></li>');
	}
	// 備考欄
	if (remarks) {
		if ($('div.remarks', this.suggestionWindow).length)
			$('div.remarks', this.suggestionWindow).text(remarks);
		else
			$('ul', this.suggestionWindow).before($('<div class="remarks">'+remarks+'</div>'));
	} else {
		$('div.remarks', this.suggestionWindow).remove();
	}
	
	// 候補をクリックしたときの挙動
	$('ul li a', this.suggestionWindow).click(function(){
		var clicked = $(this).html();
		// alert(clicked)
		owner.placeholder.val(clicked);
		owner.removeSuggestionWindow();
	});
	// キーワードがない場合には非表示
	if (this.suggestionWindow)
		this.suggestionWindow.css('display', (keywords.length==0)?'none':'block');
};


/**
 * 選択リストを表示
 */
KeywordSuggestion.prototype.createSuggestionWindow = function() {
	if (this.suggestionWindow == null) {
		this.suggestionWindow = $('<div class="suggestion-window"><ul class="keywords"></ul></div>');
		$('body').append(this.suggestionWindow);
		$(this.suggestionWindow).css('width', this.placeholder.css('width'));
		var inputElementPosition = $(this.placeholder).offset();
		var inputElementHeight = Number(this.placeholder.css('height').substr(0, this.placeholder.css('height').indexOf('px')));
		if (this.placeholder.css('height')=='auto') {
			inputElementHeight = 18;
		}
		$(this.suggestionWindow).css('top', (Number(inputElementPosition.top)+inputElementHeight+KeywordSuggestion.suggestionWindowTopOffset)+'px');
		$(this.suggestionWindow).css('left', inputElementPosition.left);
		this.suggestionWindow.css('display', 'block');
	}
};


/**
 * ウィンドウを消去
 */
KeywordSuggestion.prototype.removeSuggestionWindow = function() {
	var owner = this;
	// if (this.suggestionWindow != null) {
	if (this.suggestionWindow && this.suggestionWindow.css('display')=='block') {
		/*
		this.suggestionWindow.slideUp('normal', function(){
			$(this).remove();
			owner.suggestionWindow = null;
		});
		*/
		// $(this.suggestionWindow).remove();
		// this.suggestionWindow = null;
		setTimeout(function(){
			owner.suggestionWindow.hide();
		}, 100);
	}
}


/**
 * キーワード候補リストを選択
 *
 * @param int num リスト番号
 */
KeywordSuggestion.prototype.selectList = function(num) {
	var i = 0;
	$('li a', this.suggestionWindow).each(function(){
		if (i==num) {
			$(this).addClass('active');
		} else {
			$(this).removeClass('active');
		}
		i++;
	});
	/*
	// すべてのスタイルを消去
	$('li a', this.suggestionWindow).removeClass('active');
	// 選択
	if ($('li a', this.suggestionWindow)[num]) {
		$($('li a', this.suggestionWindow)[num]).addClass('active');
	}
	*/
};

KeywordSuggestion.prototype.selectNext = function() {
	if (this.selectedList == null) {
		this.selectedList = 0;
	} else {
		this.selectedList++;
	}
	if (this.selectedList>=this.suggestionList.length)
		this.selectedList = this.suggestionList.length-1;
	this.selectList(this.selectedList);
};


KeywordSuggestion.prototype.selectPrev = function() {
	if (this.selectedList == null) {
		this.selectedList = 0;
	} else {
		this.selectedList--;
	}
	if (this.selectedList < 0)
		this.selectedList = 0;
	this.selectList(this.selectedList);
};


/**
 * 検索〜検索結果取得
 */
KeywordSuggestion.search = function(instance) {
	KeywordSuggestion.searchFunction(instance.container, function(results, remarks){
		instance.setKeywords(results, remarks);
	});
};


/**
 * 検索処理を設定させる
 *
 * @param Function func 検索処理を行う関数
 */
KeywordSuggestion.setSearchFunction = function(func) {
	KeywordSuggestion.searchFunction = func;
};


/**
 * インスタンスのIDを取得
 *
 * @return int
 */
KeywordSuggestion.getNextId = function() {
	return KeywordSuggestion.sequence++;
};

