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

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