/* sync.js
(C) 2009 digitalstage inc.
v 20091110
--------------------------------------------------------- */

//var SYNC_SERVER = 'http://localhost:8000/';
var SYNC_SERVER = 'http://sync2-cnsl.digitalstage.jp/';

jQuery.noConflict();
jQuery.ajaxSetup({scriptCharset:'utf-8'});
jQuery.fnbind = function(t, fn){ return function() { return fn.apply(t, arguments);}};

var currentBlogId;
var currentYm = null;
var currentPage = 1;
var mainJson = null;
var catList = [];
var blogOption;
var partsId = 0;
var currentNewsIdx = {};
var feedManager = null;

jQuery(document).ready(function() {
	syncDig(document);
	
	if (feedManager!=null) {
		if (typeof(BlockEdit) == 'undefined') {
			SWFAddress.addEventListener(SWFAddressEvent.CHANGE, jQuery.fnbind(feedManager, feedManager.load));
		} else {
			feedManager.load();
		}
	}
});

function syncDig(p) {
	var cl = p.childNodes;
	for (var i=0; i<cl.length; i++) {
		var c = cl[i];
		var nm = c.nodeName;
		var cls = c.className;

		if (nm == '#text') continue;
		else if (nm == 'DIV' || nm == 'SPAN') {
			if (cls.indexOf('sync') > -1) {
				loadService(cls, c);
			}
		}

		if (c.hasChildNodes()) {
			syncDig(c);
		}
	}
}

function loadService(cls, c) {
	var ary = cls.split(' ');
	var type = ary[1];
	var did = ary[2];
	
	var buf = c.innerHTML;
	ary = buf.split(',');
	var gid = ary[0];
	var sid = ary[1];
	var did = ary[2];
	var option = null;
	
	if (buf.indexOf('{') > -1 && buf.indexOf('}') > -1) {
		var startidx = buf.indexOf('{');
		var endidx = buf.lastIndexOf('}');
		option = jQuery.parseJSON(buf.substring(startidx,endidx+1));
	}
	
	if (type == 'blog') {
		if (option == null) {
			dispSync1Error(c);
			return;
		}
		if (feedManager == null) feedManager = new FeedManager();
		feedManager.addFeed(option.site, option.blogid, did, option, c, sid);

	} else if (type == 'video') {
		dispVideo(c, sid, did, option);
		
	} else if (type == 'form') {
		// TODO:複数フォームへの対応
		var form_load_tm = setTimeout(function() {
			dispSync1Error(c);
		}, 10000);
		jQuery.ajax({
			url: SYNC_SERVER + 'sync/form.action',
			type: 'GET',
			dataType: 'jsonp',
			data: {
				's': sid
			},
			success: function(json) {
				clearTimeout(form_load_tm);
				dispForm(c, sid, json);
			},
			error: function() {
				alert('JSON取得失敗！');
			}
		});

	} else if (type == 'docs') {
		dispDoc(c, sid);
		
	} else if (type == 'news') {
		if (sid=='1')
			dispNews(c, option);
		else
			dispBookmark(c, option);
		
	}
}

function dispSync1Error(c) {
	c.innerHTML = '<div class="kakomi"><p class="kakomi ac"><i><span class="fsize_l" style="color:#6C6C6C;">ここに貼られたBiND2のSYNCウィジェットは、BiND3では表示できません。</span></i><br />' +
		'<i><span class="fsize_l" style="color:#6C6C6C;">一度このパーツを削除し、新規にパーツを作成してください。</span></i><br />' +
		'<br />' +
		'<span class="fsize_s" style="color:#6C6C6C;"><a href="http://www2.digitalstage.jp/support/bind3/trouble/16/">SYNC2のトラブルシューティングを開く</a></span></p></div>';
	c.style.display = '';
}

/**********
N E W S
********/
function dispNews(c, opt) {
	var rssUrl = '';
	if (opt.newsSourceType=='typeRssDirect')
		rssUrl = SYNC_SERVER + 'sync/rss?url=' + encodeURIComponent(opt.rssUrl);
	else
		rssUrl = SYNC_SERVER + 'sync/news.json/' + opt.bindNewsId + '/?dm=1';
	
	jQuery.getJSON(rssUrl + '&callback=?', function(json) {
		c.innerHTML = '';
		var isStandard = (getSkinClass(c).indexOf('standard') > -1);
		var titleStr = '<a href="' + json.url + '" target="_blank">' + json.title + '</a>';
		
		// 通常
		if (opt.designId == 'design1') {
			if (isStandard) {
				var mc = nineSlice('slice h3', c);
				mc.append('<h3>' + titleStr + '</h3>');
			} else {
				var h3div = jQuery('<div class="h3"/>').appendTo(c);
				jQuery('<h3></h3>').appendTo(h3div).append(titleStr);
			}
			
			var div = jQuery('<div class="indent tabular"></div>');
			var table = jQuery('<table class="table"></table>').appendTo(div);
			for (var i=0,l=json.entries.length; i<l; i++) {
				var e = json.entries[i];
				var d = parseFeedDate(e.updated_date);
				var dt = d.year + '/' + d.month + '/' + d.day;
				
				var tr = jQuery('<tr></tr>');
				var th = jQuery('<th><div class="th">' + dt + '</div></th>').appendTo(tr);
				var td = jQuery('<td></td>').appendTo(tr);
				var a = jQuery('<a href="' + e.url + '">' + e.subject + '</a>');
				var balloon = (isStandard) ? nineSlice('balloon', td) : jQuery('<div class="balloon"></div>').appendTo(td);
				balloon.append(a);
				
				table.append(tr);
			}
			
			div.appendTo(c);
			
		// ティッカー
		} else if (opt.designId == 'design2') {
			var ptid = getSyncPartsId();
			var div = jQuery('<div class="indent tabular"></div>');
			var table = jQuery('<table class="table"></table>').appendTo(div);
			var tr = jQuery('<tr></tr>');
			var th = jQuery('<th><div class="th">' + titleStr + '</div></th>').appendTo(tr);
			var td = jQuery('<td></td>').appendTo(tr);
			var area = jQuery('<div id="' + ptid + '" class="sync_news_ticker"></div>');
			var balloon = (isStandard) ? nineSlice('balloon', td) : jQuery('<div class="balloon"></div>').appendTo(td);
			balloon.append(area);
			table.append(tr);
			div.appendTo(c);
			
			// 入れ替えの処理
			var ents = json.entries;
			if (ents.length > 0) {
				doNewsTicker(ents[0], ptid);
				
				if (ents.length > 1) {
					currentNewsIdx[ptid] = 1;
					setInterval(function(){
						var e = ents[currentNewsIdx[ptid]];
						doNewsTicker(e, ptid);
						
						currentNewsIdx[ptid]++;
						if (currentNewsIdx[ptid] >= ents.length) currentNewsIdx[ptid] = 0;
					}, 10000);
				}
			}
		}
		
		c.style.display = '';
		bdRefresh();
		Bindfooter.set();
	});
}

function doNewsTicker(e, ptid) {
	jQuery('#' + ptid + ' span').fadeOut(1000, function() {
		this.parentNode.removeChild(this);
	});
	
	var pt = jQuery('#' + ptid);
	var w = pt.parent().width();
	if (w == 0) w = 500;
	
	var d = parseFeedDate(e.updated_date);
	var dt = d.year + '.' + d.month + '.' + d.day;
	var a = jQuery('<a href="' + e.url + '" class="no_linkeffect">' + dt + ' ' + e.subject + '</a>');
	var csso = {
		left: w + 'px', position:'absolute', width: '100%'
	};
	if (!bindobj.vista && !bindobj.win7) csso.opacity = 0;
	var n = jQuery('<span></span>').css(csso).append(a).appendTo(pt);
	
	var o = {
		left: 0
	};
	if (!bindobj.vista && !bindobj.win7) o.opacity = 1;
	n.animate(o, 2000, 'easeOutExpo');
}

function dispBookmark(c, option) {
	var services = option.services;
	var linkNm = document.title;
	var addr = (option.urlType == 'urlTypeOwn') ? option.ownUrl:location.href;
	var isLocal = (addr.indexOf('file://') == 0);
	
	var hdr = '';
	var buf = '';
	var url = '';
	if (option.buttons.bookmark) {
		hdr += '<a href="#" onclick="showPanel(this, \'bookmark-area\'); return false">ブックマーク<img src="http://sync2-res.digitalstage.jp/_modules/images/arrow_b_6x6.gif" width="6" height="23" /></a>';
		buf += '<div class="bookmark-area">';
		for (var k in services) {
			if (services[k]) {
				switch (k) {
				case 'bmYahoo':
					var yid = getSyncPartsId();
					buf += '<div class="bookmark-panel">';
					buf += '<div class="bookmark-title">';
					buf += '<a href="javascript:void window.open(\'http://bookmarks.yahoo.co.jp/bookmarklet/showpopup?t=' + escape(linkNm) + '&u=' + encodeURIComponent(addr) + '&opener=bm&ei=UTF-8\',\'popup\',\'width=550,height=480,left=100,top=50,scrollbars=1,resizable=1\',0);" title="Yahoo!ブックマークへ追加">';
					buf += '<img src="http://i.yimg.jp/images/sicons/ybm16.gif" />Yahoo!ブックマーク</a>';
					buf += '</div>';
					buf += '<div id="' + yid + '"></div>';
					if (isLocal==false) {
						jQuery.getJSON(SYNC_SERVER + 'sync/yahoobm.action?u=' + encodeURIComponent(addr) + '&callback=?', function(json) {
							jQuery('#' + yid).html('<a href="http://bookmarks.yahoo.co.jp/url?url=' + encodeURIComponent(addr) + '" target="_blank">' + json.ybm_cnt + '人</a>');
						});
					}
					buf += '<a href="http://bookmarks.yahoo.co.jp/promo-about" target="_blank" class="help">?</a>';
					buf += '</div>';
					break;
				case 'bmGoogle':
					buf += '<div class="bookmark-panel">';
					var url = 'http://www.google.com/bookmarks/mark?op=add&bkmk=' + encodeURIComponent(addr) + '&title=' + escape(linkNm);
					buf += '<div class="bookmark-title">';
					buf += '<a href="javascript:wordOfMouse(\'' + url + '\')" title="Googleブックマークへ追加">';
					buf += '<img src="http://sync2-res.digitalstage.jp/_modules/images/google.png" />Googleブックマーク</a>&nbsp;';
					buf += '</div>';
					buf += '<a href="http://www.google.com/support/toolbar/bin/answer.py?answer=43305&topic=15364&hl=ja" target="_blank" class="help">?</a>';
					buf += '</div>';
					break;
				case 'bmHatena':
					buf += '<div class="bookmark-panel">';
					var hid = getSyncPartsId();
					var url = 'http://b.hatena.ne.jp/add?mode=confirm&title=' + escape(linkNm) + '&url=' + encodeURIComponent(addr);
					buf += '<div class="bookmark-title">';
					buf += '<a href="javascript:wordOfMouse(\'' + url + '\')" title="はてなブックマークへ追加">';
					buf += '<img src="http://b.hatena.ne.jp/images/append.gif" style="vertical-align:middle" />はてなブックマーク</a>';
					buf += '</div>';
					buf += '<span id="' + hid + '"></span>&nbsp;';
					if (isLocal==false) {
						jQuery.getJSON('http://api.b.st-hatena.com/entry.count?url=' + encodeURIComponent(addr) + '&callback=?', function(json) {
							jQuery('#' + hid).html('<a href="http://b.hatena.ne.jp/entry/' + addr + '" target="_blank">' + json + '人</a>');
						});
					}
					buf += '<a href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B7%A5%E3%A5%EB%A5%D6%A5%C3%A5%AF%A5%DE%A1%BC%A5%AF" target="_blank" class="help">?</a>';
					buf += '</div>';
					break;
				}
			}
		}
		buf += '</div>';
	}
	
	if (option.buttons.rss) {
		var rssAddr = (option.newsSourceType == 'typeRssDirect') ? option.rssUrl : SYNC_SERVER + 'sync/news.atom/' + option.bindNewsId + '/';
		hdr += '<a href="#" onclick="showPanel(this, \'rss-area\'); return false;">RSSを購読<img src="http://sync2-res.digitalstage.jp/_modules/images/arrow_b_6x6.gif" width="6" height="23" /></a>';
		buf += '<div class="rss-area">';
		for (var k in services) {
			if (services[k]) {
				switch (k) {
				case 'rssYahoo':
					buf += '<div class="bookmark-panel">';
					var url = 'http://rd.yahoo.co.jp/myyahoo/rss/addtomy/users/*http://add.my.yahoo.co.jp/rss?url=' + encodeURIComponent(rssAddr);
					buf += '<div class="bookmark-title">';
					buf += '<a href="javascript:wordOfMouse(\'' + url + '\')" title="My Yahoo!へ追加">';
					buf += '<img src="http://i.yimg.jp/i/jp/my/addtomy2.gif" width="62" height="17" border="0" />My Yahoo!</a>';
					buf += '</div>';
					buf += '<a href="http://my.yahoo.co.jp/st/rss/" target="_blank" class="help">?</a>';
					buf += '</div>';
					break;
				case 'rssGoogle':
					buf += '<div class="bookmark-panel">';
					var url = 'http://fusion.google.com/add?feedurl=' + encodeURIComponent(rssAddr);
					buf += '<div class="bookmark-title">';
					buf += '<a href="javascript:wordOfMouse(\'' + url + '\')" title="Googleリーダーへ追加">';
					buf += '<img src="http://gmodules.com/ig/images/plus_google.gif" border="0" />Googleリーダー</a>&nbsp;';
					buf += '</div>';
					buf += '<a href="http://www.google.co.jp/reader/" target="_blank" class="help">?</a>';
					buf += '</div>';
					break;
				case 'rssHatena':
					buf += '<div class="bookmark-panel">';
					var url = 'http://r.hatena.ne.jp/append/' + encodeURIComponent(rssAddr);
					buf += '<div class="bookmark-title">';
					buf += '<a href="javascript:wordOfMouse(\'' + url + '\')" title="はてなブックマークに追加">';
					buf += '<img src="http://r.hatena.ne.jp/images/addto_w.gif" width="89" height="22" border="0" style="vertical-align:middle" />はてなRSS</a>';
					buf += '</div>';
					buf += '<a href="http://r.hatena.ne.jp/" target="_blank" class="help">?</a>';
					buf += '</div>';
					break;
				}
			}
		}
		buf += '</div>';
	}
	
	if (option.buttons.twitter) {
		var tid = getSyncPartsId();
		var rtid = getSyncPartsId();
		
		hdr += '<a href="#" onclick="showPanel(this, \'twitter-area\'); return false;">Twitterでつぶやく<img src="http://sync2-res.digitalstage.jp/_modules/images/arrow_b_6x6.gif" width="6" height="23" /></a>';
		buf += '<div class="twitter-area">';
		buf += '<div class="bookmark-panel">';
		buf += '<div class="bookmark-title">';
		buf += '<span id="' + tid + '"></span>';
		buf += '</div>';
		buf += '<span id="' + rtid + '"></span>&nbsp;';
		if (isLocal==false) {
			jQuery.getJSON(SYNC_SERVER + 'sync/shorten.action?u=' + encodeURIComponent(addr) + '&callback=?', function(json){
				var su = encodeURIComponent(json.shortUrl);
				var tg = 'http://twitter.com/home/?status=RT+%40' + services.twitterId + '+' + escape(linkNm) + '+' + su;
				jQuery('#' + tid).html('<a href="' + tg + '" title="retweet" target="_blank"><img src="http://sync2-res.digitalstage.jp/_modules/images/twitter_link.gif" />つぶやく</a>');
				
				jQuery.getJSON('http://search.twitter.com/search.json?q=' + su + '+OR+' + encodeURIComponent(addr) + '&callback=?', function(json){
					var twid = getSyncPartsId();
					var retwBuf = '';
					var retwNum = json.results.length;
					if (retwNum > 0) {
						for (var i=0; i<retwNum; i++) {
							var r = json.results[i];
							retwBuf += '<p><img src="' + r.profile_image_url + '" width="20" style="margin-right:2px"/>';
							retwBuf += r.text;
							var dt = new Date(r.created_at);
							var twurl = 'http://twitter.com/' + r.from_user + '/statuses/' + r.id;
							retwBuf += '&nbsp;<a href="' + twurl + '" target="_blank">'
								+ String(dt.getMonth()+1) + '/' + String(dt.getDay()) + ' '
								+ String(dt.getHours()) + ':' + String(dt.getMinutes()) + "</a>";
							retwBuf += '</p>';
						}
						var retwPanel = jQuery('<div id="' + twid + '" class="rt-wrapper"></div>').append('<div class="close-btn"></div>').click(function(e){
							jQuery(this).fadeOut(200);
						}).appendTo(document.body).hide();
						jQuery('<div class="retweeter-panel">' + retwBuf + '</div>').appendTo(retwPanel);
					}
					
					var a = jQuery('<a href="http://search.twitter.com/search?q=' + su + '+OR+' + encodeURIComponent(addr) + '" target="_blank">' + retwNum + '人</a>');
					if (retwNum > 0) {
						a.hover(function(e){
							retwPanel.css({'left': e.pageX, 'top': e.pageY});
							retwPanel.fadeIn(200);
						});
					}
					jQuery('#' + rtid).append('').append(a).append('');
				});
			});
		}
		buf += '<a href="http://twitter.com/" target="_blank" class="help">?</a>';
		buf += '</div>';
		buf += '<div class="bookmark-panel">';
		buf += '<a href="http://twitter.com/' + services.twitterId + '/" target="_blank">このサイトのオーナーをfollowする</a>';
		buf += '</div>';
		buf += '</div>';
	}
	
	hdr = '<div class="bookmark-toolbar">' + hdr + '</div>';
	jQuery(c).html(hdr + buf).show();
	bdRefresh();
	Bindfooter.set();
}

function showPanel(a, cls) {
	var anc = jQuery(a);
	var prt = anc.parent();
	prt.children('a').each(function(i, e) {
		if (e != a)	jQuery(e).removeClass('sel');
	});
	anc.toggleClass('sel');
	
	var bmtop = prt.parent();
	bmtop.children('div.dispnow:not(.' + cls + ')').hide();
	bmtop.children('div.' + cls).slideToggle(200).addClass('dispnow');
}

function wordOfMouse(url) {
	var win = window.open(url, 'bind_wordOfMouse', 'width=800,height=500,resizable=yes,scrollbars=yes,menubar=no,toolbar=no,location=no,status=no');
	win.focus();
}

/**********
 D O C S
********/
function dispDoc(c, sid) {
	var tv = sid.split(':');
	var type = tv[0];
	var docid = tv[1];
	if (type.indexOf('document') == 0) {
		var url = SYNC_SERVER + 'sync/docs.action?callback=?';
		jQuery.getJSON(url, {'s': sid}, function(json) {
			if (json.csspart && json.csspart.length > 0)
				jQuery('<style type="text/css">' + json.csspart + '</style>').appendTo('head');
			c.innerHTML = json.content;
			jQuery('#report-abuse-button').hide();
			jQuery('a.google-small-link').attr('href', 'http://docs.google.com/');
			jQuery(c).fadeIn(500);
			bdRefresh();
			Bindfooter.set();
		});

	} else if (type.indexOf('spreadsheet') == 0) {
		c.innerHTML = '<iframe id="sheet_frame" src="http://spreadsheets.google.com/pub?key=' + docid + '" frameborder="0" width="620" height="560"></iframe>';
		jQuery(c).fadeIn(500);
		bdRefresh();
		Bindfooter.set();

	} else if (type.indexOf('presentation') == 0) {
		c.innerHTML = '<iframe src="http://docs.google.com/EmbedSlideshow?docid=' + docid + '&amp;size=m" frameborder="0" width="555" height="451"></iframe>';
		jQuery(c).fadeIn(500);
		bdRefresh();
		Bindfooter.set();

	}
}

/**********
 F O R M
********/
var forms = null;
function dispForm(c, formId, json) {

	c.innerHTML = '';

	// for error check
	var sync_form_id = 'sync_form_' + formId;
	if (forms == null) forms = {};
	var fields = {
		'form_id' : formId,
		'last_msg' : breakToTag(json.last_msg)
	};

	forms[sync_form_id] = fields;

	var required = jQuery('<span class="required" id="warningA" style="display:visibility">＊</span>');

	var skin = getSkinClass(c);
	if (skin.indexOf('standard') > -1) {
		var mc = nineSlice('slice h3', c);
		mc.append('<h3>' + json.title + '</h3>');
	} else {
		var h3div = jQuery('<div class="h3"/>').appendTo(c);
		jQuery('<h3></h3>').appendTo(h3div).append(json.title);
	}

	var subt = json.subtitle;
	if (subt.length > 0)
		jQuery('<p class="lead"></p>').append(breakToTag(subt)).appendTo(c);

	jQuery('<p class="note" id="warningA2" style="display:visibility">').append(required.clone()).append('は必須入力です。').appendTo(c);

	var frm = jQuery('<form id="' + sync_form_id + '"></form>');
	var inpA = jQuery('<div id="inputA" style="display:visibility"></div>');
	var cfmA = jQuery('<div id="confirmA" style="display:none">Confirm Area<table class="table sync_form"></table></div>');
	var tbl = jQuery('<table class="table sync_form">');

	// comps
	jQuery.each(json.comps, function(i, c) {
		var tr = jQuery('<tr>');
		var th = jQuery('<th>').appendTo(tr).append(c.label);

		var td = jQuery('<td>');
		var fcnt = c.fields.length;

		var err_area = 'err_' + sync_form_id + c.id;

		// fields
		var has_required = false;
		jQuery.each(c.fields, function(j, f) {
			var id = f.id;
			fields[id] = f;
			f['err_area'] = err_area;

			if (f.req) has_required = true;

			var sep = (id.indexOf('postal2') > -1 || id.indexOf('tel2') > -1 || id.indexOf('tel3') > -1) ? '':
				(getByFieldId(c.id)=='name' || getByFieldId(c.id)=='name_kana') ? '　':'<br />';
			
			if (j > 0) td.append(sep);
			if (fcnt > 1) jQuery('<label for="' + id + '">' + f.label + '</label>').appendTo(td);

			if (f.type == 'テキスト') {
				var txt = jQuery('<input type="text" />').attr('id', id).attr('name', id);
				if (f.size > 0) txt.attr('size', f.size);
				txt.appendTo(td);
				txt.focus(chkInput).keyup(chkInput);

			} else if (f.type == '複数行テキスト') {
				var txt = jQuery('<textarea cols="40" rows="7"></textarea>').attr('id', id).attr('name', id).appendTo(td);
				txt.focus(chkInput).keyup(chkInput);

			} else if (f.type == '選択リスト') {
				var sel = jQuery('<select></select>').attr('id', id).attr('name', id).appendTo(td);
				jQuery.each(f.choices, function(i, cho) {
					sel.append(jQuery('<option></option>').append(cho).attr('value', cho));
				});

			} else if (f.type == 'チェックボックス') {
				var sel = jQuery('<span></span>').appendTo(td);
				jQuery.each(f.choices, function(i, cho) {
					sel.append(jQuery('<input type="checkbox" /><span>'+ cho + '&nbsp;&nbsp;</span>').attr('id', id).attr('name', id).attr('value', cho));
				});

			} else if (f.type == 'ラジオボタン') {
				var sel = jQuery('<span></span>').appendTo(td);
				jQuery.each(f.choices, function(i, cho) {
					sel.append(jQuery('<input type="radio" /><span>'+ cho + '&nbsp;&nbsp;</span>').attr('id', id).attr('name', id).attr('value', cho));
				});
			}
		});

		if (has_required) {
			th.append(required.clone());
		}

		td.append('<div id="' + err_area + '"></div>');
		tr.append(td);
		tr.appendTo(tbl);
	});

	var footer = jQuery('<p class="ac">');
	jQuery('<button class="sync_form_button" type="submit">').append('確認').appendTo(footer);
	frm.submit(function(e){
		var flds = forms[this.id]
 		var hasError = false;
 		jQuery.each(flds, function(i, f) {
 			if (!chkOne(f, flds)) hasError = true;
 		});
 		// 更新
 		if (hasError == false) {
 			confirmForm(c, formId, json);
 		}
 		return false;
	});
	
	tbl.appendTo(inpA);
	footer.appendTo(inpA);
	inpA.appendTo(frm);
	cfmA.appendTo(frm);
	var div = jQuery('<div class="indent tabular">').append(frm);
	div.appendTo(c);

	jQuery(c).fadeIn(500);

	bdRefresh();
}

function confirmForm(c, formId, json) {

	c.style.display = 'none';
	var wrnA = jQuery('#warningA');
	var wrnA2 = jQuery('#warningA2');
	var inpA = jQuery('#inputA');
	var cfmA = jQuery('#confirmA');
	cfmA.html('');

	// for error check
	var sync_form_id = 'sync_form_' + formId;
	if (forms == null) forms = {};
	var fields = {
		'form_id' : formId,
		'last_msg' : breakToTag(json.last_msg)
	};

	forms[sync_form_id] = fields;

	var required = jQuery('<span class="required"></span>');

	jQuery('<p class="note">').append(required.clone()).append('この内容で送信します。よろしいですか？').appendTo(cfmA);

	var frm = jQuery('<div></div>');
	var tbl = jQuery('<table class="table sync_form">');
	// comps
	jQuery.each(json.comps, function(i, c) {
		var tr = jQuery('<tr>');
		var th = jQuery('<th>').appendTo(tr).append(c.label);

		var td = jQuery('<td>');
		var fcnt = c.fields.length;

		// fields
		var has_required = false;
		jQuery.each(c.fields, function(j, f) {
			var id = f.id;
			fields[id] = f;

			if (getByFieldId(id)=='email_check') { return false; }
			var sep = (id.indexOf('postal2') > -1 || id.indexOf('tel2') > -1 || id.indexOf('tel3') > -1) ? '':
				(getByFieldId(c.id)=='name' || getByFieldId(c.id)=='name_kana') ? '　':'<br />';
			if (j > 0) td.append(sep);
			if (fcnt > 1) jQuery('<label for="' + id + '">' + f.label + '</label>').appendTo(td);

			switch (f.type) {
			case 'テキスト':
			case '複数行テキスト':
			case '選択リスト':
			case 'チェックボックス':
			case 'ラジオボタン':
				value = getValue(id);
				if (f.type=='複数行テキスト') {
					var CR = String.fromCharCode(13);
					var LF = String.fromCharCode(10);
					workVal = '';
					for (i=0; i<value.length; i++) {
						if (value.charAt(i)==CR) {
						} else if (LF==value.charAt(i)) {
							workVal += "<br>";
						} else {
							workVal += value.charAt(i);
						}
					}
					value = workVal;
				}
				var txt = jQuery('<span>' + value + '</span>').attr('id', id).attr('name', id);
				txt.appendTo(td);
				break;
			default:
			}
		});
		tr.append(td);
		tr.appendTo(tbl);
	});

	var footer = jQuery('<p class="ac">');

	jQuery('<button class="sync_form_button">').append('内容を修正').click(function() {
		pageBack(c, wrnA, wrnA2, inpA, cfmA);
		return false;
	}).appendTo(footer);

	jQuery('<button class="sync_form_button">').append('送信').click(function() {
		var flds = forms[this.form.id]
		var hasError = false;
		jQuery.each(flds, function(i, f) {
			if (!chkOne(f, flds)) hasError = true;
		});

		// 更新
		if (hasError == false) {
			tbl.hide();
			footer.hide();
			jQuery('#confirmA p.note').hide();
			var sending = jQuery('<div class="loading">').height(tbl.height()).width(tbl.width()).appendTo(c);

			fdata = {};
			jQuery.each(flds, function(key, f) {
				if (key == 'form_id')
					fdata['form_id'] = f;
				else if (key == 'last_msg' && key.indexOf('email_check')>=0) {
				}
				else
					fdata[f.id] = getValue(f.id);
			});

			var form_tm = setTimeout(function() {
				sending.removeClass('loading');
				sending.height(0);
				tbl.show();
				footer.show();
				alert('フォームの送信に失敗した可能性があります。\n再送信してください。');
			}, 15000);
			jQuery.ajax({
				url: SYNC_SERVER + 'sync/form_save.action',
				type: 'GET',
				dataType: 'jsonp',
				data: fdata,
				async: false,
				success: function(json) {
					clearTimeout(form_tm);

					// 終了メッセージの表示
					sending.removeClass('loading');
					jQuery('<h3 class="ac"></h3>').append('<span class="sent_msg"></span>').append('送信を完了しました。').appendTo(sending);
					sending.append('<br />');
					var endmsg = jQuery('<p class="lead ac">').hide().append(flds.last_msg).appendTo(sending);
					endmsg.fadeIn(500);
				},
				error: function(xhr, status) {
					clearTimeout(form_tm);
					alert('送信に失敗しました。');
					pageBack(c, wrnA, wrnA2, inpA, cfmA);
				}
			});
		}
		return false;
	}).appendTo(footer);

	tbl.appendTo(frm);
	footer.appendTo(frm);
	var div = jQuery('<div class="indent tabular">').append(frm);
	div.appendTo(cfmA);

	wrnA.attr('style','display: none');
	wrnA2.attr('style','display: none');
	inpA.attr('style','display: none');
	cfmA.attr('style','display: visibility');
	jQuery(c).fadeIn(500);
}

function chkInput(e) {
	var flds = forms[this.form.id]
	var f = flds[this.id];
	chkOne(f, flds);
}

function chkOne(f, flds) {
	if (typeof(f) == 'string') return true;
	
	var msg = '';
	var val = jQuery('#' + f.id).val();
	
	if (f.req) {
		if (f.type == 'チェックボックス' || f.type == 'ラジオボタン') {
			val = getValue(f.id);
			if (f.req && val.length == 0) {
				msg = '選択してください。';
			}
		} else {
			if (f.req && val.length == 0) {
				msg = '入力してください。';
			}
		}
	}
	
	if (f.re.length > 0 && val.length > 0) {
		if (f.re.length > 0 && !val.match(eval(f.re))) {
			if (msg.length > 0) msg += '<br />';
			msg += (f.err.length > 0) ? f.err:'正しい書式で入れてください。';
		}

	}
	
	if (f.type == 'テキスト' || f.type == '複数行テキスト') {
		if (val.length > 500) {
			if (msg.length > 0) msg += '<br />';
			msg += '送信できるテキストは５００文字以内です。';
		}
	}
	
	// 確認用項目
	var pos = f.id.indexOf('_check');
	if (pos > -1) {
		var o = flds[f.id.substring(0, pos)];
		if (o) {
			if (jQuery('#' + o.id).val() != val) {
				if (msg.length > 0) msg += '<br />';
				msg += o.label + 'と一致しません。';
			}
		}
	}

	// エラー表示
	var msgArea = jQuery('#' + f.err_area);
	if (msg.length == 0) {
		msgArea.removeClass('err_msg');
		//msgArea.addClass('success_msg');
		msgArea.empty();
		return true;
	} else {
		msgArea.removeClass('success_msg');
		msgArea.addClass('err_msg');
		msgArea.html(msg);
		return false;
	}
	
	return true;
}


/**********
B L O G
********/
/*
 * ブログのパーツレンダラー
 */
function BlogHandler() {
	this.initialize.apply(this, arguments);
}
BlogHandler.prototype = {
	initialize: function(service, blogId, designId, option, c, sid) {
		this.service = service;
		this.blogId = blogId;
		this.designId = designId;
		this.option = option;
		this.oldId = sid;
		
		this.container = jQuery(c).empty();
		this.container.append('<span class="loading"></span>').show();
		
		this.rendered1st = false;
		// sideは最初のみ読み込み
		this.loadOnly1st = (this.designId.indexOf('side') > -1) ? true : false;
	},
	attachFeedLoader: function(loader) {
		this.feedLoader = loader;
	},
	loadStart: function() {
		if (this.rendered1st && this.designId.indexOf('side') == -1) {
			var wrap = this.container.children('#blogWrapper');
			wrap.empty();
			wrap.attr('className', 'loading');
		}
	},
	render: function(json) {
		this.json = json;
		var skin = getSkinClass(this.container[0]);
		this.skin = skin;
		
		switch (this.designId) {
		case 'title':
			this.renderTitle(json, skin);
			break;
		case 'table':
			this.renderTable(json, skin);
			break;
		case 'standard':
			this.renderStandard(json, skin);
			break;
		case 'paging':
			this.renderPaging(json, skin);
			break;
		case 'accordion':
			this.renderAccordion(json, skin);
			break;
		case 'tab':
			this.renderTab(json, skin);
			break;
		case 'main01':
			this.renderMain01(json, skin);
			break;
		case 'side01':
			if (this.rendered1st == false) this.renderBlogSide(json, skin);
			break;
		}
		
		if (typeof(this.labelArea) != 'undefined') {
			this.labelArea.html(json.headerGuide);
			this.labelArea.show();
		}
		
		this.rendered1st = true;
		bdRefresh();
	},
	getHtmlLink: function(links) {
		var url = '';
		for (var i=0,l=links.length; i<l; i++) {
			var ln = links[i];
			if (ln.rel == 'alternate') {
				url = ln.href;
				break;
			}
		}
		return url;
	},
	renderHeaderV2: function(json, skin) {
		var url = this.getHtmlLink(json.feed.link);
		
		// タイトル
		var h3div = null;
		if (skin.indexOf('standard') > -1) {
			h3div = nineSlice('slice h3', this.container);
		} else {
			h3div = jQuery('<div class="h3"/>').appendTo(this.container);
		}
		
		var h3 = jQuery('<h3/>').appendTo(h3div);
		jQuery('<a href="' + url + '"></a>').append(json.feed.title.$t).appendTo(h3);

		// サブタイトル
		var subt = json.feed.subtitle;
		if (subt && subt.$t.length > 0)
			jQuery('<p class="lead"></p>').text(subt.$t).appendTo(this.container);
	},
	renderDetailV2: function(e, wrapper, skin) {
		var url = this.getHtmlLink(e.link);
		
		var h2 = null;
		if (skin.indexOf('standard') > -1) {
			h2 = jQuery('<span class="mc"></span>');
			var h2core = jQuery('<span class="mm"></span>').append(h2);
			var h2div = jQuery('<h2></h2>').append(h2core)
			jQuery('<div class="h2"></div>').append(h2div).appendTo(wrapper);
		} else {
			h2 = jQuery('<h2></h2>');
			jQuery('<div class="h2"></div>').append(h2).appendTo(wrapper);
		}
		var a = jQuery('<a href="' + url + '"></a>').append(e.title.$t).appendTo(h2);
		
		jQuery('<address class="ar"></address>').append(this.formatBlogDate(e.published.$t)).appendTo(wrapper);
		
		wrapper.append(e.content.$t).append('<br class="clear" />');
		
		if (this.option.link_words != '') {
			var anc = jQuery('<a href="' + url + '"></a>').append(this.option.link_words + ' &gt;&gt;&gt;');
			var p = jQuery('<p class="kakomi ar"></p>').append(anc);
			jQuery('<div class="kakomi"></div>').append(p).appendTo(wrapper);
		}
		
		jQuery('<div class="hr"></div>').appendTo(wrapper);
	},
	cutBody: function(str) {
		var pos = str.indexOf('<br');
		var cutPt = 0;
		if (pos==-1) {
			pos = str.indexOf('</p>');
			cutPt = 4;
		}
		if (pos==-1) {
			pos = str.indexOf('</div>');
			cutPt = 6;
		}
		if (pos > -1) return str.substring(0, pos + cutPt);
		return str;
	},
	renderStandard: function(json, skin) {
		var clazz = this;
		
		jQuery.each(json.feed.entry, function(i, e) {
			clazz.renderDetailV2(e, clazz.container, skin);
		});
	},
	renderTitle: function(json, skin) {
		// タイトル、サブタイトル表示
		this.renderHeaderV2(json, skin);
		
		var dl = jQuery('<dl></dl>');
		jQuery('<div class="indent lined"></div>').append(dl).appendTo(this.container);
		
		// 記事一覧
		var ents = json.feed.entry;
		for (var i=0, l=ents.length; i<l; i++) {
			var e = ents[i];
			jQuery('<dt></dt>').append(this.formatBlogDate(e.published.$t)).appendTo(dl);
			var url = this.getHtmlLink(e.link);
			var a = jQuery('<a href="' + url + '"></a>').append(e.title.$t);
			jQuery('<dd></dd>').append(a).appendTo(dl);
		}
		
		// more
		if (this.option.link_words != '') {
			var url = this.getHtmlLink(json.feed.link);
			var anc = jQuery('<a href="' + url + '"></a>').append(this.option.link_words + ' &gt;&gt;&gt;');
			var p = jQuery('<p class="kakomi"></p>').append(anc);
			jQuery('<div class="kakomi"></div>').append(p).appendTo(this.container);
		}
	},
	renderTable: function(json, skin) {
		// タイトル、サブタイトル表示
		this.renderHeaderV2(json, skin);
		
		var div = jQuery('<div class="indent tabular"></div>');
		var table = jQuery('<table class="table"></table>').appendTo(div);
		
		// 記事一覧
		var ents = json.feed.entry;
		for (var i=0, l=ents.length; i<l; i++) {
			var e = ents[i];
			var tr = jQuery('<tr></tr>');
			var th = jQuery('<th><div class="th">' + this.formatBlogDate(e.published.$t) + '</div></th>').appendTo(tr);
			var td = jQuery('<td></td>').appendTo(tr);
			var url = this.getHtmlLink(e.link);
			var a = jQuery('<a href="' + url + '">' + e.title.$t + '</a>');
			var balloon = (skin.indexOf('standard') > -1) ? nineSlice('balloon', td) : jQuery('<div class="balloon"></div>').appendTo(td);
			balloon.append(a);
			
			jQuery('<p class="affix"></p>').append(e.content.$t).appendTo(td);
			
			// more
			if (this.option.link_words != '') {
				var anc = jQuery('<a href="' + url + '"></a>').append(this.option.link_words + ' &gt;&gt;&gt;');
				jQuery('<p class="affix"></p>').append(anc).appendTo(td);
			}
			
			table.append(tr);
		}
		
		div.appendTo(this.container);
		
	},
	renderPaging: function(json, skin) {
		var prev = jQuery('<a href="#" class="prev"></a>').append('前のエントリーへ').click(jQuery.fnbind(this, this.pagePrev));
		var next = jQuery('<a href="#" class="next"></a>').append('次のエントリーへ').click(jQuery.fnbind(this, this.pageNext));
		jQuery('<p class="ac"></p>').append(prev).append('|').append(next).appendTo(this.container);
		jQuery('<div class="hr"></div>').appendTo(this.container);
		
		blogWrapper = jQuery('<div id="blogWrapper"></div>').appendTo(this.container);
		
		// more
		if (this.option.link_words != '') {
			var url = this.getHtmlLink(json.feed.link);
			var anc = jQuery('<a href="' + url + '"></a>').append(this.option.link_words + ' &gt;&gt;&gt;');
			var p = jQuery('<p class="kakomi ar"></p>').append(anc);
			jQuery('<div class="kakomi"></div>').append(p).appendTo(this.container);
		}
		
		jQuery('<div class="hr"></div>').appendTo(this.container);
		var prevB = jQuery('<a href="#" class="prev"></a>').append('前のエントリーへ').click(jQuery.fnbind(this, this.pagePrev));
		var nextB = jQuery('<a href="#" class="next"></a>').append('次のエントリーへ').click(jQuery.fnbind(this, this.pageNext));
		jQuery('<p class="ac"></p>').append(prevB).append('|').append(nextB).appendTo(this.container);
		
		this.pageDisp(0);
	},
	pageNext: function() {
		if (this.pageIndex < this.json.feed.entry.length) this.pageDisp(this.pageIndex + 1);
	},
	pagePrev: function() {
		if (this.pageIndex > 0) this.pageDisp(this.pageIndex - 1);
	},
	pageDisp: function(idx) {
		var ents = this.json.feed.entry;
		if (ents.length > idx) {
			var e = ents[idx];
			blogWrapper = jQuery(this.container).children('#blogWrapper');
			blogWrapper.html('');
			
			var h2 = null;
			if (this.skin.indexOf('standard') > -1) {
				h2 = jQuery('<span class="mc"></span>');
				var h2core = jQuery('<span class="mm"></span>').append(h2);
				var h2div = jQuery('<h2></h2>').append(h2core)
				jQuery('<div class="h2"></div>').append(h2div).appendTo(blogWrapper);
			} else {
				h2 = jQuery('<h2></h2>');
				jQuery('<div class="h2"></div>').append(h2).appendTo(blogWrapper);
			}
			var ary = e.id.$t.split('-');
			var eid = ary[ary.length-1];
			var url = this.getHtmlLink(e.link);
			var a = jQuery('<a href="' + url + '"></a>').append(e.title.$t).appendTo(h2);
			
			jQuery('<address class="ar"></address>').append(this.formatBlogDate(e.published.$t)).appendTo(blogWrapper);
			blogWrapper.append(e.content.$t + '<br /><br class="clear" />');
			
			if (idx == 0) {
				jQuery('a.prev').css('visibility', 'hidden');
			} else {
				jQuery('a.prev').css('visibility', 'visible');
			}
			
			if (idx == ents.length-1) {
				jQuery('a.next').css('visibility', 'hidden');
			} else {
				jQuery('a.next').css('visibility', 'visible');
			}
			
			this.pageIndex = idx;
		}
	},
	renderAccordion: function(json, skin) {
		this.container.html('アコーディオン！');
	},
	renderTab: function(json, skin) {
		this.container.html('タブ！');
	},
	// ブログのメイン部の書き出し処理
	// 
	renderMain01: function(json, skin) {
		var blogWrapper = null;
		
		// まだ初期描画をしていない時
		if (this.rendered1st == false && json.feed) {
			// タイトル
			var h3div = null;
			if (skin.indexOf('standard') > -1) {
				h3div = nineSlice('slice h3', this.container);
			} else {
				h3div = jQuery('<div class="h3"/>').appendTo(this.container);
			}

			var h3 = jQuery('<h3/>').appendTo(h3div);
			jQuery('<a href="javascript:;"></a>').append(json.feed.title.$t).bind('click', function(e) {
				SWFAddress.setValue('');
			}).appendTo(h3);
			this.labelArea = jQuery('<span id="blog-pwd"></span>').appendTo(h3);

			// サブタイトル
			var subt = json.feed.subtitle;
			if (subt && subt.$t.length > 0)
				jQuery('<p class="lead"></p>').text(subt.$t).appendTo(this.container);

			blogWrapper = jQuery('<div id="blogWrapper"></div>').appendTo(this.container);
			
		} else {
			blogWrapper = jQuery(this.container).children('#blogWrapper');
			blogWrapper.removeClass('loading');
			
		}
		
		if (json.feed) {
			var clazz = this;
			jQuery.each(json.feed.entry, function(i, e) {
				clazz.renderDetail(e, blogWrapper, skin);
			});
		} else {
			this.renderDetail(json.entry, blogWrapper, skin);
		}
		
	},
	renderDetail: function(e, blogWrapper, skin) {
		var wrapper = jQuery('<div class="entryWrapper"/>').appendTo(blogWrapper);
		var h2 = null;
		/*if (skin.indexOf('standard') > -1) {
			h2 = jQuery('<span class="mc"></span>');
			var h2core = jQuery('<span class="mm"></span>').append(h2);
			var h2div = jQuery('<h2></h2>').append(h2core)
			jQuery('<div class="h2"></div>').append(h2div).appendTo(wrapper);
		} else {*/
			h2 = jQuery('<h2></h2>');
			jQuery('<div class="h2"></div>').append(h2).appendTo(wrapper);
		//}
		var ary = e.id.$t.split('-');
		var eid = ary[ary.length-1];
		var a = jQuery('<a href="javascript:;"></a>').append(e.title.$t).bind('click', {blogId: this.blogId, entryId: eid}, function(e) {
			SWFAddress.setValue('detail/' + e.data.entryId);
		}).appendTo(h2);
		
		jQuery('<address class="ar"></address>').append(this.formatBlogDate(e.published.$t)).appendTo(wrapper);
		wrapper.append(e.content.$t + '<br class="clear" />');
		
		// 投稿者が取得できるのはBloggerのみ
		if (this.service == 'google') {
			var link = this.findCommentLink(e.link);
			var footer = jQuery('<p class="kakomi ar"/>').append('投稿者：');
			if (skin.indexOf('standard') > -1) {
				var mm = nineSlice('slice kakomi', wrapper);
				mm.append(footer);
			} else {
				jQuery('<div class="kakomi"/>').append(footer).appendTo(wrapper);
			}
			for (var i=0; i<e.author.length; i++) {
				if (i > 0) footer.append(', ');
				var auth = e.author[i];
				if (auth.uri)
					jQuery('<a target="_blank"></a>').text(auth.name.$t).attr('href', auth.uri.$t).appendTo(footer);
				else
					footer.append(auth.name.$t);
			}

			footer.append('&nbsp;&nbsp;&nbsp;');

			a = jQuery('<a></a>').attr({href: link.href, title: link.title});
			a.text(link.text);
			a.appendTo(footer);
		}
		
		jQuery('<div class="hr"></div>').appendTo(wrapper);
		
	},
	renderBlogSide: function(json, skin) {
		var clazz = this;
		
		if (this.rendered1st == false) {
			// カレンダー
			var calWrap = jQuery('<div class="calWrapper"></div>').appendTo(this.container);
			jQuery('<h3 class="ac" id="blog-calendar-ym"></h3>').appendTo(calWrap);
			var calHdr = jQuery('<div class="calHdr"></div>').appendTo(calWrap);
			jQuery('<a href="javascript:;" class="prevM">&lt;&lt;</a>').appendTo(calHdr).click(function(e) {
				clazz.moveMonth(-1);
			});
			jQuery('<a href="javascript:;" class="nextM">&gt;&gt;</a>').appendTo(calHdr).click(function(e) {
				clazz.moveMonth(1);
			});
			jQuery('<div class="hr clear"></div>').appendTo(calWrap);
			this.calArea = jQuery('<div id="blog-calendar-area"></div>').appendTo(calWrap);

			jQuery('<div class="hr"></div>').appendTo(this.container);
		}

		// カテゴリ
		// amebaはカテゴリーが取得できないので
		if (this.service != 'ameba') {
			var ul = null;
			if (this.rendered1st == false) {
				jQuery('<h4>ラベル</h4>').appendTo(this.container);
				ul = jQuery('<ul id="category-list" class="disc"></ul>').appendTo(this.container);
				
				jQuery('<div class="hr"></div>').appendTo(this.container);
				
			} else {
				ul = this.container.children('#category-list');
			}
			
			// カテゴリ表示
			this.renderCategory(ul, json);
		}
		
		// カレンダー読み込み
		this.loadCalendar();
		
	},
	
	loadCalendar: function(ym) {
		this.calArea.empty();
		this.calArea.attr('className', 'loading');

		var y, m;
		if (ym == null) {
			var d = new Date();
			y = d.getFullYear();
			m = d.getMonth() + 1;
		} else {
			y = new Number(ym.substring(0, 4));
			sm = ym.substring(4);
			if (sm.substring(0, 1) == '0') sm = sm.substring(1);
			m = new Number(sm);
		}

		jQuery('#blog-calendar-ym').text(y + '年 ' + m + '月');

		var st = new Date(y, m - 1, 1);
		var ed = new Date(y, m, 0, 23, 59, 59);	//月末
		var published_min = formatFeedDate(st);
		var published_max = formatFeedDate(ed);
		
		var url = '';
		copyOpt = {};
		if (this.service == 'google') {
			if (this.oldId != '') {
				url = 'http://www.blogger.com/feeds/' + this.oldId + '/posts/default';
			} else if (this.blogId.length > 0) {
				url = 'http://' + this.blogId + '.blogspot.com/feeds/posts/default';
			}
			url += '?redirect=false' +
				'&published-min=' + published_min +
				'&published-max=' + published_max +
				'&alt=json-in-script&callback=?';
		} else {
			url = SYNC_SERVER + "blog/rss/json?callback=?";
			copyOpt = clone(this.option);
			copyOpt.published_min = published_min;
			copyOpt.published_max = published_max;
		}
		
		var clazz = this;
		jQuery.getJSON(url, copyOpt, function(json) {
			clazz.calArea.removeAttr('className');
			var list = [];
			if (json.feed.entry) {
				jQuery.each(json.feed.entry, function(i, e) {
					var o = {
						title: e.title.$t,
						pubdate: parseFeedDate(e.published.$t)
					};
					list.push(o);
				});
			}

			var calTbl = jQuery('<table id="blog-calendar"></table>').appendTo(clazz.calArea);

			var tr  = jQuery('<tr></tr>').appendTo(calTbl);
			for (var i=0; i<7; i++) {
				var d = '';
				switch (i) {
					case 0: d = '日'; break;
					case 1: d = '月'; break;
					case 2: d = '火'; break;
					case 3: d = '水'; break;
					case 4: d = '木'; break;
					case 5: d = '金'; break;
					case 6: d = '土'; break;
				}
				jQuery('<th>' + d + '</th>').appendTo(tr);
			}

			var day = 1;
			var dt = st;
			var stw = dt.getDay();
			var iniMon = dt.getMonth();
			var inCal = false;
			for (var i=0; i<6; i++) {
				tr = jQuery('<tr></tr>').appendTo(calTbl);
				for (var j=0; j<7; j++) {
					if (i==0 && !inCal && j==stw) inCal = true;

					if (inCal) {
						var e = clazz.findEntry(dt, list);

						if (e != null) {
							var td = jQuery('<td></td>').appendTo(tr);
							var a = jQuery('<a href="javascript:;"></a>').attr('title', e.title).text(dt.getDate()).appendTo(td).click(function(evt) {
								SWFAddress.setValue('list/' + this.rel);
							});
							a.attr('rel', e.pubdate.ymd);
						} else {
							jQuery('<td></td>').appendTo(tr).text(dt.getDate());
						}
						day++;
						dt.setDate(day);
						if (dt.getMonth() != iniMon) inCal = false;
					} else {
						jQuery('<td></td>').appendTo(tr).html('&nbsp;');
					}
				}
				if (i > 1 && inCal == false) break;
			}
		});
		
	},
	
	renderCategory: function(wrapper, json) {
		jQuery.each(json.feed.entry, function(i, e) {
			if (e.category) {
				for (var i=0; i<e.category.length; i++) {
					var nm = e.category[i].term;
					if (nm != '' && jQuery.inArray(nm, catList) == -1) {
						var a = jQuery('<a href="javascript:;"></a>').text(nm).click(function() {
							SWFAddress.setValue('label/' + nm);
						});
						jQuery('<li></li>').append(a).appendTo(wrapper);
						catList.push(nm);
					}
				}
			}
		});
	},
	
	moveMonth: function(amont) {
		if (!this.currentYm) this.currentYm = getYm();
		this.currentYm.setMonth(this.currentYm.getMonth() + amont);
		var ym = String(this.currentYm.getFullYear()) + zeroPad(String(this.currentYm.getMonth() + 1));
		this.loadCalendar(ym);
	},
	
	formatBlogDate: function(srcString) {
		var d = parseFeedDate(srcString);
		return d.year + '年' + d.month + '月' + d.day + '日&nbsp;&nbsp;' + d.tm;
	},
	
	findCommentLink: function(links) {
		var o = {};
		for (var i=0; i<links.length; i++) {
			var link = links[i];
			if (link.rel == 'replies') {
				if (link.type == 'text/html') {
					o.href = link.href;
					o.text = link.title;
				} else {
					o.title = link.title;
				}
			}
		}
		return o;
	},
	
	findEntry: function(dt, list) {
		for (var i=0; i<list.length; i++) {
			var o = list[i];
			var pub = o.pubdate;
			if (dt.getFullYear() == pub.year
				&& dt.getMonth() + 1 == pub.month
				&& dt.getDate() == pub.day) {
				return o;
			}
		}
		return null;
	}
};

/*
 * ブログのFeed管理クラス
 */
function FeedManager() {
	this.initialize.apply(this, arguments);
}
FeedManager.prototype = {
	initialize: function() {
		this.db = {};
		this.gfeeds = [];
	},
	addFeed: function(service, blogId, designId, option, container, sid) {
		var handler = new BlogHandler(service, blogId, designId, option, container, sid);
		if (service=='google') {
			this.gfeeds.push(new FeedLoader(service, blogId, option, handler, sid));
		} else {
			var key = service + ':' + blogId;
			if (!(key in this.db)) {
				this.db[key] = new FeedLoader(service, blogId, option, handler, sid);
			} else {
				var ldr = this.db[key];
				ldr.addFeed(handler);
			}
		}
	},
	load: function(evt) {
		var path = '/';
		if (typeof(evt) != 'undefined') {
			path = evt.path;
		}
		
		if (path == 'page') return;

		var args = path.split('/');
		var type = (args.length > 1) ? args[1] : '';
		var param1 = (args.length > 2) ? args[2] : '';
		var param2 = (args.length > 3) ? args[3] : '';
		
		for (var i=0,l=this.gfeeds.length; i<l; i++) {
			var ldr = this.gfeeds[i];
			ldr.load(type, param1, param2);
		}
		
		for (var key in this.db) {
			var ldr = this.db[key];
			ldr.load(type, param1, param2);
		}
	}
};

/*
 * ブログのFeed読み込みクラス
 */
function FeedLoader() {
	this.initialize.apply(this, arguments);
}
FeedLoader.prototype = {
	initialize: function(service, blogId, option, handler, sid) {
		this.service = service;
		this.blogId = blogId;
		this.option = option;
		this.oldId = sid;
		this.loaded1st = false;
		this.detailTopMode = false;
		this.addFeed(handler);
	},
	addFeed: function(handler) {
		handler.attachFeedLoader(this);
		if (!this.handlers) this.handlers = [];
		this.handlers.push(handler);
	},
	load: function(type, param1, param2) {
		// ローディング表示
		this.doLoading();
		
		// ブックマークなどで、詳細ページが最初から読まれた場合の対処
		if (this.loaded1st == false && type == 'detail') {
			this.detailTopMode = true;
			this.getDetailTopFeed(type, param1, param2);
			return;
		}
		
		// 通常の読み込み
		var url = '';
		var loadOpt = {};
		var guide = '';
		var published_min = '';
		var published_max = '';
		
		if (type == 'label') {
			guide = ' − ラベル：「' + decodeURI(param1) + '」のリスト';
			
		} else if (type == 'list') {
			var y = param1.substring(0, 4);
			var m = new Number(omitZero(param1.substring(4, 6)));
			var d = omitZero(param1.substring(6));
			var st = new Date(y, m - 1, d);
			var ed = new Date(y, m - 1, d, 23, 59, 59);
			published_min = formatFeedDate(st);
			published_max = formatFeedDate(ed);
			
			guide = ' − ' + y + '年' + m + '月' + d + '日のリスト';
		}
		
		if (this.service == 'google') {
			var dt_condition = '';
			if (this.oldId != '') {
				url = 'http://www.blogger.com/feeds/' + this.oldId + '/posts/default';
			} else if (this.blogId.length > 0) {
				url = 'http://' + this.blogId + '.blogspot.com/feeds/posts/default';
			}
			
			if (type == 'detail') {
				url += '/' + param1;
				
			} else if (type == 'label') {
				url += '/-/' + param1;
				
			} else if (type == 'list') {
				dt_condition = '&published-min=' + published_min +
							'&published-max=' + published_max;
				
			}
			
			url += '?redirect=false';
			url += dt_condition;
			if (type != 'label' && type != 'detail') url += '&max-results=' + this.option.max_results;
			url += '&alt=json-in-script&callback=?';
			
		} else {
			url = SYNC_SERVER + "blog/rss/json?callback=?";
			loadOpt = clone(this.option);
			if (type == 'detail') loadOpt.entryid = param1;
			else if (type == 'label') loadOpt.category = param1;
			else if (type == 'list') {
				loadOpt.published_min = published_min;
				loadOpt.published_max = published_max;
			}
		}
		
		var clazz = this;
		
		jQuery.getJSON(url, loadOpt, function(json) {
			json.headerGuide = guide;
			
			if (clazz.detailTopMode && clazz.detailTopFeed != null) {
				clazz.detailTopFeed.feed.entry = [];
				clazz.detailTopFeed.feed.entry[0] = json.entry;
				json = clazz.detailTopFeed;
				clazz.detailTopMode = false;
			}
			
			clazz.feed = json;
			clazz.doCallback(json);
			clazz.loaded1st = true;
		});
	},
	getDetailTopFeed: function(type, param1, param2) {
		var url = '';
		var loadOpt = {};
		if (this.service == 'google') {
			if (this.option==null && this.oldId != '') {
				url = 'http://http://www.blogger.com/feeds/' + this.oldId + '/posts/default';
			} else {
				url = 'http://' + this.blogId + '.blogspot.com/feeds/posts/default';
			}
			url += '?redirect=false&max-results=1&alt=json-in-script&callback=?';
			
		} else {
			url = SYNC_SERVER + "blog/rss/json?callback=?";
			loadOpt = clone(this.option);
		}
		
		jQuery.getJSON(url, loadOpt, jQuery.fnbind(this, function(json) {
			this.detailTopFeed = json;
			this.loaded1st = true;
			this.load(type, param1, param2);
		}));
		
	},
	doLoading: function() {
		for (var i=0,l=this.handlers.length; i<l; i++) this.handlers[i].loadStart();
	},
	doCallback: function(json) {
		for (var i=0,l=this.handlers.length; i<l; i++) this.handlers[i].render(json);
	}
};

/**********
V I D E O
********/
function getYTHeight(w) {
	return Math.floor(w / 16 * 9 + 25);
}
function dispVideo(c, sid, did, opt) {
	var tm = new Date().getTime();
	var buf = '';
	if (did == 'standard') {
		var pos = sid.lastIndexOf('/');
		var vid = sid.substring(pos+1);
		
		var h = getYTHeight(opt.playerWidth);
		var a = '';
		if (typeof(Value)=="undefined" || Value.preview) {
			a = '&autoplay=' + ((opt.autoPlay) ? '1':'0');
			a += '&loop=' + ((opt.autoLoop) ? '1':'0');
		}
		
		if (sid.indexOf('playlists') > -1) {
			buf = '<object width="' + opt.playerWidth + '" height="' + h + '">';
			buf += '<param name="movie" value="http://www.youtube.com/p/' + vid + '&hl=ja&fs=1"></param>';
			buf += '<param name="allowFullScreen" value="true"></param>';
			buf += '<param name="allowscriptaccess" value="always"></param>';
			buf += '<embed src="http://www.youtube.com/p/' + vid + '&hl=ja&fs=1' + a + '"';
			buf += ' type="application/x-shockwave-flash" width="480" height="385" allowscriptaccess="always"';
			buf += ' allowfullscreen="true"></embed>';
			buf += '</object>'
		} else {
			buf = '<object width="' + opt.playerWidth + '" height="' + h + '">';
			buf += '<param name="movie" value="http://www.youtube.com/v/' + vid + '&hl=ja&fs=1' + a + '"></param>';
			buf += '<param name="allowFullScreen" value="true"></param>';
			buf += '<param name="allowscriptaccess" value="always"></param>';
			buf += '<embed src="http://www.youtube.com/v/' + vid + '&hl=ja&fs=1' + a + '"';
			buf += ' type="application/x-shockwave-flash" width="' + opt.playerWidth + '" height="' + h + '" allowscriptaccess="always"';
			buf += ' allowfullscreen="true"></embed>';
			buf += '</object>'
		}
		
	} else if (did.indexOf('simple') > -1) {
		var fvars = '';
		if (typeof(Value)=="undefined" || Value.preview) {
			fvars += 'autoPlay=' + opt.autoPlay
				+ '&autoLoop=' + opt.autoLoop + '&autoNext=' + opt.autoNext;
		}
		fvars += '&feedURL=' + sid;
		
		var h = Math.floor(opt.playerWidth / 16 * 9);
		var swf = 'http://sync2-res.digitalstage.jp/_modules/swf/' + did + '.swf?tm=' + tm;
		buf = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"'
			+ ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0"';
	
		buf += ' width="' + opt.playerWidth + '" height="' + h + '" ';
		buf += '>';
	
		buf += '<param name="movie" value="' + swf + '" />';
		buf += '<param name="allowFullScreen" value="true" />';
		buf += '<param name="allowScriptAccess" value="always" />';
		buf += '<param name="align" value="middle" />';
		buf += '<param name="scale" value="showall" />';
		buf += '<param name="quality" value="high" />';
		buf += '<param name="wmode" value="transparent" />';
		buf += '<param name="flashVars" value="' + fvars + '" />';
	
		if (!bindobj.ie) {
			buf += '<embed src="' + swf + '" type="application/x-shockwave-flash"'
			buf += ' width="' + opt.playerWidth + '" height="' + h + '" ';
	
			buf += ' allowFullScreen="true"';
			buf += ' allowScriptAccess="always"';
			buf += ' align="middle"';
			buf += ' scale="showall"';
			buf += ' quality="high" wmode="transparent"';
			buf += ' flashVars="' + fvars + '"';
			buf += ' pluginspage="http://www.adobe.com/go/getflashplayer_jp"></embed>';
		}
	
		buf += '</object>';
		buf += '<br /><br />';
		
	} else {
		var fvars = '';
		if (opt != null && (typeof(Value)=="undefined" || Value.preview)) {
			fvars += 'autoPlay=' + opt.autoPlay
				+ '&autoLoop=' + opt.autoLoop + '&autoNext=' + opt.autoNext;
		}
		fvars += '&feedURL=' + sid;
		
		var swf = 'http://sync2-res.digitalstage.jp/_modules/swf/ytplayer.swf?tm=' + tm;
		buf = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"'
			+ ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0"';
	
		buf += ' width="746" height="430" ';
		buf += '>';
	
		buf += '<param name="movie" value="' + swf + '" />';
		buf += '<param name="allowFullScreen" value="true" />';
		buf += '<param name="allowScriptAccess" value="always" />';
		buf += '<param name="align" value="middle" />';
		buf += '<param name="scale" value="showall" />';
		buf += '<param name="quality" value="high" />';
		buf += '<param name="wmode" value="transparent" />';
		buf += '<param name="flashVars" value="' + fvars + '" />';
	
		if (!bindobj.ie) {
			buf += '<embed src="' + swf + '" type="application/x-shockwave-flash"'
			buf += ' width="746" height="430" ';
	
			buf += ' allowFullScreen="true"';
			buf += ' allowScriptAccess="always"';
			buf += ' align="middle"';
			buf += ' scale="showall"';
			buf += ' quality="high" wmode="transparent"';
			buf += ' flashVars="' + fvars + '"';
			buf += ' pluginspage="http://www.adobe.com/go/getflashplayer_jp"></embed>';
		}
	
		buf += '</object>';
		buf += '<br /><br />';
	}
	
	c.innerHTML = buf;
	c.style.display = '';
	c.style.textAlign = 'center';

	bdRefresh();

}

var Utils = function() {
};
Utils.prototype = {
};

/*******
 * Utils
 ********/
//cにアペンドして、mcを返す
function nineSlice(cls, c) {
	var mc = jQuery('<div class="mc"></div>');
	var mm = jQuery('<div class="mm"></div>').append('<div class="ml"></div>').append('<div class="mr"></div>').append(mc);
	var h3 = jQuery('<div class="' + cls + '"></div>')
		.append('<div class="tl"></div>').append('<div class="tr"></div>').append('<div class="tc"></div>').append(mm);
	h3.append('<div class="bl"></div>').append('<div class="br"></div>').append('<div class="bc"></div>').appendTo(c);
	return mc;
}

function getSkinClass(c) {
	var p = c.parentNode;
	while(true) {
		if (p.tagName && p.tagName=='body') return;
		var cls = p.className;
		if (cls.indexOf('simple')==0 || cls.indexOf('standard')==0) return cls;
		p = p.parentNode;
	}
}

function getYm() {
	var d = new Date();
	d.setDate(1);
	d.setHours(0);
	d.setMinutes(0);
	d.setSeconds(0);
	d.setMilliseconds(0);
	return d;
}

// feed 日付変換
function formatFeedDate(dt) {
	var y = String(dt.getFullYear());
	var m = zeroPad(String(dt.getMonth() + 1));
	var d = zeroPad(String(dt.getDate()));
	var h = zeroPad(String(dt.getHours()));
	var mi = zeroPad(String(dt.getMinutes()));
	var s = zeroPad(String(dt.getSeconds()));
	return y + '-' + m + '-' + d + 'T' + h + ':' + mi + ':' + s + '%2b09:00';
}

// feed 日付解析
function parseFeedDate(s) {
	var local = s.substring(0, s.length - 6);
	var ary = local.split('T');
	var dary = ary[0].split('-');
	var wk = ary[1].split('.');
	var tary = wk[0].split(':');
	var ms = wk[1];
	var o = {
		year: dary[0],
		month: omitZero(dary[1]),
		day: omitZero(dary[2]),
		hour: omitZero(tary[0]),
		min: omitZero(tary[1]),
		sec: omitZero(tary[2]),
		tm: omitZero(tary[0]) + ':' + tary[1]
	};
	o['ymd'] = o.year + zeroPad(o.month) + zeroPad(o.day);
	return o;
}

function zeroPad(s) {
	if (s.length==1) return '0' + s;
	return s;
}

// ゼロ除去。先頭のみ
function omitZero(s) {
	if (s.substring(0, 1) == '0') return s.substring(1);
	return s;
}

function breakToTag(str) {
	rtn = str.replace(/\r\n/ig, '<br />');
	rtn = rtn.replace(/\n/ig, '<br />');
	rtn = rtn.replace(/\r/ig, '<br />');
	return rtn;
}

function bdRefresh() {
	if (typeof(BlockEdit) != 'undefined') {
		BlockEdit.resize();
	}
}

/* オブジェクトコピー */
function clone(obj) {
	var func = function(){};
	func.prototype = obj;
	return new func;
}


function getValue(id) {
	var value = "";
	if (jQuery("#"+id).attr("type")=="radio" || jQuery("#"+id).attr("type")=="checkbox") {
		var obj = jQuery("input:checked[id=" + id + "]");
		for (i=0 ; i<obj.length ; i++) {
			if (i!=0) { value += ","; }
			value += obj.get(i).value;
		}
	} else {
		value = jQuery("#"+id).val();
	}
	return value;
}

function pageBack(c, wrnA, wrnA2, inpA, cfmA) {
	c.style.display = 'none';
	wrnA.attr('style','display: visibility');
	wrnA2.attr('style','display: visibility');
	inpA.attr('style','display: visibility');
	cfmA.attr('style','display: none');
	jQuery(c).fadeIn(500);
}

function getByFieldId(id) {
	if (id.indexOf('__')>0) {
		return id.substring(0,id.indexOf('__'));
	}
	return id;
}

function findWord(id,word) {
	res = false;
	if (id.indexOf(word)>=0) {
		res = true;
	}
	return res;
}

function getParameters(params) {

	if (params.indexOf('{')>=0 && params.indexOf('}')>=0) {
		var startidx = params.indexOf('{');
		var endidx = params.indexOf('}');
		option = jQuery.parseJSON(params.substring(startidx,endidx+1));
	}
	return option;
}

function getSyncPartsId() {
	partsId++;
	return 'syncpt-' + String(partsId);
}
