/**
 * JSONPのクラス
 *
 * 具体的には、引数のURLのJSファイルを読み込む<script>を動的に生成します.
 *
 */

// Constructor -- pass a REST request URL to the constructor
//
function JSONscriptRequest(fullUrl) {
    // REST request path
    this.fullUrl = fullUrl; 
    // Keep IE from caching requests
    this.noCacheIE = '&noCacheIE=' + (new Date()).getTime();
    // Get the DOM location to put the script tag
    this.headLoc = document.getElementsByTagName("head").item(0);
    // Generate a unique script tag id
    this.scriptId = 'JscriptId' + JSONscriptRequest.scriptCounter++;
}

// Static script ID counter
JSONscriptRequest.scriptCounter = 1;

// buildScriptTag method
//
JSONscriptRequest.prototype.buildScriptTag = function () {

    // Create the script tag
    this.scriptObj = document.createElement("script");
    
    // Add script object attributes
    this.scriptObj.setAttribute("type", "text/javascript");
    this.scriptObj.setAttribute("charset", "utf-8");
    this.scriptObj.setAttribute("src", this.fullUrl + this.noCacheIE);
    this.scriptObj.setAttribute("id", this.scriptId);
}
 
// removeScriptTag method
// 
JSONscriptRequest.prototype.removeScriptTag = function () {
    // Destroy the script tag
    this.headLoc.removeChild(this.scriptObj);  
}

// addScriptTag method
//
JSONscriptRequest.prototype.addScriptTag = function () {
    // Create the script tag
    this.headLoc.appendChild(this.scriptObj);
}




















/**
 * タグ検索クラス
 */
 
 /**
 * コンストラクタ - タグ検索を行なうための設定を行います。
 *
 * 例)
 * <script type="text/javascript">
 * <!--
 * var taggyApiConfig = {
 * 	url		:	"http://taggy.jp/user/media/new/jsonp.do",	// JSONP形式の検索結果を返すURL
 * 	encoding:	"UTF-8",									// JSONP形式の検索結果の文字コード
 * 	callback:	"callback",									// CALLBACK関数の名前
 * 	limit	:	"5",										// 検索結果の表示件数
 *  taglimit:	"5",										// 検索結果の1つの記事で表示するタグの上限数
 * 	imgsize	:	"44",										// 検索結果に含まれる画像のサイズ
 *	query	:	"taggysearch_query,"						// 検索するタグを入力するINPUT要素(hiddenでも可)
 * 	target	:	"taggysearch_result_list",					// 検索結果を展開する要素のID
 *  host    :	"taggy.jp"									// サーバー名
 *	me		:	"taggyTagSearch"							// 自身のインスタンスの変数名
 * }
 * -->
 * </script>
 */
function TaggyTagSearch(config) {

	// 設定をインスタンス変数にインスタンス変数にセット
	this.config = config;
	
	// 検索結果を描画する要素をインスタンス変数にインスタンス変数にセット
	this.resultDrawTarget = document.getElementById(config.target);
	
	// 検索するタグを入力するINPUT要素をインスタンス変数にインスタンス変数にセット
	this.queryInput = document.getElementById(config.query);
}

/**
 * JSONP形式のタグ検索結果を返すURLを引数と設定値より構築して、
 * <script>タグを動的に構築します.
 */
TaggyTagSearch.prototype.tagSearch = function(media,query,page,order) {

	// ページを検索タグをインスタンス変数にセット
	if (page == undefined) {
		page = 0;
	}
	this.page = page;
	
	// 検索対象のメディアをインスタンス変数にセット
	this.page = page;
	
	// 検索タグをインスタンス変数にセット
	this.query = query;
	
	// 検索メディアをインスタンス変数にセット
	this.media = media;
	
	// ソート順をインスタンス変数にセット
	this.order = order;

	// URLを検索タグを構築
	var requestURL = this.config.url
		+ '?encoding=' + this.config.encoding 
		+ '&callback=' + this.config.callback
		+ '&limit=' + this.config.limit
		+ '&offset=' + (page * this.config.limit)
		+ '&media=' + media;
	
	if (order) {
		requestURL += '&order=' + encodeURI(order);
	}
	
	// 検索タグをURLに追加
	if (query) {
		requestURL += '&query=' + encodeURI(query);
	}
	
	// referer matching host
	if (this.config.ref) {
		requestURL += '&ref=' + encodeURI(this.config.ref);
	}
	
	// <script>タグをJSONscriptRequestクラスを使って動的に生成する
	jsonRequest = new JSONscriptRequest(requestURL);
	jsonRequest.buildScriptTag();
	jsonRequest.addScriptTag();
}

/**
 * IEかの判定を行ないます.
 */
TaggyTagSearch.prototype.isIE = function() {

	if(document.documentElement.getAttribute("style") == document.documentElement.style) {
		return true;
	}
	return false;
}

/**
 * IEの場合"class"では属性をセット出来ないので分岐する(IE7は未検証)
 */
TaggyTagSearch.prototype.setClassAttribute = function(element,value) {
 	if (this.isIE()) {
		element.setAttribute('className',value);
	} else {
		element.setAttribute('class',value);
	}
}

/**
 * IEの場合"class"では属性をセット出来ないので分岐する(IE7は未検証)
 */
TaggyTagSearch.prototype.setStyleAttribute = function(element,value) {
 	if (this.isIE()) {
		element.style.cssText = value;
	} else {
		element.setAttribute('style',value);
	}
}

/**
 * 検索結果を展開するHTMLタグの子要素をクリアします.
 */
TaggyTagSearch.prototype.clear = function() {
	while (this.resultDrawTarget.childNodes.length) {
		this.resultDrawTarget.removeChild(this.resultDrawTarget.childNodes.item(0));
	}
}

/**
 * 「Now Loading」を描画します. (オーバーライド可)
 */
TaggyTagSearch.prototype.nowLoading = function() {
	var div = document.createElement('div');
	this.setStyleAttribute(div,'loading');
	div.setAttribute('id','loading');
	div.innerText = ' ';
	this.resultDrawTarget.appendChild(div);
}

/**
 * 検索結果がない場合の描画を行ないます.(オーバーライド可)
 */
TaggyTagSearch.prototype.noSearchResult = function() {
	var p = document.createElement('p');
	this.setClassAttribute(p,'noarticle');
	p.appendChild(document.createTextNode('該当する記事はありませんでした.'));
	this.resultDrawTarget.appendChild(p);
}


/**
 * IEの場合は、onClickの属性を「setAttribute」で指定できないので、
 * 特別なメソッドを定義しておく - 記事のタグのクリック用 - (オーバーライド可)
 */
TaggyTagSearch.prototype.tagClickFunction = function(a) {
	var tag = a.firstChild.nodeValue;
	this.search(this.media,tag);
	this.queryInput.value=tag;
	return false;
}

/**
 * IEの場合は、onClickの属性を「setAttribute」で指定できないので、
 * 特別なメソッドを定義しておく - 「前へ」のクリック用 - (オーバーライド可)
 */
TaggyTagSearch.prototype.prevClickFunction = function() {
	this.search(this.media,this.query,(this.page-1));
	this.queryInput.value=this.query;
	return false;
}

/**
 * IEの場合は、onClickの属性を「setAttribute」で指定できないので、
 * 特別なメソッドを定義しておく - 「次へ」のクリック用 - (オーバーライド可)
 */
TaggyTagSearch.prototype.nextClickFunction = function() {
	this.search(this.media,this.query,(this.page+1));
	this.queryInput.value=this.query;
	return false;
}

/**
 * 引数のJSON形式のデータから検索結果のリストを描画します.(オーバーライド可)
 */
TaggyTagSearch.prototype.render = function(jsonData) {
	
	// 既にある場合は、検索結果の描画をクリアする.
	this.clear();
	
	// 検索結果が0件の場合は「該当する記事はありませんでした」と表示して終る.
	if(jsonData.Entry.length == 0) {
		this.noSearchResult();
		return;
	}

	// 検索結果のリスト	
	var listRoot = document.createElement('div');

	// IDをセット
	if (this.media == 'video' || this.media == 'photo') {
		listRoot.setAttribute('id','taggysearch_content_media');
	} else {
		listRoot.setAttribute('id','taggysearch_content_news');
	}
	this.resultDrawTarget.appendChild(listRoot);
	
	// 検索結果の記事を1つ1つ描画する.
	for (var i = 0; i < jsonData.Entry.length; i++) {
		this.renderEntry(listRoot,jsonData.Entry[i]);
	}
	
	// スペーサーを生成
	var clearDiv = document.createElement('div');
	
	// CSSをセット
	this.setClassAttribute(clearDiv,'taggysearch_lclear');
		
	var spacer = document.createElement('img');
	spacer.setAttribute('src','http://" + host + "/user/images/blogparts/images/spacer.gif');
	spacer.setAttribute('width','1');
	spacer.setAttribute('height','1');
	
	clearDiv.appendChild(spacer);
	listRoot.appendChild(clearDiv);
	

	// 検索結果のPagerDIV要素を生成
	var pager = document.createElement('div');
	
	// CSSをセット
	this.setClassAttribute(pager,'footer');
	
	// Pagerの「前へ」となるA要素を生成
	var me = this;
	if (this.page > 0) {
		var a = document.createElement('a');
		a.setAttribute('href',"#");
		a.appendChild(document.createTextNode('前へ'));
		// thisとして自身は渡せないのでmeに代入している
		a.onclick=function(){me.prevClickFunction();return false;};
		pager.appendChild(a);
	}

	// nbsp=String.fromCharCode(160)を生成
	pager.appendChild(document.createTextNode(String.fromCharCode(160)));
	
	// Pagerの「前へ」となるA要素を生成
	if ((this.page + 1) * this.config.limit < jsonData.Count) {
		var a = document.createElement('a');
		a.setAttribute('href',"#");
		a.appendChild(document.createTextNode('次へ'));
		// thisとして自身は渡せないのでmeに代入している
		a.onclick=function(){me.nextClickFunction();return false;};
		pager.appendChild(a);
	}
	
	// Pagerを検索結果を描画する要素に追加
	this.resultDrawTarget.appendChild(pager);
}

/**
 * 引数のJSON形式のデータから検索結果のリストを描画します.(オーバーライド可)
 */
TaggyTagSearch.prototype.render2 = function(jsonData) {
	
	// CSSをセット
	this.setClassAttribute(this.resultDrawTarget,'taggy_blogparts_content');
	
	// 既にある場合は、検索結果の描画をクリアする.
	this.clear();
	
	// 検索結果が0件の場合は「該当する記事はありませんでした」と表示して終る.
	if(jsonData.Entry.length == 0) {
		this.noSearchResult();
		return;
	}
	
	// 検索結果の記事を1つ1つ描画する.
	for (var i = 0; i < jsonData.Entry.length; i++) {
		this.renderEntry(jsonData.Entry[i]);
	}

	// 検索結果のPagerDIV要素を生成
	var pager = document.createElement('div');
	
	// CSSをセット
	this.setClassAttribute(pager,'footer');
	
	// Pagerの「前へ」となるA要素を生成
	var me = this;
	if (this.page > 0) {
		var a = document.createElement('a');
		a.setAttribute('href',"#");
		a.appendChild(document.createTextNode('前へ'));
		// thisとして自身は渡せないのでmeに代入している
		a.onclick=function(){me.prevClickFunction();return false;};
		pager.appendChild(a);
	}

	// nbsp=String.fromCharCode(160)を生成
	pager.appendChild(document.createTextNode(String.fromCharCode(160)));
	
	// Pagerの「前へ」となるA要素を生成
	if ((this.page + 1) * this.config.limit < jsonData.Count) {
		var a = document.createElement('a');
		a.setAttribute('href',"#");
		a.appendChild(document.createTextNode('次へ'));
		// thisとして自身は渡せないのでmeに代入している
		a.onclick=function(){me.nextClickFunction();return false;};
		pager.appendChild(a);
	}
	
	// Pagerを検索結果を描画する要素に追加
	this.resultDrawTarget.appendChild(pager);
}

/**
 * 引数のJSON形式のデータから検索結果のリストの中の1記事を描画します.(オーバーライド可)
 */
 TaggyTagSearch.prototype.renderEntry = function(listRoot,jsonRowData) {

	// ビデオか写真の場合はp、それ以外はh2
	if (jsonRowData.media == 'video' || jsonRowData.media == 'photo') {
		var row = document.createElement('p');
	} else {
		var row = document.createElement('h2');
	}

	// リンクを生成	
	var a = document.createElement('a');
	a.setAttribute('href', jsonRowData.link);
	a.setAttribute('target',"_blank");
	
	// ビデオか写真の場合はイメージ要素を追加
	if (jsonRowData.media == 'video' || jsonRowData.media == 'photo') {
		// 画像のIMG要素を生成
		var img = document.createElement('img');
		img.setAttribute('src',jsonRowData.relation);
		img.setAttribute('height',this.config.imgsize);
		img.setAttribute('alt',jsonRowData.title);
		
		//イメージを読み込み後　widthを指定 (For IE)
		img.onload = function() {
			var imgScale = Math.floor(44*img.width/img.height);
			img.setAttribute('width',imgScale);
		}
		
		a.appendChild(img);
		
		
		
	} else {
		a.appendChild(document.createTextNode(jsonRowData.title));
	}
	row.appendChild(a);
	listRoot.appendChild(row);
}
 
 
 
/**
 * 引数のJSON形式のデータから検索結果のリストの中の1記事を描画します.(オーバーライド可)
 */
TaggyTagSearch.prototype.renderEntry2 = function(jsonRowData) {
	
	// 記事タイトルを生成
	var h2 = document.createElement('h2');
	var a = document.createElement('a');
	a.setAttribute('href',jsonRowData.link);
	a.setAttribute('target',"_blank");
	a.appendChild(document.createTextNode(jsonRowData.title));
	h2.appendChild(a);
	
	this.resultDrawTarget.appendChild(h2);
	
	// メディアのDIV要素を生成
	var mediaDiv = document.createElement('div');
	
	// CSSをセット
	this.setClassAttribute(mediaDiv,'media');
	
	// ビデオか写真の場合はイメージ要素を追加
	if (jsonRowData.media == 'video' || jsonRowData.media == 'photo') {
	
		// 画像のDIV要素を生成
		var imgDiv = document.createElement('div');
		
		// CSSをセット
		this.setClassAttribute(imgDiv,'media_pic');
		
		// 画像のIMG要素を生成
		var img = document.createElement('img');
		img.setAttribute('src',jsonRowData.relation);
		img.setAttribute('height',this.config.imgsize);
		imgDiv.appendChild(img);
		
		mediaDiv.appendChild(imgDiv);
	}
	
	// 記事に付いているタグの親要素を生成(メディア毎にCLASSが異なる)
	var tagDiv = document.createElement('div');
	if (jsonRowData.media == 'video' || jsonRowData.media == 'photo') {
		// CSSをセット
		this.setClassAttribute(tagDiv,'media_tags');
	} else {
		// CSSをセット
		this.setClassAttribute(tagDiv,'text_tags');
	}
	
	// 記事に付いているタグを生成
	if (jsonRowData.subjects != undefined) {
		tagDiv.appendChild(document.createTextNode('タグ：'));
		
		for (var i=0; i<jsonRowData.subjects.length; i++) {
		
			var a = document.createElement('a');
			a.setAttribute('href',"#");
			a.appendChild(document.createTextNode(jsonRowData.subjects[i].subject));
			
			var me = this;
			a.onclick = function(){me.tagClickFunction(this)};
			tagDiv.appendChild(a);
			tagDiv.appendChild(document.createTextNode(' '));
			
			// 記事に付いているタグが多い場合は「more」のリンクを生成
			if (i >= this.config.taglimit) {
				var more = document.createElement('a');
				more.setAttribute('href',jsonRowData.link);
				more.setAttribute('target',"_blank");
				more.appendChild(document.createTextNode('...'));
				tagDiv.appendChild(more);
				break;				
			}
		}
		if (jsonRowData.media == 'video' || jsonRowData.media == 'photo') {
			mediaDiv.appendChild(tagDiv);
		} else {
			this.resultDrawTarget.appendChild(tagDiv);
		}
	}
	
	// スペーサーを生成
	var clearDiv = document.createElement('div');
	
	// CSSをセット
	this.setClassAttribute(clearDiv,'taggysearch_wclear');
		
	var spacer = document.createElement('img');
	spacer.setAttribute('src','http://" + host + "/user/images/blogparts/images/spacer.gif');
	spacer.setAttribute('width','1');
	spacer.setAttribute('height','1');
	
	clearDiv.appendChild(spacer);
	if (jsonRowData.media == 'video' || jsonRowData.media == 'photo') {
		mediaDiv.appendChild(clearDiv);
		this.resultDrawTarget.appendChild(mediaDiv);
	} else {
		this.resultDrawTarget.appendChild(clearDiv);
	}
	
}

/**
 * タグ検索を行ないます - ページ指定なし
 */
TaggyTagSearch.prototype.search = function(media,query) {
	this.clear();
	this.nowLoading();
	this.tagSearch(media,query,0,'new');
}

/**
 * タグ検索を行ないます - ページ指定あり
 */
TaggyTagSearch.prototype.search = function (media,query,page) {
	this.clear();
	this.nowLoading();
	this.tagSearch(media,query,page,'new');
}

/**
 * タグ検索を行ないます - ページ指定あり
 */
TaggyTagSearch.prototype.search = function (media,query,page,order) {
	this.clear();
	this.nowLoading();
	this.tagSearch(media,query,page,order);
}

/**
 * URLからホスト名を抽出します.
 */
TaggyTagSearch.prototype.getHost = function (url) {

	url.match(/[http|https]:\/\/([-_.!~*\'()a-zA-Z0-9;\?:\@&=+\$,%#]+)\/(.*)/);
	return RegExp.$1;
}

/**
 * Get mouse x position.
 */
TaggyTagSearch.prototype.getMouseX = function(E) {

	if(this.isIE())
		return window.event.clientX + document.documentElement.scrollLeft;
	else if ( document.layers || document.getElementById )
		return E.pageX;
}

/**
 * Get mouse y position.
 */
TaggyTagSearch.prototype.getMouseY = function(E) {

	if(this.isIE())
		return window.event.clientY + document.documentElement.scrollTop;
	else if( document.layers || document.getElementById )
		return E.pageY;
}

/**
 * Show Tool Tip.
 */
TaggyTagSearch.prototype.showToolTip = function(E) {

	E = E || window.event;

	this.hideToolTip(E);

	var element;
	if (E.target) { /* Firefox */  
		element = E.target;
	} else if (E.srcElement) { /* IE */  
		element = window.event.srcElement;
	}

	var title = element.getAttribute('alt');
	var src = element.getAttribute('src');
	//var link = element.parentElement().getAttribute('href');

	var root = document.createElement('span');
	root.setAttribute('id','taggy_plus_tooltip');
	this.setClassAttribute(root,'taggy_plus_tooltips');
	root.style.display="block";

	var top = document.createElement('span');
	this.setClassAttribute(top,'top');
	top.style.display="block";

	top.appendChild(document.createTextNode(title));
	root.appendChild(top);

	var bottom = document.createElement('span');
	this.setClassAttribute(bottom,'bottom');
	bottom.style.display="block";

	var img = new Image();
	img=document.createElement("img");
	img.setAttribute("src",src);

	var me = this;
	var execute = function() {
		if (img.width > 170 || img.width == 0) {
			if (img.width == 0)
				img.setAttribute("width","170");
			var scale = 170 * img.height / img.width;
			img.setAttribute("width","170");
			img.setAttribute("height",scale);
		}
	}
	setTimeout(execute,10);

	// Get mouse position.
	var Xpos = this.getMouseX(E);
	var Ypos = this.getMouseY(E);

	var execute2 = function() {
		// Move element.
		if(me.isIE()) {
			root.style.top=Ypos + 10;
			root.style.left=Xpos -45;
		} else {
			root.style.top=Ypos + 10 + "px";
			root.style.left= Xpos -45 + "px";
		}
		bottom.appendChild(img);
		root.appendChild(bottom);
		document.body.appendChild(root);
	}
	setTimeout(execute2,10);

	element.onmouseout = function(E) { me.hideToolTip(E); };
}

/**
 * Hide Tool Tip.
 */
TaggyTagSearch.prototype.hideToolTip = function(E) {

	var root = document.getElementById('taggy_plus_tooltip');
	if (root)
		document.body.removeChild(root);
}