andrewjackson

Rescreatu Enhanced Chatroom

Nov 14th, 2012
37
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name            Recreatu Chatroom Enchancement
  3. // @include         http://*.rescreatu.com/chat/*
  4. // @description     An extension to add rich features to the Rescreatu shoutbox
  5. // @version         2.2.5
  6. // ==/UserScript==
  7.  
  8. /*
  9.     This work is protected by copyright. I reserve the right to refuse use of my work to anyone.
  10. */
  11.  
  12. (function (window, undefined) {
  13. "use strict";
  14.     var data = { // not a configuration, all data needs to be set on runtime in release version
  15.             alert:[] // empty array to store alert objects that are loaded
  16.         ,   DOMLoadTimer:null
  17.         ,   options:{}
  18.         ,   playAudio:null
  19.         ,   poll:null
  20.         ,   soundurl:['http://www.ilovewavs.com/Effects/Beeps/Bleep.wav'] // array of some sound files
  21.         ,   timeout:1225
  22.         ,   tmp:null
  23.         ,   userid:null
  24.         ,   userlist:{}
  25.         ,   usersound:{} // map some user ids to sounds ids
  26.     }
  27.     ,   loader = document.createElement('div')
  28.     ,   $_RCVmeta = {
  29.             major:1
  30.         ,   minor:8
  31.         ,   revision:107
  32.     };
  33.  
  34.     // quality assurance, and beta testing; helps me find new javascript errors and bugs to fix
  35.     window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
  36.         // there's an error we keep catching that's not my fault and I don't have control to fix
  37.         if (errorMsg.toLowerCase() == "uncaught typeerror: cannot set property 'innerhtml' of null") return false;//&& lineNumber == 285) return false; // so we try to detect it and ignore
  38.  
  39.         if(confirm('An unexpected error has occured on line '+lineNumber+'\nMay we attempt to notify the developer?')) { // ask user for permission to report it
  40.             var posty = new Poll('POST');
  41.             posty.callback('http://www.rescreatu.com/rmail/new/', { // gonna send an rmail through ajax
  42.                 'open' : function () {
  43.                     this.ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
  44.                     return 'to=pseudonymous&subject=ResChatv1%20beta%20error%20report&message='+encodeURIComponent('<div><b>'+errorMsg+'</b></div><div><b>Error line:</b> '+lineNumber+'</div><div><b>Error url:</b> '+url+'</div><div><b>Last MID:</b> '+(data.room.last||'none')+'</div><div><b>Message count:</b> '+(this.msgcount||0)+'</div>');
  45.                 },
  46.                 'success':function(){
  47.                     alert('The error had been reported,\nThank you for your help and testing!\n\nYou may need to refresh the page if have any issues');
  48.                 },
  49.                 'unexpected':function () {
  50.                     alert('That failed too... Please contact pseudonymous through rmail.\n\nError message: '+errorMsg+'\nError line: '+lineNumber);
  51.                 }
  52.             });
  53.         };
  54.         return false;
  55.     }
  56.  
  57.     // temporary bandaid until I improve the preferences
  58.     window.onhashchange = function () {
  59.         if (confirm('Changing options requires the page to reload.\nAre you sure you want to continue?')) window.location.reload();
  60.     };
  61.  
  62.     document.body.style.overflow = 'hidden'; // hide scrollbars
  63.     loader.style.backgroundColor = '#000';
  64.     // this is an entire gif file encoded in base64 and embedded directly on the page using data-uris, because it's silly to have to wait to load a "now loading" image
  65.     loader.style.backgroundImage = 'url(data:image/gif;base64,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)';
  66.     loader.style.backgroundPosition = 'center center';
  67.     loader.style.backgroundRepeat = 'no-repeat';
  68.     loader.style.height = '100%';
  69.     loader.style.left = '0px';
  70.     loader.style.position = 'fixed';
  71.     loader.style.top = '0px';
  72.     loader.style.width = '100%';
  73.     loader.style.zIndex = '999999999';
  74.     document.body.appendChild(loader); // we cleanup a lot of stuff, which looks quite ugly as we load, so we create an element to overlay and hide everything
  75.  
  76.     data.DOMLoadTimer = setInterval(init, 10); // An interval to constantly run init every one hundredth of a second until DOM is Ready
  77.  
  78.     function init() {
  79.         if (/loaded|complete/i.test(document.readyState)) { // Begin working if DOM is Ready or do nothing
  80.             clearInterval(data.DOMLoadTimer); // Clear interval so we only run the code once
  81.             window.onload = function () { clearTimeout(window.counter); }; // Stop the timer that refreshes the page
  82.  
  83.             var userid = document.getElementById('avatar').src // Looking for the userid, which can be found in the avatar url
  84.             ,   username = document.getElementById('username').children[0].innerText // Looking for the member's username
  85.             ,   chatmini = document.getElementById('chatroom')
  86.             ,   matchsound = []
  87.             ,   usersound = [];
  88.  
  89.             // mini chat still loads on rescreatu.com/chat/ rather than rescreatu.com/chat.php
  90.             if (chatmini) document.body.removeChild(chatmini); // so remove it
  91.             else {
  92.                 chatmini = document.getElementById('chatroom_close');
  93.                 if (chatmini) document.body.removeChild(chatmini);
  94.                 //else probably b& or does not meet coppa
  95.             };
  96.  
  97.             data.options = init.getOptions({
  98.                 audio:'true'
  99.             ,   autolink:'false'
  100.             ,   last:null
  101.             ,   lean:'true'
  102.             ,   limit:20
  103.             ,   matchsound:''
  104.             ,   threshold:1000
  105.             ,   usersound:''
  106.             });
  107.  
  108.             data.options.limit = Number(data.options.limit);
  109.             data.options.threshold = Number(data.options.threshold);
  110.  
  111.             if (data.options.matchsound.length > 0) {
  112.                 matchsound = data.options.matchsound.split('|');
  113.             }
  114.  
  115.             if (data.options.usersound.length > 0) {
  116.                 usersound = data.options.usersound.split('|');
  117.                 for (var i = 0; i < usersound.length; ++i) data.usersound[usersound[i].toLowerCase()] = 0;
  118.             }
  119.  
  120.             userid = userid.split('/').pop(); // splits string into array then gets last array item
  121.  
  122.             if (userid == 'empty-na.gif') { console.log("You must be logged in"); return; }; // end it all if not logged in
  123.  
  124.             // expects userid to be something like "crop.php?id=__UID__"
  125.             userid = userid.substring(12); // Final digest for userid, everything from 12th char to the end of string
  126.  
  127.             data.userid = userid; // remember userid in global scope
  128.             if (data.options.lean != 'false') data.userlist[userid] = [username,'font-style:italic;']; // username and some user specific css in global scope
  129.  
  130.             if (!inArray(matchsound, username)) matchsound.push(username);
  131.             data.alert.push(new Audio(data.soundurl[0],matchsound)); // creates and registers a new sound
  132.  
  133.             data.tmp = (new Temp()).getContent().makeStyle('dynamic').makeBody();
  134.             data.room = (new Room(data.tmp)).makeRoom().makeToolbar().start(); // Bulk of work in creating template
  135.  
  136.             /*data.post = new Poll('POST');
  137.             data.post.callback('http://www.rescreatu.com/getTime.php',{
  138.                 'open' : function (event) {
  139.                 };
  140.             ,   'success' : function (event) {
  141.                 };
  142.             ,   'unexpected' : function () {
  143.                     alert('Unable to query server, chatting will not be available at this time.');
  144.                 };
  145.             };);
  146.  
  147.             else this.get.open('GET','http://www.rescreatu.com/tagbox2/getChat.php?chat=1');*/
  148.         };
  149.     };
  150.  
  151.     init.getOptions = function (ret) { // takes object of defaults
  152.         if (window.location.hash.length > 1) {
  153.             var query = window.location.hash.substring(1)
  154.             ,   vars = query.split('&')
  155.             ,   i,pair;
  156.  
  157.             for (i = 0; i < vars.length; i++) {
  158.                 pair = vars[i].split('=');
  159.                 ret[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
  160.             };
  161.         };
  162.         return ret;
  163.     };
  164.  
  165.     init.setOptions = function (opt) {
  166.         var i, ret=[];
  167.         for (i in opt) ret.push(encodeURIComponent(i)+'='+encodeURIComponent(opt[i]));
  168.         return ret.join('&');
  169.     };
  170.  
  171.     function Audio (url,list) {
  172.         this.regex = Audio.setMatchList(list);
  173.         this.audio = document.createElement('audio');
  174.         this.audio.setAttribute('preload','auto');
  175.         this.audio.setAttribute('src',url);
  176.         document.body.appendChild(this.audio);
  177.         return this;
  178.     };
  179.  
  180.     Audio.play = function (index) {
  181.         data.alert[index||data.playAudio].play();
  182.     };
  183.  
  184.     Audio.prototype.play = function () {
  185.         return this.audio.play();
  186.     };
  187.  
  188.     Audio.setMatchList = function (list) {
  189.         if (isArray(list) && list.length > 0) {
  190.             list.sort(); // sort first
  191.             return new RegExp('\\b'+list.join('\\b|\\b')+'\\b','i'); // should make something like /\bentry1\b|\bentry2\b|\bentry3\b/i
  192.         }
  193.         return null;
  194.     };
  195.  
  196.     Audio.prototype.setMatchList = function (list) {
  197.         this.regex = Audio.setMatchList(list);
  198.         return this;
  199.     };
  200.  
  201.     Audio.test = function (text) {
  202.         var i = 0
  203.         ,   x = data.alert.length;
  204.         for (; i < x; ++i) if ((data.alert[i].regex !== null && data.alert[i].regex.test(text))) return i;
  205.         return null;
  206.     };
  207.  
  208. /* [s]this ajax class is garbage and needs a complete redo[/s] - gettin better */
  209.     function Poll (method,fn) {
  210.         var _t = this; // event scopes
  211.         // XMLHttpRequest won't work on interneh splorerer
  212.         this.method = method||'GET';
  213.         this.event = {};
  214.         this.state = fn||Poll.noop;
  215.         this.ajax = new XMLHttpRequest;
  216.  
  217.         this.ajax.onreadystatechange = function(event){ // simple event mapper
  218.             //console.log(_t.ajax.readyState,event);
  219.             var eventname = Poll._[_t.ajax.readyState];
  220.             if (_t.state[eventname]) _t.state[eventname].call(_t,event);
  221.         };
  222.  
  223.         return this;
  224.     };
  225.  
  226.     Poll.prototype.getTime = function () {
  227.         //this.bg.open('GET','http://www.rescreatu.com/getTime.php');
  228.     };
  229.  
  230.     Poll.prototype.setEvent = function (name, fn) {
  231.         this.event[name] = fn;
  232.         //this.bg.open('GET','http://www.rescreatu.com/getTime.php');
  233.     };
  234.  
  235.     Poll.prototype.setEvents = function (fn) {
  236.         this.event = fn;
  237.         //this.bg.open('GET','http://www.rescreatu.com/getTime.php');
  238.     };
  239.  
  240.     Poll.prototype.callback = function (url, events, fn, method, async) {
  241.         if (events) this.event = events;
  242.         if (fn) this.state = fn;
  243.         if (method) this.method = method;
  244.         return this.ajax.open(this.method, url, (async===false?false:true));
  245.     };
  246.  
  247.     Poll._ = ['start','open','send','load','end'];
  248.  
  249.     Poll.noop = {
  250.         start:function(event){ if (this.event.start) this.event.start.call(this,event); }
  251.     ,   open:function(event){
  252.             var params = null;
  253.             if (this.event.open) params = this.event.open.call(this,open)||null;
  254.             this.ajax.send(params);
  255.         }
  256.     ,   send:function(event){}
  257.     ,   load:function(event){}
  258.     ,   end:function(event){
  259.             switch (this.ajax.status) {
  260.                 case 200:
  261.                     if (this.event.success) this.event.success.call(this,event);
  262.                 break;
  263.                 default:
  264.                     if (this.event.unexpected) this.event.unexpected.call(this,event);
  265.                 break;
  266.             };
  267.         }
  268.     };
  269.  
  270. /* very sloppy and lazy, but effective template system */
  271.     function Temp () {
  272.         this.index = {
  273.             $:[]
  274.         ,   _:{}
  275.         ,   css:{
  276.                 dynamic : {
  277.                     'a.uc':'color:#000;font-weight:bold'
  278.                 ,   'div[data-mid]':'margin:2px 0'
  279.                 ,   'div[data-mid]:hover':'background-color:#eee'
  280.                 ,   '.space':'margin-left:5px'
  281.                 ,   '.wrap':'border:#ccc 1px solid; border-radius:5px; float:left'
  282.                 ,   '.btn':'background-color:#eee; cursor:pointer; padding:5px'
  283.                 ,   '.btn:hover':'background-color:#ddd; padding:5px'
  284.                 ,   '.input':'background-color:transparent; border:none; color:#59534C; font-family:Tahoma, Arial, Verdana; padding:4px'
  285.                 ,   '.input:focus':'outline:none'
  286.                 ,   '#room':'font-size:10pt; height:400px; margin:0px 10px; overflow-Y:scroll; word-wrap:break-word'
  287.                 ,   '#room img':'max-height:15px'
  288.                 ,   '#toolbar':'border-top:#e1ecef 1px solid; margin:0 10px; padding-top:10px'
  289.                 ,   '#btn-alerts':''
  290.                 }
  291.             }
  292.         };
  293.  
  294.         return this;
  295.     };
  296.  
  297.     Temp.ele = function (node,style,attr,events) {
  298.         var node = document.createElement(node)
  299.         ,   index;
  300.         if (style) for (index in style) node.style[index] = style[index];
  301.         if (attr) for (index in attr) node.setAttribute(index,attr[index]);
  302.         if (events) for (index in events) node.addEventListener(index,events[index],false);
  303.         return node;
  304.     };
  305.  
  306.     Temp.prototype.appendTo = function (index,obj) { // get object by name
  307.         return this.index.$[index].appendChild(obj);
  308.     };
  309.  
  310.     Temp.prototype.get = function (name) { // get object by name
  311.         return this.index.$[this.index._[name]];
  312.     };
  313.  
  314.     Temp.prototype.geti = function (name) { // get index by name
  315.         return this.index._[name];
  316.     };
  317.  
  318.     Temp.prototype.set = function (name,value,appendTo) {
  319.         if (this.index._[name]) this.index.$[this.index._[name]] = value;
  320.         else {
  321.             this.index._[name] = this.index.$.length;
  322.             this.index.$.push(value);
  323.         };
  324.         if (appendTo) {
  325.             if (typeof this.index._[appendTo] == 'number') {
  326.                 this.index.$[this.index._[appendTo]].appendChild(this.index.$[this.index._[name]]);
  327.             }
  328.             else if (appendTo.appendChild) appendTo.appendChild(this.index.$[this.index._[name]]);
  329.         };
  330.         return this.index._[name];
  331.     };
  332.  
  333.     Temp.prototype.setStyle = function (name) {
  334.         var si=this.geti(name),i,css='';
  335.         for (i in this.index.css[name]) css+=i+'{'+this.index.css[name][i]+'}';
  336.         this.index.$[si].innerHTML = css;
  337.     };
  338.  
  339.     Temp.prototype.getContent = function () {
  340.         var ci = this.set('content',document.getElementById('content')); // Content: Wrapper for the old body
  341.         this.index.$[ci].removeChild(document.getElementById('body')); // remove old body
  342.         this.set('header',document.getElementById('breadcrumbs')); // breadcrumbs becomes our header
  343.         return this;
  344.     };
  345.  
  346.     Temp.prototype.makeBody = function () {
  347.         this.set('body',Temp.ele('div',{
  348.             background:'white url(http://www.rescreatu.com/system/schemes/images/content-corner-bottom.gif) no-repeat center bottom'
  349.         ,   float:'left'
  350.         ,   minHeight:'757px'
  351.         ,   width:'630px'
  352.         }),'content');
  353.         return this;
  354.     };
  355.  
  356.     Temp.prototype.makeStyle = function (name,noset) {
  357.         name = name||'style';
  358.         this.set(name,Temp.ele('style'),document.getElementsByTagName('head')[0]);
  359.         if(!noset) this.setStyle(name);
  360.         return this;
  361.     };
  362.  
  363.     Temp.userCaption = function (uid, name, css) {
  364.         var anchor = Temp.ele('a',false,{
  365.             class:'uc'
  366.         ,   'data-uid':uid
  367.         ,   href:'../profile.php?id='+uid
  368.         ,   style:css||null
  369.         ,   target:'_blank'
  370.         });
  371.         anchor.appendChild(document.createTextNode(name));
  372.         return anchor;
  373.     };
  374.  
  375. /* Todo:
  376.     make work the same with minichat, standard chat, and/or popup window chat
  377.  */
  378.     function Room (tmp) {
  379.         this.index = {
  380.             $:[],
  381.             _:{}
  382.         };
  383.         this.first = this.last = this.msgcount = this.offsetTop = 0;
  384.         this.tmp = tmp;
  385.         this.get = new Poll('GET');
  386.         this.post = new Poll('POST');
  387.  
  388.         return this;
  389.     };
  390.  
  391.     Room.prototype.start = function () {
  392.         var T = this, strikes = 0;
  393.  
  394.         this.get.callback('http://www.rescreatu.com/tagbox2/getChat.php?chat=1',{
  395.             'success' : function (event) {
  396.                 if (data.options.limit > 20) { // user wants more messages, so we get a new list based on last message's id
  397.                     var last = this.ajax.responseXML.firstChild.lastChild.getAttribute('id') // expects lastChild to be a message
  398.                     ,   limit = last-(data.options.limit>data.options.threshold&&data.options.threshold>0?data.options.threshold:data.options.limit); // make sure limit does not exceed threshold
  399.                     T.get.setEvent('success',procedure);
  400.                     console.log(limit, limit>1);
  401.                     T.get.callback('http://www.rescreatu.com/tagbox2/getChat.php?chat=1&last='+(limit>1?limit:1)); // we can only start where mid is 2
  402.                 }
  403.                 else procedure.call(this);
  404.             }
  405.         ,   'unexpected' : function () {
  406.                 keepAlive.call(this);
  407.             }
  408.         });
  409.  
  410.         this.post.setEvents({
  411.             'open' : function (event) {
  412.                 clearTimeout(data.timer);
  413.                 T.tmp.index.$[T.ii].style.color = '#aaa';
  414.                 T.tmp.index.$[T.ii].readonly = 'readonly';
  415.                 T.tmp.index.$[T.si].setAttribute('data-disabled','true');
  416.                 this.ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
  417.                 if (data.options.autolink == 'true'){
  418.                     T.tmp.index.$[T.ii].value = T.tmp.index.$[T.ii].value.replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, '[url=$1]');
  419.                 }
  420.                 return 'chat=1&message='+encodeURIComponent(T.tmp.index.$[T.ii].value);
  421.             },
  422.             'success' : function (event) {
  423.                 T.tmp.index.$[T.ii].style.color = '';
  424.                 T.tmp.index.$[T.ii].readonly = '';
  425.                 T.tmp.index.$[T.ii].value = '';
  426.                 T.tmp.index.$[T.ii].focus();
  427.                 T.tmp.index.$[T.si].setAttribute('data-disabled','false');
  428.                 T.parse(this,true);
  429.                 strikes = 0;
  430.                 clearTimeout(data.timer);
  431.                 data.timer = setTimeout(loopFunc, data.timeout);
  432.             }
  433.         ,   'unexpected' : function () {
  434.                 keepAlive.call(this);
  435.             }
  436.         });
  437.  
  438.         return this;
  439.         function procedure () {
  440.             T.get.setEvent('success',function () { // simplify success event, which we run very often
  441.                 T.parse(this);
  442.                 strikes = 0;
  443.                 clearTimeout(data.timer);
  444.                 data.timer = setTimeout(loopFunc, data.timeout);
  445.             });
  446.  
  447.             T.parse(this);
  448.             strikes = 0;
  449.             clearTimeout(data.timer);
  450.             data.timer = setTimeout(loopFunc, data.timeout);
  451.  
  452.             loader.style.display = 'none';
  453.             document.body.style.overflow = 'auto';
  454.             document.body.scrollTop = T.offsetTop;
  455.         };
  456.         function loopFunc () {
  457.             T.get.callback('http://www.rescreatu.com/tagbox2/getChat.php?chat=1&last='+T.last);
  458.         };
  459.         function keepAlive () {
  460.             ++strikes;
  461.             clearTimeout(data.timer);
  462.             if (strikes == 3) {
  463.                 var oldTO = data.timeout;
  464.                 data.timeout = data.timeout * 4;
  465.                 this.setEvent('success',function(){
  466.                     T.get.setEvent('success',function () { // simplify success event, which we run very often
  467.                         T.parse(this);
  468.                         strikes = 0;
  469.                         clearTimeout(data.timer);
  470.                         data.timer = setTimeout(loopFunc, data.timeout);
  471.                     });
  472.                     data.timeout = oldTO;
  473.                     strikes = 0;
  474.                     clearTimeout(data.timer);
  475.                     data.timer = setTimeout(loopFunc, data.timeout);
  476.                 });
  477.                 if (confirm('Unable to query server, would you like to keep trying?')) data.timer = setTimeout(loopFunc, data.timeout);
  478.             }
  479.             else data.timer = setTimeout(loopFunc, data.timeout);
  480.         };
  481.         //this.post = new Poll('GET');
  482.     }
  483.  
  484.     Room.prototype.makeRoom = function () {
  485.         this.ri = this.tmp.set('room', Temp.ele('div',false,{
  486.             id:'room'
  487.         }), 'body');
  488.         this.offsetTop = document.getElementById('sidebar').offsetTop;
  489.         this.scrollHeight = this.tmp.index.$[this.ri].scrollHeight;
  490.  
  491.         return this;
  492.     }
  493.  
  494.     Room.prototype.makeToolbar = function () {
  495.         var te = false, beText = document.createTextNode('Expand View'), m=10, T=this;
  496.  
  497.         this.be = this.tmp.set('btn-expand',Temp.ele('span',{
  498.             'cursor':'pointer'
  499.         ,   'float':'left'
  500.         ,   'font-size':'11px'
  501.         ,   'padding':'7px 0 0 15px'
  502.         },false,{
  503.             'mouseout':function () {
  504.                 this.style.textDecoration = 'none';
  505.             },
  506.             'mouseover':function () {
  507.                 this.style.textDecoration = 'underline';
  508.             },
  509.             'mouseup':function () {
  510.                 te = !te;
  511.                 if (te) {
  512.                     beText.nodeValue = 'Collapse View';
  513.                     T.tmp.index.$[T.ri].style.height = 'auto';
  514.                     T.tmp.index.$[T.ri].style.overflowY = 'visible';
  515.                 }
  516.                 else {
  517.                     beText.nodeValue = 'Expand View';
  518.                     T.tmp.index.$[T.ri].style.height = '';
  519.                     T.tmp.index.$[T.ri].style.overflowY = 'scroll';
  520.                 }
  521.             }
  522.         }),'header');
  523.         this.tmp.appendTo(this.be,beText);
  524.  
  525.  
  526.         this.tmp.set('toolbar',Temp.ele('div',false,{
  527.             id:'toolbar'
  528.         }),'body');
  529.  
  530.  
  531.         this.ai = this.tmp.set('btn-alerts',Temp.ele('div',false,{
  532.             id:'btn-alerts'
  533.         ,   class:'btn wrap'
  534.         },{
  535.             'mouseup':function(event){
  536.                 alert('Alerts not yet worthy');
  537.             }
  538.         }),'toolbar');
  539.         this.tmp.appendTo(this.ai,document.createTextNode('a'));
  540.  
  541.  
  542.         this.wi = this.tmp.set('input-wrap',Temp.ele('div',false,{
  543.             class:'wrap space'
  544.         }),'toolbar');
  545.  
  546.  
  547.         this.ii = this.tmp.set('input',Temp.ele('textarea',false,{
  548.             class:'input'
  549.         },{
  550.             'keypress':function(event){
  551.                 if (event.which === 13) T.post.callback('http://www.rescreatu.com/tagbox2/getChat.php?chat=1&last='+T.last);
  552.             }
  553.         }),'input-wrap');
  554.         this.tmp.index.$[this.ii].focus();
  555.  
  556.  
  557.         this.si = this.tmp.set('btn-submit',Temp.ele('div',false,{
  558.             class:'btn wrap space'
  559.         ,   'data-disabled':'false'
  560.         },{
  561.             'mouseup' : function (event) {
  562.                 if (this.getAttribute('data-disabled') != 'true') T.post.callback('http://www.rescreatu.com/tagbox2/getChat.php?chat=1&last='+T.last);
  563.             }
  564.         }),'toolbar');
  565.         this.tmp.appendTo(this.si, document.createTextNode('send'));
  566.  
  567.         var plus = 12; // 10 for margins 2 for wrapper border
  568.         plus += this.tmp.index.$[this.ai].offsetWidth;
  569.         plus += this.tmp.index.$[this.si].offsetWidth;
  570.         plus = this.tmp.index.$[this.ri].offsetWidth-plus;
  571.         this.tmp.index.$[this.wi].style.width = plus+'px';
  572.         this.tmp.index.$[this.ii].style.width = (plus-8)+'px'; // 8 for padding
  573.  
  574.         return this;
  575.     };
  576.  
  577.     Room.prototype.keepClean = function () {
  578.         if (data.options.threshold < 1) return;
  579.         var limit = this.last-data.options.threshold;
  580.         if (limit > this.first) for (; this.first < limit; ++this.first) this.tmp.index.$[this.ri].removeChild(this.tmp.index.$[this.ri].firstChild);
  581.         //if (data.options.threshold > 0 && this.msgcount > data.options.threshold) for (; this.msgcount > data.options.threshold; --this.msgcount) this.tmp.index.$[this.ri].removeChild(this.tmp.index.$[this.ri].firstChild);
  582.     };
  583.  
  584.     Room.prototype.checkScroll = function () {
  585.         var diff = this.tmp.index.$[this.ri].scrollHeight-this.scrollHeight; // difference of room scrollHeight and inital scrollHeight
  586.         return !!(diff<=this.tmp.index.$[this.ri].scrollTop); // true if difference is the same as scrollTop (or greater than just incase), meaning it's scrolled to the bottom
  587.     };
  588.  
  589.     Room.prototype.setScroll = function () {
  590.         return this.tmp.index.$[this.ri].scrollTop = this.tmp.index.$[this.ri].scrollHeight-this.scrollHeight;
  591.     };
  592.  
  593.     Room.prototype.addRow = function (usr, mid, text) {
  594.         var row = Temp.ele('div',false,{'data-mid':mid})
  595.         ,   msg = Temp.ele('span', row);
  596.  
  597. /* NEEDS ATTENTION: innerHTML is bad practice and has potential security flaws, but is our best option with the current system */
  598.         msg.innerHTML = text; // it puts a lot a of trust in contents of messages :(
  599.  
  600.         row.appendChild(usr);
  601.         row.appendChild(document.createTextNode(': '));
  602.         row.appendChild(msg);
  603.  
  604.         this.tmp.index.$[this.ri].appendChild(row);
  605.         this.last = mid;
  606.         ++this.msgcount;
  607.     };
  608.  
  609.     Room.prototype.sysMessage = function (mid, text) {
  610.         var user = Temp.ele('span',{'color':'#f00','fontWeight':'bold'});
  611.         user.appendChild(document.createTextNode('System message'));
  612.         this.addRow(user, mid, text);
  613.     };
  614.  
  615. /* following function needs optimization */
  616.     Room.prototype.parse = function (obj,forceScroll) {
  617.         var i, mid, uid, user, scroll, messages = obj.ajax.responseXML.getElementsByTagName('message');
  618.         if (messages.length < 1) return;
  619.         this.first = this.first||messages[0].getAttribute('id');
  620.         scroll = forceScroll||this.checkScroll(); // return true if at bottom of scroll area
  621.         for (i = 0; i < messages.length; ++i) {
  622.             mid = messages[i].getAttribute('id');
  623.             if ((uid = Room.parseUser(messages[i].childNodes[0].textContent)) === false) {
  624.                 if (data.playAudio===null) data.playAudio = Audio.test(messages[i].childNodes[1].textContent); // set alerts by only regexp for system message
  625.                 this.sysMessage(mid, messages[i].childNodes[1].textContent);
  626.             }
  627.             else {
  628.                 if (data.playAudio===null) { // only begin to set sound if not already set
  629.                     if (typeof data.usersound[uid] == 'number') data.playAudio = data.usersound[uid]; // set by user id posting
  630.                     else if (typeof data.usersound[data.userlist[uid][0].toLowerCase()] == 'number') data.playAudio = data.usersound[data.userlist[uid][0].toLowerCase()]; // set by username posting
  631.                     else data.playAudio = Audio.test(messages[i].childNodes[1].textContent); // set by regexp
  632.                 };
  633.                 this.addRow(Temp.userCaption(uid,data.userlist[uid][0],data.userlist[uid][1]), mid, messages[i].childNodes[1].textContent);
  634.             }
  635.         };
  636.         this.keepClean();
  637.         if (scroll) this.setScroll(); // only scroll to the bottom if were at the bottom
  638.         if (data.playAudio !== null && data.options.audio !== 'false') {
  639.             Audio.play(data.playAudio);
  640.             data.playAudio = null;
  641.         }
  642.     };
  643.  
  644. /*parsing old html pseudocode style to extract id, username, and color */
  645.     Room.parseUser = function (us) {
  646.         if (/system message/i.test(us)) return false; // return false if username is system message (needs work)
  647.         var uid = us.substring(49, us.indexOf('" target="_blank"'));
  648.         if (!data.userlist[uid]) { // only if we haven't seen them yet
  649.             var un = us.substring(us.indexOf('<font color=')+12)
  650.             ,   os = un.indexOf('>')
  651.             ,   css = un.substring(0,os);
  652.             un = un.substring(++os);
  653.             un = un.substring(0,un.indexOf('<'));
  654.             data.userlist[uid] = [un,(css=='black'?null:'color:'+css+';')]; // saves username color/css in an array under user id
  655.             //console.log(uid,un,css);
  656.         };
  657.         return uid; // returns user id
  658.     };
  659.  
  660.     function inArray(arr,val) {
  661.         for (var i = 0; i < arr.length; ++i) if (arr[i] === val) return true;
  662.         return false;
  663.     }
  664.  
  665.     function isArray(arr) {
  666.         return Object.prototype.toString.call(arr) === "[object Array]";
  667.     }
  668. })(window);
Add Comment
Please, Sign In to add comment