otsdaq_utilities  v2_05_02_indev
JSRootCore.js
1 
4 (function( factory ) {
5  if ( typeof define === "function" && define.amd ) {
6 
7  var jsroot = factory({}),
8  dir = jsroot.source_dir + "scripts/",
9  ext = jsroot.source_min ? ".min" : "",
10  norjs = (typeof requirejs=='undefined'),
11  paths = {
12  'd3' : dir+'d3.min',
13  'jquery' : dir+'jquery.min',
14  'jquery-ui' : dir+'jquery-ui.min',
15  'jqueryui-mousewheel' : dir+'jquery.mousewheel.min',
16  'jqueryui-touch-punch' : dir+'touch-punch.min',
17  'rawinflate' : dir+'rawinflate.min',
18  'MathJax' : 'https://root.cern/js/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG&delayStartupUntil=configured',
19  'dat.gui' : dir+'dat.gui.min',
20  'threejs' : dir+'three.min',
21  'threejs_all' : dir+'three.extra.min',
22  'JSRootCore' : dir+'JSRootCore'+ext,
23  'JSRootMath' : dir+'JSRootMath'+ext,
24  'JSRootIOEvolution' : dir+'JSRootIOEvolution'+ext,
25  'JSRootTree' : dir+'JSRootTree'+ext,
26  'JSRoot.openui5' : dir+'JSRoot.openui5'+ext,
27  'JSRootPainter' : dir+'JSRootPainter'+ext,
28  'JSRootPainter.v6' : dir+'JSRootPainter.v6'+ext,
29  'JSRootPainter.hist' : dir+'JSRootPainter.hist'+ext,
30  'JSRootPainter.hist3d' : dir+'JSRootPainter.hist3d'+ext,
31  'JSRootPainter.more' : dir+'JSRootPainter.more'+ext,
32  'JSRootPainter.hierarchy' : dir+'JSRootPainter.hierarchy'+ext,
33  'JSRootPainter.jquery' : dir+'JSRootPainter.jquery'+ext,
34  'JSRootPainter.v7' : dir+'JSRootPainter.v7'+ext,
35  'JSRootPainter.v7hist' : dir+'JSRootPainter.v7hist'+ext,
36  'JSRootPainter.v7more' : dir+'JSRootPainter.v7more'+ext,
37  'JSRoot3DPainter' : dir+'JSRoot3DPainter'+ext,
38  'ThreeCSG' : dir+'ThreeCSG'+ext,
39  'JSRootGeoBase' : dir+'JSRootGeoBase'+ext,
40  'JSRootGeoPainter' : dir+'JSRootGeoPainter'+ext
41  };
42 
43  if (norjs) {
44  // just define locations
45  paths['MathJax'] = 'https://root.cern/js/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG&delayStartupUntil=configured';
46 
47  require({ paths: paths });
48  } else {
49  var cfg_paths;
50  if ((requirejs.s!==undefined) && (requirejs.s.contexts !== undefined) && ((requirejs.s.contexts._!==undefined) &&
51  requirejs.s.contexts._.config!==undefined)) cfg_paths = requirejs.s.contexts._.config.paths;
52  else console.warn("Require.js paths changed - please contact JSROOT developers");
53 
54  // check if modules are already loaded
55  for (var module in paths)
56  if (requirejs.defined(module) || (cfg_paths && (module in cfg_paths)))
57  delete paths[module];
58 
59  // configure all dependencies
60  requirejs.config({
61  paths: paths,
62  shim: {
63  'jqueryui-mousewheel': { deps: ['jquery-ui'] },
64  'jqueryui-touch-punch': { deps: ['jquery-ui'] }
65  }
66  });
67  }
68 
69  define( jsroot );
70 
71  if (norjs || !require.specified("JSRootCore"))
72  define('JSRootCore', [], jsroot);
73 
74  if (norjs || !require.specified("jsroot"))
75  define('jsroot', [], jsroot);
76 
77  } else if (typeof exports === 'object' /*&& typeof module !== 'undefined'*/) {
78  // processing with Node.js or CommonJS
79 
80  // mark JSROOT as used with Node.js
81  exports.BatchMode = exports.nodejs = (typeof global==='object') && global.process && (Object.prototype.toString.call(global.process) === '[object process]');
82 
83  factory(exports);
84 
85  } else {
86 
87  if (typeof JSROOT != 'undefined')
88  throw new Error("JSROOT is already defined", "JSRootCore.js");
89 
90  JSROOT = {};
91 
92  factory(JSROOT);
93  }
94 } (function(JSROOT) {
95 
96  "use strict";
97 
98  JSROOT.version = "5.8.0 16/10/2019";
99 
100  JSROOT.source_dir = "";
101  JSROOT.source_min = false;
102  JSROOT.source_fullpath = ""; // full name of source script
103  JSROOT.bower_dir = null; // when specified, use standard libs from bower location
104  JSROOT.nocache = false; // when specified, used as extra URL parameter to load JSROOT scripts
105  JSROOT.wrong_http_response_handling = false; // when configured, try to handle wrong content-length response from server
106  JSROOT.sources = ['core']; // indicates which major sources were loaded
107 
108  JSROOT.id_counter = 1; // avoid id value 0, starts from 1
109  if (JSROOT.BatchMode === undefined)
110  JSROOT.BatchMode = false; // when true, disables all kind of interactive features
111 
112  //openuicfg // DO NOT DELETE, used to configure openui5 usage like JSROOT.openui5src = "nojsroot";
113 
114  // JSROOT.use_full_libs = true;
115 
116  JSROOT.touches = false;
117  JSROOT.browser = { isOpera: false, isFirefox: true, isSafari: false, isChrome: false, isIE: false, isWin: false };
118 
119  if ((typeof document !== "undefined") && (typeof window !== "undefined")) {
120  var scripts = document.getElementsByTagName('script');
121  for (var n = 0; n < scripts.length; ++n) {
122  if (!scripts[n].src || (typeof scripts[n].src !== 'string')) continue;
123 
124  var pos = scripts[n].src.indexOf("scripts/JSRootCore.");
125  if (pos<0) continue;
126 
127  JSROOT.source_dir = scripts[n].src.substr(0, pos);
128  JSROOT.source_min = scripts[n].src.indexOf("scripts/JSRootCore.min.js") >= 0;
129  JSROOT.source_fullpath = scripts[n].src;
130 
131  if ((console!==undefined) && (typeof console.log == 'function'))
132  console.log("Set JSROOT.source_dir to " + JSROOT.source_dir + ", " + JSROOT.version);
133  break;
134  }
135 
136  JSROOT.touches = ('ontouchend' in document); // identify if touch events are supported
137  JSROOT.browser.isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
138  JSROOT.browser.isFirefox = typeof InstallTrigger !== 'undefined';
139  JSROOT.browser.isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
140  JSROOT.browser.isChrome = !!window.chrome && !JSROOT.browser.isOpera;
141  JSROOT.browser.isIE = !!document.documentMode;
142  JSROOT.browser.isWin = navigator.platform.indexOf('Win') >= 0;
143  JSROOT.browser.isChromeHeadless = navigator.userAgent.indexOf('HeadlessChrome') >= 0;
144  }
145 
146  JSROOT.browser.isWebKit = JSROOT.browser.isChrome || JSROOT.browser.isSafari || JSROOT.browser.isOpera;
147 
148  // default draw styles, can be changed after loading of JSRootCore.js
149  // this style also can be changed providing style=itemname in the URL
150  JSROOT.gStyle = {
151  Tooltip: 1, // 0 - off, 1 - on
152  TooltipAnimation: 500, // time in msec for appearance of tooltips, 0 - no animation
153  ContextMenu: true,
154  Zooming: true, // global zooming flag, enable/disable any kind of interactive zooming
155  ZoomMouse: true, // Zooming with the mouse events
156  ZoomWheel: true, // Zooming with mouse wheel
157  ZoomTouch: true, // Zooming with the touch devices
158  MoveResize: true, // enable move and resize of elements like statbox, title, pave, colz
159  DragAndDrop: true, // enables drag and drop functionality
160  ToolBar: 'popup', // show additional tool buttons on the canvas, false - disabled, true - enabled, 'popup' - only toggle button
161  ToolBarSide: 'left', // 'left' left-bottom corner on canvas, 'right' - right-bottom corner on canvas, opposite on sub-pads
162  ToolBarVert: false, // display tool bar vertical (default false)
163  CanEnlarge: true, // if drawing inside particular div can be enlarged on full window
164  CanAdjustFrame: false, // if frame position can be adjusted to let show axis or colz labels
165  ApproxTextSize: false, // calculation of text size consumes time and can be skipped to improve performance (but with side effects on text adjustments)
166  OptimizeDraw: 1, // drawing optimization: 0 - disabled, 1 - only for large (>5000 1d bins, >50 2d bins) histograms, 2 - always
167  AutoStat: true,
168  FrameNDC: { fX1NDC: 0.07, fY1NDC: 0.12, fX2NDC: 0.95, fY2NDC: 0.88 },
169  Palette: 57,
170  Latex: 2, // 0 - never, 1 - only latex symbols, 2 - normal TLatex processing (default), 3 - use MathJax for complex case, 4 - use MathJax always
171  // MathJax : 0, // deprecated, will be supported till JSROOT 6.0, use Latex variable 0 - never, 1 - only for complex cases, 2 - always
172  ProgressBox: true, // show progress box
173  Embed3DinSVG: 2, // 0 - no embed, only 3D plot, 1 - overlay over SVG (IE/WebKit), 2 - embed into SVG (only Firefox)
174  ImageSVG: !JSROOT.nodejs, // when producing SVG images, use <image> elements to insert 3D drawings from three.js,
175  // To enable on nodejs, one should call "npm install canvas"
176  NoWebGL: false, // if true, WebGL will be disabled
177  GeoGradPerSegm: 6, // amount of grads per segment in TGeo spherical shapes like tube
178  GeoCompressComp: true, // if one should compress faces after creation of composite shape,
179  IgnoreUrlOptions: false, // if true, ignore all kind of URL options in the browser URL
180  HierarchyLimit: 250, // how many items shown on one level of hierarchy
181  SmallPad: { width: 150, height: 100 }, // size of pad, where many features will be deactivated like text draw or zooming
182 
183  // XValuesFormat : "6.4g", // custom format for all X values
184  // YValuesFormat : "6.4g", // custom format for all Y values
185  // ZValuesFormat : "6.4g", // custom format for all Z values
186 
187  // these are TStyle attributes, which can be changed via URL 'style' parameter or delivered by TWebCanvas
188 
189  fOptLogx: 0,
190  fOptLogy: 0,
191  fOptLogz: 0,
192  fOptDate: 0,
193  fOptFile: 0,
194  fOptTitle: 1,
195  fPadBottomMargin: 0.1,
196  fPadTopMargin: 0.1,
197  fPadLeftMargin: 0.1,
198  fPadRightMargin: 0.1,
199  fPadGridX: false,
200  fPadGridY: false,
201  fPadTickX: 0,
202  fPadTickY: 0,
203  fStatColor: 0,
204  fStatTextColor: 1,
205  fStatBorderSize: 1,
206  fStatFont: 42,
207  fStatFontSize: 0,
208  fStatStyle: 1001,
209  fStatFormat: "6.4g",
210  fStatX: 0.98,
211  fStatY: 0.935,
212  fStatW: 0.2,
213  fStatH: 0.16,
214  fTitleAlign: 23,
215  fTitleColor: 0,
216  fTitleTextColor: 1,
217  fTitleBorderSize: 0,
218  fTitleFont: 42,
219  fTitleFontSize: 0.05,
220  fTitleStyle: 0,
221  fTitleX: 0.5,
222  fTitleY: 0.995,
223  fTitleW: 0,
224  fTitleH: 0,
225  fFitFormat: "5.4g",
226  fOptStat: 1111,
227  fOptFit: 0,
228  fNumberContours: 20,
229  fGridColor: 0,
230  fGridStyle: 3,
231  fGridWidth: 1,
232  fFrameFillColor: 0,
233  fFrameFillStyle: 1001,
234  fFrameLineColor: 1,
235  fFrameLineWidth: 1,
236  fFrameLineStyle: 1,
237  fFrameBorderSize: 1,
238  fFrameBorderMode: 0,
239  fEndErrorSize: 2, // size in pixels of end error for E1 draw options
240  fErrorX: 0.5, // X size of the error marks for the histogram drawings
241  fHistMinimumZero: false, // when true, BAR and LEGO drawing using base = 0
242  fPaintTextFormat : "g",
243  fTimeOffset : 788918400 // UTC time at 01/01/95
244  };
245 
251  JSROOT.BIT = function(n) { return 1 << (n); }
252 
255  JSROOT.TH1StatusBits = {
256  kNoStats : JSROOT.BIT(9), // don't draw stats box
257  kUserContour : JSROOT.BIT(10), // user specified contour levels
258  kCanRebin : JSROOT.BIT(11), // can rebin axis
259  kLogX : JSROOT.BIT(15), // X-axis in log scale
260  kIsZoomed : JSROOT.BIT(16), // bit set when zooming on Y axis
261  kNoTitle : JSROOT.BIT(17), // don't draw the histogram title
262  kIsAverage : JSROOT.BIT(18) // Bin contents are average (used by Add)
263  };
264 
267  JSROOT.console = function(value, divid) {
268  if ((typeof divid == 'string') && document.getElementById(divid))
269  document.getElementById(divid).innerHTML = value;
270  else
271  if ((typeof console != 'undefined') && (typeof console.log == 'function'))
272  console.log(value);
273  }
274 
277  JSROOT.alert = function(msg) {
278  if (this.nodeis) throw new Error(msg);
279  if (typeof alert === 'function') alert(msg);
280  else JSROOT.console('ALERT: ' + msg);
281  }
282 
289  JSROOT.seed = function(i) {
290  i = Math.abs(i);
291  if (i > 1e8) i = Math.abs(1e8 * Math.sin(i)); else
292  if (i < 1) i*=1e8;
293  this.m_w = Math.round(i);
294  this.m_z = 987654321;
295  }
296 
304  JSROOT.random = function() {
305  if (this.m_z===undefined) return Math.random();
306  this.m_z = (36969 * (this.m_z & 65535) + (this.m_z >> 16)) & 0xffffffff;
307  this.m_w = (18000 * (this.m_w & 65535) + (this.m_w >> 16)) & 0xffffffff;
308  var result = ((this.m_z << 16) + this.m_w) & 0xffffffff;
309  result /= 4294967296;
310  return result + 0.5;
311  }
312 
322  JSROOT.JSONR_unref = function(obj) {
323 
324  var map = [], newfmt = undefined;
325 
326  function unref_value(value) {
327  if ((value===null) || (value===undefined)) return;
328 
329  if (typeof value === 'string') {
330  if (newfmt || (value.length < 6) || (value.indexOf("$ref:") !== 0)) return;
331  var ref = parseInt(value.substr(5));
332  if (isNaN(ref) || (ref < 0) || (ref >= map.length)) return;
333  newfmt = false;
334  return map[ref];
335  }
336 
337  if (typeof value !== 'object') return;
338 
339  var i, k, res, proto = Object.prototype.toString.apply(value);
340 
341  // scan array - it can contain other objects
342  if ((proto.indexOf('[object')==0) && (proto.indexOf('Array]')>0)) {
343  for (i = 0; i < value.length; ++i) {
344  res = unref_value(value[i]);
345  if (res!==undefined) value[i] = res;
346  }
347  return;
348  }
349 
350  var ks = Object.keys(value), len = ks.length;
351 
352  if ((newfmt!==false) && (len===1) && (ks[0]==='$ref')) {
353  var ref = parseInt(value['$ref']);
354  if (isNaN(ref) || (ref < 0) || (ref >= map.length)) return;
355  newfmt = true;
356  return map[ref];
357  }
358 
359  if ((newfmt!==false) && (len>1) && (ks[0]==='$arr') && (ks[1]==='len')) {
360  // this is ROOT-coded array
361  var arr = null, dflt = (value.$arr==="Bool") ? false : 0;
362  switch (value.$arr) {
363  case "Int8" : arr = new Int8Array(value.len); break;
364  case "Uint8" : arr = new Uint8Array(value.len); break;
365  case "Int16" : arr = new Int16Array(value.len); break;
366  case "Uint16" : arr = new Uint16Array(value.len); break;
367  case "Int32" : arr = new Int32Array(value.len); break;
368  case "Uint32" : arr = new Uint32Array(value.len); break;
369  case "Float32" : arr = new Float32Array(value.len); break;
370  case "Int64" :
371  case "Uint64" :
372  case "Float64" : arr = new Float64Array(value.len); break;
373  default : arr = new Array(value.len); break;
374  }
375  for (var k=0;k<value.len;++k) arr[k] = dflt;
376 
377  if (value.b !== undefined) {
378  // base64 coding
379  var buf = atob(value.b);
380 
381  if (arr.buffer) {
382  var dv = new DataView(arr.buffer, value.o || 0),
383  len = Math.min(buf.length, dv.byteLength);
384  for (var k=0; k<len; ++k)
385  dv.setUint8(k, buf.charCodeAt(k));
386  } else {
387  throw new Error('base64 coding supported only for native arrays with binary data');
388  }
389  } else {
390  // compressed coding
391  var nkey = 2, p = 0;
392  while (nkey<len) {
393  if (ks[nkey][0]=="p") p = value[ks[nkey++]]; // position
394  if (ks[nkey][0]!=='v') throw new Error('Unexpected member ' + ks[nkey] + ' in array decoding');
395  var v = value[ks[nkey++]]; // value
396  if (typeof v === 'object') {
397  for (var k=0;k<v.length;++k) arr[p++] = v[k];
398  } else {
399  arr[p++] = v;
400  if ((nkey<len) && (ks[nkey][0]=='n')) {
401  var cnt = value[ks[nkey++]]; // counter
402  while (--cnt) arr[p++] = v;
403  }
404  }
405  }
406  }
407 
408  return arr;
409  }
410 
411  if ((newfmt!==false) && (len===3) && (ks[0]==='$pair') && (ks[1]==='first') && (ks[2]==='second')) {
412  newfmt = true;
413  var f1 = unref_value(value.first),
414  s1 = unref_value(value.second);
415  if (f1!==undefined) value.first = f1;
416  if (s1!==undefined) value.second = s1;
417  value._typename = value['$pair'];
418  delete value['$pair'];
419  return; // pair object is not counted in the objects map
420  }
421 
422  // debug code, can be commented out later
423  if (map.indexOf(value) >= 0) {
424  JSROOT.console('should never happen - object already in the map');
425  return;
426  }
427 
428  // add object to object map
429  map.push(value);
430 
431  // add methods to all objects, where _typename is specified
432  if ('_typename' in value) JSROOT.addMethods(value);
433 
434  for (k = 0; k < len; ++k) {
435  i = ks[k];
436  res = unref_value(value[i]);
437  if (res!==undefined) value[i] = res;
438  }
439  }
440 
441  unref_value(obj);
442 
443  return obj;
444  }
445 
446  JSROOT.debug = 0;
447 
451  JSROOT.extend = function(tgt, src) {
452  if ((src === null) || (typeof src !== 'object')) return tgt;
453  if ((tgt === null) || (typeof tgt !== 'object')) tgt = {};
454 
455  for (var k in src)
456  tgt[k] = src[k];
457 
458  return tgt;
459  }
460 
463  JSROOT.clone = function(src, map, nofunc) {
464  if (src === null) return null;
465 
466  if (!map) {
467  map = { obj:[], clones:[], nofunc: nofunc };
468  } else {
469  var i = map.obj.indexOf(src);
470  if (i>=0) return map.clones[i];
471  }
472 
473  var proto = Object.prototype.toString.apply(src);
474 
475  // process normal array
476  if (proto === '[object Array]') {
477  var tgt = [];
478  map.obj.push(src);
479  map.clones.push(tgt);
480  for (var i = 0; i < src.length; ++i)
481  if (typeof src[i] === 'object')
482  tgt.push(JSROOT.clone(src[i], map));
483  else
484  tgt.push(src[i]);
485 
486  return tgt;
487  }
488 
489  // process typed array
490  if ((proto.indexOf('[object ') == 0) && (proto.indexOf('Array]') == proto.length-6)) {
491  var tgt = [];
492  map.obj.push(src);
493  map.clones.push(tgt);
494  for (var i = 0; i < src.length; ++i)
495  tgt.push(src[i]);
496 
497  return tgt;
498  }
499 
500  var tgt = {};
501  map.obj.push(src);
502  map.clones.push(tgt);
503 
504  for (var k in src) {
505  if (typeof src[k] === 'object')
506  tgt[k] = JSROOT.clone(src[k], map);
507  else
508  if (!map.nofunc || (typeof src[k]!=='function'))
509  tgt[k] = src[k];
510  }
511 
512  return tgt;
513  }
514 
523  JSROOT.clear_func = function(src, map) {
524  if (src === null) return src;
525 
526  var proto = Object.prototype.toString.apply(src);
527 
528  if (proto === '[object Array]') {
529  for (var n=0;n<src.length;n++)
530  if (typeof src[n] === 'object')
531  JSROOT.clear_func(src[n], map);
532  return src;
533  }
534 
535  if ((proto.indexOf('[object ') == 0) && (proto.indexOf('Array]') == proto.length-6)) return src;
536 
537  if (!map) map = [];
538  var nomap = (map.length == 0);
539  if ('__clean_func__' in src) return src;
540 
541  map.push(src);
542  src['__clean_func__'] = true;
543 
544  for (var k in src) {
545  if (typeof src[k] === 'object')
546  JSROOT.clear_func(src[k], map);
547  else
548  if (typeof src[k] === 'function') delete src[k];
549  }
550 
551  if (nomap)
552  for (var n=0;n<map.length;++n)
553  delete map[n]['__clean_func__'];
554 
555  return src;
556  }
557 
564  JSROOT.parse = function(json) {
565  if (!json) return null;
566  var obj = JSON.parse(json);
567  return obj ? this.JSONR_unref(obj) : obj;
568  }
569 
577  JSROOT.parse_multi = function(json) {
578  if (!json) return null;
579  var arr = JSON.parse(json);
580  if (arr && arr.length)
581  for (var i=0;i<arr.length;++i)
582  arr[i] = this.JSONR_unref(arr[i]);
583  return arr;
584  }
585 
592  JSROOT.toJSON = function(obj) {
593  if (!obj || typeof obj !== 'object') return "";
594 
595  var map = []; // map of stored objects
596 
597  function copy_value(value) {
598  if (typeof value === "function") return undefined;
599 
600  if ((value===undefined) || (value===null) || (typeof value !== 'object')) return value;
601 
602  var proto = Object.prototype.toString.apply(value);
603 
604  // typed array need to be converted into normal array, otherwise looks strange
605  if ((proto.indexOf('[object ') == 0) && (proto.indexOf('Array]') == proto.length-6)) {
606  var arr = new Array(value.length)
607  for (var i = 0; i < value.length; ++i)
608  arr[i] = copy_value(value[i]);
609  return arr;
610  }
611 
612  // this is how reference is code
613  var refid = map.indexOf(value);
614  if (refid >= 0) return { $ref: refid };
615 
616  var ks = Object.keys(value), len = ks.length, tgt = {};
617 
618  if ((len == 3) && (ks[0]==='$pair') && (ks[1]==='first') && (ks[2]==='second')) {
619  // special handling of pair objects which does not included into objects map
620  tgt.$pair = value.$pair;
621  tgt.first = copy_value(value.first);
622  tgt.second = copy_value(value.second);
623  return tgt;
624  }
625 
626  map.push(value);
627 
628  for (var k = 0; k < len; ++k) {
629  var name = ks[k];
630  tgt[name] = copy_value(value[name]);
631  }
632 
633  return tgt;
634  }
635 
636  var tgt = copy_value(obj);
637 
638  return JSON.stringify(tgt);
639  }
640 
653  JSROOT.GetUrlOption = function(opt, url, dflt) {
654 
655  if (dflt === undefined) dflt = null;
656  if ((opt===null) || (typeof opt != 'string') || (opt.length==0)) return dflt;
657 
658  if (!url) {
659  if (JSROOT.gStyle.IgnoreUrlOptions || (typeof document === 'undefined')) return dflt;
660  url = document.URL;
661  }
662 
663  var pos = url.indexOf("?"), nquotes;
664  if (pos<0) return dflt;
665  url = decodeURI(url.slice(pos+1));
666 
667  while (url.length>0) {
668 
669  if (url==opt) return "";
670 
671  // try to correctly handle quotes in the URL
672  pos = 0; nquotes = 0;
673  while ((pos < url.length) && ((nquotes!==0) || (url[pos]!=="&"))) {
674  switch (url[pos]) {
675  case "'": if (nquotes>=0) nquotes = (nquotes+1)%2; break;
676  case '"': if (nquotes<=0) nquotes = (nquotes-1)%2; break;
677  }
678  pos++;
679  }
680 
681  if (url.indexOf(opt) == 0) {
682  if (url[opt.length]=="&") return "";
683 
684  if (url[opt.length]==="=") {
685  url = url.slice(opt.length+1, pos);
686  if (((url[0]==="'") || (url[0]==='"')) && (url[0]===url[url.length-1])) url = url.substr(1, url.length-2);
687  return url;
688  }
689  }
690 
691  url = url.substr(pos+1);
692  }
693  return dflt;
694  }
695 
704  JSROOT.ParseAsArray = function(val) {
705 
706  var res = [];
707 
708  if (typeof val != 'string') return res;
709 
710  val = val.trim();
711  if (val=="") return res;
712 
713  // return as array with single element
714  if ((val.length<2) || (val[0]!='[') || (val[val.length-1]!=']')) {
715  res.push(val); return res;
716  }
717 
718  // try to split ourself, checking quotes and brackets
719  var nbr = 0, nquotes = 0, ndouble = 0, last = 1;
720 
721  for (var indx = 1; indx < val.length; ++indx) {
722  if (nquotes > 0) {
723  if (val[indx]==="'") nquotes--;
724  continue;
725  }
726  if (ndouble > 0) {
727  if (val[indx]==='"') ndouble--;
728  continue;
729  }
730  switch (val[indx]) {
731  case "'": nquotes++; break;
732  case '"': ndouble++; break;
733  case "[": nbr++; break;
734  case "]": if (indx < val.length - 1) { nbr--; break; }
735  case ",":
736  if (nbr === 0) {
737  var sub = val.substring(last, indx).trim();
738  if ((sub.length>1) && (sub[0]==sub[sub.length-1]) && ((sub[0]=='"') || (sub[0]=="'")))
739  sub = sub.substr(1, sub.length-2);
740  res.push(sub);
741  last = indx+1;
742  }
743  break;
744  }
745  }
746 
747  if (res.length === 0)
748  res.push(val.substr(1, val.length-2).trim());
749 
750  return res;
751  }
752 
761  JSROOT.GetUrlOptionAsArray = function(opt, url) {
762 
763  var res = [];
764 
765  while (opt.length>0) {
766  var separ = opt.indexOf(";");
767  var part = (separ>0) ? opt.substr(0, separ) : opt;
768 
769  if (separ>0) opt = opt.substr(separ+1); else opt = "";
770 
771  var canarray = true;
772  if (part[0]=='#') { part = part.substr(1); canarray = false; }
773 
774  var val = this.GetUrlOption(part, url, null);
775 
776  if (canarray) res = res.concat(JSROOT.ParseAsArray(val));
777  else if (val!==null) res.push(val);
778  }
779  return res;
780  }
781 
789  JSROOT.findFunction = function(name) {
790  if (typeof name === 'function') return name;
791  if (typeof name !== 'string') return null;
792  var names = name.split('.'), elem = null;
793  if (typeof window === 'object') elem = window;
794  if (names[0]==='JSROOT') { elem = this; names.shift(); }
795 
796  for (var n=0;elem && (n<names.length);++n)
797  elem = elem[names[n]];
798 
799  return (typeof elem == 'function') ? elem : null;
800  }
801 
812  JSROOT.CallBack = function(func, arg1, arg2) {
813 
814  if (typeof func == 'string') func = JSROOT.findFunction(func);
815 
816  if (!func) return;
817 
818  if (typeof func == 'function') return func(arg1,arg2);
819 
820  if (typeof func != 'object') return;
821 
822  if (('obj' in func) && ('func' in func) &&
823  (typeof func.obj == 'object') && (typeof func.func == 'string') &&
824  (typeof func.obj[func.func] == 'function')) {
825  return func.obj[func.func](arg1, arg2);
826  }
827  }
828 
860  JSROOT.NewHttpRequest = function(url, kind, user_call_back) {
861 
862  var xhr = JSROOT.nodejs ? new (require("xhr2"))() : new XMLHttpRequest();
863 
864  xhr.http_callback = (typeof user_call_back == 'function') ? user_call_back.bind(xhr) : function() {};
865 
866  if (!kind) kind = "buf";
867 
868  var method = "GET", async = true, p = kind.indexOf(";sync");
869  if (p>0) { kind = kind.substr(0,p); async = false; }
870  if (kind === "head") method = "HEAD"; else
871  if ((kind === "post") || (kind === "multi") || (kind === "posttext")) method = "POST";
872 
873  xhr.kind = kind;
874 
875  if (JSROOT.wrong_http_response_handling && (method == "GET") && (typeof xhr.addEventListener === 'function'))
876  xhr.addEventListener("progress", function(oEvent) {
877  if (oEvent.lengthComputable && this.expected_size && (oEvent.loaded > this.expected_size)) {
878  this.did_abort = true;
879  this.abort();
880  console.warn('Server sends more bytes ' + oEvent.loaded + ' than expected ' + this.expected_size + '. Abort I/O operation');
881  this.http_callback(null);
882  }
883  }.bind(xhr));
884 
885  xhr.onreadystatechange = function() {
886 
887  if (this.did_abort) return;
888 
889  if ((this.readyState === 2) && this.expected_size) {
890  var len = parseInt(this.getResponseHeader("Content-Length"));
891  if (!isNaN(len) && (len>this.expected_size) && !JSROOT.wrong_http_response_handling) {
892  this.did_abort = true;
893  this.abort();
894  console.warn('Server response size ' + len + ' larger than expected ' + this.expected_size + '. Abort I/O operation');
895  return this.http_callback(null);
896  }
897  }
898 
899  if (this.readyState != 4) return;
900 
901  if ((this.status != 200) && (this.status != 206) && !JSROOT.browser.qt5 &&
902  // in these special cases browsers not always set status
903  !((this.status == 0) && ((url.indexOf("file://")==0) || (url.indexOf("blob:")==0)))) {
904  return this.http_callback(null);
905  }
906 
907  if (this.nodejs_checkzip && (this.getResponseHeader("content-encoding") == "gzip")) {
908  // special handling of gzipped JSON objects in Node.js
909  var zlib = require('zlib'),
910  str = zlib.unzipSync(Buffer.from(this.response));
911  return this.http_callback(JSROOT.parse(str));
912  }
913 
914  switch(this.kind) {
915  case "xml": return this.http_callback(this.responseXML);
916  case "posttext":
917  case "text": return this.http_callback(this.responseText);
918  case "object": return this.http_callback(JSROOT.parse(this.responseText));
919  case "multi": return this.http_callback(JSROOT.parse_multi(this.responseText));
920  case "head": return this.http_callback(this);
921  }
922 
923  // if no response type is supported, return as text (most probably, will fail)
924  if (this.responseType === undefined)
925  return this.http_callback(this.responseText);
926 
927  if ((this.kind == "bin") && ('byteLength' in this.response)) {
928  // if string representation in requested - provide it
929 
930  var filecontent = "", u8Arr = new Uint8Array(this.response);
931  for (var i = 0; i < u8Arr.length; ++i)
932  filecontent += String.fromCharCode(u8Arr[i]);
933 
934  return this.http_callback(filecontent);
935  }
936 
937  this.http_callback(this.response);
938  }
939 
940  xhr.open(method, url, async);
941 
942  if ((kind == "bin") || (kind == "buf")) xhr.responseType = 'arraybuffer';
943 
944  if (JSROOT.nodejs && (method == "GET") && (kind === "object") && (url.indexOf('.json.gz')>0)) {
945  xhr.nodejs_checkzip = true;
946  xhr.responseType = 'arraybuffer';
947  }
948 
949  return xhr;
950  }
951 
964  JSROOT.loadScript = function(urllist, callback, debugout, from_previous) {
965 
966  delete JSROOT.complete_script_load;
967 
968  if (from_previous) {
969  if (debugout)
970  document.getElementById(debugout).innerHTML = "";
971  else
972  JSROOT.progress();
973 
974  if (!urllist) return JSROOT.CallBack(callback);
975  }
976 
977  if (!urllist) return JSROOT.CallBack(callback);
978 
979  var filename = urllist, separ = filename.indexOf(";"),
980  isrootjs = false, isbower = false;
981 
982  if (separ>0) {
983  filename = filename.substr(0, separ);
984  urllist = urllist.substr(separ+1);
985  } else {
986  urllist = "";
987  }
988 
989  var completeLoad = JSROOT.loadScript.bind(JSROOT, urllist, callback, debugout, true);
990 
991  if (filename.indexOf('&&&scripts/')===0) {
992  isrootjs = true;
993  filename = filename.slice(3);
994  if (JSROOT.use_full_libs) filename = "libs/" + filename.slice(8, filename.length-7) + ".js";
995  } else if (filename.indexOf("$$$")===0) {
996  isrootjs = true;
997  filename = filename.slice(3);
998  if ((filename.indexOf("style/")==0) && JSROOT.source_min &&
999  (filename.lastIndexOf('.css')==filename.length-4) &&
1000  (filename.indexOf('.min.css')<0))
1001  filename = filename.slice(0, filename.length-4) + '.min.css';
1002  } else if (filename.indexOf("###")===0) {
1003  isbower = true;
1004  filename = filename.slice(3);
1005  }
1006 
1007  if (JSROOT.nodejs) {
1008  if ((filename.indexOf("scripts/")===0) && (filename.indexOf(".js")>0)) {
1009  console.log('load', filename);
1010  require("." + filename.substr(7));
1011  }
1012  return completeLoad();
1013  }
1014 
1015  var isstyle = filename.indexOf('.css') > 0;
1016 
1017  if (isstyle) {
1018  var styles = document.getElementsByTagName('link');
1019  for (var n = 0; n < styles.length; ++n) {
1020  if (!styles[n].href || (styles[n].type !== 'text/css') || (styles[n].rel !== 'stylesheet')) continue;
1021 
1022  if (styles[n].href.indexOf(filename)>=0) return completeLoad();
1023  }
1024 
1025  } else {
1026  var scripts = document.getElementsByTagName('script');
1027 
1028  for (var n = 0; n < scripts.length; ++n) {
1029  var src = scripts[n].src;
1030  if (!src) continue;
1031 
1032  if ((src.indexOf(filename)>=0) && (src.indexOf("load=")<0))
1033  // avoid wrong decision when script name is specified as more argument
1034  return completeLoad();
1035  }
1036  }
1037 
1038  if (isrootjs && JSROOT.source_dir) filename = JSROOT.source_dir + filename; else
1039  if (isbower && (JSROOT.bower_dir!==null)) filename = JSROOT.bower_dir + filename;
1040 
1041  var element = null;
1042 
1043  if (debugout)
1044  document.getElementById(debugout).innerHTML = "loading " + filename + " ...";
1045  else
1046  JSROOT.progress("loading " + filename + " ...");
1047 
1048  if (JSROOT.nocache && isrootjs && (filename.indexOf("?")<0))
1049  filename += "?stamp=" + JSROOT.nocache;
1050 
1051  if (isstyle) {
1052  element = document.createElement("link");
1053  element.setAttribute("rel", "stylesheet");
1054  element.setAttribute("type", "text/css");
1055  element.setAttribute("href", filename);
1056  } else {
1057  element = document.createElement("script");
1058  element.setAttribute('type', "text/javascript");
1059  element.setAttribute('src', filename);
1060  }
1061 
1062  JSROOT.complete_script_load = completeLoad;
1063 
1064  if (element.readyState) { // Internet Explorer specific
1065  element.onreadystatechange = function() {
1066  if (element.readyState == "loaded" || element.readyState == "complete") {
1067  element.onreadystatechange = null;
1068  if (JSROOT.complete_script_load) JSROOT.complete_script_load();
1069  }
1070  }
1071  } else { // Other browsers
1072  element.onload = function() {
1073  element.onload = null;
1074  if (JSROOT.complete_script_load) JSROOT.complete_script_load();
1075  }
1076  }
1077 
1078  document.getElementsByTagName("head")[0].appendChild(element);
1079  }
1080 
1116  JSROOT.AssertPrerequisites = function(kind, callback, debugout) {
1117  // one could specify kind of requirements
1118 
1119  var jsroot = JSROOT;
1120 
1121  if (jsroot.doing_assert === undefined) jsroot.doing_assert = [];
1122  if (jsroot.ready_modules === undefined) jsroot.ready_modules = [];
1123 
1124  if (!kind || (typeof kind !== 'string'))
1125  return jsroot.CallBack(callback);
1126 
1127  if (kind === '__next__') {
1128  if (jsroot.doing_assert.length==0) return;
1129  var req = jsroot.doing_assert[0];
1130  if (req.running) return;
1131  kind = req._kind;
1132  callback = req._callback;
1133  debugout = req._debug;
1134  } else {
1135  jsroot.doing_assert.push({_kind:kind, _callback:callback, _debug: debugout});
1136  if (jsroot.doing_assert.length > 1) return;
1137  }
1138 
1139  function normal_callback() {
1140  var req = jsroot.doing_assert.shift();
1141  for (var n=0;n<req.modules.length;++n)
1142  jsroot.ready_modules.push(req.modules[n]);
1143  jsroot.CallBack(req._callback);
1144  jsroot.AssertPrerequisites('__next__');
1145  }
1146 
1147  jsroot.doing_assert[0].running = true;
1148 
1149  if (kind[kind.length-1]!=";") kind+=";";
1150  var ext = jsroot.source_min ? ".min" : "",
1151  need_jquery = false,
1152  use_require = (typeof define === "function") && define.amd,
1153  use_bower = jsroot.bower_dir!==null,
1154  mainfiles = "",
1155  extrafiles = "", // scripts for direct loading
1156  modules = [], // modules used for require.js
1157  load_callback = normal_callback;
1158 
1159  if ((kind.indexOf('io;')>=0) || (kind.indexOf('tree;')>=0))
1160  if (jsroot.sources.indexOf("io")<0) {
1161  mainfiles += "&&&scripts/rawinflate.min.js;" +
1162  "$$$scripts/JSRootIOEvolution" + ext + ".js;";
1163  modules.push('rawinflate', 'JSRootIOEvolution');
1164  }
1165 
1166  if ((kind.indexOf('math;')>=0) || (kind.indexOf('tree;')>=0) || (kind.indexOf('more2d;')>=0))
1167  if (jsroot.sources.indexOf("math")<0) {
1168  mainfiles += '$$$scripts/JSRootMath' + ext + ".js;";
1169  modules.push('JSRootMath');
1170  }
1171 
1172  if (kind.indexOf('tree;')>=0)
1173  if (jsroot.sources.indexOf("tree")<0) {
1174  mainfiles += "$$$scripts/JSRootTree" + ext + ".js;";
1175  modules.push('JSRootTree');
1176  }
1177 
1178  if ((kind.indexOf('2d;')>=0) || (kind.indexOf('v6;')>=0) || (kind.indexOf('v7;')>=0) ||
1179  (kind.indexOf("3d;")>=0) || (kind.indexOf("geom;")>=0)) {
1180  if (!use_require && (typeof d3 != 'object') && (jsroot._test_d3_ === undefined)) {
1181  mainfiles += use_bower ? '###d3/d3.min.js;' : '&&&scripts/d3.min.js;';
1182  jsroot._test_d3_ = null;
1183  }
1184  if (jsroot.sources.indexOf("2d") < 0) {
1185  modules.push('JSRootPainter');
1186  mainfiles += '$$$scripts/JSRootPainter' + ext + ".js;";
1187  extrafiles += '$$$style/JSRootPainter' + ext + '.css;';
1188  }
1189  if ((jsroot.sources.indexOf("v6") < 0) && (kind.indexOf('v7;') < 0)) {
1190  mainfiles += '$$$scripts/JSRootPainter.v6' + ext + ".js;";
1191  modules.push('JSRootPainter.v6');
1192  }
1193  }
1194 
1195  if (kind.indexOf('jq;')>=0) need_jquery = true;
1196 
1197  if (((kind.indexOf('hist;')>=0) || (kind.indexOf('hist3d;')>=0)) && (jsroot.sources.indexOf("hist")<0)) {
1198  mainfiles += '$$$scripts/JSRootPainter.hist' + ext + ".js;";
1199  modules.push('JSRootPainter.hist');
1200  }
1201 
1202  if ((kind.indexOf('v6;')>=0) && (jsroot.sources.indexOf("v6")<0)) {
1203  mainfiles += '$$$scripts/JSRootPainter.v6' + ext + ".js;";
1204  modules.push('JSRootPainter.v6');
1205  }
1206 
1207  if ((kind.indexOf('v7;')>=0) && (jsroot.sources.indexOf("v7")<0)) {
1208  mainfiles += '$$$scripts/JSRootPainter.v7' + ext + ".js;";
1209  modules.push('JSRootPainter.v7');
1210  }
1211 
1212  if ((kind.indexOf('v7hist;')>=0) && (jsroot.sources.indexOf("v7hist")<0)) {
1213  mainfiles += '$$$scripts/JSRootPainter.v7hist' + ext + ".js;";
1214  modules.push('JSRootPainter.v7hist');
1215  }
1216 
1217  if ((kind.indexOf('v7more;')>=0) && (jsroot.sources.indexOf("v7more")<0)) {
1218  mainfiles += '$$$scripts/JSRootPainter.v7more' + ext + ".js;";
1219  modules.push('JSRootPainter.v7more');
1220  }
1221 
1222  if ((kind.indexOf('more2d;')>=0) && (jsroot.sources.indexOf("more2d")<0)) {
1223  mainfiles += '$$$scripts/JSRootPainter.more' + ext + ".js;";
1224  modules.push('JSRootPainter.more');
1225  }
1226 
1227  if (((kind.indexOf('hierarchy;')>=0) || (kind.indexOf('jq2d;')>=0)) && (jsroot.sources.indexOf("hierarchy")<0)) {
1228  mainfiles += '$$$scripts/JSRootPainter.hierarchy' + ext + ".js;";
1229  modules.push('JSRootPainter.hierarchy');
1230  }
1231 
1232  if ((kind.indexOf('jq2d;')>=0) && (jsroot.sources.indexOf("jq2d")<0)) {
1233  mainfiles += '$$$scripts/JSRootPainter.jquery' + ext + ".js;";
1234  modules.push('JSRootPainter.jquery');
1235  need_jquery = true;
1236  }
1237 
1238  if ((kind.indexOf('openui5;')>=0) && (jsroot.sources.indexOf("openui5")<0)) {
1239  mainfiles += '$$$scripts/JSRoot.openui5' + ext + ".js;";
1240  modules.push('JSRoot.openui5');
1241  need_jquery = true;
1242  }
1243 
1244  if (((kind.indexOf("3d;")>=0) || (kind.indexOf("geom;")>=0)) && (jsroot.sources.indexOf("3d")<0)) {
1245  mainfiles += (use_bower ? "###threejs/build/" : "&&&scripts/") + "three.min.js;" +
1246  "&&&scripts/three.extra.min.js;";
1247  modules.push("threejs", "threejs_all");
1248  mainfiles += "$$$scripts/JSRoot3DPainter" + ext + ".js;";
1249  modules.push('JSRoot3DPainter');
1250  }
1251 
1252  if ((kind.indexOf('hist3d;')>=0) && (jsroot.sources.indexOf("hist3d")<0)) {
1253  mainfiles += '$$$scripts/JSRootPainter.hist3d' + ext + ".js;";
1254  modules.push('JSRootPainter.hist3d');
1255  }
1256 
1257  if (kind.indexOf("datgui;")>=0) {
1258  if (!JSROOT.nodejs && (typeof window !='undefined'))
1259  mainfiles += (use_bower ? "###dat.gui" : "&&&scripts") + "/dat.gui.min.js;";
1260  // console.log('extra loading module dat.gui');
1261  modules.push('dat.gui');
1262  }
1263 
1264  if ((kind.indexOf("geom;")>=0) && (jsroot.sources.indexOf("geom")<0)) {
1265  mainfiles += "$$$scripts/ThreeCSG" + ext + ".js;" +
1266  "$$$scripts/JSRootGeoBase" + ext + ".js;" +
1267  "$$$scripts/JSRootGeoPainter" + ext + ".js;";
1268  extrafiles += "$$$style/JSRootGeoPainter" + ext + ".css;";
1269  modules.push('ThreeCSG', 'JSRootGeoBase', 'JSRootGeoPainter');
1270  }
1271 
1272  if (kind.indexOf("mathjax;")>=0) {
1273 
1274  if (typeof MathJax == 'undefined') {
1275  mainfiles += (use_bower ? "###MathJax" : "https://root.cern/js/mathjax/latest") +
1276  "/MathJax.js?config=TeX-AMS-MML_SVG&delayStartupUntil=configured;";
1277  modules.push('MathJax');
1278 
1279  load_callback = function() {
1280  MathJax.Hub.Config({ jax: ["input/TeX", "output/SVG"],
1281  TeX: { extensions: ["color.js"] },
1282  SVG: { mtextFontInherit: true, minScaleAdjust: 100, matchFontHeight: true, useFontCache: false } });
1283 
1284  MathJax.Hub.Register.StartupHook("SVG Jax Ready",function () {
1285  var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;
1286  VARIANT["normal"].fonts.unshift("MathJax_SansSerif");
1287  VARIANT["bold"].fonts.unshift("MathJax_SansSerif-bold");
1288  VARIANT["italic"].fonts.unshift("MathJax_SansSerif");
1289  VARIANT["-tex-mathit"].fonts.unshift("MathJax_SansSerif");
1290  });
1291 
1292  MathJax.Hub.Configured();
1293 
1294  normal_callback();
1295  }
1296  }
1297  }
1298 
1299  if (kind.indexOf("simple;")>=0) {
1300  need_jquery = true;
1301  }
1302 
1303  if (need_jquery && !jsroot.load_jquery) {
1304  var has_jq = (typeof jQuery != 'undefined'), lst_jq = "";
1305 
1306  if (has_jq)
1307  jsroot.console('Reuse existing jQuery ' + jQuery.fn.jquery + ", required 3.1.1", debugout);
1308  else
1309  lst_jq += (use_bower ? "###jquery/dist" : "&&&scripts") + "/jquery.min.js;";
1310  if (has_jq && typeof $.ui != 'undefined') {
1311  jsroot.console('Reuse existing jQuery-ui ' + $.ui.version + ", required 1.12.1", debugout);
1312  } else {
1313  lst_jq += (use_bower ? "###jquery-ui" : "&&&scripts") + '/jquery-ui.min.js;';
1314  extrafiles += '$$$style/jquery-ui' + ext + '.css;';
1315  }
1316 
1317  if (jsroot.touches) {
1318  lst_jq += use_bower ? '###jqueryui-touch-punch/jquery.ui.touch-punch.min.js;' : '$$$scripts/touch-punch.min.js;';
1319  modules.push('jqueryui-touch-punch');
1320  }
1321 
1322  modules.splice(0, 0, 'jquery', 'jquery-ui', 'jqueryui-mousewheel');
1323  mainfiles = lst_jq + mainfiles;
1324 
1325  jsroot.load_jquery = true;
1326  }
1327 
1328  var pos = kind.indexOf("user:");
1329  if (pos<0) pos = kind.indexOf("load:");
1330  if (pos>=0) extrafiles += kind.slice(pos+5);
1331 
1332  // check if modules already loaded
1333  for (var n=modules.length-1;n>=0;--n)
1334  if (jsroot.ready_modules.indexOf(modules[n])>=0)
1335  modules.splice(n,1);
1336 
1337  // no modules means no main files
1338  if (modules.length===0) mainfiles = "";
1339 
1340  jsroot.doing_assert[0].modules = modules;
1341 
1342  if ((modules.length>0) && (typeof define === "function") && define.amd) {
1343  jsroot.console("loading " + JSON.stringify(modules) + " with require.js", debugout);
1344  require(modules, function() {
1345  jsroot.loadScript(extrafiles, load_callback, debugout);
1346  });
1347  } else {
1348  jsroot.loadScript(mainfiles + extrafiles, load_callback, debugout);
1349  }
1350  }
1351 
1352  // function can be used to open ROOT file, I/O functionality will be loaded when missing
1353  JSROOT.OpenFile = function(filename, callback) {
1354  JSROOT.AssertPrerequisites("io", function() {
1355  JSROOT.OpenFile(filename, callback);
1356  });
1357  }
1358 
1359  // function can be used to draw supported ROOT classes,
1360  // required functionality will be loaded automatically
1361  // if painter pointer required, one should load '2d' functionality itself
1362  // or use callback function which provides painter pointer as first argument
1363  // defined in JSRootPainter.js
1364  JSROOT.draw = function(divid, obj, opt, callback) {
1365  JSROOT.AssertPrerequisites("2d", function() {
1366  JSROOT.draw(divid, obj, opt, callback);
1367  });
1368  }
1369 
1370  // redraw object on given element
1371  // defined in JSRootPainter.js
1372  JSROOT.redraw = function(divid, obj, opt, callback) {
1373  JSROOT.AssertPrerequisites("2d", function() {
1374  JSROOT.redraw(divid, obj, opt, callback);
1375  });
1376  }
1377 
1378  // Create SVG, defined in JSRootPainter.js
1379  JSROOT.MakeSVG = function(args, callback) {
1380  JSROOT.AssertPrerequisites("2d", function() {
1381  JSROOT.MakeSVG(args, callback);
1382  });
1383  }
1384 
1388  JSROOT.BuildSimpleGUI = function(user_scripts, andThen) {
1389  if (typeof user_scripts == 'function') {
1390  andThen = user_scripts;
1391  user_scripts = null;
1392  }
1393 
1394  var debugout = null,
1395  nobrowser = JSROOT.GetUrlOption('nobrowser')!=null,
1396  requirements = "2d;hierarchy;",
1397  simplegui = document.getElementById('simpleGUI');
1398 
1399  if (JSROOT.GetUrlOption('libs')!==null) JSROOT.use_full_libs = true;
1400 
1401  if (simplegui) {
1402  debugout = 'simpleGUI';
1403  if (JSROOT.GetUrlOption('file') || JSROOT.GetUrlOption('files')) requirements += "io;";
1404  if (simplegui.getAttribute('nobrowser') && (simplegui.getAttribute('nobrowser')!="false")) nobrowser = true;
1405  } else if (document.getElementById('onlineGUI')) {
1406  debugout = 'onlineGUI';
1407  } else if (document.getElementById('drawGUI')) {
1408  debugout = 'drawGUI';
1409  nobrowser = true;
1410  } else {
1411  requirements += "io;";
1412  }
1413 
1414  if (user_scripts == 'check_existing_elements') {
1415  user_scripts = null;
1416  if (debugout == null) return;
1417  }
1418 
1419  if (!nobrowser) requirements += 'jq2d;';
1420 
1421  if (!user_scripts) user_scripts = JSROOT.GetUrlOption("autoload") || JSROOT.GetUrlOption("load");
1422 
1423  if (user_scripts) requirements += "load:" + user_scripts + ";";
1424 
1425  JSROOT.AssertPrerequisites(requirements, function() {
1426  JSROOT.CallBack(JSROOT.findFunction(nobrowser ? 'JSROOT.BuildNobrowserGUI' : 'JSROOT.BuildGUI'));
1427  JSROOT.CallBack(andThen);
1428  }, debugout);
1429  }
1430 
1439  JSROOT.Create = function(typename, target) {
1440  var obj = target || {};
1441 
1442  switch (typename) {
1443  case 'TObject':
1444  JSROOT.extend(obj, { fUniqueID: 0, fBits: 0x3000008 });
1445  break;
1446  case 'TNamed':
1447  JSROOT.extend(obj, { fUniqueID: 0, fBits: 0x3000008, fName: "", fTitle: "" });
1448  break;
1449  case 'TList':
1450  case 'THashList':
1451  JSROOT.extend(obj, { name: typename, arr : [], opt : [] });
1452  break;
1453  case 'TAttAxis':
1454  JSROOT.extend(obj, { fNdivisions: 510, fAxisColor: 1,
1455  fLabelColor: 1, fLabelFont: 42, fLabelOffset: 0.005, fLabelSize: 0.035, fTickLength: 0.03,
1456  fTitleOffset: 1, fTitleSize: 0.035, fTitleColor: 1, fTitleFont : 42 });
1457  break;
1458  case 'TAxis':
1459  JSROOT.Create("TNamed", obj);
1460  JSROOT.Create("TAttAxis", obj);
1461  JSROOT.extend(obj, { fNbins: 0, fXmin: 0, fXmax: 0, fXbins : [], fFirst: 0, fLast: 0,
1462  fBits2: 0, fTimeDisplay: false, fTimeFormat: "", fLabels: null, fModLabs: null });
1463  break;
1464  case 'TAttLine':
1465  JSROOT.extend(obj, { fLineColor: 1, fLineStyle: 1, fLineWidth: 1 });
1466  break;
1467  case 'TAttFill':
1468  JSROOT.extend(obj, { fFillColor: 0, fFillStyle: 0 } );
1469  break;
1470  case 'TAttMarker':
1471  JSROOT.extend(obj, { fMarkerColor: 1, fMarkerStyle: 1, fMarkerSize: 1. });
1472  break;
1473  case 'TLine':
1474  JSROOT.Create("TObject", obj);
1475  JSROOT.Create("TAttLine", obj);
1476  JSROOT.extend(obj, { fX1: 0, fX2: 1, fY1: 0, fY2: 1 });
1477  break;
1478  case 'TBox':
1479  JSROOT.Create("TObject", obj);
1480  JSROOT.Create("TAttLine", obj);
1481  JSROOT.Create("TAttFill", obj);
1482  JSROOT.extend(obj, { fX1: 0, fX2: 1, fY1: 0, fY2: 1 });
1483  break;
1484  case 'TPave':
1485  JSROOT.Create("TBox", obj);
1486  JSROOT.extend(obj, { fX1NDC : 0., fY1NDC: 0, fX2NDC: 1, fY2NDC: 1,
1487  fBorderSize: 0, fInit: 1, fShadowColor: 1,
1488  fCornerRadius: 0, fOption: "blNDC", fName: "title" });
1489  break;
1490  case 'TAttText':
1491  JSROOT.extend(obj, { fTextAngle: 0, fTextSize: 0, fTextAlign: 22, fTextColor: 1, fTextFont: 42});
1492  break;
1493  case 'TPaveText':
1494  JSROOT.Create("TPave", obj);
1495  JSROOT.Create("TAttText", obj);
1496  JSROOT.extend(obj, { fLabel: "", fLongest: 27, fMargin: 0.05, fLines: JSROOT.Create("TList") });
1497  break;
1498  case 'TPaveStats':
1499  JSROOT.Create("TPaveText", obj);
1500  JSROOT.extend(obj, { fOptFit: 0, fOptStat: 0, fFitFormat: "", fStatFormat: "", fParent: null });
1501  break;
1502  case 'TLegend':
1503  JSROOT.Create("TPave", obj);
1504  JSROOT.Create("TAttText", obj);
1505  JSROOT.extend(obj, { fColumnSeparation: 0, fEntrySeparation: 0.1, fMargin: 0.25, fNColumns: 1, fPrimitives: JSROOT.Create("TList") });
1506  break;
1507  case 'TLegendEntry':
1508  JSROOT.Create("TObject", obj);
1509  JSROOT.Create("TAttText", obj);
1510  JSROOT.Create("TAttLine", obj);
1511  JSROOT.Create("TAttFill", obj);
1512  JSROOT.Create("TAttMarker", obj);
1513  JSROOT.extend(obj, { fLabel: "", fObject: null, fOption: "" });
1514  break;
1515  case 'TText':
1516  JSROOT.Create("TNamed", obj);
1517  JSROOT.Create("TAttText", obj);
1518  JSROOT.extend(obj, { fLimitFactorSize: 3, fOriginSize: 0.04 });
1519  break;
1520  case 'TLatex':
1521  JSROOT.Create("TText", obj);
1522  JSROOT.Create("TAttLine", obj);
1523  JSROOT.extend(obj, { fX: 0, fY: 0 });
1524  break;
1525  case 'TObjString':
1526  JSROOT.Create("TObject", obj);
1527  JSROOT.extend(obj, { fString: "" });
1528  break;
1529  case 'TH1':
1530  JSROOT.Create("TNamed", obj);
1531  JSROOT.Create("TAttLine", obj);
1532  JSROOT.Create("TAttFill", obj);
1533  JSROOT.Create("TAttMarker", obj);
1534 
1535  JSROOT.extend(obj, {
1536  fNcells : 0,
1537  fXaxis: JSROOT.Create("TAxis"),
1538  fYaxis: JSROOT.Create("TAxis"),
1539  fZaxis: JSROOT.Create("TAxis"),
1540  fBarOffset: 0, fBarWidth: 1000, fEntries: 0.,
1541  fTsumw: 0., fTsumw2: 0., fTsumwx: 0., fTsumwx2: 0.,
1542  fMaximum: -1111., fMinimum: -1111, fNormFactor: 0., fContour: [],
1543  fSumw2: [], fOption: "",
1544  fFunctions: JSROOT.Create("TList"),
1545  fBufferSize: 0, fBuffer: [], fBinStatErrOpt: 0, fStatOverflows: 2 });
1546  break;
1547  case 'TH1I':
1548  case 'TH1F':
1549  case 'TH1D':
1550  case 'TH1S':
1551  case 'TH1C':
1552  JSROOT.Create("TH1", obj);
1553  obj.fArray = [];
1554  break;
1555  case 'TH2':
1556  JSROOT.Create("TH1", obj);
1557  JSROOT.extend(obj, { fScalefactor: 1., fTsumwy: 0., fTsumwy2: 0, fTsumwxy: 0});
1558  break;
1559  case 'TH2I':
1560  case 'TH2F':
1561  case 'TH2D':
1562  case 'TH2S':
1563  case 'TH2C':
1564  JSROOT.Create("TH2", obj);
1565  obj.fArray = [];
1566  break;
1567  case 'TH3':
1568  JSROOT.Create("TH1", obj);
1569  JSROOT.extend(obj, { fTsumwy: 0., fTsumwy2: 0, fTsumwz: 0., fTsumwz2: 0, fTsumwxy: 0, fTsumwxz: 0, fTsumwyz: 0 });
1570  break;
1571  case 'TH3I':
1572  case 'TH3F':
1573  case 'TH3D':
1574  case 'TH3S':
1575  case 'TH3C':
1576  JSROOT.Create("TH3", obj);
1577  obj.fArray = [];
1578  break;
1579  case 'THStack':
1580  JSROOT.Create("TNamed", obj);
1581  JSROOT.extend(obj, { fHists: JSROOT.Create("TList"), fHistogram: null, fMaximum: -1111, fMinimum: -1111 });
1582  break;
1583  case 'TGraph':
1584  JSROOT.Create("TNamed", obj);
1585  JSROOT.Create("TAttLine", obj);
1586  JSROOT.Create("TAttFill", obj);
1587  JSROOT.Create("TAttMarker", obj);
1588  JSROOT.extend(obj, { fFunctions: JSROOT.Create("TList"), fHistogram: null,
1589  fMaxSize: 0, fMaximum: -1111, fMinimum: -1111, fNpoints: 0, fX: [], fY: [] });
1590  break;
1591  case 'TGraphAsymmErrors':
1592  JSROOT.Create("TGraph", obj);
1593  JSROOT.extend(obj, { fEXlow: [], fEXhigh: [], fEYlow: [], fEYhigh: []});
1594  break;
1595  case 'TMultiGraph':
1596  JSROOT.Create("TNamed", obj);
1597  JSROOT.extend(obj, { fFunctions: JSROOT.Create("TList"), fGraphs: JSROOT.Create("TList"),
1598  fHistogram: null, fMaximum: -1111, fMinimum: -1111 });
1599  break;
1600  case 'TGraphPolargram':
1601  JSROOT.Create("TNamed", obj);
1602  JSROOT.Create("TAttText", obj);
1603  JSROOT.Create("TAttLine", obj);
1604  JSROOT.extend(obj, { fRadian: true, fDegree: false, fGrad: false, fPolarLabelColor: 1, fRadialLabelColor: 1,
1605  fAxisAngle: 0, fPolarOffset: 0.04, fPolarTextSize: 0.04, fRadialOffset: 0.025, fRadialTextSize: 0.035,
1606  fRwrmin: 0, fRwrmax: 1, fRwtmin: 0, fRwtmax: 2*Math.PI, fTickpolarSize: 0.02,
1607  fPolarLabelFont: 62, fRadialLabelFont: 62, fCutRadial: 0, fNdivRad: 508, fNdivPol: 508 });
1608  break;
1609  case 'TPolyLine':
1610  JSROOT.Create("TObject", obj);
1611  JSROOT.Create("TAttLine", obj);
1612  JSROOT.Create("TAttFill", obj);
1613  JSROOT.extend(obj, { fLastPoint: -1, fN: 0, fOption: "", fX: null, fY: null });
1614  break;
1615  case 'TGaxis':
1616  JSROOT.Create("TLine", obj);
1617  JSROOT.Create("TAttText", obj);
1618  JSROOT.extend(obj, { fChopt: "", fFunctionName: "", fGridLength: 0,
1619  fLabelColor: 1, fLabelFont: 42, fLabelOffset: 0.005, fLabelSize: 0.035,
1620  fName: "", fNdiv: 12, fTickSize: 0.02, fTimeFormat: "",
1621  fTitle: "", fTitleOffset: 1, fTitleSize: 0.035,
1622  fWmax: 100, fWmin: 0 });
1623  break;
1624  case 'TAttPad':
1625  JSROOT.extend(obj, { fLeftMargin: JSROOT.gStyle.fPadLeftMargin,
1626  fRightMargin: JSROOT.gStyle.fPadRightMargin,
1627  fBottomMargin: JSROOT.gStyle.fPadBottomMargin,
1628  fTopMargin: JSROOT.gStyle.fPadTopMargin,
1629  fXfile: 2, fYfile: 2, fAfile: 1, fXstat: 0.99, fYstat: 0.99, fAstat: 2,
1630  fFrameFillColor: JSROOT.gStyle.fFrameFillColor,
1631  fFrameFillStyle: JSROOT.gStyle.fFrameFillStyle,
1632  fFrameLineColor: JSROOT.gStyle.fFrameLineColor,
1633  fFrameLineWidth: JSROOT.gStyle.fFrameLineWidth,
1634  fFrameLineStyle: JSROOT.gStyle.fFrameLineStyle,
1635  fFrameBorderSize: JSROOT.gStyle.fFrameBorderSize,
1636  fFrameBorderMode: JSROOT.gStyle.fFrameBorderMode });
1637  break;
1638  case 'TPad':
1639  JSROOT.Create("TObject", obj);
1640  JSROOT.Create("TAttLine", obj);
1641  JSROOT.Create("TAttFill", obj);
1642  JSROOT.Create("TAttPad", obj);
1643  JSROOT.extend(obj, { fX1: 0, fY1: 0, fX2: 1, fY2: 1, fXtoAbsPixelk: 1, fXtoPixelk: 1,
1644  fXtoPixel: 1, fYtoAbsPixelk: 1, fYtoPixelk: 1, fYtoPixel: 1,
1645  fUtoAbsPixelk: 1, fUtoPixelk: 1, fUtoPixel: 1, fVtoAbsPixelk: 1,
1646  fVtoPixelk: 1, fVtoPixel: 1, fAbsPixeltoXk: 1, fPixeltoXk: 1,
1647  fPixeltoX: 1, fAbsPixeltoYk: 1, fPixeltoYk: 1, fPixeltoY: 1,
1648  fXlowNDC: 0, fYlowNDC: 0, fXUpNDC: 0, fYUpNDC: 0, fWNDC: 1, fHNDC: 1,
1649  fAbsXlowNDC: 0, fAbsYlowNDC: 0, fAbsWNDC: 1, fAbsHNDC: 1,
1650  fUxmin: 0, fUymin: 0, fUxmax: 0, fUymax: 0, fTheta: 30, fPhi: 30, fAspectRatio: 0,
1651  fNumber: 0, fLogx: JSROOT.gStyle.fOptLogx, fLogy: JSROOT.gStyle.fOptLogy, fLogz: JSROOT.gStyle.fOptLogz,
1652  fTickx: JSROOT.gStyle.fPadTickX,
1653  fTicky: JSROOT.gStyle.fPadTickY,
1654  fPadPaint: 0, fCrosshair: 0, fCrosshairPos: 0, fBorderSize: 2,
1655  fBorderMode: 0, fModified: false,
1656  fGridx: JSROOT.gStyle.fPadGridX,
1657  fGridy: JSROOT.gStyle.fPadGridY,
1658  fAbsCoord: false, fEditable: true, fFixedAspectRatio: false,
1659  fPrimitives: JSROOT.Create("TList"), fExecs: null,
1660  fName: "pad", fTitle: "canvas" });
1661 
1662  break;
1663  case 'TAttCanvas':
1664  JSROOT.extend(obj, { fXBetween: 2, fYBetween: 2, fTitleFromTop: 1.2,
1665  fXdate: 0.2, fYdate: 0.3, fAdate: 1 });
1666  break;
1667  case 'TCanvas':
1668  JSROOT.Create("TPad", obj);
1669  JSROOT.extend(obj, { fNumPaletteColor: 0, fNextPaletteColor: 0, fDISPLAY: "$DISPLAY",
1670  fDoubleBuffer: 0, fRetained: true, fXsizeUser: 0,
1671  fYsizeUser: 0, fXsizeReal: 20, fYsizeReal: 10,
1672  fWindowTopX: 0, fWindowTopY: 0, fWindowWidth: 0, fWindowHeight: 0,
1673  fCw: 500, fCh: 300, fCatt: JSROOT.Create("TAttCanvas"),
1674  kMoveOpaque: true, kResizeOpaque: true, fHighLightColor: 5,
1675  fBatch: true, kShowEventStatus: false, kAutoExec: true, kMenuBar: true });
1676  break;
1677  case 'TGeoVolume':
1678  JSROOT.Create("TNamed", obj);
1679  JSROOT.Create("TAttLine", obj);
1680  JSROOT.Create("TAttFill", obj);
1681  JSROOT.extend(obj, { fGeoAtt:0, fFinder: null, fMedium: null, fNodes: null, fNtotal: 0, fNumber: 0, fRefCount: 0, fShape: null, fVoxels: null });
1682  break;
1683  case 'TGeoNode':
1684  JSROOT.Create("TNamed", obj);
1685  JSROOT.extend(obj, { fGeoAtt:0, fMother: null, fNovlp: 0, fNumber: 0, fOverlaps: null, fVolume: null });
1686  break;
1687  case 'TGeoNodeMatrix':
1688  JSROOT.Create("TGeoNode", obj);
1689  JSROOT.extend(obj, { fMatrix: null });
1690  break;
1691  case 'TGeoTrack':
1692  JSROOT.Create("TObject", obj);
1693  JSROOT.Create("TAttLine", obj);
1694  JSROOT.Create("TAttMarker", obj);
1695  JSROOT.extend(obj, { fGeoAtt:0, fNpoints: 0, fPoints: [] });
1696  break;
1697  }
1698 
1699  obj._typename = typename;
1700  this.addMethods(obj);
1701  return obj;
1702  }
1703 
1707  JSROOT.CreateTList = function() { return JSROOT.Create("TList"); }
1708 
1712  JSROOT.CreateTAxis = function() { return JSROOT.Create("TAxis"); }
1713 
1720  JSROOT.CreateHistogram = function(typename, nbinsx, nbinsy, nbinsz) {
1721  // create histogram object of specified type
1722  // if bins numbers are specified, appropriate typed array will be created
1723  var histo = JSROOT.Create(typename);
1724  if (!histo.fXaxis || !histo.fYaxis || !histo.fZaxis) return null;
1725  histo.fName = "hist"; histo.fTitle = "title";
1726  if (nbinsx) JSROOT.extend(histo.fXaxis, { fNbins: nbinsx, fXmin: 0, fXmax: nbinsx });
1727  if (nbinsy) JSROOT.extend(histo.fYaxis, { fNbins: nbinsy, fXmin: 0, fXmax: nbinsy });
1728  if (nbinsz) JSROOT.extend(histo.fZaxis, { fNbins: nbinsz, fXmin: 0, fXmax: nbinsz });
1729  switch (parseInt(typename[2])) {
1730  case 1: if (nbinsx) histo.fNcells = nbinsx+2; break;
1731  case 2: if (nbinsx && nbinsy) histo.fNcells = (nbinsx+2) * (nbinsy+2); break;
1732  case 3: if (nbinsx && nbinsy && nbinsz) histo.fNcells = (nbinsx+2) * (nbinsy+2) * (nbinsz+2); break;
1733  }
1734  if (histo.fNcells > 0) {
1735  switch (typename[3]) {
1736  case "C" : histo.fArray = new Int8Array(histo.fNcells); break;
1737  case "S" : histo.fArray = new Int16Array(histo.fNcells); break;
1738  case "I" : histo.fArray = new Int32Array(histo.fNcells); break;
1739  case "F" : histo.fArray = new Float32Array(histo.fNcells); break;
1740  case "L" : histo.fArray = new Float64Array(histo.fNcells); break;
1741  case "D" : histo.fArray = new Float64Array(histo.fNcells); break;
1742  default: histo.fArray = new Array(histo.fNcells); break;
1743  }
1744  for (var i=0;i<histo.fNcells;++i) histo.fArray[i] = 0;
1745  }
1746  return histo;
1747  }
1748 
1752  JSROOT.CreateTH1 = function(nbinsx) {
1753  return JSROOT.CreateHistogram("TH1I", nbinsx);
1754  }
1755 
1759  JSROOT.CreateTH2 = function(nbinsx, nbinsy) {
1760  return JSROOT.CreateHistogram("TH2I", nbinsx, nbinsy);
1761  }
1762 
1766  JSROOT.CreateTH3 = function(nbinsx, nbinsy, nbinsz) {
1767  return JSROOT.CreateHistogram("TH3I", nbinsx, nbinsy, nbinsz);
1768  }
1769 
1773  JSROOT.CreateTPolyLine = function(npoints, use_int32) {
1774  var poly = JSROOT.Create("TPolyLine");
1775  if (npoints) {
1776  poly.fN = npoints;
1777  if (use_int32) {
1778  poly.fX = new Int32Array(npoints);
1779  poly.fY = new Int32Array(npoints);
1780  } else {
1781  poly.fX = new Float32Array(npoints);
1782  poly.fY = new Float32Array(npoints);
1783  }
1784  }
1785 
1786  return poly;
1787  }
1788 
1793  JSROOT.CreateTGraph = function(npoints, xpts, ypts) {
1794  var graph = JSROOT.extend(JSROOT.Create("TGraph"), { fBits: 0x3000408, fName: "graph", fTitle: "title" });
1795 
1796  if (npoints>0) {
1797  graph.fMaxSize = graph.fNpoints = npoints;
1798 
1799  var usex = (typeof xpts == 'object') && (xpts.length === npoints);
1800  var usey = (typeof ypts == 'object') && (ypts.length === npoints);
1801 
1802  for (var i=0;i<npoints;++i) {
1803  graph.fX.push(usex ? xpts[i] : i/npoints);
1804  graph.fY.push(usey ? ypts[i] : i/npoints);
1805  }
1806  }
1807 
1808  return graph;
1809  }
1810 
1821  JSROOT.CreateTHStack = function() {
1822  var stack = JSROOT.Create("THStack");
1823  for(var i=0; i<arguments.length; ++i)
1824  stack.fHists.Add(arguments[i], "");
1825  return stack;
1826  }
1827 
1831  JSROOT.CreateTMultiGraph = function() {
1832  var mgraph = JSROOT.Create("TMultiGraph");
1833  for(var i=0; i<arguments.length; ++i)
1834  mgraph.fGraphs.Add(arguments[i], "");
1835  return mgraph;
1836  }
1837 
1838  JSROOT.methodsCache = {}; // variable used to keep methods for known classes
1839 
1843  JSROOT.getMethods = function(typename, obj) {
1844 
1845  var m = JSROOT.methodsCache[typename],
1846  has_methods = (m!==undefined);
1847 
1848  if (!has_methods) m = {};
1849 
1850  // Due to binary I/O such TObject methods may not be set for derived classes
1851  // Therefore when methods requested for given object, check also that basic methods are there
1852  if ((typename=="TObject") || (typename=="TNamed") || (obj && (obj.fBits!==undefined)))
1853  if (m.TestBit === undefined) {
1854  m.TestBit = function (f) { return (this.fBits & f) != 0; };
1855  m.InvertBit = function (f) { this.fBits = this.fBits ^ (f & 0xffffff); };
1856  }
1857 
1858  if (has_methods) return m;
1859 
1860  if ((typename === 'TList') || (typename === 'THashList')) {
1861  m.Clear = function() {
1862  this.arr = [];
1863  this.opt = [];
1864  }
1865  m.Add = function(obj,opt) {
1866  this.arr.push(obj);
1867  this.opt.push((opt && typeof opt=='string') ? opt : "");
1868  }
1869  m.AddFirst = function(obj,opt) {
1870  this.arr.unshift(obj);
1871  this.opt.unshift((opt && typeof opt=='string') ? opt : "");
1872  }
1873  m.RemoveAt = function(indx) {
1874  this.arr.splice(indx, 1);
1875  this.opt.splice(indx, 1);
1876  }
1877  }
1878 
1879  if ((typename === "TPaveText") || (typename === "TPaveStats")) {
1880  m.AddText = function(txt) {
1881  // this.fLines.Add({ _typename: 'TLatex', fTitle: txt, fTextColor: 1 });
1882  var line = JSROOT.Create("TLatex");
1883  line.fTitle = txt;
1884  this.fLines.Add(line);
1885  }
1886  m.Clear = function() {
1887  this.fLines.Clear();
1888  }
1889  }
1890 
1891  if ((typename.indexOf("TF1") == 0) || (typename === "TF2")) {
1892  m.addFormula = function(obj) {
1893  if (!obj) return;
1894  if (this.formulas === undefined) this.formulas = [];
1895  this.formulas.push(obj);
1896  }
1897 
1898  m.evalPar = function(x, y) {
1899  if (! ('_func' in this) || (this._title !== this.fTitle)) {
1900 
1901  var _func = this.fTitle, isformula = false, pprefix = "[";
1902  if (_func === "gaus") _func = "gaus(0)";
1903  if (this.fFormula && typeof this.fFormula.fFormula == "string") {
1904  if (this.fFormula.fFormula.indexOf("[](double*x,double*p)")==0) {
1905  isformula = true; pprefix = "p[";
1906  _func = this.fFormula.fFormula.substr(21);
1907  } else {
1908  _func = this.fFormula.fFormula;
1909  pprefix = "[p";
1910  }
1911  if (this.fFormula.fClingParameters && this.fFormula.fParams) {
1912  for (var i=0;i<this.fFormula.fParams.length;++i) {
1913  var regex = new RegExp('(\\[' + this.fFormula.fParams[i].first + '\\])', 'g'),
1914  parvalue = this.fFormula.fClingParameters[this.fFormula.fParams[i].second];
1915  _func = _func.replace(regex, (parvalue < 0) ? "(" + parvalue + ")" : parvalue);
1916  }
1917  }
1918  }
1919 
1920  if ('formulas' in this)
1921  for (var i=0;i<this.formulas.length;++i)
1922  while (_func.indexOf(this.formulas[i].fName) >= 0)
1923  _func = _func.replace(this.formulas[i].fName, this.formulas[i].fTitle);
1924  _func = _func.replace(/\b(abs)\b/g, 'TMath::Abs')
1925  .replace(/TMath::Exp\(/g, 'Math.exp(')
1926  .replace(/TMath::Abs\(/g, 'Math.abs(');
1927  if (typeof JSROOT.Math == 'object') {
1928  this._math = JSROOT.Math;
1929  _func = _func.replace(/TMath::Prob\(/g, 'this._math.Prob(')
1930  .replace(/TMath::Gaus\(/g, 'this._math.Gaus(')
1931  .replace(/TMath::BreitWigner\(/g, 'this._math.BreitWigner(')
1932  .replace(/xygaus\(/g, 'this._math.gausxy(this, x, y, ')
1933  .replace(/gaus\(/g, 'this._math.gaus(this, x, ')
1934  .replace(/gausn\(/g, 'this._math.gausn(this, x, ')
1935  .replace(/expo\(/g, 'this._math.expo(this, x, ')
1936  .replace(/landau\(/g, 'this._math.landau(this, x, ')
1937  .replace(/landaun\(/g, 'this._math.landaun(this, x, ')
1938  .replace(/ROOT::Math::/g, 'this._math.');
1939  }
1940  for (var i=0;i<this.fNpar;++i) {
1941  var parname = pprefix + i + "]";
1942  while(_func.indexOf(parname) != -1)
1943  _func = _func.replace(parname, '('+this.GetParValue(i)+')');
1944  }
1945  _func = _func.replace(/\b(sin)\b/gi, 'Math.sin')
1946  .replace(/\b(cos)\b/gi, 'Math.cos')
1947  .replace(/\b(tan)\b/gi, 'Math.tan')
1948  .replace(/\b(exp)\b/gi, 'Math.exp')
1949  .replace(/\b(pow)\b/gi, 'Math.pow')
1950  .replace(/pi/g, 'Math.PI');
1951  for (var n=2;n<10;++n)
1952  _func = _func.replace('x^'+n, 'Math.pow(x,'+n+')');
1953 
1954  if (isformula) {
1955  _func = _func.replace(/x\[0\]/g,"x");
1956  if (this._typename==="TF2") {
1957  _func = _func.replace(/x\[1\]/g,"y");
1958  this._func = new Function("x", "y", _func).bind(this);
1959  } else {
1960  this._func = new Function("x", _func).bind(this);
1961  }
1962  } else
1963  if (this._typename==="TF2")
1964  this._func = new Function("x", "y", "return " + _func).bind(this);
1965  else
1966  this._func = new Function("x", "return " + _func).bind(this);
1967 
1968  this._title = this.fTitle;
1969  }
1970 
1971  return this._func(x, y);
1972  }
1973  m.GetParName = function(n) {
1974  if (this.fParams && this.fParams.fParNames) return this.fParams.fParNames[n];
1975  if (this.fFormula && this.fFormula.fParams) return this.fFormula.fParams[n].first;
1976  if (this.fNames && this.fNames[n]) return this.fNames[n];
1977  return "p"+n;
1978  }
1979  m.GetParValue = function(n) {
1980  if (this.fParams && this.fParams.fParameters) return this.fParams.fParameters[n];
1981  if (this.fFormula && this.fFormula.fClingParameters) return this.fFormula.fClingParameters[n];
1982  if (this.fParams) return this.fParams[n];
1983  return undefined;
1984  }
1985  m.GetParError = function(n) {
1986  return this.fParErrors ? this.fParErrors[n] : undefined;
1987  }
1988  m.GetNumPars = function() {
1989  return this.fNpar;
1990  }
1991  }
1992 
1993  if (((typename.indexOf("TGraph") == 0) || (typename == "TCutG")) && (typename != "TGraphPolargram") && (typename != "TGraphTime")) {
1994  // check if point inside figure specified by the TGraph
1995  m.IsInside = function(xp,yp) {
1996  var i, j = this.fNpoints - 1, x = this.fX, y = this.fY, oddNodes = false;
1997 
1998  for (i=0; i<this.fNpoints; ++i) {
1999  if ((y[i]<yp && y[j]>=yp) || (y[j]<yp && y[i]>=yp)) {
2000  if (x[i]+(yp-y[i])/(y[j]-y[i])*(x[j]-x[i])<xp) {
2001  oddNodes = !oddNodes;
2002  }
2003  }
2004  j=i;
2005  }
2006 
2007  return oddNodes;
2008  };
2009  }
2010 
2011  if (typename.indexOf("TH1") == 0 ||
2012  typename.indexOf("TH2") == 0 ||
2013  typename.indexOf("TH3") == 0) {
2014  m.getBinError = function(bin) {
2015  // -*-*-*-*-*Return value of error associated to bin number bin*-*-*-*-*
2016  // if the sum of squares of weights has been defined (via Sumw2),
2017  // this function returns the sqrt(sum of w2).
2018  // otherwise it returns the sqrt(contents) for this bin.
2019  if (bin >= this.fNcells) bin = this.fNcells - 1;
2020  if (bin < 0) bin = 0;
2021  if (bin < this.fSumw2.length)
2022  return Math.sqrt(this.fSumw2[bin]);
2023  return Math.sqrt(Math.abs(this.fArray[bin]));
2024  };
2025  m.setBinContent = function(bin, content) {
2026  // Set bin content - only trivial case, without expansion
2027  this.fEntries++;
2028  this.fTsumw = 0;
2029  if ((bin>=0) && (bin<this.fArray.length))
2030  this.fArray[bin] = content;
2031  };
2032  }
2033 
2034  if (typename.indexOf("TH1") == 0) {
2035  m.getBin = function(x) { return x; }
2036  m.getBinContent = function(bin) { return this.fArray[bin]; }
2037  m.Fill = function(x, weight) {
2038  var axis = this.fXaxis,
2039  bin = 1 + Math.floor((x - axis.fXmin) / (axis.fXmax - axis.fXmin) * axis.fNbins);
2040  if (bin < 0) bin = 0; else
2041  if (bin > axis.fNbins + 1) bin = axis.fNbins + 1;
2042  this.fArray[bin] += ((weight===undefined) ? 1 : weight);
2043  }
2044  }
2045 
2046  if (typename.indexOf("TH2") == 0) {
2047  m.getBin = function(x, y) { return (x + (this.fXaxis.fNbins+2) * y); }
2048  m.getBinContent = function(x, y) { return this.fArray[this.getBin(x, y)]; }
2049  m.Fill = function(x, y, weight) {
2050  var axis1 = this.fXaxis, axis2 = this.fYaxis,
2051  bin1 = 1 + Math.floor((x - axis1.fXmin) / (axis1.fXmax - axis1.fXmin) * axis1.fNbins),
2052  bin2 = 1 + Math.floor((y - axis2.fXmin) / (axis2.fXmax - axis2.fXmin) * axis2.fNbins);
2053  if (bin1 < 0) bin1 = 0; else
2054  if (bin1 > axis1.fNbins + 1) bin1 = axis1.fNbins + 1;
2055  if (bin2 < 0) bin2 = 0; else
2056  if (bin2 > axis2.fNbins + 1) bin2 = axis2.fNbins + 1;
2057  this.fArray[bin1 + (axis1.fNbins+2)*bin2] += ((weight===undefined) ? 1 : weight);
2058  }
2059  }
2060 
2061  if (typename.indexOf("TH3") == 0) {
2062  m.getBin = function(x, y, z) { return (x + (this.fXaxis.fNbins+2) * (y + (this.fYaxis.fNbins+2) * z)); }
2063  m.getBinContent = function(x, y, z) { return this.fArray[this.getBin(x, y, z)]; };
2064  m.Fill = function(x, y, z, weight) {
2065  var axis1 = this.fXaxis, axis2 = this.fYaxis, axis3 = this.fZaxis,
2066  bin1 = 1 + Math.floor((x - axis1.fXmin) / (axis1.fXmax - axis1.fXmin) * axis1.fNbins),
2067  bin2 = 1 + Math.floor((y - axis2.fXmin) / (axis2.fXmax - axis2.fXmin) * axis2.fNbins),
2068  bin3 = 1 + Math.floor((z - axis3.fXmin) / (axis3.fXmax - axis3.fXmin) * axis3.fNbins);
2069  if (bin1 < 0) bin1 = 0; else
2070  if (bin1 > axis1.fNbins + 1) bin1 = axis1.fNbins + 1;
2071  if (bin2 < 0) bin2 = 0; else
2072  if (bin2 > axis2.fNbins + 1) bin2 = axis2.fNbins + 1;
2073  if (bin3 < 0) bin3 = 0; else
2074  if (bin3 > axis3.fNbins + 1) bin3 = axis3.fNbins + 1;
2075  this.fArray[bin1 + (axis1.fNbins+2)* (bin2+(axis2.fNbins+2)*bin3)] += ((weight===undefined) ? 1 : weight);
2076  }
2077  }
2078 
2079  if (typename.indexOf("TProfile") == 0) {
2080  if (typename.indexOf("TProfile2D") == 0) {
2081  m.getBin = function(x, y) { return (x + (this.fXaxis.fNbins+2) * y); }
2082  m.getBinContent = function(x, y) {
2083  var bin = this.getBin(x, y);
2084  if (bin < 0 || bin >= this.fNcells) return 0;
2085  if (this.fBinEntries[bin] < 1e-300) return 0;
2086  if (!this.fArray) return 0;
2087  return this.fArray[bin]/this.fBinEntries[bin];
2088  }
2089  m.getBinEntries = function(x, y) {
2090  var bin = this.getBin(x, y);
2091  if (bin < 0 || bin >= this.fNcells) return 0;
2092  return this.fBinEntries[bin];
2093  }
2094  }
2095  else {
2096  m.getBin = function(x) { return x; }
2097  m.getBinContent = function(bin) {
2098  if (bin < 0 || bin >= this.fNcells) return 0;
2099  if (this.fBinEntries[bin] < 1e-300) return 0;
2100  if (!this.fArray) return 0;
2101  return this.fArray[bin]/this.fBinEntries[bin];
2102  };
2103  }
2104  m.getBinEffectiveEntries = function(bin) {
2105  if (bin < 0 || bin >= this.fNcells) return 0;
2106  var sumOfWeights = this.fBinEntries[bin];
2107  if ( !this.fBinSumw2 || this.fBinSumw2.length != this.fNcells) {
2108  // this can happen when reading an old file
2109  return sumOfWeights;
2110  }
2111  var sumOfWeightsSquare = this.fBinSumw2[bin];
2112  return (sumOfWeightsSquare > 0) ? sumOfWeights * sumOfWeights / sumOfWeightsSquare : 0;
2113  };
2114  m.getBinError = function(bin) {
2115  if (bin < 0 || bin >= this.fNcells) return 0;
2116  var cont = this.fArray[bin], // sum of bin w *y
2117  sum = this.fBinEntries[bin], // sum of bin weights
2118  err2 = this.fSumw2[bin], // sum of bin w * y^2
2119  neff = this.getBinEffectiveEntries(bin); // (sum of w)^2 / (sum of w^2)
2120  if (sum < 1e-300) return 0; // for empty bins
2121  var EErrorType = { kERRORMEAN : 0, kERRORSPREAD : 1, kERRORSPREADI : 2, kERRORSPREADG : 3 };
2122  // case the values y are gaussian distributed y +/- sigma and w = 1/sigma^2
2123  if (this.fErrorMode === EErrorType.kERRORSPREADG)
2124  return 1.0/Math.sqrt(sum);
2125  // compute variance in y (eprim2) and standard deviation in y (eprim)
2126  var contsum = cont/sum, eprim = Math.sqrt(Math.abs(err2/sum - contsum*contsum));
2127  if (this.fErrorMode === EErrorType.kERRORSPREADI) {
2128  if (eprim != 0) return eprim/Math.sqrt(neff);
2129  // in case content y is an integer (so each my has an error +/- 1/sqrt(12)
2130  // when the std(y) is zero
2131  return 1.0/Math.sqrt(12*neff);
2132  }
2133  // if approximate compute the sums (of w, wy and wy2) using all the bins
2134  // when the variance in y is zero
2135  // case option "S" return standard deviation in y
2136  if (this.fErrorMode === EErrorType.kERRORSPREAD) return eprim;
2137  // default case : fErrorMode = kERRORMEAN
2138  // return standard error on the mean of y
2139  return (eprim/Math.sqrt(neff));
2140  };
2141  }
2142 
2143  if (typename == "TAxis") {
2144  m.GetBinLowEdge = function(bin) {
2145  if (this.fNbins <= 0) return 0;
2146  if ((this.fXbins.length > 0) && (bin > 0) && (bin <= this.fNbins)) return this.fXbins[bin-1];
2147  return this.fXmin + (bin-1) * (this.fXmax - this.fXmin) / this.fNbins;
2148  }
2149  m.GetBinCenter = function(bin) {
2150  if (this.fNbins <= 0) return 0;
2151  if ((this.fXbins.length > 0) && (bin > 0) && (bin < this.fNbins)) return (this.fXbins[bin-1] + this.fXbins[bin])/2;
2152  return this.fXmin + (bin-0.5) * (this.fXmax - this.fXmin) / this.fNbins;
2153  }
2154  }
2155 
2156  if (typeof JSROOT.getMoreMethods == "function")
2157  JSROOT.getMoreMethods(m, typename, obj);
2158 
2159  JSROOT.methodsCache[typename] = m;
2160  return m;
2161  }
2162 
2165  JSROOT.IsRootCollection = function(lst, typename) {
2166  if (lst && (typeof lst === 'object')) {
2167  if ((lst.$kind === "TList") || (lst.$kind === "TObjArray")) return true;
2168  if (!typename) typename = lst._typename;
2169  }
2170  if (!typename) return false;
2171  return (typename === 'TList') || (typename === 'THashList') || (typename === 'TMap') ||
2172  (typename === 'TObjArray') || (typename === 'TClonesArray');
2173  }
2174 
2182  JSROOT.addMethods = function(obj, typename) {
2183  this.extend(obj, JSROOT.getMethods(typename || obj._typename, obj));
2184  }
2185 
2186  JSROOT.lastFFormat = "";
2187 
2195  JSROOT.FFormat = function(value, fmt) {
2196  if (!fmt) fmt = "6.4g";
2197 
2198  JSROOT.lastFFormat = "";
2199 
2200  fmt = fmt.trim();
2201  var len = fmt.length;
2202  if (len<2) return value.toFixed(4);
2203  var last = fmt[len-1];
2204  fmt = fmt.slice(0,len-1);
2205  var isexp = null;
2206  var prec = fmt.indexOf(".");
2207  if (prec<0) prec = 4; else prec = Number(fmt.slice(prec+1));
2208  if (isNaN(prec) || (prec<0) || (prec==null)) prec = 4;
2209 
2210  var significance = false;
2211  if ((last=='e') || (last=='E')) { isexp = true; } else
2212  if (last=='Q') { isexp = true; significance = true; } else
2213  if ((last=='f') || (last=='F')) { isexp = false; } else
2214  if (last=='W') { isexp = false; significance = true; } else
2215  if ((last=='g') || (last=='G')) {
2216  var se = JSROOT.FFormat(value, fmt+'Q'),
2217  _fmt = JSROOT.lastFFormat,
2218  sg = JSROOT.FFormat(value, fmt+'W');
2219 
2220  if (se.length < sg.length) {
2221  JSROOT.lastFFormat = _fmt;
2222  return se;
2223  }
2224  return sg;
2225  } else {
2226  isexp = false;
2227  prec = 4;
2228  }
2229 
2230  if (isexp) {
2231  // for exponential representation only one significant digit befor point
2232  if (significance) prec--;
2233  if (prec<0) prec = 0;
2234 
2235  JSROOT.lastFFormat = '5.'+prec+'e';
2236 
2237  return value.toExponential(prec);
2238  }
2239 
2240  var sg = value.toFixed(prec);
2241 
2242  if (significance) {
2243 
2244  // when using fixed representation, one could get 0.0
2245  if ((value!=0) && (Number(sg)==0.) && (prec>0)) {
2246  prec = 20; sg = value.toFixed(prec);
2247  }
2248 
2249  var l = 0;
2250  while ((l<sg.length) && (sg[l] == '0' || sg[l] == '-' || sg[l] == '.')) l++;
2251 
2252  var diff = sg.length - l - prec;
2253  if (sg.indexOf(".")>l) diff--;
2254 
2255  if (diff != 0) {
2256  prec-=diff;
2257  if (prec<0) prec = 0; else if (prec>20) prec = 20;
2258  sg = value.toFixed(prec);
2259  }
2260  }
2261 
2262  JSROOT.lastFFormat = '5.'+prec+'f';
2263 
2264  return sg;
2265  }
2266 
2269  JSROOT.log10 = function(n) {
2270  return Math.log(n) / Math.log(10);
2271  }
2272 
2273  // Dummy function, will be redefined when JSRootPainter is loaded
2274  JSROOT.progress = function(msg, tmout) {
2275  if ((msg !== undefined) && (typeof msg=="string")) JSROOT.console(msg);
2276  }
2277 
2278  // connect to the TWebWindow instance
2279  JSROOT.ConnectWebWindow = function(arg) {
2280  if (typeof arg == 'function') arg = { callback: arg };
2281 
2282  if (arg.openui5src) JSROOT.openui5src = arg.openui5src;
2283  if (arg.openui5libs) JSROOT.openui5libs = arg.openui5libs;
2284  JSROOT.AssertPrerequisites("2d;" + (arg && arg.prereq ? arg.prereq : ""), function() {
2285  if (arg && arg.prereq) delete arg.prereq;
2286  JSROOT.ConnectWebWindow(arg);
2287  }, (arg ? arg.prereq_logdiv : undefined));
2288  }
2289 
2294  JSROOT.Initialize = function() {
2295 
2296  if (JSROOT.source_fullpath.length === 0) return this;
2297 
2298  function window_on_load(func) {
2299  if (func!=null) {
2300  if (document.attachEvent ? document.readyState === 'complete' : document.readyState !== 'loading')
2301  func();
2302  else
2303  window.onload = func;
2304  }
2305  return JSROOT;
2306  }
2307 
2308  var src = JSROOT.source_fullpath;
2309 
2310  if (JSROOT.GetUrlOption('nocache', src) != null) JSROOT.nocache = (new Date).getTime(); // use timestamp to overcome cache limitation
2311  if ((JSROOT.GetUrlOption('wrong_http_response', src) != null) || (JSROOT.GetUrlOption('wrong_http_response') != null))
2312  JSROOT.wrong_http_response_handling = true; // server may send wrong content length by partial requests, use other method to control this
2313 
2314  if (JSROOT.GetUrlOption('gui', src) !== null)
2315  return window_on_load( function() { JSROOT.BuildSimpleGUI(); } );
2316 
2317  if ( typeof define === "function" && define.amd )
2318  return window_on_load( function() { JSROOT.BuildSimpleGUI('check_existing_elements'); } );
2319 
2320  var prereq = "";
2321  if (JSROOT.GetUrlOption('io', src)!=null) prereq += "io;";
2322  if (JSROOT.GetUrlOption('tree', src)!=null) prereq += "tree;";
2323  if (JSROOT.GetUrlOption('2d', src)!=null) prereq += "2d;";
2324  if (JSROOT.GetUrlOption('v7', src)!=null) prereq += "v7;";
2325  if (JSROOT.GetUrlOption('hist', src)!=null) prereq += "2d;hist;";
2326  if (JSROOT.GetUrlOption('hierarchy', src)!=null) prereq += "2d;hierarchy;";
2327  if (JSROOT.GetUrlOption('jq2d', src)!=null) prereq += "2d;hierarchy;jq2d;";
2328  if (JSROOT.GetUrlOption('more2d', src)!=null) prereq += "more2d;";
2329  if (JSROOT.GetUrlOption('geom', src)!=null) prereq += "geom;";
2330  if (JSROOT.GetUrlOption('3d', src)!=null) prereq += "3d;";
2331  if (JSROOT.GetUrlOption('math', src)!=null) prereq += "math;";
2332  if (JSROOT.GetUrlOption('mathjax', src)!=null) prereq += "mathjax;";
2333  if (JSROOT.GetUrlOption('openui5', src)!=null) prereq += "openui5;";
2334  var user = JSROOT.GetUrlOption('load', src),
2335  onload = JSROOT.GetUrlOption('onload', src),
2336  bower = JSROOT.GetUrlOption('bower', src);
2337 
2338  if (user) prereq += "io;2d;load:" + user;
2339  if ((bower===null) && (JSROOT.source_dir.indexOf("bower_components/jsroot/")>=0)) bower = "";
2340  if (bower!==null) {
2341  if (bower.length>0) JSROOT.bower_dir = bower; else
2342  if (JSROOT.source_dir.indexOf("jsroot/") == JSROOT.source_dir.length - 7)
2343  JSROOT.bower_dir = JSROOT.source_dir.substr(0, JSROOT.source_dir.length - 7);
2344  if (JSROOT.bower_dir !== null) console.log("Set JSROOT.bower_dir to " + JSROOT.bower_dir);
2345  }
2346 
2347  if ((prereq.length>0) || (onload!=null))
2348  window_on_load(function() {
2349  if (prereq.length>0) JSROOT.AssertPrerequisites(prereq, onload); else
2350  if (onload!=null) {
2351  onload = JSROOT.findFunction(onload);
2352  if (typeof onload == 'function') onload();
2353  }
2354  });
2355 
2356  return this;
2357  }
2358 
2359  return JSROOT.Initialize();
2360 
2361 }));
2362 
2364