GSI Object Oriented Online Offline (Go4)  GO4-6.1.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
pareditor.js
Go to the documentation of this file.
1 (function() {
2 
3  "use strict";
4 
5  if (typeof JSROOT != "object") {
6  var e1 = new Error("pareditor.js requires JSROOT to be already loaded");
7  e1.source = "pareditor.js";
8  throw e1;
9  }
10 
11  if (typeof GO4 != "object") {
12  var e1 = new Error("pareditor.js requires GO4 to be already loaded");
13  e1.source = "pareditor.js";
14  throw e1;
15  }
16 
17  // ===========================================================================================
18 
19  let BasePainter = JSROOT.BasePainter || JSROOT.TBasePainter;
20 
21  GO4.ParameterEditor = function(divid, par) {
22  BasePainter.call(this, divid);
23  if (this.SetDivId) this.SetDivId(divid);
24  this.par = par;
25  this.changes = ["dummy", "init"]; // TODO: put to common "base class" of condition and parameter editor
26  }
27 
28  GO4.ParameterEditor.prototype = Object.create(BasePainter.prototype);
29 
30  GO4.ParameterEditor.prototype.CheckResize = function() { }
31  GO4.ParameterEditor.prototype.checkResize = function() { }
32 
33  // TODO: put to common "base class" of condition and parameter editor
34  // add identifier of changed element to list, make warning sign visible
35  GO4.ParameterEditor.prototype.MarkChanged = function(key) {
36  // first avoid duplicate keys:
37  for (var index = 0; index < this.changes.length; index++) {
38  if (this.changes[index] == key) return;
39  }
40  this.changes.push(key);
41  console.log("Mark changed :%s", key);
42  var id = "#" + this.get_main_id();
43  $(id + " .buttonChangeLabel").show();// show warning sign
44  }
45 
46  // TODO: put to common "base class" of condition and parameter editor
47  GO4.ParameterEditor.prototype.ClearChanges = function() {
48  var index;
49  var len = this.changes.length;
50  for (index = 0; index < len; index++) {
51  var removed = this.changes.pop();
52  console.log("Clear changes removed :%s", removed);
53  }
54  var id = "#" + this.get_main_id();
55  $(id + " .buttonChangeLabel").hide(); // hide warning sign
56  }
57 
58  // scan changed value list and return optionstring to be send to server
59  GO4.ParameterEditor.prototype.EvaluateChanges = function(optionstring) {
60  var id = "#" + this.get_main_id();
61  var len = this.changes.length;
62  for (var index = 0; index < len; index++) {
63  //var cursor=changes.pop();
64  var key = this.changes[index];
65  console.log("Evaluate change key:%s", key);
66  // here mapping of key to editor field:
67  // key will be name of variable which is class name of input field:
68  var val = $(id + " ." + key.toString())[0].value;
69  //var opt= key.replace(/_/g, "[").replace(/-/g, "]"); // old with other placeholders
70  var arraysplit = key.split("_");
71  var opt = "";
72  if (arraysplit.length > 1) {
73  // found array with index after separator, reformat it:
74  opt = arraysplit[0];
75  if (arraysplit.length > 2) {
76  if (arraysplit.length > 3) {
77  // 3dim array:
78  var ix = arraysplit[arraysplit.length - 3]; //
79  var iy = arraysplit[arraysplit.length - 2]; //
80  var iz = arraysplit[arraysplit.length - 1]; //
81  opt += "[" + ix + "][" + iy + "][" + iz + "]";
82  }
83  else {
84  // 2dim array:
85  var ix = arraysplit[arraysplit.length - 2]; //
86  var iy = arraysplit[arraysplit.length - 1]; //
87  opt += "[" + ix + "][" + iy + "]";
88  }
89  var iy = arraysplit[arraysplit.length - 2]; //
90  }
91  else {
92  // 1dim array:
93  opt = arraysplit[0];
94  var ix = arraysplit[arraysplit.length - 1]; //
95  opt += "[" + ix + "]";
96  }
97  }
98  else {
99  opt = key;
100  }
101 
102  optionstring += "&" + opt + "=" + val;
103  }// for index
104  console.log("Resulting option string:%s", optionstring);
105  return optionstring;
106  }
107 
108  GO4.ParameterEditor.prototype.fillComments = function() {
109  var editor = this;
110  if (editor.xreq || !this.getItemName()) return; // avoid double requests
111  var pre = this.getItemName() + "/";
112  editor.xreq = true;
113 
114  GO4.httpRequest(pre + "h.json?more", 'object').then(res => {
115  var id = "#" + editor.get_main_id();
116  $(id + " .par_values tbody").find("tr").each(function(i, tr) {
117  var name = $(tr).find("td:first").text();
118  var title = null;
119  var arrayinfo = null;
120  var typeinfo = null;
121  for (var i in res._childs) {
122  var n = res._childs[i]._name;
123  var arsplit = name.split("["); // remove array information at the end, if any
124  if (arsplit[0] == n) {
125  //if ((name==n) || (name.indexOf(n)==0)) {
126  title = res._childs[i]._title;
127  arrayinfo = res._childs[i]._arraydim;
128  typeinfo = res._childs[i]._typename;
129  //console.log("found title="+title+", arrayinfo="+arrayinfo);
130  break;
131  }
132  }
133  if (title != null)
134  $(tr).find("td.par_comment").text(title).css('white-space', 'nowrap'); // comments from class member declaration
135  if (typeinfo != null) {
136  $(tr).find("td.par_class").text(typeinfo).css('white-space', 'nowrap'); // member type
137 
138  $(tr).parents('table.par_arraytable').find('td.par_comment:first').text("Array").css('white-space', 'nowrap');
139  // if we are inside array table, indicate that we are an array
140 
141  if (arrayinfo != null)
142  $(tr).parents('table.par_arraytable').find('td.par_class:first').text(typeinfo + " [" + arrayinfo + "]").css('white-space', 'nowrap');
143  else
144  $(tr).parents('table.par_arraytable').find('td.par_class:first').text(typeinfo).css('white-space', 'nowrap');
145 
146  // put type information of array to subtable header
147  }
148 
149  });
150  }).finally(() => { editor.xreq = false; });
151 
152  }
153 
154  GO4.ParameterEditor.prototype.fillMemberTable = function() {
155  var editor = this;
156  var id = "#" + this.get_main_id();
157  var par = this.par;
158  $(id + " .par_values tbody").html("");
159  var found_title = false;
160  for (var key in par) {
161  if (typeof par[key] == 'function') continue;
162  if (key == 'fTitle') { found_title = true; continue; }
163  if (!found_title) continue;
164  var value = (par[key] != null ? (par[key] instanceof Array ? par[key] : par[key].toString()) : "null");
165  var classname = "";
166  if (value instanceof Array) {
167  // here put array table with clickable header:
168  // (thanks to Jonathan at http://mediaformations.com/accordion-tables-with-jquery/ for this idea!)
169  var arraytableclass = key.toString() + "_array";
170  var isTooBig = false;
171  $(id + " .par_values > tbody").append("<tr><td style='width:100%; padding:0px' colspan='4' > <table class='" + arraytableclass + " par_arraytable'><thead><tr><td class='par_key'> <bf>[+]</bf> " + key.toString() + "</td><td class='par_class'></td><td class='par_value' >Click to expand</td><td class='par_comment'></td></tr></thead><tbody></tbody></table></td></tr>");
172  for (i = 0; i < value.length; i++) {
173  if (value[i] instanceof Array) {
174  subvalue = value[i];
175  for (j = 0; j < subvalue.length; j++) {
176  if (subvalue[j] instanceof Array) {
177  subsubvalue = subvalue[j];
178  // here supress display of 3d arrays if too
179  // large:
180  if (subsubvalue.length * subvalue.length * value.length > 1000) {
181  isTooBig = true;
182  break;
183  }
184  else {
185  for (k = 0; k < subsubvalue.length; k++) {
186  // decode 3dim array
187  classname = key.toString() + "_" + i
188  + "_" + j + "_" + k;
189  // $(id + " .par_values
190  // tbody").append("<tr><td>" +
191  // key.toString() + "[" + i +
192  // "]["+j+"]["+k+"]</td><td><input
193  // type='text' value='" + subsubvalue[k]
194  // + "' class='"+ classname
195  // +"'/></td><td></td></tr>");
196  $(id + " ." + arraytableclass + " tbody").append(
197  "<tr><td class='par_key'>"
198  + key.toString()
199  + "[" + i + "][" + j + "][" + k + "]"
200  + "</td><td class='par_class'></td><td class='par_value'><input type='text' size='10' value='"
201  + subsubvalue[k]
202  + "' class='" + classname + "'/></td><td class='par_comment'></td></tr>");
203 
204  } // for k
205  }
206  }
207  else {
208  // decode 2dim array
209  classname = key.toString() + "_" + i + "_" + j;
210  //$(id + " .par_values tbody").append("<tr><td>" + key.toString() + "[" + i + "]["+j+"]</td><td><input type='text' value='" + subvalue[j] + "' class='"+ classname +"'/></td><td></td></tr>");
211  $(id + " ." + arraytableclass + " tbody").append("<tr><td class='par_key'>" + key.toString() + "[" + i + "][" + j + "]</td><td class='par_class'></td><td class='par_value'><input type='text' size='10' value='" + subvalue[j] + "' class='" + classname + "'/></td><td class='par_comment'></td></tr>");
212 
213  }
214  } // for j
215  }
216  else {
217  // decode 1dim array
218  //classname=key.toString()+"_"+ i+"-"; // old with placeholders instead brackets
219 
220  classname = key.toString() + "_" + i;
221  //$(id + " .par_values tbody").append("<tr><td>" + key.toString() + "[" + i + "]</td><td><input type='text' value='" + value[i] + "' class='"+ classname +"'/></td><td></td></tr>");
222  $(id + " ." + arraytableclass + " tbody").append("<tr><td class='par_key'>" + key.toString() + "[" + i + "]</td><td class='par_class'></td><td class='par_value'><input type='text' size='10' value='" + value[i] + "' class='" + classname + "'/></td><td class='par_comment'></td></tr>");
223 
224  }
225  } // for i
226  //
227  if (isTooBig) {
228  $(id + " ." + arraytableclass + " tbody")
229  .append(
230  "<tr><td class='par_key'>" + key.toString() + "</td><td colspan='3'> Sorry, Array dimension ["
231  + value.length
232  + "]["
233  + subvalue.length
234  + "]["
235  + subsubvalue.length
236  + "] too big to display!</td></tr>");
237  }
238 
239 
240  $(id + " table." + arraytableclass + " thead tr").click(
241  function() {
242  $(this).parents('table.par_arraytable').children('tbody').toggle();
243  $(this).parents('table.par_arraytable').find('td:first').text(
244  function(i, origText) {
245  var changed = origText;
246  if (origText.indexOf("[+]") != -1)
247  changed = origText.replace("[+]", "[-]");
248  if (origText.indexOf("[-]") != -1)
249  changed = origText.replace("[-]", "[+]");
250  //console.log("original text= "+origText+", changed="+changed);
251  return changed;
252  });
253  $(this).parents('table.par_arraytable').find('td.par_value:first').text(
254  function(i, origText) {
255  var changed = origText;
256  if (origText.indexOf("expand") != -1)
257  changed = origText.replace("expand", "shrink");
258  if (origText.indexOf("shrink") != -1)
259  changed = origText.replace("shrink", "expand");
260  //console.log("original text= "+origText+", changed="+changed);
261  return changed;
262  });
263 
264  //console.log("Clicked on table header");
265  }
266  );
267  $(id + " table." + arraytableclass).children('tbody').hide();
268 
269  } else {
270  classname = key.toString();
271  $(id + " .par_values > tbody").append("<tr><td class='par_key'>" + key.toString() + "</td><td class='par_class'></td><td class='par_value'><input type='text' size='10' value='" + value + "' class='" + classname + "'/></td><td class='par_comment'></td></tr>");
272  }
273 
274  }
275  // here set callbacks; referred classname must be evaluated dynamically in function!:
276  $(id + " .par_values tbody input").change(function() { editor.MarkChanged($(this).attr('class')) });
277  $(id + " .par_values tbody td").addClass("par_membertable_style");
278  $(id + " .par_values > thead th").addClass("par_memberheader_style");
279  $(id + " .par_arraytable thead td").addClass("par_arrayheader_style");
280 
281  this.ClearChanges();
282  }
283 
284  GO4.ParameterEditor.prototype.fillEditor = function() {
285  var editor = this;
286  var par = this.par;
287  var id = "#" + this.get_main_id();
288  var width = $(id).width();
289  var height = $(id).height();
290 
291  $(id + " .par_name").text(par.fName);
292  $(id + " .par_type").text(par._typename);
293 
294  $(id).children().eq(0).width(width - 4).height(height - 4);
295 
296  $(id + " .buttonGetParameter")
297  .button({ text: false, icons: { primary: "ui-icon-blank MyButtonStyle" } }).click(function() {
298  console.log("update item = " + editor.getItemName());
299  if (JSROOT.hpainter)
300  JSROOT.hpainter.display(editor.getItemName());
301  else
302  console.log("dabc object not found!");
303  })
304  .children(":first") // select first button element, used for images
305  .css('background-image', "url(" + GO4.source_dir + "icons/right.png)");
306 
307  $(id + " .buttonSetParameter")
308  .button({ text: false, icons: { primary: "ui-icon-blank MyButtonStyle" } })
309  .click(function() {
310  var options = ""; // do not need to use name here
311  options = editor.EvaluateChanges(options); // complete option string from all changed elements
312  console.log("set - condition " + editor.getItemName() + ", options=" + options);
313  GO4.ExecuteMethod(editor, "UpdateFromUrl", options, function(result) {
314  console.log(result ? "set parameter done. " : "set parameter FAILED.");
315  if (result) editor.ClearChanges();
316  });
317  })
318  .children(":first") // select first button element, used for images
319  .css('background-image', "url(" + GO4.source_dir + "icons/left.png)");
320 
321  $(id + " .buttonChangeLabel")
322  .button({ text: false, icons: { primary: "ui-icon-blank MyButtonStyle" } }).click()
323  .children(":first") // select first button element, used for images
324  .css('background-image', "url(" + GO4.source_dir + "icons/info1.png)");
325 
326 
327  this.fillMemberTable();
328  }
329 
330  if (JSROOT._) {
331 
332  GO4.ParameterEditor.prototype.redrawObject = function(obj) {
333  if (obj._typename != this.par._typename) return false;
334  this.par = JSROOT.clone(obj);
335  this.redraw(); // no need to redraw complete pad
336  return true;
337  }
338 
339  GO4.ParameterEditor.prototype.setItemName = function(name, opt, hpainter) {
340  BasePainter.prototype.setItemName.call(this, name, opt, hpainter);
341  this.fillComments();
342  }
343 
344  } else {
345 
346  // old style, new jsroot does not have RedrawPad for BasePainter
347  GO4.ParameterEditor.prototype.RedrawPad = function(resize) {
348  this.redraw();
349  }
350 
351  // makes sense only in jsroot v5, in v6 should be defined redrawObject
352  GO4.ParameterEditor.prototype.UpdateObject = function(obj) {
353  if (obj._typename != this.par._typename) return false;
354  this.par = JSROOT.clone(obj);
355  return true;
356  }
357 
358  GO4.ParameterEditor.prototype.SetItemName = function(name, opt, hpainter) {
359  BasePainter.prototype.SetItemName.call(this, name, opt, hpainter);
360  this.fillComments();
361  }
362 
363  }
364 
365 
366  GO4.ParameterEditor.prototype.redraw = function() {
367  console.log("ParemeterEditor Redraw...");
368  this.fillMemberTable();
369  this.fillComments();
370  }
371 
372  // support older jsroot v5
373  if (!JSROOT._) GO4.ParameterEditor.prototype.Redraw = GO4.ParameterEditor.prototype.redraw;
374 
375  GO4.ParameterEditor.prototype.drawEditor = function() {
376 
377  var sel = JSROOT._ ? this.selectDom() : this.select_main();
378 
379  var main = $(sel.node());
380 
381  var h = main.height(), w = main.width();
382  if ((h < 10) && (w > 10)) main.height(w * 0.4);
383 
384  var pthis = this;
385 
386  function loadEditor(resolve) {
387  main.empty();
388  main.load(GO4.source_dir + "html/pareditor.htm", "", function() {
389  pthis.fillEditor();
390  pthis.fillComments();
391  if (resolve) {
392  pthis.setTopPainter();
393  resolve(pthis);
394  } else {
395  pthis.SetDivId(this.divid); // old
396  pthis.DrawingReady();
397  }
398  });
399  return pthis;
400  }
401 
402  if (JSROOT._)
403  return new Promise(resolve => loadEditor(resolve));
404 
405  return loadEditor();
406  }
407 
408 
409  GO4.drawParameter = function(divid, par /*, option */) {
410  var editor = new GO4.ParameterEditor(divid, par);
411  return editor.drawEditor();
412  }
413 
414 })();
let BasePainter
Definition: pareditor.js:19
function JSROOT
Definition: go4canvas.js:17
int main(int argc, char **argv)
function GO4
Definition: go4canvas.js:17