source: sandbox/jabberit_messenger/trophy_expresso/js/trophyim.js @ 2863

Revision 2863, 58.9 KB checked in by alexandrecorreia, 14 years ago (diff)

Ticket #986 - [ FEITO POR Emmanuel Ferro SERPRO ] Internacionalizacao, criado o arquivo i18n_pt_BR

  • Property svn:executable set to *
Line 
1/**
2 *   This program is distributed under the terms of the MIT license.
3 *   Please see the LICENSE file for details.
4 *
5 *   Copyright 2008 Michael Garvin
6 */
7
8var TROPHYIM_BOSH_SERVICE       = "/proxy/ejabberd";  //Change to suit
9
10var TROPHYIM_LOG_LINES          = 200;
11
12var TROPHYIM_LOGLEVEL           = 0; //0=debug, 1=info, 2=warn, 3=error, 4=fatal
13
14var TROPHYIM_VERSION            = "0.3";
15
16var TROPHYIM_RESOURCE           = "/JABBERITWEB";
17
18//Uncomment to make session reattachment work
19//var TROPHYIM_JSON_STORE = "json_store.php";
20
21/** Object: DOMObjects
22 *  This class contains builders for all the DOM objects needed by TrophyIM
23 */
24DOMObjects = {
25    /** Function: xmlParse
26     *  Cross-browser alternative to using innerHTML
27     *  Parses given string, returns valid DOM HTML object
28     *
29     *  Parameters:
30     *    (String) xml - the xml string to parse
31     */
32    xmlParse : function(xmlString) {
33        var xmlObj = this.xmlRender(xmlString);
34        if(xmlObj) {
35            try { //Firefox, Gecko, etc
36                if (this.processor == undefined) {
37                    this.processor = new XSLTProcessor();
38                    this.processor.importStylesheet(this.xmlRender(
39                    '<xsl:stylesheet version="1.0"\
40                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\
41                    <xsl:output method="html" indent="yes"/><xsl:template\
42                    match="@*|node()"><xsl:copy><xsl:copy-of\
43                    select="@*|node()"/></xsl:copy></xsl:template>\
44                    </xsl:stylesheet>'));
45                }
46                var htmlObj =
47                this.processor.transformToDocument(xmlObj).documentElement;
48                //Safari has a quirk where it wraps dom elements in <html><body>
49                if (htmlObj.tagName.toLowerCase() == 'html') {
50                    htmlObj = htmlObj.firstChild.firstChild;
51                }
52                return document.importNode(htmlObj, true);
53            } catch(e) {
54                try { //IE is so very very special
55                    var htmlObj = document.importNode(xmlObj.documentElement, true);
56                    if (htmlObj.tagName.toLowerCase() == "div") {
57                        var div_wrapper = document.createElement('div');
58                        div_wrapper.appendChild(htmlObj);
59                        if(div_wrapper.innerHTML) {
60                            div_wrapper.innerHTML = div_wrapper.innerHTML;
61                        }
62                        htmlObj = div_wrapper.firstChild;
63                    }
64                    return htmlObj;
65                } catch(e) {
66                    alert("TrophyIM Error: Cannot add html to page " + e.message);
67                }
68            }
69        }
70    },
71    /** Function: xmlRender
72     *  Uses browser-specific methods to turn given string into xml object
73     *
74     *  Parameters:
75     *    (String) xml - the xml string to parse
76     */
77    xmlRender : function(xmlString) {
78        try {//IE
79            var renderObj = new ActiveXObject("Microsoft.XMLDOM");
80            renderObj.async="false";
81            if(xmlString) {
82                renderObj.loadXML(xmlString);
83            }
84        } catch (e) {
85            try { //Firefox, Gecko, etc
86                if (this.parser == undefined) {
87                    this.parser = new DOMParser();
88                }
89                var renderObj = this.parser.parseFromString(xmlString,
90                "application/xml");
91            } catch(e) {
92                alert("TrophyIM Error: Cannot create new html for page");
93            }
94        }
95
96        return renderObj;
97    },
98    /** Function: getHTML
99     *  Returns named HTML snippet as DOM object
100     *
101     *  Parameters:
102     *    (String) name - name of HTML snippet to retrieve (see HTMLSnippets
103     *    object)
104     */
105    getHTML : function(page)
106        {
107        return this.xmlParse(HTMLSnippets[page]);
108    },
109       
110    /** Function: getScript
111     *  Returns script object with src to given script
112     *
113     *  Parameters:
114     *    (String) script - name of script to put in src attribute of script
115     *    element
116     */
117    getScript : function(script)
118        {
119        var newscript = document.createElement('script');
120        newscript.setAttribute('src', script);
121        newscript.setAttribute('type', 'text/javascript');
122        return newscript;
123    }
124};
125
126/** Object: TrophyIM
127 *
128 *  This is the actual TrophyIM application.  It searches for the
129 *  'trophyimclient' element and inserts itself into that.
130 */
131TrophyIM = {
132   
133        /** AutoConnection
134         *
135         */     
136               
137        autoConnection : { connect : true },
138
139        /** Object: chatHistory
140    *
141    *  Stores chat history (last 10 message) and current presence of active
142    *  chat tabs.  Indexed by jid.
143    */
144       
145        chatHistory : {},
146       
147        /** Constants:
148    *
149    *    (Boolean) stale_roster - roster is stale and needs to be rewritten.
150    */
151       
152        constants : {stale_roster: false},
153       
154        /** PosWindow
155         *
156         */     
157        posWindow : { left : 400, top : 100 }, 
158               
159        /** StatusConnection
160         *
161         */
162
163        statusConn : { connected : false },
164       
165        /** TimeOut Render Roster
166         *
167         *
168         */
169       
170        _timeOut : { renderRoster : null },
171       
172     /** Function: setCookie
173     *
174     *  Sets cookie name/value pair.  Date and path are auto-selected.
175     *
176     *  Parameters:
177     *    (String) name - the name of the cookie variable
178     *    (String) value - the value of the cookie variable
179     */
180   
181        setCookie : function(name, value)
182        {
183        var expire = new Date();
184        expire.setDate(expire.getDate() + 365);
185        document.cookie = name + "=" + value + "; expires=" + expire.toGMTString();
186    },
187   
188        /** Function: delCookie
189     *
190     *  Deletes cookie
191     *
192     *  Parameters:
193     *    (String) name) - the name of the cookie to delete
194     */
195   
196        delCookie : function(name)
197        {
198        var expire = new Date();
199        expire.setDate(expire.getDate() - 365);
200        document.cookie = name + "= ; expires=" + expire.toGMTString();
201        delete TrophyIM.cookies[name];
202    },
203   
204        /** Function: getCookies
205     *
206     *  Retrieves all trophyim cookies into an indexed object.  Inteneded to be
207     *  called once, at which time the app refers to the returned object instead
208     *  of re-parsing the cookie string every time.
209     *
210     *  Each cookie is also re-applied so as to refresh the expiry date.
211     */
212   
213        getCookies : function()
214        {
215        var cObj = {};
216        var cookies = document.cookie.split(';');
217       
218        for(var i = 0 ; i < cookies.length; i++ )
219        {
220                while ( cookies[i].charAt(0) == ' ')
221            {
222                cookies[i] = cookies[i].substring(1,cookies[i].length);
223            }
224               
225            if (cookies[i].substr(0, 8) == "trophyim")
226            {
227                var nvpair = cookies[i].split("=", 2);
228                cObj[nvpair[0]] = nvpair[1];
229                TrophyIM.setCookie(nvpair[0], nvpair[1]);
230            }
231        }
232       
233        return cObj;
234    },
235       
236    /** Function: load
237     *
238     *  This function searches for the trophyimclient div and loads the client
239     *  into it.
240     */
241
242        load : function()
243        {
244        if( loadscript.getUserCurrent() == null )
245        {
246                loadscript.setUserCurrent();     
247        }       
248
249        if ( !TrophyIM.statusConn.connected )
250                {
251                        TrophyIM.cookies = TrophyIM.getCookies();
252
253                        //Wait a second to give scripts time to load
254                        setTimeout( "TrophyIM.showLogin()", 550 );
255                }
256                else
257                {
258                        loadscript.rosterDiv();
259                }
260   },
261
262   /** Function: storeData
263     *
264     *  Store all our data in the JSONStore, if it is active
265     */
266     
267   storeData : function()
268   {
269        if ( TrophyIM.connection && TrophyIM.connection.connected )
270                {
271            TrophyIM.setCookie('trophyim_bosh_xid', TrophyIM.connection.jid + "|" +
272            TrophyIM.connection.sid + "|" +  TrophyIM.connection.rid);
273            TrophyIM.rosterObj.save();
274        }
275    },
276   
277    /**  Function: showlogin
278     *
279     *   This function clears out the IM box and either redisplays the login
280     *   page, or re-attaches to Strophe, preserving the logging div if it
281     *   exists, or creating a new one of we are re-attaching.
282     */
283     
284    showLogin : function()
285        {
286        /**
287         *
288         * JSON is the last script to load, so we wait on it
289                 * Added Strophe check too because of bug where it's sometimes missing
290                 *
291                 */
292
293                if ( typeof(JSON) != undefined && typeof(Strophe) != undefined )
294        {
295                TrophyIM.JSONStore = new TrophyIMJSONStore();
296               
297                        if ( TrophyIM.JSONStore.store_working && TrophyIM.cookies['trophyim_bosh_xid'] )
298            {
299                var xids = TrophyIM.cookies['trophyim_bosh_xid'].split("|");
300                TrophyIM.delCookie('trophyim_bosh_xid');
301                TrophyIM.constants.stale_roster = true;
302                       
303                                TrophyIM.connection                             = new Strophe.Connection(TROPHYIM_BOSH_SERVICE);
304                TrophyIM.connection.rawInput    = TrophyIM.rawInput;
305                TrophyIM.connection.rawOutput   = TrophyIM.rawOutput;
306                Strophe.log = TrophyIM.log;
307                Strophe.info('Attempting Strophe attach.');
308                TrophyIM.connection.attach(xids[0], xids[1], xids[2], TrophyIM.onConnect);
309                TrophyIM.onConnect(Strophe.Status.CONNECTED);
310            }
311            else
312            {
313                // List Contact
314                                loadscript.rosterDiv();
315                               
316                                // Get User Current;
317                                var _getUserCurrent = loadscript.getUserCurrent();
318                               
319                                setTimeout(function()
320                                {
321                                        if ( _getUserCurrent != null )
322                                                TrophyIM.login( Base64.decode( _getUserCurrent.jid ), Base64.decode( _getUserCurrent.password ));
323                                        else
324                                                loadscript.loginPage();
325                                }, 200);
326            }
327        }
328        else
329        {
330                setTimeout("TrophyIM.showLogin()", 500);
331        }
332    },
333   
334        /** Function: log
335     *
336     *  This function logs the given message in the trophyimlog div
337     *
338     *  Parameter: (String) msg - the message to log
339     */
340   
341    log : function(level, msg)
342    {
343        if (TrophyIM.logging_div && level >= TROPHYIM_LOGLEVEL) {
344            while(TrophyIM.logging_div.childNodes.length > TROPHYIM_LOG_LINES) {
345                TrophyIM.logging_div.removeChild(
346                TrophyIM.logging_div.firstChild);
347            }
348            var msg_div = document.createElement('div');
349            msg_div.className = 'trophyimlogitem';
350            msg_div.appendChild(document.createTextNode(msg));
351            TrophyIM.logging_div.appendChild(msg_div);
352            TrophyIM.logging_div.scrollTop = TrophyIM.logging_div.scrollHeight;
353        }
354    },
355       
356    /** Function: rawInput
357     *
358     *  This logs the packets actually recieved by strophe at the debug level
359     */
360    rawInput : function (data)
361        {
362        Strophe.debug("RECV: " + data);
363    },
364       
365    /** Function: rawInput
366     *
367     *  This logs the packets actually recieved by strophe at the debug level
368     */
369    rawOutput : function (data)
370        {
371        Strophe.debug("SEND: " + data);
372    },
373       
374    /** Function: login
375     *
376     *  This function logs into server using information given on login page.
377     *  Since the login page is where the logging checkbox is, it makes or
378     *  removes the logging div and cookie accordingly.
379     *
380     */
381    login : function()
382        {
383                if ( TrophyIM.JSONStore.store_working )
384                {
385                   //In case they never logged out
386            TrophyIM.JSONStore.delData(['groups','roster', 'active_chat', 'chat_history']);
387        }
388
389                TrophyIM.connection                             = new Strophe.Connection(TROPHYIM_BOSH_SERVICE);
390        TrophyIM.connection.rawInput    = TrophyIM.rawInput;
391        TrophyIM.connection.rawOutput   = TrophyIM.rawOutput;
392        Strophe.log                                     = TrophyIM.log;
393       
394                if ( arguments.length > 0 )
395                {
396                        var barejid = arguments[0];
397                        var password = arguments[1];
398                       
399                        TrophyIM.connection.connect( barejid + TROPHYIM_RESOURCE, password, TrophyIM.onConnect );
400                }
401                else
402                {
403                       
404                        var barejid             = document.getElementById('trophyimjid').value
405                        var fulljid             = barejid + TROPHYIM_RESOURCE;
406                        var password    = document.getElementById('trophyimpass').value;
407                        var button              = document.getElementById('trophyimconnect');
408                       
409                        loadscript.setUserCurrent( barejid, password);
410                       
411                        if ( button.value == 'connect' )
412                        {
413                                button.value = 'disconnect';
414                                //TrophyIM.connection.connect( fulljid , password, TrophyIM.onConnect );
415                               
416                                TrophyIM.login( barejid, password );
417                                _winBuild('window_login_page', 'remove');
418                        }
419                }
420
421                TrophyIM.setCookie('trophyimjid', barejid);
422    },
423       
424    /** Function: logout
425     *
426     *  Logs into fresh session through Strophe, purging any old data.
427     */
428    logout : function()
429        {
430        TrophyIM.autoConnection.connect = false;
431       
432        TrophyIM.delCookie('trophyim_bosh_xid');
433       
434        delete TrophyIM['cookies']['trophyim_bosh_xid'];
435       
436        TrophyIM.connection.disconnect();
437    },
438       
439    /** Function onConnect
440     *
441     *  Callback given to Strophe upon connection to BOSH proxy.
442     */
443    onConnect : function(status)
444        {
445        var loading_gif = document.getElementById("JabberIMRosterLoadingGif");
446               
447        if( status == Strophe.Status.CONNECTING )
448                {
449                loading_gif.style.display = "block";
450                Strophe.info('Strophe is connecting.');
451        }
452               
453                if( status == Strophe.Status.CONNFAIL )
454                {
455                        TrophyIM.delCookie('trophyim_bosh_xid');
456            TrophyIM.statusConn.connected = false;
457            loading_gif.style.display = "block";
458        }
459               
460                if( status == Strophe.Status.DISCONNECTING )
461                {
462                        TrophyIM.statusConn.connected = false;
463        }
464               
465                if( status == Strophe.Status.DISCONNECTED )
466                {
467                        if( TrophyIM.autoConnection.connect )
468                        {
469                                loading_gif.style.display = "block";
470                               
471                                TrophyIM.delCookie('trophyim_bosh_xid');
472                   
473                    TrophyIM.statusConn.connected = false;
474                   
475                                setTimeout(function()
476                                {
477                            TrophyIM.showLogin();
478                           
479                                },10000);
480                               
481                    loadscript.clrAllContacts();       
482                   
483                    loadscript.setStatusJabber(i18n.STATUS_ANAVAILABLE,"unavailable");
484                   
485                    delete TrophyIM.rosterObj.roster;
486                    delete TrophyIM.rosterObj.groups;
487                        }
488        }
489               
490                if( status == Strophe.Status.CONNECTED )
491                {
492                        loadscript.setStatusJabber(i18n.STATUS_AVAILABLE,'available');
493                        TrophyIM.statusConn.connected = true;
494            TrophyIM.showClient();
495        }
496    },
497
498    /** Function: showClient
499     *
500     *  This clears out the main div and puts in the main client.  It also
501     *  registers all the handlers for Strophe to call in the client.
502     */
503    showClient : function()
504        {
505        TrophyIM.setCookie('trophyim_bosh_xid', TrophyIM.connection.jid + "|" +
506        TrophyIM.connection.sid + "|" +  TrophyIM.connection.rid);
507               
508        TrophyIM.rosterObj = new TrophyIMRoster();
509        TrophyIM.connection.addHandler(TrophyIM.onVersion, Strophe.NS.VERSION, 'iq', null, null, null);
510        TrophyIM.connection.addHandler(TrophyIM.onRoster, Strophe.NS.ROSTER, 'iq', null, null, null);
511        TrophyIM.connection.addHandler(TrophyIM.onPresence, null, 'presence', null, null, null);
512        TrophyIM.connection.addHandler(TrophyIM.onMessage, null, 'message', null, null,  null);
513       
514                //Get roster then announce presence.
515        TrophyIM.connection.send($iq({type: 'get', xmlns: Strophe.NS.CLIENT}).c('query', {xmlns: Strophe.NS.ROSTER}).tree());
516        TrophyIM.connection.send($pres().tree());
517                setTimeout( TrophyIM.renderRoster, 1000);
518    },
519       
520    /** Function: clearClient
521     *
522     *  Clears out client div, preserving and returning existing logging_div if
523     *  one exists
524     */
525     
526    clearClient : function()
527    {
528        if(TrophyIM.logging_div)
529        {
530            var logging_div = TrophyIM.client_div.removeChild(document.getElementById('trophyimlog'));
531        }
532        else
533        {
534            var logging_div = null;
535        }
536       
537        while(TrophyIM.client_div.childNodes.length > 0)
538        {
539            TrophyIM.client_div.removeChild(TrophyIM.client_div.firstChild);
540        }
541       
542        return logging_div;
543    },
544   
545    /** Function: onVersion
546     *
547     *  jabber:iq:version query handler
548     */
549     
550    onVersion : function(msg)
551    {
552        Strophe.debug("Version handler");
553        if (msg.getAttribute('type') == 'get')
554        {
555            var from = msg.getAttribute('from');
556            var to = msg.getAttribute('to');
557            var id = msg.getAttribute('id');
558            var reply = $iq({type: 'result', to: from, from: to, id: id}).c('query',
559            {name: "TrophyIM", version: TROPHYIM_VERSION, os:
560            "Javascript-capable browser"});
561            TrophyIM.connection.send(reply.tree());
562        }
563        return true;
564    },
565   
566    /** Function: onRoster
567     *
568     *  Roster iq handler
569     */
570   
571    onRoster : function(msg)
572        {
573        var roster_items = msg.firstChild.getElementsByTagName('item');
574               
575                for (var i = 0; i < roster_items.length; i++)
576                {
577                        with(roster_items[i])
578                        {
579                                var groups              = getElementsByTagName('group');       
580                                var group_array = [];
581                               
582                                for( var g = 0 ; g < groups.length; g++ )
583                                {
584                                        if( groups[g].hasChildNodes() )
585                                                group_array[group_array.length] = groups[g].firstChild.nodeValue;
586                                }
587
588                                if( getAttribute('ask') )
589                                        TrophyIM.rosterObj.addContact(getAttribute('jid'), getAttribute('ask'), getAttribute('name'), group_array);
590                                else
591                                        TrophyIM.rosterObj.addContact(getAttribute('jid'), getAttribute('subscription'), getAttribute('name'), group_array);
592                        }
593        }
594
595                if ( msg.getAttribute('type') == 'set' )
596                {
597                        var _iq = $iq({type: 'reply', id: msg.getAttribute('id'), to: msg.getAttribute('from')});
598                        TrophyIM.connection.send( _iq.tree());
599        }
600       
601                return true;
602    },
603    /** Function: onPresence
604     *
605     *  Presence handler
606     */
607    onPresence : function(msg)
608        {
609                Strophe.debug("Presence handler");
610        var type                = msg.getAttribute('type') ? msg.getAttribute('type') : 'available';
611        var show                = msg.getElementsByTagName('show').length ? Strophe.getText(msg.getElementsByTagName('show')[0]) : type;
612        var status              = msg.getElementsByTagName('status').length ? Strophe.getText(msg.getElementsByTagName('status')[0]) : '';
613        var priority    = msg.getElementsByTagName('priority').length ? parseInt(Strophe.getText(msg.getElementsByTagName('priority')[0])) : 0;
614
615        TrophyIM.rosterObj.setPresence(msg.getAttribute('from'), priority, show, status);
616               
617        return true;
618    },
619   
620    /** Function: onMessage
621     *
622     *  Message handler
623     */
624    onMessage : function(msg)
625    {
626        var checkTime = function(i)
627        {
628                if ( i < 10 ) i= "0" + i;
629               
630                return i;
631        };
632       
633                var messageDate = function( _date )
634                {
635                        var _dt = _date.substr( 0, _date.indexOf( 'T' ) ).split( '-' );
636                        var _hr = _date.substr( _date.indexOf( 'T' ) + 1, _date.length - _date.indexOf( 'T' ) - 2 ).split( ':' );
637                       
638                        ( _date = new Date ).setTime( Date.UTC( _dt[0], _dt[1] - 1, _dt[2], _hr[0], _hr[1], _hr[2] ) );
639
640                        return ( _date.toLocaleDateString( ).replace( /-/g, '/' ) + ' ' + _date.toLocaleTimeString( ) );
641                };
642
643        var data        = new Date();
644        var dtNow       = checkTime(data.getHours()) + ":" + checkTime(data.getMinutes()) + ":" + checkTime(data.getSeconds());
645       
646        var from        = msg.getAttribute('from');
647        var type        = msg.getAttribute('type');
648        var elems       = msg.getElementsByTagName('body');
649        var delay       = ( msg.getElementsByTagName('delay') ) ? msg.getElementsByTagName('delay') : null;
650        var stamp       = ( delay[0] != null ) ? "<font style='color:red;'>" + messageDate(delay[0].getAttribute('stamp')) + "</font>" :  dtNow;
651
652                var barejid             = Strophe.getBareJidFromJid(from);
653                var jid_lower   = barejid.toLowerCase();
654                var contact             = "";
655                var state               = "";
656
657                var chatBox     = document.getElementById(jid_lower + "__chatState");
658                var chatStateOnOff = null;
659                var active      = msg.getElementsByTagName('active');
660               
661                contact = barejid.toLowerCase();
662                contact = contact.substring(0, contact.indexOf('@'));
663           
664                if( TrophyIM.rosterObj.roster[barejid] )
665                {
666                        if( TrophyIM.rosterObj.roster[barejid.toLowerCase()]['contact']['name'] )
667                        {
668                                contact = TrophyIM.rosterObj.roster[barejid.toLowerCase()]['contact']['name'];
669                        }
670                }
671
672                // Message with body are "content message", this means state active
673                if ( elems.length > 0 )
674                {
675                        state = "";
676                        // Set notify chat state capability on when sender notify it themself
677                        chatStateOnOff = document.getElementById(jid_lower + "__chatStateOnOff");
678                        if (active.length > 0 & chatStateOnOff != null )
679                        {
680                                chatStateOnOff.value = 'on';
681                        }
682
683                        if (type == 'chat' || type == 'normal')
684                        {
685                                var _message = document.createElement("div");
686                                _message.innerHTML = Strophe.getText(elems[0]);
687                               
688                                var scripts = _message.getElementsByTagName('script');
689                               
690                                for (var i = 0; i < scripts.length; i++)
691                                        _message.removeChild(scripts[i--]);
692                               
693                                _message.innerHTML = _message.innerHTML.replace(/^\s+|\s+$|^\n|\n$/g, "");
694                               
695                                // Get Smiles
696                                _message.innerHTML = loadscript.getSmiles( _message.innerHTML );
697                               
698                                if ( _message.hasChildNodes() )
699                                {
700                                        var message =
701                                        {
702                                contact : "[" + stamp + "] <font style='font-weight:bold; color:black;'>" + contact + "</font>",
703                                msg             : "</br>" + _message.innerHTML
704                        };
705                                       
706                                        TrophyIM.addMessage( TrophyIM.makeChat( from ), jid_lower, message );
707                                }
708                        }
709                }
710                // Message without body are "content message", this mean state is not active
711                else
712                {
713                        if( chatBox != null )
714                                state = TrophyIM.getChatState(msg);                     
715                }
716               
717                // Clean chat status message some time later           
718                var clearChatState = function(){
719                        chatBox.innerHTML='';
720                }
721               
722                if (chatBox != null)
723                {
724                        var clearChatStateTimer;
725                       
726                        chatBox.innerHTML = "<font style='font-weight:bold; color:grey; float:right;'>" + state + "</font>";
727                       
728                        var _composing =  msg.getElementsByTagName('composing');
729                       
730                        if ( _composing.length == 0 )
731                               
732                                clearChatStateTimer = setTimeout(clearChatState, 2000);
733                        else
734                                clearTimeout(clearChatStateTimer);                     
735                }
736
737                return true;
738        },
739
740        /** Function: getChatState
741         *
742         *  Parameters:
743         *    (string) msg - the message to get chat state
744         *    (string) jid - the jid of chat box to update the chat state to.
745         */
746        getChatState : function(msg)
747        {
748                var     state =  msg.getElementsByTagName('inactive');
749               
750                if ( state.length > 0 )
751                {
752                return i18n.INACTIVE;
753                }
754                else
755                {
756                state = msg.getElementsByTagName('gone');
757            if ( state.length > 0 )
758            {
759                return i18n.GONE;
760                        }
761            else
762            {
763                state = msg.getElementsByTagName('composing');
764                if ( state.length > 0 )
765                {
766                        return i18n.COMPOSING;
767                                }
768                else
769                {
770                        state =  msg.getElementsByTagName('paused');
771                        if ( state.length > 0 )
772                        {
773                                return i18n.PAUSED;
774                                        }
775                                }
776                        }
777                }
778               
779                return '';
780        },
781
782   
783    /** Function: makeChat
784     *
785     *  Make sure chat window to given fulljid exists, switching chat context to
786     *  given resource.
787     */
788     
789    makeChat : function(fulljid)
790    {
791        var barejid             = Strophe.getBareJidFromJid(fulljid);
792        var titleWindow = "";
793               
794        var paramsChatBox =
795        {
796                        'enabledPopUp'  : ( ( loadscript.getIsIE() ) ? "none" : "block" ),
797                        'idChatBox'     : barejid + "__chatBox",
798                        'jidTo'                 : barejid,
799                                'path_jabberit' : path_jabberit
800        };
801
802        titleWindow = barejid.toLowerCase();
803                titleWindow = titleWindow.substring(0, titleWindow.indexOf('@'));
804
805        if( TrophyIM.rosterObj.roster[barejid] )
806        {
807            if( TrophyIM.rosterObj.roster[barejid.toLowerCase()]['contact']['name'] )
808            {
809                titleWindow = TrophyIM.rosterObj.roster[barejid.toLowerCase()]['contact']['name'];
810            }
811        }
812
813        // Position Top
814        TrophyIM.posWindow.top  = TrophyIM.posWindow.top + 10;
815        if( TrophyIM.posWindow.top > 200 )
816                TrophyIM.posWindow.top  = 100;
817       
818        // Position Left
819        TrophyIM.posWindow.left = TrophyIM.posWindow.left + 5;
820        if( TrophyIM.posWindow.left > 455 )
821                TrophyIM.posWindow.left = 400;
822       
823        var _content = document.createElement( 'div' );
824        _content.innerHTML = loadscript.parse( "chat_box", "chatBox.xsl", paramsChatBox);
825        _content = _content.firstChild;
826       
827        var _messages = _content.firstChild.firstChild;
828        var _textarea = _content.getElementsByTagName( 'textarea' ).item( 0 );
829        var _send = _content.getElementsByTagName( 'input' ).item( 0 );
830                var _chatStateOnOff = _content.getElementsByTagName( 'input' ).item( 1 );
831
832        function _send_message( )
833        {
834                if ( ! TrophyIM.sendMessage( barejid, _textarea.value ) )
835                        return false;
836
837                // Add Message in chatBox;
838                TrophyIM.addMessage( _messages, barejid, {
839                        contact : "<font style='font-weight:bold; color:red;'>" + i18n.ME + "</font>",
840                        msg : "<br/>" + _textarea.value
841                } );
842
843                _textarea.value = '';
844                _textarea.focus( );
845        }
846               
847                var composingTimer_ = 0;
848                var isComposing_ = 0;
849                var timeCounter;
850
851                function setComposing()
852                {
853                        var checkComposing = function()
854                        {
855                if (!isComposing_) {
856                        // User stopped composing
857                        composingTimer_ = 0;
858                        clearInterval(timeCounter);
859                        TrophyIM.sendContentMessage(barejid, 'paused');
860                } else {
861                        TrophyIM.sendContentMessage(barejid, 'composing');
862                }
863                isComposing_ = 0; // Reset composing
864                }
865
866                if (!composingTimer_) {
867                /* User (re)starts composing */
868                composingTimer_ = 1;
869                timeCounter = setInterval(checkComposing,4000);
870                }
871                isComposing_ = 1;
872        }
873
874        loadscript.configEvents( _send, 'onclick', _send_message );
875                loadscript.configEvents( _textarea, 'onkeyup', function( e )
876                {
877                        if ( e.keyCode == 13 ){
878                                _send_message( );
879                                // User stopped composing
880                composingTimer_ = 0;
881                clearInterval(timeCounter);
882                        }else{
883                                if (_chatStateOnOff.value == 'on')
884                                        setComposing();
885                        }
886                } );       
887
888        var winChatBox =
889        {
890                         id_window              : "window_chat_area_" + barejid,
891                         barejid                : barejid,
892                         width                  : 387,
893                         height                 : 375,
894                         top                    : TrophyIM.posWindow.top,
895                         left                   : TrophyIM.posWindow.left,
896                         draggable              : true,
897                         visible                : "display",
898                         resizable              : true,
899                         zindex                 : loadscript.getZIndex(),
900                         title                  : titleWindow,
901                         closeAction    : "hidden",
902                         content                : _content     
903        }
904       
905                _win = _winBuild(winChatBox);
906
907        // Notification New Message
908        loadscript.notification(barejid);
909       
910        // Photo User;
911                loadscript.getPhotoUser(barejid);
912               
913                _textarea.focus( );
914               
915                return ( _messages = _win.content( ).firstChild );
916    },
917
918        /** Function addContacts
919         *
920         *  Parameters:
921         *              (string) jidFrom         
922         *      (string) jidTo
923         *              (string) name
924         *              (string) group   
925         */
926       
927        addContact : function( jidTo, name, group )
928        {
929                // Add Contact
930        var _id = TrophyIM.connection.getUniqueId('add');
931                var newContact = $iq({type: 'set', id: _id });
932                        newContact = newContact.c('query').attrs({xmlns : 'jabber:iq:roster'});
933                        newContact = newContact.c('item').attrs({jid: jidTo, name:name });
934                        newContact = newContact.c('group').t(group).tree();
935
936                TrophyIM.connection.send(newContact);
937        },
938
939    /** Function: addMessage
940     *
941     *  Parameters:
942     *    (string) msg - the message to add
943     *    (string) jid - the jid of chat box to add the message to.
944     */
945       
946    addMessage : function(chatBox, jid, msg)
947    {
948        // Get Smiles
949        msg.msg = loadscript.getSmiles( msg.msg );
950 
951        var messageDiv  = document.createElement("div");
952                messageDiv.style.margin = "3px 0px 1em 3px";
953        messageDiv.innerHTML    = msg.contact + " : " + msg.msg ;
954               
955        chatBox.appendChild(messageDiv);
956        chatBox.scrollTop = chatBox.scrollHeight;
957    },
958       
959    /** Function : renameContact
960     *
961     *
962     */
963   
964    renameContact : function( jid, index )
965    {
966        // Name
967        var name                = TrophyIM.rosterObj.roster[jid].contact.name;
968
969                if(( name = prompt(i18n.ASK_NEW_NAME_QUESTION + name + "!", name )))
970                        if(( name = name.replace(/^\s+|\s+$|^\n|\n$/g,"")) == "" )
971                                name = "";
972
973                if( name == null || name == "")
974                        name = "";
975               
976        var jidTo = jid
977        var name  = ( name ) ? name : TrophyIM.rosterObj.roster[jid].contact.name;
978        var group = TrophyIM.rosterObj.roster[jid].contact.groups[0];
979       
980        TrophyIM.addContact( jidTo, name, group );
981       
982        document.getElementById('itenContact_' + jid + '_' + index).innerHTML = name;
983    },
984   
985    /** Function : renameGroup
986     *
987     *
988     */
989
990    renameGroup : function( jid, index)
991    {
992        var group               = TrophyIM.rosterObj.roster[jid].contact.groups[0];
993        var presence    = TrophyIM.rosterObj.roster[jid].presence;
994       
995                // Group
996                if(( group = prompt( i18n.ASK_NEW_GROUP_QUESTION, group )))
997                        if(( group = group.replace(/^\s+|\s+$|^\n|\n$/g,"")) == "" )
998                                group = "";
999
1000                if( group == null || group == "")
1001                        group = "";
1002
1003        var jidTo = TrophyIM.rosterObj.roster[jid].contact.jid;
1004        var name  = TrophyIM.rosterObj.roster[jid].contact.name;
1005                var group = ( group ) ? group : TrophyIM.rosterObj.roster[jid].contact.groups[0];
1006
1007                TrophyIM.rosterObj.removeContact( jid );
1008               
1009                TrophyIM.addContact( jidTo, name, group );
1010       
1011                document.getElementById("JabberIMRoster").innerHTML = "";
1012               
1013        TrophyIM.renderRoster();
1014       
1015        setTimeout(function()
1016        {
1017                for( var i in presence )
1018                {
1019                        if ( presence[ i ].constructor == Function )
1020                                continue;
1021                               
1022                        TrophyIM.rosterObj.setPresence( jid, presence[i].priority, presence[i].show, presence[i].status);
1023                }
1024        },500);
1025    },
1026   
1027    /** Function: removeContact
1028     *
1029     *  Parameters:
1030     *          (string) jidTo
1031     */
1032   
1033    removeContact : function(jidTo, indexTo)
1034    {
1035        var divItenContact       = null;
1036        var spanShow             = null;
1037       
1038        if( ( divItenContact = document.getElementById('itenContact_' + jidTo + '_' + indexTo )))
1039        {       
1040                spanShow = document.getElementById('span_show_itenContact_' + jidTo + '_' + indexTo )
1041               
1042                spanShow.parentNode.removeChild(spanShow);
1043               
1044                loadscript.removeGroup( divItenContact.parentNode );
1045               
1046                divItenContact.parentNode.removeChild(divItenContact);
1047
1048                // Remove Contact
1049                        var _id = TrophyIM.connection.getUniqueId();   
1050                var delContact  = $iq({type: 'set', id: _id})
1051                        delContact      = delContact.c('query').attrs({xmlns : 'jabber:iq:roster'});
1052                        delContact      = delContact.c('item').attrs({jid: jidTo, subscription:'remove'}).tree();
1053
1054                TrophyIM.connection.send( delContact );                 
1055                       
1056                // Remove Contact       
1057                var _id = TrophyIM.connection.getUniqueId();
1058                var _delContact_ = $iq({type: 'set', id: _id})
1059                        _delContact_ = _delContact_.c('query').attrs({xmlns : 'jabber:iq:private'});
1060                        _delContact_ = _delContact_.c('storage').attrs({xmlns : 'storage:metacontacts'}).tree();
1061
1062                TrophyIM.connection.send( _delContact_ );       
1063        }
1064    },
1065   
1066    /** Function: renderRoster
1067     *
1068     *  Renders roster, looking only for jids flagged by setPresence as having
1069     *  changed.
1070     */
1071   
1072        renderRoster : function()
1073        {
1074                var roster_div = document.getElementById('JabberIMRoster');
1075               
1076                if( roster_div )
1077                {
1078                        var users = new Array();
1079                       
1080                        var loading_gif = document.getElementById("JabberIMRosterLoadingGif");
1081                       
1082                        if( loading_gif.style.display == "block" )
1083                                loading_gif.style.display = "none";
1084                               
1085                        for( var user in TrophyIM.rosterObj.roster )
1086                        {
1087                                if ( TrophyIM.rosterObj.roster[ user ].constructor == Function )
1088                                        continue;
1089
1090                                users[users.length] = TrophyIM.rosterObj.roster[user].contact.jid;
1091                        }
1092
1093                        users.sort();
1094                       
1095                        var groups              = new Array();
1096                        var flagGeral   = false;
1097                       
1098                        for (var group in TrophyIM.rosterObj.groups)
1099                        {
1100                                if ( TrophyIM.rosterObj.groups[ group ].constructor == Function )
1101                                        continue;
1102                               
1103                                if( group )
1104                                        groups[groups.length] = group;
1105                               
1106                                if( group == "Geral" )
1107                                        flagGeral = true;
1108            }
1109           
1110                        if( !flagGeral && users.length > 0 )
1111                                groups[groups.length] = "Geral";
1112                               
1113                        groups.sort();
1114                       
1115                        for ( var i = 0; i < groups.length; i++ )
1116                        {
1117                                TrophyIM.renderGroups( groups[i] , roster_div );       
1118                        }
1119                       
1120                        TrophyIM.renderItensGroup( users, roster_div );
1121                }
1122                       
1123                TrophyIM._timeOut.renderRoster = setTimeout("TrophyIM.renderRoster()", 1000 );         
1124        },
1125       
1126    /** Function: renderGroups
1127     *
1128     *
1129     */
1130       
1131        renderGroups: function( nameGroup, element )
1132        {
1133                var _addGroup = function()
1134                {
1135                        var _nameGroup  = nameGroup;
1136                        var _element    = element;
1137
1138                        var paramsGroup =
1139                        {
1140                                'nameGroup'     : _nameGroup,
1141                                'path_jabberit' : path_jabberit
1142                        }
1143                       
1144                        _element.innerHTML += loadscript.parse("group","groups.xsl", paramsGroup);
1145                }
1146
1147                if( !element.hasChildNodes() )
1148                {
1149                        _addGroup();
1150                }
1151                else
1152                {
1153                        var _NodeChild  = element.firstChild;
1154                        var flagAdd             = false;
1155                       
1156                        while( _NodeChild )
1157                        {
1158                                if( _NodeChild.childNodes[0].nodeName.toLowerCase() === "span" )
1159                                {
1160                                        if( _NodeChild.childNodes[0].childNodes[0].nodeValue === nameGroup )
1161                                        {
1162                                                flagAdd = true;
1163                                        }
1164                                }
1165                               
1166                                _NodeChild = _NodeChild.nextSibling;
1167                        }
1168
1169                        if( !flagAdd )
1170                        {
1171                                _addGroup();
1172                        }
1173                }
1174        },
1175
1176    /** Function: renderItensGroup
1177     *
1178     *
1179     */
1180
1181        renderItensGroup : function( users, element )
1182        {
1183                var addItem = function()
1184                {
1185                        if( arguments.length > 0 )
1186                        {
1187                                var objContact  = arguments[0];
1188                                var group               = arguments[1];
1189                                var element             = arguments[2];
1190                                var index               = arguments[3];
1191                                var showOffline = loadscript.getShowContactsOffline();
1192                               
1193                                var itensJid    = document.getElementById( 'itenContact_' + objContact.contact.jid + '_' + index );
1194
1195                                if( itensJid == null )
1196                                {
1197                                        // Name
1198                                        var nameContact = "";                                   
1199                                       
1200                                        if ( objContact.contact.name )
1201                                                nameContact = objContact.contact.name;
1202                                        else
1203                                        {
1204                                                nameContact = objContact.contact.jid;
1205                                                nameContact = nameContact.substring(0, nameContact.indexOf('@'));
1206                                        }
1207                                       
1208                                        // Presence e Status
1209                                        var presence            = "unavailable";
1210                                        var status                      = "";
1211                                        var statusDisplay       = "none";
1212                                       
1213                                        if (objContact.presence)
1214                                        {
1215                                                for (var resource in objContact.presence)
1216                                                {
1217                                                        if ( objContact.presence[resource].constructor == Function )
1218                                                                continue;
1219
1220                                                        if( objContact.presence[resource].show != 'invisible' )
1221                                                                presence = objContact.presence[resource].show;
1222
1223                                                        if( objContact.contact.subscription != "both")
1224                                                                presence = 'subscription';
1225                                                       
1226                                                        if( objContact.presence[resource].status )
1227                                                        {
1228                                                                status = " ( " + objContact.presence[resource].status + " ) ";
1229                                                                statusDisplay   = "block";
1230                                                        }
1231                                                }
1232                                        }
1233                                       
1234                                        var paramsContact =
1235                                        {
1236                                                divDisplay              : "block",
1237                                                id                              : 'itenContact_' + objContact.contact.jid + '_' + index ,
1238                                                index                   : ((index == 0 ) ? "0" : index),
1239                                                jid                             : objContact.contact.jid,
1240                                                nameContact     : nameContact,
1241                                                path_jabberit   : path_jabberit,
1242                                                presence                : presence,
1243                                                spanDisplay             : statusDisplay,
1244                                                status                  : status,
1245                                                statusColor             : "black",
1246                                                subscription    : objContact.contact.subscription
1247                                        }
1248                                       
1249                                        // Authorization       
1250                                        if( objContact.contact.subscription != "both" )
1251                                        {
1252                                               
1253                                                switch(objContact.contact.subscription)
1254                                                {
1255                                                        case "none" :
1256                                                                                                                         
1257                                                                paramsContact.status            = " (( " + i18n.ASK_AUTHO + " )) ";
1258                                                                paramsContact.statusColor       = "red";
1259                                                                break;
1260       
1261                                                        case "to" :
1262                                                               
1263                                                                paramsContact.status            = " (( " + i18n.CONTACT_ASK_FOR_AUTH + ")) ";
1264                                                                paramsContact.statusColor       = "orange";
1265                                                                break;
1266       
1267                                                        case "from" :
1268                                                               
1269                                                                paramsContact.status            = " (( " + i18n.AUTH_ASK + " )) ";
1270                                                                paramsContact.statusColor       = "green";
1271                                                                break;
1272                                                               
1273                                                        case "subscribe" :
1274                                                               
1275                                                                paramsContact.status            =  " (( " + i18n.AUTH_SENT + " )) ";
1276                                                                paramsContact.statusColor       = "red";       
1277                                                                break;
1278
1279                                                        case "not-in-roster" :
1280                                                               
1281                                                                paramsContact.status            = " (( " + i18n.ASK_FOR_AUTH_QUESTION + " )) ";
1282                                                                paramsContact.statusColor       = "orange";     
1283                                                                break;
1284                                                               
1285                                                        default:
1286                                                                paramsContact.status = " ( " + objContact.contact.subscription + " ) ";
1287                                                }
1288                                        }
1289                                       
1290                                        if( group != "")
1291                                        {
1292                                                var _NodeChild          = element.firstChild;
1293                                               
1294                                                while( _NodeChild )
1295                                                {
1296                                                        if( _NodeChild.childNodes[0].nodeName.toLowerCase() === "span" )
1297                                                        {
1298                                                                if( _NodeChild.childNodes[0].childNodes[0].nodeValue === group )
1299                                                                {
1300                                                                        _NodeChild.innerHTML += loadscript.parse("itens_group", "itensGroup.xsl", paramsContact);
1301                                                                }
1302                                                        }
1303
1304                                                        _NodeChild = _NodeChild.nextSibling;
1305                                                }
1306                                        }       
1307                                }
1308                                else
1309                                {
1310
1311                                        // Presence e Status
1312                                        var presence            = "unavailable";
1313                                        var status                      = "";
1314                                        var statusColor         = "black";
1315                                        var statusDisplay       = "none";
1316                                       
1317                                        if ( objContact.presence )
1318                                        {
1319                                                for ( var resource in objContact.presence )
1320                                                {
1321                                                        if ( objContact.presence[resource].constructor == Function )
1322                                                                continue;
1323
1324                                                        if( objContact.presence[resource].show != 'invisible' )
1325                                                                presence = objContact.presence[resource].show;
1326
1327                                                        if( objContact.contact.subscription != "both")
1328                                                                presence = 'subscription';
1329                                                       
1330                                                        if( objContact.presence[resource].status )
1331                                                        {
1332                                                                status = " ( " + objContact.presence[resource].status + " ) ";
1333                                                                statusDisplay   = "block";
1334                                                        }
1335                                                }       
1336                                        }
1337                                               
1338                                        var is_open = itensJid.parentNode.childNodes[0].style.backgroundImage; 
1339                                                is_open = is_open.indexOf("arrow_down.gif");
1340                                       
1341                                        // Authorization       
1342                                        if( objContact.contact.subscription != "both" )
1343                                        {
1344                                                switch(objContact.contact.subscription)
1345                                                {
1346                                                        case "none" :
1347                                                               
1348                                                                status          = " (( " + i18n.ASK_FOR_AUTH  + " )) ";
1349                                                                statusColor     = "red";
1350                                                                break;
1351       
1352                                                        case "to" :
1353                                                               
1354                                                                status          = " (( " + i18n.CONTACT_ASK_FOR_AUTH  + " )) ";
1355                                                                statusColor     = "orange";
1356                                                                break;
1357       
1358                                                        case "from" :
1359                                                               
1360                                                                status          = " (( " + i18n.AUTH_ASK + " )) ";
1361                                                                statusColor = "green";
1362                                                                break;
1363                                                               
1364                                                        case "subscribe" :
1365                                                               
1366                                                                status          = " (( " + i18n.AUTH_SENT  + " )) ";
1367                                                                statusColor     = "red";       
1368                                                                break;
1369
1370                                                        case "not-in-roster" :
1371                                                               
1372                                                                status          = " (( " + i18n.ASK_FOR_AUTH_QUESTION  + " )) ";
1373                                                                statusColor     = "orange";     
1374                                                                break;
1375                                                               
1376                                                        default:
1377                                                                status = " ( " + objContact.contact.subscription + " ) ";
1378                                                }
1379
1380                                                statusDisplay = "block";
1381                                        }
1382                                       
1383                                        with ( document.getElementById('span_show_' + 'itenContact_' + objContact.contact.jid + '_' + index ) )
1384                                        {
1385                                                if( presence == "unavailable" && !showOffline )
1386                                                {
1387                                                        style.display = "none";
1388                                                }
1389                                                else
1390                                                {
1391                                                        if( is_open > 0 )
1392                                                        {
1393                                                                style.display   = statusDisplay;
1394                                                                style.color             = statusColor;
1395                                                                innerHTML               = status;
1396                                                        }
1397                                                }
1398                                        }
1399                                       
1400                                        if( presence == "unavailable" && !showOffline )
1401                                                itensJid.style.display = "none";
1402                                        else
1403                                        {
1404                                                if( is_open > 0 )
1405                                                {
1406                                                        itensJid.style.display = "block";
1407                                                }
1408                                        }
1409                                       
1410                                        itensJid.style.background       = "url('"+path_jabberit+"templates/default/images/" + presence + ".gif') no-repeat center left";
1411                                }
1412
1413                                // Contact OffLine
1414                                if( !objContact.presence && !showOffline )
1415                                {
1416                                        with ( document.getElementById('span_show_' + 'itenContact_' + objContact.contact.jid + '_' + index ))
1417                                        {
1418                                                style.display   = "none";
1419                                        }
1420
1421                                        with ( document.getElementById('itenContact_' + objContact.contact.jid + '_' + index ) )
1422                                        {
1423                                                style.display   = "none";
1424                                        }
1425                                }
1426                        }
1427                }
1428               
1429                for( var i = 0 ; i < users.length; i++ )
1430                {
1431                        if( TrophyIM.rosterObj.roster[users[i]].contact.jid != Base64.decode(loadscript.getUserCurrent().jid) )
1432                        {
1433                                if( TrophyIM.rosterObj.roster[users[i]].contact.groups )
1434                                {
1435                                        var groups = TrophyIM.rosterObj.roster[users[i]].contact.groups;
1436                                       
1437                                        if( groups.length > 0 )
1438                                        {
1439                                                for( var j = 0; j < groups.length; j++ )
1440                                                {
1441                                                        addItem( TrophyIM.rosterObj.roster[users[i]], groups[j], element, j );
1442                                                }
1443                                        }
1444                                        else
1445                                        {
1446                                                addItem( TrophyIM.rosterObj.roster[users[i]], "Geral", element, 0 );
1447                                        }
1448                                }
1449                                else
1450                                {
1451                                        addItem( TrophyIM.rosterObj.roster[users[i]], "Geral", element, 0 );
1452                                }
1453                        }
1454                }       
1455        },
1456
1457    /** Function: rosterClick
1458     *
1459     *  Handles actions when a roster item is clicked
1460     */
1461   
1462        rosterClick : function(fulljid)
1463        {
1464        TrophyIM.makeChat(fulljid);
1465    },
1466
1467        /** Function SetAutorization
1468         *
1469         */
1470
1471        setAutorization : function( jidTo, jidFrom, _typeSubscription )
1472        {
1473        var _id = TrophyIM.connection.getUniqueId();
1474       
1475        TrophyIM.connection.send($pres( ).attrs( {to: jidTo, from: jidFrom, type: _typeSubscription, id: _id}).tree());
1476        },
1477   
1478        /** Function: setPresence
1479     *
1480     */
1481
1482        setPresence : function( _type )
1483        {
1484                if( _type != 'status')
1485                {
1486                        if( _type == "unavailable" &&  TrophyIM.statusConn.connected )
1487                        {
1488                                var loading_gif = document.getElementById("JabberIMRosterLoadingGif");
1489                               
1490                                if( TrophyIM._timeOut.renderRoster != null )
1491                                        clearTimeout(TrophyIM._timeOut.renderRoster);
1492                               
1493                                if( TrophyIM.statusConn.connected )
1494                                        TrophyIM.connection.send($pres({type : _type}).tree());
1495                               
1496                                for( var i = 0; i < TrophyIM.connection._requests.length; i++ )
1497                        {
1498                                if( TrophyIM.connection._requests[i] )
1499                                        TrophyIM.connection._removeRequest(TrophyIM.connection._requests[i]);
1500                        }
1501                               
1502                                TrophyIM.logout();
1503                               
1504                        loadscript.clrAllContacts();
1505                       
1506                        delete TrophyIM.rosterObj.roster;
1507                        delete TrophyIM.rosterObj.groups;
1508                       
1509                        setTimeout(function()
1510                        {
1511                                        if( loading_gif.style.display == "block" )
1512                                                loading_gif.style.display = "none";
1513                        }, 1000);
1514                        }
1515                        else
1516                        {
1517                                if( !TrophyIM.autoConnection.connect )
1518                                {
1519                                        TrophyIM.autoConnection.connect = true;
1520                                        TrophyIM.load();
1521                                }
1522                                else
1523                                {
1524                                        if( TrophyIM.statusConn.connected )
1525                                        {
1526                                                if( loadscript.getStatusMessage() != "" )
1527                                                {
1528                                                        var _presence = $pres( );
1529                                                        _presence.node.appendChild( Strophe.xmlElement( 'show' ) ).appendChild( Strophe.xmlTextNode( _type ) );
1530                                                        _presence.node.appendChild( Strophe.xmlElement( 'status' ) ).appendChild( Strophe.xmlTextNode( loadscript.getStatusMessage() ));
1531                                                       
1532                                                        TrophyIM.connection.send( _presence.tree() );
1533                                                }
1534                                                else
1535                                                {
1536                                                        TrophyIM.connection.send($pres( ).c('show').t(_type).tree());
1537                                                }
1538                                        }
1539                                }
1540                        }
1541                }
1542                else
1543                {
1544                        var _show       = "available";
1545                        var _status     = "";
1546                       
1547                        if( arguments.length < 2 )
1548                        {
1549                                if( loadscript.getStatusMessage() != "" )
1550                                        _status = prompt(i18n.TYPE_YOUR_MSG, loadscript.getStatusMessage());
1551                                else
1552                                        _status = prompt(i18n.TYPE_YOUR_MSG);
1553                               
1554                                var _divStatus = document.getElementById("JabberIMStatusMessage");
1555                               
1556                                if( ( _status = _status.replace(/^\s+|\s+$|^\n|\n$/g,"") ) != "")
1557                                        _divStatus.firstChild.innerHTML = "( " + _status + " )";
1558                        }
1559                        else
1560                        {
1561                                _status = arguments[1];
1562                        }
1563
1564                        for( var resource in TrophyIM.rosterObj.roster[Base64.decode(loadscript.getUserCurrent().jid)].presence )
1565                        {
1566                        if ( TrophyIM.rosterObj.roster[Base64.decode(loadscript.getUserCurrent().jid)].presence[ resource ].constructor == Function )
1567                                continue;
1568                       
1569                                if ( TROPHYIM_RESOURCE === ("/" + resource) )
1570                                        _show = TrophyIM.rosterObj.roster[Base64.decode(loadscript.getUserCurrent().jid)].presence[resource].show;
1571                        }
1572
1573                        if ( TrophyIM.statusConn.connected )
1574                        {
1575                                var _presence = $pres( );
1576                                _presence.node.appendChild( Strophe.xmlElement( 'show' ) ).appendChild( Strophe.xmlTextNode( _show ) );
1577                                _presence.node.appendChild( Strophe.xmlElement( 'status' ) ).appendChild( Strophe.xmlTextNode( _status ) );
1578                               
1579                                TrophyIM.connection.send( _presence.tree() );
1580                        }
1581                }
1582        },
1583       
1584        /** Function: sendMessage
1585     *
1586     *  Send message from chat input to user
1587     */
1588     
1589    sendMessage : function()
1590    {
1591                if (arguments.length > 0) {
1592                        var jidTo = arguments[0];
1593                        var message_input = arguments[1];
1594                       
1595                       
1596                        message_input = message_input.replace(/^\s+|\s+$|^\n|\n$/g, "");
1597                       
1598                        if (message_input != "") {
1599                       
1600                                // Send Message
1601                                var newMessage = $msg({
1602                                        to: jidTo,
1603                                        from: TrophyIM.connection.jid,
1604                                        type: 'chat'
1605                                });
1606                                newMessage = newMessage.c('body').t(message_input);
1607                                newMessage.up();
1608                                newMessage = newMessage.c('active').attrs({
1609                                        xmlns: 'http://jabber.org/protocol/chatstates'
1610                                });
1611                                // Send Message
1612                                TrophyIM.connection.send(newMessage.tree());
1613                               
1614                                return true;
1615                        }
1616                }
1617               
1618                return false;
1619    },
1620       
1621        /** Function: sendContentMessage
1622     *
1623     *  Send a content message from chat input to user
1624     */
1625        sendContentMessage : function()
1626    {
1627      if( arguments.length > 0 )
1628      {
1629         var jidTo = arguments[0];
1630         var state = arguments[1];
1631
1632         var newMessage = $msg({to: jidTo, from: TrophyIM.connection.jid, type: 'chat'});
1633         newMessage = newMessage.c(state).attrs({xmlns : 'http://jabber.org/protocol/chatstates'});
1634         // Send content message
1635         TrophyIM.connection.send(newMessage.tree());
1636      }
1637    }
1638};
1639
1640/** Class: TrophyIMRoster
1641 *
1642 *
1643 *  This object stores the roster and presence info for the TrophyIMClient
1644 *
1645 *  roster[jid_lower]['contact']
1646 *  roster[jid_lower]['presence'][resource]
1647 */
1648function TrophyIMRoster()
1649{
1650    /** Constants: internal arrays
1651     *    (Object) roster - the actual roster/presence information
1652     *    (Object) groups - list of current groups in the roster
1653     *    (Array) changes - array of jids with presence changes
1654     */
1655    if (TrophyIM.JSONStore.store_working)
1656        {
1657        var data = TrophyIM.JSONStore.getData(['roster', 'groups']);
1658        this.roster = (data['roster'] != null) ? data['roster'] : {};
1659        this.groups = (data['groups'] != null) ? data['groups'] : {};
1660    }
1661        else
1662        {
1663        this.roster = {};
1664        this.groups = {};
1665    }
1666    this.changes = new Array();
1667   
1668        if (TrophyIM.constants.stale_roster)
1669        {
1670        for (var jid in this.roster)
1671                {
1672                        this.changes[this.changes.length] = jid;
1673        }
1674    }
1675
1676        /** Function: addChange
1677         *
1678         *  Adds given jid to this.changes, keeping this.changes sorted and
1679         *  preventing duplicates.
1680         *
1681         *  Parameters
1682         *    (String) jid : jid to add to this.changes
1683         */
1684         
1685        this.addChange = function(jid)
1686        {
1687                for (var c = 0; c < this.changes.length; c++)
1688                {
1689                        if (this.changes[c] == jid)
1690                        {
1691                                return;
1692                        }
1693                }
1694               
1695                this.changes[this.changes.length] = jid;
1696               
1697                this.changes.sort();
1698        }
1699       
1700    /** Function: addContact
1701     *
1702     *  Adds given contact to roster
1703     *
1704     *  Parameters:
1705     *    (String) jid - bare jid
1706     *    (String) subscription - subscription attribute for contact
1707     *    (String) name - name attribute for contact
1708     *    (Array)  groups - array of groups contact is member of
1709     */
1710   
1711        this.addContact = function(jid, subscription, name, groups )
1712        {
1713        if( subscription !== "remove" )
1714        {
1715                var contact             = { jid:jid, subscription:subscription, name:name, groups:groups }
1716                var jid_lower   = jid.toLowerCase();
1717       
1718                        if ( this.roster[jid_lower] )
1719                        {
1720                    this.roster[jid_lower]['contact'] = contact;
1721                }
1722                        else
1723                        {
1724                    this.roster[jid_lower] = {contact:contact};
1725                }
1726
1727                        groups = groups ? groups : [''];
1728               
1729                        for ( var g = 0; g < groups.length; g++ )
1730                        {
1731                                if ( !this.groups[groups[g]] )
1732                                {
1733                        this.groups[groups[g]] = {};
1734                    }
1735                   
1736                                this.groups[groups[g]][jid_lower] = jid_lower;
1737                }
1738        }
1739        else
1740        {
1741                this.removeContact(jid);
1742        }
1743    }
1744   
1745    /** Function: getContact
1746     *
1747     *  Returns contact entry for given jid
1748     *
1749     *  Parameter: (String) jid - jid to return
1750     */
1751     
1752    this.getContact = function(jid)
1753        {
1754        if (this.roster[jid.toLowerCase()])
1755                {
1756            return this.roster[jid.toLowerCase()]['contact'];
1757        }
1758    }
1759
1760   /** Function: getPresence
1761        *
1762        *  Returns best presence for given jid as Array(resource, priority, show,
1763        *  status)
1764        *
1765        *  Parameter: (String) fulljid - jid to return best presence for
1766        */
1767         
1768        this.getPresence = function(fulljid)
1769        {
1770                var jid = Strophe.getBareJidFromJid(fulljid);
1771                var current = null;
1772                   
1773                if (this.roster[jid.toLowerCase()] && this.roster[jid.toLowerCase()]['presence'])
1774                {
1775                        for (var resource in this.roster[jid.toLowerCase()]['presence'])
1776                        {
1777                        if ( this.roster[jid.toLowerCase()]['presence'][ resource ].constructor == Function )
1778                                continue;
1779                       
1780                                var presence = this.roster[jid.toLowerCase()]['presence'][resource];
1781                                if (current == null)
1782                                {
1783                                        current = presence
1784                                }
1785                                else
1786                                {
1787                                        if(presence['priority'] > current['priority'] && ((presence['show'] == "chat"
1788                                        || presence['show'] == "available") || (current['show'] != "chat" ||
1789                                        current['show'] != "available")))
1790                                        {
1791                                                current = presence
1792                                        }
1793                                }
1794                        }
1795                }
1796                return current;
1797        }
1798
1799        /** Function: groupHasChanges
1800         *
1801         *  Returns true if current group has members in this.changes
1802         *
1803         *  Parameters:
1804         *    (String) group - name of group to check
1805         */
1806         
1807        this.groupHasChanges = function(group)
1808        {
1809                for (var c = 0; c < this.changes.length; c++)
1810                {
1811                        if (this.groups[group][this.changes[c]])
1812                        {
1813                                return true;
1814                        }
1815                }
1816                return false;
1817        }
1818       
1819        /** Function removeContact
1820         *
1821         * Parameters
1822         *       (String) jid           
1823         */
1824         
1825         this.removeContact = function(jid)
1826         {
1827                if( this.roster[ jid ] )
1828                {
1829                        var groups = this.roster[ jid ].contact.groups;
1830                       
1831                        if( groups )
1832                        {
1833                                for ( var i = 0; i < groups.length; i++ )
1834                                {
1835                                        delete this.groups[ groups[ i ] ][ jid ];
1836                                }
1837       
1838                                for ( var i = 0; i < groups.length; i++ )
1839                                {
1840                                        var contacts = 0;
1841                                        for ( var contact in this.groups[ groups[ i ] ] )
1842                                        {
1843                                        if ( this.groups[ groups[ i ] ][ contact ].constructor == Function )
1844                                                continue;
1845                                       
1846                                                contacts++;
1847                                        }
1848               
1849                                        if ( ! contacts )
1850                                                delete this.groups[ groups[ i ] ];
1851                                }
1852                        }
1853       
1854                        // Delete Object roster
1855                        if( this.roster[jid] )
1856                                delete this.roster[jid];
1857                }
1858         }
1859         
1860    /** Function: setPresence
1861     *
1862     *  Sets presence
1863     *
1864     *  Parameters:
1865     *    (String) fulljid: full jid with presence
1866     *    (Integer) priority: priority attribute from presence
1867     *    (String) show: show attribute from presence
1868     *    (String) status: status attribute from presence
1869     */
1870   
1871        this.setPresence = function(fulljid, priority, show, status)
1872        {
1873                var barejid             = Strophe.getBareJidFromJid(fulljid);
1874        var resource    = Strophe.getResourceFromJid(fulljid);
1875        var jid_lower   = barejid.toLowerCase();
1876       
1877                if( show != 'unavailable')
1878                {
1879            if (!this.roster[jid_lower])
1880                        {
1881                this.addContact(barejid, 'not-in-roster');
1882            }
1883            var presence =
1884                        {
1885                resource:resource, priority:priority, show:show, status:status
1886            }
1887           
1888                        if (!this.roster[jid_lower]['presence'])
1889                        {
1890                this.roster[jid_lower]['presence'] = {};
1891            }
1892            this.roster[jid_lower]['presence'][resource] = presence;
1893        }
1894                else if (this.roster[jid_lower] && this.roster[jid_lower]['presence'] && this.roster[jid_lower]['presence'][resource])
1895                {
1896            delete this.roster[jid_lower]['presence'][resource];
1897        }
1898       
1899                this.addChange(jid_lower);
1900    }
1901
1902        /** Fuction: save
1903         *
1904         *  Saves roster data to JSON store
1905         */
1906       
1907        this.save = function()
1908        {
1909                if (TrophyIM.JSONStore.store_working)
1910                {
1911                        TrophyIM.JSONStore.setData({roster:this.roster,
1912                        groups:this.groups, active_chat:TrophyIM.activeChats['current'],
1913                        chat_history:TrophyIM.chatHistory});
1914                }
1915        }
1916
1917}
1918/** Class: TrophyIMJSONStore
1919 *
1920 *
1921 *  This object is the mechanism by which TrophyIM stores and retrieves its
1922 *  variables from the url provided by TROPHYIM_JSON_STORE
1923 *
1924 */
1925function TrophyIMJSONStore() {
1926    this.store_working = false;
1927    /** Function _newXHR
1928     *
1929     *  Set up new cross-browser xmlhttprequest object
1930     *
1931     *  Parameters:
1932     *    (function) handler = what to set onreadystatechange to
1933     */
1934     this._newXHR = function (handler) {
1935        var xhr = null;
1936        if (window.XMLHttpRequest) {
1937            xhr = new XMLHttpRequest();
1938            if (xhr.overrideMimeType) {
1939            xhr.overrideMimeType("text/xml");
1940            }
1941        } else if (window.ActiveXObject) {
1942            xhr = new ActiveXObject("Microsoft.XMLHTTP");
1943        }
1944        return xhr;
1945    }
1946    /** Function getData
1947     *  Gets data from JSONStore
1948     *
1949     *  Parameters:
1950     *    (Array) vars = Variables to get from JSON store
1951     *
1952     *  Returns:
1953     *    Object with variables indexed by names given in parameter 'vars'
1954     */
1955    this.getData = function(vars) {
1956        if (typeof(TROPHYIM_JSON_STORE) != undefined) {
1957            Strophe.debug("Retrieving JSONStore data");
1958            var xhr = this._newXHR();
1959            var getdata = "get=" + vars.join(",");
1960            try {
1961                xhr.open("POST", TROPHYIM_JSON_STORE, false);
1962            } catch (e) {
1963                Strophe.error("JSONStore open failed.");
1964                return false;
1965            }
1966            xhr.setRequestHeader('Content-type',
1967            'application/x-www-form-urlencoded');
1968            xhr.setRequestHeader('Content-length', getdata.length);
1969            xhr.send(getdata);
1970            if (xhr.readyState == 4 && xhr.status == 200) {
1971                try {
1972                    var dataObj = JSON.parse(xhr.responseText);
1973                    return this.emptyFix(dataObj);
1974                } catch(e) {
1975                    Strophe.error("Could not parse JSONStore response" +
1976                    xhr.responseText);
1977                    return false;
1978                }
1979            } else {
1980                Strophe.error("JSONStore open failed. Status: " + xhr.status);
1981                return false;
1982            }
1983        }
1984    }
1985    /** Function emptyFix
1986     *    Fix for bugs in external JSON implementations such as
1987     *    http://bugs.php.net/bug.php?id=41504.
1988     *    A.K.A. Don't use PHP, people.
1989     */
1990    this.emptyFix = function(obj) {
1991        if (typeof(obj) == "object") {
1992            for (var i in obj) {
1993                        if ( obj[i].constructor == Function )
1994                                continue;
1995                       
1996                if (i == '_empty_') {
1997                    obj[""] = this.emptyFix(obj['_empty_']);
1998                    delete obj['_empty_'];
1999                } else {
2000                    obj[i] = this.emptyFix(obj[i]);
2001                }
2002            }
2003        }
2004        return obj
2005    }
2006    /** Function delData
2007     *    Deletes data from JSONStore
2008     *
2009     *  Parameters:
2010     *    (Array) vars  = Variables to delete from JSON store
2011     *
2012     *  Returns:
2013     *    Status of delete attempt.
2014     */
2015    this.delData = function(vars) {
2016        if (typeof(TROPHYIM_JSON_STORE) != undefined) {
2017            Strophe.debug("Retrieving JSONStore data");
2018            var xhr = this._newXHR();
2019            var deldata = "del=" + vars.join(",");
2020            try {
2021                xhr.open("POST", TROPHYIM_JSON_STORE, false);
2022            } catch (e) {
2023                Strophe.error("JSONStore open failed.");
2024                return false;
2025            }
2026            xhr.setRequestHeader('Content-type',
2027            'application/x-www-form-urlencoded');
2028            xhr.setRequestHeader('Content-length', deldata.length);
2029            xhr.send(deldata);
2030            if (xhr.readyState == 4 && xhr.status == 200) {
2031                try {
2032                    var dataObj = JSON.parse(xhr.responseText);
2033                    return dataObj;
2034                } catch(e) {
2035                    Strophe.error("Could not parse JSONStore response");
2036                    return false;
2037                }
2038            } else {
2039                Strophe.error("JSONStore open failed. Status: " + xhr.status);
2040                return false;
2041            }
2042        }
2043    }
2044    /** Function setData
2045     *    Stores data in JSONStore, overwriting values if they exist
2046     *
2047     *  Parameters:
2048     *    (Object) vars : Object containing named vars to store ({name: value,
2049     *    othername: othervalue})
2050     *
2051     *  Returns:
2052     *    Status of storage attempt
2053     */
2054    this.setData = function(vars)
2055    {
2056        if ( typeof(TROPHYIM_JSON_STORE) != undefined )
2057        {
2058            var senddata = "set=" + JSON.stringify(vars);
2059            var xhr = this._newXHR();
2060            try
2061            {
2062                xhr.open("POST", TROPHYIM_JSON_STORE, false);
2063            }
2064            catch (e)
2065            {
2066                Strophe.error("JSONStore open failed.");
2067                return false;
2068            }
2069            xhr.setRequestHeader('Content-type',
2070            'application/x-www-form-urlencoded');
2071            xhr.setRequestHeader('Content-length', senddata.length);
2072            xhr.send(senddata);
2073            if (xhr.readyState == 4 && xhr.status == 200 && xhr.responseText ==
2074            "OK") {
2075                return true;
2076            } else {
2077                Strophe.error("JSONStore open failed. Status: " + xhr.status);
2078                return false;
2079            }
2080        }
2081    }
2082   
2083    var testData = true;
2084   
2085    if (this.setData({testData:testData})) {
2086        var testResult = this.getData(['testData']);
2087        if (testResult && testResult['testData'] == true) {
2088            this.store_working = true;
2089        }
2090    }
2091}
2092/** Constants: Node types
2093 *
2094 * Implementations of constants that IE doesn't have, but we need.
2095 */
2096if (document.ELEMENT_NODE == null) {
2097    document.ELEMENT_NODE = 1;
2098    document.ATTRIBUTE_NODE = 2;
2099    document.TEXT_NODE = 3;
2100    document.CDATA_SECTION_NODE = 4;
2101    document.ENTITY_REFERENCE_NODE = 5;
2102    document.ENTITY_NODE = 6;
2103    document.PROCESSING_INSTRUCTION_NODE = 7;
2104    document.COMMENT_NODE = 8;
2105    document.DOCUMENT_NODE = 9;
2106    document.DOCUMENT_TYPE_NODE = 10;
2107    document.DOCUMENT_FRAGMENT_NODE = 11;
2108    document.NOTATION_NODE = 12;
2109}
2110
2111/** Function: importNode
2112 *
2113 *  document.importNode implementation for IE, which doesn't have importNode
2114 *
2115 *  Parameters:
2116 *    (Object) node - dom object
2117 *    (Boolean) allChildren - import node's children too
2118 */
2119if (!document.importNode) {
2120    document.importNode = function(node, allChildren) {
2121        switch (node.nodeType) {
2122            case document.ELEMENT_NODE:
2123                var newNode = document.createElement(node.nodeName);
2124                if (node.attributes && node.attributes.length > 0) {
2125                    for(var i = 0; i < node.attributes.length; i++) {
2126                        newNode.setAttribute(node.attributes[i].nodeName,
2127                        node.getAttribute(node.attributes[i].nodeName));
2128                    }
2129                }
2130                if (allChildren && node.childNodes &&
2131                node.childNodes.length > 0) {
2132                    for (var i = 0; i < node.childNodes.length; i++) {
2133                        newNode.appendChild(document.importNode(
2134                        node.childNodes[i], allChildren));
2135                    }
2136                }
2137                return newNode;
2138                break;
2139            case document.TEXT_NODE:
2140            case document.CDATA_SECTION_NODE:
2141            case document.COMMENT_NODE:
2142                return document.createTextNode(node.nodeValue);
2143                break;
2144        }
2145    };
2146}
2147
2148/**
2149 *
2150 * Bootstrap self into window.onload and window.onunload
2151 */
2152
2153var oldonunload = window.onunload;
2154
2155window.onunload = function()
2156{
2157        if( oldonunload )
2158        {
2159        oldonunload();
2160    }
2161       
2162        TrophyIM.setPresence('unavailable');
2163}
Note: See TracBrowser for help on using the repository browser.