forked from jackyaz/spdMerlin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
spdstats_www.asp
369 lines (369 loc) · 83.2 KB
/
spdstats_www.asp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
<link rel="shortcut icon" href="images/favicon.png">
<link rel="icon" href="images/favicon.png">
<title>spdMerlin</title>
<link rel="stylesheet" type="text/css" href="index_style.css">
<link rel="stylesheet" type="text/css" href="form_style.css">
<style>
p{font-weight:bolder}thead.collapsible-jquery{color:#fff;padding:0;width:100%;border:none;text-align:left;outline:none;cursor:pointer}td.nodata{height:65px!important;border:none!important;text-align:center!important;font:bolder 48px Arial!important}.SettingsTable{text-align:left}.SettingsTable input{text-align:left;margin-left:3px!important}.SettingsTable input.savebutton{text-align:center;margin-top:5px;margin-bottom:5px;border-right:solid 1px #000;border-left:solid 1px #000;border-bottom:solid 1px #000}.SettingsTable td.savebutton{border-right:solid 1px #000;border-left:solid 1px #000;border-bottom:solid 1px #000;background-color:#4d595d}.SettingsTable .cronbutton{text-align:center;min-width:50px;width:50px;height:23px;vertical-align:middle}.SettingsTable select{margin-left:3px!important}.SettingsTable label{margin-right:10px!important;vertical-align:top!important}.SettingsTable th{background-color:#1F2D35!important;background:#2F3A3E!important;border-bottom:none!important;border-top:none!important;font-size:12px!important;color:#fff!important;padding:4px!important;font-weight:bolder!important;padding:0!important}.SettingsTable td{word-wrap:break-word!important;overflow-wrap:break-word!important;border-right:none;border-left:none}.SettingsTable span.settingname{background-color:#1F2D35!important;background:#2F3A3E!important}.SettingsTable td.settingname{border-right:solid 1px #000;border-left:solid 1px #000;background-color:#1F2D35!important;background:#2F3A3E!important;width:35%!important}.SettingsTable td.settingvalue{text-align:left!important;border-right:solid 1px #000}.SettingsTable th:first-child{border-left:none!important}.SettingsTable th:last-child{border-right:none!important}.SettingsTable .invalid{background-color:#8b0000!important}.SettingsTable .disabled{background-color:#CCC!important;color:#888!important}div.sortTableContainer{height:300px;overflow-y:scroll;width:745px;border:1px solid #000}.sortTable{table-layout:fixed!important;border:none}thead.sortTableHeader th{background-image:linear-gradient(#92a0a5 0%,#66757c 100%);border-top:none!important;border-left:none!important;border-right:none!important;border-bottom:1px solid #000!important;font-weight:bolder;padding:2px;text-align:center;color:#fff;position:sticky;top:0;font-size:11px!important}thead.sortTableHeader th:first-child,thead.sortTableHeader th:last-child{border-right:none!important}thead.sortTableHeader th:first-child,thead.sortTableHeader td:first-child{border-left:none!important}tbody.sortTableContent td{border-bottom:1px solid #000!important;border-left:none!important;border-right:1px solid #000!important;border-top:none!important;padding:2px;text-align:center;overflow:hidden!important;white-space:nowrap!important;font-size:12px!important}tbody.sortTableContent tr.sortRow:nth-child(odd) td{background-color:#2F3A3E!important}tbody.sortTableContent tr.sortRow:nth-child(even) td{background-color:#475A5F!important}th.sortable{cursor:pointer}tbody.sortTableContent td a{text-decoration:underline!important}.removespacing{padding-left:0!important;margin-left:0!important;margin-bottom:5px!important;text-align:center!important}.schedulespan{display:inline-block!important;width:70px!important;color:#FFF!important;font-weight:700!important}div.schedulesettings{margin-bottom:5px}.spdtest_output{border:solid 1px #000}textarea.settings{padding:2px!important;background:#576D73!important;width:98%!important;font:11px 'Courier New',Courier,mono!important}
</style>
<script language="JavaScript" type="text/javascript" src="/ext/shared-jy/jquery.js"></script>
<script language="JavaScript" type="text/javascript" src="/ext/shared-jy/moment.js"></script>
<script language="JavaScript" type="text/javascript" src="/ext/shared-jy/chart.js"></script>
<script language="JavaScript" type="text/javascript" src="/ext/shared-jy/hammerjs.js"></script>
<script language="JavaScript" type="text/javascript" src="/ext/shared-jy/chartjs-plugin-zoom.js"></script>
<script language="JavaScript" type="text/javascript" src="/ext/shared-jy/chartjs-plugin-annotation.js"></script>
<script language="JavaScript" type="text/javascript" src="/ext/shared-jy/d3.js"></script>
<script language="JavaScript" type="text/javascript" src="/state.js"></script>
<script language="JavaScript" type="text/javascript" src="/general.js"></script>
<script language="JavaScript" type="text/javascript" src="/popup.js"></script>
<script language="JavaScript" type="text/javascript" src="/help.js"></script>
<script language="JavaScript" type="text/javascript" src="/ext/shared-jy/detect.js"></script>
<script language="JavaScript" type="text/javascript" src="/tmhist.js"></script>
<script language="JavaScript" type="text/javascript" src="/tmmenu.js"></script>
<script language="JavaScript" type="text/javascript" src="/client_function.js"></script>
<script language="JavaScript" type="text/javascript" src="/validator.js"></script>
<script>
var custom_settings;
function LoadCustomSettings(){
custom_settings = <% get_custom_settings(); %>;
for(var prop in custom_settings){
if(Object.prototype.hasOwnProperty.call(custom_settings,prop)){
if(prop.indexOf('spdmerlin') != -1 && prop.indexOf('spdmerlin_version') == -1){
eval('delete custom_settings.'+prop)
}
}
}
}
var $j=jQuery.noConflict(),daysofweek=["Mon","Tues","Wed","Thurs","Fri","Sat","Sun"],maxNoCharts=0,currentNoCharts=0,interfacelist="",interfacescomplete=[],interfacesdisabled=[],arraysortlistlinesWAN=[],sortnameWAN="Time",sortdirWAN="desc",arraysortlistlinesVPNC1=[],sortnameVPNC1="Time",sortdirVPNC1="desc",arraysortlistlinesVPNC2=[],sortnameVPNC2="Time",sortdirVPNC2="desc",arraysortlistlinesVPNC3=[],sortnameVPNC3="Time",sortdirVPNC3="desc",arraysortlistlinesVPNC4=[],sortnameVPNC4="Time",sortdirVPNC4="desc",arraysortlistlinesVPNC5=[],sortnameVPNC5="Time",sortdirVPNC5="desc",speedtestbinary="built-in",ShowLines=GetCookie("ShowLines","string"),ShowFill=GetCookie("ShowFill","string");""==ShowFill&&(ShowFill="origin");var DragZoom=!0,ChartPan=!1;Chart.defaults.global.defaultFontColor="#CCC",Chart.Tooltip.positioners.cursor=function(e,t){return t};var dataintervallist=["raw","hour","day"],chartlist=["daily","weekly","monthly"],timeunitlist=["hour","day","day"],intervallist=[24,7,30],bordercolourlist_Combined=["#fc8500","#42ecf5"],backgroundcolourlist_Combined=["rgba(252,133,0,0.5)","rgba(66,236,245,0.5)"],bordercolourlist_Quality=["#53047a","#07f242","#ffffff"],backgroundcolourlist_Quality=["rgba(83,4,122,0.5)","rgba(7,242,66,0.5)","rgba(255,255,255,0.5)"],typelist=["Combined","Quality"];function keyHandler(t){82==t.keyCode?($j(document).off("keydown"),ResetZoom()):68==t.keyCode?($j(document).off("keydown"),ToggleDragZoom(document.form.btnDragZoom)):70==t.keyCode?($j(document).off("keydown"),ToggleFill()):76==t.keyCode&&($j(document).off("keydown"),ToggleLines())}$j(document).keydown(function(t){keyHandler(t)}),$j(document).keyup(function(){$j(document).keydown(function(t){keyHandler(t)})});function Draw_Chart_NoData(e,t,a){document.getElementById("divLineChart_"+e+"_"+t).width="730",document.getElementById("divLineChart_"+e+"_"+t).height="500",document.getElementById("divLineChart_"+e+"_"+t).style.width="730px",document.getElementById("divLineChart_"+e+"_"+t).style.height="500px";var s=document.getElementById("divLineChart_"+e+"_"+t).getContext("2d");s.save(),s.textAlign="center",s.textBaseline="middle",s.font="normal normal bolder 48px Arial",s.fillStyle="white",s.fillText(a,365,250),s.restore()}function Draw_Chart(e,t){var a="",s="",r="",i="",l="",n="",d=!1;"Combined"==t?(a="Mbps",r="Bandwidth",i="Download",l="Upload"):"Quality"==t&&(a="ms",s="%",r="Quality",i="Latency",l="Jitter",n="PktLoss",d=!0);var o=getChartPeriod($j("#"+e+"_Period_"+t+" option:selected").val()),p=getChartInterval($j("#"+e+"_Interval_"+t+" option:selected").val()),c=timeunitlist[$j("#"+e+"_Period_"+t+" option:selected").val()],m=intervallist[$j("#"+e+"_Period_"+t+" option:selected").val()],u=moment(),h=null,b=moment().subtract(m,c+"s"),f="line",_=window[t+"_"+p+"_"+o+"_"+e];if("undefined"==typeof _||null===_)return void Draw_Chart_NoData(e,t,"No data to display");if(0==_.length)return void Draw_Chart_NoData(e,t,"No data to display");var y=_.map(function(e){return{x:e.Time,y:e.Value}}),g=[],v=[];for(let a=0;a<_.length;a++)g[_[a].Metric]||(v.push(_[a].Metric),g[_[a].Metric]=1);var x=_.filter(function(e){return e.Metric==i}).map(function(e){return{x:e.Time,y:e.Value}}),C=_.filter(function(e){return e.Metric==l}).map(function(e){return{x:e.Time,y:e.Value}}),w=_.filter(function(e){return e.Metric==n}).map(function(e){return{x:e.Time,y:e.Value}}),L=window["LineChart_"+e+"_"+t],S=getTimeFormat($j("#Time_Format option:selected").val(),"axis"),T=getTimeFormat($j("#Time_Format option:selected").val(),"tooltip");"day"==p&&(f="bar",h=moment().endOf("day").subtract(9,"hours"),b=moment().startOf("day").subtract(m-1,c+"s").subtract(12,"hours"),u=h),"daily"==o&&"day"==p&&(c="day",m=1,h=moment().endOf("day").subtract(9,"hours"),b=moment().startOf("day").subtract(12,"hours"),u=h),factor=0,"hour"==c?factor=3600000:"day"==c&&(factor=86400000),L!=null&&L.destroy();var k=document.getElementById("divLineChart_"+e+"_"+t).getContext("2d"),D={segmentShowStroke:!1,segmentStrokeColor:"#000",animationEasing:"easeOutQuart",animationSteps:100,maintainAspectRatio:!1,animateScale:!0,hover:{mode:"point"},legend:{display:!0,position:"top",reverse:!0,onClick:function(t,e){var a=e.datasetIndex,s=this.chart,r=s.getDatasetMeta(a);if(r.hidden=null===r.hidden?!s.data.datasets[a].hidden:null,"line"==ShowLines){var i="";if(!0!=r.hidden&&(i="line"),"Latency"==s.data.datasets[a].label||"Download"==s.data.datasets[a].label)for(aindex=0;3>aindex;aindex++)s.options.annotation.annotations[aindex].type=i;else if("Jitter"==s.data.datasets[a].label||"Upload"==s.data.datasets[a].label)for(aindex=3;6>aindex;aindex++)s.options.annotation.annotations[aindex].type=i;else if("Packet Loss"==s.data.datasets[a].label)for(aindex=6;9>aindex;aindex++)s.options.annotation.annotations[aindex].type=i}if("Packet Loss"==s.data.datasets[a].label){var l=!1;!0!=r.hidden&&(l=!0),s.scales["right-y-axis"].options.display=l}s.update()}},title:{display:!0,text:r},tooltips:{callbacks:{title:function(e){return"day"==p?moment(e[0].xLabel,"X").format("YYYY-MM-DD"):moment(e[0].xLabel,"X").format(T)},label:function(e,t){var r=a;return"Packet Loss"==t.datasets[e.datasetIndex].label&&(r=s),round(t.datasets[e.datasetIndex].data[e.index].y,2).toFixed(2)+" "+r}},itemSort:function(e,t){return t.datasetIndex-e.datasetIndex},mode:"point",position:"cursor",intersect:!0},scales:{xAxes:[{type:"time",gridLines:{display:!0,color:"#282828"},ticks:{min:b,max:h,display:!0},time:{parser:"X",unit:c,stepSize:1,displayFormats:S}}],yAxes:[{type:getChartScale($j("#"+e+"_Scale_"+t+" option:selected").val()),gridLines:{display:!1,color:"#282828"},scaleLabel:{display:!1,labelString:a},id:"left-y-axis",position:"left",ticks:{display:!0,beginAtZero:!0,labels:{index:["min","max"],removeEmptyLines:!0},userCallback:LogarithmicFormatter}},{type:getChartScale($j("#"+e+"_Scale_"+t+" option:selected").val()),gridLines:{display:!1,color:"#282828"},scaleLabel:{display:!1,labelString:s},id:"right-y-axis",position:"right",ticks:{display:d,beginAtZero:!0,labels:{index:["min","max"],removeEmptyLines:!0},userCallback:LogarithmicFormatter}}]},plugins:{zoom:{pan:{enabled:ChartPan,mode:"xy",rangeMin:{x:b,y:0},rangeMax:{x:u}},zoom:{enabled:!0,drag:DragZoom,mode:"xy",rangeMin:{x:b,y:0},rangeMax:{x:u},speed:.1}}},annotation:{drawTime:"afterDatasetsDraw",annotations:[{type:ShowLines,mode:"horizontal",scaleID:"left-y-axis",value:getAverage(x),borderColor:window["bordercolourlist_"+t][0],borderWidth:1,borderDash:[5,5],label:{backgroundColor:"rgba(0,0,0,0.3)",fontFamily:"sans-serif",fontSize:10,fontStyle:"bold",fontColor:"#fff",xPadding:6,yPadding:6,cornerRadius:6,position:"center",enabled:!0,xAdjust:0,yAdjust:0,content:"Avg. "+i+"="+round(getAverage(x),2).toFixed(2)+a}},{type:ShowLines,mode:"horizontal",scaleID:"left-y-axis",value:getLimit(x,"y","max",!0),borderColor:window["bordercolourlist_"+t][0],borderWidth:1,borderDash:[5,5],label:{backgroundColor:"rgba(0,0,0,0.3)",fontFamily:"sans-serif",fontSize:10,fontStyle:"bold",fontColor:"#fff",xPadding:6,yPadding:6,cornerRadius:6,position:"right",enabled:!0,xAdjust:15,yAdjust:0,content:"Max. "+i+"="+round(getLimit(x,"y","max",!0),2).toFixed(2)+a}},{type:ShowLines,mode:"horizontal",scaleID:"left-y-axis",value:getLimit(x,"y","min",!0),borderColor:window["bordercolourlist_"+t][0],borderWidth:1,borderDash:[5,5],label:{backgroundColor:"rgba(0,0,0,0.3)",fontFamily:"sans-serif",fontSize:10,fontStyle:"bold",fontColor:"#fff",xPadding:6,yPadding:6,cornerRadius:6,position:"left",enabled:!0,xAdjust:15,yAdjust:0,content:"Min. "+i+"="+round(getLimit(x,"y","min",!0),2).toFixed(2)+a}},{type:ShowLines,mode:"horizontal",scaleID:"left-y-axis",value:getAverage(C),borderColor:window["bordercolourlist_"+t][1],borderWidth:1,borderDash:[5,5],label:{backgroundColor:"rgba(0,0,0,0.3)",fontFamily:"sans-serif",fontSize:10,fontStyle:"bold",fontColor:"#fff",xPadding:6,yPadding:6,cornerRadius:6,position:"center",enabled:!0,xAdjust:0,yAdjust:0,content:"Avg. "+l+"="+round(getAverage(C),2).toFixed(2)+a}},{type:ShowLines,mode:"horizontal",scaleID:"left-y-axis",value:getLimit(C,"y","max",!0),borderColor:window["bordercolourlist_"+t][1],borderWidth:1,borderDash:[5,5],label:{backgroundColor:"rgba(0,0,0,0.3)",fontFamily:"sans-serif",fontSize:10,fontStyle:"bold",fontColor:"#fff",xPadding:6,yPadding:6,cornerRadius:6,position:"right",enabled:!0,xAdjust:15,yAdjust:0,content:"Max. "+l+"="+round(getLimit(C,"y","max",!0),2).toFixed(2)+a}},{type:ShowLines,mode:"horizontal",scaleID:"left-y-axis",value:getLimit(C,"y","min",!0),borderColor:window["bordercolourlist_"+t][1],borderWidth:1,borderDash:[5,5],label:{backgroundColor:"rgba(0,0,0,0.3)",fontFamily:"sans-serif",fontSize:10,fontStyle:"bold",fontColor:"#fff",xPadding:6,yPadding:6,cornerRadius:6,position:"left",enabled:!0,xAdjust:15,yAdjust:0,content:"Min. "+l+"="+round(getLimit(C,"y","min",!0),2).toFixed(2)+a}},{type:ShowLines,mode:"horizontal",scaleID:"right-y-axis",value:getAverage(w),borderColor:window["bordercolourlist_"+t][2],borderWidth:1,borderDash:[5,5],label:{backgroundColor:"rgba(0,0,0,0.3)",fontFamily:"sans-serif",fontSize:10,fontStyle:"bold",fontColor:"#fff",xPadding:6,yPadding:6,cornerRadius:6,position:"center",enabled:!0,xAdjust:0,yAdjust:0,content:"Avg. "+n+"="+round(getAverage(w),2).toFixed(2)+s}},{type:ShowLines,mode:"horizontal",scaleID:"right-y-axis",value:getLimit(w,"y","max",!0),borderColor:window["bordercolourlist_"+t][2],borderWidth:1,borderDash:[5,5],label:{backgroundColor:"rgba(0,0,0,0.3)",fontFamily:"sans-serif",fontSize:10,fontStyle:"bold",fontColor:"#fff",xPadding:6,yPadding:6,cornerRadius:6,position:"right",enabled:!0,xAdjust:15,yAdjust:0,content:"Max. "+n+"="+round(getLimit(w,"y","max",!0),2).toFixed(2)+s}},{type:ShowLines,mode:"horizontal",scaleID:"right-y-axis",value:getLimit(w,"y","min",!0),borderColor:window["bordercolourlist_"+t][2],borderWidth:1,borderDash:[5,5],label:{backgroundColor:"rgba(0,0,0,0.3)",fontFamily:"sans-serif",fontSize:10,fontStyle:"bold",fontColor:"#fff",xPadding:6,yPadding:6,cornerRadius:6,position:"left",enabled:!0,xAdjust:15,yAdjust:0,content:"Min. "+n+"="+round(getLimit(w,"y","min",!0),2).toFixed(2)+s}}]}},I={datasets:getDataSets(t,_,v)};L=new Chart(k,{type:f,options:D,data:I}),window["LineChart_"+e+"_"+t]=L}function LogarithmicFormatter(e,t,a){var s=this.options.scaleLabel.labelString;if("logarithmic"!=this.type)return isNaN(e)?e+" "+s:round(e,2).toFixed(2)+" "+s;var r=this.options.ticks.labels||{},i=r.index||["min","max"],l=r.significand||[1,2,5],n=e/Math.pow(10,Math.floor(Chart.helpers.log10(e))),d=!0===r.removeEmptyLines?void 0:"",o="";return 0===t?o="min":t==a.length-1&&(o="max"),"all"===r||-1!==l.indexOf(n)||-1!==i.indexOf(t)||-1!==i.indexOf(o)?0===e?"0 "+s:isNaN(e)?e+" "+s:round(e,2).toFixed(2)+" "+s:d}function getDataSets(e,t,a){var s=[];colourname="#fc8500";for(var r=0;r<a.length;r++){var l=t.filter(function(e){return e.Metric==a[r]}).map(function(e){return{x:e.Time,y:e.Value}}),n="left-y-axis";"PktLoss"==a[r]&&(n="right-y-axis"),s.push({label:a[r].replace("PktLoss","Packet Loss"),data:l,yAxisID:n,borderWidth:1,pointRadius:1,lineTension:0,fill:ShowFill,backgroundColor:window["backgroundcolourlist_"+e][r],borderColor:window["bordercolourlist_"+e][r]})}return s.reverse(),s}function getLimit(e,t,a,s){var r,i=0;return r="x"==t?e.map(function(e){return e.x}):e.map(function(e){return e.y}),i="max"==a?Math.max.apply(Math,r):Math.min.apply(Math,r),"max"==a&&0==i&&!1==s&&(i=1),i}function getAverage(e){for(var t=0,a=0;a<e.length;a++)t+=1*e[a].y;var s=t/e.length;return s}function round(e,t){return+(Math.round(e+"e"+t)+"e-"+t)}function ToggleLines(){var e=interfacelist.split(",");""==ShowLines?(ShowLines="line",SetCookie("ShowLines","line")):(ShowLines="",SetCookie("ShowLines",""));for(var t=0;t<e.length;t++)for(var a,s=0;s<typelist.length;s++)if(a=window["LineChart_"+e[t]+"_"+typelist[s]],"undefined"!=typeof a&&null!==a){var r=6;"Quality"==typelist[s]&&(r=9);for(var l=0;l<r;l++)a.options.annotation.annotations[l].type=ShowLines;a.update()}}function ToggleFill(){var e=interfacelist.split(",");"origin"==ShowFill?(ShowFill="false",SetCookie("ShowFill","false")):(ShowFill="origin",SetCookie("ShowFill","origin"));for(var t=0;t<e.length;t++)for(var a,s=0;s<typelist.length;s++)(a=window["LineChart_"+e[t]+"_"+typelist[s]],"undefined"!=typeof a&&null!==a)&&(a.data.datasets[0].fill=ShowFill,a.data.datasets[1].fill=ShowFill,"Quality"==typelist[s]&&(a.data.datasets[2].fill=ShowFill),a.update())}function RedrawAllCharts(){for(var e=interfacelist.split(","),t=0;t<chartlist.length;t++)for(var a=0;a<e.length;a++){Draw_Chart_NoData(e[a],"Combined","Data loading..."),Draw_Chart_NoData(e[a],"Quality","Data loading...");for(var s=0;s<dataintervallist.length;s++)d3.csv("/ext/spdmerlin/csv/Combined_"+dataintervallist[s]+"_"+chartlist[t]+"_"+e[a]+".htm").then(SetGlobalDataset.bind(null,"Combined_"+dataintervallist[s]+"_"+chartlist[t]+"_"+e[a])),d3.csv("/ext/spdmerlin/csv/Quality_"+dataintervallist[s]+"_"+chartlist[t]+"_"+e[a]+".htm").then(SetGlobalDataset.bind(null,"Quality_"+dataintervallist[s]+"_"+chartlist[t]+"_"+e[a]))}}function SetGlobalDataset(e,t){if(window[e]=t,currentNoCharts++,currentNoCharts==maxNoCharts)for(var a=interfacelist.split(","),s=0;s<a.length;s++)$j("#"+a[s]+"_Interval_Combined").val(GetCookie(a[s]+"_Interval_Combined","number")),$j("#"+a[s]+"_Interval_Quality").val(GetCookie(a[s]+"_Interval_Quality","number")),changePeriod(document.getElementById(a[s]+"_Interval_Combined")),changePeriod(document.getElementById(a[s]+"_Interval_Quality")),$j("#"+a[s]+"_Period_Combined").val(GetCookie(a[s]+"_Period_Combined","number")),$j("#"+a[s]+"_Period_Quality").val(GetCookie(a[s]+"_Period_Quality","number")),$j("#"+a[s]+"_Scale_Combined").val(GetCookie(a[s]+"_Scale_Combined","number")),$j("#"+a[s]+"_Scale_Quality").val(GetCookie(a[s]+"_Scale_Quality","number")),Draw_Chart(a[s],"Combined"),Draw_Chart(a[s],"Quality")}function getTimeFormat(e,t){var a;return"axis"==t?0==e?a={millisecond:"HH:mm:ss.SSS",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm"}:1==e&&(a={millisecond:"h:mm:ss.SSS A",second:"h:mm:ss A",minute:"h:mm A",hour:"h A"}):"tooltip"==t&&(0==e?a="YYYY-MM-DD HH:mm:ss":1==e&&(a="YYYY-MM-DD h:mm:ss A")),a}function GetCookie(e,t){if(null!=cookie.get("spd_"+e))return cookie.get("spd_"+e);return"string"==t?"":"number"==t?0:void 0}function SetCookie(e,t){cookie.set("spd_"+e,t,3650)}$j.fn.serializeObject=function(){var e=custom_settings,t=this.serializeArray();$j.each(t,function(){void 0!==e[this.name]&&-1!=this.name.indexOf("spdmerlin")&&-1==this.name.indexOf("version")&&-1==this.name.indexOf("spdmerlin_iface_enabled")&&-1==this.name.indexOf("spdmerlin_usepreferred")&&-1==this.name.indexOf("schdays")&&-1==this.name.indexOf("spdmerlin_preferredserver")?(!e[this.name].push&&(e[this.name]=[e[this.name]]),e[this.name].push(this.value||"")):-1!=this.name.indexOf("spdmerlin")&&-1==this.name.indexOf("version")&&-1==this.name.indexOf("spdmerlin_iface_enabled")&&-1==this.name.indexOf("spdmerlin_usepreferred")&&-1==this.name.indexOf("schdays")&&-1==this.name.indexOf("spdmerlin_preferredserver")&&(e[this.name]=this.value||"")}),$j.each(t,function(){void 0!==e[this.name]&&-1!=this.name.indexOf("spdmerlin_preferredserver")?(!e[this.name].push&&(e[this.name]=[e[this.name]]),e[this.name].push(this.value||"")):-1!=this.name.indexOf("spdmerlin_preferredserver")&&(e[this.name]=this.value||"")});var a=[];$j.each($j("input[name=\"spdmerlin_schdays\"]:checked"),function(){a.push($j(this).val())});var s=a.join(",");"Mon,Tues,Wed,Thurs,Fri,Sat,Sun"==s&&(s="*"),e.spdmerlin_schdays=s,$j.each($j("input[name^=\"spdmerlin_usepreferred\"]"),function(){e[this.id]=this.checked.toString()});var r=[];$j.each($j("input[name=\"spdmerlin_iface_enabled\"]:checked"),function(){r.push(this.value)});var i=r.join(",");return e.spdmerlin_ifaces_enabled=i,e};function SetCurrentPage(){document.form.next_page.value=window.location.pathname.substring(1),document.form.current_page.value=window.location.pathname.substring(1)}function initial(){SetCurrentPage(),LoadCustomSettings(),show_menu(),$j("#Time_Format").val(GetCookie("Time_Format","number")),ScriptUpdateLayout(),get_spdtestbinary_file(),get_statstitle_file(),get_interfaces_file()}function ScriptUpdateLayout(){var e=GetVersionNumber("local"),t=GetVersionNumber("server");$j("#spdmerlin_version_local").text(e),e!=t&&"N/A"!=t&&($j("#spdmerlin_version_server").text("Updated version available: "+t),showhide("btnChkUpdate",!1),showhide("spdmerlin_version_server",!0),showhide("btnDoUpdate",!0))}function reload(){location.reload(!0)}function getYAxisMax(e){if(-1!=e.indexOf("Quality"))return 100}function getChartInterval(e){var t="raw";return 0==e?t="raw":1==e?t="hour":2==e&&(t="day"),t}function changePeriod(t){var e=1*t.value,a=t.id.substring(0,t.id.indexOf("_")),s=t.id.substring(t.id.lastIndexOf("_")+1);2==e?$j("select[id=\""+a+"_Period_"+s+"\"] option:contains(24)").text("Today"):$j("select[id=\""+a+"_Period_"+s+"\"] option:contains(\"Today\")").text("Last 24 hours")}function getChartPeriod(e){var t="daily";return 0==e?t="daily":1==e?t="weekly":2==e&&(t="monthly"),t}function getChartScale(e){var t="";return 0==e?t="linear":1==e&&(t="logarithmic"),t}function ResetZoom(){for(var e=interfacelist.split(","),t=0;t<e.length;t++)for(var a,s=0;s<typelist.length;s++)(a=window["LineChart_"+e[t]+"_"+typelist[s]],"undefined"!=typeof a&&null!==a)&&a.resetZoom()}function ToggleDragZoom(e){var t=!0,a=!1,s="";-1==e.value.indexOf("On")?(t=!0,a=!1,DragZoom=!0,ChartPan=!1,s="Drag Zoom On"):(t=!1,a=!0,DragZoom=!1,ChartPan=!0,s="Drag Zoom Off");for(var r=interfacelist.split(","),l=0;l<r.length;l++){for(var n,d=0;d<typelist.length;d++)(n=window["LineChart_"+r[l]+"_"+typelist[d]],"undefined"!=typeof n&&null!==n)&&(n.options.plugins.zoom.zoom.drag=t,n.options.plugins.zoom.pan.enabled=a,n.update());e.value=s}}function ExportCSV(){return location.href="/ext/spdmerlin/csv/spdmerlindata.zip",0}function update_status(){$j.ajax({url:"/ext/spdmerlin/detect_update.js",dataType:"script",error:function(){setTimeout(update_status,1e3)},success:function(){"InProgress"==updatestatus?setTimeout(update_status,1e3):(document.getElementById("imgChkUpdate").style.display="none",showhide("spdmerlin_version_server",!0),"None"==updatestatus?($j("#spdmerlin_version_server").text("No update available"),showhide("btnChkUpdate",!0),showhide("btnDoUpdate",!1)):($j("#spdmerlin_version_server").text("Updated version available: "+updatestatus),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0)))}})}function CheckUpdate(){showhide("btnChkUpdate",!1),document.formScriptActions.action_script.value="start_spdmerlincheckupdate",document.formScriptActions.submit(),document.getElementById("imgChkUpdate").style.display="",setTimeout(update_status,2e3)}function DoUpdate(){document.form.action_script.value="start_spdmerlindoupdate",document.form.action_wait.value=10,showLoading(),document.form.submit()}function getAllIndexes(e,t){for(var a=[],s=0;s<e.length;s++)e[s].id==t&&a.push(s);return a}function get_spdtestservers_file(e){$j.ajax({url:"/ext/spdmerlin/spdmerlin_serverlist_"+e.toUpperCase()+".htm?cachebuster="+new Date().getTime(),dataType:"text",error:function(){setTimeout(get_spdtestservers_file,1e3,e)},success:function(t){var a=[];$j.each(t.split("\n").filter(Boolean),function(e,t){var s={};s.id=t.split("|")[0],s.name=t.split("|")[1],a.push(s)}),$j("#spdmerlin_preferredserver_"+e).prop("disabled",!1),$j("#spdmerlin_preferredserver_"+e).removeClass("disabled");let s=$j("#spdmerlin_preferredserver_"+e);s.empty(),$j.each(a,function(e,t){s.append($j("<option></option>").attr("value",t.id+"|"+t.name).text(t.id+"|"+t.name))}),s.prop("selectedIndex",0),$j("#spdmerlin_preferredserver_"+e)[0].style.display="",showhide("imgServerList_"+e,!1)}})}function get_manualspdtestservers_file(){$j.ajax({url:"/ext/spdmerlin/spdmerlin_manual_serverlist.htm?cachebuster="+new Date().getTime(),dataType:"text",error:function(){setTimeout(get_manualspdtestservers_file,2e3)},success:function(e){var t=[];if($j.each(e.split("\n").filter(Boolean),function(e,a){var s={};s.id=a.split("|")[0],s.name=a.split("|")[1],t.push(s)}),"All"==document.form.spdtest_enabled.value){for(var a=getAllIndexes(t,"-----"),s=0;s<a.length;s++){let e=$j($j("select[name^=spdtest_serverprefselect]")[s]);e.empty();var r=[];r=0==s?t.slice(0,a[s]):s==a.length-1?t.slice(a[s-1]+1,t.length-1):t.slice(a[s-1]+1,a[s]),$j.each(r,function(t,a){e.append($j("<option></option>").attr("value",a.id+"|"+a.name).text(a.id+"|"+a.name))}),e.prop("selectedIndex",0)}$j.each($j("select[name^=spdtest_serverprefselect]"),function(){this.style.display="inline-block"}),$j.each($j("span[id^=spdtest_serverprefselectspan]"),function(){this.style.display="inline-block"}),showhide("imgManualServerList",!1)}else{let e=$j("select[name=spdtest_serverprefselect]");e.empty(),$j.each(t,function(t,a){e.append($j("<option></option>").attr("value",a.id+"|"+a.name).text(a.id+"|"+a.name))}),e.prop("selectedIndex",0),showhide("spdtest_serverprefselect",!0),showhide("imgManualServerList",!1)}for(var s=0;s<interfacescomplete.length;s++)!1==interfacesdisabled.includes(interfacescomplete[s])&&($j("#spdtest_enabled_"+interfacescomplete[s].toLowerCase()).prop("disabled",!1),$j("#spdtest_enabled_"+interfacescomplete[s].toLowerCase()).removeClass("disabled"));$j.each($j("input[name=spdtest_serverpref]"),function(){$j(this).prop("disabled",!1),$j(this).removeClass("disabled")})}})}function get_spdtestresult_file(){$j.ajax({url:"/ext/spdmerlin/spd-result.htm",dataType:"text",error:function(){setTimeout(get_spdtestresult_file,1e3)},success:function(e){var t=e.trim().split("\n");e=t.join("\n"),$j("#spdtest_output").html(e),PostSpeedTest()}})}function get_spdtestbinary_file(){$j.ajax({url:"/ext/spdmerlin/spd-binary.htm",dataType:"text",error:function(){setTimeout(get_spdtestbinary_file,1e3)},success:function(e){speedtestbinary="/usr/sbin/ookla"==e?"built-in":"external"}})}function get_spdtest_file(){$j.ajax({url:"/ext/spdmerlin/spd-stats.htm",dataType:"text",error:function(){},success:function(e){var t=e.trim().split("\n"),a=t.slice(-1)[0].split("%").filter(Boolean);"built-in"==speedtestbinary&&(t.unshift(""),t.unshift("Speedtest by Ookla")),5<t.length?$j("#spdtest_output").html(t[0]+"\n"+t[1]+"\n"+t[2]+"\n"+t[3]+"\n"+t[4]+"\n"+a[a.length-1]+"%"):$j("#spdtest_output").html("")}})}function update_spdtest(){$j.ajax({url:"/ext/spdmerlin/detect_spdtest.js",dataType:"script",error:function(){},success:function(){-1==spdteststatus.indexOf("InProgress")?"GenerateCSV"==spdteststatus?document.getElementById("spdtest_text").innerHTML="Retrieving data for charts...":"Done"==spdteststatus?(clearInterval(myinterval),!1==intervalclear&&(intervalclear=!0,document.getElementById("spdtest_text").innerHTML="Refreshing tables and charts...",get_spdtestresult_file())):"LOCKED"==spdteststatus?(clearInterval(myinterval),showhide("imgSpdTest",!1),document.getElementById("spdtest_text").innerHTML="Scheduled speedtest already running!",showhide("spdtest_text",!0),document.getElementById("spdtest_output").parentElement.parentElement.style.display="none",showhide("btnRunSpeedtest",!0)):"NoLicense"==spdteststatus?(clearInterval(myinterval),showhide("imgSpdTest",!1),document.getElementById("spdtest_text").innerHTML="Please accept Ookla license at command line via spdmerlin",showhide("spdtest_text",!0),document.getElementById("spdtest_output").parentElement.parentElement.style.display="none",showhide("btnRunSpeedtest",!0)):"Error"==spdteststatus?(clearInterval(myinterval),showhide("imgSpdTest",!1),document.getElementById("spdtest_text").innerHTML="Error running speedtest",showhide("spdtest_text",!0),document.getElementById("spdtest_output").parentElement.parentElement.style.display="none",showhide("btnRunSpeedtest",!0)):"NoSwap"==spdteststatus&&(clearInterval(myinterval),showhide("imgSpdTest",!1),document.getElementById("spdtest_text").innerHTML="No Swap file configured/detected",showhide("spdtest_text",!0),document.getElementById("spdtest_output").parentElement.parentElement.style.display="none",showhide("btnRunSpeedtest",!0)):-1!=spdteststatus.indexOf("_")&&(showhide("imgSpdTest",!0),showhide("spdtest_text",!0),document.getElementById("spdtest_text").innerHTML="Speedtest in progress for "+spdteststatus.substring(spdteststatus.indexOf("_")+1),document.getElementById("spdtest_output").parentElement.parentElement.style.display="",get_spdtest_file())}})}function PostSpeedTest(){$j("#table_allinterfaces").empty(),$j("#rowautomaticspdtest").empty(),$j("#rowautospdprefserver").empty(),$j("#rowautospdprefserverselect").empty(),$j("#rowmanualspdtest").empty(),$j("#table_allinterfaces").remove(),$j("#rowautomaticspdtest").remove(),$j("#rowautospdprefserver").remove(),$j("#rowautospdprefserverselect").remove(),$j("#rowmanualspdtest").remove(),currentNoCharts=0,$j("#Time_Format").val(GetCookie("Time_Format","number")),get_statstitle_file(),setTimeout(get_interfaces_file,3e3)}function RunSpeedtest(){showhide("btnRunSpeedtest",!1),$j("#spdtest_output").html("");var e="";"onetime"==document.form.spdtest_serverpref.value&&("All"==document.form.spdtest_enabled.value?($j.each($j("select[name^=spdtest_serverprefselect]"),function(){e+=this.value.substring(0,this.value.indexOf("|"))+"+"}),e=e.slice(0,-1)):e=document.form.spdtest_serverprefselect.value.substring(0,document.form.spdtest_serverprefselect.value.indexOf("|"))),document.formScriptActions.action_script.value="start_spdmerlinspdtest_"+document.form.spdtest_serverpref.value+"_"+document.form.spdtest_enabled.value+"_"+e.replace(/ /g,"%"),document.formScriptActions.submit(),showhide("imgSpdTest",!0),showhide("spdtest_text",!1),setTimeout(StartSpeedTestInterval,5e3)}var myinterval,intervalclear=!1;function StartSpeedTestInterval(){intervalclear=!1,myinterval=setInterval(update_spdtest,1e3)}function SaveConfig(){if(Validate_All()){$j("[name*=spdmerlin_]").prop("disabled",!1);for(var e=0;e<interfacescomplete.length;e++)$j("#spdmerlin_iface_enabled_"+interfacescomplete[e].toLowerCase()).prop("disabled",!1),$j("#spdmerlin_iface_enabled_"+interfacescomplete[e].toLowerCase()).removeClass("disabled"),$j("#spdmerlin_usepreferred_"+interfacescomplete[e].toLowerCase()).prop("disabled",!1),$j("#spdmerlin_usepreferred_"+interfacescomplete[e].toLowerCase()).removeClass("disabled"),$j("#changepref_"+interfacescomplete[e].toLowerCase()).prop("disabled",!1),$j("#changepref_"+interfacescomplete[e].toLowerCase()).removeClass("disabled");if("EveryX"==document.form.schedulemode.value)if("hours"==document.form.everyxselect.value){var t=1*document.form.everyxvalue.value;document.form.spdmerlin_schmins.value=0,document.form.spdmerlin_schhours.value=24==t?0:"*/"+t}else if("minutes"==document.form.everyxselect.value){document.form.spdmerlin_schhours.value="*";var t=1*document.form.everyxvalue.value;document.form.spdmerlin_schmins.value="*/"+t}document.getElementById("amng_custom").value=JSON.stringify($j("form").serializeObject()),document.form.action_script.value="start_spdmerlinconfig",document.form.action_wait.value=10,showLoading(),document.form.submit()}else return!1}function GetVersionNumber(e){var t;return"local"==e?t=custom_settings.spdmerlin_version_local:"server"==e&&(t=custom_settings.spdmerlin_version_server),"undefined"==typeof t||null==t?"N/A":t}function get_autobw_file(){$j.ajax({url:"/ext/spdmerlin/autobwoutfile.htm",dataType:"text",error:function(){},success:function(e){document.getElementById("AutoBWOutput").innerHTML=e}})}function get_conf_file(){$j.ajax({url:"/ext/spdmerlin/config.htm",dataType:"text",error:function(){setTimeout(get_conf_file,1e3)},success:function(data){var configdata=data.split("\n");configdata=configdata.filter(Boolean);for(var i=0;i<configdata.length;i++){let settingname=configdata[i].split("=")[0].toLowerCase(),settingvalue=configdata[i].split("=")[1].replace(/(\r\n|\n|\r)/gm,"");if(!(-1!=configdata[i].indexOf("SCHDAYS")))-1==configdata[i].indexOf("USEPREFERRED")?-1==configdata[i].indexOf("PREFERREDSERVER")?-1==configdata[i].indexOf("PREFERRED")&&(eval("document.form.spdmerlin_"+settingname).value=settingvalue):$j("#span_spdmerlin_"+settingname).html(configdata[i].split("=")[0].split("_")[1]+" - "+settingvalue):"true"==settingvalue?eval("document.form.spdmerlin_"+settingname).checked=!0:"false"==settingvalue&&(eval("document.form.spdmerlin_"+settingname).checked=!1);else if("*"==settingvalue)for(var i2=0;i2<daysofweek.length;i2++)$j("#spdmerlin_"+daysofweek[i2].toLowerCase()).prop("checked",!0);else for(var schdayarray=settingvalue.split(","),i2=0;i2<schdayarray.length;i2++)$j("#spdmerlin_"+schdayarray[i2].toLowerCase()).prop("checked",!0);-1!=configdata[i].indexOf("AUTOMATED")&&AutomaticInterfaceEnableDisable($j("#spdmerlin_auto_"+document.form.spdmerlin_automated.value)[0]),-1!=configdata[i].indexOf("AUTOBW")&&AutoBWEnableDisable($j("#spdmerlin_autobw_"+document.form.spdmerlin_autobw_enabled.value)[0])}-1!=$j("[name=spdmerlin_schhours]").val().indexOf("/")&&0==$j("[name=spdmerlin_schmins]").val()?(document.form.schedulemode.value="EveryX",document.form.everyxselect.value="hours",document.form.everyxvalue.value=$j("[name=spdmerlin_schhours]").val().split("/")[1]):-1!=$j("[name=spdmerlin_schmins]").val().indexOf("/")&&"*"==$j("[name=spdmerlin_schhours]").val()?(document.form.schedulemode.value="EveryX",document.form.everyxselect.value="minutes",document.form.everyxvalue.value=$j("[name=spdmerlin_schmins]").val().split("/")[1]):document.form.schedulemode.value="Custom",ScheduleModeToggle($j("#schmode_"+$j("[name=schedulemode]:checked").val().toLowerCase())[0])}}),get_autobw_file()}function get_interfaces_file(){$j.ajax({url:"/ext/spdmerlin/interfaces_user.htm",dataType:"text",error:function(){setTimeout(get_interfaces_file,1e3)},success:function(e){showhide("spdtest_text",!1),showhide("imgSpdTest",!1),showhide("btnRunSpeedtest",!0);var t=e.split("\n");t=t.filter(Boolean),interfacelist="",interfacescomplete=[],interfacesdisabled=[];var a="<div style=\"line-height:10px;\"> </div>";a+="<table width=\"100%\" border=\"1\" align=\"center\" cellpadding=\"4\" cellspacing=\"0\" bordercolor=\"#6b8fa3\" class=\"FormTable\" id=\"table_allinterfaces\">",a+="<thead class=\"collapsible-jquery\" id=\"thead_allinterfaces\">",a+="<tr><td>Interfaces (click to expand/collapse)</td></tr>",a+="</thead>",a+="<tr><td align=\"center\" style=\"padding: 0px;\">";var s="<tr id=\"rowautomaticspdtest\"><td class=\"settingname\">Interfaces to use for automatic speedtests</th><td class=\"settingvalue\">",r="<tr id=\"rowautospdprefserver\"><td class=\"settingname\">Interfaces that use a preferred server</th><td class=\"settingvalue\">",l="<tr id=\"rowautospdprefserverselect\"><td class=\"settingname\">Preferred servers for interfaces</th><td class=\"settingvalue\">",n="<tr id=\"rowmanualspdtest\"><td class=\"settingname\">Interfaces to use for manual speedtest</th><td class=\"settingvalue\">";n+="<input type=\"radio\" name=\"spdtest_enabled\" id=\"spdtest_enabled_all\" onchange=\"Change_SpdTestInterface(this)\" class=\"input\" settingvalueradio\" value=\"All\" checked>",n+="<label for=\"spdtest_enabled_all\">All</label>";for(var d,o=t.length,p=0;p<o;p++){if(d="",-1!=t[p].indexOf("#")){d=t[p].substring(0,t[p].indexOf("#")).trim(),interfacescomplete.push(d);var c="",m=d.toUpperCase(),u="Change?";-1!=t[p].indexOf("interface not up")&&(interfacesdisabled.push(d),c="disabled",m="<a class=\"hintstyle\" href=\"javascript:void(0);\" onclick=\"SettingHint(1);\">"+d.toUpperCase()+"</a>",u="<a class=\"hintstyle\" href=\"javascript:void(0);\" onclick=\"SettingHint(1);\">Change?</a>"),s+="<input type=\"checkbox\" name=\"spdmerlin_iface_enabled\" id=\"spdmerlin_iface_enabled_"+d.toLowerCase()+"\" class=\"input "+c+" settingvalue\" value=\""+d.toUpperCase()+"\" "+c+">",s+="<label for=\"spdmerlin_iface_enabled_"+d.toLowerCase()+"\">"+m+"</label>",r+="<input type=\"checkbox\" name=\"spdmerlin_usepreferred_"+d.toLowerCase()+"\" id=\"spdmerlin_usepreferred_"+d.toLowerCase()+"\" class=\"input "+c+" settingvalue\" value=\""+d.toUpperCase()+"\" "+c+">",r+="<label for=\"spdmerlin_usepreferred_"+d.toLowerCase()+"\">"+m+"</label>",l+="<span style=\"margin-left:4px;vertical-align:top;max-width:465px;display:inline-block;\" id=\"span_spdmerlin_preferredserver_"+d.toLowerCase()+"\">"+d.toUpperCase()+":</span><br />",l+="<input type=\"checkbox\" name=\"changepref_"+d.toLowerCase()+"\" id=\"changepref_"+d.toLowerCase()+"\" class=\"input settingvalue "+c+"\" "+c+" onchange=\"Toggle_ChangePrefServer(this)\">",l+="<label for=\"changepref_"+d.toLowerCase()+"\">"+u+"</label>",l+="<img id=\"imgServerList_"+d.toLowerCase()+"\" style=\"display:none;vertical-align:middle;\" src=\"images/InternetScan.gif\"/>",l+="<select class=\"disabled\" name=\"spdmerlin_preferredserver_"+d.toLowerCase()+"\" id=\"spdmerlin_preferredserver_"+d.toLowerCase()+"\" style=\"min-width:100px;max-width:400px;display:none;vertical-align:top;\" disabled></select><br />",n+="<input autocomplete=\"off\" autocapitalize=\"off\" type=\"radio\" name=\"spdtest_enabled\" id=\"spdtest_enabled_"+d.toLowerCase()+"\" onchange=\"Change_SpdTestInterface(this)\" class=\"input "+c+" settingvalueradio\" value=\""+d.toUpperCase()+"\" "+c+">",n+="<label for=\"spdtest_enabled_"+d.toLowerCase()+"\">"+m+"</label>"}else d=t[p].trim(),interfacescomplete.push(d),s+="<input type=\"checkbox\" name=\"spdmerlin_iface_enabled\" id=\"spdmerlin_iface_enabled_"+d.toLowerCase()+"\" class=\"input settingvalue\" value=\""+d.toUpperCase()+"\" checked>",s+="<label for=\"spdmerlin_iface_enabled_"+d.toLowerCase()+"\">"+d.toUpperCase()+"</label>",r+="<input type=\"checkbox\" name=\"spdmerlin_usepreferred_"+d.toLowerCase()+"\" id=\"spdmerlin_usepreferred_"+d.toLowerCase()+"\" class=\"input settingvalue\" value=\""+d.toUpperCase()+"\" checked>",r+="<label for=\"spdmerlin_usepreferred_"+d.toLowerCase()+"\">"+d.toUpperCase()+"</label>",l+="<span style=\"margin-left:4px;vertical-align:top;max-width:465px;display:inline-block;\" id=\"span_spdmerlin_preferredserver_"+d.toLowerCase()+"\">"+d.toUpperCase()+":</span><br />",l+="<input type=\"checkbox\" name=\"changepref_"+d.toLowerCase()+"\" id=\"changepref_"+d.toLowerCase()+"\" class=\"input settingvalue\" onchange=\"Toggle_ChangePrefServer(this)\">",l+="<label for=\"changepref_"+d.toLowerCase()+"\">Change?</label>",l+="<img id=\"imgServerList_"+d.toLowerCase()+"\" style=\"display:none;vertical-align:middle;\" src=\"images/InternetScan.gif\"/>",l+="<select class=\"disabled\" name=\"spdmerlin_preferredserver_"+d.toLowerCase()+"\" id=\"spdmerlin_preferredserver_"+d.toLowerCase()+"\" style=\"min-width:100px;max-width:400px;display:none;vertical-align:top;\" disabled></select><br />",n+="<input type=\"radio\" name=\"spdtest_enabled\" id=\"spdtest_enabled_"+d.toLowerCase()+"\" onchange=\"Change_SpdTestInterface(this)\" class=\"input settingvalueradio\" value=\""+d.toUpperCase()+"\">",n+="<label for=\"spdtest_enabled_"+d.toLowerCase()+"\">"+d.toUpperCase()+"</label>";a+=BuildInterfaceTable(d),interfacelist+=d+","}a+="</td></tr></table>",s+="</td></tr>",r+="</td></tr>",l+="</td></tr>",n+="</td></tr>",$j("#rowautomatedtests").after(l),$j("#rowautomatedtests").after(r),$j("#rowautomatedtests").after(s),$j("#thead_manualspeedtests").after(n),GenerateManualSpdTestServerPrefSelect(),document.form.spdtest_serverpref.value="auto",","==interfacelist.charAt(interfacelist.length-1)&&(interfacelist=interfacelist.slice(0,-1)),$j("#table_buttons2").after(a),maxNoCharts=2*(3*(3*interfacelist.split(",").length)),RedrawAllCharts(),AddEventHandlers();for(var h=interfacelist.split(","),p=0;p<h.length;p++)$j("#sortTable"+h[p]).empty(),$j("#sortTable"+h[p]).append(BuildLastXTableNoData(h[p])),get_lastx_file(h[p]);get_conf_file()}})}function get_statstitle_file(){$j.ajax({url:"/ext/spdmerlin/spdtitletext.js",dataType:"script",error:function(){setTimeout(get_statstitle_file,1e3)},success:function(){SetSPDStatsTitle()}})}function get_lastx_file(e){$j.ajax({url:"/ext/spdmerlin/lastx_"+e+".htm",dataType:"text",error:function(){setTimeout(get_lastx_file,1e3,e)},success:function(t){ParseLastXData(e,t)}})}function ParseLastXData(name,data){var arraysortlines=data.split("\n");arraysortlines=arraysortlines.filter(Boolean),window["arraysortlistlines"+name]=[];for(var i=0;i<arraysortlines.length;i++)try{var resultfields=arraysortlines[i].split(","),parsedsortline={};parsedsortline.Time=moment.unix(resultfields[0].trim()).format("YYYY-MM-DD HH:mm:ss"),parsedsortline.Download=resultfields[1].trim(),parsedsortline.Upload=resultfields[2].trim(),parsedsortline.Latency=resultfields[3].trim(),parsedsortline.Jitter=resultfields[4].trim(),parsedsortline.PacketLoss=resultfields[5].trim(),parsedsortline.DownloadData=resultfields[6].trim(),parsedsortline.UploadData=resultfields[7].trim(),parsedsortline.URL=resultfields[8].trim(),parsedsortline.ServerID=resultfields[9].trim(),parsedsortline.ServerName=resultfields[10].trim(),window["arraysortlistlines"+name].push(parsedsortline)}catch{}SortTable("sortTable"+name,"arraysortlistlines"+name,eval("sortname"+name)+" "+eval("sortdir"+name).replace("desc","\u2191").replace("asc","\u2193").trim(),"sortname"+name,"sortdir"+name)}function SortTable(tableid,arrayid,sorttext,sortname,sortdir){window[sortname]=sorttext.replace("\u2191","").replace("\u2193","").trim();var sorttype="number",sortfield=window[sortname];switch(window[sortname]){case"Time":sorttype="date";break;case"ResultURL":case"ServerName":sorttype="string";}"string"==sorttype?-1==sorttext.indexOf("\u2193")&&-1==sorttext.indexOf("\u2191")?(eval(arrayid+" = "+arrayid+".sort((a,b) => (a."+sortfield+".toLowerCase() > b."+sortfield+".toLowerCase()) ? 1 : ((b."+sortfield+".toLowerCase() > a."+sortfield+".toLowerCase()) ? -1 : 0));"),window[sortdir]="asc"):-1==sorttext.indexOf("\u2193")?(eval(arrayid+" = "+arrayid+".sort((a,b) => (a."+sortfield+".toLowerCase() < b."+sortfield+".toLowerCase()) ? 1 : ((b."+sortfield+".toLowerCase() < a."+sortfield+".toLowerCase()) ? -1 : 0));"),window[sortdir]="desc"):(eval(arrayid+" = "+arrayid+".sort((a,b) => (a."+sortfield+".toLowerCase() > b."+sortfield+".toLowerCase()) ? 1 : ((b."+sortfield+".toLowerCase() > a."+sortfield+".toLowerCase()) ? -1 : 0));"),window[sortdir]="asc"):"number"==sorttype?-1==sorttext.indexOf("\u2193")&&-1==sorttext.indexOf("\u2191")?(eval(arrayid+" = "+arrayid+".sort((a,b) => parseFloat(a."+sortfield+".replace(\"m\",\"000\")) - parseFloat(b."+sortfield+".replace(\"m\",\"000\")));"),window[sortdir]="asc"):-1==sorttext.indexOf("\u2193")?(eval(arrayid+" = "+arrayid+".sort((a,b) => parseFloat(b."+sortfield+".replace(\"m\",\"000\")) - parseFloat(a."+sortfield+".replace(\"m\",\"000\")));"),window[sortdir]="desc"):(eval(arrayid+" = "+arrayid+".sort((a,b) => parseFloat(a."+sortfield+".replace(\"m\",\"000\")) - parseFloat(b."+sortfield+".replace(\"m\",\"000\")));"),window[sortdir]="asc"):"date"==sorttype&&(-1==sorttext.indexOf("\u2193")&&-1==sorttext.indexOf("\u2191")?(eval(arrayid+" = "+arrayid+".sort((a, b) => new Date(a."+sortfield+") - new Date(b."+sortfield+"));"),window[sortdir]="asc"):-1==sorttext.indexOf("\u2193")?(eval(arrayid+" = "+arrayid+".sort((a, b) => new Date(b."+sortfield+") - new Date(a."+sortfield+"));"),window[sortdir]="desc"):(eval(arrayid+" = "+arrayid+".sort((a, b) => new Date(a."+sortfield+") - new Date(b."+sortfield+"));"),window[sortdir]="asc")),$j("#"+tableid).empty(),$j("#"+tableid).append(BuildLastXTable(tableid.replace("sortTable",""))),$j("#"+tableid).find(".sortable").each(function(e,t){t.innerHTML.replace(/ \(.*\)/,"").replace(" ","")==window[sortname]&&("asc"==window[sortdir]?t.innerHTML+=" \u2191":t.innerHTML+=" \u2193")})}function BuildLastXTableNoData(){var e="<table width=\"100%\" border=\"1\" align=\"center\" cellpadding=\"4\" cellspacing=\"0\" bordercolor=\"#6b8fa3\" class=\"sortTable\">";return e+="<tr>",e+="<td class=\"nodata\">",e+="Data loading...",e+="</td>",e+="</tr>",e+="</table>",e}function BuildLastXTable(e){var t="<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" class=\"sortTable\">";t+="<col style=\"width:120px;\">",t+="<col style=\"width:70px;\">",t+="<col style=\"width:60px;\">",t+="<col style=\"width:60px;\">",t+="<col style=\"width:60px;\">",t+="<col style=\"width:65px;\">",t+="<col style=\"width:80px;\">",t+="<col style=\"width:80px;\">",t+="<col style=\"width:130px;\">",t+="<col style=\"width:80px;\">",t+="<col style=\"width:250px;\">",t+="<thead class=\"sortTableHeader\">",t+="<tr>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,''),'sortname"+e+"','sortdir"+e+"')\">Time</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,''),'sortname"+e+"','sortdir"+e+"')\">Download (Mbps)</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,''),'sortname"+e+"','sortdir"+e+"')\">Upload (Mbps)</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,''),'sortname"+e+"','sortdir"+e+"')\">Latency (ms)</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,''),'sortname"+e+"','sortdir"+e+"')\">Jitter (ms)</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,'').replace(' ',''),'sortname"+e+"','sortdir"+e+"')\">Packet Loss (%)</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,'').replace(' ',''),'sortname"+e+"','sortdir"+e+"')\">Download Data (MB)</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,'').replace(' ',''),'sortname"+e+"','sortdir"+e+"')\">Upload Data (MB)</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,''),'sortname"+e+"','sortdir"+e+"')\">URL</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,'').replace(' ',''),'sortname"+e+"','sortdir"+e+"')\">Server ID</th>",t+="<th class=\"sortable\" onclick=\"SortTable('sortTable"+e+"','arraysortlistlines"+e+"',this.innerHTML.replace(/ \\(.*\\)/,'').replace(' ',''),'sortname"+e+"','sortdir"+e+"')\">Server Name</th>",t+="</tr>",t+="</thead>",t+="<tbody class=\"sortTableContent\">";for(var a=0;a<window["arraysortlistlines"+e].length;a++)t+="<tr class=\"sortRow\">",t+="<td>"+window["arraysortlistlines"+e][a].Time+"</td>",t+="<td>"+window["arraysortlistlines"+e][a].Download+"</td>",t+="<td>"+window["arraysortlistlines"+e][a].Upload+"</td>",t+="<td>"+window["arraysortlistlines"+e][a].Latency+"</td>",t+="<td>"+window["arraysortlistlines"+e][a].Jitter+"</td>",t+="<td>"+window["arraysortlistlines"+e][a].PacketLoss.replace("null","N/A")+"</td>",t+="<td>"+window["arraysortlistlines"+e][a].DownloadData+"</td>",t+="<td>"+window["arraysortlistlines"+e][a].UploadData+"</td>",t+=""==window["arraysortlistlines"+e][a].URL?"<td>No result URL</td>":"<td><a href=\""+window["arraysortlistlines"+e][a].URL+"\" target=\"_blank\">Speedtest result URL</a></td>",t+="<td>"+window["arraysortlistlines"+e][a].ServerID.replace("null","")+"</td>",t+="<td>"+window["arraysortlistlines"+e][a].ServerName.replace("null","")+"</td>",t+="</tr>";return t+="</tbody>",t+="</table>",t}function changeAllCharts(t){value=1*t.value,name=t.id.substring(0,t.id.indexOf("_")),SetCookie(t.id,value);for(var e=interfacelist.split(","),a=0;a<e.length;a++)Draw_Chart(e[a],"Combined"),Draw_Chart(e[a],"Quality")}function changeChart(t){value=1*t.value,name=t.id.substring(0,t.id.indexOf("_")),SetCookie(t.id,value),-1==t.id.indexOf("Combined")?-1!=t.id.indexOf("Quality")&&Draw_Chart(name,"Quality"):Draw_Chart(name,"Combined")}function SettingHint(e){for(var t=document.getElementsByTagName("a"),a=0;a<t.length;a++)t[a].onmouseout=nd;return hinttext="My text goes here",1==e&&(hinttext="Interface not enabled"),2==e&&(hinttext="Hour(s) of day to run speedtest<br />* for all<br />Valid numbers between 0 and 23<br />comma (,) separate for multiple<br />dash (-) separate for a range"),3==e&&(hinttext="Minute(s) of day to run speedtest<br />(* for all<br />Valid numbers between 0 and 59<br />comma (,) separate for multiple<br />dash (-) separate for a range"),overlib(hinttext,0,0)}function BuildInterfaceTable(e){var t="<div style=\"line-height:10px;\"> </div>";return t+="<table width=\"100%\" border=\"1\" align=\"center\" cellpadding=\"4\" cellspacing=\"0\" bordercolor=\"#6b8fa3\" class=\"FormTable\" id=\"table_interfaces_"+e+"\">",t+="<thead class=\"collapsible-jquery\" id=\""+e+"\">",t+="<tr>",t+="<td colspan=\"2\">"+e+" (click to expand/collapse)</td>",t+="</tr>",t+="</thead>",t+="<tr>",t+="<td colspan=\"2\" align=\"center\" style=\"padding: 0px;\">",t+="<table width=\"100%\" border=\"1\" align=\"center\" cellpadding=\"4\" cellspacing=\"0\" bordercolor=\"#6b8fa3\" class=\"FormTable\">",t+="<thead class=\"collapsible-jquery\" id=\"resulttable_"+e+"\">",t+="<tr><td>Latest speedtest results (click to expand/collapse)</td></tr>",t+="</thead>",t+="<tr>",t+="<td style=\"padding: 0px;\">",t+="<div id=\"sortTable"+e+"\" class=\"sortTableContainer\" style=\"height:300px;\"></div>",t+="</td>",t+="</tr>",t+="</table>",t+="<div style=\"line-height:10px;\"> </div>",t+="<table width=\"100%\" border=\"1\" align=\"center\" cellpadding=\"4\" cellspacing=\"0\" bordercolor=\"#6b8fa3\" class=\"FormTable\">",t+="<thead class=\"collapsible-jquery\" id=\"table_charts\">",t+="<tr>",t+="<td>Tables and Charts (click to expand/collapse)</td>",t+="</tr>",t+="</thead>",t+="<tr><td align=\"center\" style=\"padding: 0px;\">",t+="<table width=\"100%\" border=\"1\" align=\"center\" cellpadding=\"4\" cellspacing=\"0\" bordercolor=\"#6b8fa3\" class=\"FormTable\">",t+="<thead class=\"collapsible-jquery\" id=\""+e+"_ChartCombined\">",t+="<tr>",t+="<td colspan=\"2\">Bandwidth (click to expand/collapse)</td>",t+="</tr>",t+="</thead>",t+="<tr class=\"even\">",t+="<th width=\"40%\">Data interval</th>",t+="<td>",t+="<select style=\"width:150px\" class=\"input_option\" onchange=\"changeChart(this);changePeriod(this);\" id=\""+e+"_Interval_Combined\">",t+="<option value=\"0\">Raw</option>",t+="<option value=\"1\">Hours</option>",t+="<option value=\"2\">Days</option>",t+="</select>",t+="</td>",t+="</tr>",t+="<tr class=\"even\">",t+="<th width=\"40%\">Period to display</th>",t+="<td>",t+="<select style=\"width:150px\" class=\"input_option\" onchange=\"changeChart(this)\" id=\""+e+"_Period_Combined\">",t+="<option value=0>Last 24 hours</option>",t+="<option value=1>Last 7 days</option>",t+="<option value=2>Last 30 days</option>",t+="</select>",t+="</td>",t+="</tr>",t+="<tr class=\"even\">",t+="<th width=\"40%\">Scale type</th>",t+="<td>",t+="<select style=\"width:150px\" class=\"input_option\" onchange=\"changeChart(this)\" id=\""+e+"_Scale_Combined\">",t+="<option value=\"0\">Linear</option>",t+="<option value=\"1\">Logarithmic</option>",t+="</select>",t+="</td>",t+="</tr>",t+="<tr>",t+="<td colspan=\"2\" align=\"center\" style=\"padding: 0px;\">",t+="<div style=\"background-color:#2f3e44;border-radius:10px;width:730px;height:500px;padding-left:5px;\"><canvas id=\"divLineChart_"+e+"_Combined\" height=\"500\" /></div>",t+="</td>",t+="</tr>",t+="</table>",t+="<div style=\"line-height:10px;\"> </div>",t+="<table width=\"100%\" border=\"1\" align=\"center\" cellpadding=\"4\" cellspacing=\"0\" bordercolor=\"#6b8fa3\" class=\"FormTable\">",t+="<thead class=\"collapsible-jquery\" id=\""+e+"_ChartQuality\">",t+="<tr>",t+="<td colspan=\"2\">Quality (click to expand/collapse)</td>",t+="</tr>",t+="</thead>",t+="<tr class=\"even\">",t+="<th width=\"40%\">Data interval</th>",t+="<td>",t+="<select style=\"width:150px\" class=\"input_option\" onchange=\"changeChart(this);changePeriod(this);\" id=\""+e+"_Interval_Quality\">",t+="<option value=\"0\">Raw</option>",t+="<option value=\"1\">Hours</option>",t+="<option value=\"2\">Days</option>",t+="</select>",t+="</td>",t+="</tr>",t+="<tr class=\"even\">",t+="<th width=\"40%\">Period to display</th>",t+="<td>",t+="<select style=\"width:150px\" class=\"input_option\" onchange=\"changeChart(this)\" id=\""+e+"_Period_Quality\">",t+="<option value=0>Last 24 hours</option>",t+="<option value=1>Last 7 days</option>",t+="<option value=2>Last 30 days</option>",t+="</select>",t+="</td>",t+="</tr>",t+="<tr class=\"even\">",t+="<th width=\"40%\">Scale type</th>",t+="<td>",t+="<select style=\"width:150px\" class=\"input_option\" onchange=\"changeChart(this)\" id=\""+e+"_Scale_Quality\">",t+="<option value=\"0\">Linear</option>",t+="<option value=\"1\">Logarithmic</option>",t+="</select>",t+="</td>",t+="</tr>",t+="<tr>",t+="<td colspan=\"2\" align=\"center\" style=\"padding: 0px;\">",t+="<div style=\"background-color:#2f3e44;border-radius:10px;width:730px;height:500px;padding-left:5px;\"><canvas id=\"divLineChart_"+e+"_Quality\" height=\"500\" /></div>",t+="</td>",t+="</tr>",t+="</table>",t+="</td>",t+="</tr>",t+="</table>",t+="</td>",t+="</tr>",t+="</table>",t}function AutomaticInterfaceEnableDisable(e){var t=e.name,a=e.value,s=t.substring(0,t.lastIndexOf("_")),r=["schhours","schmins"],l=["schedulemode","everyxselect","everyxvalue"];if("false"==a){for(var n=0;n<interfacescomplete.length;n++)$j("#"+s+"_iface_enabled_"+interfacescomplete[n].toLowerCase()).prop("disabled",!0),$j("#"+s+"_iface_enabled_"+interfacescomplete[n].toLowerCase()).addClass("disabled"),$j("#"+s+"_usepreferred_"+interfacescomplete[n].toLowerCase()).prop("disabled",!0),$j("#"+s+"_usepreferred_"+interfacescomplete[n].toLowerCase()).addClass("disabled"),$j("#changepref_"+interfacescomplete[n].toLowerCase()).prop("disabled",!0),$j("#changepref_"+interfacescomplete[n].toLowerCase()).addClass("disabled");for(var n=0;n<r.length;n++)$j("input[name="+s+"_"+r[n]+"]").addClass("disabled"),$j("input[name="+s+"_"+r[n]+"]").prop("disabled",!0);for(var n=0;n<daysofweek.length;n++)$j("#"+s+"_"+daysofweek[n].toLowerCase()).prop("disabled",!0);for(var n=0;n<l.length;n++)$j("[name="+l[n]+"]").addClass("disabled"),$j("[name="+l[n]+"]").prop("disabled",!0)}else if("true"==a){for(var n=0;n<interfacescomplete.length;n++)!1==interfacesdisabled.includes(interfacescomplete[n])&&($j("#"+s+"_iface_enabled_"+interfacescomplete[n].toLowerCase()).prop("disabled",!1),$j("#"+s+"_iface_enabled_"+interfacescomplete[n].toLowerCase()).removeClass("disabled"),$j("#"+s+"_usepreferred_"+interfacescomplete[n].toLowerCase()).prop("disabled",!1),$j("#"+s+"_usepreferred_"+interfacescomplete[n].toLowerCase()).removeClass("disabled"),$j("#changepref_"+interfacescomplete[n].toLowerCase()).prop("disabled",!1),$j("#changepref_"+interfacescomplete[n].toLowerCase()).removeClass("disabled"));for(var n=0;n<r.length;n++)$j("input[name="+s+"_"+r[n]+"]").removeClass("disabled"),$j("input[name="+s+"_"+r[n]+"]").prop("disabled",!1);for(var n=0;n<daysofweek.length;n++)$j("#"+s+"_"+daysofweek[n].toLowerCase()).prop("disabled",!1);for(var n=0;n<l.length;n++)$j("[name="+l[n]+"]").removeClass("disabled"),$j("[name="+l[n]+"]").prop("disabled",!1)}}function ScheduleModeToggle(e){var t=e.name,a=e.value;"EveryX"==a?(showhide("schfrequency",!0),showhide("schcustom",!1),"hours"==$j("#everyxselect").val()?(showhide("spanxhours",!0),showhide("spanxminutes",!1)):"minutes"==$j("#everyxselect").val()&&(showhide("spanxhours",!1),showhide("spanxminutes",!0))):"Custom"==a&&(showhide("schfrequency",!1),showhide("schcustom",!0))}function EveryXToggle(e){var t=e.name,a=e.value;"hours"==a?(showhide("spanxhours",!0),showhide("spanxminutes",!1)):"minutes"==a&&(showhide("spanxhours",!1),showhide("spanxminutes",!0)),Validate_ScheduleValue($j("[name=everyxvalue]")[0])}function AutoBWEnableDisable(e){var t=e.name,a=e.value,s=t.substring(0,t.indexOf("_")),r=["autobw_ulimit","autobw_llimit","autobw_sf","autobw_threshold","autobw_average"];if("false"==a){for(var l=0;l<r.length;l++)$j("input[name^="+s+"_"+r[l]+"]").addClass("disabled"),$j("input[name^="+s+"_"+r[l]+"]").prop("disabled",!0);$j("input[name^="+s+"_excludefromqos]").removeClass("disabled"),$j("input[name^="+s+"_excludefromqos]").prop("disabled",!1)}else if("true"==a){for(var l=0;l<r.length;l++)$j("input[name^="+s+"_"+r[l]+"]").removeClass("disabled"),$j("input[name^="+s+"_"+r[l]+"]").prop("disabled",!1);document.form.spdmerlin_excludefromqos.value=!0,$j("input[name^="+s+"_excludefromqos]").addClass("disabled"),$j("input[name^="+s+"_excludefromqos]").prop("disabled",!0)}}function Toggle_ChangePrefServer(e){var t=e.name,a=e.checked,s=t.split("_")[1];!0==a?(document.formScriptActions.action_script.value="start_spdmerlinserverlist_"+s,document.formScriptActions.submit(),showhide("imgServerList_"+s,!0),setTimeout(get_spdtestservers_file,2e3,s)):($j("#spdmerlin_preferredserver_"+s)[0].style.display="none",$j("#spdmerlin_preferredserver_"+s).prop("disabled",!0),$j("#spdmerlin_preferredserver_"+s).addClass("disabled"))}function Change_SpdTestInterface(e){var t=e.name,a=e.value;GenerateManualSpdTestServerPrefSelect(),Toggle_SpdTestServerPref(document.form.spdtest_serverpref)}function Toggle_SpdTestServerPref(e){var t=e.name,a=e.value;if("onetime"==a){document.formScriptActions.action_script.value="start_spdmerlinserverlistmanual_"+document.form.spdtest_enabled.value,document.formScriptActions.submit();for(var s=0;s<interfacescomplete.length;s++)$j("#spdtest_enabled_"+interfacescomplete[s].toLowerCase()).prop("disabled",!0),$j("#spdtest_enabled_"+interfacescomplete[s].toLowerCase()).addClass("disabled");$j.each($j("input[name=spdtest_serverpref]"),function(){$j(this).prop("disabled",!0),$j(this).addClass("disabled")}),showhide("rowmanualserverprefselect",!0),showhide("imgManualServerList",!0),"All"==document.form.spdtest_enabled.value?$j.each($j("select[name^=spdtest_serverprefselect]"),function(){$j(this).empty()}):$j("select[name=spdtest_serverprefselect]").empty(),setTimeout(get_manualspdtestservers_file,2e3)}else showhide("rowmanualserverprefselect",!1),"All"==document.form.spdtest_enabled.value?($j.each($j("select[name^=spdtest_serverprefselect]"),function(){showhide(this.id,!1)}),$j.each($j("span[id^=spdtest_serverprefselectspan]"),function(){showhide(this.id,!1)})):showhide("spdtest_serverprefselect",!1),showhide("imgManualServerList",!1)}function GenerateManualSpdTestServerPrefSelect(){$j("#rowmanualserverprefselect").remove();var e="<tr class=\"even\" id=\"rowmanualserverprefselect\" style=\"display:none;\">";if(e+="<td class=\"settingname\">Choose a server</th><td class=\"settingvalue\"><img id=\"imgManualServerList\" style=\"display:none;vertical-align:middle;\" src=\"images/InternetScan.gif\"/>","All"==document.form.spdtest_enabled.value){for(var t=0;t<interfacescomplete.length;t++)if(!1==interfacesdisabled.includes(interfacescomplete[t])){var a=interfacescomplete[t].toLowerCase();e+="<span style=\"width:50px;display:none;\" id=\"spdtest_serverprefselectspan_"+a+"\">"+interfacescomplete[t]+":</span><select name=\"spdtest_serverprefselect_"+a+"\" id=\"spdtest_serverprefselect_"+a+"\" style=\"display:none;max-width:415px;\"></select><br />"}}else e+="<select name=\"spdtest_serverprefselect\" id=\"spdtest_serverprefselect\" style=\"display:none;\"></select>";e+="</td></tr>",$j("#rowmanualserverpref").after(e)}function Validate_All(){var e=!1;return Validate_Number_Setting(document.form.spdmerlin_autobw_sf_down,100,0)||(e=!0),Validate_Number_Setting(document.form.spdmerlin_autobw_sf_up,100,0)||(e=!0),Validate_Number_Setting(document.form.spdmerlin_autobw_threshold_down,100,0)||(e=!0),Validate_Number_Setting(document.form.spdmerlin_autobw_threshold_up,100,0)||(e=!0),Validate_Number_Setting(document.form.spdmerlin_autobw_average_calc,30,1)||(e=!0),"EveryX"==document.form.schedulemode.value?!Validate_ScheduleValue(document.form.everyxvalue)&&(e=!0):"Custom"==document.form.schedulemode.value&&(!Validate_Schedule(document.form.spdmerlin_schhours,"hours")&&(e=!0),!Validate_Schedule(document.form.spdmerlin_schmins,"mins")&&(e=!0)),!e||(alert("Validation for some fields failed. Please correct invalid values and try again."),!1)}function Validate_Schedule(e,t){var a=e.name,s=e.value.split(","),r=0;"hours"==t?r=23:"mins"==t&&(r=59),showhide("btnfixhours",!1),showhide("btnfixmins",!1);for(var l="false",n=0;n<s.length;n++)if("*"==s[n]&&0==n)l="false";else if("*"==s[n]&&0!=n)l="true";else if("*"==s[0]&&0<n)l="true";else if(""==s[n])l="true";else if(s[n].startsWith("*/"))isNaN(1*s[n].replace("*/",""))?l="true":(1*s[n].replace("*/","")>r||0>1*s[n].replace("*/",""))&&(l="true");else if(!(-1!=s[n].indexOf("-")))isNaN(1*s[n])?l="true":(1*s[n]>r||0>1*s[n])&&(l="true");else if(s[n].startsWith("-"))l="true";else for(var d=s[n].split("-"),o=0;o<d.length;o++)""==d[o]?l="true":isNaN(1*d[o])?l="true":1*d[o]>r||0>1*d[o]?l="true":1*d[o+1]<1*d[o]&&(l="true","hours"==t?showhide("btnfixhours",!0):"mins"==t&&showhide("btnfixmins",!0));return"true"==l?($j(e).addClass("invalid"),!1):($j(e).removeClass("invalid"),!0)}function Validate_ScheduleValue(e){var t=e.name,a=1*e.value,s=0,r=$j("#everyxselect").val();return"hours"==r?s=24:"minutes"==r&&(s=30),a>s||a<1||1>e.value.length?($j(e).addClass("invalid"),!1):($j(e).removeClass("invalid"),!0)}function Validate_Number_Setting(e,t,a){var s=e.name,r=1*e.value;return r>t||r<a?($j(e).addClass("invalid"),!1):($j(e).removeClass("invalid"),!0)}function Format_Number_Setting(e){var t=e.name,a=1*e.value;return 0!=e.value.length&&a!=NaN&&(e.value=parseInt(e.value),!0)}function FixCron(e){if("hours"==e){var t=document.form.spdmerlin_schhours.value;document.form.spdmerlin_schhours.value=t.split("-")[0]+"-23,0-"+t.split("-")[1],Validate_Schedule(document.form.spdmerlin_schhours,"hours")}else if("mins"==e){var t=document.form.spdmerlin_schmins.value;document.form.spdmerlin_schmins.value=t.split("-")[0]+"-59,0-"+t.split("-")[1],Validate_Schedule(document.form.spdmerlin_schmins,"mins")}}function AddEventHandlers(){$j(".collapsible-jquery").off("click").on("click",function(){$j(this).siblings().toggle("fast",function(){"none"==$j(this).css("display")?SetCookie($j(this).siblings()[0].id,"collapsed"):SetCookie($j(this).siblings()[0].id,"expanded")})}),$j(".collapsible-jquery").each(function(){"collapsed"==GetCookie($j(this)[0].id,"string")?$j(this).siblings().toggle(!1):$j(this).siblings().toggle(!0)})}
</script>
</head>
<body onload="initial();" onunload="return unload_body();">
<div id="TopBanner"></div>
<div id="Loading" class="popup_bg"></div>
<iframe name="hidden_frame" id="hidden_frame" src="about:blank" width="0" height="0" frameborder="0"></iframe>
<form method="post" name="form" id="ruleForm" action="/start_apply.htm" target="hidden_frame">
<input type="hidden" name="action_script" value="start_spdmerlin">
<input type="hidden" name="current_page" value="">
<input type="hidden" name="next_page" value="">
<input type="hidden" name="modified" value="0">
<input type="hidden" name="action_mode" value="apply">
<input type="hidden" name="action_wait" value="90">
<input type="hidden" name="first_time" value="">
<input type="hidden" name="SystemCmd" value="">
<input type="hidden" name="preferred_lang" id="preferred_lang" value="<% nvram_get("preferred_lang"); %>">
<input type="hidden" name="firmver" value="<% nvram_get("firmver"); %>">
<input type="hidden" name="amng_custom" id="amng_custom" value="">
<table class="content" align="center" cellpadding="0" cellspacing="0">
<tr>
<td width="17"> </td>
<td valign="top" width="202">
<div id="mainMenu"></div>
<div id="subMenu"></div></td>
<td valign="top">
<div id="tabMenu" class="submenuBlock"></div>
<table width="98%" border="0" align="left" cellpadding="0" cellspacing="0">
<tr>
<td valign="top">
<table width="760px" border="0" cellpadding="4" cellspacing="0" bordercolor="#6b8fa3" class="FormTitle" id="FormTitle">
<tbody>
<tr bgcolor="#4D595D">
<td valign="top">
<div> </div>
<div class="formfonttitle" id="scripttitle" style="text-align:center;">spdMerlin</div>
<div id="statstitle" style="text-align:center;">Stats last updated:</div>
<div style="margin:10px 0 10px 5px;" class="splitLine"></div>
<div class="formfontdesc">spdMerlin is an internet speedtest and monitoring tool for AsusWRT Merlin with charts for daily, weekly and monthly summaries. It tracks download/upload bandwidth as well as latency, jitter and packet loss.</div>
<table width="100%" border="1" align="center" cellpadding="4" cellspacing="0" bordercolor="#6b8fa3" class="FormTable" style="border:0px;" id="table_buttons">
<thead class="collapsible-jquery" id="scripttools">
<tr><td colspan="2">Utilities (click to expand/collapse)</td></tr>
</thead>
<tr>
<th width="20%">Version information</th>
<td>
<span id="spdmerlin_version_local" style="color:#FFFFFF;"></span>
<span id="spdmerlin_version_server" style="display:none;">Update version</span>
<input type="button" class="button_gen" onclick="CheckUpdate();" value="Check" id="btnChkUpdate">
<img id="imgChkUpdate" style="display:none;vertical-align:middle;" src="images/InternetScan.gif"/>
<input type="button" class="button_gen" onclick="DoUpdate();" value="Update" id="btnDoUpdate" style="display:none;">
</td>
</tr>
<tr>
<th width="20%">Export</th>
<td>
<input type="button" onclick="ExportCSV();" value="Export to CSV" class="button_gen" name="btnExport">
</td>
</tr>
</table>
<div style="line-height:10px;"> </div>
<table width="100%" border="1" align="center" cellpadding="4" cellspacing="0" bordercolor="#6b8fa3" class="FormTable SettingsTable" style="border:0px;" id="table_manualspeedtests">
<thead class="collapsible-jquery" id="thead_manualspeedtests">
<tr><td colspan="2">Manual Speedtest (click to expand/collapse)</td></tr>
</thead>
<tr class="even" id="rowmanualserverpref">
<td class="settingname">Mode for speedtest</td>
<td class="settingvalue">
<input type="radio" name="spdtest_serverpref" id="spdtest_serverpref_auto" class="input" value="auto" onchange="Toggle_SpdTestServerPref(this)" checked>
<label for="spdtest_serverpref_auto">Auto-select server</label>
<input type="radio" name="spdtest_serverpref" id="spdtest_serverpref_user" class="input" value="user" onchange="Toggle_SpdTestServerPref(this)">
<label for="spdtest_serverpref_user">Preferred server</label>
<input type="radio" name="spdtest_serverpref" id="spdtest_serverpref_onetime" class="input" value="onetime" onchange="Toggle_SpdTestServerPref(this)">
<label for="spdtest_serverpref_onetime">Choose a server</label>
</td>
</tr>
<tr class="apply_gen" valign="top" height="35px">
<td colspan="2" class="savebutton">
<input type="button" onclick="RunSpeedtest();" value="Run speedtest" class="button_gen savebutton" name="btnRunSpeedtest" id="btnRunSpeedtest">
<img id="imgSpdTest" style="display:none;vertical-align:middle;" src="images/InternetScan.gif"/>
<span id="spdtest_text" style="display:none;"></span>
</td>
</tr>
<tr style="display:none;" class="spdtest_output"><td colspan="2" style="padding: 0px;">
<textarea cols="63" rows="8" wrap="off" readonly="readonly" id="spdtest_output" class="textarea_log_table" style="border:0px;font-family:Courier New,Courier,mono; font-size:11px;overflow-y:auto;overflow-x:hidden;">Speedtest output</textarea>
</td></tr>
</table>
<div style="line-height:10px;"> </div>
<table width="100%" border="1" align="center" cellpadding="2" cellspacing="0" bordercolor="#6b8fa3" class="FormTable SettingsTable" style="border:0px;" id="table_config">
<thead class="collapsible-jquery" id="scriptconfig">
<td colspan="2">General Configuration (click to expand/collapse)</td>
</thead>
<tr class="even" valign="middle" style="border-width:0px 1px;border-style:solid;border-color:black;">
<td style="padding:0px;">
<table width="100%" border="1" align="center" cellpadding="2" cellspacing="0" bordercolor="#6b8fa3" class="FormTable SettingsTable" style="border:0px;">
<thead class="collapsible-jquery" id="testconfig">
<td colspan="2">Automatic speedtest configuration</td>
</thead>
<tr class="even" id="rowautomatedtests">
<td class="settingname">Enable automatic speedtests</td>
<td class="settingvalue">
<input type="radio" name="spdmerlin_automated" id="spdmerlin_auto_true" onchange="AutomaticInterfaceEnableDisable(this)" class="input" value="true" checked>
<label for="spdmerlin_auto_true">Yes</label>
<input type="radio" name="spdmerlin_automated" id="spdmerlin_auto_false" onchange="AutomaticInterfaceEnableDisable(this)" class="input" value="false">
<label for="spdmerlin_auto_false">No</label>
</td>
</tr>
<tr class="even" id="rowschedule">
<td class="settingname">Schedule for automatic speedtests</td>
<td class="settingvalue">
<div class="schedulesettings" id="schdays">
<span class="schedulespan" style="vertical-align:top;">Day(s)</span>
<input type="checkbox" name="spdmerlin_schdays" id="spdmerlin_mon" class="input" value="Mon" style="margin-left:0px;"><label for="spdmerlin_mon">Mon</label>
<input type="checkbox" name="spdmerlin_schdays" id="spdmerlin_tues" class="input" value="Tues"><label for="spdmerlin_tues">Tues</label>
<input type="checkbox" name="spdmerlin_schdays" id="spdmerlin_wed" class="input" value="Wed"><label for="spdmerlin_wed">Wed</label>
<input type="checkbox" name="spdmerlin_schdays" id="spdmerlin_thurs" class="input" value="Thurs"><label for="spdmerlin_thurs">Thurs</label>
<input type="checkbox" name="spdmerlin_schdays" id="spdmerlin_fri" class="input" value="Fri"><label for="spdmerlin_fri">Fri</label>
<input type="checkbox" name="spdmerlin_schdays" id="spdmerlin_sat" class="input" value="Sat"><label for="spdmerlin_sat">Sat</label>
<input type="checkbox" name="spdmerlin_schdays" id="spdmerlin_sun" class="input" value="Sun"><label for="spdmerlin_sun">Sun</label>
</div>
<div class="schedulesettings" id="schmode">
<span class="schedulespan" style="vertical-align:top;">Mode</span>
<input type="radio" onchange="ScheduleModeToggle(this)" name="schedulemode" id="schmode_everyx" class="input" value="EveryX"><label for="schmode_everyx">Every X hours/minutes</label>
<input type="radio" onchange="ScheduleModeToggle(this)" name="schedulemode" id="schmode_custom" class="input" value="Custom" checked><label for="schmode_custom">Custom</label>
</div>
<div style="margin-bottom:0px;" class="schedulesettings" id="schfrequency">
<span class="schedulespan">Frequency</span>
<span style="color:#FFFFFF;margin-left:3px;">Every </span>
<input autocomplete="off" style="text-align:center;padding-left:2px;" type="text" maxlength="2" class="input_3_table removespacing" name="everyxvalue" id="everyxvalue" value="30" onkeypress="return validator.isNumber(this,event)" onkeyup="Validate_ScheduleValue(this)" onblur="Validate_ScheduleValue(this)" />
<select name="everyxselect" id="everyxselect" class="input_option" onchange="EveryXToggle(this)">
<option value="hours">hours</option><option value="minutes" selected>minutes</option></select>
<span id="spanxhours" style="color:#FFCC00;"> (between 1 and 24)</span>
<span id="spanxminutes" style="color:#FFCC00;"> (between 1 and 30, default: 30)</span>
</div>
<div id="schcustom">
<div class="schedulesettings">
<a class="hintstyle" href="javascript:void(0);" onclick="SettingHint(2);">
<span class="schedulespan">Hours</span>
</a>
<input data-lpignore="true" autocomplete="off" autocapitalize="off" type="text" class="input_25_table" name="spdmerlin_schhours" value="*" onkeyup="Validate_Schedule(this,'hours')" onblur="Validate_Schedule(this,'hours')" />
<input id="btnfixhours" type="button" onclick="FixCron('hours');" value="Fix?" class="button_gen cronbutton" name="button" style="display:none;">
</div>
<div class="schedulesettings">
<a class="hintstyle" href="javascript:void(0);" onclick="SettingHint(3);">
<span class="schedulespan">Minutes</span>
</a>
<input data-lpignore="true" autocomplete="off" autocapitalize="off" type="text" class="input_25_table" name="spdmerlin_schmins" value="*" onkeyup="Validate_Schedule(this,'mins')" onblur="Validate_Schedule(this,'mins')" />
<input id="btnfixmins" type="button" onclick="FixCron('mins');" value="Fix?" class="button_gen cronbutton" name="button" style="display:none;">
</div>
</div>
</td>
</tr>
</table>
<div style="line-height:10px;"> </div>
<table width="100%" border="1" align="center" cellpadding="2" cellspacing="0" bordercolor="#6b8fa3" class="FormTable SettingsTable" style="border:0px;">
<thead class="collapsible-jquery" id="autobwconfig">
<td colspan="2">AutoBW configuration</td>
</thead>
<tr class="even" id="rowautobwenabled">
<td class="settingname">Enable AutoBW?<br/><span style="color:#FFCC00;background:#2F3A3E;">Automatically adjust QoS bandwidth limits using automatic speedtest data</span></td>
<td class="settingvalue">
<input type="radio" name="spdmerlin_autobw_enabled" id="spdmerlin_autobw_true" onchange="AutoBWEnableDisable(this)" class="input" value="true">
<label for="spdmerlin_autobw_true">Yes</label>
<input type="radio" name="spdmerlin_autobw_enabled" id="spdmerlin_autobw_false" onchange="AutoBWEnableDisable(this)" class="input" value="false" checked>
<label for="spdmerlin_autobw_false">No</label>
</td>
</tr>
<tr class="even" id="rowautobwavgcalc">
<td class="settingname">Number of speedtests to use to calculate average bandwidth</td>
<td class="settingvalue">
<input autocomplete="off" type="text" maxlength="2" class="input_3_table removespacing" name="spdmerlin_autobw_average_calc" value="10" onkeypress="return validator.isNumber(this,event)" onkeyup="Validate_Number_Setting(this,30,1)" onblur="Validate_Number_Setting(this,30,1);Format_Number_Setting(this)" /><span style="color:#FFFFFF;"> speedtest(s) </span><span style="color:#FFCC00;">(between 1 and 30,default: 10)</span>
</td>
</tr>
<tr class="even" id="rowautobwsf">
<td class="settingname">Scale factor to use for speedtest results</td>
<td class="settingvalue">
<span class="schedulespan">Download</span><input autocomplete="off" type="text" maxlength="3" class="input_6_table removespacing" name="spdmerlin_autobw_sf_down" value="100" onkeypress="return validator.isNumber(this,event)" onkeyup="Validate_Number_Setting(this,100,0)" onblur="Validate_Number_Setting(this,100,0);Format_Number_Setting(this)" /><span style="color:#FFFFFF;"> %</span>
<span class="schedulespan">Upload</span><input autocomplete="off" type="text" maxlength="3" class="input_6_table removespacing" name="spdmerlin_autobw_sf_up" value="100" onkeypress="return validator.isNumber(this,event)" onkeyup="Validate_Number_Setting(this,100,0)" onblur="Validate_Number_Setting(this,100,0);Format_Number_Setting(this)" /><span style="color:#FFFFFF;"> %</span>
</td>
</tr>
<tr class="even" id="rowautobwlimits">
<td class="settingname">Bandwidth limits for AutoBW calculations<br/><span style="color:#FFCC00;background:#2F3A3E;">(for Upper Limit 0 = Unlimited)</span></td>
<td class="settingvalue"><span style="font-weight:bolder;color:#FFFFFF;">Upper Limit: </span>
<span class="schedulespan">Download</span><input autocomplete="off" type="text" maxlength="4" class="input_6_table removespacing" name="spdmerlin_autobw_ulimit_down" value="100" onkeypress="return validator.isNumber(this,event)" /><span style="color:#FFFFFF;"> Mbps</span>
<span class="schedulespan">Upload</span><input autocomplete="off" type="text" maxlength="4" class="input_6_table removespacing" name="spdmerlin_autobw_ulimit_up" value="20" onkeypress="return validator.isNumber(this,event)" /><span style="color:#FFFFFF;"> Mbps</span><br />
<span style="font-weight:bolder;color:#FFFFFF;">Lower Limit: </span>
<span class="schedulespan">Download</span><input autocomplete="off" type="text" maxlength="4" class="input_6_table removespacing" name="spdmerlin_autobw_llimit_down" value="50" onkeypress="return validator.isNumber(this,event)" /><span style="color:#FFFFFF;"> Mbps</span>
<span class="schedulespan">Upload</span><input autocomplete="off" type="text" maxlength="4" class="input_6_table removespacing" name="spdmerlin_autobw_llimit_up" value="10" onkeypress="return validator.isNumber(this,event)" /><span style="color:#FFFFFF;"> Mbps</span><br />
</td>
</tr>
<tr class="even" id="rowautobwth">
<td class="settingname">Threshold for updating QoS bandwidth values</td>
<td class="settingvalue">
<span class="schedulespan">Download</span><input autocomplete="off" type="text" maxlength="3" class="input_6_table removespacing" name="spdmerlin_autobw_threshold_down" value="10" onkeypress="return validator.isNumber(this,event)" onkeyup="Validate_Number_Setting(this,100,0)" onblur="Validate_Number_Setting(this,100,0);Format_Number_Setting(this)" /><span style="color:#FFFFFF;"> %</span>
<span class="schedulespan">Upload</span><input autocomplete="off" type="text" maxlength="3" class="input_6_table removespacing" name="spdmerlin_autobw_threshold_up" value="10" onkeypress="return validator.isNumber(this,event)" onkeyup="Validate_Number_Setting(this,100,0)" onblur="Validate_Number_Setting(this,100,0);Format_Number_Setting(this)" /><span style="color:#FFFFFF;"> %</span>
</td>
</tr>
<tr>
<td class="settingname">AutoBW status</td>
<td class="settingvalue" style="padding:2px">
<textarea cols="75" rows="15" wrap="soft" readonly="readonly" id="AutoBWOutput" class="textarea_log_table settings" style="font-size:11px;"></textarea>
</td>
</tr>
</table>
<div style="line-height:10px;"> </div>
<table width="100%" border="1" align="center" cellpadding="2" cellspacing="0" bordercolor="#6b8fa3" class="FormTable SettingsTable" style="border:0px;">
<thead class="collapsible-jquery" id="generalconfig">
<td colspan="2">Script configuration</td>
</thead>
<tr class="even" id="rowtimeoutput">
<td class="settingname">Time Output Mode<br/><span style="color:#FFCC00;background:#2F3A3E;">(for CSV export)</span></td>
<td class="settingvalue">
<input type="radio" name="spdmerlin_outputtimemode" id="spdmerlin_timeoutput_non-unix" class="input" value="non-unix" checked>
<label for="spdmerlin_timeoutput_non-unix">Non-Unix</label>
<input type="radio" name="spdmerlin_outputtimemode" id="spdmerlin_timeoutput_unix" class="input" value="unix">
<label for="spdmerlin_timeoutput_unix">Unix</label>
</td>
</tr>
<tr class="even" id="rowlastxresults">
<td class="settingname">Last X results to display</td>
<td class="settingvalue">
<input autocomplete="off" type="text" maxlength="3" class="input_6_table removespacing" name="spdmerlin_lastxresults" value="10" onkeypress="return validator.isNumber(this,event)" onblur="Validate_Number_Setting(this,100,1);Format_Number_Setting(this)" onkeyup="Validate_Number_Setting(this,100,1)"/>
results <span style="color:#FFCC00;">(between 1 and 100,default: 10)</span>
</td>
</tr>
<tr class="even" id="rowdaystokeep">
<td class="settingname">Number of days of data to keep</td>
<td class="settingvalue">
<input autocomplete="off" type="text" maxlength="3" class="input_6_table removespacing" name="spdmerlin_daystokeep" value="30" onkeypress="return validator.isNumber(this,event)" onblur="Validate_Number_Setting(this,365,30);Format_Number_Setting(this)" onkeyup="Validate_Number_Setting(this,365,30)"/>
days <span style="color:#FFCC00;">(between 30 and 365,default: 30)</span>
</td>
</tr>
<tr class="even" id="rowstorageloc">
<td class="settingname">Data Storage Location</td>
<td class="settingvalue">
<input type="radio" name="spdmerlin_storagelocation" id="spdmerlin_storageloc_jffs" class="input" value="jffs" checked>
<label for="spdmerlin_storageloc_jffs">JFFS</label>
<input type="radio" name="spdmerlin_storagelocation" id="spdmerlin_storageloc_usb" class="input" value="usb">
<label for="spdmerlin_storageloc_usb">USB</label>
</td>
</tr>
<tr class="even" id="rowstoreresulturl">
<td class="settingname">Save speedtest URLs to database</td>
<td class="settingvalue">
<input type="radio" name="spdmerlin_storeresulturl" id="spdmerlin_store_true" class="input" value="true">
<label for="spdmerlin_store_true">Yes</label>
<input type="radio" name="spdmerlin_storeresulturl" id="spdmerlin_store_false" class="input" value="false" checked>
<label for="spdmerlin_store_false">No</label>
</td>
</tr>
<tr class="even" id="rowexcludefromqos">
<td class="settingname">Exclude speedtests from QoS</td>
<td class="settingvalue">
<input type="radio" name="spdmerlin_excludefromqos" id="spdmerlin_exclude_true" class="input" value="true" checked>
<label for="spdmerlin_exclude_true">Yes</label>
<input type="radio" name="spdmerlin_excludefromqos" id="spdmerlin_exclude_false" class="input" value="false">
<label for="spdmerlin_exclude_false">No</label>
</td>
</tr>
</table>
</td>
</tr>
<tr class="apply_gen" valign="top" height="35px">
<td colspan="2" class="savebutton">
<input type="button" onclick="SaveConfig();" value="Save" class="button_gen savebutton" name="button">
</td>
</tr>
</table>
<div style="line-height:10px;"> </div>
<table width="100%" border="1" align="center" cellpadding="4" cellspacing="0" bordercolor="#6b8fa3" class="FormTable" style="border:0px;" id="table_buttons2">
<thead class="collapsible-jquery" id="charttools">
<tr><td colspan="2">Chart Display Options (click to expand/collapse)</td></tr>
</thead>
<tr>
<th width="20%"><span style="color:#FFFFFF;background:#2F3A3E;">Time format</span><br /><span style="color:#FFCC00;background:#2F3A3E;">(for tooltips and Last 24h chart axis)</span></th>
<td>
<select style="width:100px" class="input_option" onchange="changeAllCharts(this)" id="Time_Format">
<option value="0">24h</option>
<option value="1">12h</option>
</select>
</td>
</tr>
<tr class="apply_gen" valign="top">
<td colspan="2" style="background-color:rgb(77,89,93);">
<input type="button" onclick="ToggleDragZoom(this);" value="Drag Zoom On" class="button_gen" name="btnDragZoom">
<input type="button" onclick="ResetZoom();" value="Reset Zoom" class="button_gen" name="btnResetZoom">
<input type="button" onclick="ToggleLines();" value="Toggle Lines" class="button_gen" name="btnToggleLines">
<input type="button" onclick="ToggleFill();" value="Toggle Fill" class="button_gen" name="btnToggleFill">
</td>
</tr>
</table>
<!-- Charts inserted here -->
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</form>
<form method="post" name="formScriptActions" action="/start_apply.htm" target="hidden_frame">
<input type="hidden" name="productid" value="<% nvram_get("productid"); %>">
<input type="hidden" name="current_page" value="">
<input type="hidden" name="next_page" value="">
<input type="hidden" name="action_mode" value="apply">
<input type="hidden" name="action_script" value="">
<input type="hidden" name="action_wait" value="">
</form>
<div id="footer">
</div>
</body>
</html>