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

Revision 2971, 57.7 KB checked in by alexandrecorreia, 14 years ago (diff)

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

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