lastest modifies
[brisk.git] / web / commons.js
index a38a36c..462ce2e 100644 (file)
@@ -1,8 +1,8 @@
 /*
- *  brisk - commons.js
+ *  brisk / fieldify - commons.js
  *
- *  Copyright (C) 2006-2012 Matteo Nastasi
- *                          mailto: nastasi@alternativeoutput.it 
+ *  Copyright (C) 2006-2016 Matteo Nastasi
+ *                          mailto: nastasi@alternativeoutput.it
  *                                  matteo.nastasi@milug.org
  *                          web: http://www.alternativeoutput.it
  *
  *
  */
 
+var __mop_commons_vers="0.1.0"
+
 var PLAYERS_N = 3;
 var EXIT_BAN_TIME = 3600;
 var cookiepath = "/brisk/";
 
 var mlang_commons = { 'imgload_a' : { 'it' : 'Immagini caricate ',
                                       'en' : 'Loaded images ' },
-                      'imgload_b' : { 'it' : '%.', 
+                      'imgload_b' : { 'it' : '%.',
                                       'en' : '%.' },
                       'gamleav'   : { 'it' : 'Sei sicuro di volere lasciare questa mano?' ,
                                       'en' : 'Are you sure to leave this game?' },
@@ -45,13 +47,15 @@ var mlang_commons = { 'imgload_a' : { 'it' : 'Immagini caricate ',
                                                'en' : '(only aut.)' },
                                       '2'  : { 'it' : '(isolam.to)',
                                                'en' : '(isolation)' } },
-                      'lic_refu'  : { 'it' : 'Rifiutando di sottoscrivere la nuova licenza d\' uso non ti sarà più possibile accedere col tuo utente registrato al sito, sei proprio sicuro di non voler accettare le nuove condizioni d\'uso ?',
-                                      'en' : 'EN Rifiutando di sottoscrivere la nuova licenza d\' uso non ti sarà più possibile accedere col tuo utente registrato al sito, sei proprio sicuro di non voler accettare le nuove condizioni d\'uso ?'
+                      'tos_refu'  : { 'it' : 'Rifiutando di sottoscrivere i nuovi termini del servizio non ti sarà più possibile accedere come utente registrato al sito, sei proprio sicuro di voler rifiutare le nuove condizioni d\'uso ?',
+                                      'en' : 'EN Rifiutando di sottoscrivere i nuovi termini del servizio non ti sarà più possibile accedere come utente registrato al sito, sei proprio sicuro di voler rifiutare le nuove condizioni d\'uso ?'
                                     }
                     };
 
 function $(id) { return document.getElementById(id); }
 
+function $C(cls) { return document.getElementsByClassName(cls); }
+
 function dec2hex(d, padding)
 {
     var hex = Number(d).toString(16);
@@ -64,7 +68,15 @@ function dec2hex(d, padding)
     return hex;
 }
 
-function getStyle(x,IEstyleProp, MozStyleProp) 
+function ends_with(s, suffix)
+{
+    if (s.indexOf(suffix, s.length - suffix.length) !== -1) {
+        return true;
+    }
+    return false;
+}
+
+function getStyle(x,IEstyleProp, MozStyleProp)
 {
     if (x.currentStyle) {
        var y = x.currentStyle[IEstyleProp];
@@ -81,7 +93,7 @@ function getStyle(x,IEstyleProp, MozStyleProp)
 
     /*Copy the default setInterval behavior*/
     var nativeSetInterval = window.setInterval;
-    window.setInterval = function(fn,ms) {             
+    window.setInterval = function(fn,ms) {
        var param = [];
        if(arguments.length <= 2)       {
            return nativeSetInterval(fn,ms);
@@ -89,16 +101,16 @@ function getStyle(x,IEstyleProp, MozStyleProp)
        else {
            for(var i=2;i<arguments.length;i+=1) {
                param[i-2] =  arguments[i];
-           }   
+           }
        }
-       
+
        if(typeof(fn)=='function') {
-           
+
            return (function (fn,ms,param) {
-               var fo = function () {                                                          
+               var fo = function () {
                    fn.apply(window,param);
-               };                      
-               return nativeSetInterval(fo,ms); 
+               };
+               return nativeSetInterval(fo,ms);
            })(fn,ms,param);
        }
        else if(typeof(fn)=='string')
@@ -113,7 +125,7 @@ function getStyle(x,IEstyleProp, MozStyleProp)
 
     /*Copy the default setTimeout behavior*/
     var nativeSetTimeout = window.setTimeout;
-    window.setTimeout = function(fn,ms) {              
+    window.setTimeout = function(fn,ms) {
        var param = [];
        if(arguments.length <= 2)       {
            return nativeSetTimeout(fn,ms);
@@ -121,16 +133,16 @@ function getStyle(x,IEstyleProp, MozStyleProp)
        else {
            for(var i=2;i<arguments.length;i+=1) {
                param[i-2] =  arguments[i];
-           }   
+           }
        }
-       
+
        if(typeof(fn)=='function') {
-           
+
            return (function (fn,ms,param) {
-               var fo = function () {                                                          
+               var fo = function () {
                    fn.apply(window,param);
-               };                      
-               return nativeSetTimeout(fo,ms); 
+               };
+               return nativeSetTimeout(fo,ms);
            })(fn,ms,param);
        }
        else if(typeof(fn)=='string')
@@ -145,7 +157,7 @@ function getStyle(x,IEstyleProp, MozStyleProp)
 
 })()
 
-function addEvent(obj,type,fn)
+function addEvent(obj, type, fn)
 {
     if (obj.addEventListener) {
         obj.addEventListener( type, fn, false);
@@ -235,7 +247,7 @@ function update_images()
 function preload_images(arr,idx)
 {
     var im = new Image;
-    
+
     // $("imgct").innerHTML = "Stiamo caricando "+arr[idx]+"%.<br>";
     im.onload =   update_images;
     im.onerror =  error_images;
@@ -268,9 +280,9 @@ function send_mesg(mesg)
 {
     var xhr_wr = createXMLHttpRequest();
     var is_conn = (sess == "not_connected" ? false : true);
-    
+
     // alert("xhr_wr: "+xhr_wr+"  is_conn: "+is_conn);
-    xhr_wr.open('GET', 'index_wr.php?'+(is_conn ? 'sess='+sess+'&' : '')+'mesg='+mesg, (is_conn ? true : false));
+    xhr_wr.open('GET', 'index_wr.php?&'+(is_conn ? 'sess='+sess : '')+'&stp='+gst.st+'&mesg='+mesg, (is_conn ? true : false));
     xhr_wr.setRequestHeader("If-Modified-Since", new Date().toUTCString());
     xhr_wr.onreadystatechange = function() { return; };
     if (typeof(g_debug) == 'number' && g_debug > 0
@@ -293,13 +305,14 @@ function send_mesg(mesg)
   if var name == '__POST__' than all other vars will be managed as POST content
                                  and the call will be a POST
  */
-function server_request()
+function server_request(page, sess)
 {
     var xhr_wr = createXMLHttpRequest();
+    var tout = -1;
     var i, collect = "", post_collect = null, is_post = false;
 
     if (arguments.length > 0) {
-        for (i = 0 ; i < arguments.length ; i+= 2) {
+        for (i = 2 ; i < arguments.length ; i+= 2) {
             if (arguments[i] == "__POST__") {
                 is_post = true;
                 post_collect = "";
@@ -312,30 +325,75 @@ function server_request()
                 collect += (i == 0 ? "" : "&") + arguments[i] + "=" + encodeURIComponent(arguments[i+1]);
         }
     }
-    // alert("Args: "+arguments.length);
-
-    var is_conn = (sess == "not_connected" ? false : true);
-    
-    // console.log("server_request:preresp: "+xhr_wr.responseText);
-
+    var uri = page + '?' + (sess != null ? 'sess=' + sess + '&' : '') + collect;
     if (is_post) {
-        xhr_wr.open('POST', 'index_wr.php?'+(is_conn ? 'sess='+sess+'&' : '')+collect, false);
+        xhr_wr.open('POST', uri, false);
         xhr_wr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
     }
     else {
-        xhr_wr.open('GET', 'index_wr.php?'+(is_conn ? 'sess='+sess+'&' : '')+collect, false);
+        xhr_wr.open('GET', uri, false);
     }
-    xhr_wr.onreadystatechange = function() { return; };
+    if (tout > 0) {
+        xhr_wr.timeout = tout;
+    }
+
+    xhr_wr.onreadystatechange = function() {
+        console.log('we are here');
+        return; };
     xhr_wr.send(post_collect);
-    
+
     if (xhr_wr.responseText != null) {
         // console.log("server_request:resp: "+xhr_wr.responseText);
         return (xhr_wr.responseText);
-    } 
+    }
     else
         return (null);
 }
 
+
+function server_asyncreq(async_req, page, sess)
+{
+    var xhr_wr = createXMLHttpRequest();
+    var tout = -1;
+    var i, collect = "", post_collect = null, is_post = false;
+
+    if (arguments.length > 0) {
+        for (i = 3 ; i < arguments.length ; i+= 2) {
+            if (arguments[i] == "__POST__") {
+                is_post = true;
+                post_collect = "";
+                i -= 1;
+                continue;
+            }
+            else if (arguments[i] == "__TOUT__") {
+                tout = arguments[i+1];
+                continue;
+            }
+            if (is_post)
+                post_collect += (post_collect == "" ? "" : "&") + arguments[i] + "=" + encodeURIComponent(arguments[i+1]);
+            else
+                collect += (i == 0 ? "" : "&") + arguments[i] + "=" + encodeURIComponent(arguments[i+1]);
+        }
+    }
+    var already_quest = (page.indexOf('?') != -1);
+    var uri = page + (already_quest ? '&' : '?') + (sess != null ? 'sess=' + sess + '&' : '') + collect;
+    if (is_post) {
+        xhr_wr.open('POST', uri, true);
+        xhr_wr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
+    }
+    else {
+        xhr_wr.open('GET', uri, true);
+    }
+    if (tout > 0) {
+        xhr_wr.timeout = tout;
+    }
+
+    xhr_wr.onreadystatechange = async_req;
+    xhr_wr.send(post_collect);
+
+    return;
+}
+
 /* Stat: CHAT and TABLE */
 
 function chatt_checksend(obj,e)
@@ -358,7 +416,12 @@ function chatt_checksend(obj,e)
 }
 function act_chatt(value)
 {
-    send_mesg("chatt|"+encodeURIComponent(value));
+    if (value.substring(0, 6) == "/info ") {
+        info_show(value.substring(6));
+    }
+    else {
+        send_mesg("chatt|"+encodeURIComponent(value));
+    }
     /*
     obj.disabled = true;
     obj.value = "";
@@ -406,7 +469,7 @@ function act_mesgtoadm()
 
 function act_tav()
 {
-    act_chatt('/tav '+$('txt_in').value); 
+    act_chatt('/tav '+$('txt_in').value);
     $('txt_in').value = '';
 }
 
@@ -425,11 +488,6 @@ function act_roadmap()
     send_mesg("roadmap");
 }
 
-function act_whysupport()
-{
-    send_mesg("whysupport");
-}
-
 function act_lascio()
 {
     send_mesg("lascio");
@@ -468,8 +526,8 @@ function act_shutdown()
 function postact_logout()
 {
     // alert("postact_logout");
-    try { 
-       hstm.abort();
+    try {
+       xstm.abort();
     } catch (e) {}
 
     // eraseCookie("sess");
@@ -478,10 +536,10 @@ function postact_logout()
 
 /*
   type - 'hard' or 'soft'
-  code - if soft: accept (0), refuse (1), after (2)
-         if hard: accept (0), refuse (1)
+  code - if soft: accept (0), refuse (1), download (2), later (3)
+         if hard: accept (0), refuse (1), download (2)
  */
-function act_licencemgr(type, code, lice_curr, lice_vers)
+function act_tosmgr(type, code, tos_curr, tos_vers)
 {
     if (type != "soft" && type != "hard") {
         return false;
@@ -489,23 +547,33 @@ function act_licencemgr(type, code, lice_curr, lice_vers)
     switch (code) {
     case 0:
     case 1:
-        send_mesg("licencemgr|"+type+"|"+code+"|"+lice_curr+"|"+lice_vers);
+        send_mesg("tosmgr|"+type+"|"+code+"|"+tos_curr+"|"+tos_vers);
         break;
     case 2:
         break;
     default:
         break;
     }
+
     return true;
 }
 
-function lice_confirm(val)
+function tos_confirm(val, url)
 {
-    if (val == 1) {
-        return (window.confirm(mlang_commons['lic_refu'][g_lang]));
-    }
+    var dlm;
 
-    return true;
+    switch (val) {
+    case 1:
+        return (window.confirm(mlang_commons['tos_refu'][g_lang]));
+        break;
+    case 2:
+        dlm = new download_mgr(url);
+        return false;
+        break;
+    default:
+        return true;
+        break;
+    }
 }
 
 /*
@@ -545,7 +613,7 @@ function slowimg(img,x1,y1,deltat,free,action,srcend) {
 }
 
 slowimg.prototype = {
-    img: null, 
+    img: null,
     st: null,
     x0: 0,
     y0: 0,
@@ -562,20 +630,20 @@ slowimg.prototype = {
     tout: 0,
     action: null,
     srcend: null,
-    
+
     setstart: function(x0,y0)
     {
        this.x0 = x0;
        this.y0 = y0;
     },
-    
+
     setaction: function(act)
     {
        this.action = act;
     },
-    
 
-    settime: function(time) 
+
+    settime: function(time)
     {
        this.time = (time < this.deltat ? this.deltat : time);
        this.step_n = parseInt(this.time / this.deltat);
@@ -588,17 +656,17 @@ slowimg.prototype = {
             this.step_free = parseInt(this.step_n * this.free);
         }
     },
-    
+
     start: function(st)
     {
        // $("logz").innerHTML += "               xxxxxxxxxxxxxxxxxxxxxSTART<br>";
        this.st = st;
        this.st.st_loc_new++;
-       
+
        this.img.style.visibility = "visible";
        setTimeout(function(obj){ obj.animate(); }, this.deltat, this);
     },
-    
+
     animate: function()
     {
        // $("log").innerHTML = "Val " + this.step_cur + " N: " + this.step_n + "<br>";
@@ -659,7 +727,7 @@ function div_show(div)
   block_time:
   */
 
-function notify_document(st, text, tout, butt, confirm_func, w, h, is_opa, block_time)
+function notify_document(st, text, tout, butt, confirm_func, confirm_func_args, w, h, is_opa, block_time)
 {
     var i, clo, clodiv_ctx, clodiv_wai, box;
 
@@ -667,7 +735,7 @@ function notify_document(st, text, tout, butt, confirm_func, w, h, is_opa, block
 
     this.ancestor = document.body;
     this.confirm_func = confirm_func;
-
+    this.confirm_func_args = confirm_func_args;
     this.st.st_loc_new++;
 
     clodiv_ctx = document.createElement("div");
@@ -695,8 +763,10 @@ function notify_document(st, text, tout, butt, confirm_func, w, h, is_opa, block
     cont.style.borderBottomStyle = "solid";
     cont.style.borderBottomWidth = "1px";
     cont.style.borderBottomColor = "gray";
-    cont.style.height = (h - 30)+"px";
+    cont.style.height = (h - 50)+"px";
     cont.style.overflow = "auto";
+    cont.style.textAlign = "left";
+    cont.style.padding = "8px";
     cont.style.fontFamily = "monospace";
     cont.innerHTML = text;
 
@@ -742,6 +812,7 @@ notify_document.prototype = {
     tblkid: null,
 
     confirm_func: null,
+    confirm_func_args: [],
 
     ret: -1,
 
@@ -790,7 +861,11 @@ notify_document.prototype = {
     hide: function(val)
     {
         if (this.confirm_func != null) {
-            if (this.confirm_func(val) == false) {
+            var args;
+
+            args = [ val ].concat(this.confirm_func_args);
+
+            if (this.confirm_func.apply(null, args) == false) {
                 return false;
             }
         }
@@ -808,11 +883,11 @@ function notify_ex(st, text, tout, butt, w, h, is_opa, block_time)
 {
     var clo, box;
     var t = this;
-    
+
     this.st = st;
 
     this.ancestor = document.body;
-    
+
     this.st.st_loc_new++;
 
     clo = document.createElement("input");
@@ -861,9 +936,9 @@ function notify_ex(st, text, tout, butt, w, h, is_opa, block_time)
     box.style.visibility = "visible";
 
     this.notitag = box;
-    
+
     this.ancestor.appendChild(box);
-    
+
     this.toutid = setTimeout(function(obj){ obj.unblock(); }, tout, this);
 
     if (block_time != 0) {
@@ -883,7 +958,7 @@ notify_ex.prototype = {
     notitag: null,
     toutid: null,
     clo: null,
-    clodiv: null, 
+    clodiv: null,
     butt: null,
     tblkid: null,
 
@@ -893,7 +968,7 @@ notify_ex.prototype = {
            this.st.st_loc++;
        }
     },
-    
+
     hide: function()
     {
        clearTimeout(this.toutid);
@@ -912,12 +987,6 @@ function notify(st, text, tout, butt, w, h)
 {
     notify_ex.call(this, st, text, tout, butt, w, h, false, 0);
 }
-       
-
-function $(id) { 
-    return document.getElementById(id); 
-}
-
 
 function globst() {
     this.st = -1;
@@ -953,7 +1022,7 @@ globst.prototype = {
 function remark_step()
 {
     var ct = $("remark").l_remct;
-    
+
     if (ct != 0) {
        ct++;
        if (ct > 2)
@@ -964,7 +1033,7 @@ function remark_step()
     }
     else
        $("remark").className = "remark0";
-    
+
     return;
 }
 
@@ -986,7 +1055,7 @@ function remark_off()
 function italizer(ga)
 {
     var pre, pos;
-    if (ga[0] & 2) 
+    if (ga[0] & 2)
         return "<i>"+ga[1]+"</i>";
     else
         return ga[1];
@@ -1013,14 +1082,28 @@ var chatt_lines_n = 0;
 
 var CHATT_MAXLINES = 40;
 
-function user_decorator(user)
+function user_decorator(user, is_real)
 {
-    var name;
-    var flags = user[0];
-    if ((flags & 0x03) != 0)
-        name = "<span class='au" + (flags & 0x03) + "'>"+user[1]+"</span>";
-    else
+    var name, i, sp = "", cl = "";
+    var flags = user[0] & 0x03 | ((user[0] & 0x0c0000) >> 16);
+
+    // console.log(user[1]+" FLAGS: "+flags);
+
+    for (i = 0 ; i < 4 ; i++) {
+        if (flags & (1 << i)) {
+            cl += sp + "au" + i + (is_real ? "" : "_off");
+            sp = " ";
+        }
+    }
+
+    if (flags != 0) {
+        name = "<span class='" + cl + "'><span class='" +
+        (is_real && (flags & 0xfffffe && ((flags & 0x01) == 0)) ? "id_usr" : "") +
+        "'>" + user[1] + "</span></span>";
+    }
+    else {
         name = user[1];
+    }
 
     return (name);
 }
@@ -1030,9 +1113,9 @@ function user_dec_and_state(el)
     var content = "";
     var val_el;
 
-    content = user_decorator(el);
+    content = user_decorator(el, true);
     content += state_add(el[0],(typeof(el[2]) != 'undefined' ? el[2] : null));
-    
+
     return (content);
 }
 
@@ -1045,7 +1128,7 @@ function chatt_sub(dt,data,str)
     var flags;
     var isauth;
     var bolder = [ (data[0] | 1), data[1] ];
-    name = user_decorator(bolder);
+    name = user_decorator(bolder, false);
 
     if ($("txt").scrollTop + parseInt(getStyle($("txt"),"height", "height")) -  $("txt").scrollHeight >= 0)
         must_scroll = true;
@@ -1067,7 +1150,7 @@ function chatt_sub(dt,data,str)
     }
     // $("txt").innerHTML;
 
-    
+
     if (must_scroll) {
         $("txt").scrollTop = 10000000;
     }
@@ -1092,8 +1175,10 @@ function readCookie(name) {
        var ca = document.cookie.split(';');
        for(var i=0;i < ca.length;i++) {
                var c = ca[i];
-               while (c.charAt(0)==' ') c = c.substring(1,c.length);
-               if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
+               while (c.charAt(0)==' ')
+                    c = c.substring(1,c.length);
+               if (c.indexOf(nameEQ) == 0)
+                    return c.substring(nameEQ.length,c.length);
        }
        return null;
 }
@@ -1107,24 +1192,24 @@ function onbeforeunload_cb () {
 }
 
 function onunload_cb () {
-    
-    if (typeof(hstm) != "undefined")
-        hstm.the_end = true; 
+
+    if (typeof(xstm) != "undefined")
+        xstm.the_end = true;
 
     act_shutdown();
-    
+
     return(false);
 }
 
 function room_checkspace(emme,tables,inpe)
 {
     nome = "<b>";
-    for (i = 0 ; i < emme ; i++) 
+    for (i = 0 ; i < emme ; i++)
        nome += "m";
     nome += "</b>";
 
     alta = "";
-    for (i = 0 ; i < 5 ; i++) 
+    for (i = 0 ; i < 5 ; i++)
        alta += nome+"<br>";
 
     for (i = 0 ; i < tables ; i++) {
@@ -1162,7 +1247,7 @@ function  unescapeHTML(cont) {
                 var length = div.childNodes.length, results = new Array(length);
             while (length--)
                 results[length] = div.childNodes[length];
-                
+
             for (i=0 ; i<results.length ; i++)
                memo = memo + results[i].nodeValue;
             }
@@ -1209,38 +1294,20 @@ function topbanner_cb()
     // console.log("A: "+a+"  B: "+b);
 }
 
-function sidebanner_init()
-{
-    setInterval(sidebanner_cb, 666);
-}
-
-function sidebanner2_init()
+function sidebanner_init(idx)
 {
-    setInterval(sidebanner2_cb, 666);
-}
-
-function sidebanner_cb()
-{
-    var a, b;
-
-    a = $('sidebanner').style.backgroundColor;
-    b = $('sidebanner').style.borderLeftColor;
-
-    $('sidebanner').style.backgroundColor = b;
-    $('sidebanner').style.borderColor = a+" "+a+" "+a+" "+a;
-
-    // console.log("A: "+a+"  B: "+b);
+    setInterval(function () { sidebanner_cb(idx); }, 666);
 }
 
-function sidebanner2_cb()
+function sidebanner_cb(idx)
 {
     var a, b;
 
-    a = $('sidebanner2').style.backgroundColor;
-    b = $('sidebanner2').style.borderLeftColor;
+    a = $('sidebanner'+idx).style.backgroundColor;
+    b = $('sidebanner'+idx).style.borderLeftColor;
 
-    $('sidebanner2').style.backgroundColor = b;
-    $('sidebanner2').style.borderColor = a+" "+a+" "+a+" "+a;
+    $('sidebanner'+idx).style.backgroundColor = b;
+    $('sidebanner'+idx).style.borderColor = a+" "+a+" "+a+" "+a;
 
     // console.log("A: "+a+"  B: "+b);
 }
@@ -1389,3 +1456,159 @@ function url_complete(parent, url)
         return (host+path+url);
     }
 }
+
+function download_mgr(url)
+{
+    var ifra;
+
+    if ((ifra = $('the_downloader')) == null) {
+        ifra = document.createElement("iframe");
+        ifra.style.display = "none";
+        ifra.id = 'the_downloader';
+        document.body.appendChild(ifra);
+    }
+
+    ifra.contentWindow.location.href = url;
+
+    this.ifra = ifra;
+}
+
+download_mgr.prototype = {
+    ifra: null
+}
+
+function submit_click(obj)
+{
+    obj.form.elements['realsub'].value = obj.id;
+}
+
+function class_check(item, cls_name)
+{
+    if ((" " + item.className + " ").indexOf(" " + cls_name + " ") == -1)
+        return (false);
+    else
+        return (true);
+}
+
+function class_add(item, cls_name)
+{
+    for (i = 1 ; i < arguments.length ; i++) {
+        if (! class_check(item, arguments[i])) {
+            item.className = item.className + " " + arguments[i];
+        }
+    }
+}
+
+function class_rem(item, cls_name)
+{
+    for (i = 1 ; i < arguments.length ; i++) {
+        var item_spc = " " + item.className + " ";
+        var cls_spc = " " + arguments[i] + " ";
+        var cls_out;
+
+        var pos = item_spc.indexOf(cls_spc);
+        if (pos != -1) {
+            cls_out = item_spc.substring(0, pos) + item_spc.substring(pos + cls_spc.length - 1);
+            if (cls_out == " ") {
+                item.className = "";
+            }
+            else {
+                item.className = cls_out.substring(1, cls_out.length - 1);
+            }
+        }
+    }
+}
+
+function class_subst(item, cls_out, cls_in)
+{
+    class_rem(item, cls_out);
+    class_add(item, cls_in);
+}
+
+function nexst(after)
+{
+    if (after != undefined) {
+        this._after = after;
+    }
+}
+
+nexst.next = function(st)
+{
+    if (st === null || st === undefined)
+        st = new nexst();
+    st._step++;
+
+    return st;
+};
+
+nexst.prev = function(st)
+{
+    st._step--;
+}
+
+nexst.reprise = function ()
+{
+    var thiz, args_in, args = [];
+
+    if (arguments.length > 1) {
+        thiz = arguments[0];
+        args_in = arguments[1];
+        }
+    else {
+        thiz = null;
+        args_in = arguments[0];
+        }
+
+    for (var i = 0 ; i < args_in.length ; i++) {
+        args[i] = args_in[i];
+    }
+    return args_in.callee.apply(thiz, args);
+};
+
+nexst.prototype = {
+    _step: 0,     // current step for the async multistep command
+    _data: null,  // data returned at the end of the async command
+    _subst: null, // substatus for nested async command
+    _after: null, // callback (as 'arguments' object) to run at the end
+                  // of last step
+
+    step_set: function(step) {
+        this._step = step;
+    },
+
+    step_get: function() {
+        return this._step;
+    },
+
+    data_set: function(data) {
+        this._data = data;
+    },
+
+    data_get: function() {
+        return this._data;
+    },
+
+    subst_set: function(subst) {
+        this._subst = subst;
+    },
+
+    subst_get: function() {
+        return this._subst;
+    },
+
+    after_set: function(after) {
+        this._after = after;
+    },
+
+    after_get: function() {
+        return this._after;
+    },
+
+    done_set: function() {
+        this.done = true;
+    },
+
+    done_get: function() {
+        return (this.done);
+    }
+};