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

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

Ticket #1122 - Retirado a tela de login do modulo IM sem java( Novo IM )

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