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