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

Revision 2647, 50.8 KB checked in by alexandrecorreia, 14 years ago (diff)

Ticket #986 - Correcao para compatibilizar o carregamento do script para o IE e status offline.

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