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