Changeset 4ce18ee5ee6ff487e9a9eef689ba73e59107ffae

Show
Ignore:
Timestamp:
09/29/09 21:15:45 (5 years ago)
Author:
John Schulz <jschulz@omniti.com>
git-committer:
John Schulz <jschulz@omniti.com> 1254258945 +0000
git-parent:

[bc6d38fb32dfba045d3d058ce5af6a748d983b9a]

git-author:
John Schulz <jschulz@omniti.com> 1254258945 +0000
Message:

Standardizing the code formatting for the JS:

  • 4 spaces
  • { on opening line
    • if (conditional) {
    • function name(parameters) {
  • else on it's own line

closes #191

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • ui/web/htdocs/js/recon.js

    r3db67ae r4ce18ee  
    66var stream_dirty; 
    77var polltime = 2000; // (ms) how often we want data from the stream 
    8 var timewindow = 300000; // (ms) width of the stream window 
     8var timewindow = 300000; // (ms) width of the stream window 
    99var recon_realtime_hostname = ''; 
    1010var streaming = false; 
     
    2222 
    2323//this will copy data only, ignoring other series variables 
    24 function copyData(d) {   
     24function copyData(d) { 
    2525    var res = []; 
    2626     
    2727    for (var i = 0; i < d.length; ++i) { 
    28         var s = {data: []}; 
    29         if(d[i].data) { 
    30             for (var j=0; j<d[i].data.length; j++) { 
    31                 s.data[j] = d[i].data[j].slice(); 
    32             } 
    33             for (var v in d[i]) { 
    34                 if(!s[v]) s[v] = d[i][v]; 
    35             } 
    36         } 
    37         else {               
    38             for (var j=0; j<d[i].length; j++) { 
    39                 s.data[j] = d[i][j].slice(); 
    40             } 
    41         } 
    42         res.push(s); 
     28        var s = { 
     29            data: [] 
     30        }; 
     31        if (d[i].data) { 
     32            for (var j = 0; j < d[i].data.length; j++) { 
     33                s.data[j] = d[i].data[j].slice(); 
     34            } 
     35            for (var v in d[i]) { 
     36                if (!s[v])  
     37                    s[v] = d[i][v]; 
     38            } 
     39        } 
     40        else { 
     41            for (var j = 0; j < d[i].length; j++) { 
     42                s.data[j] = d[i][j].slice(); 
     43            } 
     44        } 
     45        res.push(s); 
    4346    } 
    4447    return res; 
    4548} 
    4649 
    47 function dump(arr,level) { 
    48         var dumped_text = ""; 
    49         if(!level) level = 0; 
    50          
    51         //The padding given at the beginning of the line. 
    52         var level_padding = ""; 
    53         for(var j=0;j<level+1;j++) level_padding += "    "; 
    54          
    55         if(typeof(arr) == 'object') { //Array/Hashes/Objects  
    56                 for(var item in arr) { 
    57                         var value = arr[item]; 
    58                          
    59                         if(typeof(value) == 'object') { //If it is an array, 
    60                                 dumped_text += level_padding + "'" + item + "' ...\n"; 
    61                                 dumped_text += dump(value,level+1); 
    62                         } else { 
    63                                 dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n"; 
    64                         } 
    65                 } 
    66         } else { //Stings/Chars/Numbers etc. 
    67                 dumped_text = "===>"+arr+"<===("+typeof(arr)+")"; 
    68         } 
    69         return dumped_text; 
     50function dump(arr, level) { 
     51    var dumped_text = ""; 
     52    if (!level)  
     53        level = 0; 
     54     
     55    //The padding given at the beginning of the line. 
     56    var level_padding = ""; 
     57    for (var j = 0; j < level + 1; j++)  
     58        level_padding += "    "; 
     59     
     60    if (typeof(arr) == 'object') { //Array/Hashes/Objects  
     61        for (var item in arr) { 
     62            var value = arr[item]; 
     63             
     64            if (typeof(value) == 'object') { //If it is an array, 
     65                dumped_text += level_padding + "'" + item + "' ...\n"; 
     66                dumped_text += dump(value, level + 1); 
     67            } 
     68            else { 
     69                dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n"; 
     70            } 
     71        } 
     72    } 
     73    else { //Stings/Chars/Numbers etc. 
     74        dumped_text = "===>" + arr + "<===(" + typeof(arr) + ")"; 
     75    } 
     76    return dumped_text; 
    7077} 
    7178 
    7279function rpn_magic(expr) { 
    73   return function(value, o) { 
    74     return rpn_eval(value, expr, (o != null) ? o : {}); 
    75   }; 
    76 
     80    return function(value, o) { 
     81        return rpn_eval(value, expr, (o != null) ? o : {}); 
     82    }; 
     83
     84 
    7785function rpn_eval(value, expr, meta) { 
    78   var s = []; 
    79   var ops = expr.split(","); 
    80   s.unshift(value) 
    81   for (var i = 0; i < ops.length; i++) { 
    82     var opname = ops[i]; 
    83     if(meta && meta[opname]) 
    84       for(var j = 0; j < meta[opname].length; j++) 
    85         ops.splice(i, (j==0) ? 1 : 0, meta[opname][j]); 
    86   } 
    87  
    88   for (var i = 0; i < ops.length; i++) { 
    89     op = ops[i]; 
    90  
    91     switch(op) { 
    92       case 'ln': 
    93         s.unshift(Math.log(s.shift())); break; 
    94       case 'round': 
    95         r = Math.pow(10,s.shift()); 
    96         l = s.shift(); 
    97         s.unshift(Math.round(r * l)/r); 
    98         break; 
    99       case 'floor': 
    100         s.unshift(Math.floor(s.shift())); break; 
    101       case 'ceil': 
    102         s.unshift(Math.ceil(s.shift())); break; 
    103       case 'log': 
    104         r = s.shift(); 
    105         l = s.shift(); 
    106         s.unshift(Math.log(l, r)); 
    107         break; 
    108       case 'e': 
    109         s.unshift(Math.exp(1)); break; 
    110       case 'pi': 
    111         s.unshift(Math.pi()); break; 
    112       case '^': 
    113         r = s.shift(); 
    114         l = s.shift(); 
    115         s.unshift(Math.pow(l, r)); 
    116         break; 
    117       case '-': 
    118         r = s.shift(); 
    119         l = s.shift(); 
    120         s.unshift(l - r); 
    121         break; 
    122       case '/': 
    123         r = s.shift(); 
    124         l = s.shift(); 
    125         s.unshift(l / r); 
    126         break; 
    127       case '~': 
    128         s.shift(); break; 
    129       case '.': 
    130         s.unshift(s[s.shift()]); break; 
    131       case '+': 
    132         s.unshift(s.shift() + s.shift()); break; 
    133       case '*': 
    134         s.unshift(s.shift() * s.shift()); break; 
    135       case 'auto': 
    136         var units = 1; 
    137         if(meta && meta._max) { 
    138           units = Math.pow(1000,Math.floor(Math.log(meta._max)/Math.log(1000))) 
    139           if(units == 0) units = 1; 
    140         } 
    141         switch(units) { 
    142           case 0.000000001: meta.suffix = 'n'; break; 
    143           case 0.000001: meta.suffix = 'u'; break; 
    144           case 0.001: meta.suffix = 'm'; break; 
    145           case 1000: meta.suffix = 'k'; break; 
    146           case 1000000: meta.suffix = 'M'; break; 
    147           case 1000000000: meta.suffix = 'G'; break; 
    148           case 1000000000000: meta.suffix = 'T'; break; 
    149           default: meta.suffix = null; break; 
    150         } 
    151         s.unshift( s.shift() / units ); 
    152         break; 
    153       case 'min': 
    154         s.unshift(Math.min(s.shift(),s.shift())); break; 
    155       case 'max': 
    156         s.unshift(Math.max(s.shift(),s.shift())); break; 
    157       default: 
    158         if(op.match(/^-?\d+$/)) { 
    159           s.unshift(op); 
    160         } 
    161     } 
    162   } 
    163   var newvalue = s.shift(); 
    164   return newvalue; 
     86    var s = []; 
     87    var ops = expr.split(","); 
     88    s.unshift(value) 
     89    for (var i = 0; i < ops.length; i++) { 
     90        var opname = ops[i]; 
     91        if (meta && meta[opname])  
     92            for (var j = 0; j < meta[opname].length; j++)  
     93                ops.splice(i, (j == 0) ? 1 : 0, meta[opname][j]); 
     94    } 
     95     
     96    for (var i = 0; i < ops.length; i++) { 
     97        op = ops[i]; 
     98         
     99        switch (op) { 
     100            case 'ln': 
     101                s.unshift(Math.log(s.shift())); 
     102                break; 
     103            case 'round': 
     104                r = Math.pow(10, s.shift()); 
     105                l = s.shift(); 
     106                s.unshift(Math.round(r * l) / r); 
     107                break; 
     108            case 'floor': 
     109                s.unshift(Math.floor(s.shift())); 
     110                break; 
     111            case 'ceil': 
     112                s.unshift(Math.ceil(s.shift())); 
     113                break; 
     114            case 'log': 
     115                r = s.shift(); 
     116                l = s.shift(); 
     117                s.unshift(Math.log(l, r)); 
     118                break; 
     119            case 'e': 
     120                s.unshift(Math.exp(1)); 
     121                break; 
     122            case 'pi': 
     123                s.unshift(Math.pi()); 
     124                break; 
     125            case '^': 
     126                r = s.shift(); 
     127                l = s.shift(); 
     128                s.unshift(Math.pow(l, r)); 
     129                break; 
     130            case '-': 
     131                r = s.shift(); 
     132                l = s.shift(); 
     133                s.unshift(l - r); 
     134                break; 
     135            case '/': 
     136                r = s.shift(); 
     137                l = s.shift(); 
     138                s.unshift(l / r); 
     139                break; 
     140            case '~': 
     141                s.shift(); 
     142                break; 
     143            case '.': 
     144                s.unshift(s[s.shift()]); 
     145                break; 
     146            case '+': 
     147                s.unshift(s.shift() + s.shift()); 
     148                break; 
     149            case '*': 
     150                s.unshift(s.shift() * s.shift()); 
     151                break; 
     152            case 'auto': 
     153                var units = 1; 
     154                if (meta && meta._max) { 
     155                    units = Math.pow(1000, Math.floor(Math.log(meta._max) / Math.log(1000))) 
     156                    if (units == 0)  
     157                        units = 1; 
     158                } 
     159                switch (units) { 
     160                    case 0.000000001: 
     161                        meta.suffix = 'n'; 
     162                        break; 
     163                    case 0.000001: 
     164                        meta.suffix = 'u'; 
     165                        break; 
     166                    case 0.001: 
     167                        meta.suffix = 'm'; 
     168                        break; 
     169                    case 1000: 
     170                        meta.suffix = 'k'; 
     171                        break; 
     172                    case 1000000: 
     173                        meta.suffix = 'M'; 
     174                        break; 
     175                    case 1000000000: 
     176                        meta.suffix = 'G'; 
     177                        break; 
     178                    case 1000000000000: 
     179                        meta.suffix = 'T'; 
     180                        break; 
     181                    default: 
     182                        meta.suffix = null; 
     183                        break; 
     184                } 
     185                s.unshift(s.shift() / units); 
     186                break; 
     187            case 'min': 
     188                s.unshift(Math.min(s.shift(), s.shift())); 
     189                break; 
     190            case 'max': 
     191                s.unshift(Math.max(s.shift(), s.shift())); 
     192                break; 
     193            default: 
     194                if (op.match(/^-?\d+$/)) { 
     195                    s.unshift(op); 
     196                } 
     197        } 
     198    } 
     199    var newvalue = s.shift(); 
     200    return newvalue; 
    165201} 
    166202 
    167203function my_rpn_eval(expr, meta) { 
    168   var s = []; 
    169   var ops = expr.split(","); 
    170   for (var i = 0; i < ops.length; i++) { 
    171     var opname = ops[i]; 
    172     if(meta && meta[opname]) 
    173       for(var j = 0; j < meta[opname].length; j++) 
    174         ops.splice(i, (j==0) ? 1 : 0, meta[opname][j]); 
    175   } 
    176  
    177   for (var i = 0; i < ops.length; i++) { 
    178     op = ops[i]; 
    179  
    180     switch(op) { 
    181       case 'ln': 
    182         s.unshift(Math.log(parseFloat(s.shift()))); break; 
    183       case 'round': 
    184         r = Math.pow(10,parseFloat(s.shift())); 
    185         l = parseFloat(s.shift()); 
    186         s.unshift(Math.round(r * l)/r); 
    187         break; 
    188       case 'floor': 
    189         s.unshift(Math.floor(parseFloat(s.shift()))); break; 
    190       case 'ceil': 
    191         s.unshift(Math.ceil(parseFloat(s.shift()))); break; 
    192       case 'log': 
    193         r = parseFloat(s.shift()); 
    194         l = parseFloat(s.shift()); 
    195         s.unshift(Math.log(l, r)); 
    196         break; 
    197       case 'e': 
    198         s.unshift(Math.exp(1)); break; 
    199       case 'pi': 
    200         s.unshift(Math.pi()); break; 
    201       case '^': 
    202         r = parseFloat(s.shift()); 
    203         l = parseFloat(s.shift()); 
    204         s.unshift(Math.pow(l, r)); 
    205         break; 
    206       case '-': 
    207         r = parseFloat(s.shift()); 
    208         l = parseFloat(s.shift()); 
    209         s.unshift(l - r); 
    210         break; 
    211       case '/': 
    212         r = parseFloat(s.shift()); 
    213         l = parseFloat(s.shift()); 
    214         s.unshift(l / r); 
    215         break; 
    216       case '+': 
    217           s.unshift(parseFloat(s.shift()) + parseFloat(s.shift()) ); break; 
    218       case '*': 
    219         s.unshift(parseFloat(s.shift()) * parseFloat(s.shift())); break; 
    220       case 'min': 
    221         s.unshift(Math.min(parseFloat(s.shift()),parseFloat(s.shift()))); break; 
    222       case 'max': 
    223         s.unshift(Math.max(parseFloat(s.shift()),parseFloat(s.shift()))); break; 
    224       default: 
    225         if(op.match(/^-?\d+$/)) { 
    226           s.unshift(op); 
    227         } 
    228         else if(op.match(/^-?\d+\.\d*$/)) { 
    229             s.unshift(op); 
    230         } 
    231     } 
    232   } 
    233   var newvalue = s.shift(); 
    234   return newvalue; 
    235 
    236  
    237 (function ($) { 
    238   var ReconGraph = function() { 
    239     var displayinfo = { start : 14*86400, end: '', width: 380, height: 180 }; 
    240     var doptions, dplaceholder, ddata; 
    241  
    242     function ytickformatter (ddata, axisidx) { 
    243       return function(val,axis) { 
    244         for(var i=0; i<ddata.length; i++) { 
    245           if(ddata[i].yaxis == axisidx && 
    246              ddata[i].reconnoiter_display_expression) { 
    247             var meta = { _max: Math.max(Math.abs(axis.datamax), 
    248                                         Math.abs(axis.datamin)), 
    249                          // for delta calc, we don't want to 
    250                          // lose precision 
    251                          floor: ['.'], ciel: ['.'], round: ['~','.'] 
    252                        }, 
    253                 pval = rpn_eval(val, ddata[i].reconnoiter_display_expression, meta); 
    254             if((val > 0 && pval < 0) || 
    255                (val < 0 && pval > 0)) { 
    256               // Sign inversion means we're being clever and using 
    257               // the negative axis as a positive one. 
    258               pval = Math.abs(pval); 
    259             } 
    260             if(axis.tickDecimals == Infinity) { 
    261               return pval.toFixed(2) + 
    262                      ((meta.suffix != null) ? meta.suffix : ''); 
    263             } 
    264             return pval.toFixed(axis.tickDecimals) + 
    265                    ((meta.suffix != null) ? meta.suffix : ''); 
    266           } 
    267         }  
    268         return val.toFixed(axis.tickDecimals); 
    269       } 
    270     } 
    271  
    272     return { 
    273       init: 
    274         function(options) { 
    275           this.graphinfo = $.extend({}, displayinfo, options||{}); 
    276           if(!this.graphinfo.cnt) this.graphinfo.cnt = this.graphinfo.width / 2; 
    277           if(!this.attr("id")) this.attr("id", this.graphinfo.graphid); 
    278           this.append($('<div/>').addClass("graphTitle") 
    279                                .html(this.graphinfo.title || '')) 
    280               .append($('<div></div>').addClass("plot-area") 
    281                                       .css('width', this.width + 'px') 
    282                                       .css('height', this.height + 'px')) 
    283               .append($('<div></div>').addClass("plot-legend")); 
    284           this.data('__recon', this); 
    285           return this; 
    286         }, 
    287       reset: 
    288         function() { 
    289           if(this.length > 1) { 
    290             this.each(function(i) { $(this).ReconGraphReset(); }); 
    291             return this; 
    292           } 
    293           this.graphinfo.graphid = ''; 
    294           if(this.flot_plot) { 
    295             this.find(".graphTitle").html(''); 
    296             this.find("div.plot-legend").html(''); 
    297             this.flot_plot.setData({}); 
    298             this.flot_plot.setupGrid(); 
    299             this.flot_plot.draw(); 
    300           } 
    301           this.data('__recon', this); 
    302           return this; 
    303         }, 
    304       PrepareStream: 
    305         function (time_window, time_interval) {                       
    306             if(this.flot_plot) { 
    307                 doptions.time_window = time_window; 
    308                 doptions.time_interval = time_interval; 
    309                 doptions.max_time = 0; 
    310                 for(var i=0; i<ddata.length;i++) {   
    311                     ddata[i].data = []; 
    312                 }                
    313                 this.flot_plot.setData({});        
    314                 this.flot_plot.setupGrid(); 
    315                 this.flot_plot.draw();                          
    316             }            
    317             return this; 
    318         }, 
    319      AddPoint: 
    320         function (xdata, uuid, metric_name, ydata) { 
    321  
    322             //note that lastval[0] and the xdata need to be converted from seconds to milliseconds for flot 
    323  
    324             tdata = [xdata, ydata.toString()]; 
    325  
    326             for(var i=0; i<ddata.length;i++) { 
    327                 if( (ddata[i].uuid ==  uuid)  
    328                     && (ddata[i].metric_name == metric_name) 
    329                     && !ddata[i].hidden ) { 
    330  
    331                     //console.log("got data from stream for ",uuid,"-",metric_name," data = ",tdata, "hidden = ", ddata[i].hidden); 
    332  
    333                     if((xdata*1000)>doptions.max_time) { doptions.max_time = xdata*1000; } 
    334                     if( !doptions.min_time || ((xdata*1000)<doptions.min_time)) { doptions.min_time = xdata*1000;} 
    335  
    336                     if(ddata[i].metric_type == 'numeric') { 
    337  
    338                         if(ddata[i].lastval) { 
    339                             slope = (tdata[1] - ddata[i].lastval[1]) / (tdata[0] - ddata[i].lastval[0]);                      
    340                             if(ddata[i].derive_val == 'derive') { 
    341                                 tdata[1] = slope; 
    342                             } 
    343                             else if(ddata[i].derive_val == 'counter') { 
    344                                 if(slope>=0) tdata[1] = slope;  
    345                                 else tdata[1] = ''; 
    346                             } 
    347                         }//end if there was a last value available     
    348                         //if this is the first live datapoint, set slope and count to null 
    349                         else if( (ddata[i].derive_val == 'derive') || (ddata[i].derive_val == 'counter') ) 
    350                             { 
    351                                 tdata[1]=''; 
    352                             }                        
    353                         if(tdata[1]!=''){ 
    354                             if(ddata[i].reconnoiter_source_expression) { 
    355                                 tdata[1] = rpn_eval(tdata[1], ddata[i].reconnoiter_source_expression, {}); 
    356                             } 
    357                         } //end if ydata was a number 
    358                         else { //we need to fix this so we can do numerical calcs with this val later 
    359                             tdata[1] = 0; 
    360                         } 
    361  
    362                         tdata[0]*=1000; //convert from seconds to milliseconds for flot 
    363  
    364                         ddata[i].data.push(tdata); 
    365                         if(ddata[i].lastval) { 
    366                             if ((tdata[0] - ddata[i].data[0][0]) > doptions.time_window) { 
    367                                 ddata[i].data.shift(); 
    368                             } 
    369                         } 
    370                     }//end if metric was numeric 
    371                      
    372                     //if we have a text data type 
    373                     else {  
    374  
    375                         tdata[0]*=1000; //convert from seconds to milliseconds for flot 
    376                         tdata.push(tdata[1]); 
    377                         tdata[1] = "0";  
    378                          
    379                         //if we had a previous value stored, only push data to plot when the value changes 
    380                         if(ddata[i].lastval) {                               
    381                             if( ddata[i].lastval[1] != tdata[2] ) { 
    382                                 ddata[i].data.push(tdata); 
    383                                 if ((tdata[0] - ddata[i].data[0][0]) > doptions.time_window) { 
    384                                     ddata[i].data.shift(); 
    385                                 } 
    386                             } 
    387                             else { //if there was no change in the value clear the metric so it doesnt display 
    388                                 ddata[i].data = [];  
    389                             } 
    390                         } 
    391                         //otherwise we are adding a text point for the first time 
    392                         else {  
    393                             ddata[i].data.push(tdata); 
    394                         } 
    395                          
    396                     }//end if text metric type 
    397  
    398                     ddata[i].lastval = [xdata, ydata]; 
    399                      
    400                 } //end if the uuid and metric_name match 
    401             } //end for each dataset         
    402              
    403             return this; 
    404         }, 
    405     PlotPoints: 
    406         function () { 
    407  
    408             if( (doptions.max_time >= doptions.min_time + doptions.time_window)) { 
    409                 doptions.xaxis.min = doptions.max_time - doptions.time_window; 
    410                 doptions.xaxis.max = doptions.max_time; 
    411             } 
    412             else { 
    413                 doptions.xaxis.min = doptions.min_time; 
    414                 doptions.xaxis.max = doptions.min_time + doptions.time_window; 
    415             } 
    416  
    417             flotdata = copyData(ddata); 
    418             this.flot_plot = $.plot(dplaceholder, flotdata, doptions); 
    419             return this; 
    420         }, 
    421     refresh: 
    422         function(options) { 
    423  
    424           if(this.length > 1) { 
    425             this.each(function(i) { $(this).ReconGraphRefresh(options); }); 
    426             return this; 
    427           } 
    428            
    429           var o = this.data('__recon'); 
    430           if(o == null) return this; 
    431           this.graphinfo = $.extend({}, o.graphinfo, options||{}); 
    432           var url = "flot/graph/settings/" + this.graphinfo.graphid; 
    433            
    434           this.find(".plot-area") 
    435               .html('<div class="centered"><div class="loading">&nbsp;</div></div>'); 
    436  
    437           data = {'cnt':this.graphinfo.cnt, 
    438                           'start':this.graphinfo.start, 
    439                           'end':this.graphinfo.end, 
    440                        'type':this.graphinfo.type}; 
    441          
    442           $.ajaxq (this.graphinfo.graphid, { url: url, 
    443             data: data, 
    444                       success: (function(o) { return function (r) { r = eval('('+r+')'); o.ReconGraphPlot(r, function() { o.ReconGraphRefresh(); }) }}) (this) 
    445                       }); 
    446  
    447           this.data('__recon', this); 
    448           return this; 
    449         }, 
    450       make_composite_data: 
    451         function (cindex, data) { 
    452  
    453             expr = data[cindex].reconnoiter_source_expression; 
    454  
    455             //we gotta find a numeric dataset to use for going through datapoints 
    456             var nindex = -1; 
    457             for(i=0; i<data.length; i++) { 
    458                 if(data[i].metric_type == 'numeric') { 
    459                     nindex = i; 
    460                     break; 
    461                 } 
    462             } 
    463             if(nindex == -1) return false;  
    464  
    465             //TODO we assume here that all numeric datasets have the same length, number of points, and time discreteness 
    466             //if iths is not the case, we need to think of interpolating, like we do for stacking in flot 
    467             for(var i=0; i<data[nindex].data.length; i++){ 
    468                 nexpr = expr.replace(/\[(\d+)\]/g, function($1) {  
    469                         mat = parseInt($1.match(/\d+/)); 
    470                         //if the expression refers to a dataset that isnt numeric, throw an error and dont plot this dataset 
    471                         if(data[mat] && (data[mat].metric_type == 'numeric') && data[mat].data[i][1]) return data[mat].data[i][1]; 
    472                         else return "BAD"; 
    473                     }); 
    474                 if(nexpr.match(/BAD/)) return false; 
    475                 var val = my_rpn_eval(nexpr, {}); 
    476                 data[cindex].data.push([ data[nindex].data[i][0], val ]); 
    477             } 
    478             return true; 
    479         },         
    480       plot: 
    481         function (r, redraw) { 
    482  
    483           var title = this.ReconGraphMacro(r.title, r.data); 
    484           this.find(".graphTitle").html(title); 
    485           var placeholder = this.find("> div.plot-area"); 
    486           placeholder.bind("plotselected", (function (o) { 
    487             return function (event, ranges) { 
    488               var start = new Date(Math.floor(ranges.xaxis.from)); 
    489               var end = new Date(Math.floor(ranges.xaxis.to)); 
    490               o.graphinfo.start = start.toUTCString(); 
    491               o.graphinfo.end = end.toUTCString(); 
    492               if(redraw) redraw(); 
    493             }; 
    494           })(this)); 
    495           dplaceholder = placeholder; 
    496  
    497           for(var i=0; i<r.data.length; i++) { 
    498               if(r.data[i].metric_type == 'composite' && r.data[i].reconnoiter_source_expression) { 
    499                   if(!this.ReconGraphMakeCompositeData(i, r.data)) { 
    500                       modal_warning("Composite Error!",  
    501                                     "The composite dataset '"+r.data[i].metric_name+"' refers to a non-existant or non-numeric dataset, and will not be plotted."); 
    502                   } 
    503               } 
    504  
    505             if(r.data[i].reconnoiter_display_expression) 
    506               r.data[i].dataManip = rpn_magic(r.data[i].reconnoiter_display_expression); 
    507           } 
    508  
    509           ddata = r.data;           
    510  
    511           if(!r.options.grid) r.options.grid = {}; 
    512           r.options.grid.hoverable = true; 
    513           $("div.tooltip").remove(); 
    514           r.options.legend.container = this.find("div.plot-legend"); 
    515           r.options.grid.autoHighlight = false; 
    516           r.options.grid.mouseActiveRadius = 4; 
    517           r.options.grid.hoverXOnly = true; 
    518           if(!r.options.points) r.options.points = {}; 
    519           r.options.points.radius = 2; 
    520           if(!r.options.yaxis) r.options.yaxis = {}; 
    521           r.options.yaxis.tickFormatter = ytickformatter(ddata, 1); 
    522           if(!r.options.y2axis) r.options.y2axis = {}; 
    523           r.options.y2axis.tickFormatter = ytickformatter(ddata, 2); 
    524           r.options.xaxis.localtime = true; 
    525  
    526           r.options.stackSets = this.graphinfo.stacks; 
    527  
    528           doptions = r.options; 
    529  
    530           var plot = this.flot_plot = $.plot(placeholder, r.data, r.options); 
    531           var hoverings = []; 
    532           placeholder.bind("plothover", function (event, pos, items) { 
    533             var opacity = 0.7; 
    534             for(var h=0; h<hoverings.length; h++) 
    535               plot.unhighlight(hoverings[h].series, hoverings[h].datapoint); 
    536             hoverings = []; 
    537             if(items && items.length) { 
    538               // Emulate opacity on white 
    539               if(! $("div.tooltip")[0]) { 
    540                 $('<div class="tooltip"><div class="wrap"></div></div>').appendTo($('body')); 
    541                 $("div.tooltip .wrap").bind('mousemove', 
    542                   function() { plot.getEventHolder().trigger('mousemove'); }); 
    543               } 
    544               var tt = $("div.tooltip"); 
    545               tt.css( { width: 'auto', 
    546                         position: 'absolute', 
    547                         'z-index': 4000 }); 
    548               var ttw = $("div.tooltip .wrap"); 
    549               ttw.empty(); 
    550               ttw.append('<div class="point-down"></div>'); 
    551  
    552               items.sort(function(a,b) { return a.pageY - b.pageY; }); 
    553               var topitem = items[0]; 
    554               for(var i = 0; i < items.length; i++) { 
    555                 if(items[i].pageY < topitem.pageY) topitem = items[i]; 
    556                 var rgb = (items[i].series.color.match(/\((.+)\)/))[1].split(','); 
    557                 rgb = rgb.map(function(a) { return Math.round(255-(255-a)*1); }); 
    558                 var soft = 'rgba(' + rgb.join(',') + ',' + opacity + ')'; 
    559                 var val = items[i].datapoint[1]; 
    560                 if(items[i].series.dataManip) { 
    561                   var meta = { _max: val }; 
    562                   val = items[i].series.dataManip(val, meta); 
    563                   if(meta.suffix) val = val + meta.suffix; 
    564                 } 
    565  
    566                 // I want Y of YUV... for text color selection 
    567                 // if Y [0,255], if high (>255 * (1-opacity)) I want black, else white 
    568  
    569                 var Y = 0.299 * rgb[0] + 0.587 * rgb[1]  + 0.114 * rgb[2]; 
    570                 var ttp = $('<div class="tip"><div/>') 
    571                   .html((items[i].datapoint[2] ? items[i].datapoint[2] : val) + " (" + items[i].series.label + ")") 
    572                   .css( { color: ( Y > ((1-opacity) * 255) ? 'black' : 'white' ), backgroundColor: soft }); 
    573                 ttp.appendTo(ttw); 
    574                 hoverings.push(items[i]); 
    575                 plot.highlight(items[i].series, items[i].datapoint); 
    576               } 
    577               tt.css( { width: tt.width() + 10 } ); 
    578               tt.css( { overflow: 'hidden', 
    579                         top: topitem.pageY - tt.height() - 25, 
    580                         left: topitem.pageX - Math.floor(tt.width()/2) - 10, 
    581                         display: 'block' } ); 
    582               return true; 
    583             } 
    584             $("div.tooltip").remove(); 
     204    var s = []; 
     205    var ops = expr.split(","); 
     206    for (var i = 0; i < ops.length; i++) { 
     207        var opname = ops[i]; 
     208        if (meta && meta[opname])  
     209            for (var j = 0; j < meta[opname].length; j++)  
     210                ops.splice(i, (j == 0) ? 1 : 0, meta[opname][j]); 
     211    } 
     212     
     213    for (var i = 0; i < ops.length; i++) { 
     214        op = ops[i]; 
     215         
     216        switch (op) { 
     217            case 'ln': 
     218                s.unshift(Math.log(parseFloat(s.shift()))); 
     219                break; 
     220            case 'round': 
     221                r = Math.pow(10, parseFloat(s.shift())); 
     222                l = parseFloat(s.shift()); 
     223                s.unshift(Math.round(r * l) / r); 
     224                break; 
     225            case 'floor': 
     226                s.unshift(Math.floor(parseFloat(s.shift()))); 
     227                break; 
     228            case 'ceil': 
     229                s.unshift(Math.ceil(parseFloat(s.shift()))); 
     230                break; 
     231            case 'log': 
     232                r = parseFloat(s.shift()); 
     233                l = parseFloat(s.shift()); 
     234                s.unshift(Math.log(l, r)); 
     235                break; 
     236            case 'e': 
     237                s.unshift(Math.exp(1)); 
     238                break; 
     239            case 'pi': 
     240                s.unshift(Math.pi()); 
     241                break; 
     242            case '^': 
     243                r = parseFloat(s.shift()); 
     244                l = parseFloat(s.shift()); 
     245                s.unshift(Math.pow(l, r)); 
     246                break; 
     247            case '-': 
     248                r = parseFloat(s.shift()); 
     249                l = parseFloat(s.shift()); 
     250                s.unshift(l - r); 
     251                break; 
     252            case '/': 
     253                r = parseFloat(s.shift()); 
     254                l = parseFloat(s.shift()); 
     255                s.unshift(l / r); 
     256                break; 
     257            case '+': 
     258                s.unshift(parseFloat(s.shift()) + parseFloat(s.shift())); 
     259                break; 
     260            case '*': 
     261                s.unshift(parseFloat(s.shift()) * parseFloat(s.shift())); 
     262                break; 
     263            case 'min': 
     264                s.unshift(Math.min(parseFloat(s.shift()), parseFloat(s.shift()))); 
     265                break; 
     266            case 'max': 
     267                s.unshift(Math.max(parseFloat(s.shift()), parseFloat(s.shift()))); 
     268                break; 
     269            default: 
     270                if (op.match(/^-?\d+$/)) { 
     271                    s.unshift(op); 
     272                } 
     273                else if (op.match(/^-?\d+\.\d*$/)) { 
     274                    s.unshift(op); 
     275                } 
     276        } 
     277    } 
     278    var newvalue = s.shift(); 
     279    return newvalue; 
     280
     281 
     282(function($) { 
     283    var ReconGraph = function() { 
     284        var displayinfo = { 
     285            start: 14 * 86400, 
     286            end: '', 
     287            width: 380, 
     288            height: 180 
     289        }; 
     290        var doptions, dplaceholder, ddata; 
     291         
     292        function ytickformatter(ddata, axisidx) { 
     293            return function(val, axis) { 
     294                for (var i = 0; i < ddata.length; i++) { 
     295                    if (ddata[i].yaxis == axisidx && ddata[i].reconnoiter_display_expression) { 
     296                        var meta = { 
     297                            _max: Math.max(Math.abs(axis.datamax), Math.abs(axis.datamin)), 
     298                            // for delta calc, we don't want to 
     299                            // lose precision 
     300                            floor: ['.'], 
     301                            ciel: ['.'], 
     302                            round: ['~', '.'] 
     303                        }, pval = rpn_eval(val, ddata[i].reconnoiter_display_expression, meta); 
     304                        if ((val > 0 && pval < 0) || (val < 0 && pval > 0)) { 
     305                            // Sign inversion means we're being clever and using 
     306                            // the negative axis as a positive one. 
     307                            pval = Math.abs(pval); 
     308                        } 
     309                        if (axis.tickDecimals == Infinity) { 
     310                            return pval.toFixed(2) + ((meta.suffix != null) ? meta.suffix : ''); 
     311                        } 
     312                        return pval.toFixed(axis.tickDecimals) + ((meta.suffix != null) ? meta.suffix : ''); 
     313                    } 
     314                } 
     315                return val.toFixed(axis.tickDecimals); 
     316            } 
     317        } 
     318         
     319        return { 
     320            init: function(options) { 
     321                this.graphinfo = $.extend({}, displayinfo, options || 
     322                {}); 
     323                if (!this.graphinfo.cnt)  
     324                    this.graphinfo.cnt = this.graphinfo.width / 2; 
     325                if (!this.attr("id"))  
     326                    this.attr("id", this.graphinfo.graphid); 
     327                this.append($('<div/>').addClass("graphTitle").html(this.graphinfo.title || '')).append($('<div></div>').addClass("plot-area").css('width', this.width + 'px').css('height', this.height + 'px')).append($('<div></div>').addClass("plot-legend")); 
     328                this.data('__recon', this); 
     329                return this; 
     330            }, 
     331            reset: function() { 
     332                if (this.length > 1) { 
     333                    this.each(function(i) { 
     334                        $(this).ReconGraphReset(); 
     335                    }); 
     336                    return this; 
     337                } 
     338                this.graphinfo.graphid = ''; 
     339                if (this.flot_plot) { 
     340                    this.find(".graphTitle").html(''); 
     341                    this.find("div.plot-legend").html(''); 
     342                    this.flot_plot.setData({}); 
     343                    this.flot_plot.setupGrid(); 
     344                    this.flot_plot.draw(); 
     345                } 
     346                this.data('__recon', this); 
     347                return this; 
     348            }, 
     349            PrepareStream: function(time_window, time_interval) { 
     350                if (this.flot_plot) { 
     351                    doptions.time_window = time_window; 
     352                    doptions.time_interval = time_interval; 
     353                    doptions.max_time = 0; 
     354                    for (var i = 0; i < ddata.length; i++) { 
     355                        ddata[i].data = []; 
     356                    } 
     357                    this.flot_plot.setData({}); 
     358                    this.flot_plot.setupGrid(); 
     359                    this.flot_plot.draw(); 
     360                } 
     361                return this; 
     362            }, 
     363            AddPoint: function(xdata, uuid, metric_name, ydata) { 
     364             
     365                //note that lastval[0] and the xdata need to be converted from seconds to milliseconds for flot 
     366                tdata = [xdata, ydata.toString()]; 
     367                 
     368                for (var i = 0; i < ddata.length; i++) { 
     369                    if ((ddata[i].uuid == uuid) && (ddata[i].metric_name == metric_name) && !ddata[i].hidden) { 
     370                     
     371                        //console.log("got data from stream for ",uuid,"-",metric_name," data = ",tdata, "hidden = ", ddata[i].hidden); 
     372                        if ((xdata * 1000) > doptions.max_time) { 
     373                            doptions.max_time = xdata * 1000; 
     374                        } 
     375                        if (!doptions.min_time || ((xdata * 1000) < doptions.min_time)) { 
     376                            doptions.min_time = xdata * 1000; 
     377                        } 
     378                         
     379                        if (ddata[i].metric_type == 'numeric') { 
     380                         
     381                            if (ddata[i].lastval) { 
     382                                slope = (tdata[1] - ddata[i].lastval[1]) / (tdata[0] - ddata[i].lastval[0]); 
     383                                if (ddata[i].derive_val == 'derive') { 
     384                                    tdata[1] = slope; 
     385                                } 
     386                                else if (ddata[i].derive_val == 'counter') { 
     387                                    if (slope >= 0)  
     388                                        tdata[1] = slope; 
     389                                    else  
     390                                        tdata[1] = ''; 
     391                                } 
     392                            } //end if there was a last value available     
     393                            //if this is the first live datapoint, set slope and count to null 
     394                            else if ((ddata[i].derive_val == 'derive') || (ddata[i].derive_val == 'counter')) { 
     395                                tdata[1] = ''; 
     396                            } 
     397                            if (tdata[1] != '') { 
     398                                if (ddata[i].reconnoiter_source_expression) { 
     399                                    tdata[1] = rpn_eval(tdata[1], ddata[i].reconnoiter_source_expression, {}); 
     400                                } 
     401                            } //end if ydata was a number 
     402                            else { //we need to fix this so we can do numerical calcs with this val later 
     403                                tdata[1] = 0; 
     404                            } 
     405                             
     406                            tdata[0] *= 1000; //convert from seconds to milliseconds for flot 
     407                            ddata[i].data.push(tdata); 
     408                            if (ddata[i].lastval) { 
     409                                if ((tdata[0] - ddata[i].data[0][0]) > doptions.time_window) { 
     410                                    ddata[i].data.shift(); 
     411                                } 
     412                            } 
     413                        } //end if metric was numeric 
     414                        //if we have a text data type 
     415                        else { 
     416                         
     417                            tdata[0] *= 1000; //convert from seconds to milliseconds for flot 
     418                            tdata.push(tdata[1]); 
     419                            tdata[1] = "0"; 
     420                             
     421                            //if we had a previous value stored, only push data to plot when the value changes 
     422                            if (ddata[i].lastval) { 
     423                                if (ddata[i].lastval[1] != tdata[2]) { 
     424                                    ddata[i].data.push(tdata); 
     425                                    if ((tdata[0] - ddata[i].data[0][0]) > doptions.time_window) { 
     426                                        ddata[i].data.shift(); 
     427                                    } 
     428                                } 
     429                                else { //if there was no change in the value clear the metric so it doesnt display 
     430                                    ddata[i].data = []; 
     431                                } 
     432                            } 
     433                            //otherwise we are adding a text point for the first time 
     434                            else { 
     435                                ddata[i].data.push(tdata); 
     436                            } 
     437                             
     438                        } //end if text metric type 
     439                        ddata[i].lastval = [xdata, ydata]; 
     440                         
     441                    } //end if the uuid and metric_name match 
     442                } //end for each dataset         
     443                return this; 
     444            }, 
     445            PlotPoints: function() { 
     446             
     447                if ((doptions.max_time >= doptions.min_time + doptions.time_window)) { 
     448                    doptions.xaxis.min = doptions.max_time - doptions.time_window; 
     449                    doptions.xaxis.max = doptions.max_time; 
     450                } 
     451                else { 
     452                    doptions.xaxis.min = doptions.min_time; 
     453                    doptions.xaxis.max = doptions.min_time + doptions.time_window; 
     454                } 
     455                 
     456                flotdata = copyData(ddata); 
     457                this.flot_plot = $.plot(dplaceholder, flotdata, doptions); 
     458                return this; 
     459            }, 
     460            refresh: function(options) { 
     461             
     462                if (this.length > 1) { 
     463                    this.each(function(i) { 
     464                        $(this).ReconGraphRefresh(options); 
     465                    }); 
     466                    return this; 
     467                } 
     468                 
     469                var o = this.data('__recon'); 
     470                if (o == null)  
     471                    return this; 
     472                this.graphinfo = $.extend({}, o.graphinfo, options || 
     473                {}); 
     474                var url = "flot/graph/settings/" + this.graphinfo.graphid; 
     475                 
     476                this.find(".plot-area").html('<div class="centered"><div class="loading">&nbsp;</div></div>'); 
     477                 
     478                data = { 
     479                    'cnt': this.graphinfo.cnt, 
     480                    'start': this.graphinfo.start, 
     481                    'end': this.graphinfo.end, 
     482                    'type': this.graphinfo.type 
     483                }; 
     484                 
     485                $.ajaxq(this.graphinfo.graphid, { 
     486                    url: url, 
     487                    data: data, 
     488                    success: (function(o) { 
     489                        return function(r) { 
     490                            r = eval('(' + r + ')'); 
     491                            o.ReconGraphPlot(r, function() { 
     492                                o.ReconGraphRefresh(); 
     493                            }) 
     494                        } 
     495                    })(this) 
     496                }); 
     497                 
     498                this.data('__recon', this); 
     499                return this; 
     500            }, 
     501            make_composite_data: function(cindex, data) { 
     502             
     503                expr = data[cindex].reconnoiter_source_expression; 
     504                 
     505                //we gotta find a numeric dataset to use for going through datapoints 
     506                var nindex = -1; 
     507                for (i = 0; i < data.length; i++) { 
     508                    if (data[i].metric_type == 'numeric') { 
     509                        nindex = i; 
     510                        break; 
     511                    } 
     512                } 
     513                if (nindex == -1)  
     514                    return false; 
     515                 
     516                //TODO we assume here that all numeric datasets have the same length, number of points, and time discreteness 
     517                //if iths is not the case, we need to think of interpolating, like we do for stacking in flot 
     518                for (var i = 0; i < data[nindex].data.length; i++) { 
     519                    nexpr = expr.replace(/\[(\d+)\]/g, function($1) { 
     520                        mat = parseInt($1.match(/\d+/)); 
     521                        //if the expression refers to a dataset that isnt numeric, throw an error and dont plot this dataset 
     522                        if (data[mat] && (data[mat].metric_type == 'numeric') && data[mat].data[i][1])  
     523                            return data[mat].data[i][1]; 
     524                        else  
     525                            return "BAD"; 
     526                    }); 
     527                    if (nexpr.match(/BAD/))  
     528                        return false; 
     529                    var val = my_rpn_eval(nexpr, {}); 
     530                    data[cindex].data.push([data[nindex].data[i][0], val]); 
     531                } 
     532                return true; 
     533            }, 
     534            plot: function(r, redraw) { 
     535             
     536                var title = this.ReconGraphMacro(r.title, r.data); 
     537                this.find(".graphTitle").html(title); 
     538                var placeholder = this.find("> div.plot-area"); 
     539                placeholder.bind("plotselected", (function(o) { 
     540                    return function(event, ranges) { 
     541                        var start = new Date(Math.floor(ranges.xaxis.from)); 
     542                        var end = new Date(Math.floor(ranges.xaxis.to)); 
     543                        o.graphinfo.start = start.toUTCString(); 
     544                        o.graphinfo.end = end.toUTCString(); 
     545                        if (redraw)  
     546                            redraw(); 
     547                    }; 
     548                })(this)); 
     549                dplaceholder = placeholder; 
     550                 
     551                for (var i = 0; i < r.data.length; i++) { 
     552                    if (r.data[i].metric_type == 'composite' && r.data[i].reconnoiter_source_expression) { 
     553                        if (!this.ReconGraphMakeCompositeData(i, r.data)) { 
     554                            modal_warning("Composite Error!", "The composite dataset '" + r.data[i].metric_name + "' refers to a non-existant or non-numeric dataset, and will not be plotted."); 
     555                        } 
     556                    } 
     557                     
     558                    if (r.data[i].reconnoiter_display_expression)  
     559                        r.data[i].dataManip = rpn_magic(r.data[i].reconnoiter_display_expression); 
     560                } 
     561                 
     562                ddata = r.data; 
     563                 
     564                if (!r.options.grid)  
     565                    r.options.grid = {}; 
     566                r.options.grid.hoverable = true; 
     567                $("div.tooltip").remove(); 
     568                r.options.legend.container = this.find("div.plot-legend"); 
     569                r.options.grid.autoHighlight = false; 
     570                r.options.grid.mouseActiveRadius = 4; 
     571                r.options.grid.hoverXOnly = true; 
     572                if (!r.options.points)  
     573                    r.options.points = {}; 
     574                r.options.points.radius = 2; 
     575                if (!r.options.yaxis)  
     576                    r.options.yaxis = {}; 
     577                r.options.yaxis.tickFormatter = ytickformatter(ddata, 1); 
     578                if (!r.options.y2axis)  
     579                    r.options.y2axis = {}; 
     580                r.options.y2axis.tickFormatter = ytickformatter(ddata, 2); 
     581                r.options.xaxis.localtime = true; 
     582                 
     583                r.options.stackSets = this.graphinfo.stacks; 
     584                 
     585                doptions = r.options; 
     586                 
     587                var plot = this.flot_plot = $.plot(placeholder, r.data, r.options); 
     588                var hoverings = []; 
     589                placeholder.bind("plothover", function(event, pos, items) { 
     590                    var opacity = 0.7; 
     591                    for (var h = 0; h < hoverings.length; h++)  
     592                        plot.unhighlight(hoverings[h].series, hoverings[h].datapoint); 
     593                    hoverings = []; 
     594                    if (items && items.length) { 
     595                        // Emulate opacity on white 
     596                        if (!$("div.tooltip")[0]) { 
     597                            $('<div class="tooltip"><div class="wrap"></div></div>').appendTo($('body')); 
     598                            $("div.tooltip .wrap").bind('mousemove', function() { 
     599                                plot.getEventHolder().trigger('mousemove'); 
     600                            }); 
     601                        } 
     602                        var tt = $("div.tooltip"); 
     603                        tt.css({ 
     604                            width: 'auto', 
     605                            position: 'absolute', 
     606                            'z-index': 4000 
     607                        }); 
     608                        var ttw = $("div.tooltip .wrap"); 
     609                        ttw.empty(); 
     610                        ttw.append('<div class="point-down"></div>'); 
     611                         
     612                        items.sort(function(a, b) { 
     613                            return a.pageY - b.pageY; 
     614                        }); 
     615                        var topitem = items[0]; 
     616                        for (var i = 0; i < items.length; i++) { 
     617                            if (items[i].pageY < topitem.pageY)  
     618                                topitem = items[i]; 
     619                            var rgb = (items[i].series.color.match(/\((.+)\)/))[1].split(','); 
     620                            rgb = rgb.map(function(a) { 
     621                                return Math.round(255 - (255 - a) * 1); 
     622                            }); 
     623                            var soft = 'rgba(' + rgb.join(',') + ',' + opacity + ')'; 
     624                            var val = items[i].datapoint[1]; 
     625                            if (items[i].series.dataManip) { 
     626                                var meta = { 
     627                                    _max: val 
     628                                }; 
     629                                val = items[i].series.dataManip(val, meta); 
     630                                if (meta.suffix)  
     631                                    val = val + meta.suffix; 
     632                            } 
     633                             
     634                            // I want Y of YUV... for text color selection 
     635                            // if Y [0,255], if high (>255 * (1-opacity)) I want black, else white 
     636                            var Y = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]; 
     637                            var ttp = $('<div class="tip"><div/>').html((items[i].datapoint[2] ? items[i].datapoint[2] : val) + " (" + items[i].series.label + ")").css({ 
     638                                color: (Y > ((1 - opacity) * 255) ? 'black' : 'white'), 
     639                                backgroundColor: soft 
     640                            }); 
     641                            ttp.appendTo(ttw); 
     642                            hoverings.push(items[i]); 
     643                            plot.highlight(items[i].series, items[i].datapoint); 
     644                        } 
     645                        tt.css({ 
     646                            width: tt.width() + 10 
     647                        }); 
     648                        tt.css({ 
     649                            overflow: 'hidden', 
     650                            top: topitem.pageY - tt.height() - 25, 
     651                            left: topitem.pageX - Math.floor(tt.width() / 2) - 10, 
     652                            display: 'block' 
     653                        }); 
     654                        return true; 
     655                    } 
     656                    $("div.tooltip").remove(); 
     657                    return false; 
     658                }); 
     659            }, 
     660            macro: function(str, data) { 
     661                if (str == null)  
     662                    return str; 
     663                var newstr = str.replace(/%\{[^\}]+\}/g, function(match) { 
     664                    var matches = match.match(/^%{([^:]+):?(.*)\}$/); 
     665                    for (var i = 0; i < data.length; i++) { 
     666                        if (data[i].dataname == matches[1]) { 
     667                            if (matches[2] == "" || matches[2] == "description" || matches[2] == "last_description")  
     668                                return data[i].data[data[i].data.length - 1][2]; 
     669                            else if (matches[2] == "value" || matches[2] == "last_value")  
     670                                return data[i].data[data[i].data.length - 1][1]; 
     671                            else if (matches[2] == "first_description")  
     672                                return data[i].data[0][2]; 
     673                            else if (matches[2] == "first_value")  
     674                                return data[i].data[0][1]; 
     675                            return "[unknown: " + matches[2] + "]"; 
     676                        } 
     677                    } 
     678                    return "[unknown: " + matches[1] + "]"; 
     679                }); 
     680                return newstr; 
     681            } 
     682        }; 
     683    }(); 
     684    $.fn.extend({ 
     685        ReconGraph: ReconGraph.init, 
     686        ReconGraphRefresh: ReconGraph.refresh, 
     687        ReconGraphPlot: ReconGraph.plot, 
     688        ReconGraphReset: ReconGraph.reset, 
     689        ReconGraphMacro: ReconGraph.macro, 
     690        ReconGraphPrepareStream: ReconGraph.PrepareStream, 
     691        ReconGraphAddPoint: ReconGraph.AddPoint, 
     692        ReconGraphPlotPoints: ReconGraph.PlotPoints, 
     693        ReconGraphMakeCompositeData: ReconGraph.make_composite_data 
     694    }); 
     695})(jQuery); 
     696 
     697function perform_graph_search_add(params) { 
     698    perform_generic_search('json/graph/search', params, perform_graph_search_add, graphs_for_worksheet, graph_search_summary); 
     699
     700 
     701function perform_graph_search_edit(params) { 
     702    perform_generic_search('json/graph/search', params, perform_graph_search_edit, graphs_for_edit, graph_search_summary); 
     703
     704 
     705function perform_ws_search_edit(params) { 
     706    perform_generic_search('json/worksheet/search', params, perform_ws_search_edit, ws_for_edit, ws_search_summary); 
     707
     708 
     709function perform_datapoint_search_add(params) { 
     710    perform_generic_search('json/datapoint/search', params, perform_datapoint_search_add, datapoints_for_graph, datapoint_search_summary); 
     711
     712 
     713function ws_search_summary(r) { 
     714    if (r.count > 0 && r.query == '')  
     715        return ''; 
     716    return r.count + ' worksheet' + (r.count == 1 ? '' : 's') + ' found for \'' + htmlentities(r.query) + '\''; 
     717
     718 
     719function graph_search_summary(r) { 
     720    if (r.count > 0 && r.query == '')  
     721        return ''; 
     722    return r.count + ' graph' + (r.count == 1 ? '' : 's') + ' found for \'' + htmlentities(r.query) + '\''; 
     723
     724 
     725function datapoint_search_summary(r) { 
     726    if (r.count > 0 && r.query == '')  
     727        return ''; 
     728    return 'Found ' + r.count + ' data point' + (r.count == 1 ? '' : 's') + ' found for \'' + htmlentities(r.query) + '\''; 
     729
     730 
     731function perform_generic_search(url, params, search_func, create_item, summary_func) { 
     732    $.getJSON(url, { 
     733        'q': params.search, 
     734        'o': params.offset, 
     735        'l': params.limit 
     736    }, function(r) { 
     737        var summary = summary_func(r); 
     738        if (r.error)  
     739            summary = 'Error: ' + htmlentities(r.error); 
     740        $(params.domid + " > p.search-summary").html(summary).fadeIn('fast'); 
     741        var c = new Number(r.count); 
     742        var l = new Number(r.limit); 
     743        var o = new Number(r.offset); 
     744        var page = $(params.domid + " > p.paginate"); 
     745        page.html(''); 
     746        if (c > l) { 
     747            if (o > 0) { 
     748                var po = Math.max(o - l, 0); 
     749                $('<a/>').html((po + 1) + ' - ' + (po + l)).click(function() { 
     750                    search_func({ 
     751                        'domid': params.domid, 
     752                        'search': params.search, 
     753                        'offset': po, 
     754                        'limit': r.limit 
     755                    }); 
     756                    return false; 
     757                }).appendTo(page); 
     758            } 
     759            page.append($('<span/>').html((o + 1) + '-' + (o + l)).addClass('searchselect')); 
     760            if (o + l < c) { 
     761                var pop = o + l; 
     762                $('<a/>').html((pop + 1) + '-' + (pop + l)).click(function() { 
     763                    search_func({ 
     764                        'domid': params.domid, 
     765                        'search': params.search, 
     766                        'offset': pop, 
     767                        'limit': r.limit 
     768                    }); 
     769                    return false; 
     770                }).appendTo(page); 
     771            } 
     772            page.slideDown('fast'); 
     773        } 
     774        else  
     775            page.slideUp('fast'); 
     776        $(params.domid + " > ul.searchresults > li").remove(); 
     777        for (var i = 0; r.results && i < r.results.length; i++) { 
     778            var g = r.results[i]; 
     779            var li = $('<li/>'); 
     780            create_item(li, g, { 
     781                'domid': params.domid, 
     782                'search': params.search, 
     783                'offset': o, 
     784                'limit': l 
     785            }); 
     786            $(params.domid + " > ul.searchresults").append(li); 
     787        } 
     788    }); 
     789
     790 
     791function graphs_for_edit(li, g, params) { 
     792    var edit = $('<a href="#"/>'); 
     793    edit.html('Edit').addClass('editgraph'); 
     794    edit.click((function(graphid) { 
     795        return function() { 
     796            set_current_graph_id(graphid); 
    585797            return false; 
    586           }); 
    587         }, 
    588       macro: 
    589         function(str, data) { 
    590           if(str == null) return str; 
    591           var newstr = str.replace( 
    592             /%\{[^\}]+\}/g, 
    593             function(match) { 
    594               var matches = match.match(/^%{([^:]+):?(.*)\}$/); 
    595               for(var i=0; i<data.length; i++) { 
    596                 if(data[i].dataname == matches[1]) { 
    597                   if(matches[2] == "" || 
    598                      matches[2] == "description" || 
    599                      matches[2] == "last_description") 
    600                     return data[i].data[data[i].data.length-1][2]; 
    601                   else if(matches[2] == "value" || 
    602                           matches[2] == "last_value") 
    603                     return data[i].data[data[i].data.length-1][1]; 
    604                   else if(matches[2] == "first_description") 
    605                     return data[i].data[0][2]; 
    606                   else if(matches[2] == "first_value") 
    607                     return data[i].data[0][1]; 
    608                   return "[unknown: "+matches[2]+"]"; 
    609                 } 
    610               } 
    611               return "[unknown: "+matches[1]+"]"; 
    612             } 
    613           ); 
    614           return newstr; 
    615         } 
    616     }; 
    617   }(); 
    618   $.fn.extend({ ReconGraph: ReconGraph.init, 
    619                 ReconGraphRefresh: ReconGraph.refresh, 
    620                 ReconGraphPlot: ReconGraph.plot, 
    621                 ReconGraphReset: ReconGraph.reset, 
    622               ReconGraphMacro: ReconGraph.macro, 
    623               ReconGraphPrepareStream: ReconGraph.PrepareStream, 
    624               ReconGraphAddPoint: ReconGraph.AddPoint, 
    625               ReconGraphPlotPoints: ReconGraph.PlotPoints, 
    626               ReconGraphMakeCompositeData: ReconGraph.make_composite_data 
    627               }); 
    628   })(jQuery); 
    629  
    630 function perform_graph_search_add(params) { 
    631   perform_generic_search('json/graph/search', params, 
    632                          perform_graph_search_add, 
    633                          graphs_for_worksheet, graph_search_summary); 
    634 
    635 function perform_graph_search_edit(params) { 
    636   perform_generic_search('json/graph/search', params, 
    637                          perform_graph_search_edit, 
    638                          graphs_for_edit, graph_search_summary); 
    639 
    640 function perform_ws_search_edit(params) { 
    641   perform_generic_search('json/worksheet/search', params, 
    642                          perform_ws_search_edit, 
    643                          ws_for_edit, ws_search_summary); 
    644 
    645 function perform_datapoint_search_add(params) { 
    646   perform_generic_search('json/datapoint/search', params, 
    647                          perform_datapoint_search_add, 
    648                          datapoints_for_graph, datapoint_search_summary); 
    649 
    650 function ws_search_summary(r) { 
    651   if(r.count > 0 && r.query == '') return ''; 
    652   return r.count + ' worksheet' + (r.count == 1 ? '' : 's' ) + ' found for \'' + htmlentities(r.query) + '\''; 
    653 
    654 function graph_search_summary(r) { 
    655   if(r.count > 0 && r.query == '') return ''; 
    656   return r.count + ' graph' + (r.count == 1 ? '' : 's' ) + ' found for \'' + htmlentities(r.query) + '\''; 
    657 
    658 function datapoint_search_summary(r) { 
    659   if(r.count > 0 && r.query == '') return ''; 
    660   return 'Found ' + r.count + ' data point' + (r.count == 1 ? '' : 's' ) + ' found for \'' + htmlentities(r.query) + '\''; 
    661 
    662 function perform_generic_search(url, params, search_func, create_item, summary_func) { 
    663   $.getJSON(url, 
    664             { 'q' : params.search, 'o' : params.offset, 'l' : params.limit }, 
    665             function(r) { 
    666               var summary = summary_func(r); 
    667               if(r.error) summary = 'Error: ' + htmlentities(r.error); 
    668               $(params.domid + " > p.search-summary").html(summary).fadeIn('fast'); 
    669               var c = new Number(r.count); 
    670               var l = new Number(r.limit); 
    671               var o = new Number(r.offset); 
    672               var page = $(params.domid + " > p.paginate"); 
    673               page.html(''); 
    674               if(c > l) { 
    675                 if(o > 0) { 
    676                   var po = Math.max(o-l, 0); 
    677                   $('<a/>').html( (po+1) + ' - ' + (po+l) ) 
    678                            .click(function() { 
    679                              search_func({ 'domid': params.domid, 
    680                                            'search': params.search, 
    681                                            'offset': po, 
    682                                            'limit': r.limit }); 
    683                              return false; 
    684                            }).appendTo(page); 
    685                 } 
    686                 page.append($('<span/>').html((o+1) + '-' + (o+l)).addClass('searchselect')); 
    687                 if(o + l < c) { 
    688                   var pop = o + l; 
    689                   $('<a/>').html( (pop + 1) + '-' + (pop+l) ) 
    690                            .click(function() { 
    691                              search_func({ 'domid': params.domid, 
    692                                            'search': params.search, 
    693                                            'offset': pop, 
    694                                            'limit': r.limit }); 
    695                              return false; 
    696                            }).appendTo(page); 
    697                 } 
    698                 page.slideDown('fast'); 
    699               } 
    700               else page.slideUp('fast'); 
    701               $(params.domid + " > ul.searchresults > li").remove(); 
    702               for(var i=0; r.results && i<r.results.length; i++) { 
    703                 var g = r.results[i]; 
    704                 var li = $('<li/>'); 
    705                 create_item(li, g, { 'domid': params.domid, 
    706                                      'search': params.search, 
    707                                      'offset': o, 
    708                                      'limit': l }); 
    709                 $(params.domid + " > ul.searchresults").append(li); 
    710               } 
     798        } 
     799    })(g.graphid)); 
     800    var del = $('<a href="#"/>'); 
     801    del.html('Forget').addClass('deletegraph'); 
     802    del.click((function(graphid, li) { 
     803        return function() { 
     804            confirm("I will forget the current graph.  Are you sure?", function() { 
     805                $.getJSON('json/graph/forget/' + graphid + '/0', function(r) { 
     806                    if (r.refed) { 
     807                        var msg = "This graph is used in worksheet(s):<p>"; 
     808                        for (var wg in r.refed) { 
     809                            msg += "<br>" + r.refed[wg]; 
     810                        } 
     811                        msg += "<p> Forgetting it will remove it from these worksheets as well. <p>Are you sure you want to forget it?"; 
     812                        confirm(msg, function() { 
     813                            $.getJSON('json/graph/forget/' + graphid + '/1', function(r) { 
     814                                if (r.error) { 
     815                                    modal_warning("Database Error!", r.error); 
     816                                } 
     817                                else { 
     818                                    perform_graph_search_edit(params); 
     819                                } 
     820                            }); 
     821                        }); 
     822                    } 
     823                    else { 
     824                        if (r.error) { 
     825                            modal_warning("Database Error!", r.error); 
     826                        } 
     827                        else { 
     828                            perform_graph_search_edit(params); 
     829                        } 
     830                    } 
     831                }); 
     832                if (current_graph_id == graphid) { 
     833                    set_current_graph_id(''); 
     834                } 
    711835            }); 
    712 
    713  
    714 function graphs_for_edit(li, g, params) { 
    715   var edit = $('<a href="#"/>'); 
    716   edit.html('Edit').addClass('editgraph'); 
    717   edit.click( 
    718     (function(graphid) { 
     836            return false; 
     837        } 
     838    })(g.graphid, li)); 
     839    var add = $('<a href="#"/>'); 
     840    add.html('Stack'); 
     841    add.click((function(graphid) { 
    719842        return function() { 
    720           set_current_graph_id(graphid); 
    721           return false; 
    722         } 
    723      })(g.graphid) 
    724   ); 
    725   var del = $('<a href="#"/>'); 
    726   del.html('Forget').addClass('deletegraph'); 
    727   del.click( 
    728     (function(graphid, li) { 
     843            aggregate_graph(graphid, true); 
     844            return false; 
     845        } 
     846    })(g.graphid)); 
     847     
     848    var addover = $('<a href="#"/>'); 
     849    addover.html('Overlay'); 
     850    addover.click((function(graphid) { 
    729851        return function() { 
    730             confirm("I will forget the current graph.  Are you sure?", function(){ 
    731                     $.getJSON('json/graph/forget/' + graphid + '/0', 
    732                               function (r) { 
    733                                   if(r.refed) { 
    734                                       var msg = "This graph is used in worksheet(s):<p>"; 
    735                                       for(var wg in r.refed){ msg += "<br>"+r.refed[wg];} 
    736                                       msg+="<p> Forgetting it will remove it from these worksheets as well. <p>Are you sure you want to forget it?"; 
    737                                       confirm(msg, 
    738                                               function() { 
    739                                                   $.getJSON('json/graph/forget/' + graphid + '/1', 
    740                                                             function(r) { 
    741                                                                 if(r.error) { modal_warning("Database Error!", r.error); } 
    742                                                                 else { perform_graph_search_edit(params);} 
    743                                                             }); 
    744                                               }); 
    745                                   } 
    746                                   else { 
    747                                       if(r.error) { modal_warning("Database Error!", r.error); } 
    748                                       else {  
    749                                           perform_graph_search_edit(params); 
    750                                       } 
    751                                   } 
    752                               }); 
    753                     if(current_graph_id==graphid) {set_current_graph_id('');} 
    754                 });              
    755           return false; 
    756         } 
    757     })(g.graphid, li) 
    758             ); 
    759   var add = $('<a href="#"/>'); 
    760   add.html('Stack'); 
    761   add.click( 
    762     (function(graphid) { 
     852            aggregate_graph(graphid, false); 
     853            return false; 
     854        } 
     855    })(g.graphid)); 
     856     
     857    var ul = $('<ul/>'); 
     858    ul.append($('<li/>').html(g.last_update)); 
     859    ul.append($('<li/>').append(edit)); 
     860    ul.append($('<li/>').append(del)); 
     861    ul.append($('<li/>').append(add)); 
     862    ul.append($('<li/>').append(addover)); 
     863    gtitle = $('<div class="graphlist-title"/>').html(g.title); 
     864     
     865    li.append(gtitle).append(ul); 
     866
     867 
     868function ws_for_edit(li, ws, params) { 
     869    var add = $('<a href="#"/>'); 
     870    add.html('View').addClass('addtows'); 
     871    add.click((function(sheetid) { 
    763872        return function() { 
    764             aggregate_graph(graphid, true); 
    765           return false; 
    766         } 
    767      })(g.graphid) 
    768   ); 
    769  
    770   var addover = $('<a href="#"/>'); 
    771   addover.html('Overlay'); 
    772   addover.click( 
    773     (function(graphid) { 
     873            worksheet.load(sheetid); 
     874            return false; 
     875        } 
     876    })(ws.sheetid)); 
     877    var ul = $('<ul/>'); 
     878    ul.append($('<li/>').html(ws.last_update)); 
     879    ul.append($('<li/>').append(add)); 
     880    li.append($('<div class="worksheetlist-title"/>').html(ws.title)).append(ul); 
     881
     882 
     883function graphs_for_worksheet(li, g, params) { 
     884    var add = $('<a href="#"/>'); 
     885    var qview = $('<a href="#"/>'); 
     886    add.html('Add').addClass('addtows'); 
     887    add.click((function(graphid) { 
    774888        return function() { 
    775             aggregate_graph(graphid, false); 
    776           return false; 
    777         } 
    778      })(g.graphid) 
    779   ); 
    780  
    781   var ul = $('<ul/>'); 
    782   ul.append($('<li/>').html(g.last_update)); 
    783   ul.append($('<li/>').append(edit)); 
    784   ul.append($('<li/>').append(del)); 
    785   ul.append($('<li/>').append(add)); 
    786   ul.append($('<li/>').append(addover)); 
    787   gtitle = $('<div class="graphlist-title"/>').html(g.title); 
    788    
    789   li.append(gtitle).append(ul); 
    790 
    791 function ws_for_edit(li, ws, params) { 
    792   var add = $('<a href="#"/>'); 
    793   add.html('View').addClass('addtows'); 
    794   add.click( 
    795     (function(sheetid) { 
     889            worksheet.add_graph(graphid); 
     890            return false; 
     891        } 
     892    })(g.graphid)); 
     893    qview.html('Quick View').addClass('quickviewgraph'); 
     894    qview.click((function(graphid, gtype) { 
    796895        return function() { 
    797           worksheet.load(sheetid); 
    798           return false; 
    799         } 
    800      })(ws.sheetid) 
    801   ); 
    802   var ul = $('<ul/>'); 
    803   ul.append($('<li/>').html(ws.last_update)); 
    804   ul.append($('<li/>').append(add)); 
    805   li.append($('<div class="worksheetlist-title"/>').html(ws.title)).append(ul); 
    806 
    807 function graphs_for_worksheet(li, g, params) { 
    808   var add = $('<a href="#"/>'); 
    809   var qview = $('<a href="#"/>'); 
    810   add.html('Add').addClass('addtows'); 
    811   add.click( 
    812     (function(graphid) { 
     896            worksheet.zoom(graphid, gtype); 
     897            return false; 
     898        } 
     899    })(g.graphid, 'standard')); 
     900    var ul = $('<ul/>'); 
     901    ul.append($('<li/>').html(g.last_update)); 
     902    ul.append($('<li/>').append(add)); 
     903    ul.append($('<li/>').append(qview)); 
     904    li.append($('<div class="ws-add-graph-title"/>').html(g.title)).append(ul); 
     905
     906 
     907function datapoints_for_graph(li, ds, params) { 
     908    var a = $('<a href="#"/>'); 
     909    a.html(ds.target + '`' + ds.name + '`' + ds.metric_name); 
     910    a.click((function(ds_c) { 
    813911        return function() { 
    814           worksheet.add_graph(graphid); 
    815           return false; 
    816         } 
    817      })(g.graphid) 
    818   ); 
    819   qview.html('Quick View').addClass('quickviewgraph'); 
    820   qview.click( 
    821     (function(graphid, gtype) { 
    822       return function() { worksheet.zoom(graphid, gtype); return false; } 
    823     })(g.graphid, 'standard') 
    824   ); 
    825   var ul = $('<ul/>'); 
    826   ul.append($('<li/>').html(g.last_update)); 
    827   ul.append($('<li/>').append(add)); 
    828   ul.append($('<li/>').append(qview)); 
    829   li.append($('<div class="ws-add-graph-title"/>').html(g.title)).append(ul); 
    830 
    831 function datapoints_for_graph(li, ds, params) { 
    832   var a = $('<a href="#"/>'); 
    833   a.html(ds.target + '`' + ds.name + '`' + ds.metric_name); 
    834   a.click( 
    835     (function(ds_c) { 
    836         return function() { 
    837           graph_add_datapoint({'sid':ds_c.sid, 
    838                                'name':ds_c.target + '`' + ds_c.metric_name, 
    839                                'metric_name':ds_c.metric_name, 
    840                                'metric_type':ds_c.metric_type, 
    841                                'module': ds_c.module, 
    842                                'target': ds_c.target, 
    843                                'orig_name': ds_c.name 
    844                               }); 
    845           return false; 
    846         } 
    847      })(ds) 
    848   ); 
    849   if(ds.metric_type == 'text') li.addClass('txt'); 
    850   li.append(a); 
     912            graph_add_datapoint({ 
     913                'sid': ds_c.sid, 
     914                'name': ds_c.target + '`' + ds_c.metric_name, 
     915                'metric_name': ds_c.metric_name, 
     916                'metric_type': ds_c.metric_type, 
     917                'module': ds_c.module, 
     918                'target': ds_c.target, 
     919                'orig_name': ds_c.name 
     920            }); 
     921            return false; 
     922        } 
     923    })(ds)); 
     924    if (ds.metric_type == 'text')  
     925        li.addClass('txt'); 
     926    li.append(a); 
    851927} 
    852928 
    853929function time_window_to_seconds(w) { 
    854   var p = w.match(/^(\d+)(M|h|d|w|m|y)$/); 
    855   if(!p) return 86400*2; 
    856   switch(p[2]) { 
    857     case 'M': return p[1] * 60; 
    858     case 'h': return p[1] * 3600; 
    859     case 'd': return p[1] * 86400; 
    860     case 'w': return p[1] * 86400 * 7; 
    861     case 'm': return p[1] * 86400 * 30; 
    862     case 'y': return p[1] * 86400 * 365; 
    863   } 
    864   return 86400*2; 
     930    var p = w.match(/^(\d+)(M|h|d|w|m|y)$/); 
     931    if (!p)  
     932        return 86400 * 2; 
     933    switch (p[2]) { 
     934        case 'M': 
     935            return p[1] * 60; 
     936        case 'h': 
     937            return p[1] * 3600; 
     938        case 'd': 
     939            return p[1] * 86400; 
     940        case 'w': 
     941            return p[1] * 86400 * 7; 
     942        case 'm': 
     943            return p[1] * 86400 * 30; 
     944        case 'y': 
     945            return p[1] * 86400 * 365; 
     946    } 
     947    return 86400 * 2; 
    865948} 
    866949 
     
    868951    play_pause = $("<span id='play_pause'>PLAY</span>"); 
    869952    stop = $("<span id='stopstream' style='display:none' >STOP</span>"); 
    870     oslider = $("<div id='oslider' style='display:none'><div id='pollslider'></div><div id='polltime'>"+polltime+" ms</div></div>"); 
     953    oslider = $("<div id='oslider' style='display:none'><div id='pollslider'></div><div id='polltime'>" + polltime + " ms</div></div>"); 
    871954    stream_controls = $("<div class='stream_controls'></div>").append(play_pause).append(stop).append(oslider); 
    872955    return stream_controls; 
     
    877960//stream_graph: the dom element to update with the stream 
    878961//streambox: the hidden element to insert the iframe remote calls 
    879     function stream_data(graph_id, stream_graph, streambox) { 
    880     if(!streaming) { 
    881        stream_object = stream_graph; 
    882        stream_dirty = false; 
    883        stream_graph.ReconGraphPrepareStream(timewindow, polltime); 
    884  
    885        //this should be the only place we set streaming to true 
    886        streaming = true; 
    887     } 
    888 //setup functionality so that every 2 seconds check if we are streaming and dirty, plot if true 
     962function stream_data(graph_id, stream_graph, streambox) { 
     963    if (!streaming) { 
     964        stream_object = stream_graph; 
     965        stream_dirty = false; 
     966        stream_graph.ReconGraphPrepareStream(timewindow, polltime); 
     967         
     968        //this should be the only place we set streaming to true 
     969        streaming = true; 
     970    } 
     971    //setup functionality so that every 2 seconds check if we are streaming and dirty, plot if true 
    889972    stream_graph.everyTime(2000, function() { 
    890       if(!streaming) { 
    891        streambox.html(''); 
    892        $(".stream-log").hide(); 
    893        stream_graph.stopTime(); 
    894       } 
    895       else { 
    896         if(stream_dirty){ 
    897           stream_graph.ReconGraphPlotPoints(); 
    898           stream_dirty=false; 
    899         } 
    900       } 
    901         }); 
    902  
    903     $.getJSON("json/graph/info/" + graph_id, 
    904       function(g) { 
    905  
     973        if (!streaming) { 
     974            streambox.html(''); 
     975            $(".stream-log").hide(); 
     976            stream_graph.stopTime(); 
     977        } 
     978        else { 
     979            if (stream_dirty) { 
     980                stream_graph.ReconGraphPlotPoints(); 
     981                stream_dirty = false; 
     982            } 
     983        } 
     984    }); 
     985     
     986    $.getJSON("json/graph/info/" + graph_id, function(g) { 
     987     
    906988        sids = ""; 
    907989        var sidneed = new Object(); 
    908  
    909         //we could set a polltime for each dataset, but for now we make them the same 
    910         //we assume we never give datasets we dont want to graph sids, like composites 
    911         for(var i=0; i<g.datapoints.length; i++) { 
    912           if(g.datapoints[i].sid) { 
    913             sidneed[g.datapoints[i].sid] = polltime; 
    914           } 
    915         } 
    916         for(var sid in sidneed) { 
    917           sids+= "/"+sid+"@"+sidneed[sid]; 
    918         } 
    919         //console.log("sids request: http://" +recon_realtime_hostname+"/data"+sids); 
    920         streambox.html('<iframe src="http://' + recon_realtime_hostname + '/data'+sids+'"></iframe>'); 
    921      }); 
    922   } 
    923  
     990         
     991        //we could set a polltime for each dataset, but for now we make them the same 
     992        //we assume we never give datasets we dont want to graph sids, like composites 
     993        for (var i = 0; i < g.datapoints.length; i++) { 
     994            if (g.datapoints[i].sid) { 
     995                sidneed[g.datapoints[i].sid] = polltime; 
     996            } 
     997        } 
     998        for (var sid in sidneed) { 
     999            sids += "/" + sid + "@" + sidneed[sid]; 
     1000        } 
     1001        //console.log("sids request: http://" +recon_realtime_hostname+"/data"+sids); 
     1002        streambox.html('<iframe src="http://' + recon_realtime_hostname + '/data' + sids + '"></iframe>'); 
     1003    }); 
     1004
    9241005 
    9251006/////////////////////////// 
    9261007// Worksheet manipulation 
    9271008////////////////////////// 
    928  
    9291009var worksheet = (function($) { 
    930   var ws_displayinfo = { start : 14*86400, cnt: '100', end: '' }; 
    931   var wsinfo = {}; 
    932   var locked = false; 
    933   streaming = false;  //precautionary...should be set to false wherever we use it when weere done 
    934   var stream_graph; 
    935  
    936   function ws_locked(warning) { 
    937     if(locked) { 
    938       modal_warning("Worksheet Locked!", warning); 
    939       return locked; 
    940     } 
    941     else if($(".rememberWorksheet:visible").length != 0) { 
    942       modal_warning("Worksheet not saved!", "You must hit 'Remember' to continue editing."); 
    943       return true; 
    944     } 
    945     return locked; 
    946   } 
    947  
    948   function make_ws_graph(g) { 
    949     var o = $('<div></div>').ReconGraph(g); 
    950  
    951     zb = $("<li class='zoomGraph' id='Zoom-"+g.graphid+"'><img src='images/zoom_icon.png'></li>"); 
    952     zb.attr("graphid", g.graphid); 
    953     zb.attr("graphtype", g.type); 
    954     zb.click(function() { worksheet.zoom($(this).attr("graphid"), $(this).attr("graphtype")); }); 
    955     mb = $("<li class='moveGraph' id='Move-"+g.graphid+"'><img src='images/drag_icon.png'></li>"); 
    956     rb = $("<li class='deleteWorksheetGraph' id='Remove-"+g.graphid+"'><img src='images/remove_icon.png'></li>"); 
    957     rb.attr("graphid", g.graphid); 
    958     rb.click( function() { 
    959       $.getJSON('json/worksheet/deletegraph/' + wsinfo.id + '/' + $(this).attr("graphid"), 
    960         function(r) { if(r.error) { $("#ws-tool-error").html(r.error).fadeIn('fast');  } }); 
    961       $("#"+$(this).attr("graphid")).remove(); 
    962     }); 
    963  
    964     var ws_tbar = $('<div class="ws-toolbar"></div>').append("<ul/>").append(zb).append(mb).append(rb); 
    965  
    966     ws_tbar.attr("style", "display:none;"); 
    967  
    968     o.prepend(ws_tbar); 
    969     o.mouseover( 
    970               function() { 
    971                  o.attr("style", "outline: 1px solid #DDDDDD;"); 
    972                  ws_tbar.removeAttr("style"); 
    973               }); 
    974     o.mouseout( 
    975               function() { 
    976                 o.removeAttr("style"); 
    977                 ws_tbar.attr("style", "display:none;"); 
    978               }); 
    979  
    980     return o; 
    981   } 
    982  
    983   function render_ws_inpage(divid, id, start, end, gran) { 
    984       ws_displayinfo.start = start; 
    985       ws_displayinfo.end = end; 
    986       if(gran) ws_displayinfo.cnt = gran; 
    987  
    988       plot_board = $('#'+divid); 
    989  
    990         plot_board.append('<h2 class="ws_title" id="worksheetTitlePerma">Worksheet Title</h2>\ 
     1010    var ws_displayinfo = { 
     1011        start: 14 * 86400, 
     1012        cnt: '100', 
     1013        end: '' 
     1014    }; 
     1015    var wsinfo = {}; 
     1016    var locked = false; 
     1017    streaming = false; //precautionary...should be set to false wherever we use it when weere done 
     1018    var stream_graph; 
     1019     
     1020    function ws_locked(warning) { 
     1021        if (locked) { 
     1022            modal_warning("Worksheet Locked!", warning); 
     1023            return locked; 
     1024        } 
     1025        else if ($(".rememberWorksheet:visible").length != 0) { 
     1026            modal_warning("Worksheet not saved!", "You must hit 'Remember' to continue editing."); 
     1027            return true; 
     1028        } 
     1029        return locked; 
     1030    } 
     1031     
     1032    function make_ws_graph(g) { 
     1033        var o = $('<div></div>').ReconGraph(g); 
     1034         
     1035        zb = $("<li class='zoomGraph' id='Zoom-" + g.graphid + "'><img src='images/zoom_icon.png'></li>"); 
     1036        zb.attr("graphid", g.graphid); 
     1037        zb.attr("graphtype", g.type); 
     1038        zb.click(function() { 
     1039            worksheet.zoom($(this).attr("graphid"), $(this).attr("graphtype")); 
     1040        }); 
     1041        mb = $("<li class='moveGraph' id='Move-" + g.graphid + "'><img src='images/drag_icon.png'></li>"); 
     1042        rb = $("<li class='deleteWorksheetGraph' id='Remove-" + g.graphid + "'><img src='images/remove_icon.png'></li>"); 
     1043        rb.attr("graphid", g.graphid); 
     1044        rb.click(function() { 
     1045            $.getJSON('json/worksheet/deletegraph/' + wsinfo.id + '/' + $(this).attr("graphid"), function(r) { 
     1046                if (r.error) { 
     1047                    $("#ws-tool-error").html(r.error).fadeIn('fast'); 
     1048                } 
     1049            }); 
     1050            $("#" + $(this).attr("graphid")).remove(); 
     1051        }); 
     1052         
     1053        var ws_tbar = $('<div class="ws-toolbar"></div>').append("<ul/>").append(zb).append(mb).append(rb); 
     1054         
     1055        ws_tbar.attr("style", "display:none;"); 
     1056         
     1057        o.prepend(ws_tbar); 
     1058        o.mouseover(function() { 
     1059            o.attr("style", "outline: 1px solid #DDDDDD;"); 
     1060            ws_tbar.removeAttr("style"); 
     1061        }); 
     1062        o.mouseout(function() { 
     1063            o.removeAttr("style"); 
     1064            ws_tbar.attr("style", "display:none;"); 
     1065        }); 
     1066         
     1067        return o; 
     1068    } 
     1069     
     1070    function render_ws_inpage(divid, id, start, end, gran) { 
     1071        ws_displayinfo.start = start; 
     1072        ws_displayinfo.end = end; 
     1073        if (gran)  
     1074            ws_displayinfo.cnt = gran; 
     1075         
     1076        plot_board = $('#' + divid); 
     1077         
     1078        plot_board.append('<h2 class="ws_title" id="worksheetTitlePerma">Worksheet Title</h2>\ 
    9911079                 <p/>\ 
    9921080                 <div id="ws_datetool">\ 
    9931081                 <div class="zoom">\ 
    994                <dl>\ 
    995                        <dt>Zoom:</dt>\ 
    996                        <dd><a href="#" class="first datechoice">6h</a></dd>\ 
    997                        <dd><a href="#" class="datechoice">12h</a></dd>\ 
    998                        <dd><a href="#" class="datechoice">1d</a></dd>\ 
    999                        <dd><a href="#" class="datechoice">2d</a></dd>\ 
    1000                        <dd><a href="#" class="datechoice">1w</a></dd>\ 
    1001                        <dd><a href="#" class="selected datechoice">2w</a></dd>\ 
    1002                        <dd><a href="#" class="datechoice">4w</a></dd>\ 
    1003                        <dd><a href="#" class="datechoice">1y</a></dd>\ 
    1004                </dl>\ 
    1005               </div>\ 
    1006               <div class="range">\ 
    1007                <dl>\ 
    1008                        <dt>Date Range:</dt>\ 
    1009                        <dd><a href="" class="btn-slide">YYYY/MM/DD - YYYY/MM/DD</a></dd>\ 
    1010                </dl>\ 
    1011        </div>\ 
     1082        <dl>\ 
     1083            <dt>Zoom:</dt>\ 
     1084            <dd><a href="#" class="first datechoice">6h</a></dd>\ 
     1085            <dd><a href="#" class="datechoice">12h</a></dd>\ 
     1086            <dd><a href="#" class="datechoice">1d</a></dd>\ 
     1087            <dd><a href="#" class="datechoice">2d</a></dd>\ 
     1088            <dd><a href="#" class="datechoice">1w</a></dd>\ 
     1089            <dd><a href="#" class="selected datechoice">2w</a></dd>\ 
     1090            <dd><a href="#" class="datechoice">4w</a></dd>\ 
     1091            <dd><a href="#" class="datechoice">1y</a></dd>\ 
     1092        </dl>\ 
     1093           </div>\ 
     1094           <div class="range">\ 
     1095        <dl>\ 
     1096            <dt>Date Range:</dt>\ 
     1097            <dd><a href="" class="btn-slide">YYYY/MM/DD - YYYY/MM/DD</a></dd>\ 
     1098        </dl>\ 
     1099    </div>\ 
    10121100        <br style="clear:both; margin-bottom:0.5em;"/>\ 
    1013        <div id="ws_widgetCalendar" class="widgetCalendar"></div>'); 
    1014  
    1015       plot_board.append('<div>\ 
     1101    <div id="ws_widgetCalendar" class="widgetCalendar"></div>'); 
     1102         
     1103        plot_board.append('<div>\ 
    10161104      <ul id="worksheet-graphs" />\ 
    10171105      <br style="clear:left" />\ 
    1018       </div>   
     1106      </div>   
    10191107          <div style="display:none">\ 
    1020         <div id="maingraph-template">\ 
     1108    <div id="maingraph-template">\ 
    10211109         <div class="plot-area" style="width:380px;height:180px"></div>\ 
    10221110         <div class="plot-legend">legend</div>\ 
     
    10261114       <div id="ws_payload">\ 
    10271115       </div>'); 
    1028       $.getJSON("json/worksheet/info/" + id, process_worksheet_json); 
    1029       locked = true; 
    1030       lock_wforms(); 
    1031   } 
    1032  
    1033   function render_graph_inpage(divid, id, start, end, gran) { 
    1034  
    1035 $.getJSON("json/graph/info/" + id, function (ginfo) { 
    1036  
    1037               streaming = false;  //precautionary 
    1038               stream_graph = $('#'+divid); 
    1039               stream_graph.ReconGraph({graphid: ginfo.id, type: ginfo.type, width: (gran) ? gran : 780}); 
    1040               stream_graph.ReconGraphRefresh({graphid: ginfo.id, start: start, end: end, stacks: ginfo.stacks}); 
    1041  
    1042     var dtool =  $("<div id='mini_ws_datetool'>"); 
    1043     dtool.append('<div class="zoom"> \ 
     1116        $.getJSON("json/worksheet/info/" + id, process_worksheet_json); 
     1117        locked = true; 
     1118        lock_wforms(); 
     1119    } 
     1120     
     1121    function render_graph_inpage(divid, id, start, end, gran) { 
     1122     
     1123        $.getJSON("json/graph/info/" + id, function(ginfo) { 
     1124         
     1125            streaming = false; //precautionary 
     1126            stream_graph = $('#' + divid); 
     1127            stream_graph.ReconGraph({ 
     1128                graphid: ginfo.id, 
     1129                type: ginfo.type, 
     1130                width: (gran) ? gran : 780 
     1131            }); 
     1132            stream_graph.ReconGraphRefresh({ 
     1133                graphid: ginfo.id, 
     1134                start: start, 
     1135                end: end, 
     1136                stacks: ginfo.stacks 
     1137            }); 
     1138             
     1139            var dtool = $("<div id='mini_ws_datetool'>"); 
     1140            dtool.append('<div class="zoom"> \ 
    10441141                <dl> \ 
    10451142                        <dt>Zoom:</dt> \ 
     
    10531150                 </div>\ 
    10541151                  </div>'); 
    1055  
    1056     var mheader = $("<div id='stream-header'>").append(dtool); 
    1057     stream_controls = get_stream_controls(); 
    1058     mheader.append(stream_controls); 
    1059  
    1060     stream_graph.prepend(mheader); 
    1061     stream_graph.append("<div id='streambox' style='display:none'></div>"); 
    1062     stream_graph.append("<div class='stream-log' style='display:none'></div>"); 
    1063  
    1064     $("#stopstream").click(function() { 
    1065         streaming = false; 
    1066         $("#mini_ws_datetool").show(); 
    1067         $("#play_pause").html('PLAY'); 
    1068         $('#streambox').html(''); 
    1069         $(".stream-log").hide(); 
    1070         $("#oslider").hide(); 
    1071         $(".stream_controls").width(""); 
    1072         $(this).hide(); 
    1073         stream_graph.ReconGraphRefresh({graphid: ginfo.id, stacks: ginfo.stacks}); 
    1074      }); 
    1075  
    1076     $("#play_pause").click(function() { 
    1077       if($(this).html() == 'PLAY') { 
    1078         $(this).html('PAUSE'); 
    1079         //if we are playing for the frist time 
    1080         if(!streaming) { 
    1081             $('#mini_ws_datetool').hide(); 
    1082             $(".stream-log").show().html("stream log_"); 
    1083             //theres probably a better way to make sure stuff fits in the stream_controls div 
    1084             $(".stream_controls").width("290px"); 
    1085             $("#stopstream").show(); 
    1086             $("#oslider").show();            
    1087         } 
    1088         //setup/restart the plotting 
    1089         stream_data(ginfo.id, stream_graph, $('#streambox')); 
    1090       } 
    1091       else if($(this).html() == 'PAUSE') { 
    1092              $(this).html('PLAY'); 
    1093              //this is where we pause for a bit 
    1094              stream_graph.stopTime(); 
    1095       } 
    1096    }); 
    1097  
    1098               $("#pollslider").slider({orientation: 'horizontal', value: polltime, max: 10000, min: 1000, step: 1000, 
    1099                     change: function (event, ui) {   
    1100                         polltime = $(this).slider('option', 'value');  
    1101                         $("#polltime").html(polltime+" ms"); 
    1102                         if(streaming) { 
    1103                             streaming = false; 
    1104                             $('#streambox').html(''); 
    1105                             $("#play_pause").html('PAUSE'); 
    1106                             stream_data(ginfo.id, stream_graph, $('#streambox')); 
    1107                         } 
    1108                       }                  
    1109             }); 
    1110  
    1111    $("#mini_ws_datetool .datechoice").click(function(){ 
    1112         $(".datechoice").removeClass("selected"); 
    1113         $(this).addClass("selected"); 
    1114         stream_graph.ReconGraphRefresh({graphid: ginfo.id, stacks: ginfo.stacks, start: time_window_to_seconds($(this).html()), end: ''}); 
    1115         return false; 
    1116     }); 
    1117  
    1118     });//end json call 
    1119  
    1120   } 
    1121   function zoom_modal (id, gtype) { 
    1122  
    1123   if(id) $.getJSON("json/graph/info/" + id, function (ginfo) { 
    1124  
    1125     streaming = false;  //precautionary 
    1126     stream_graph = $('<div></div>').ReconGraph({graphid: ginfo.id, type: ginfo.type, width:780}); 
    1127     var smod = stream_graph.modal({ 
    1128       containerId: 'StreamingModalContainer', 
    1129       close: 'true', 
    1130       overlayCss: { 
    1131         backgroundColor: '#000000', 
    1132         cursor: 'wait' 
    1133         }, 
    1134       containerCss: { 
    1135         backgroundColor: '#FFFFFF', 
    1136         left: '30%', 
    1137         top: '10%', 
    1138         border: '2px solid #000000', 
    1139         padding: '5px' 
    1140       }, 
    1141     }); 
    1142     stream_graph.ReconGraphRefresh({graphid: ginfo.id, stacks: ginfo.stacks}); 
    1143  
    1144  
    1145     var dtool =  $("<div id='mini_ws_datetool'>"); 
    1146     dtool.append('<div class="zoom"> \ 
     1152             
     1153            var mheader = $("<div id='stream-header'>").append(dtool); 
     1154            stream_controls = get_stream_controls(); 
     1155            mheader.append(stream_controls); 
     1156             
     1157            stream_graph.prepend(mheader); 
     1158            stream_graph.append("<div id='streambox' style='display:none'></div>"); 
     1159            stream_graph.append("<div class='stream-log' style='display:none'></div>"); 
     1160             
     1161            $("#stopstream").click(function() { 
     1162                streaming = false; 
     1163                $("#mini_ws_datetool").show(); 
     1164                $("#play_pause").html('PLAY'); 
     1165                $('#streambox').html(''); 
     1166                $(".stream-log").hide(); 
     1167                $("#oslider").hide(); 
     1168                $(".stream_controls").width(""); 
     1169                $(this).hide(); 
     1170                stream_graph.ReconGraphRefresh({ 
     1171                    graphid: ginfo.id, 
     1172                    stacks: ginfo.stacks 
     1173                }); 
     1174            }); 
     1175             
     1176            $("#play_pause").click(function() { 
     1177                if ($(this).html() == 'PLAY') { 
     1178                    $(this).html('PAUSE'); 
     1179                    //if we are playing for the frist time 
     1180                    if (!streaming) { 
     1181                        $('#mini_ws_datetool').hide(); 
     1182                        $(".stream-log").show().html("stream log_"); 
     1183                        //theres probably a better way to make sure stuff fits in the stream_controls div 
     1184                        $(".stream_controls").width("290px"); 
     1185                        $("#stopstream").show(); 
     1186                        $("#oslider").show(); 
     1187                    } 
     1188                    //setup/restart the plotting 
     1189                    stream_data(ginfo.id, stream_graph, $('#streambox')); 
     1190                } 
     1191                else if ($(this).html() == 'PAUSE') { 
     1192                    $(this).html('PLAY'); 
     1193                    //this is where we pause for a bit 
     1194                    stream_graph.stopTime(); 
     1195                } 
     1196            }); 
     1197             
     1198            $("#pollslider").slider({ 
     1199                orientation: 'horizontal', 
     1200                value: polltime, 
     1201                max: 10000, 
     1202                min: 1000, 
     1203                step: 1000, 
     1204                change: function(event, ui) { 
     1205                    polltime = $(this).slider('option', 'value'); 
     1206                    $("#polltime").html(polltime + " ms"); 
     1207                    if (streaming) { 
     1208                        streaming = false; 
     1209                        $('#streambox').html(''); 
     1210                        $("#play_pause").html('PAUSE'); 
     1211                        stream_data(ginfo.id, stream_graph, $('#streambox')); 
     1212                    } 
     1213                } 
     1214            }); 
     1215             
     1216            $("#mini_ws_datetool .datechoice").click(function() { 
     1217                $(".datechoice").removeClass("selected"); 
     1218                $(this).addClass("selected"); 
     1219                stream_graph.ReconGraphRefresh({ 
     1220                    graphid: ginfo.id, 
     1221                    stacks: ginfo.stacks, 
     1222                    start: time_window_to_seconds($(this).html()), 
     1223                    end: '' 
     1224                }); 
     1225                return false; 
     1226            }); 
     1227             
     1228        }); //end json call 
     1229    } 
     1230    function zoom_modal(id, gtype) { 
     1231     
     1232        if (id)  
     1233            $.getJSON("json/graph/info/" + id, function(ginfo) { 
     1234             
     1235                streaming = false; //precautionary 
     1236                stream_graph = $('<div></div>').ReconGraph({ 
     1237                    graphid: ginfo.id, 
     1238                    type: ginfo.type, 
     1239                    width: 780 
     1240                }); 
     1241                var smod = stream_graph.modal({ 
     1242                    containerId: 'StreamingModalContainer', 
     1243                    close: 'true', 
     1244                    overlayCss: { 
     1245                        backgroundColor: '#000000', 
     1246                        cursor: 'wait' 
     1247                    }, 
     1248                    containerCss: { 
     1249                        backgroundColor: '#FFFFFF', 
     1250                        left: '30%', 
     1251                        top: '10%', 
     1252                        border: '2px solid #000000', 
     1253                        padding: '5px' 
     1254                    }, 
     1255                }); 
     1256                stream_graph.ReconGraphRefresh({ 
     1257                    graphid: ginfo.id, 
     1258                    stacks: ginfo.stacks 
     1259                }); 
     1260                 
     1261                var dtool = $("<div id='mini_ws_datetool'>"); 
     1262                dtool.append('<div class="zoom"> \ 
    11471263                <dl> \ 
    11481264                        <dt>Zoom:</dt> \ 
     
    11561272                 </div>\ 
    11571273                  </div>'); 
    1158  
    1159     var mheader = $("<div id='stream-modal-header'>").append(dtool); 
    1160  
    1161     mheader.append("<span class='zoomClose'>x</span>") 
    1162     mheader.append(get_stream_controls()); 
    1163  
    1164  
    1165     stream_graph.prepend(mheader); 
    1166     stream_graph.append("<div class='stream-log' style='display:none'></div>"); 
    1167  
    1168  
    1169     $(".zoomClose").click(function() { 
    1170       streaming = false; 
    1171       $('#streambox').html(''); 
    1172       smod.close(); 
    1173     }); 
    1174  
    1175  
    1176     $("#play_pause").click(function() { 
    1177       if($(this).html() == 'PLAY') { 
    1178         $(this).html('PAUSE'); 
    1179         //if we are playing for the frist time 
    1180         if(!streaming) { 
    1181             $("#mini_ws_datetool").hide(); 
    1182             $(".stream-log").show().html("stream log_"); 
    1183             $("#stopstream").show(); 
    1184             $("#oslider").show(); 
    1185             //theres probably a better way to make sure stuff fits in the stream_controls div 
    1186             $(".stream_controls").width("290px"); 
    1187         } 
    1188         //setup/restart the plotting 
    1189         stream_data(ginfo.id, stream_graph, $('#streambox')); 
    1190       } 
    1191       else if($(this).html() == 'PAUSE') { 
    1192              $(this).html('PLAY'); 
    1193              //this is where we pause for a bit 
    1194              stream_graph.stopTime(); 
    1195       } 
    1196    }); 
    1197  
    1198     $("#stopstream").click(function() { 
    1199         streaming = false; 
    1200         $('#mini_ws_datetool').show(); 
    1201         $("#play_pause").html('PLAY'); 
    1202         $('#streambox').html(''); 
    1203         $(".stream-log").hide(); 
    1204         $(this).hide(); 
    1205         $("#oslider").hide(); 
    1206         $(".stream_controls").width(""); 
    1207         stream_graph.ReconGraphRefresh({graphid: ginfo.id, stacks: ginfo.stacks}); 
    1208      }); 
    1209  
    1210     $("#pollslider").slider({orientation: 'horizontal', value: polltime, max: 10000, min: 1000, step: 1000, 
    1211                     change: function (event, ui) {   
    1212                         polltime = $(this).slider('option', 'value');  
    1213                         $("#polltime").html(polltime+" ms"); 
    1214                         if(streaming) { 
    1215                             streaming = false; 
    1216                             $('#streambox').html(''); 
    1217                             $("#play_pause").html('PAUSE'); 
    1218                             stream_data(ginfo.id, stream_graph, $('#streambox')); 
    1219                         } 
    1220                       }                  
    1221     }); 
    1222  
    1223     $("#mini_ws_datetool .datechoice").click(function(){ 
    1224        $(".datechoice").removeClass("selected"); 
    1225        $(this).addClass("selected"); 
    1226        stream_graph.ReconGraphRefresh({graphid: ginfo.id, stacks: ginfo.stacks, start: time_window_to_seconds($(this).html()), end: ''}); 
    1227        return false; 
    1228    }); 
    1229   }); 
    1230   } //end zoom_modal 
    1231  
    1232   function lock_wforms() { 
    1233     locked = true; 
    1234     $("h2#worksheetTitle").unbind(); 
    1235     $("ul#worksheet-graphs").unbind(); 
    1236     $(".ws-toolbar-edit").attr("class","ws-toolbar"); 
    1237   } 
    1238  
    1239   function unlock_wforms() { 
    1240     locked = false; 
    1241     $("h2#worksheetTitle").editable(function(value, settings) { 
    1242       wsinfo.title = value; 
    1243       update_current_worksheet(); 
    1244       return(value); 
    1245     }, { }); 
    1246  
    1247     var ul = $("ul#worksheet-graphs"); 
    1248     ul.sortable({ handle: '.moveGraph', 
    1249                   scroll: true, 
    1250                   stop: 
    1251                     function (e,ui) { 
    1252                       wsinfo.graphs = new Array(); 
    1253                       ui.item.parent().find("> li > div").each( 
    1254                         function(i) { 
    1255                           wsinfo.graphs.push($(this).attr("id")); 
     1274                 
     1275                var mheader = $("<div id='stream-modal-header'>").append(dtool); 
     1276                 
     1277                mheader.append("<span class='zoomClose'>x</span>") 
     1278                mheader.append(get_stream_controls()); 
     1279                 
     1280                stream_graph.prepend(mheader); 
     1281                stream_graph.append("<div class='stream-log' style='display:none'></div>"); 
     1282                 
     1283                $(".zoomClose").click(function() { 
     1284                    streaming = false; 
     1285                    $('#streambox').html(''); 
     1286                    smod.close(); 
     1287                }); 
     1288                 
     1289                $("#play_pause").click(function() { 
     1290                    if ($(this).html() == 'PLAY') { 
     1291                        $(this).html('PAUSE'); 
     1292                        //if we are playing for the frist time 
     1293                        if (!streaming) { 
     1294                            $("#mini_ws_datetool").hide(); 
     1295                            $(".stream-log").show().html("stream log_"); 
     1296                            $("#stopstream").show(); 
     1297                            $("#oslider").show(); 
     1298                            //theres probably a better way to make sure stuff fits in the stream_controls div 
     1299                            $(".stream_controls").width("290px"); 
    12561300                        } 
    1257                       ); 
    1258                       update_current_worksheet(); 
     1301                        //setup/restart the plotting 
     1302                        stream_data(ginfo.id, stream_graph, $('#streambox')); 
     1303                    } 
     1304                    else if ($(this).html() == 'PAUSE') { 
     1305                        $(this).html('PLAY'); 
     1306                        //this is where we pause for a bit 
     1307                        stream_graph.stopTime(); 
    12591308                    } 
    12601309                }); 
    1261  
    1262     $(".ws-toolbar").attr("class","ws-toolbar-edit"); 
    1263   } 
    1264  
    1265  
    1266   //this is a bad function, because we have to account for start/end being UTC strings or integers, and to do so outside 
    1267   //would require changes to the where we keep worksheet ui code 
    1268   function update_worksheet_permalink(id, start, end, gran){ 
    1269         if(start != ""){ 
    1270                   if(parseInt(start) == start) { 
    1271                       var cdate = new Date(); 
    1272                       start = parseInt(cdate.getTime() - ws_displayinfo.start*1000); 
    1273                   } 
    1274                   else { 
    1275                       start = new Date(start); 
    1276                       start = parseInt(start.getTime()); 
    1277                   } 
    1278         }      
    1279         if(end!="") { 
    1280              if(parseInt(end) == end) { 
    1281                  end = parseInt(end); 
    1282              } 
    1283              else { 
    1284                  end = new Date(end); 
    1285                  end = parseInt(end.getTime()); 
    1286              } 
    1287          }       
    1288       if($('#wpermalink a')){          
    1289           $('#wpermalink a').attr('href', "drawing_board.php?otype=wsheet&id="+id+"&start="+start+"&end="+end+"&gran="+gran); 
    1290       } 
    1291   }   
    1292    
    1293  
    1294   function update_current_worksheet(f) { 
    1295     var str = JSON.stringify(wsinfo); 
    1296     $.post("json/worksheet/store", 
    1297            {'json':str}, 
    1298            function(d) { 
    1299              wsinfo.id = d.id; 
    1300              if(d.error) $("#ws-tool-error").html(d.error).fadeIn('fast'); 
    1301              else $("#ws-tool-error").fadeOut('fast'); 
    1302              if(wsinfo.id && wsinfo.title && wsinfo.saved != true && 
    1303                 $(".rememberWorksheet:visible").length == 0) { 
    1304                wsinfo.saved = false; 
    1305                $(".rememberWorksheet").html('"Remember" this worksheet.').fadeIn('slow'); 
    1306                lock_wforms(); 
    1307                modal_warning("Worksheet not saved!", "You must hit 'Remember' to continue editing."); 
    1308                $(".rememberWorksheet").click(function() { 
    1309                  wsinfo.saved = true; 
    1310                  update_current_worksheet(function(r) { 
    1311                    if(r.error) wsinfo.saved = false; 
    1312                    else { 
    1313                       $(".rememberWorksheet").html('Remebered').fadeOut('slow'); 
    1314                       if(wsinfo.id) update_worksheet_permalink(wsinfo.id, "", "", ""); 
    1315                       unlock_wforms(); 
    1316                    } 
    1317                  }); 
    1318                }); 
    1319              } 
    1320              if(f) f(d); 
    1321            }, 'json'); 
    1322   } 
    1323  
    1324   function process_worksheet_json(r) { 
    1325     wsinfo.id = r.sheetid; 
    1326     wsinfo.title = r.title; 
    1327     ws_displayinfo.title = r.title; 
    1328     wsinfo.graphs = new Array(); 
    1329  
    1330     var ul = $("ul#worksheet-graphs"); 
    1331     $("h2.ws_title").html(r.title); 
    1332     ul.empty(); 
    1333     for(var i = 0; i < r.graphs.length; i++) { 
    1334       var g = {}; 
    1335       g.graphid = r.graphs[i]; 
    1336       g.start = ws_displayinfo.start; 
    1337       g.end = ws_displayinfo.end; 
    1338       g.cnt = ws_displayinfo.cnt; 
    1339  
    1340       $.getJSON("json/graph/info/" + g.graphid, 
    1341         function (j) { 
    1342             g.type = j.type; 
    1343             g.graphid = j.id; 
    1344             g.stacks = j.stacks; 
    1345             var o = make_ws_graph(g); 
    1346             ul.append($('<li/>').append(o)); 
    1347             o.ReconGraphRefresh(); 
    1348             wsinfo.graphs.push(g.graphid); 
    1349          }); 
    1350       } 
    1351       update_worksheet_permalink(wsinfo.id, "", "", ws_displayinfo.cnt); 
    1352       ul.sortable("refresh"); 
    1353   } 
    1354  
    1355   function add_graph_to_worksheet(graphid) { 
    1356     if(!ws_locked("Click 'Edit Worksheet' to unlock.")){ 
    1357       for(var i = 0; wsinfo.graphs && (i < wsinfo.graphs.length); i++) { 
    1358         if(wsinfo.graphs[i]==graphid) { 
    1359           modal_warning("", "Worksheets cannot have duplicate graphs!"); 
    1360           return; 
    1361         } 
    1362       } 
    1363       var g = { start: ws_displayinfo.start, 
     1310                 
     1311                $("#stopstream").click(function() { 
     1312                    streaming = false; 
     1313                    $('#mini_ws_datetool').show(); 
     1314                    $("#play_pause").html('PLAY'); 
     1315                    $('#streambox').html(''); 
     1316                    $(".stream-log").hide(); 
     1317                    $(this).hide(); 
     1318                    $("#oslider").hide(); 
     1319                    $(".stream_controls").width(""); 
     1320                    stream_graph.ReconGraphRefresh({ 
     1321                        graphid: ginfo.id, 
     1322                        stacks: ginfo.stacks 
     1323                    }); 
     1324                }); 
     1325                 
     1326                $("#pollslider").slider({ 
     1327                    orientation: 'horizontal', 
     1328                    value: polltime, 
     1329                    max: 10000, 
     1330                    min: 1000, 
     1331                    step: 1000, 
     1332                    change: function(event, ui) { 
     1333                        polltime = $(this).slider('option', 'value'); 
     1334                        $("#polltime").html(polltime + " ms"); 
     1335                        if (streaming) { 
     1336                            streaming = false; 
     1337                            $('#streambox').html(''); 
     1338                            $("#play_pause").html('PAUSE'); 
     1339                            stream_data(ginfo.id, stream_graph, $('#streambox')); 
     1340                        } 
     1341                    } 
     1342                }); 
     1343                 
     1344                $("#mini_ws_datetool .datechoice").click(function() { 
     1345                    $(".datechoice").removeClass("selected"); 
     1346                    $(this).addClass("selected"); 
     1347                    stream_graph.ReconGraphRefresh({ 
     1348                        graphid: ginfo.id, 
     1349                        stacks: ginfo.stacks, 
     1350                        start: time_window_to_seconds($(this).html()), 
     1351                        end: '' 
     1352                    }); 
     1353                    return false; 
     1354                }); 
     1355            }); 
     1356    } //end zoom_modal 
     1357    function lock_wforms() { 
     1358        locked = true; 
     1359        $("h2#worksheetTitle").unbind(); 
     1360        $("ul#worksheet-graphs").unbind(); 
     1361        $(".ws-toolbar-edit").attr("class", "ws-toolbar"); 
     1362    } 
     1363     
     1364    function unlock_wforms() { 
     1365        locked = false; 
     1366        $("h2#worksheetTitle").editable(function(value, settings) { 
     1367            wsinfo.title = value; 
     1368            update_current_worksheet(); 
     1369            return (value); 
     1370        }, {}); 
     1371         
     1372        var ul = $("ul#worksheet-graphs"); 
     1373        ul.sortable({ 
     1374            handle: '.moveGraph', 
     1375            scroll: true, 
     1376            stop: function(e, ui) { 
     1377                wsinfo.graphs = new Array(); 
     1378                ui.item.parent().find("> li > div").each(function(i) { 
     1379                    wsinfo.graphs.push($(this).attr("id")); 
     1380                }); 
     1381                update_current_worksheet(); 
     1382            } 
     1383        }); 
     1384         
     1385        $(".ws-toolbar").attr("class", "ws-toolbar-edit"); 
     1386    } 
     1387     
     1388    //this is a bad function, because we have to account for start/end being UTC strings or integers, and to do so outside 
     1389    //would require changes to the where we keep worksheet ui code 
     1390    function update_worksheet_permalink(id, start, end, gran) { 
     1391        if (start != "") { 
     1392            if (parseInt(start) == start) { 
     1393                var cdate = new Date(); 
     1394                start = parseInt(cdate.getTime() - ws_displayinfo.start * 1000); 
     1395            } 
     1396            else { 
     1397                start = new Date(start); 
     1398                start = parseInt(start.getTime()); 
     1399            } 
     1400        } 
     1401        if (end != "") { 
     1402            if (parseInt(end) == end) { 
     1403                end = parseInt(end); 
     1404            } 
     1405            else { 
     1406                end = new Date(end); 
     1407                end = parseInt(end.getTime()); 
     1408            } 
     1409        } 
     1410        if ($('#wpermalink a')) { 
     1411            $('#wpermalink a').attr('href', "drawing_board.php?otype=wsheet&id=" + id + "&start=" + start + "&end=" + end + "&gran=" + gran); 
     1412        } 
     1413    } 
     1414     
     1415    function update_current_worksheet(f) { 
     1416        var str = JSON.stringify(wsinfo); 
     1417        $.post("json/worksheet/store", { 
     1418            'json': str 
     1419        }, function(d) { 
     1420            wsinfo.id = d.id; 
     1421            if (d.error)  
     1422                $("#ws-tool-error").html(d.error).fadeIn('fast'); 
     1423            else  
     1424                $("#ws-tool-error").fadeOut('fast'); 
     1425            if (wsinfo.id && wsinfo.title && wsinfo.saved != true && $(".rememberWorksheet:visible").length == 0) { 
     1426                wsinfo.saved = false; 
     1427                $(".rememberWorksheet").html('"Remember" this worksheet.').fadeIn('slow'); 
     1428                lock_wforms(); 
     1429                modal_warning("Worksheet not saved!", "You must hit 'Remember' to continue editing."); 
     1430                $(".rememberWorksheet").click(function() { 
     1431                    wsinfo.saved = true; 
     1432                    update_current_worksheet(function(r) { 
     1433                        if (r.error)  
     1434                            wsinfo.saved = false; 
     1435                        else { 
     1436                            $(".rememberWorksheet").html('Remebered').fadeOut('slow'); 
     1437                            if (wsinfo.id)  
     1438                                update_worksheet_permalink(wsinfo.id, "", "", ""); 
     1439                            unlock_wforms(); 
     1440                        } 
     1441                    }); 
     1442                }); 
     1443            } 
     1444            if (f)  
     1445                f(d); 
     1446        }, 'json'); 
     1447    } 
     1448     
     1449    function process_worksheet_json(r) { 
     1450        wsinfo.id = r.sheetid; 
     1451        wsinfo.title = r.title; 
     1452        ws_displayinfo.title = r.title; 
     1453        wsinfo.graphs = new Array(); 
     1454         
     1455        var ul = $("ul#worksheet-graphs"); 
     1456        $("h2.ws_title").html(r.title); 
     1457        ul.empty(); 
     1458        for (var i = 0; i < r.graphs.length; i++) { 
     1459            var g = {}; 
     1460            g.graphid = r.graphs[i]; 
     1461            g.start = ws_displayinfo.start; 
     1462            g.end = ws_displayinfo.end; 
     1463            g.cnt = ws_displayinfo.cnt; 
     1464             
     1465            $.getJSON("json/graph/info/" + g.graphid, function(j) { 
     1466                g.type = j.type; 
     1467                g.graphid = j.id; 
     1468                g.stacks = j.stacks; 
     1469                var o = make_ws_graph(g); 
     1470                ul.append($('<li/>').append(o)); 
     1471                o.ReconGraphRefresh(); 
     1472                wsinfo.graphs.push(g.graphid); 
     1473            }); 
     1474        } 
     1475        update_worksheet_permalink(wsinfo.id, "", "", ws_displayinfo.cnt); 
     1476        ul.sortable("refresh"); 
     1477    } 
     1478     
     1479    function add_graph_to_worksheet(graphid) { 
     1480        if (!ws_locked("Click 'Edit Worksheet' to unlock.")) { 
     1481            for (var i = 0; wsinfo.graphs && (i < wsinfo.graphs.length); i++) { 
     1482                if (wsinfo.graphs[i] == graphid) { 
     1483                    modal_warning("", "Worksheets cannot have duplicate graphs!"); 
     1484                    return; 
     1485                } 
     1486            } 
     1487            var g = { 
     1488                start: ws_displayinfo.start, 
    13641489                end: ws_displayinfo.end, 
    13651490                cnt: ws_displayinfo.cnt, 
    1366                 graphid: graphid }; 
    1367  
    1368       $.getJSON("json/graph/info/" + g.graphid, 
    1369         function (j) { 
    1370           g.type = j.type; 
    1371           g.graphid = j.id; 
    1372           g.stacks = j.stacks; 
    1373           var o = make_ws_graph(g); 
    1374           var ul = $("ul#worksheet-graphs"); 
    1375           ul.append($('<li/>').append(o)); 
    1376           o.ReconGraphRefresh(); 
    1377           ul.sortable("refresh"); 
    1378           if(!wsinfo.graphs) {wsinfo.graphs = new Array();} 
    1379           wsinfo.graphs.push(graphid); 
    1380           update_current_worksheet(); 
    1381           unlock_wforms(); 
    1382         }); 
    1383     } 
    1384   } 
    1385   function display_info(start,end,cnt) { 
    1386     ws_displayinfo.start = start; 
    1387     ws_displayinfo.end = end; 
    1388     if(cnt) ws_displayinfo.cnt = cnt; 
    1389     update_worksheet_permalink(wsinfo.id, ws_displayinfo.start, ws_displayinfo.end, ws_displayinfo.cnt); 
    1390   } 
    1391   function refresh_worksheet() { 
    1392     var g = { start: ws_displayinfo.start, 
    1393               end: ws_displayinfo.end, 
    1394               cnt: ws_displayinfo.cnt }; 
    1395     $("ul#worksheet-graphs > li > div").ReconGraphRefresh(g); 
    1396   } 
    1397   function load_worksheet(id) { 
    1398     if(id==null) { 
    1399       wsinfo.saved = false; 
    1400       locked = false; 
    1401       unlock_wforms(); 
    1402       $(".editWorksheet").html('Editing!').fadeIn('slow'); 
    1403       process_worksheet_json({graphs: [], title:'Worksheet Title (click to edit)', sheetid: ''}); 
    1404     } 
    1405     else { 
    1406       wsinfo.saved = true; 
    1407       locked = true; 
    1408       lock_wforms(); 
    1409       $(".editWorksheet").html('Edit Worksheet').fadeIn('slow'); 
    1410       $.getJSON("json/worksheet/info/" + id, process_worksheet_json); 
    1411     } 
    1412   } 
    1413   return { 
    1414     load: load_worksheet, 
    1415     display_info: display_info, 
    1416     refresh: refresh_worksheet, 
    1417     add_graph: add_graph_to_worksheet, 
    1418     update: update_current_worksheet, 
    1419     lock: lock_wforms, 
    1420     unlock: unlock_wforms, 
    1421     zoom: zoom_modal, 
    1422     render_graph_inpage: render_graph_inpage, 
    1423     render_ws_inpage: render_ws_inpage, 
    1424     stream: stream_data, 
    1425     islocked: function () { return locked; } 
    1426   }; 
    1427   })(jQuery); 
     1491                graphid: graphid 
     1492            }; 
     1493             
     1494            $.getJSON("json/graph/info/" + g.graphid, function(j) { 
     1495                g.type = j.type; 
     1496                g.graphid = j.id; 
     1497                g.stacks = j.stacks; 
     1498                var o = make_ws_graph(g); 
     1499                var ul = $("ul#worksheet-graphs"); 
     1500                ul.append($('<li/>').append(o)); 
     1501                o.ReconGraphRefresh(); 
     1502                ul.sortable("refresh"); 
     1503                if (!wsinfo.graphs) { 
     1504                    wsinfo.graphs = new Array(); 
     1505                } 
     1506                wsinfo.graphs.push(graphid); 
     1507                update_current_worksheet(); 
     1508                unlock_wforms(); 
     1509            }); 
     1510        } 
     1511    } 
     1512    function display_info(start, end, cnt) { 
     1513        ws_displayinfo.start = start; 
     1514        ws_displayinfo.end = end; 
     1515        if (cnt)  
     1516            ws_displayinfo.cnt = cnt; 
     1517        update_worksheet_permalink(wsinfo.id, ws_displayinfo.start, ws_displayinfo.end, ws_displayinfo.cnt); 
     1518    } 
     1519    function refresh_worksheet() { 
     1520        var g = { 
     1521            start: ws_displayinfo.start, 
     1522            end: ws_displayinfo.end, 
     1523            cnt: ws_displayinfo.cnt 
     1524        }; 
     1525        $("ul#worksheet-graphs > li > div").ReconGraphRefresh(g); 
     1526    } 
     1527    function load_worksheet(id) { 
     1528        if (id == null) { 
     1529            wsinfo.saved = false; 
     1530            locked = false; 
     1531            unlock_wforms(); 
     1532            $(".editWorksheet").html('Editing!').fadeIn('slow'); 
     1533            process_worksheet_json({ 
     1534                graphs: [], 
     1535                title: 'Worksheet Title (click to edit)', 
     1536                sheetid: '' 
     1537            }); 
     1538        } 
     1539        else { 
     1540            wsinfo.saved = true; 
     1541            locked = true; 
     1542            lock_wforms(); 
     1543            $(".editWorksheet").html('Edit Worksheet').fadeIn('slow'); 
     1544            $.getJSON("json/worksheet/info/" + id, process_worksheet_json); 
     1545        } 
     1546    } 
     1547    return { 
     1548        load: load_worksheet, 
     1549        display_info: display_info, 
     1550        refresh: refresh_worksheet, 
     1551        add_graph: add_graph_to_worksheet, 
     1552        update: update_current_worksheet, 
     1553        lock: lock_wforms, 
     1554        unlock: unlock_wforms, 
     1555        zoom: zoom_modal, 
     1556        render_graph_inpage: render_graph_inpage, 
     1557        render_ws_inpage: render_ws_inpage, 
     1558        stream: stream_data, 
     1559        islocked: function() { 
     1560            return locked; 
     1561        } 
     1562    }; 
     1563})(jQuery); 
  • ui/web/htdocs/js/reconui.js

    r62e653b r4ce18ee  
    1 $(document).ready(function(){ 
    2   $(".accordion h3:first").addClass("active"); 
    3   $(".accordion span").slideUp(); 
    4   $(".accordion span:first").slideDown(); 
    5  
    6   $("div#content > div:first").siblings().slideUp(); 
    7  
    8   $(".accordion h3").click(function(){ 
    9       $(this).next("span").slideToggle("normal") 
    10       .siblings("span:visible").slideUp("normal"); 
    11       $(this).toggleClass("active"); 
    12       $(this).siblings("h3").removeClass("active"); 
    13       $(this).siblings("h3").each(function(e) { 
    14         $("#" + $(this).attr("id") + "_panel").slideUp("fast");       }); 
    15       if($(this).hasClass("active")) 
    16         $("#" + $(this).attr("id") + "_panel").slideDown("fast"); 
    17       else 
    18         $("#" + $(this).attr("id") + "_panel").slideUp("fast"); 
    19   }); 
    20  
    21   var tabContainers = $('div.tabs > div'); 
    22   tabContainers.hide().filter(':first').show(); 
    23  
    24   $('div.tabs ul.tabNavigation a').click(function () { 
    25           tabContainers.hide(); 
    26           tabContainers.filter(this.hash).show(); 
    27           $('div.tabs ul.tabNavigation a').removeClass('selected'); 
    28           $(this).addClass('selected'); 
    29           return false; 
    30   }).filter(':first').click(); 
    31   var wstabContainers = $('div.ws-tabs > div'); 
    32   wstabContainers.hide().filter(':first').show(); 
    33     
    34   $('div.ws-tabs ul.tabNavigation a').click(function () { 
    35     wstabContainers.hide(); 
    36     wstabContainers.filter(this.hash).show(); 
    37     $('div.ws-tabs ul.tabNavigation a').removeClass('selected'); 
    38     $(this).addClass('selected'); 
    39     return false; 
    40   }).filter(':first').click(); 
    41  
    42   $("#ws-searchform").submit(function() { 
    43     perform_ws_search_edit({ domid: '#worksheetlist', 
    44                              search: $("#ws-searchinput").val(), 
    45                              offset: 0, 
    46                              limit: 25 }); 
    47     return false; 
    48   }); 
    49   $("#ws-graph-searchform").submit(function() { 
    50     perform_graph_search_add({ 'domid': '#ws-graphlist', 
    51                                'search': $("#ws-graph-searchinput").val(), 
    52                                'offset': 0, 
    53                                'limit': 25 }); 
    54     return false; 
    55   }); 
    56  
    57   perform_ws_search_edit({ domid: '#worksheetlist', 
    58                            search: '', 
    59                            offset: 0, 
    60                            limit: 25 }); 
    61  
    62   $("#templates").treeview({ 
    63     url: "json/templates/templateid/targetname/sid", 
    64     params: {} 
    65   }); 
    66   $("#targets").treeview({ 
    67     url: "json/ds/remote_address/target/name/metric_name", 
    68     params: {} // will become hash, indexed by id, of url params 
    69   }); 
    70  
    71   var state = false; 
    72 worksheet.load(); 
    73  
    74   $("h2#worksheetTitle").editable(function(value, settings) { 
    75     wsinfo.title = value; 
    76     worksheet.update(); 
    77     return(value); 
    78   }, { }); 
    79  
    80   $(".editWorksheet").click(function() { 
    81     if(worksheet.islocked()){ 
    82       worksheet.unlock(); 
    83       $(".editWorksheet").html('Editing!').fadeIn('slow'); 
    84     } 
    85     else { 
    86       worksheet.lock(); 
    87       $(".editWorksheet").html('Edit Worksheet').fadeIn('slow'); 
    88     } 
    89   }); 
    90  
    91  
    92   $(".blankWorksheet").click(function() { 
     1$(document).ready(function() { 
     2    $(".accordion h3:first").addClass("active"); 
     3    $(".accordion span").slideUp(); 
     4    $(".accordion span:first").slideDown(); 
     5     
     6    $("div#content > div:first").siblings().slideUp(); 
     7     
     8    $(".accordion h3").click(function() { 
     9        $(this).next("span").slideToggle("normal").siblings("span:visible").slideUp("normal"); 
     10        $(this).toggleClass("active"); 
     11        $(this).siblings("h3").removeClass("active"); 
     12        $(this).siblings("h3").each(function(e) { 
     13            $("#" + $(this).attr("id") + "_panel").slideUp("fast"); 
     14        }); 
     15        if ($(this).hasClass("active"))  
     16            $("#" + $(this).attr("id") + "_panel").slideDown("fast"); 
     17        else  
     18            $("#" + $(this).attr("id") + "_panel").slideUp("fast"); 
     19    }); 
     20     
     21    var tabContainers = $('div.tabs > div'); 
     22    tabContainers.hide().filter(':first').show(); 
     23     
     24    $('div.tabs ul.tabNavigation a').click(function() { 
     25        tabContainers.hide(); 
     26        tabContainers.filter(this.hash).show(); 
     27        $('div.tabs ul.tabNavigation a').removeClass('selected'); 
     28        $(this).addClass('selected'); 
     29        return false; 
     30    }).filter(':first').click(); 
     31    var wstabContainers = $('div.ws-tabs > div'); 
     32    wstabContainers.hide().filter(':first').show(); 
     33     
     34    $('div.ws-tabs ul.tabNavigation a').click(function() { 
     35        wstabContainers.hide(); 
     36        wstabContainers.filter(this.hash).show(); 
     37        $('div.ws-tabs ul.tabNavigation a').removeClass('selected'); 
     38        $(this).addClass('selected'); 
     39        return false; 
     40    }).filter(':first').click(); 
     41     
     42    $("#ws-searchform").submit(function() { 
     43        perform_ws_search_edit({ 
     44            domid: '#worksheetlist', 
     45            search: $("#ws-searchinput").val(), 
     46            offset: 0, 
     47            limit: 25 
     48        }); 
     49        return false; 
     50    }); 
     51    $("#ws-graph-searchform").submit(function() { 
     52        perform_graph_search_add({ 
     53            'domid': '#ws-graphlist', 
     54            'search': $("#ws-graph-searchinput").val(), 
     55            'offset': 0, 
     56            'limit': 25 
     57        }); 
     58        return false; 
     59    }); 
     60     
     61    perform_ws_search_edit({ 
     62        domid: '#worksheetlist', 
     63        search: '', 
     64        offset: 0, 
     65        limit: 25 
     66    }); 
     67     
     68    $("#templates").treeview({ 
     69        url: "json/templates/templateid/targetname/sid", 
     70        params: {} 
     71    }); 
     72    $("#targets").treeview({ 
     73        url: "json/ds/remote_address/target/name/metric_name", 
     74        params: {} // will become hash, indexed by id, of url params 
     75    }); 
     76     
     77    var state = false; 
    9378    worksheet.load(); 
    94   }); 
    95  
    96   $("#ws_datetool .btn-slide").click(function(){ 
    97     $("#ws_widgetCalendar").stop().animate({ 
    98       height: state ? 0 : 
    99                 $('#ws_widgetCalendar div.datepicker').get(0).offsetHeight 
    100     }, 500); 
    101     state = !state; 
    102     $(this).toggleClass("active"); 
    103     return false; 
    104   }); 
    105   $("#ws_datetool .datechoice").click(function(){ 
    106     $("#ws_datetool .range a.btn-slide").html("YYYY/MM/DD - YYYY/MM/DD"); 
    107     $("#ws_widgetCalendar").slideUp("slow"); 
    108     $("#ws_datetool .datechoice").removeClass("selected"); 
    109     $(this).addClass("selected"); 
    110     worksheet.display_info(time_window_to_seconds($(this).html()), ''); 
    111     //time_windows[$(this).html()], ''); 
    112     worksheet.refresh(); 
    113     return false; 
    114   }); 
    115   $('#ws_widgetCalendar').DatePicker({ 
    116     flat: true, 
    117     format: 'Y/m/d', 
    118     date: [new Date(), new Date()], 
    119     calendars: 3, 
    120     mode: 'range', 
    121     starts: 1, 
    122     onChange: function(formated) { 
    123       var dates; 
    124       dates = formated[0].split('/'); 
    125       var start = new Date(dates[0], dates[1]-1, dates[2], 0, 0, 0); 
    126       dates = formated[1].split('/'); 
    127       var end = new Date((new Date(dates[0], dates[1]-1, dates[2], 0, 0, 0)).getTime() + 86400000); 
    128       worksheet.display_info(start.toUTCString(), end.toUTCString()); 
    129       worksheet.refresh(); 
    130       $("#ws_datetool .datechoice").removeClass("selected"); 
    131       $('#ws_datetool .range a.btn-slide').get(0).innerHTML = formated.join(' - '); 
    132     } 
    133   }); 
    134   $("#ws-tool-error").click(function(){ 
    135     $("#ws-tool-error").fadeOut("slow"); 
    136   }); 
    137   $("#graph-searchform").submit(function() { 
    138     perform_graph_search_edit({ 'domid': '#graphlist', 
    139                                 'search': $("#graph-searchinput").val(), 
    140                                 'offset': 0, 
    141                                 'limit': 25 }); 
    142     return false; 
    143   }); 
    144   $("#datapoint-searchform").submit(function() { 
    145     perform_datapoint_search_add({ domid: '#searchlist', 
    146                                    search: $("#searchinput").val(), 
    147                                    offset: 0, 
    148                                    limit: 25 }); 
    149     return false; 
    150   }); 
    151  
     79     
     80    $("h2#worksheetTitle").editable(function(value, settings) { 
     81        wsinfo.title = value; 
     82        worksheet.update(); 
     83        return (value); 
     84    }, {}); 
     85     
     86    $(".editWorksheet").click(function() { 
     87        if (worksheet.islocked()) { 
     88            worksheet.unlock(); 
     89            $(".editWorksheet").html('Editing!').fadeIn('slow'); 
     90        } 
     91        else { 
     92            worksheet.lock(); 
     93            $(".editWorksheet").html('Edit Worksheet').fadeIn('slow'); 
     94        } 
     95    }); 
     96     
     97     
     98    $(".blankWorksheet").click(function() { 
     99        worksheet.load(); 
     100    }); 
     101     
     102    $("#ws_datetool .btn-slide").click(function() { 
     103        $("#ws_widgetCalendar").stop().animate({ 
     104            height: state ? 0 : $('#ws_widgetCalendar div.datepicker').get(0).offsetHeight 
     105        }, 500); 
     106        state = !state; 
     107        $(this).toggleClass("active"); 
     108        return false; 
     109    }); 
     110    $("#ws_datetool .datechoice").click(function() { 
     111        $("#ws_datetool .range a.btn-slide").html("YYYY/MM/DD - YYYY/MM/DD"); 
     112        $("#ws_widgetCalendar").slideUp("slow"); 
     113        $("#ws_datetool .datechoice").removeClass("selected"); 
     114        $(this).addClass("selected"); 
     115        worksheet.display_info(time_window_to_seconds($(this).html()), ''); 
     116        //time_windows[$(this).html()], ''); 
     117        worksheet.refresh(); 
     118        return false; 
     119    }); 
     120    $('#ws_widgetCalendar').DatePicker({ 
     121        flat: true, 
     122        format: 'Y/m/d', 
     123        date: [new Date(), new Date()], 
     124        calendars: 3, 
     125        mode: 'range', 
     126        starts: 1, 
     127        onChange: function(formated) { 
     128            var dates; 
     129            dates = formated[0].split('/'); 
     130            var start = new Date(dates[0], dates[1] - 1, dates[2], 0, 0, 0); 
     131            dates = formated[1].split('/'); 
     132            var end = new Date((new Date(dates[0], dates[1] - 1, dates[2], 0, 0, 0)).getTime() + 86400000); 
     133            worksheet.display_info(start.toUTCString(), end.toUTCString()); 
     134            worksheet.refresh(); 
     135            $("#ws_datetool .datechoice").removeClass("selected"); 
     136            $('#ws_datetool .range a.btn-slide').get(0).innerHTML = formated.join(' - '); 
     137        } 
     138    }); 
     139    $("#ws-tool-error").click(function() { 
     140        $("#ws-tool-error").fadeOut("slow"); 
     141    }); 
     142    $("#graph-searchform").submit(function() { 
     143        perform_graph_search_edit({ 
     144            'domid': '#graphlist', 
     145            'search': $("#graph-searchinput").val(), 
     146            'offset': 0, 
     147            'limit': 25 
     148        }); 
     149        return false; 
     150    }); 
     151    $("#datapoint-searchform").submit(function() { 
     152        perform_datapoint_search_add({ 
     153            domid: '#searchlist', 
     154            search: $("#searchinput").val(), 
     155            offset: 0, 
     156            limit: 25 
     157        }); 
     158        return false; 
     159    }); 
     160     
    152161}); 
    153162