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

Revision 2728, 56.1 KB checked in by alexandrecorreia, 14 years ago (diff)

Ticket #986 - [ Criado por Emmanuel Ferro - SERPRO ] - Implementacao da XEP-0085 - notificacao de status do chat

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