otsdaq_utilities  v2_04_02
MacroMaker.js
1 // Created by swu at fnal dot gov
2 // February 2016
3 //
4 
5  //Function List:
6  //init
7  //initLite
8  //redrawWindow
9  //FElistHandler
10  //getPermissionHandler
11  //listSelectionHandler
12 
13  //callWrite
14  //callRead
15  //writeHandler
16  //readHandler
17  //toggleReadBitField
18 
19  //isArrayAllZero
20  //convertToHex
21  //convertFromHex
22  //reverseLSB
23  //LSBchecker
24  //toggleDisplay
25  //toggleMacroPublicity
26  //addCommand
27  //hideDeletex
28  //showDeletex
29  //getOrder
30  //removeCommand
31  //undoDelete
32  //showPopupClearAllConfirm
33  //showPopupClearHistoryConfirm
34  //clearAll
35  //clearHistory
36  //clearHistoryHandler
37  //hideSmallPopup
38  //saveMacro
39  //hidePopupSaveMacro
40  //hidePopupEditMacro
41  //saveAsMacro()
42  //createMacroHandler(req,macroName)
43  //runMacro
44  //loadExistingMacros
45  //loadUserHistory
46  //loadingMacrosHandler
47  //loadingHistHandler
48  //histCmdWriteDivOnclick
49  //histCmdReadDivOnclick
50  //histCmdDelayDivOnclick
51  //macroActionOnRightClick
52  //exportMacroHandler
53  //editCommands
54  //deleteMacroHandler
55  //saveChangedMacro
56  //saveChangedMacroHandler(req,macroName)
57  //reloadMacroSequence
58  //setFieldToVariable
59  //dealWithVariables
60 
61  //exportFEMacro(macroName,macroSequence)
62 
63  var ADMIN_PERMISSION_THRESHOLD = 255;
64  var userPermission = 10;
65  var CMDHISTDIVINDEX = 0;
66  var SEQINDEX = 0;
67  var MACROINDEX = 0;
68  var FEELEMENTS = [];
69  var macroString = [];
70  var sortable;
71  var stringOfAllMacros = [];
72  var tempString = [];
73  var readoutDictionary = [];
74  var namesOfAllMacros = [];
75 
76  var theAddressStrForRead = ""; // for callread and its handler
77  var isOnMacroMakerPage = false;
78  var isOnPrivateMacros = false;
79  var timeIntervalID;
80  var isMacroRunning = false;
81  var waitForCurrentCommandToComeBack = false;
82  var putReadResultInBoxFlag = false;
83  var runningMacroLSBF = 0; //0 = Don't care; 1 = no LSBF; 2 = yes LSBF
84  var SEQFORMAT = "hex";
85 
86  var arrayOfCommandsForEdit = [];
87  var oldMacroNameForEdit = "";
88  var newMacroNameForEdit = "";
89  var macroDateForEdit = "";
90  var macroNotesForEdit = "";
91 
92  var lastDeletedMacro = "";
93  var boxOfFreshVar = "";
94  var barWidth = 0;
95  var barIncrement = 0;
96 
97 
98  //=====================================================================================
99  function init()
100  {
101  Debug.log("init() was called");
102  DesktopContent.XMLHttpRequest("Request?RequestType=FElist","",FElistHandler);
103  DesktopContent.XMLHttpRequest("Request?RequestType=getPermission","",getPermissionHandler);
104  fecListDiv = document.getElementById('fecList');
105  macroLibDiv = document.getElementById('macroLib');
106  mainDiv = document.getElementById('main');
107 
108  progressbarOuterDiv = document.getElementById('progressBarOuter');
109  progressbarOuterDiv.style.display = "none"; //only show while macro is running
110 
111  historyDiv = document.getElementById('history');
112  sequenceDiv = document.getElementById('sequence');
113  makerDiv = document.getElementById('maker');
114  popupEditMacroDiv = document.getElementById('popupEditMacro');
115 
116  historybox = document.getElementById('historyContent');
117  sequencebox = document.getElementById('sequenceContent');
118  privateMacroBox = document.getElementById('listOfPrivateMacros');
119  publicMacroBox = document.getElementById('listOfPublicMacros');
120  window.onresize = redrawWindow;
121  redrawWindow(); //redraw window for the first time
122  loadExistingMacros();
123  loadUserHistory();
124  toggleDisplay(0);
125  toggleMacroPublicity(0);
126  }
127 
128  //=====================================================================================
129  //This is what refresh button and redrawWindow() calls
130  function initLite()
131  {
132  DesktopContent.XMLHttpRequest("Request?RequestType=FElist","",
133  FElistHandler);
134  loadUserHistory();
135  }
136 
137  //=====================================================================================
138  //Handling window resizing
139  function redrawWindow()
140  {
141  Debug.log("Window redraw to " + window.innerWidth + " - " + window.innerHeight);
142 
143  var w = window.innerWidth;
144  var h = window.innerHeight;
145  if(w < 550){
146  w = 550;
147  }
148 
149  //square [x,y] [w,h]
150  var _MARGIN = 5;
151 
152  var b1 = [_MARGIN, _MARGIN+4*_MARGIN, w/3, h/2-_MARGIN]; //left top
153  var b2 = [_MARGIN, h/2+2*_MARGIN, w/3-_MARGIN, h/2-_MARGIN]; //left bottom
154  var b3 = [w/3, _MARGIN+4*_MARGIN, w/3, h/2-_MARGIN]; //top middle
155  var b4 = [w/3, h/2+2*_MARGIN, w/3, h/2-_MARGIN]; //bottom middle
156  var b5 = [w*2/3,_MARGIN+4*_MARGIN,w/3-_MARGIN, h-2*_MARGIN]; //right
157  var b6 = [_MARGIN, _MARGIN+4*_MARGIN,w/3-2*_MARGIN, h-2*_MARGIN]; //left
158  var b7 = [w/3, _MARGIN+4*_MARGIN, w/3, h/2-_MARGIN];//middle
159  var b8 = [w/2-200,h/5,2*w/3,3*h/5+15];//popup
160 
161  // fecListDiv.style.left = b1[0] + "px";
162  // fecListDiv.style.top = b1[1] + "px";
163  // fecListDiv.style.width = b1[2] + "px";
164  // fecListDiv.style.height = b1[3] + "px";
165 
166  // macroLibDiv.style.left = b2[0] + "px";
167  // macroLibDiv.style.top = b2[1] + "px";
168  // macroLibDiv.style.width = b2[2] + "px";
169  // macroLibDiv.style.height = b2[3] + "px";
170 
171  // mainDiv.style.left = b3[0] + "px";
172  // mainDiv.style.top = b3[1] + "px";
173  // mainDiv.style.width = b3[2] + "px";
174  // mainDiv.style.height = b3[3] + "px";
175 
176  // progressbarOuterDiv.style.left = b4[0] + "px";
177  // progressbarOuterDiv.style.top = b4[1] + "px";
178  // progressbarOuterDiv.style.width = b4[2] + "px";
179  // progressbarOuterDiv.style.height = b4[3] + "px";
180 
181  // historyDiv.style.left = b5[0] + "px";
182  // historyDiv.style.top = b5[1] + "px";
183  // historyDiv.style.width = b5[2] + "px";
184  // historyDiv.style.height = b5[3] + "px";
185 
186  // sequenceDiv.style.left = b6[0] + "px";
187  // sequenceDiv.style.top = b6[1] + "px";
188  // sequenceDiv.style.width = b6[2] + "px";
189  // sequenceDiv.style.height = b6[3] + "px";
190 
191  // makerDiv.style.left = b7[0] + "px";
192  // makerDiv.style.top = b7[1] + "px";
193  // makerDiv.style.width = b7[2] + "px";
194  // makerDiv.style.height = b7[3] + "px";
195 
196  popupEditMacroDiv.style.left = b8[0] + "px";
197  popupEditMacroDiv.style.top = b8[1] + "px";
198  popupEditMacroDiv.style.height = b8[3] + "px";
199 
200  historybox.style.height = (h-_MARGIN*2-54) + "px"; //h*0.88 + "px";
201  sequencebox.style.height = (h-_MARGIN*2-54) + "px"; //h*0.88 + "px";
202  privateMacroBox.style.height = (h/2-_MARGIN*2-54-2) + "px"; //h*0.38 + "px";
203  publicMacroBox.style.height = (h/2-_MARGIN*2-54-2) + "px"; //h*0.38 + "px";
204 
205  initLite();
206  }
207 
208  //=====================================================================================
209  function FElistHandler(req)
210  {
211  Debug.log("FElistHandler() was called. ");//Req: " + req.responseText);
212 
213  FEELEMENTS = req.responseXML.getElementsByTagName("FE");
214  var listoffecs = document.getElementById('list');
215  if(FEELEMENTS.length === 0)
216  listoffecs.innerHTML = "<p class='red'>" +
217  "<br>No Front-End interfaces were found. <br><br>Otsdaq must be configured with Front-ends, then " +
218  "click " +
219  "<a href='#' onclick='initLite(); return false;' >refresh</a>" +
220  " (also in the upper-right of Macro Maker).</p>";
221  else
222  {
223  //get width of multiselect text
224  var w = document.getElementById("fecList").offsetWidth - 76;//window.innerWidth;
225  w /= 7; //divide by letter width to get number of letters allowed
226  w -= 3; //to account for elipsis ...
227 
228  //Make search box for the list
229  var noMultiSelect = false;
230 
231  var keys = [];
232  var vals = [];
233  var types = [];
234  var fullnames = [];
235 
236  //Only displays the first 11 letters, mouse over display full name
237  for(var i=0;i<FEELEMENTS.length;++i)
238  {
239  keys[i] = "one";
240  fullnames[i] = FEELEMENTS[i].getAttribute("value");
241  var sp = fullnames[i].split(":");
242 
243 
244  display = sp[2] + ":" + sp[0] + ":" + sp[1];
245 
246  if(display.length > w)
247  display = display.substr(0,w-4) + "..." + display.substr(display.length - 4);
248 
249  vals[i] = "<abbr title='" + (sp[2] + ":" + sp[0] + ":" + sp[1]) + "'>"+display+"</abbr>";
250 
251 // if (sp[0].length < 11)
252 // vals[i] = sp[2] + ":" + sp[0] + ":" + sp[1]; //fullnames[i];
253 // else
254 // {
255 // var display;
256 // if (w < 680)
257 // display = sp[2] + ":" + sp[0].substr(0,4)+"...:"+sp[1];
258 // else if (w < 810)
259 // display = sp[2] + ":" + sp[0].substr(0,8)+"...:"+sp[1];
260 // else if (w < 1016)
261 // display = sp[2] + ":" + sp[0].substr(0,12)+"...:"+sp[1];
262 // else
263 // display = sp[2] + ":" + sp[0] + ":" + sp[1];
264 // vals[i] = "<abbr title='" + fullnames[i] + "'>"+display+"</abbr>";
265 // }
266  types[i] = "number";
267  Debug.log(vals[i]);
268  }
269  listoffecs.innerHTML = "";
270  MultiSelectBox.createSelectBox(listoffecs,
271  "box1",
272  "Please select from below:",
273  vals,keys,types,"listSelectionHandler",noMultiSelect,
274  0,//mouseOverHandler,
275  0,//iconURLs,
276  0,//mouseDownHandler,
277  0,//mouseUpHandler,
278  true,//requireCtrlMultiClick
279  0 //titles
280  );
281  //End of making box
282  }
283 
284  MultiSelectBox.initMySelectBoxes();
285  }
286 
287  //=====================================================================================
288  function getPermissionHandler(req)
289  {
290  Debug.log("getPermissionHandler() was called. ");//Req: " + req.responseText);
291 
292  userPermission = DesktopContent.getXMLValue(req, "Permission");
293  console.log("User Permission: " + userPermission);
294  }
295 
296  //=====================================================================================
297  function listSelectionHandler(listoffecs)
298  {
299  var splits = listoffecs.id.split('_');
300  elementIndex = splits[splits.length-1] | 0;
301  MultiSelectBox.dbg("Chosen element index:",elementIndex);
302  }
303 
304  //=====================================================================================
305  function callWrite(address,data)
306  {
307  var reminderEl = document.getElementById('reminder');
308  if(isArrayAllZero(selected))
309  Debug.log("Please select at least one interface from the list",Debug.HIGH_PRIORITY);
310  else
311  {
312  var addressFormatStr = document.getElementById("addressFormat").value;
313  var dataFormatStr = document.getElementById("dataFormat").value;
314  if(isMacroRunning == true)
315  {
316  addressFormatStr = "hex";
317  dataFormatStr = "hex";
318  }
319 
320  if (typeof address === 'undefined')
321  {
322  var addressStr = document.getElementById('addressInput').value.toString();
323  var dataStr = document.getElementById('dataInput').value.toString();
324  if(addressStr == "")
325  {
326  reminderEl.innerHTML = "Please enter an address to write to";
327  return;
328  }
329  else if(dataStr == "")
330  {
331  reminderEl.innerHTML = "Please enter your data";
332  return;
333  }
334  }
335  else
336  {
337  var addressStr = address.toString();
338  var dataStr = data.toString();
339  }
340 
341  if (addressStr.substr(0,2)=="0x") addressStr = addressStr.substr(2);
342  if (dataStr.substr(0,2)=="0x") dataStr = dataStr.substr(2);
343 
344  var selectionStrArray = [];
345  var supervisorIndexArray = [];
346  var interfaceIndexArray = [];
347  for (var i = 0; i < selected.length; i++)
348  {
349  if (selected[i]!==0)
350  {
351  var oneInterface = FEELEMENTS[i].getAttribute("value")
352  selectionStrArray.push(oneInterface);
353  supervisorIndexArray.push(oneInterface.split(":")[1]);
354  interfaceIndexArray.push(oneInterface.split(":")[2]);
355  }
356  }
357  var contentEl = document.getElementById('historyContent');
358  var innerClass = "class=\"innerClass1\"";
359  if (CMDHISTDIVINDEX%2) innerClass = "class=\"innerClass2\"";
360 
361  var reverse = document.getElementById("lsbFirst").checked;
362  if(runningMacroLSBF == 1) reverse = true;
363  if(runningMacroLSBF == 2) reverse = false;
364 
365  var update = "<div " + innerClass + " id = \"" + CMDHISTDIVINDEX + "\" title=\"" + "Entered: "
366  + Date().toString() + "\nSelected interface: " + selectionStrArray
367  + "\" onclick=\"histCmdWriteDivOnclick(" + "'" + addressStr + "','" + dataStr + "','"
368  + addressFormatStr + "','" + dataFormatStr + "')\">Write [" + dataFormatStr + "] <b>"
369  + dataStr + LSBchecker(reverse) + "</b> into register [" + addressFormatStr + "] <b> "
370  + addressStr + LSBchecker(reverse) + "</b></div>";
371 
372 
373  var convertedAddress = reverseLSB(convertToHex(addressFormatStr,addressStr),reverse);
374  var convertedData = reverseLSB(convertToHex(dataFormatStr,dataStr),reverse);
375 
376  DesktopContent.XMLHttpRequest("Request?RequestType=writeData" +
377  "&Address=" + convertedAddress +
378  "&Data=" + convertedData +
379  "&supervisorIndex=" + supervisorIndexArray +
380  "&interfaceIndex=" + interfaceIndexArray +
381  "&time=" + Date().toString() +
382  "&addressFormatStr=" + addressFormatStr +
383  "&dataFormatStr=" + dataFormatStr,
384  //post data
385  "interfaces=" + selectionStrArray,
386  writeHandler);
387  contentEl.innerHTML += update;
388  CMDHISTDIVINDEX++;
389  contentEl.scrollTop = contentEl.scrollHeight;
390  reminderEl.innerHTML = "Data successfully written!";
391  }
392  }
393 
394  //=====================================================================================
395  function callRead(address)
396  {
397  var reminderEl = document.getElementById('reminder');
398  if(isArrayAllZero(selected))
399  Debug.log("Please select at least one interface from the list",Debug.HIGH_PRIORITY);
400  else
401  {
402  var addressFormatStr = document.getElementById("addressFormat").value;
403  var dataFormatStr = document.getElementById("dataFormat").value;
404 
405  if (typeof address === 'undefined')
406  {
407  theAddressStrForRead = document.getElementById('addressInput').value.toString();
408  if(theAddressStrForRead === "")
409  {
410  reminderEl.innerHTML = "Please enter an address to read from";
411  return;
412  }
413  }
414  else
415  theAddressStrForRead = address.toString();
416 
417  if (theAddressStrForRead.substr(0,2)=="0x") theAddressStrForRead = theAddressStrForRead.substr(2);
418 
419  var selectionStrArray = [];
420  var supervisorIndexArray = [];
421  var interfaceIndexArray = [];
422  for (var i = 0; i < selected.length; i++)
423  {
424  if (selected[i]!==0)
425  {
426  var oneInterface = FEELEMENTS[i].getAttribute("value");
427  if (selected[i]!==0) selectionStrArray.push(FEELEMENTS[i].getAttribute("value"));
428  supervisorIndexArray.push(oneInterface.split(":")[1]);
429  interfaceIndexArray.push(oneInterface.split(":")[2]);
430  }
431  }
432  var reverse = document.getElementById("lsbFirst").checked;
433  if(runningMacroLSBF == 1) reverse = true;
434  if(runningMacroLSBF == 2) reverse = false;
435 
436  var convertedAddress = reverseLSB(convertToHex(addressFormatStr,theAddressStrForRead),reverse);
437 
438  DesktopContent.XMLHttpRequest("Request?RequestType=readData" +
439  "&Address=" + convertedAddress +
440  "&supervisorIndex=" + supervisorIndexArray +
441  "&interfaceIndex=" + interfaceIndexArray +
442  "&time=" + Date().toString() +
443  "&addressFormatStr=" + addressFormatStr +
444  "&dataFormatStr=" + dataFormatStr,
445  //post data
446  "interfaces=" + selectionStrArray,
447  readHandler);
448  }
449  }
450 
451  //=====================================================================================
452  function toggleReadBitField(fromLink)
453  {
454  var el = document.getElementById("enableReadBitField");
455  if(fromLink)
456  el.checked = !el.checked;
457 
458  var val = el.checked;
459 
460  Debug.log("checkbox val " + val);
461  document.getElementById("readBitFieldTable").style.display = val?"block":"none";
462  }
463 
464  //=====================================================================================
465  function writeHandler(req)
466  {
467  Debug.log("writeHandler() was called.");// Req: ");//" + req.responseText);
468 
469  var runningPercentageEl = document.getElementById('macroRunningPercentage');
470  var barEl = document.getElementById('macroRunningBar');
471  barWidth += barIncrement;
472  barEl.style.width = barWidth + '%';
473  runningPercentageEl.innerHTML = Math.round(barWidth*10)/10 + '%';
474  waitForCurrentCommandToComeBack = false;
475 
476  }
477 
478  //=====================================================================================
479  function readHandler(req)
480  {
481  Debug.log("readHandler() was called.");// Req: " + req.responseText);
482 
483  var addressFormatStr = document.getElementById("addressFormat").value;
484  var dataFormatStr = document.getElementById("dataFormat").value;
485  var extractBitField = document.getElementById("enableReadBitField").checked && !isMacroRunning;
486 
487  if(isMacroRunning == true)
488  {
489  addressFormatStr = "hex";
490  dataFormatStr = "hex";
491  }
492 
493  var reminderEl = document.getElementById('reminder');
494 
495  var dataOutput = DesktopContent.getXMLValue(req,"readData");
496  if(putReadResultInBoxFlag) boxOfFreshVar = dataOutput;
497 
498  var convertedOutput;
499 
500  var reverse = document.getElementById("lsbFirst").checked;
501  if(runningMacroLSBF == 1) reverse = true;
502  if(runningMacroLSBF == 2) reverse = false;
503 
504  var argOutput;
505  if (isNaN("0x"+dataOutput))
506  {
507  convertedOutput = "<span class='red'>" + dataOutput + "</span>";
508  argOutput = "";
509  }
510  else
511  {
512  convertedOutput = convertFromHex(dataFormatStr,reverseLSB(dataOutput,reverse),extractBitField);
513  argOutput = convertedOutput;
514  }
515 
516  var selectionStrArray = [];
517  for (var i = 0; i < selected.length; i++)
518  {
519  if (selected[i]!==0) selectionStrArray.push(FEELEMENTS[i].getAttribute("value"));
520  }
521  var innerClass = "class=\"innerClass1\"";
522  if (CMDHISTDIVINDEX%2) innerClass = "class=\"innerClass2\"";
523  var contentEl = document.getElementById('historyContent');
524 
525  var update = "<div " + innerClass + " id = \"" + CMDHISTDIVINDEX + "\" title=\"" + "Entered: " + Date().toString()
526  + "\nSelected interface: " + selectionStrArray + "\" onclick=\"histCmdReadDivOnclick(" +
527  "'" + theAddressStrForRead + "','" + argOutput + "'" +
528  ",'" + addressFormatStr + "','" + dataFormatStr + "'" +
529  ")\">Read [" + dataFormatStr + "] <b>"
530  + convertedOutput + LSBchecker(reverse)
531  + "</b> from register [" + addressFormatStr + "]<b>" +
532  theAddressStrForRead + LSBchecker(reverse) + "</b></div>";
533 
534  theAddressStrForRead = "";
535  contentEl.innerHTML += update;
536  CMDHISTDIVINDEX++;
537  contentEl.scrollTop = contentEl.scrollHeight;
538  reminderEl.innerHTML = "Data read: " + convertedOutput;
539  var runningPercentageEl = document.getElementById('macroRunningPercentage');
540  var barEl = document.getElementById('macroRunningBar');
541  barWidth += barIncrement;
542  barEl.style.width = barWidth + '%';
543  runningPercentageEl.innerHTML = Math.round(barWidth*10)/10 + '%';
544  waitForCurrentCommandToComeBack = false;
545  }
546 
547  //=====================================================================================
548  function isArrayAllZero(arr)
549  {
550  for(var j = 0; j < arr.length; j++)
551  {
552  if (arr[j]!==0) return false;
553  }
554  return true;
555  }
556 
557  //=====================================================================================
558  function convertToHex(format,target)
559  {
560  switch (format)
561  {
562  case "hex":
563  return target;
564  case "dec": //dec
565  return Number(target).toString(16);
566  case "ascii": //ascii
567  var output = [];
568  for(var i = target.length-1; i>=0; i--)
569  output.push(target.charCodeAt(i).toString(16));
570  return output.join('');
571  }
572  }
573 
574  //=====================================================================================
575  function convertFromHex(format,target,extractBitField)
576  {
577  if(extractBitField)
578  {
579  Debug.log("Extracting Bit-Field");
580  var startPos = document.getElementById("readBitFieldStartPos").value | 0;
581  var fieldSz = document.getElementById("readBitFieldLength").value | 0;
582  Debug.log("Extracting Bit-Field start/size = " + startPos + " / " + fieldSz);
583 
584  while(((startPos/4)|0) && target.length)
585  {
586  target = target.substr(0,target.length-1); //shift by 4 bits right
587  Debug.log("div4 target " + target);
588  startPos -= 4; //moved 4 bits
589  }
590 
591  Debug.log("target " + target);
592 
593  var size = Math.ceil((startPos+fieldSz)/4);
594  target = target.substr(target.length-size);
595 
596  Debug.log("sized target " + target);
597 
598  if(target.length == 0) target = "0";
599 
600 
601  //target should be shifted for bit manipulations
602  var num = parseInt(target,16);
603  Debug.log("num " + num);
604 
605  var mask = 0;
606  for(var i=0;i<fieldSz;++i)
607  mask |= (1<<i);
608  Debug.log("mask " + mask);
609  num = (num >> startPos) & mask;
610 
611  Debug.log("final num " + num);
612  target = num.toString(16).toUpperCase(); //return to hex number
613 
614  Debug.log("final target " + target);
615  }
616 
617  switch(format)
618  {
619  case "hex":
620  return target;
621  case "dec":
622  return parseInt(target,16).toString();
623  case "ascii":
624  var str = '';
625  for (var i = 0; i < target.length; i += 2)
626  str += String.fromCharCode(parseInt(target.substr(i, 2), 16));
627  return str;
628  }
629  }
630 
631  //=====================================================================================
632  function reverseLSB(original, execute)
633  {
634  if(execute)
635  {
636  var str = '';
637  if(original.length%2)
638  original = "0"+original;
639  for (var i = original.length-2; i > -2; i -= 2)
640  str += original.substr(i,2);
641  return str;
642  }
643  else return original;
644  }
645 
646  //=====================================================================================
647  function LSBchecker(LSBF)
648  {
649  if(LSBF) return "*";
650  else return "";
651  }
652 
653  //=====================================================================================
654  // The function below sets dynamic styling for the elements on the MacroMaker html page
655  function toggleDisplay(onMacro)
656  {
657  var fecListEl = document.getElementById("fecList");
658  var macroLibEl = document.getElementById("macroLib");
659  var sequenceEl = document.getElementById("sequence");
660  var progressBarOuterEl = document.getElementById("progressBarOuter");
661  var mainEl = document.getElementById("main");
662  var makerEl = document.getElementById("maker");
663 
664  if (onMacro) {
665  isOnMacroMakerPage = true;
666  fecListEl.style.display = "none";
667  macroLibEl.style.display = "none";
668  sequenceEl.style.display = "block";
669  progressBarOuterEl.style.display = "none";
670  mainEl.style.display = "none";
671  makerEl.style.display = "block";
672  document.getElementById("page2tag").style.backgroundColor = "#8A2A2B";
673  document.getElementById("page1tag").style.backgroundColor = "#333";
674 
675  }
676  else
677  {
678  isOnMacroMakerPage = false;
679  fecListEl.style.display = "block";
680  macroLibEl.style.display = "block";
681  sequenceEl.style.display = "none";
682  progressBarOuterEl.style.display = "none";
683  mainEl.style.display = "block";
684  makerEl.style.display = "none";
685  document.getElementById("page1tag").style.backgroundColor = "#8A2A2B";
686  document.getElementById("page2tag").style.backgroundColor = "#333";
687 
688  }
689  }
690 
691  //=====================================================================================
692  function toggleMacroPublicity(onPublic)
693  {
694  var privateEl = document.getElementById("listOfPrivateMacros");
695  var publicEl = document.getElementById("listOfPublicMacros");
696  if(onPublic) {
697  privateEl.style.display = "none";
698  publicEl.style.display = "block";
699  // document.getElementById("publicTag").style.fontWeight = "900";
700  // document.getElementById("privateTag").style.fontWeight = "400";
701  // document.getElementById("publicTag").style.background = "#002a52";
702  // document.getElementById("privateTag").style.background = "#001626";
703 
704  isOnPrivateMacros = false;
705  }
706  else
707  {
708  privateEl.style.display = "block";
709  publicEl.style.display = "none";
710  // document.getElementById("privateTag").style.fontWeight = "900";
711  // document.getElementById("publicTag").style.fontWeight = "400";
712  // document.getElementById("privateTag").style.background = "#002a52";
713  // document.getElementById("publicTag").style.background = "#001626";
714 
715  isOnPrivateMacros = true;
716  }
717  }
718 
719  //=====================================================================================
720  function addCommand(command,address,data)//either has address+data, or have no address/data. # of parameters = 1 or 3
721  {
722  var contentEl = document.getElementById('sequenceContent');
723  var macroReminderEl = document.getElementById('macroReminder');
724  macroReminderEl.innerHTML = "";
725  var formatMarkerHead, formatMarkerTail = "";
726  if(SEQFORMAT == "hex") formatMarkerHead = "0x";
727  else if(SEQFORMAT == "ascii")
728  {
729  formatMarkerHead = "\"";
730  formatMarkerTail = "\"";
731  }
732  else
733  {
734  formatMarkerHead = "";
735  formatMarkerTail = "";
736  }
737  switch(command)
738  {
739  case 'w':
740  if (typeof address === 'undefined')
741  {
742  var addressStrBefore = document.getElementById('macroAddressInput').value.toString();
743  var dataStrBefore = document.getElementById('macroDataInput').value.toString();
744  if(addressStrBefore === "")
745  {
746  macroReminderEl.innerHTML = "Please enter an address to write to";
747  return;
748  }
749  else if(dataStrBefore === "")
750  {
751  macroReminderEl.innerHTML = "Please enter your data";
752  return;
753  }
754  var addressFormatStr = document.getElementById("macroAddressFormat").value;
755  var dataFormatStr = document.getElementById("macroDataFormat").value;
756  var reverse = document.getElementById("lsbFirst").checked;
757  var addressStr = reverseLSB(convertToHex(addressFormatStr,addressStrBefore),reverse);
758  var dataStr = reverseLSB(convertToHex(dataFormatStr,dataStrBefore),reverse);
759  }
760  else
761  {
762  var addressStr = address.toString();
763  var dataStr = data.toString();
764  }
765  var update = "<div id = \"seq" + SEQINDEX + "\" data-id =" + SEQINDEX
766  + " onmouseout=\"hideDeletex(" + SEQINDEX + ")\" onmouseover=\"showDeletex("
767  + SEQINDEX + ")\" ondragstart=\"hideDeletex(" + SEQINDEX
768  + ")\" ondragend=\"getOrder()\" class=\"seqDiv\"><p class=\"insideSEQ textSEQ\">Write <b>"
769  + formatMarkerHead + convertFromHex(SEQFORMAT,dataStr) + formatMarkerTail + "</b> into <b>"
770  + formatMarkerHead + convertFromHex(SEQFORMAT,addressStr) + formatMarkerTail
771  + "</b></p><img src=\"/WebPath/images/windowContentImages/macromaker-delete.png\" id=\"deletex"
772  + SEQINDEX + "\" class=\"insideSEQ deletex\" onclick=\"removeCommand("
773  + SEQINDEX + ")\"></></div>";
774  var writeMacroString = SEQINDEX + ":w:" + addressStr + ":" + dataStr;
775  macroString.push(writeMacroString);
776  break;
777  case 'r':
778  if (typeof address === 'undefined')
779  {
780  var addressStrBefore = document.getElementById('macroAddressInput').value.toString();
781  if(addressStrBefore === "")
782  {
783  macroReminderEl.innerHTML = "Please enter an address to read from";
784  return;
785  }
786  var addressFormatStr = document.getElementById("macroAddressFormat").value;
787  var reverse = document.getElementById("lsbFirst").checked;
788  var addressStr = reverseLSB(convertToHex(addressFormatStr,addressStrBefore),reverse);
789  }
790  else var addressStr = address.toString();
791  var update = "<div id = \"seq" + SEQINDEX + "\" data-id =" + SEQINDEX
792  + " onmouseout=\"hideDeletex(" + SEQINDEX + ")\" onmouseover=\"showDeletex("
793  + SEQINDEX + ")\" ondragstart=\"hideDeletex(" + SEQINDEX
794  + ")\" ondragend=\"getOrder()\" class=\"seqDiv\"><p class=\"insideSEQ\">Read from <b>"
795  + formatMarkerHead + convertFromHex(SEQFORMAT,addressStr) + formatMarkerTail
796  + "</b></p><img src=\"/WebPath/images/windowContentImages/macromaker-delete.png\" id=\"deletex"
797  + SEQINDEX + "\" class=\"insideSEQ deletex\" onclick=\"removeCommand("
798  + SEQINDEX + ")\"></></div>";
799  var readMacroString = SEQINDEX+":r:"+addressStr+":";
800  macroString.push(readMacroString);
801  break;
802  case 'd':
803  if (typeof address === 'undefined') //adding from Sequence Maker
804  {
805  var delayStr = document.getElementById('delayInput').value.toString();
806  if(delayStr === "")
807  {
808  macroReminderEl.innerHTML = "Please enter a delay";
809  return;
810  }
811  else if (isNaN(delayStr))
812  {
813  macroReminderEl.innerHTML = "Delay has to be a numerical number";
814  return;
815  }
816  if(document.getElementById("delayUnit").value === "s") delayStr = Number(delayStr)*1000;
817 
818  }
819  else // adding from Command History
820  var delayStr = address.toString();
821  var update = "<div id = \"seq" + SEQINDEX + "\" data-id =" + SEQINDEX
822  + " onmouseout=\"hideDeletex(" + SEQINDEX + ")\" onmouseover=\"showDeletex("
823  + SEQINDEX + ")\" ondragstart=\"hideDeletex(" + SEQINDEX
824  + ")\" ondragend=\"getOrder()\" class=\"seqDiv\"><p class=\"insideSEQ\">Delay <b>"
825  + delayStr + "</b> ms</p><img src=\"/WebPath/images/windowContentImages/macromaker-delete.png\" id=\"deletex"
826  + SEQINDEX + "\" class=\"insideSEQ deletex\" onclick=\"removeCommand(" + SEQINDEX
827  + ")\"></></div>";
828  var delayMacroString = SEQINDEX+":d:"+delayStr;
829  macroString.push(delayMacroString);
830  break;
831  default:
832  Debug.log("So if it's not write, read, or delay, what is it??");
833  }
834  contentEl.innerHTML += update;
835  SEQINDEX++;
836  contentEl.scrollTop = contentEl.scrollHeight;
837  sortable = Sortable.create(contentEl,{
838  chosenClass: 'chosenClassInSequence',
839  ghostClass:'ghostClassInSequence'
840  });//Works like magic!
841  getOrder();
842  }
843 
844  //=====================================================================================
845  function hideDeletex(seqIndex)
846  {
847  var deleteID = "deletex"+seqIndex;
848  document.getElementById(deleteID).style.display = "none";
849  }
850 
851  //=====================================================================================
852  function showDeletex(seqIndex)
853  {
854  var deleteID = "deletex"+seqIndex;
855  var deleteEl = document.getElementById(deleteID);
856  deleteEl.style.top = (deleteEl.parentNode.offsetTop + 1) + "px";
857  deleteEl.style.left = (deleteEl.parentNode.offsetLeft +
858  deleteEl.parentNode.offsetWidth - 20) + "px";
859  deleteEl.style.display = "block";
860  }
861 
862  //=====================================================================================
863  function getOrder()
864  {
865  tempString = [];
866  var order = sortable.toArray();
867  //copy and sort indices
868  var sorting = order.slice();
869  sorting.sort(function(a,b){ return a-b;}); //to sort in numeric-increasing order
870 
871  //get the possibly-reordered index out of macro string
872  for(var i = 0; i < macroString.length; i++)
873  tempString.push(macroString[sorting.indexOf(order[i])]);
874  }
875 
876  //=====================================================================================
877  function removeCommand(seqIndex)
878  {
879  document.getElementById("undoDelete").disabled = false;
880  var child = document.getElementById("seq"+seqIndex);
881  var parent = document.getElementById('sequenceContent');
882  parent.removeChild(child);
883  for (var i = 0; i < macroString.length; i++)
884  {
885  if (seqIndex == macroString[i].split(":")[0])
886  {
887  lastDeletedMacro = macroString[i];
888  macroString.splice(i,1);
889  }
890  }
891  getOrder();
892  }
893 
894  //=====================================================================================
895  function undoDelete()
896  {
897  addCommand(lastDeletedMacro.split(":")[1],lastDeletedMacro.split(":")[2],lastDeletedMacro.split(":")[3]);
898  document.getElementById("undoDelete").disabled = true;
899  }
900 
901  //=====================================================================================
902  function showPopupClearAllConfirm()
903  {
904  var popupClearAllConfirm = document.getElementById("popupClearAllConfirm");
905  popupClearAllConfirm.style.display = "block";
906  }
907 
908  //=====================================================================================
909  function showPopupClearHistoryConfirm()
910  {
911  var popupClearAllConfirm = document.getElementById("popupClearHistoryConfirm");
912  popupClearAllConfirm.style.display = "block";
913  }
914 
915  //=====================================================================================
916  function clearAll(el)
917  {
918  var contentEl = document.getElementById('sequenceContent');
919  contentEl.innerHTML = "";
920  macroString = [];
921  hideSmallPopup(el);
922  }
923 
924  //=====================================================================================
925  function clearHistory(el)
926  {
927  DesktopContent.XMLHttpRequest("Request?RequestType=clearHistory","",clearHistoryHandler);
928  var contentEl = document.getElementById('historyContent');
929  contentEl.innerHTML = "";
930  hideSmallPopup(el);
931  }
932 
933  //=====================================================================================
934  function clearHistoryHandler(req)
935  {
936  Debug.log("clearHistoryHandler() was called.");// Req: " + req.responseText);
937 
938  loadUserHistory();
939  }
940 
941  //=====================================================================================
942  function hideSmallPopup(el)
943  {
944  var wholeDiv = el.parentNode.parentNode.parentNode;
945  wholeDiv.style.display = "none";
946  }
947 
948  //=====================================================================================
949  function saveMacro()
950  {
951  if (macroString.length === 0)
952  document.getElementById('macroReminder').innerHTML = "Macro sequence cannot be empty";
953  else
954  {
955  document.getElementById("popupSaveMacro").style.display = "block";
956  if (userPermission == ADMIN_PERMISSION_THRESHOLD)
957  document.getElementById("makeMacroPublic").style.display = "block";
958  }
959  }
960 
961  //=====================================================================================
962  function hidePopupSaveMacro()
963  {
964  var popupSaveMacro = document.getElementById("popupSaveMacro");
965  popupSaveMacro.style.display = "none";
966  document.getElementById("macroName").value="";
967  document.getElementById("macroNotes").value="";
968  document.getElementById('macroReminder').innerHTML = "Macro successfully saved!";
969  }
970 
971  //=====================================================================================
972  function hidePopupEditMacro()
973  {
974  var popupEditMacro = document.getElementById("popupEditMacro");
975  popupEditMacro.style.display = "none";
976  arrayOfCommandsForEdit = [];
977  }
978 
979  //=====================================================================================
980  function saveAsMacro()
981  {
982  getOrder();
983  var macroName = document.getElementById("macroName").value;
984  //var Regex = /^[\w\s]+$/;
985  var Regex = /^[a-zA-Z0-9\_]+$/g;
986  if (!Regex.test(macroName))
987  document.getElementById("popupIllegalNaming").style.display = "block";
988  else
989  {
990  var macroNotes = document.getElementById("macroNotes").value;
991  if(macroNotes.indexOf("@") >= 0 || macroNotes.indexOf("#") >= 0 || macroNotes.indexOf("..") >= 0)
992  {
993  document.getElementById("popupIllegalNotes").style.display = "block";
994  return;
995  }
996  var macroLibEl = document.getElementById('listOfPrivateMacros');
997  stringOfAllMacros[MACROINDEX] = tempString;
998  var isMacroPublic = document.getElementById("isMacroPublic").checked;
999  var isMacroLSBF = document.getElementById("isMacroLSBF").checked;
1000 
1001  if(namesOfAllMacros.indexOf(macroName) !== -1) //duplicate name
1002  {
1003  document.getElementById("popupMacroAlreadyExists").style.display = "block";
1004  document.getElementById("duplicateName").innerHTML = macroName;
1005  document.getElementById("popupMacroAlreadyExistsCancel").onclick = function(){
1006  hideSmallPopup(this);
1007  return;
1008  };
1009 
1010  document.getElementById('popupMacroAlreadyExistsOverwrite').onclick = function(){ //call edit
1011  DesktopContent.XMLHttpRequest("Request?RequestType=editMacro" +
1012  "&isPublic=" + isMacroPublic +
1013  "&isLSBF=" + isMacroLSBF +
1014  //post data
1015  "oldMacroName=" + macroName +
1016  "&newMacroName=" + macroName +
1017  "&Sequence=" + tempString +
1018  "&Time=" + Date().toString() +
1019  "&Notes=" + encodeURIComponent(macroNotes),
1020  saveChangedMacroHandler /*handler*/,
1021  macroName /*parameter*/);
1022 
1023  hideSmallPopup(this);
1024  hidePopupSaveMacro();
1025  macroLibEl.scrollTop = macroLibEl.scrollHeight - macroLibEl.clientHeight;
1026  };
1027  }
1028  else
1029  {
1030  DesktopContent.XMLHttpRequest("Request?RequestType=createMacro" +
1031  "&isPublic="+isMacroPublic+
1032  "&isLSBF="+isMacroLSBF,
1033  //post data
1034  "Name=" + macroName +
1035  "&Sequence=" + tempString +
1036  "&Time=" + Date().toString() +
1037  "&Notes=" + encodeURIComponent(macroNotes),
1038  createMacroHandler /*handler*/,
1039  macroName /*parameter*/);
1040 
1041  hidePopupSaveMacro();
1042  macroLibEl.scrollTop = macroLibEl.scrollHeight - macroLibEl.clientHeight;
1043  }
1044  }
1045  } //end saveAsMacro()
1046 
1047  //=====================================================================================
1048  function createMacroHandler(req,macroName)
1049  {
1050  Debug.log("createMacroHandler() was called for " + macroName);// Req: " + req.responseText);
1051 
1052  Debug.log("Your Macro '" + macroName + "' was succesfully saved!",Debug.INFO_PRIORITY);
1053  loadExistingMacros();
1054 
1055  } //end createMacroHandler()
1056 
1057  //=====================================================================================
1058  function runMacro(stringOfCommands,macroName)
1059  {
1060  var contentEl = document.getElementById('historyContent');
1061  var progressBarInnerEl = document.getElementById('progressBarInner');
1062  var progressBarOuterEl = document.getElementById("progressBarOuter");
1063 
1064  var start = "<p class=\"red\"><b><small>-- Start of Macro: " + macroName + " --</small></b></p>";
1065  contentEl.innerHTML += start;
1066  contentEl.scrollTop = contentEl.scrollHeight;
1067 
1068  progressBarInnerEl.style.display = "block";
1069  progressBarOuterEl.style.display = "block";
1070  var barEl = document.getElementById('macroRunningBar');
1071  barEl.style.width = '0%';
1072  barIncrement = 100/stringOfCommands.length;
1073  var i = 0;
1074  var copyOfStringOfCommands = stringOfCommands.slice(); //Needed because the variable assignments are temporary
1075  timeIntervalID = setInterval(function(){
1076  if(!waitForCurrentCommandToComeBack)
1077  {
1078  if(i == stringOfCommands.length)
1079  {
1080  var end = "<p class=\"red\"><b><small>-- End of Macro: " + macroName + " --</small></b></p>";
1081  contentEl.innerHTML += end;
1082  contentEl.scrollTop = contentEl.scrollHeight;
1083  isMacroRunning = false;
1084  setTimeout(function(){
1085  progressBarInnerEl.style.display = "none";
1086  progressBarOuterEl.style.display = "none";
1087  }, 150);
1088  barWidth = 0;
1089  barIncrement = 0;
1090  runningMacroLSBF = 0;
1091  clearInterval(timeIntervalID);
1092  }
1093  else
1094  {
1095  var Command = copyOfStringOfCommands[i].split(":")
1096  var commandType = Command[1];
1097  if(commandType=='w'){
1098  callWrite(Command[2],Command[3]);
1099  waitForCurrentCommandToComeBack = true;
1100  }else if(commandType=='r'){
1101  if(readoutDictionary.indexOf(Command[3].toString()) !== -1) //check if Command[3] is a var!
1102  {
1103  if(boxOfFreshVar === "") //box is empty ????? not enough
1104  {
1105  putReadResultInBoxFlag = true;
1106  callRead(Command[2]) //flag for readResult
1107  waitForCurrentCommandToComeBack = true;
1108  i--;
1109  }
1110  else //only come in here to replace.
1111  {
1112  for(var j = i+1; j < copyOfStringOfCommands.length; j++) //take whatever is in the box
1113  {
1114  if(copyOfStringOfCommands[j].split(":")[2] == Command[3]) //replace everything in copyOfStringOfCommands
1115  {
1116  var newCommand = copyOfStringOfCommands[j].split(":");
1117  newCommand[2] = boxOfFreshVar;
1118  copyOfStringOfCommands[j] = newCommand.join(":");
1119  }
1120 
1121  if(copyOfStringOfCommands[j].split(":")[3] == Command[3])
1122  {
1123  var newCommand = copyOfStringOfCommands[j].split(":");
1124  newCommand[3] = boxOfFreshVar;
1125  copyOfStringOfCommands[j] = newCommand.join(":");
1126  }
1127  }
1128  boxOfFreshVar = ""; //dump the box empty
1129  putReadResultInBoxFlag = false;
1130  console.log("final command after 2nd replacement" + copyOfStringOfCommands);
1131  }
1132  }
1133  else
1134  {
1135  callRead(Command[2]);
1136  waitForCurrentCommandToComeBack = true;
1137  }
1138  }
1139  else if(commandType=='d'){
1140  waitForCurrentCommandToComeBack = true;
1141  setTimeout(function(){delay();},Number(Command[2]));
1142  function delay(){
1143  //delay handler here, does what read and write handlers do
1144  var contentEl = document.getElementById('historyContent');
1145  var innerClass = "class=\"innerClass1\"";
1146  if (CMDHISTDIVINDEX%2) innerClass = "class=\"innerClass2\"";
1147  var selectionStrArray = [];
1148  for (var i = 0; i < selected.length; i++)
1149  {
1150  if (selected[i]!==0) selectionStrArray.push(FEELEMENTS[i].getAttribute("value"));
1151  }
1152  var update = "<div " + innerClass + " id = \"" + CMDHISTDIVINDEX + "\" title=\"" + "Entered: " + Date().toString()
1153  + "\nSelected interface: " + selectionStrArray + "\" onclick=\"histCmdDelayDivOnclick(" + Command[2]
1154  + ")\">Delay <b>" + Command[2] + "</b> ms</div>";
1155  contentEl.innerHTML += update;
1156  contentEl.scrollTop = contentEl.scrollHeight;
1157  CMDHISTDIVINDEX++;
1158  var runningPercentageEl = document.getElementById('macroRunningPercentage');
1159  var barEl = document.getElementById('macroRunningBar');
1160  barWidth += barIncrement;
1161  barEl.style.width = barWidth + '%';
1162  runningPercentageEl.innerHTML = Math.round(barWidth*10)/10 + '%';
1163  waitForCurrentCommandToComeBack = false;
1164  }
1165  }else
1166  console.log("ERROR! Command type "+commandType+" not found");
1167  i++;
1168  }
1169  }
1170  },200);
1171  }
1172 
1173  //=====================================================================================
1174  function loadExistingMacros()
1175  {
1176  DesktopContent.XMLHttpRequest("Request?RequestType=loadMacros","",loadingMacrosHandler);
1177  }
1178 
1179  //=====================================================================================
1180  function loadUserHistory()
1181  {
1182  DesktopContent.XMLHttpRequest("Request?RequestType=loadHistory","",loadingHistHandler);
1183  }
1184 
1185  //=====================================================================================
1186  function loadingMacrosHandler(req)
1187  {
1188  Debug.log("loadingMacrosHandler() was called.");// Req: " + req.responseText);
1189 
1190  var hugeStringOfMacros = DesktopContent.getXMLValue(req,"returnMacroStr");
1191  var hugeStringOfPublicMacros = DesktopContent.getXMLValue(req,"returnPublicStr");
1192  namesOfAllMacros = [];
1193  if (hugeStringOfMacros && hugeStringOfMacros.length > 0)
1194  {
1195  var macrosArray = hugeStringOfMacros.split("@");
1196  var out = "";
1197  var finalOutput = "";
1198  for(var i = 0; i < macrosArray.length; i++)
1199  {
1200  var arr = JSON.parse(macrosArray[i]);
1201  namesOfAllMacros.push(arr.name);
1202  var macroString = arr.sequence.split(",");
1203  var forDisplay = []; //getting rid of the first element (macroIndex) for all and the last ";" of reads for display
1204  for (var j = 0; j < macroString.length; j++) //because users don't need to see that
1205  forDisplay.push(macroString[j].split(":").slice(1).filter(Boolean).join(":"));
1206 
1207  stringOfAllMacros[MACROINDEX] = macroString;
1208  out += "<div title='Sequence: " + forDisplay.join(",") + "\nNotes: "
1209  + arr.notes + "\nCreated: " + arr.time + "\nLSBF: " + arr.LSBF
1210  + "\' class='macroDiv' data-id=\"" + arr.name + "\" data-sequence=\""
1211  + macroString + "\" data-notes=\"" + arr.notes + "\" data-time=\""
1212  + arr.time + "\" data-LSBF=\"" + arr.LSBF
1213  + "\" onclick='dealWithVariables(stringOfAllMacros["
1214  + MACROINDEX + "],\"" + arr.name + "\",\"" + arr.LSBF + "\")'><b>" + arr.name + "</b></br></div>";
1215  MACROINDEX++;
1216  }
1217  //finalOutput = decodeURI(out);
1218  document.getElementById("listOfPrivateMacros").innerHTML = out;//finalOutput;
1219  }
1220  else
1221  document.getElementById("listOfPrivateMacros").innerHTML = "";
1222  if (hugeStringOfPublicMacros && hugeStringOfPublicMacros.length > 0)
1223  {
1224  var publicMacrosArray = hugeStringOfPublicMacros.split("@");
1225  var out = "";
1226  var finalOutput = "";
1227  for(var i = 0; i < publicMacrosArray.length; i++)
1228  {
1229  var arr = JSON.parse(publicMacrosArray[i]);
1230  namesOfAllMacros.push(arr.name);
1231  var macroString = arr.sequence.split(",");
1232  var forDisplay = []; //getting rid of the first element (macroIndex) for display
1233  for (var j = 0; j < macroString.length; j++)
1234  forDisplay.push(macroString[j].split(":").slice(1).filter(Boolean).join(":"));
1235 
1236  stringOfAllMacros[MACROINDEX] = macroString;
1237  out += "<div title='Sequence: " + forDisplay.join(",") + "\nNotes: "
1238  + arr.notes + "\nCreated: " + arr.time + "\nLSBF: " + arr.LSBF
1239  + "\' class='macroDiv' data-id=\"" + arr.name + "\" data-sequence=\""
1240  + macroString + "\" data-notes=\""
1241  + arr.notes + "\" data-time=\"" + arr.time
1242  + "\" data-LSBF=\"" + arr.LSBF
1243  + "\" onclick='dealWithVariables(stringOfAllMacros["
1244  + MACROINDEX + "],\"" + arr.name + "\",\"" + arr.LSBF + "\")'><b>" + arr.name + "</b></br></div>";
1245  //finalOutput = decodeURI(out);
1246  MACROINDEX++;
1247  }
1248  document.getElementById("listOfPublicMacros").innerHTML = out; //finalOutput;
1249  }
1250  else
1251  document.getElementById("listOfPublicMacros").innerHTML = "";
1252  console.log(namesOfAllMacros);
1253  }
1254 
1255  //=====================================================================================
1256  function loadingHistHandler(req)
1257  {
1258  Debug.log("loadingHistHandler() was called.");// Req: " + req.responseText);
1259 
1260  var hugeStringOfHistory = DesktopContent.getXMLValue(req,"returnHistStr");
1261  var contentEl = document.getElementById('historyContent');
1262  if ( !hugeStringOfHistory ) return; //this happens when history doesn't exist
1263 
1264  var commandHistArray = hugeStringOfHistory.split("#");
1265  var out = "";
1266  var finalOutPut = "";
1267  for(var i = 0; i < commandHistArray.length; i++)
1268  {
1269  var innerClass = "class=\"innerClass1\"";
1270  if (CMDHISTDIVINDEX%2) innerClass = "class=\"innerClass2\"";
1271 
1272  var arr = JSON.parse(commandHistArray[i]);
1273  var oneCommand = arr.Command.split(":");
1274  var commandType = oneCommand[0];
1275  var addressFormat = arr.Format.split(":")[0];
1276  var dataFormat = arr.Format.split(":")[1];
1277  var convertedAddress = convertFromHex(addressFormat,oneCommand[1]);
1278  var convertedData = convertFromHex(dataFormat,oneCommand[2]);
1279  if (isNaN('0x'+oneCommand[2]))
1280  {
1281  convertedData = "<span class='red'>" + oneCommand[2] + "</span>";
1282  argData = "";
1283  }
1284  else
1285  argData = convertedData;
1286 
1287  if(commandType=='w')
1288  {
1289  out = "<div " + innerClass + " id = \"" + CMDHISTDIVINDEX + "\" title=\"" + "Entered: "
1290  + arr.Time + "\nSelected interface: " + arr.Interfaces
1291  + "\" onclick=\"histCmdWriteDivOnclick(" + "'" + convertedAddress +
1292  "','" + argData + "','"
1293  + addressFormat + "','" + dataFormat + "')\">Write [" + dataFormat + "] <b>"
1294  + convertedData + "</b> into register [" + addressFormat + "] <b> "
1295  + convertedAddress + "</b></div>";
1296  finalOutPut += decodeURI(out);
1297  CMDHISTDIVINDEX++;
1298  }
1299  else if(commandType=='r')
1300  {
1301  out = "<div " + innerClass + " id = \"" + CMDHISTDIVINDEX + "\" title=\"" + "Entered: "
1302  + arr.Time + "\nSelected interface: " + arr.Interfaces + "\" onclick=\"histCmdReadDivOnclick(" +
1303  "'" + convertedAddress + "','" + argData + "'" +
1304  ",'" + addressFormat + "','" + dataFormat + "'" +
1305  ")\">Read [" + dataFormat + "] <b>"
1306  + convertedData + "</b> from register [" + addressFormat + "] <b>" + convertedAddress + "</b></div>";
1307  finalOutPut += decodeURI(out);
1308  CMDHISTDIVINDEX++;
1309  }
1310  else
1311  Debug.log("ERROR! Command type "+commandType+" not found", Debug.HIGH_PRIORITY);
1312 
1313  }
1314 
1315  contentEl.innerHTML = finalOutPut;
1316  contentEl.scrollTop = contentEl.scrollHeight;
1317  }
1318 
1319  function histCmdWriteDivOnclick(addressStr, dataStr, addressFormatStr, dataFormatStr)
1320  {
1321  var reverse = document.getElementById("lsbFirst").checked;
1322  var convertedAddress = reverseLSB(convertToHex(addressFormatStr,addressStr),reverse);
1323  var convertedData = reverseLSB(convertToHex(dataFormatStr,dataStr),reverse);
1324 
1325  //attempt to capture into input fields
1326  try
1327  {
1328  document.getElementById('addressInput').value = convertedAddress;
1329  document.getElementById('macroAddressInput').value = convertedAddress;
1330  document.getElementById('dataInput').value = convertedData;
1331  document.getElementById('macroDataInput').value = convertedData;
1332  }
1333  catch(e)
1334  {
1335  Debug.log("Error capturing address/data into input fields: " + e);
1336  }
1337 
1338 
1339  if(isOnMacroMakerPage)
1340  {
1341  addCommand("w",convertedAddress,convertedData);
1342  }
1343  else
1344  callWrite(addressStr, dataStr);
1345 
1346  } //end histCmdWriteDivOnclick()
1347 
1348  //=====================================================================================
1349  function histCmdReadDivOnclick(addressStr, outputStr,
1350  addressFormatStr, outputFormatStr)
1351  {
1352  var reverse = document.getElementById("lsbFirst").checked;
1353  var convertedAddress = reverseLSB(convertToHex(addressFormatStr,addressStr),reverse);
1354 
1355 
1356  //attempt to capture into input fields
1357  try
1358  {
1359  var convertedData = reverseLSB(convertToHex(outputFormatStr,outputStr),reverse);
1360 
1361  document.getElementById('addressInput').value = convertedAddress;
1362  document.getElementById('macroAddressInput').value = convertedAddress;
1363  document.getElementById('dataInput').value = convertedData;
1364  document.getElementById('macroDataInput').value = convertedData;
1365  }
1366  catch(e)
1367  {
1368  Debug.log("Error capturing address/data into input fields: " + e);
1369  }
1370 
1371  if(isOnMacroMakerPage)
1372  {
1373  addCommand("r",convertedAddress)
1374  }
1375  else
1376  callRead(addressStr);
1377 
1378  } //end histCmdReadDivOnclick()
1379 
1380  function histCmdDelayDivOnclick(delayStr)
1381  {
1382  if(isOnMacroMakerPage)
1383  {
1384  addCommand("d",delayStr);
1385  }
1386  else return;
1387  } //end histCmdDelayDivOnclick()
1388 
1389  function macroActionOnRightClick(macroName, macroAction, macroSequence, macroNotes, macroDate, macroLSBF)
1390  {
1391  Debug.log("macroName=" + macroName + " macroAction=" + macroAction +
1392  " macroSequence=" + macroSequence + " macroNotes=" + macroNotes +
1393  " macroDate=" + macroDate);
1394  var isMacroPublic = !isOnPrivateMacros;
1395  switch(macroAction)
1396  {
1397  case "Delete":
1398  if (userPermission != ADMIN_PERMISSION_THRESHOLD && isMacroPublic)
1399  document.getElementById("popupNoDeletePermission").style.display = "block";
1400  else
1401  {
1402  document.getElementById('popupDeleteMacroConfirm').style.display = "block";
1403  document.getElementById('macroNameForDelete').innerHTML = macroName;
1404  document.getElementById('popupDeleteMacroConfirmYes').onclick = function(){
1405  DesktopContent.XMLHttpRequest("Request?RequestType=deleteMacro" +
1406  "&isPublic=" + isMacroPublic +
1407  "&MacroName=" + macroName,
1408  //post data
1409  "",
1410  deleteMacroHandler);
1411  hideSmallPopup(this);
1412  };
1413  document.getElementById('popupDeleteMacroConfirmCancel').onclick = function(){hideSmallPopup(this)};
1414  }
1415  break;
1416  case "Edit":
1417  if (userPermission != ADMIN_PERMISSION_THRESHOLD && isMacroPublic)
1418  document.getElementById("popupNoEditPermission").style.display = "block";
1419  else
1420  {
1421  var popupEditMacro = document.getElementById("popupEditMacro");
1422  popupEditMacro.style.display = "block";
1423 
1424  oldMacroNameForEdit = macroName;
1425  macroNotesForEdit = macroNotes;
1426  macroDateForEdit = macroDate;
1427  var seqID = 0;
1428 
1429  var macroSequenceEditEl = document.getElementById("macroSequenceEdit");
1430  arrayOfCommandsForEdit = macroSequence.split(",");
1431  var output = "";
1432 
1433  for (var i = 0; i < arrayOfCommandsForEdit.length; i++)
1434  {
1435  var Command = arrayOfCommandsForEdit[i].split(":")
1436  var commandType = Command[1];
1437  var markColor = "1";
1438  var disable = "";
1439  var markColorData = "1";
1440  var disableData = "";
1441  var readResult = "...";
1442  if(commandType=='w'){
1443  if(isNaN('0x'+Command[2]))
1444  {
1445  markColor = "2";
1446  disable = "disabled";
1447  }
1448  if(isNaN('0x'+Command[3]))
1449  {
1450  markColorData = "2";
1451  disableData = "disabled";
1452  }
1453  var writeEdit = "<lable>Write <textarea " + disableData +
1454  " class=\"JStextarea\" onchange=\"editCommands(this," +
1455  seqID + ",3)\">" + Command[3]
1456  + "</textarea><div class='variableMark" + markColorData +
1457  "' title='Set field to variable' onclick='setFieldToVariable(this," + seqID
1458  + ",3)'>V</div> into address <textarea " + disable +
1459  " class=\"JStextarea\" onchange=\"editCommands(this," + seqID + ",2)\">" + Command[2]
1460  + "</textarea><div class='variableMark" + markColor + "' title='Set field to variable' onclick='setFieldToVariable(this," + seqID
1461  + ",2)'>V</div><br/></lable>";
1462  seqID++;
1463  output += writeEdit;
1464  }else if(commandType=='r'){
1465  if(isNaN('0x'+Command[2]))
1466  {
1467  markColor = "2";
1468  disable = "disabled";
1469  }
1470  if(Command[3] !== "")
1471  {
1472  markColorData = "2";
1473  readResult = Command[3];
1474  }
1475  var readEdit = "<lable>Read <textarea disabled class=\"JStextarea\" onchange=\"editCommands(this," + seqID + ",3)\">" + readResult
1476  + "</textarea><div class='variableMark" + markColorData + "' title='Set field to variable' onclick='setFieldToVariable(this," + seqID
1477  + ",3,1)'>V</div> from address <textarea " + disable + " class=\"JStextarea\" onchange=\"editCommands(this," + seqID + ",2)\">" + Command[2]
1478  + "</textarea><div class='variableMark" + markColor + "' title='Set field to variable' onclick='setFieldToVariable(this," + seqID
1479  + ",2)'>V</div><br/></lable>";
1480  seqID++;
1481  output += readEdit;
1482  }else if(commandType=='d'){
1483  if(isNaN(Command[2]))
1484  {
1485  markColor = "2";
1486  disable = "disabled";
1487  }
1488  var delayEdit = "<lable>Delay <textarea " + disable + " class=\"JStextarea\" onchange=\"editCommands(this," + seqID + ",2)\">" + Command[2]
1489  + "</textarea><div class='variableMark" + markColor + "' title='Set field to variable' onclick='setFieldToVariable(this," + seqID
1490  + ",2)'>V</div> milliseconds<br/></lable>";
1491  seqID++;
1492  output += delayEdit;
1493  }else
1494  console.log("ERROR! Command type "+commandType+" not found");
1495  }
1496  macroSequenceEditEl.innerHTML = output;
1497  if(macroLSBF == "true")
1498  document.getElementById("isMacroEditLSBF").checked = true;
1499  else
1500  document.getElementById("isMacroEditLSBF").checked = false;
1501 
1502 
1503  var macroNameEl = document.getElementById("macroNameEdit");
1504  macroNameEl.value = macroName;
1505  var macroNotesEl = document.getElementById("macroNotesEdit");
1506  var date = new Date();
1507  var minutes = "";
1508  if(date.getMinutes() < 10)
1509  minutes = "0"+date.getMinutes().toString();
1510  else minutes = date.getMinutes();
1511  var time = date.getHours() + ":" + minutes + " " + date.toLocaleDateString();
1512  macroNotesForEdit = "[Modified " + time + "] " + macroNotes;
1513  macroNotesEl.value = macroNotesForEdit;
1514  document.getElementById("editFormat").selectedIndex = 0;
1515  }
1516  break;
1517  case "Start":
1518  var sequenceContentEl = document.getElementById("sequenceContent");
1519  var temp = sequenceContentEl.innerHTML;
1520  sequenceContentEl.innerHTML = "";
1521  var arrayOfCommands = macroSequence.split(",");
1522  for (var i = 0; i < arrayOfCommands.length; i++)
1523  {
1524  var Command = arrayOfCommands[i].split(":");
1525  addCommand(Command[1],Command[2],Command[3]);
1526  }
1527  sequenceContentEl.innerHTML += temp;
1528  getOrder();
1529  toggleDisplay(1);
1530  break;
1531  case "End":
1532  var arrayOfCommands = macroSequence.split(",");
1533  for (var i = 0; i < arrayOfCommands.length; i++)
1534  {
1535  var Command = arrayOfCommands[i].split(":");
1536  addCommand(Command[1],Command[2],Command[3]);
1537  }
1538  toggleDisplay(1);
1539  break;
1540  case "Export":
1541  DesktopContent.XMLHttpRequest("Request?RequestType=exportMacro" +
1542  "&MacroName=" + macroName,
1543  //post data
1544  "MacroSequence=" + macroSequence +
1545  "&MacroNotes=" + encodeURIComponent(macroNotes),
1546  exportMacroHandler);
1547  break;
1548  case "FEExport":
1549  Debug.log("FE Macro Export...");
1550  exportFEMacro(macroName,macroSequence,macroNotes);
1551  break;
1552  default:
1553  Debug.log("Impossible!? macroAction=" + macroAction);
1554  }
1555  }
1556 
1557  //=====================================================================================
1558  function exportFEMacro(macroName,macroSequence,macroNotes)
1559  {
1560  Debug.log("exportFEMacro()");
1561 
1562  var targetFEPluginName = "";
1563  var targetCnt = 0;
1564  try
1565  {
1566  for (var i = 0; i < selected.length; i++)
1567  if(selected[i] !== 0)
1568  {
1569  if(targetCnt == 0)
1570  {
1571  targetFEPluginName = FEELEMENTS[i].getAttribute("value").split(":")[0];
1572  }
1573 
1574  ++targetCnt;
1575  }
1576  }
1577  catch(e)
1578  {
1579  Debug.log("Error occured during FE Macro export: " + e, Debug.HIGH_PRIORITY);
1580  return;
1581  }
1582  if(targetCnt != 1)
1583  {
1584  Debug.log("Error! To export the Macro to a FE plugin, please select " +
1585  "a single FE target from FE list. There are currently " +
1586  targetCnt + " selected.", Debug.HIGH_PRIORITY);
1587  return;
1588  }
1589 
1590  //if here, then have plugin name
1591  Debug.log("Exporting to plugin " + targetFEPluginName);
1592  console.log("macroName",macroName);
1593  console.log("macroSequence",macroSequence);
1594  console.log("macroNotes",macroNotes);
1595 
1596 
1597  DesktopContent.XMLHttpRequest("Request?RequestType=exportFEMacro" +
1598  "&MacroName=" + macroName +
1599  "&PluginName=" + targetFEPluginName,
1600  //post data
1601  "MacroSequence=" + macroSequence +
1602  "&MacroNotes=" + encodeURIComponent(macroNotes),
1603  function(req)
1604  {
1605  var err = DesktopContent.getXMLValue(req,"Error");
1606  if(err)
1607  {
1608  Debug.log("To view your front-end plugin " +
1609  "source code files...\n" +
1610  "(Click " +
1611  "<a onclick='DesktopContent.openNewBrowserTab(" +
1612  "\"Code Editor\",undefined /*subname undefined for LID lookup*/," +
1613  "\"?startFilePrimary=" +
1614  headerFile + "&startFileSecondary=" +
1615  sourceFile + "&startViewMode=1\",undefined /*unique undefined for LID lookup*/);' " +
1616  "title='Click to open a new browser tab with both source files in the Code Editor.'>" +
1617  "here</a> to open them in the Code Editor)" +
1618  "\n\n" +
1619 
1620  "<a onclick='DesktopContent.openNewWindow(" +
1621  "\"Code Editor\",undefined /*subname undefined for LID lookup*/," +
1622  "\"?startFilePrimary=" +
1623  headerFile + "\",undefined /*unique undefined for LID lookup*/);' " +
1624  "title='Click to open this header file in the Code Editor.'>" +
1625  headerFile + "</a>\n\nand...\n\n" +
1626 
1627 
1628  "<a onclick='DesktopContent.openNewWindow(" +
1629  "\"Code Editor\",undefined /*subname undefined for LID lookup*/," +
1630  "\"?startFilePrimary=" +
1631  sourceFile + "\",undefined /*unique undefined for LID lookup*/);' " +
1632  "title='Click to open this source file in the Code Editor.'>" +
1633  sourceFile + "</a>\n\n" +
1634 
1635  "Click the links above to open the source code files in the Code Editor.\n\n"
1636  +
1637 
1638  "If you would like to run existing FE Macros, try doing so here...\n" +
1639  "(You MUST compile the plugin, and reconfigure otsdaq for FE Macro changes to take effect!): " +
1640  "<a onclick='DesktopContent.openNewWindow(" +
1641  "\"FE Macro Test\",\".h\"," +
1642  "\"/WebPath/html/FEMacroTest.html?urn=" +
1643  DesktopContent._localUrnLid + //same LID as MacroMaker
1644  "\",0 /*unique*/);' " +
1645  "title='Click to open the FE Macro Test web app.'>" +
1646  "FE Macro Test" + "</a>\n\n"
1647  ,
1648  Debug.HIGH_PRIORITY);
1649 
1650  Debug.log("Error! Something went wrong with your FE Macro export: " +
1651  err,Debug.HIGH_PRIORITY);
1652 
1653  return;
1654  }
1655 
1656  var headerFile = DesktopContent.getXMLValue(req,"headerFile");
1657  var sourceFile = DesktopContent.getXMLValue(req,"sourceFile");
1658  if(headerFile && sourceFile)
1659  {
1660  Debug.log("Your FE Macro was succesfully exported to the front-end plugin " +
1661  "source code files...\n" +
1662  "(Click " +
1663  "<a onclick='DesktopContent.openNewBrowserTab(" +
1664  "\"Code Editor\",\"\"," +
1665  "\"/WebPath/html/CodeEditor.html?startFilePrimary=" +
1666  headerFile + "&startFileSecondary=" +
1667  sourceFile + "&startViewMode=1\",0 /*unique*/);' " +
1668  "title='Click to open a new browser tab with both source files in the Code Editor.'>" +
1669  "here</a> to open them in the Code Editor)" +
1670  "\n\n" +
1671 
1672  "<a onclick='DesktopContent.openNewWindow(" +
1673  "\"Code Editor\",\".h\"," +
1674  "\"/WebPath/html/CodeEditor.html?startFilePrimary=" +
1675  headerFile + "\",0 /*unique*/);' " +
1676  "title='Click to open this header file in the Code Editor.'>" +
1677  headerFile + "</a>\n\nand...\n\n" +
1678 
1679 
1680  "<a onclick='DesktopContent.openNewWindow(" +
1681  "\"Code Editor\",\".cc\"," +
1682  "\"/WebPath/html/CodeEditor.html?startFilePrimary=" +
1683  sourceFile + "\",0 /*unique*/);' " +
1684  "title='Click to open this source file in the Code Editor.'>" +
1685  sourceFile + "</a>\n\n" +
1686 
1687  "Click the links above to open the source code files in the Code Editor.\n\n"
1688  +
1689 
1690  "If you would like to run your new FE Macro, try doing so here...\n" +
1691  "(You MUST compile the plugin, and reconfigure otsdaq for your FE Macro changes to take effect!): " +
1692  "<a onclick='DesktopContent.openNewWindow(" +
1693  "\"FE Macro Test\",\".h\"," +
1694  "\"/WebPath/html/FEMacroTest.html?urn=" +
1695  DesktopContent._localUrnLid + //same LID as MacroMaker
1696  "\",0 /*unique*/);' " +
1697  "title='Click to open the FE Macro Test web app.'>" +
1698  "FE Macro Test" + "</a>\n\n"
1699  ,
1700  Debug.INFO_PRIORITY);
1701  }
1702  else
1703  Debug.log("Error! Something went wrong with your FE Macro export." +
1704  " Please check the logs to understand the error.",
1705  Debug.HIGH_PRIORITY);
1706 
1707  }, //end export FE Macro request handling
1708  0 /*reqParam*/, 0 /*progressHandler*/, true /*callHandlerOnErr*/);
1709 
1710  } //end exportFEMacro()
1711 
1712  //=====================================================================================
1713  function exportMacroHandler(req)
1714  {
1715  Debug.log("exportMacroHandler() was called. ");//Req: " + req.responseText);
1716 
1717  var exportFile = DesktopContent.getXMLValue(req,"ExportFile");
1718  if(exportFile)
1719  Debug.log("Your Macro was succesfully exported!" +
1720  " It was saved to...\n\n" + exportFile
1721  ,Debug.INFO_PRIORITY);
1722  } //end exportMacroHandler()
1723 
1724  //=====================================================================================
1725  function editCommands(textarea, seqID, index)
1726  {
1727  var x = arrayOfCommandsForEdit[seqID].split(":");
1728  if(isNaN("0x" + textarea.value) && textarea.value !== "")
1729  {
1730  document.getElementById("popupIllegalEdit").style.display = "block";
1731  textarea.value = x[index];
1732  }
1733  else
1734  {
1735  x[index] = textarea.value;
1736  arrayOfCommandsForEdit[seqID] = x.join(":");
1737  }
1738  }
1739 
1740  //=====================================================================================
1741  function deleteMacroHandler(req)
1742  {
1743  Debug.log("deleteMacroHandler() was called. ");//Req: " + req.responseText);
1744 
1745  loadExistingMacros();
1746 
1747  var deletedMacroName = DesktopContent.getXMLValue(req,"deletedMacroName");
1748  var reminderEl = document.getElementById('reminder');
1749  reminderEl.innerHTML = "Successfully deleted " + decodeURI(deletedMacroName);
1750  }
1751 
1752  //=====================================================================================
1753  function saveChangedMacro()
1754  {
1755  newMacroNameForEdit = document.getElementById("macroNameEdit").value;
1756  //var Regex = /^[\w\s]+$/;
1757  var Regex = /^[a-zA-Z0-9\_]+$/g;
1758  var Regex2 = /^[a-z0-9]+$/i;
1759  if (!Regex.test(newMacroNameForEdit))
1760  document.getElementById("popupIllegalNaming").style.display = "block";
1761  else
1762  {
1763  if(document.getElementById("editFormat").value == "dec")
1764  {
1765  var nodeListOfTextareas=document.getElementsByTagName('textarea');
1766  for(var i=1;i<nodeListOfTextareas.length-1;i++) //Loop through all fields in the numerical sequence
1767  {
1768  if(!isNaN('0x'+nodeListOfTextareas[i].value))
1769  nodeListOfTextareas[i].innerHTML = convertToHex("dec",nodeListOfTextareas[i].value);
1770  }
1771  }
1772  for(var i = 0; i < arrayOfCommandsForEdit.length; i++)
1773  {
1774  var eachCommand = arrayOfCommandsForEdit[i].split(":");
1775  for (var j = 1; j < eachCommand.length; j++)
1776  {
1777  if(!Regex2.test(eachCommand[j]) && eachCommand[j] !== '')
1778  {
1779  document.getElementById("popupIllegalInput").style.display = "block";
1780  document.getElementById("illegalInputValue").innerHTML = eachCommand[j];
1781  return;
1782  }
1783  else if (eachCommand[j] === '')
1784  {
1785  if(eachCommand[j-2] == 'r') continue; //OK if readback result is empty!
1786  else
1787  {
1788  document.getElementById("popupEmptyInput").style.display = "block";
1789  return;
1790  }
1791  }
1792  }
1793  }
1794 
1795  macroNotesForEdit = document.getElementById('macroNotesEdit').value;
1796  if(macroNotesForEdit.indexOf("@") >= 0 || macroNotesForEdit.indexOf("#") >= 0 || macroNotesForEdit.indexOf("..") >= 0)
1797  {
1798  document.getElementById("popupIllegalNotes").style.display = "block";
1799  return;
1800  }
1801  var isMacroLSBF = document.getElementById('isMacroEditLSBF').checked;
1802  var isMacroPublic = !isOnPrivateMacros;
1803  DesktopContent.XMLHttpRequest("Request?RequestType=editMacro" +
1804  "&isPublic=" + isMacroPublic +
1805  "&isLSBF=" + isMacroLSBF,
1806  //post data
1807  "Sequence=" + arrayOfCommandsForEdit +
1808  "&oldMacroName=" + oldMacroNameForEdit +
1809  "&newMacroName=" + newMacroNameForEdit +
1810  "&Time=" + macroDateForEdit +
1811  "&Notes=" + encodeURIComponent(macroNotesForEdit),
1812  saveChangedMacroHandler /*handler*/,
1813  newMacroNameForEdit /*parameter*/);
1814  hidePopupEditMacro();
1815  }
1816  }
1817 
1818  //=====================================================================================
1819  function saveChangedMacroHandler(req,macroName)
1820  {
1821  Debug.log("saveChangedMacroHandler() was called.");
1822 
1823  Debug.log("Your Macro '" + macroName + "' was succesfully saved!",Debug.INFO_PRIORITY);
1824  loadExistingMacros();
1825  } //end saveChangedMacroHandler()
1826 
1827  //=====================================================================================
1828  function reloadMacroSequence()
1829  {
1830  var sequenceContentEl = document.getElementById("sequenceContent");
1831  sequenceContentEl.innerHTML = "";
1832  macroString = [];
1833  SEQFORMAT = document.getElementById("sequenceFormat").value;
1834  var macroStringForReload = tempString.slice();
1835  for (var i = 0; i < macroStringForReload.length; i++)
1836  {
1837  var Command = macroStringForReload[i].split(":");
1838  addCommand(Command[1],Command[2],Command[3]);
1839  }
1840  }
1841 
1842  //=====================================================================================
1843  function reloadEditSequence()
1844  {
1845  //FIXME: this function needs to know the old value before onchange!
1846  var nodeListOfTextareas=document.getElementsByTagName('textarea');
1847  if(document.getElementById("editFormat").value == "dec")
1848  {
1849  for(var i=1;i<nodeListOfTextareas.length-1;i++) //Loop through all fields in the numerical sequence
1850  {
1851  if(!isNaN('0x'+nodeListOfTextareas[i].value))
1852  nodeListOfTextareas[i].innerHTML = convertFromHex("dec",nodeListOfTextareas[i].value);
1853  }
1854  }
1855 // else if(document.getElementById("editFormat").value == "ascii")
1856 // {
1857 // for(var i=1;i<nodeListOfTextareas.length-1;i++) //Loop through all fields in the numerical sequence
1858 // {
1859 // if(!isNaN('0x'+nodeListOfTextareas[i].value))
1860 // nodeListOfTextareas[i].innerHTML = convertToHex("ascii",nodeListOfTextareas[i].value);
1861 // }
1862 // }
1863  else
1864  {
1865  for(var i=1;i<nodeListOfTextareas.length-1;i++) //Loop through all fields in the numerical sequence
1866  {
1867  if(!isNaN('0x'+nodeListOfTextareas[i].value))
1868  nodeListOfTextareas[i].innerHTML = convertToHex("dec",nodeListOfTextareas[i].value);
1869  }
1870  }
1871  }
1872 
1873  //=====================================================================================
1874  function setFieldToVariable(div, seqID, index,isReadResultField)
1875  {
1876  Debug.log("setFieldToVariable");
1877 
1878  var popupNameVariableEl = document.getElementById("popupNameVariable");
1879  popupNameVariableEl.style.display = "block";
1880 
1881  var nameVariablePromptEl = document.getElementById("nameVariablePrompt");
1882  var textareaEl = div.previousSibling;
1883  var currentVal = textareaEl.value;
1884 
1885  document.getElementById('popupNameVariableCancelButton').onclick = function()
1886  {
1887  popupNameVariableEl.style.display = "none";
1888  document.getElementById("nameVariable").value = "";
1889  return;
1890  };
1891 
1892  if(currentVal != "..." && isReadResultField) //read result field! handle with caution
1893  {
1894  document.getElementById('popupNameVariableSaveButton').style.display = "none";
1895  document.getElementById('popupNameVariableYesButton').style.display = "inline-block";
1896  document.getElementById('nameVariable').style.display = "none";
1897  nameVariablePromptEl.innerHTML = "Would you like to remove this field as a variable?";
1898  document.getElementById('popupNameVariableYesButton').onclick = function() {
1899  div.style.backgroundColor = "#002a52";
1900  textareaEl.value = "...";
1901  var x = arrayOfCommandsForEdit[seqID].split(":");
1902  x[index] = "";
1903  arrayOfCommandsForEdit[seqID] = x.join(":");
1904  document.getElementById('popupNameVariableSaveButton').style.display = "inline-block";
1905  document.getElementById('popupNameVariableYesButton').style.display = "none";
1906  document.getElementById('nameVariable').style.display = "inline-block";
1907  popupNameVariableEl.style.display = "none";
1908  };
1909  }
1910  else if(!isNaN("0x"+currentVal) || currentVal == "" || //if is a number or blank
1911  isReadResultField) // or read field.. set variable name
1912  {
1913  nameVariablePromptEl.innerHTML = "Setting field to variable! How would you like to name it?";
1914  document.getElementById('popupNameVariableSaveButton').onclick = function() {
1915  var variableName = document.getElementById("nameVariable").value.toString();
1916  if(variableName === "")
1917  {
1918  nameVariablePromptEl.innerHTML =
1919  "<span class='red'>Name of the variable cannot be empty.</span>";
1920  return;
1921  }
1922  else if(!isNaN("0x"+variableName))
1923  {
1924  nameVariablePromptEl.innerHTML =
1925  "<span class='red'>Name of the variable cannot be a valid hex number.</span>";
1926  return;
1927  }
1928  div.style.backgroundColor = "#ff0101";
1929  textareaEl.value = variableName;
1930  textareaEl.disabled = true;
1931  var x = arrayOfCommandsForEdit[seqID].split(":");
1932  x[index] = variableName;
1933  arrayOfCommandsForEdit[seqID] = x.join(":");
1934  document.getElementById("nameVariable").value = "";
1935  popupNameVariableEl.style.display = "none";
1936  };
1937  }
1938  else
1939  {
1940  nameVariablePromptEl.innerHTML = "Would you like a set value instead of a variable?";
1941  document.getElementById('popupNameVariableSaveButton').onclick = function() {
1942  var variableName = document.getElementById("nameVariable").value.toString();
1943  if(variableName === "")
1944  {
1945  nameVariablePromptEl.innerHTML =
1946  "<span class='red'>Name of the variable cannot be empty.</span>";
1947  return;
1948  }
1949  else if(isNaN("0x"+variableName))
1950  {
1951  nameVariablePromptEl.innerHTML =
1952  "<span class='red'>The value has to be a valid hex number.</span>";
1953  return;
1954  }
1955  div.style.backgroundColor = "#002a52";
1956  textareaEl.value = variableName;
1957  textareaEl.disabled = false;
1958  var x = arrayOfCommandsForEdit[seqID].split(":");
1959  x[index] = variableName;
1960  arrayOfCommandsForEdit[seqID] = x.join(":");
1961  document.getElementById("nameVariable").value = "";
1962  popupNameVariableEl.style.display = "none";
1963  };
1964  }
1965  }
1966 
1967  //=====================================================================================
1968  function dealWithVariables(stringOfCommands,macroName,LSBF)
1969  {
1970  if (LSBF == "true") runningMacroLSBF = 1;
1971  if (LSBF == "false") runningMacroLSBF = 2;
1972 
1973  var reminderEl = document.getElementById('reminder');
1974  var waitForUserInputFlag = 0;
1975  var copyOfStringOfCommands = stringOfCommands.slice(); //Needed because the variable assignments are temporary
1976  var i = 0;
1977  var commandToChange = 0;
1978  var newCommand = [];
1979  var dictionary = {};
1980  var globalIndex = 0;
1981  var isAddressField = true;
1982  if(isMacroRunning)
1983  reminderEl.innerHTML = "Please wait till the current macro ends";
1984  else if(isArrayAllZero(selected))
1985  Debug.log("Please select at least one interface from the list",Debug.HIGH_PRIORITY);
1986  else
1987  {
1988  isMacroRunning = true;
1989  var promptEl = document.getElementById('popupAskForVariableValue');
1990  timeIntervalID = setInterval(function()
1991  {
1992  if(i < stringOfCommands.length && waitForUserInputFlag === 0)
1993  {
1994  var Command = stringOfCommands[i].split(":");
1995  function setValue(index,isReadAddress) //This function is called when encountering a variable name in the address(index=2)/data(index=3) field
1996  { //instead of a hex value, and prompt the user to set the temporary value of variable
1997  globalIndex = index;
1998  if(isReadAddress && Command[index] !== "")
1999  {
2000  readoutDictionary.push(Command[index].toString());
2001  }
2002  else if (dictionary[Command[index].toString()] !== undefined) //Look up name-value pair of the variable in the dictionary
2003  {
2004  newCommand = copyOfStringOfCommands[i].split(":");
2005  newCommand[index] = dictionary[Command[index].toString()];
2006  copyOfStringOfCommands[i] = newCommand.join(":");
2007  }
2008  else if (isNaN("0x"+Command[index]) && Command[index] !== "") //If not found in the dictionary, prompt user for the value OR
2009  {
2010  if(readoutDictionary.indexOf(Command[index].toString()) !== -1) //is one of those variables we want to temporarily preserve
2011  {
2012  return;
2013  }
2014  else
2015  {
2016  waitForUserInputFlag = 1;
2017  newCommand = copyOfStringOfCommands[i].split(":");
2018  var variableNameAtRunTime = Command[index];
2019  commandToChange = i;
2020  if(waitForUserInputFlag === 0) //Keep looping after user enters value and clicks continue
2021  return;
2022  else
2023  {
2024  promptEl.style.display = "block"; //Pop-up window prompting user for value of variable
2025  document.getElementById('assignValuePrompt').innerHTML
2026  = "What value would you assign to variable <span id=\"variableNameAtRunTime\" class=\"red\"></span>?</h4>"
2027  document.getElementById('variableNameAtRunTime').innerHTML = variableNameAtRunTime;
2028  }
2029  }
2030  }
2031  }
2032  if (Command[1] == "w") //A "write" command will go through this loop twice
2033  {
2034  if(isAddressField) //Address goes first, and then data
2035  {
2036  setValue(2);
2037  i--; //Decrementing the count after checking address field
2038  isAddressField = false;
2039  }
2040  else
2041  {
2042  setValue(3);
2043  isAddressField = true;
2044  }
2045  }
2046  else if (Command[1] == "r")
2047  {
2048  if(isAddressField) //Address goes first, and then data
2049  {
2050  setValue(2);
2051  i--; //Decrementing the count after checking address field
2052  isAddressField = false;
2053  }
2054  else
2055  {
2056  setValue(3,1);
2057  isAddressField = true;
2058  }
2059  }
2060  else setValue(2);
2061  i++;
2062  }
2063  else if(i == stringOfCommands.length && waitForUserInputFlag === 0)
2064  {
2065  clearInterval(timeIntervalID);
2066  console.log("Final command to send to run: " + copyOfStringOfCommands);
2067  runMacro(copyOfStringOfCommands, macroName); //End of function: send new macro to run
2068  }
2069  },200);
2070  }
2071 
2072  document.getElementById('popupAskForVariableValueContinue').onclick = function()
2073  {
2074  var variableValue = document.getElementById("valueAtRunTime").value.toString();
2075  if(isNaN("0x"+variableValue))
2076  {
2077  document.getElementById("assignValuePrompt").innerHTML =
2078  "<span class='red'>The value has to be a hex number.</span>";
2079  return;
2080  }
2081  else
2082  {
2083  dictionary[newCommand[globalIndex].toString()] = variableValue; //Add new name-value pair to dictionary
2084  newCommand[globalIndex] = variableValue;
2085  promptEl.style.display = "none";
2086  copyOfStringOfCommands[commandToChange] = newCommand.join(":");
2087  document.getElementById("valueAtRunTime").value = "";
2088  waitForUserInputFlag = 0;
2089  return;
2090  }
2091  };
2092  }
2093 
2094 
2095 
2096 
2097 
2098 
2099 
2100 
2101 
2102 
2103 
2104 
2105 
2106 
2107