// ================================================================
//  ajaxcom.js ---- Ajax comment component
//  Copyright 2005-2006 Kawasaki Yusuke <u-suke [at] kawa.net>
//  http://www.kawa.net/works/ajax/ajaxcom/ajaxcom.html
// ================================================================

AjaxCom = function ( area, path ) {
    this.area = area;
    if ( typeof(path) == "undefined" ) {
        path = window.location.pathname;
        path = path.replace( /\/\/\/*/g, "/" );     // multiple /
        path = path.replace( /\/((index|default).(s?html?|asp|cgi|php))?$/, "" );
        path = path.replace( /^\//, "" );           // first /
        path = path.replace( /\/$/, "" );           // last /
        if ( path == "" ) path = "/";               // root /
    }
    this.path = path;
    this.init_comment_area();
    return this;
};

AjaxCom.prototype.form_name     = 'Name: ';
AjaxCom.prototype.form_content  = 'Comment: ';
AjaxCom.prototype.form_submit   = 'POST';
AjaxCom.prototype.content_left  = '"';
AjaxCom.prototype.content_right = '"';
AjaxCom.prototype.error_name    = 'Name is empty.';
AjaxCom.prototype.error_content = 'Comment is empty.';
AjaxCom.prototype.error_post    = 'Failed to post your comment.';
AjaxCom.prototype.error_receive = 'No comments yet.';
AjaxCom.prototype.class_root    = 'ajaxcom';
AjaxCom.prototype.class_name    = 'ajaxcom_name';
AjaxCom.prototype.class_content = 'ajaxcom_content';
AjaxCom.prototype.class_submit  = 'ajaxcom_submit';
AjaxCom.prototype.class_issued  = 'ajaxcom_issued';
AjaxCom.prototype.class_notice  = 'ajaxcom_notice';
AjaxCom.prototype.form_id       = 'ajaxcom_form';
AjaxCom.prototype.btn_id        = 'comment_btn';

////
AjaxCom.prototype.url_receive   = '/-/com/ajaxcom-data';
AjaxCom.prototype.url_post      = '/-/com/ajaxcom.cgi';
////

AjaxCom.prototype.load = function ( arg ) {
    var path = this.path.replace( /[^A-Za-z0-9\_\.\-]/g, "_" );
    var url = this.url_receive + "/" + path + ".txt";
    if ( arg ) url += "?" + arg;
    var req = this.get_http_request( "GET", url );
    var copythis = this;
    var loaded = 0;
    var func = function () {
        if ( req.readyState != 4 ) return;
        if ( loaded ++ ) return;
        if ( req.status == 404 ) {
            copythis.disp_message( copythis.error_receive );
        } else {
            copythis.update_comment( req, arg );
        }
    }
    req.onreadystatechange = func;
    req.send("");
}
AjaxCom.prototype.open_form = function() {
	var fm = document.getElementById('ajaxcom_form');
	if( fm.style.display=='block' ){
		fm.style.display = 'none';
	}else{
		fm.style.display = 'block';
	}
}
AjaxCom.prototype.init_comment_area = function () {
	// === コメント入力FORM =====================
    var ediv = document.getElementById( this.area );
    while ( ediv.childNodes.length ) {
        ediv.removeChild( ediv.firstChild );
    }

    var eform = document.createElement( "form" );
    var ep = document.createElement( "p" );
    var espan1 = document.createElement( "span" );
    var espan2 = document.createElement( "span" );
    var espan3 = document.createElement( "span" );
    var etext1 = document.createTextNode( this.form_name );
    var etext2 = document.createTextNode( this.form_content );
    var einput1 = document.createElement( "input" );
    var einput2 = document.createElement( "textarea" );
    var einput3 = document.createElement( "input" );
    var ful = document.createElement( "ul" );
	
    var br1 = document.createElement( "br" );
    var br2 = document.createElement( "br" );
    var label1 = document.createElement( "div" );
    var label2 = document.createElement( "div" );
    var label3 = document.createElement( "div" );
	var txt_btn = document.createTextNode( this.content_btn );
	var div_btn = document.createElement( "div" );
    espan1.className = this.class_name;
    espan2.className = this.class_content;
    espan3.className = this.class_submit;

	ep.id = this.form_id;
	ep.style.display = 'none';


	// コメント記入枠表示ボタン(FORMの外)
    var c0 = document.createElement( "div" );
    var a1 = document.createElement("a");
	a1.href = 'javascript:void(0);';
	a1.appendChild( txt_btn );
	this.appendEvent(a1, "click", this.open_form);
	div_btn.id = this.btn_id;
	div_btn.appendChild(a1);
	c0.appendChild(div_btn);
	// お名前
    var c1 = document.createElement( "div" );
	var c1_title = document.createTextNode( this.form_name );
	var c1_input = document.createElement("input");
	c1_input.type = "text";
    c1_input.name = "name";
    c1.appendChild( c1_title );
    c1.appendChild( document.createElement("br") );
    c1.appendChild( c1_input );
    ep.appendChild( c1 );
	// コメント
    var c2 = document.createElement( "div" );
	var c2_title = document.createTextNode( this.form_content );
	var c2_input = document.createElement("textarea");
    c2_input.name = "content";
	c2_input.cols = 50;
	c2_input.rows = 3;
    c2.appendChild( c2_title );
    c2.appendChild( document.createElement("br") );
    c2.appendChild( c2_input );
    ep.appendChild( c2 );
	// 送信ボタン
    var c3 = document.createElement( "div" );
	var c3_input = document.createElement("input");
	c3_input.type = "submit";
    c3_input.name = "submit_btn";
    c3_input.value = this.form_submit;
    c3.appendChild( c3_input );
    ep.appendChild( c3 );
	// FORM 全体
    eform.appendChild( ep );
    eform.appendChild( ful ); // 一覧用の枠を追加しておく
	// FORMに送信イベントを追加
    var copythis = this;
    var func = function (e,target) { copythis.post_content(e,target);};
    this.appendEvent( eform, "submit", func );

	// エレメント全体
    ediv.appendChild( c0 );
    ediv.appendChild( eform );
    ediv.className = this.class_root;
}

AjaxCom.prototype.update_comment = function ( req, opt ) {
// === 保存されたデータを表示する ====================
    var text = this.get_response_text( req );
    if ( typeof(text) != "string" ) return;

    var ediv = document.getElementById( this.area );
    var eul = ediv.getElementsByTagName( "ul" );
    var ful = eul[0];

    while ( ful.childNodes.length ) {
        ful.removeChild( ful.firstChild );
    }

    var lines = text.split(/[\r\n][\r\n]*/); // 改行で区切る（１行１データ）
    var scroll;
    for( var i=lines.length; i>=0; i-- ) {
        var aline = lines[i];
		if ( typeof(aline) != "string" ) continue;	/* 文字列でなければ無視 */
		if ( aline.charAt(0) == "#" ) continue;		/* 先頭が # なら無視 */
        var cols = lines[i].split("\t");
        if ( cols.length < 3 ) continue;			/* タブで３つ以上区切られてなければ無視 */
        var dd = new Date();
        dd.setW3CDTF( cols[0] ); /* 日付 */
        var iissued = dd.toLocaleString()
		
		var line1 = document.createElement("li");
        var f_bdy = document.createElement("div");
        var f_ftr = document.createElement("div");
        f_bdy.className = this.class_content;
        f_ftr.className = this.class_issued;
        var txt_name = document.createTextNode( cols[3] ); /* 名前 */
        var txt_qL = document.createTextNode( this.content_left );
        var txt_comm = document.createTextNode( cols[4] ); /* コメント */
        var txt_qR = document.createTextNode( this.content_right );
        var txt_date = document.createTextNode( iissued ); /* 日付 */
		// URL リンク処理
        // f_bdy.appendChild( txt_comm );
		var dt = cols[4].split(/\<\>/);
		var t = document.createTextNode( dt.length );
		for(var j=0; j<dt.length; j++){
			var t = document.createTextNode( dt[j] );
			f_bdy.appendChild( t );
			var tbr = document.createElement("br");
			f_bdy.appendChild( tbr );
		}
		// 投稿者＋日付
        f_ftr.appendChild( txt_name );
        f_ftr.appendChild( txt_date );

        var fa1 = document.createElement( "a" );
        fa1.name = "com-"+cols[0];
        line1.appendChild( fa1 );

        line1.appendChild( f_bdy );
        line1.appendChild( f_ftr );
		ful.appendChild( line1 );

        if ( location.hash == "#com-"+cols[0] ) {
            scroll = line1;
        }

	}
    if ( scroll && ! opt ) {
        var y = scroll.offsetTop;
        if ( y ) window.scrollTo(0,y);
    }
}

AjaxCom.prototype.disp_message = function ( content ) {
	// === エラーメッセージを表示する =============
    var ediv = document.getElementById( this.area );
    var eul = ediv.getElementsByTagName( "ul" );
    var ful = eul[0];
    var dd = new Date();
    var iissued = dd.toLocaleString()

    var fli = document.createElement( "li" );
    var fspan2 = document.createElement( "span" );
    var fspan3 = document.createElement( "span" );
    fspan2.className = this.class_notice;
    fspan3.className = this.class_issued;
    var ftext2b = document.createTextNode( content );
    var ftext3 = document.createTextNode( iissued );

    fspan2.appendChild( ftext2b );
    fspan3.appendChild( ftext3 );
    fli.appendChild( fspan2 );
    fli.appendChild( fspan3 );

    if ( ful.firstChild ) {
        ful.insertBefore( fli, ful.firstChild );
    } else {
        ful.appendChild( fli );
    }
}

AjaxCom.prototype.appendEvent = function ( target, type, func ) {
	// === オブジェクトにイベントを追加する ========
    var copyfunc = func;
    if ( target.attachEvent ) {
        var iefunc = function () {
            event.returnValue = false;
            copyfunc( event, event.srcElement );
        };
        target.attachEvent( "on"+type, iefunc );
    } else {
        var domfunc = function (e) {
            e.preventDefault();
            copyfunc( e, e.target );
        };
        target.addEventListener( type, domfunc, false );
    }
}

AjaxCom.prototype.post_content = function ( e, eform ) {
    var query = {
        name:       eform.elements[0].value,
        content:    eform.elements[1].value
    };
    if ( query.name == "" ) {
        this.disp_message( this.error_name );
        return;
    }
    if ( query.content == "" ) {
        this.disp_message( this.error_content );
        return;
    }
    var body = this.hash_to_text( query );
    var url = this.url_post + "/" + this.path;
    var req = this.get_http_request( "POST", url );
    var copythis = this;
    var loaded = 0;
    var func = function () {
        if ( req.readyState != 4 ) return;
        if ( loaded ++ ) return;
        copythis.target_form.elements[2].disabled = false;
        if ( req.status != 200 ) {
            copythis.disp_message( req.status+" "+req.statusText );
            copythis.disp_message( copythis.error_post );
        } else {
            var error = copythis.get_response_value( req, "error" );
            if ( error == "0" ) {
                var arg = "t=" + Math.floor(Math.random()*9000+1000);
                copythis.load( arg );
            } else {
                var mess = copythis.get_response_value( req, "message" );
                if ( mess ) copythis.disp_message( mess );
                copythis.disp_message( copythis.error_post );
            }
        }
    }
    req.onreadystatechange = func;
    eform.elements[2].disabled = true;
    req.send(body);
    this.target_form = eform;
    eform.elements[1].value = "";
}

AjaxCom.prototype.get_http_request = function ( method, url ) {
    var req;
    if ( window.XMLHttpRequest ) {
        req = new XMLHttpRequest();
    } else if ( window.ActiveXObject ) {
        req = new ActiveXObject( "Microsoft.XMLHTTP" );
    } else {
        return;
    }
    req.open( method, url, true );
    if ( typeof(req.setRequestHeader) != "undefined" ) {
        req.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
    }
    return req;
}

AjaxCom.prototype.get_response_text = function ( req ) {
    var text = req.responseText;
    if ( navigator.appVersion.indexOf( "KHTML" ) > -1 ) {
        var esc = escape( text );
        esc = esc.replace( /^(%[89ABab][0-9A-Fa-f])+/, "?" );
        if ( esc.indexOf("%u") < 0 && esc.indexOf("%") > -1 ) {
            text = decodeURIComponent( esc );
        }
    }
    return text;
}

AjaxCom.prototype.get_response_value = function ( req, name ) {
    var xml = req.responseXML;
    if ( ! xml ) return "";
    var elem = xml.getElementsByTagName( name );
    if ( ! elem ) return "";
    if ( ! elem.length ) return "";
    return elem[0].firstChild.nodeValue;
}

AjaxCom.prototype.hash_to_text = function ( hash ) {
	// === 連想配列を１行文字列にする =====
    var array = [];
    for( var key in hash ) {
        array[array.length] = key+"="+encodeURIComponent(hash[key]);
    }
    return array.join("&");
}

Date.prototype.setW3CDTF = function( dtf ) {
    var sp = dtf.split( /[^0-9]/ );
    if ( sp.length < 6 || sp.length > 8 ) return;

    if ( sp.length == 7 ) {
        if ( dtf.charAt( dtf.length-1 ) != "Z" ) return;
    }

    for( var i=0; i<sp.length; i++ ) sp[i] = sp[i]-0;    // to numeric

    if ( sp[0] < 1970 ||                // year
         sp[1] < 1 || sp[1] > 12 ||     // month
         sp[2] < 1 || sp[2] > 31 ||     // day
         sp[3] < 0 || sp[3] > 23 ||     // hour
         sp[4] < 0 || sp[4] > 59 ||     // min
         sp[5] < 0 || sp[5] > 60 ) {    // sec
        return;                         // invalid date 
    }

    // get UTC milli seconds
    var msec = Date.UTC( sp[0], sp[1]-1, sp[2], sp[3], sp[4], sp[5] );

    // time zene offset
    if ( sp.length == 8 ) {
        if ( dtf.indexOf("+") < 0 ) sp[6] *= -1;
        if ( sp[6] < -12 || sp[6] > 13 ) return;    // time zone offset hour
        if ( sp[7] < 0 || sp[7] > 59 ) return;      // time zone offset min
        msec -= (sp[6]*60+sp[7]) * 60000;
    }

    // set by milli second;
    return this.setTime( msec );
}

// ****
