/***    TDL Chat    version 1.1    started on 2010-11-18    Copyright (c) Marcin Szpak        Changelog:        2010-12-02 started threads        Requirements:    TDLUtils (1_5_13):      - docEl      - scriptLoad      - documentTitleAnim      - userLastVisit      - textNoEmptyAlertElem      - documentLocation      - documentLocationParams      - elemClick      - domGetFirstRoot      - domClassNameAddTree          USAGE:         HANDLERS:      - TDLChatLUOWSResultHandler = function(usersOnline)          USED NAMES:        functions TDLChat*        #TDLChat        .loading .loaded .writing .sending .nomore .emptyOr1 .input .submitHidden .message .body .sigSub .submit .sign .sendingAnim .anim  .entries .entry .new .first .info .date .loadingAnim .navi .less .more        (each one as a child or className of #TDLChat)    TODO:       - progressive reloading time (on low activity)      - numEntries param (default 10)      - refreshMilis param      - custom default description          ***/var TDLChatMaxEntries=10;var TDLChatRefreshSecs=30;var TDLChatRefreshSecsMin=30; //half a minutevar TDLChatRefreshSecsMax=480;//8 minutes/***** LOGIC *****//* server script */var TDLChatLIdPrefix="TDLChatId";var TDLChatLEntryIdPrefix="TDLChatEntryId";var TDLChatLScriptHost="http://tdl.home.pl/tdlchatservicenew";//var TDLChatLScriptHost="http://";//"http://tdlchatservice.appspot.com";//var TDLChatLScriptHost="http://localhost:8080";var TDLChatLScriptLoadName="load.php";//var TDLChatLScriptLoadName="load";//var TDLChatLScriptLoadNewerName="loadNewer";//var TDLChatLScriptLoadOlderName="loadOlder";var TDLChatLScriptLoadNewerName="load.php";var TDLChatLScriptLoadOlderName="load.php";var TDLChatLScriptPostName="post.php";//Script:WSVC params:eFunPre       - events function prefix e.g. chatResult('mainchat,//                   uoFunPre      - users online function prefix e.g uo(//                   parent        - db parent id/name//                   newerThanSec  - load entries only newer than [timestamp in sec]//                   olderThanSec  - load entries only older than [timestamp in sec]//                   limit         - number of entries to load [1..100]function TDLChatLScriptLoad(params,newer,older){        scriptLoad(TDLChatLScriptHost+"/"+(newer?TDLChatLScriptLoadNewerName:older?TDLChatLScriptLoadOlderName:TDLChatLScriptLoadName)+"?"+params); //TODO: refresh Milis}/* server script *//* chat load *///TODO://TODO: progressive reloading time (on low activity)var TDLChatLTOHandler=[]; //used to disable reloading (on close chat)var TDLChatLParentId=[];var TDLChatLEntries=[]; //{"domElemId":[entry1,entry2,...]}                        //entry=[timestampSec,description,signature]function TDLChatLInit(dbParentEntryId,domElemId,getOnlineUsersCounter,noAutoload,noRefresh){	TDLChatLEntries[domElemId]=[];    TDLChatLParentId[domElemId]=dbParentEntryId;//TODO: maybe autoload no needed//      maybe noLoad and noTimeout (if thread)    if (!noAutoload)         TDLChatLLoad(domElemId,getOnlineUsersCounter,false,noRefresh);}function TDLChatLLoad(domElemId,getOnlineUsersCounter,noLoad,noRefresh){        if (!noLoad)    {        var getNewer=TDLChatLEntries[domElemId] && TDLChatLEntries[domElemId][0];        TDLChatLScriptLoad("eFunPre=TDLChatLEWSResult('"+domElemId+"',"+(getOnlineUsersCounter?"&uoFunPre=TDLChatLUOWSResult(":"")+"&parent="+TDLChatLParentId[domElemId]+(getNewer?"&newerThanSec="+TDLChatLEntries[domElemId][0][0]:""),getNewer,false);//        TDLChatLScriptLoad("eFunPre=TDLChatLEWSResult('"+domElemId+"',"+(getOnlineUsersCounter?"&uoFunPre=TDLChatLUOWSResult(":"")+"&parent="+TDLChatLParentId[domElemId]+(getNewer?"&newerThanSec="+TDLChatLEntries[domElemId][0][0]:""));    }    if (!noRefresh)        //remember uint handler and clear on close chat        TDLChatLTOHandler[domElemId]=setTimeout("TDLChatLLoad('"+domElemId+"',"+getOnlineUsersCounter+")",TDLChatRefreshSecs*1000);}function TDLChatLStopAll(){    for (e in TDLChatLTOHandler)        clearTimeout(TDLChatLTOHandler[e]);    TDLChatLTOHandler=[];}function TDLChatLStop(elemId){    clearTimeout(TDLChatLTOHandler[elemId]);}function TDLChatLLoadAppend(domElemId,olderThanSec){         	TDLChatLScriptLoad("eFunPre=TDLChatLAEWSResult('"+domElemId+"',"+"&parent="+TDLChatLParentId[domElemId]+"&olderThanSec="+olderThanSec,false,true);}var TDLChatLUOWSResultHandler=null;function TDLChatLUOWSResult(usersOnline){    if (TDLChatLUOWSResultHandler!=null)        TDLChatLUOWSResultHandler(usersOnline);}//entry=[timestampSec,description,signature,id,visibleChildrenNum]//       0           ,1          ,2        ,3 ,4var TDLChatLEntryNewHandler=null;function TDLChatLEWSResult(domElemId,entries){    //if new entry then anim document title    if (TDLChatLEntries[domElemId].length>0 && entries.length>0) //if this is not first load (initial load - then no window status)        documentTitleAnim(entries[0][2]||"",entries[0][1]);            if (entries.length>0) //if entries than shorten refresh time        TDLChatRefreshSecs=Math.max(TDLChatRefreshSecsMin,TDLChatRefreshSecs/2);    else //if no entries than lengthen refresh time        TDLChatRefreshSecs=Math.min(TDLChatRefreshSecsMax,TDLChatRefreshSecs*2);        //test if not viewing more (with more button)    var trimMax=(TDLChatLEntries[domElemId].length<=TDLChatMaxEntries);    //TODO: remove arrayJoin    TDLChatLEntries[domElemId]=arrayJoin(entries,TDLChatLEntries[domElemId]);    //cut when more than TDLChatMaxEntries, but not in case of viewing more (if !trimMax)    if (trimMax && TDLChatLEntries[domElemId].length>TDLChatMaxEntries) TDLChatLEntries[domElemId].length=TDLChatMaxEntries;    var ce=[];    for (var i=0;i<TDLChatLEntries[domElemId].length;i++)        ce.push([TDLChatLEntries[domElemId][i][1],TDLChatLEntries[domElemId][i][2],TDLChatLEntries[domElemId][i][0],TDLChatLEntries[domElemId][i][3],TDLChatLEntries[domElemId][i][4]]);    TDLChatGShowEntries(domElemId,ce,userLastVisit());//    if (entries.length<TDLChatMaxEntries)//        TDLChatGNoMore(domElemId);}function TDLChatLAEWSResult(domElemId,entries){    //TODO: remove arrayJoin    TDLChatLEntries[domElemId]=arrayJoin(TDLChatLEntries[domElemId],entries);    var ce=[];    for (var i=0;i<entries.length;i++)        ce.push([entries[i][1],entries[i][2],entries[i][0],entries[i][3],entries[i][4]]);    TDLChatGShowEntries(domElemId,ce,userLastVisit(),true);    if (entries.length<TDLChatMaxEntries)        TDLChatGNoMore(domElemId);}function TDLChatLMoreHandler(domElemId){    var ca=TDLChatLEntries[domElemId];    TDLChatLLoadAppend(domElemId,(ca.length>0)?ca[ca.length-1][0]:0);}function TDLChatLGetId(dbId){    if (docEl(TDLChatLIdPrefix+dbId)) return TDLChatLIdPrefix+dbId;    return false;}function TDLChatForumToggleHandler(elem){    var entryBox=domGetFirstRoot(elem,"entryBox");    var dbId=entryBox.getAttribute("id").substring(TDLChatLEntryIdPrefix.length);    var toSelect=!domClassNameTest(entryBox,"selected");    if (toSelect)     {        var ebCh=domGetAllChildren(domGetFirstRoot(entryBox,"entries"),"entryBox");        for (var c in ebCh)         {            domClassNameRemove(ebCh[c],"selected");            //close all other chats (get db id -> get id -> stop)            TDLChatLStop(TDLChatLGetId(ebCh[c].getAttribute("id").substring(TDLChatLEntryIdPrefix.length)));        }    }    domClassNameSwitch(entryBox,"selected",toSelect)    var cId=TDLChatLGetId(dbId);    if (cId)    {        if (toSelect) TDLChatLLoad(cId,false,true); //restart TO        else TDLChatLStop(cId);        return;    }    //here always selected    var threadChat=TDLChatInit(entryBox.getAttribute("id"),dbId,null,false,false);} var TDLChatForumToggleAutoOpenTO=null;function TDLChatForumToggleAutoOpen(domParentId,num) //auto open forum subchat after submit (and return to page with #param){    num=num||1;    if (TDLChatForumToggleAutoOpenTO!=null) clearTimeout(TDLChatForumToggleAutoOpenTO);    if (docEl(domParentId))    {        //test other selected and click        var entries=domGetFirstRoot(docEl(domParentId),"entries");        if (!entries) return;        var ebCh=domGetAllChildren(entries,"entryBox");        for (var c in ebCh)             if (domClassNameTest(ebCh[c],"selected")) return;        elemClick(domGetFirstChild(docEl(domParentId),"entry"));    }    else        if (num<30) //15 seconds of try            TDLChatForumToggleAutoOpenTO=setTimeout("TDLChatForumToggleAutoOpen('"+domParentId+"',"+num+1+");",500);}/* chat load *//***** LOGIC *****//***** GUI *****/var TDLChatGTexts=[];var TDLChatGOnclick=[];var TDLChatGAdditionalStyle=[];var TDLChatGBodyMoreLen=50;//generates chat structure with classes//#TDLChat.loading[|.loaded|.writing|.sending/.nomore/.emptyOr1](.input(.submitHidden,.message,.sigSub(.submit,.sign)),.sendingAnim(.anim),.entries{.entry[.new/.first](.info(.sign,.date),.body)},.loadingAnim(.anim),.navi(.less,.more))function TDLChatGGenerate(elemId,domParentId,dbParentEntryId,action,returnUrl,signature,collapsed,texts,onclickHandler,additionalStyle){          TDLChatGTexts[elemId]=texts||TDLChatGTextsENChat;    TDLChatGOnclick[elemId]=onclickHandler||null;    TDLChatGAdditionalStyle[elemId]=additionalStyle||null;        	var chatI='		<div class="input">'+              '     	<form action="'+action+'" method="post" onsubmit="return TDLChatGSubmit(this);">'+              '         	<input type="submit" class="submitHidden"/>'+              '         	<input type="hidden" name="returnUrl" value="'+returnUrl+'"/>'+              '             <input type="hidden" name="parentId" value="'+dbParentEntryId+'"/>'+              '             <div class="message"><textarea onkeypress="return TDLChatGInputTAKeyup(event,this);" onfocus="textSelectAllFirst(this)" name="body" rows="1">'+TDLChatGTexts[elemId]['message']+'</textarea></div>'+              '             <div class="sigSub">'+              '             	<div onclick="TDLChatGSubmitClick(this)" class="submit">'+TDLChatGTexts[elemId]['submit']+'</div>'+              '                 <input class="sign" name="signature" onkeypress="return TDLChatGInputSKp(event,this);" type="text" onfocus="this.select();" value="'+(signature?signature:TDLChatGTexts[elemId]['signature'])+'"/>'+              '             </div>'+              '         </form>'+              '     </div>'+              '     <div class="sendingAnim" align="center"><div class="anim"></div>'+TDLChatGTexts[elemId]['wait']+'</div>'+              '     <div class="entries"></div>'+              '     <div class="loadingAnim" align="center"><div class="anim"></div>'+TDLChatGTexts[elemId]['wait']+'</div>'+              '     <div class="navi">'+			  '			<a href="#" onclick="TDLChatGLess(this);return event.returnValue=false;" class="less">'+TDLChatGTexts[elemId]['less']+'</a>&nbsp;'+			  '			<a href="#" onclick="TDLChatGMore(this);return event.returnValue=false;" class="more">'+TDLChatGTexts[elemId]['more']+'</a>'+              '     </div>';	domAppendChild(docEl(domParentId),"div",elemId,"TDLChat loading"+(collapsed?" collapsed":""),chatI);    if (TDLChatGAdditionalStyle[elemId])        domClassNameAddTree(docEl(elemId),TDLChatGAdditionalStyle[elemId]);}var TDLChatGMoreHandler=null; //used internally -> Logicfunction TDLChatGMore(elem){    var chat=domGetFirstRoot(elem,"TDLChat");	if (!domClassNameRemove(chat,"collapsed"))	{        domClassNameAdd(chat,"loading")        TDLChatGMoreHandler(chat.getAttribute("id"));	}}function TDLChatGLess(elem){	domClassNameAdd(domGetFirstRoot(elem,"TDLChat"),"collapsed")}//TODO: show this handler to user (to allow additional validation)var TDLChatGSubmitHandler=null;function TDLChatGSubmit(form){        var eId=domGetFirstRoot(form,'TDLChat').getAttribute("id");    if (!textNoEmptyAlertElem(form['body'],TDLChatGTexts[eId]['noempty'],TDLChatGTexts[eId]['message']))        return false;        var bod=textTrim(form['body'].value);    var sig=textTrim(form['signature'].value);	if (sig.length>50) sig=sig.substring(0,50);	if (bod.length>3000) bod=bod.substring(0,3000);	if (sig==TDLChatGTexts[eId]['signature']) sig="";    form['body'].value=bod;    form['signature'].value=sig;        if (bod.indexOf("http")>=0)    {        alert(TDLChatGTexts[eId]['nohttp']);        return false;    }    if (sig.indexOf("http")>=0)    {        alert(TDLChatGTexts[eId]['nowww']);        return false;    }    if (!sig) cookieSet("TDLChatSign","","",0);    else cookieSet("TDLChatSign",sig,"",13);            if (TDLChatGSubmitHandler!=null)        if (!TDLChatGSubmitHandler(bod,sig)) return false;    var c=domGetFirstRoot(form,"TDLChat");    domClassNameRemove(c,"writing");    domClassNameAdd(c,"sending");    return true;}function TDLChatGSubmitClick(elem){        var formElem=elem.parentNode.parentNode;    elemClick(domGetFirstChild(formElem,"submitHidden"));}function TDLChatGInputTAKeyup(e,elem){    if (e.stopPropagation) e.stopPropagation();    else e.cancelBubble=true;    textFieldLimit(elem,3000);    	domClassNameAdd(domGetFirstRoot(elem,"TDLChat"),"writing");	textareaAutoResize(elem,1,true);            return true;    }function TDLChatGInputSKp(e,elem){    if (e.stopPropagation) e.stopPropagation();    else e.cancelBubble=true;    textFieldLimit(elem,50);            return true;    }//entries=[[entrybody,entrysign,entrySec,entryDBId,entryChildren],[entry2body,...],...]function TDLChatGShowEntries(elemId,entries,lastVisitSec,appendMode){	var pr=docEl(elemId);    var as="";    if (TDLChatGAdditionalStyle[elemId]) as=TDLChatGAdditionalStyle[elemId]+" ";    	for (var ci=0;ci<pr.childNodes.length;ci++)	{		var ch=pr.childNodes[ci];		if (domClassNameTest(ch,"entries"))		{            //TODO:insert at begin mode (and don't removeAll!) [chat version or auto update forum]            if (!appendMode)                domRemoveAllChildren(ch);			for (var j=0;j<entries.length;j++)			{                var entryBox=domCreateElement("div",TDLChatLEntryIdPrefix+entries[j][3],as+"entryBox"+(!appendMode && j==0?" first":""),"");				var entry=null;                if (lastVisitSec && 1*entries[j][2]>lastVisitSec)                    entry=domCreateElement("div","",as+"entry new"+(TDLChatGOnclick[elemId]?" clickable":""),"");                else                    entry=domCreateElement("div","",as+"entry"+(TDLChatGOnclick[elemId]?" clickable":""),"");                if (TDLChatGOnclick[elemId])                    entry.onclick=function(){TDLChatGOnclick[domGetFirstRoot(this,"TDLChat").getAttribute("id")](this);};				var info=domCreateElement("div","",as+"info","");				domAppendChild(info,"span","",as+"childrenNum",TDLChatGTexts[elemId]['childrenNum']+entries[j][4]);				domAppendChild(info,"span","",as+"sign",(entries[j][1] || TDLChatGTexts[elemId]['anonymous']));                var d=new Date(entries[j][2]*1000.0);            				domAppendChild(info,"span","",as+"date",dateDateString(d,true)+" "+dateTimeString(d,true));				entry.appendChild(info);                domAppendChild(entry,"div","",as+"body",textNLtoBR(entries[j][0]));                entryBox.appendChild(entry);				ch.appendChild(entryBox);			}		}	}	domClassNameRemove(pr,"loading");    if (!appendMode)        domClassNameSwitch(pr,"emptyOr1",entries.length==0 || entries.length==1);}function TDLChatGNoMore(elemId){    domClassNameAdd(docEl(elemId),"noMore");}/* CHAT *//***** GUI *****//***** GUI Texts *****/var TDLChatGTextsENChat={   "message":"Enter comment here...",                            "signature":"Signature...",                            "submit":"send",                            "wait":"Please wait...",                            "less":".less <<",                            "more":".more entries >>",                            "noempty":"Comment cannot be empty..",                            "nohttp":"Enter www address without 'http://'",                            "nowww":"Www address is not allowed in here",                            "childrenNum":"",                            "anonymous":"Anonymous"};var TDLChatGTextsPLChat={   "message":"Tutaj wpisz komentarz...",                            "signature":"Podpis...",                            "submit":"dodaj",                            "wait":"Proszę czekać...",                            "less":".zwiń <<",                            "more":".więcej wpisów >>",                            "noempty":"Komentarz nie może być pusty..",                            "nohttp":"Adresy www wpisuj bez 'http://'",                            "nowww":"Adresy www nie są tutaj dozwolone",                            "childrenNum":"",                            "anonymous":"Anonim"};var TDLChatGTextsPLForum={  "message":"Tutaj wpisz treść nowego wątku...",                            "signature":"Podpis...",                            "submit":"dodaj",                            "wait":"Proszę czekać...",                            "less":"[zwiń]",                            "more":"[więcej tematów]",                            "noempty":"Treść wątku nie może być pusta..",                            "nohttp":"Adresy www wpisuj bez 'http://'",                            "nowww":"Adresy www nie są tutaj dozwolone",                            "childrenNum":"komentarzy: ",                            "anonymous":"Anonim"};/***** GUI *****//***** INIT *****///signature: by default from cookie "TDLChatSign"//onclickHandler: by default no Onclick//collapsed: by default true or false in case when url=...#domParentId//forumTexts: by default false (= chat texts)//additionalStyle: style applicated to TDLChat and it's every children//function TDLChatInit(domParentId,dbId,signature,onclickHandler,collapsed,forumTexts,additionalStyle,noRefresh)function TDLChatInit(domParentId,dbId,signature,collapsed,isForum){    TDLChatGMoreHandler=TDLChatLMoreHandler;    var chatId=TDLChatLIdPrefix+dbId;    var col=(typeof collapsed!="undefined"&&collapsed!=null?collapsed:documentLocationParams()["#"]!=domParentId);      TDLChatGGenerate(chatId,domParentId,dbId,TDLChatLScriptHost+"/"+TDLChatLScriptPostName,documentLocation(true,true,true)+"#"+domParentId,signature||cookieGet("TDLChatSign"),col,TDLChatGTextsENChat,                             isForum?TDLChatForumToggleHandler:null,isForum?"f":"c");//    TDLChatGGenerate(chatId,domParentId,dbId,TDLChatLScriptHost+"/"+TDLChatLScriptPostName,documentLocation(true,true,true)+"#"+domParentId,signature||cookieGet("TDLChatSign"),col,isForum?TDLChatGTextsPLForum:TDLChatGTextsPLChat,isForum?TDLChatForumToggleHandler:null,isForum?"f":"c");    TDLChatLInit(dbId,chatId,false,false,isForum);    if (isForum && documentLocationParams()["#"])        TDLChatForumToggleAutoOpen(documentLocationParams()["#"]);    return chatId;}
