source: trunk/jmessenger/js/trophyim.js @ 2975

Revision 2975, 58.1 KB checked in by alexandrecorreia, 14 years ago (diff)

Ticket #1116 - Melhorar a visualizacao/avisos de novos contatos e pedidos de autorizacao no modulo.

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