Subversion Repositories f9daq

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
193 f9daq 1
/** @file JSRootCore.js
2
 * Core methods of JavaScript ROOT */
3
 
4
/** @namespace JSROOT
5
  * Holder of all JSROOT functions and classes */
6
 
7
(function( factory ) {
8
   if ( typeof define === "function" && define.amd ) {
9
 
10
      var jsroot = factory({});
11
 
12
      var dir = jsroot.source_dir + "scripts/", ext = jsroot.source_min ? ".min" : "";
13
 
14
      var paths = {
15
            'd3'                   : dir+'d3.v3.min',
16
            'jquery'               : dir+'jquery.min',
17
            'jquery-ui'            : dir+'jquery-ui.min',
18
            'jqueryui-mousewheel'  : dir+'jquery.mousewheel.min',
19
            'jqueryui-touch-punch' : dir+'touch-punch.min',
20
            'rawinflate'           : dir+'rawinflate.min',
21
            'MathJax'              : 'https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG&delayStartupUntil=configured',
22
            'saveSvgAsPng'         : dir+'saveSvgAsPng.min',
23
            'dat.gui'              : dir+'dat.gui.min',
24
            'threejs'              : dir+'three.min',
25
            'threejs_all'          : dir+'three.extra.min',
26
            'JSRootCore'           : dir+'JSRootCore'+ext,
27
            'JSRootMath'           : dir+'JSRootMath'+ext,
28
            'JSRootInterface'      : dir+'JSRootInterface'+ext,
29
            'JSRootIOEvolution'    : dir+'JSRootIOEvolution'+ext,
30
            'JSRootPainter'        : dir+'JSRootPainter'+ext,
31
            'JSRootPainter.more'   : dir+'JSRootPainter.more'+ext,
32
            'JSRootPainter.jquery' : dir+'JSRootPainter.jquery'+ext,
33
            'JSRoot3DPainter'      : dir+'JSRoot3DPainter'+ext,
34
            'ThreeCSG'             : dir+'ThreeCSG'+ext,
35
            'JSRootGeoBase'        : dir+'JSRootGeoBase'+ext,
36
            'JSRootGeoPainter'     : dir+'JSRootGeoPainter'+ext
37
         };
38
 
39
      var cfg_paths;
40
      if ((requirejs.s!==undefined) && (requirejs.s.contexts !== undefined) && ((requirejs.s.contexts._!==undefined) &&
41
           requirejs.s.contexts._.config!==undefined)) cfg_paths = requirejs.s.contexts._.config.paths;
42
                                                 else console.warn("Require.js paths changed - please contact JSROOT developers");
43
 
44
      // check if modules are already loaded
45
      for (var module in paths)
46
         if (requirejs.defined(module) || (cfg_paths && (module in cfg_paths)))
47
            delete paths[module];
48
 
49
      // configure all dependencies
50
      requirejs.config({
51
        paths: paths,
52
        shim: {
53
         'jqueryui-mousewheel': { deps: ['jquery-ui'] },
54
         'jqueryui-touch-punch': { deps: ['jquery-ui'] },
55
         'threejs_all': { deps: [ 'threejs'] },
56
         'ThreeCSG' : { deps: [ 'threejs'] },
57
         'MathJax': {
58
             exports: 'MathJax',
59
             init: function () {
60
                MathJax.Hub.Config({ TeX: { extensions: ["color.js"] }, SVG: { mtextFontInherit: true } });
61
                MathJax.Hub.Register.StartupHook("SVG Jax Ready",function () {
62
                   var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;
63
                   VARIANT["normal"].fonts.unshift("MathJax_SansSerif");
64
                   VARIANT["bold"].fonts.unshift("MathJax_SansSerif-bold");
65
                   VARIANT["italic"].fonts.unshift("MathJax_SansSerif");
66
                   VARIANT["-tex-mathit"].fonts.unshift("MathJax_SansSerif");
67
                });
68
                MathJax.Hub.Startup.onload();
69
                return MathJax;
70
             }
71
          }
72
       }
73
      });
74
 
75
      // AMD. Register as an anonymous module.
76
      define( jsroot );
77
 
78
      if (!require.specified("JSRootCore"))
79
          define('JSRootCore', [], jsroot);
80
 
81
      if (!require.specified("jsroot"))
82
         define('jsroot', [], jsroot);
83
 
84
   } else {
85
 
86
      if (typeof JSROOT != 'undefined')
87
         throw new Error("JSROOT is already defined", "JSRootCore.js");
88
 
89
      JSROOT = {};
90
 
91
      factory(JSROOT);
92
   }
93
} (function(JSROOT) {
94
 
95
   JSROOT.version = "4.8.0 2/12/2016";
96
 
97
   JSROOT.source_dir = "";
98
   JSROOT.source_min = false;
99
   JSROOT.source_fullpath = ""; // full name of source script
100
   JSROOT.bower_dir = ""; // when specified, use standard libs from bower location
101
 
102
   JSROOT.id_counter = 0;
103
 
104
   JSROOT.touches = false;
105
   JSROOT.browser = { isOpera:false, isFirefox:true, isSafari:false, isChrome:false, isIE:false, isWin:false };
106
 
107
   if ((typeof document !== "undefined") && (typeof window !== "undefined")) {
108
      var scripts = document.getElementsByTagName('script');
109
      for (var n = 0; n < scripts.length; ++n) {
110
         var src = scripts[n].src;
111
         if ((src===undefined) || (typeof src !== 'string')) continue;
112
 
113
         var pos = src.indexOf("scripts/JSRootCore.");
114
         if (pos<0) continue;
115
 
116
         JSROOT.source_dir = src.substr(0, pos);
117
         JSROOT.source_min = src.indexOf("scripts/JSRootCore.min.js") >= 0;
118
 
119
         JSROOT.source_fullpath = src;
120
 
121
         if ((console!==undefined) && (typeof console.log == 'function'))
122
            console.log("Set JSROOT.source_dir to " + JSROOT.source_dir + ", " + JSROOT.version);
123
         break;
124
      }
125
 
126
      JSROOT.touches = ('ontouchend' in document); // identify if touch events are supported
127
      JSROOT.browser.isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
128
      JSROOT.browser.isFirefox = typeof InstallTrigger !== 'undefined';
129
      JSROOT.browser.isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
130
      JSROOT.browser.isChrome = !!window.chrome && !JSROOT.browser.isOpera;
131
      JSROOT.browser.isIE = false || !!document.documentMode;
132
      JSROOT.browser.isWin = navigator.platform.indexOf('Win') >= 0;
133
   }
134
 
135
   JSROOT.browser.isWebKit = JSROOT.browser.isChrome || JSROOT.browser.isSafari;
136
 
137
   // default draw styles, can be changed after loading of JSRootCore.js
138
   // this style also can be changed providing style=itemname in the URL
139
   JSROOT.gStyle = {
140
         Tooltip : 1, // 0 - off, 1 - on
141
         ContextMenu : true,
142
         Zooming : true,  // global zooming flag, enable/disable any kind of interactive zooming
143
         ZoomMouse : true,  // Zooming with the mouse events
144
         ZoomWheel : true,  // Zooming with mouse wheel
145
         ZoomTouch : true,  // Zooming with the touch devices
146
         MoveResize : true,   // enable move and resize of elements like statbox, title, pave, colz
147
         DragAndDrop : true,  // enables drag and drop functionality
148
         ToolBar : true,    // show additional tool buttons on the canvas
149
         OptimizeDraw : 1, // drawing optimization: 0 - disabled, 1 - only for large (>5000 1d bins, >50 2d bins) histograms, 2 - always
150
         AutoStat : true,
151
         FrameNDC : { fX1NDC: 0.07, fY1NDC: 0.12, fX2NDC: 0.95, fY2NDC: 0.88 },
152
         Palette : 57,
153
         MathJax : 0,  // 0 - never, 1 - only for complex cases, 2 - always
154
         ProgressBox : true,  // show progress box
155
         Embed3DinSVG : 2,  // 0 - no embed, only 3D plot, 1 - overlay over SVG (IE/WebKit), 2 - embed into SVG (only Firefox)
156
         NoWebGL : false, // if true, WebGL will be disabled,
157
         GeoGradPerSegm : 6, // amount of grads per segment in TGeo spherical shapes like tube
158
         GeoCompressComp : true, // if one should compress faces after creation of composite shape,
159
         IgnoreUrlOptions : false, // if true, ignore all kind of URL options in the browser URL
160
 
161
         // these are TStyle attributes, which can be chenged via URL 'style' parameter
162
 
163
         fPadBottomMargin : 0.1,
164
         fPadTopMargin : 0.1,
165
         fPadLeftMargin : 0.1,
166
         fPadRightMargin : 0.1,
167
         fPadGridX : false,
168
         fPadGridY : false,
169
         fPadTickX : 0,
170
         fPadTickY : 0,
171
         fStatColor : 0,
172
         fStatTextColor : 1,
173
         fStatBorderSize : 1,
174
         fStatFont : 42,
175
         fStatFontSize : 0,
176
         fStatStyle : 1001,
177
         fStatFormat : "6.4g",
178
         fStatX : 0.98,
179
         fStatY : 0.935,
180
         fStatW : 0.2,
181
         fStatH : 0.16,
182
         fTitleAlign : 23,
183
         fTitleColor : 0,
184
         fTitleTextColor : 1,
185
         fTitleBorderSize : 0,
186
         fTitleFont : 42,
187
         fTitleFontSize : 0.05,
188
         fTitleStyle : 0,
189
         fTitleX : 0.5,
190
         fTitleY : 0.995,
191
         fTitleW : 0,
192
         fTitleH : 0,
193
         fFitFormat : "5.4g",
194
         fOptStat : 1111,
195
         fOptFit : 0,
196
         fNumberContours : 20,
197
         fGridColor : 0,
198
         fGridStyle : 11,
199
         fGridWidth : 1,
200
         fFrameFillColor : 0,
201
         fFrameLineColor : 1,
202
         fFrameFillStyle : 1001,
203
         fFrameLineStyle : 1,
204
         fFrameLineWidth : 1,
205
         fFrameBorderSize : 1,
206
         fFrameBorderMode : 0,
207
         fEndErrorSize : 2,   // size in pixels of end error for E1 draw options
208
         fErrorX : 0.5,   // X size of the error marks for the histogram drawings
209
         fHistMinimumZero: false,   // when true, BAR and LEGO drawing using base = 0
210
         fPaintTextFormat : "g",
211
         fTimeOffset : 788918400, // UTC time at 01/01/95
212
      };
213
 
214
   JSROOT.BIT = function(n) { return 1 << (n); }
215
 
216
   // TH1 status bits
217
   JSROOT.TH1StatusBits = {
218
         kNoStats       : JSROOT.BIT(9),  // don't draw stats box
219
         kUserContour   : JSROOT.BIT(10), // user specified contour levels
220
         kCanRebin      : JSROOT.BIT(11), // can rebin axis
221
         kLogX          : JSROOT.BIT(15), // X-axis in log scale
222
         kIsZoomed      : JSROOT.BIT(16), // bit set when zooming on Y axis
223
         kNoTitle       : JSROOT.BIT(17), // don't draw the histogram title
224
         kIsAverage     : JSROOT.BIT(18)  // Bin contents are average (used by Add)
225
   };
226
 
227
   JSROOT.EAxisBits = {
228
         kTickPlus      : JSROOT.BIT(9),
229
         kTickMinus     : JSROOT.BIT(10),
230
         kAxisRange     : JSROOT.BIT(11),
231
         kCenterTitle   : JSROOT.BIT(12),
232
         kCenterLabels  : JSROOT.BIT(14),
233
         kRotateTitle   : JSROOT.BIT(15),
234
         kPalette       : JSROOT.BIT(16),
235
         kNoExponent    : JSROOT.BIT(17),
236
         kLabelsHori    : JSROOT.BIT(18),
237
         kLabelsVert    : JSROOT.BIT(19),
238
         kLabelsDown    : JSROOT.BIT(20),
239
         kLabelsUp      : JSROOT.BIT(21),
240
         kIsInteger     : JSROOT.BIT(22),
241
         kMoreLogLabels : JSROOT.BIT(23),
242
         kDecimals      : JSROOT.BIT(11)
243
   };
244
 
245
   // wrapper for console.log, avoids missing console in IE
246
   // if divid specified, provide output to the HTML element
247
   JSROOT.console = function(value, divid) {
248
      if ((divid!=null) && (typeof divid=='string') && ((typeof document.getElementById(divid))!='undefined'))
249
         document.getElementById(divid).innerHTML = value;
250
      else
251
      if ((typeof console != 'undefined') && (typeof console.log == 'function'))
252
         console.log(value);
253
   }
254
 
255
   /// Should be used to reintroduce objects references, produced by TBufferJSON
256
   // Replace all references inside object, object should not be null
257
   // Idea of the code taken from JSON-R code, found on
258
   // https://github.com/graniteds/jsonr
259
   // Only unref part was used, arrays are not accounted as objects
260
   JSROOT.JSONR_unref = function(obj) {
261
 
262
      var map = [], newfmt = undefined;
263
 
264
      function unref_value(value) {
265
         if (value===null) return;
266
 
267
         if (typeof value === 'string') {
268
            if (newfmt || (value.length < 6) || (value.indexOf("$ref:") !== 0)) return;
269
            var ref = parseInt(value.substr(5));
270
            if (isNaN(ref) || (ref < 0) || (ref >= map.length)) return;
271
            newfmt = false;
272
            return map[ref];
273
         }
274
 
275
         if (typeof value !== 'object') return;
276
 
277
         var i, k, res, proto = Object.prototype.toString.apply(value);
278
 
279
         // TODO: should we process here typed arrays???
280
         //       are there special JSON syntax for typed arrays
281
         if ((proto.indexOf('[object')==0) && (proto.indexOf('Array]')>0)) {
282
             for (i = 0; i < value.length; ++i) {
283
                res = unref_value(value[i]);
284
                if (res) value[i] = res;
285
             }
286
             return;
287
         }
288
 
289
         var ks = Object.keys(value), len = ks.length;
290
 
291
         if ((newfmt!==false) && (len===1) && (ks[0]==='$ref')) {
292
            var ref = parseInt(value['$ref']);
293
            if (isNaN(ref) || (ref < 0) || (ref >= map.length)) return;
294
            newfmt = true;
295
            return map[ref];
296
         }
297
 
298
         // debug code, can be commented out later
299
         if (map.indexOf(value) >= 0) {
300
            JSROOT.console('should never happen - object already in the map');
301
            return;
302
         }
303
 
304
         // add object to object map
305
         map.push(value);
306
 
307
         // add methods to all objects, where _typename is specified
308
         if ('_typename' in value) JSROOT.addMethods(value);
309
 
310
         for (k = 0; k < len; ++k) {
311
            i = ks[k];
312
            res = unref_value(value[i]);
313
            if (res) value[i] = res;
314
         }
315
      }
316
 
317
      unref_value(obj);
318
 
319
      return obj;
320
   }
321
 
322
   JSROOT.debug = 0;
323
 
324
   // This is simple replacement of jQuery.extend method
325
   // Just copy (not clone) all fields from source to the target object
326
   JSROOT.extend = function(tgt, src) {
327
      if ((src === null) || (typeof src !== 'object')) return src;
328
      if ((tgt === null) || (typeof tgt !== 'object')) tgt = {};
329
 
330
      for (var k in src)
331
         tgt[k] = src[k];
332
 
333
      return tgt;
334
   }
335
 
336
   // Make deep clone of the object, including all sub-objects
337
   JSROOT.clone = function(src, map, nofunc) {
338
      if (src === null) return null;
339
 
340
      if (!map) {
341
         map = { obj:[], clones:[], nofunc: nofunc };
342
      } else {
343
         var i = map.obj.indexOf(src);
344
         if (i>=0) return map.clones[i];
345
      }
346
 
347
      var proto = Object.prototype.toString.apply(src);
348
 
349
      // process normal array
350
      if (proto === '[object Array]') {
351
         var tgt = [];
352
         map.obj.push(src);
353
         map.clones.push(tgt);
354
         for (var i = 0; i < src.length; ++i)
355
            if (typeof src[i] === 'object')
356
               tgt.push(JSROOT.clone(src[i], map));
357
            else
358
               tgt.push(src[i]);
359
 
360
         return tgt;
361
      }
362
 
363
      // process typed array
364
      if ((proto.indexOf('[object ') == 0) && (proto.indexOf('Array]') == proto.length-6)) {
365
         var tgt = [];
366
         map.obj.push(src);
367
         map.clones.push(tgt);
368
         for (var i = 0; i < src.length; ++i)
369
            tgt.push(src[i]);
370
 
371
         return tgt;
372
      }
373
 
374
      var tgt = {};
375
      map.obj.push(src);
376
      map.clones.push(tgt);
377
 
378
      for (var k in src) {
379
         if (typeof src[k] === 'object')
380
            tgt[k] = JSROOT.clone(src[k], map);
381
         else
382
         if (!map.nofunc || (typeof src[k]!=='function'))
383
            tgt[k] = src[k];
384
      }
385
 
386
      return tgt;
387
   }
388
 
389
   // method can be used to delete all functions from objects
390
   // only such objects can be cloned when transfer to Worker
391
   JSROOT.clear_func = function(src, map) {
392
      if (src === null) return src;
393
 
394
      var proto = Object.prototype.toString.apply(src);
395
 
396
      if (proto === '[object Array]') {
397
         for (var n=0;n<src.length;n++)
398
            if (typeof src[n] === 'object')
399
               JSROOT.clear_func(src[n], map);
400
         return src;
401
      }
402
 
403
      if ((proto.indexOf('[object ') == 0) && (proto.indexOf('Array]') == proto.length-6)) return src;
404
 
405
      if (!map) map = [];
406
      var nomap = (map.length == 0);
407
      if ('__clean_func__' in src) return src;
408
 
409
      map.push(src);
410
      src['__clean_func__'] = true;
411
 
412
      for (var k in src) {
413
         if (typeof src[k] === 'object')
414
            JSROOT.clear_func(src[k], map);
415
         else
416
         if (typeof src[k] === 'function') delete src[k];
417
      }
418
 
419
      if (nomap)
420
         for (var n=0;n<map.length;++n)
421
            delete map[n]['__clean_func__'];
422
 
423
      return src;
424
   }
425
 
426
 
427
   JSROOT.parse = function(arg) {
428
      if ((arg==null) || (arg=="")) return null;
429
      var obj = JSON.parse(arg);
430
      if (obj!=null) obj = this.JSONR_unref(obj);
431
      return obj;
432
   }
433
 
434
   /** @memberOf JSROOT */
435
   JSROOT.GetUrlOption = function(opt, url, dflt) {
436
      // analyzes document.URL and extracts options after '?' mark
437
      // following options supported ?opt1&opt2=3
438
      // In case of opt1 empty string will be returned, in case of opt2 '3'
439
      // If option not found, null is returned (or provided default value)
440
 
441
      if (dflt === undefined) dflt = null;
442
      if ((opt===null) || (typeof opt != 'string') || (opt.length==0)) return dflt;
443
 
444
      if (!url) {
445
         if (JSROOT.gStyle.IgnoreUrlOptions || (typeof document === 'undefined')) return dflt;
446
         url = document.URL;
447
      }
448
 
449
      var pos = url.indexOf("?");
450
      if (pos<0) return dflt;
451
      url = url.slice(pos+1);
452
 
453
      while (url.length>0) {
454
 
455
         if (url==opt) return "";
456
 
457
         pos = url.indexOf("&");
458
         if (pos < 0) pos = url.length;
459
 
460
         if (url.indexOf(opt) == 0) {
461
            if (url.charAt(opt.length)=="&") return "";
462
 
463
            // replace several symbols which are known to make a problem
464
            if (url.charAt(opt.length)=="=")
465
               return url.slice(opt.length+1, pos).replace(/%27/g, "'").replace(/%22/g, '"').replace(/%20/g, ' ').replace(/%3C/g, '<').replace(/%3E/g, '>').replace(/%5B/g, '[').replace(/%5D/g, ']');
466
         }
467
 
468
         url = url.slice(pos+1);
469
      }
470
      return dflt;
471
   }
472
 
473
   JSROOT.ParseAsArray = function(val) {
474
      // parse string value as array.
475
      // It could be just simple string:  "value"
476
      //  or array with or without string quotes:  [element], ['eleme1',elem2]
477
 
478
      var res = [];
479
 
480
      if (typeof val != 'string') return res;
481
 
482
      val = val.trim();
483
      if (val=="") return res;
484
 
485
      // return as array with single element
486
      if ((val.length<2) || (val[0]!='[') || (val[val.length-1]!=']')) {
487
         res.push(val); return res;
488
      }
489
 
490
      // try to split ourself, checking quotes and brackes
491
      var nbr = 0, nquotes = 0, ndouble = 0, last = 1;
492
 
493
      for (var indx = 1; indx < val.length; ++indx) {
494
         if (nquotes > 0) {
495
            if (val[indx]==="'") nquotes--;
496
            continue;
497
         }
498
         if (ndouble > 0) {
499
            if (val[indx]==='"') ndouble--;
500
            continue;
501
         }
502
         switch (val[indx]) {
503
            case "'" : nquotes++; break;
504
            case '"' : ndouble++; break;
505
            case "[" : nbr++; break;
506
            case "]" :  if (indx < val.length - 1) { nbr--; break; }
507
            case "," :
508
               if (nbr === 0) {
509
                  var sub =  val.substring(last, indx).trim();
510
                  if ((sub.length>1) && (sub[0]==sub[sub.length-1]) && ((sub[0]=='"') || (sub[0]=="'")))
511
                     sub = sub.substr(1, sub.length-2);
512
                  res.push(sub);
513
                  last = indx+1;
514
               }
515
               break;
516
         }
517
      }
518
 
519
      if (res.length === 0)
520
         res.push(val.substr(1, val.length-2).trim());
521
 
522
      return res;
523
   }
524
 
525
   JSROOT.GetUrlOptionAsArray = function(opt, url) {
526
      // special handling of URL options to produce array
527
      // if normal option is specified ...?opt=abc, than array with single element will be created
528
      // one could specify normal JSON array ...?opts=['item1','item2']
529
      // but also one could skip quotes ...?opts=[item1,item2]
530
      // one could collect values from several options, specifying
531
      // options names via semicolon like opt='item;items'
532
 
533
      var res = [];
534
 
535
      while (opt.length>0) {
536
         var separ = opt.indexOf(";");
537
         var part = (separ>0) ? opt.substr(0, separ) : opt;
538
 
539
         if (separ>0) opt = opt.substr(separ+1); else opt = "";
540
 
541
         var canarray = true;
542
         if (part[0]=='#') { part = part.substr(1); canarray = false; }
543
 
544
         var val = this.GetUrlOption(part, url, null);
545
 
546
         if (canarray) res = res.concat(JSROOT.ParseAsArray(val));
547
                  else if (val!==null) res.push(val);
548
      }
549
      return res;
550
   }
551
 
552
   JSROOT.findFunction = function(name) {
553
      if (typeof name === 'function') return name;
554
      if (typeof window[name] == 'function') return window[name];
555
      if ((typeof name !== 'string') || (name.indexOf(".") < 0)) return null;
556
 
557
      var names = name.split('.'), elem = window;
558
      for (var n=0;n<names.length;++n) {
559
         if ((n==0) && (names[0]==='JSROOT'))
560
            elem = this;
561
         else
562
            elem = elem[names[n]];
563
         if (!elem) return null;
564
      }
565
 
566
      return (typeof elem == 'function') ? elem : null;
567
   }
568
 
569
   JSROOT.CallBack = function(func, arg1, arg2) {
570
      // generic method to invoke callback function
571
      // func either normal function or container like
572
      // { obj: object_pointer, func: name of method to call }
573
      // arg1, arg2 are optional arguments of the callback
574
 
575
      if (typeof func == 'string') func = JSROOT.findFunction(func);
576
 
577
      if (func == null) return;
578
 
579
      if (typeof func == 'function') return func(arg1,arg2);
580
 
581
      if (typeof func != 'object') return;
582
 
583
      if (('obj' in func) && ('func' in func) &&
584
         (typeof func.obj == 'object') && (typeof func.func == 'string') &&
585
         (typeof func.obj[func.func] == 'function')) {
586
         alert('Old-style call-back, change code for ' + func.func);
587
             return func.obj[func.func](arg1, arg2);
588
      }
589
   }
590
 
591
   JSROOT.NewHttpRequest = function(url, kind, user_call_back) {
592
      // Create asynchronous XMLHttpRequest object.
593
      // One should call req.send() to submit request
594
      // kind of the request can be:
595
      //  "bin" - abstract binary data, result as string (default)
596
      //  "buf" - abstract binary data, result as BufferArray (if supported)
597
      //  "text" - returns req.responseText
598
      //  "object" - returns JSROOT.parse(req.responseText)
599
      //  "xml" - returns res.responseXML
600
      //  "head" - returns request itself, uses "HEAD" method
601
      // Result will be returned to the callback functions
602
      // Request will be set as this pointer in the callback
603
      // If failed, request returns null
604
 
605
      var xhr = new XMLHttpRequest();
606
 
607
      function callback(res) {
608
         // we set pointer on request when calling callback
609
         if (typeof user_call_back == 'function') user_call_back.call(xhr, res);
610
      }
611
 
612
      var pthis = this;
613
 
614
      if (window.ActiveXObject) {
615
 
616
         xhr.onreadystatechange = function() {
617
            if (xhr.readyState != 4) return;
618
 
619
            if (xhr.status != 200 && xhr.status != 206) {
620
               // error
621
               return callback(null);
622
            }
623
 
624
            if (kind == "xml") return callback(xhr.responseXML);
625
            if (kind == "text") return callback(xhr.responseText);
626
            if (kind == "object") return callback(pthis.parse(xhr.responseText));
627
            if (kind == "head") return callback(xhr);
628
 
629
            if ((kind == "buf") && ('responseType' in xhr) &&
630
                (xhr.responseType == 'arraybuffer') && ('response' in xhr))
631
               return callback(xhr.response);
632
 
633
            var filecontent = new String("");
634
            var array = new VBArray(xhr.responseBody).toArray();
635
            for (var i = 0; i < array.length; ++i)
636
               filecontent = filecontent + String.fromCharCode(array[i]);
637
            delete array;
638
            callback(filecontent);
639
         }
640
 
641
         xhr.open(kind == 'head' ? 'HEAD' : 'GET', url, true);
642
 
643
         if (kind=="buf") {
644
            if (('Uint8Array' in window) && ('responseType' in xhr))
645
              xhr.responseType = 'arraybuffer';
646
         }
647
 
648
      } else {
649
 
650
         xhr.onreadystatechange = function() {
651
            if (xhr.readyState != 4) return;
652
 
653
            if ((xhr.status != 200) && (xhr.status != 206) &&
654
                ((xhr.status !== 0) || (url.indexOf("file://")!==0))) {
655
               return callback(null);
656
            }
657
 
658
            if (kind == "xml") return callback(xhr.responseXML);
659
            if (kind == "text") return callback(xhr.responseText);
660
            if (kind == "object") return callback(pthis.parse(xhr.responseText));
661
            if (kind == "head") return callback(xhr);
662
 
663
            // if no response type is supported, return as text (most probably, will fail)
664
            if (! ('responseType' in xhr))
665
               return callback(xhr.responseText);
666
 
667
            if ((kind=="bin") && ('Uint8Array' in window) && ('byteLength' in xhr.response)) {
668
               // if string representation in requested - provide it
669
 
670
               var filecontent = "", u8Arr = new Uint8Array(xhr.response);
671
               for (var i = 0; i < u8Arr.length; ++i)
672
                  filecontent += String.fromCharCode(u8Arr[i]);
673
               delete u8Arr;
674
 
675
               return callback(filecontent);
676
            }
677
 
678
            callback(xhr.response);
679
         }
680
 
681
         xhr.open(kind == 'head' ? 'HEAD' : 'GET', url, true);
682
 
683
         if ((kind == "bin") || (kind == "buf")) {
684
            if (('Uint8Array' in window) && ('responseType' in xhr)) {
685
               xhr.responseType = 'arraybuffer';
686
            } else {
687
               //XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
688
               xhr.overrideMimeType("text/plain; charset=x-user-defined");
689
            }
690
         }
691
 
692
      }
693
      return xhr;
694
   }
695
 
696
   JSROOT.loadScript = function(urllist, callback, debugout) {
697
      // dynamic script loader using callback
698
      // (as loading scripts may be asynchronous)
699
      // one could specify list of scripts or style files, separated by semicolon ';'
700
      // one can prepend file name with '$$$' - than file will be loaded from JSROOT location
701
      // This location can be set by JSROOT.source_dir or it will be detected automatically
702
      // by the position of JSRootCore.js file, which must be loaded by normal methods:
703
      // <script type="text/javascript" src="scripts/JSRootCore.js"></script>
704
 
705
      function completeLoad() {
706
         if (debugout)
707
            document.getElementById(debugout).innerHTML = "";
708
         else
709
            JSROOT.progress();
710
 
711
         if ((urllist!=null) && (urllist.length>0))
712
            return JSROOT.loadScript(urllist, callback, debugout);
713
 
714
         JSROOT.CallBack(callback);
715
      }
716
 
717
      if ((urllist==null) || (urllist.length==0))
718
         return completeLoad();
719
 
720
      var filename = urllist;
721
      var separ = filename.indexOf(";");
722
      if (separ>0) {
723
         filename = filename.substr(0, separ);
724
         urllist = urllist.slice(separ+1);
725
      } else {
726
         urllist = "";
727
      }
728
 
729
      var isrootjs = false, isbower = false;
730
      if (filename.indexOf("$$$")===0) {
731
         isrootjs = true;
732
         filename = filename.slice(3);
733
         if ((filename.indexOf("style/")==0) && JSROOT.source_min &&
734
             (filename.lastIndexOf('.css')==filename.length-3) &&
735
             (filename.indexOf('.min.css')<0))
736
            filename = filename.slice(0, filename.length-4) + '.min.css';
737
      } else
738
      if (filename.indexOf("###")===0) {
739
         isbower = true;
740
         filename = filename.slice(3);
741
      }
742
 
743
      var font_suffix = filename.indexOf('.typeface.json');
744
      if (font_suffix > 0) {
745
         var fontid = 'threejs_font_' + filename.slice(filename.lastIndexOf('/')+1, font_suffix);
746
         if (typeof JSROOT[fontid] !== 'undefined') return completeLoad();
747
 
748
         if ((typeof THREE === 'undefined') || (typeof THREE.FontLoader === 'undefined')) {
749
            console.log('fail to load',filename,'no (proper) three.js found');
750
            return completeLoad();
751
         }
752
 
753
         JSROOT.progress("loading " + filename + " ...");
754
 
755
         var loader = new THREE.FontLoader();
756
         loader.load( filename, function ( response ) {
757
            JSROOT[fontid] = response;
758
            completeLoad();
759
         } );
760
         return;
761
      }
762
 
763
      var isstyle = filename.indexOf('.css') > 0;
764
 
765
      if (isstyle) {
766
         var styles = document.getElementsByTagName('link');
767
         for (var n = 0; n < styles.length; ++n) {
768
            if ((styles[n].type != 'text/css') || (styles[n].rel !== 'stylesheet')) continue;
769
 
770
            var href = styles[n].href;
771
            if ((href == null) || (href.length == 0)) continue;
772
 
773
            if (href.indexOf(filename)>=0) return completeLoad();
774
         }
775
 
776
      } else {
777
         var scripts = document.getElementsByTagName('script');
778
 
779
         for (var n = 0; n < scripts.length; ++n) {
780
            // if (scripts[n].type != 'text/javascript') continue;
781
 
782
            var src = scripts[n].src;
783
            if ((src == null) || (src.length == 0)) continue;
784
 
785
            if ((src.indexOf(filename)>=0) && (src.indexOf("load=")<0)) {
786
               // avoid wrong decision when script name is specified as more argument
787
               return completeLoad();
788
            }
789
         }
790
      }
791
 
792
      if (isrootjs && (JSROOT.source_dir!=null)) filename = JSROOT.source_dir + filename; else
793
      if (isbower && (JSROOT.bower_dir.length>0)) filename = JSROOT.bower_dir + filename;
794
 
795
      var element = null;
796
 
797
      if (debugout)
798
         document.getElementById(debugout).innerHTML = "loading " + filename + " ...";
799
      else
800
         JSROOT.progress("loading " + filename + " ...");
801
 
802
      if (isstyle) {
803
         element = document.createElement("link");
804
         element.setAttribute("rel", "stylesheet");
805
         element.setAttribute("type", "text/css");
806
         element.setAttribute("href", filename);
807
      } else {
808
         element = document.createElement("script");
809
         element.setAttribute('type', "text/javascript");
810
         element.setAttribute('src', filename);
811
      }
812
 
813
      if (element.readyState) { // Internet Explorer specific
814
         element.onreadystatechange = function() {
815
            if (element.readyState == "loaded" || element.readyState == "complete") {
816
               element.onreadystatechange = null;
817
               completeLoad();
818
            }
819
         }
820
      } else { // Other browsers
821
         element.onload = function() {
822
            element.onload = null;
823
            completeLoad();
824
         }
825
      }
826
 
827
      document.getElementsByTagName("head")[0].appendChild(element);
828
   }
829
 
830
   JSROOT.AssertPrerequisites = function(kind, callback, debugout) {
831
      // one could specify kind of requirements
832
      // 'io' for I/O functionality (default)
833
      // '2d' for basic 2d graphic (TCanvas, TH1)
834
      // 'more2d' for extra 2d graphic (TH2, TGraph)
835
      // 'jq' jQuery and jQuery-ui
836
      // 'jq2d' jQuery-dependend part of 2d graphic
837
      // '3d' for histograms 3d graphic
838
      // 'geom' for geometry drawing support
839
      // 'simple' for basic user interface
840
      // 'load:' list of user-specific scripts at the end of kind string
841
 
842
      var jsroot = JSROOT;
843
 
844
      if (jsroot.doing_assert === undefined) jsroot.doing_assert = [];
845
      if (jsroot.ready_modules === undefined) jsroot.ready_modules = [];
846
 
847
      if ((typeof kind !== 'string') || (kind == ''))
848
         return jsroot.CallBack(callback);
849
 
850
      if (kind === '__next__') {
851
         if (jsroot.doing_assert.length==0) return;
852
         var req = jsroot.doing_assert[0];
853
         if (req.running) return;
854
         kind = req._kind;
855
         callback = req._callback;
856
         debugout = req._debug;
857
      } else {
858
         jsroot.doing_assert.push({_kind:kind, _callback:callback, _debug: debugout});
859
         if (jsroot.doing_assert.length > 1) return;
860
      }
861
 
862
      jsroot.doing_assert[0].running = true;
863
 
864
      if (kind.charAt(kind.length-1)!=";") kind+=";";
865
 
866
      var ext = jsroot.source_min ? ".min" : "",
867
          need_jquery = false,
868
          use_bower = (jsroot.bower_dir.length > 0),
869
          mainfiles = "",
870
          extrafiles = "", // scripts for direct loadin
871
          modules = [];  // modules used for require.js
872
 
873
      if (kind.indexOf('io;')>=0) {
874
         mainfiles += "$$$scripts/rawinflate.min.js;" +
875
                      "$$$scripts/JSRootIOEvolution" + ext + ".js;";
876
         modules.push('JSRootIOEvolution');
877
      }
878
 
879
      if (kind.indexOf('2d;')>=0) {
880
         if (jsroot._test_d3_ === undefined) {
881
            if (typeof d3 != 'undefined') {
882
               jsroot.console('Reuse existing d3.js ' + d3.version + ", required 3.5.9", debugout);
883
               jsroot._test_d3_ = 1;
884
            } else {
885
               mainfiles += use_bower ? '###d3/d3.min.js;' : '$$$scripts/d3.v3.min.js;';
886
               jsroot._test_d3_ = 2;
887
            }
888
         }
889
         modules.push('JSRootPainter');
890
         mainfiles += '$$$scripts/JSRootPainter' + ext + ".js;";
891
         extrafiles += '$$$style/JSRootPainter' + ext + '.css;';
892
      }
893
 
894
      if (kind.indexOf('savepng;')>=0) {
895
         modules.push('saveSvgAsPng');
896
         mainfiles += '$$$scripts/saveSvgAsPng.min.js;';
897
      }
898
 
899
      if (kind.indexOf('jq;')>=0) need_jquery = true;
900
 
901
      if (kind.indexOf('math;')>=0)  {
902
         mainfiles += '$$$scripts/JSRootMath' + ext + ".js;";
903
         modules.push('JSRootMath');
904
      }
905
 
906
      if (kind.indexOf('more2d;')>=0) {
907
         mainfiles += '$$$scripts/JSRootPainter.more' + ext + ".js;";
908
         modules.push('JSRootPainter.more');
909
      }
910
 
911
      if (kind.indexOf('jq2d;')>=0) {
912
         mainfiles += '$$$scripts/JSRootPainter.jquery' + ext + ".js;";
913
         modules.push('JSRootPainter.jquery');
914
         need_jquery = true;
915
      }
916
 
917
      if ((kind.indexOf("3d;")>=0) || (kind.indexOf("geom;")>=0)) {
918
         if (use_bower) {
919
           mainfiles += "###threejs/build/three.min.js;" +
920
                        "###threejs/examples/js/renderers/Projector.js;" +
921
                        "###threejs/examples/js/renderers/CanvasRenderer.js;" +
922
                        "###threejs/examples/js/controls/OrbitControls.js;" +
923
                        "###threejs/examples/js/controls/TransformControls.js;" +
924
                        "###threejs/examples/js/shaders/CopyShader.js;" +
925
                        "###threejs/examples/js/postprocessing/EffectComposer.js;" +
926
                        "###threejs/examples/js/postprocessing/MaskPass.js;" +
927
                        "###threejs/examples/js/postprocessing/RenderPass.js;" +
928
                        "###threejs/examples/js/postprocessing/ShaderPass.js;" +
929
                        "###threejs/examples/js/shaders/SSAOShader.js;"
930
           extrafiles += "###threejs/examples/fonts/helvetiker_regular.typeface.json;";
931
         } else {
932
            mainfiles += "$$$scripts/three.min.js;" +
933
                         "$$$scripts/three.extra.min.js;";
934
         }
935
         modules.push("threejs", "threejs_all");
936
         mainfiles += "$$$scripts/JSRoot3DPainter" + ext + ".js;";
937
         modules.push('JSRoot3DPainter');
938
      }
939
 
940
      if (kind.indexOf("geom;")>=0) {
941
         mainfiles += "$$$scripts/ThreeCSG" + ext + ".js;" +
942
                      "$$$scripts/JSRootGeoBase" + ext + ".js;" +
943
                      "$$$scripts/JSRootGeoPainter" + ext + ".js;" +
944
                      "$$$scripts/dat.gui.min.js;";
945
         extrafiles += "$$$style/JSRootGeoPainter" + ext + ".css;";
946
         modules.push('ThreeCSG', 'JSRootGeoBase', 'JSRootGeoPainter', 'dat.gui');
947
      }
948
 
949
      if (kind.indexOf("mathjax;")>=0) {
950
         if (typeof MathJax == 'undefined') {
951
            mainfiles += (use_bower ? "###MathJax/MathJax.js" : "https://cdn.mathjax.org/mathjax/latest/MathJax.js") +
952
                         "?config=TeX-AMS-MML_SVG," + jsroot.source_dir + "scripts/mathjax_config.js;";
953
         }
954
         if (jsroot.gStyle.MathJax == 0) jsroot.gStyle.MathJax = 1;
955
         modules.push('MathJax');
956
      }
957
 
958
      if (kind.indexOf("simple;")>=0) {
959
         need_jquery = true;
960
         mainfiles += '$$$scripts/JSRootInterface' + ext + ".js;";
961
         extrafiles += '$$$style/JSRootInterface' + ext + '.css;';
962
         modules.push('JSRootInterface');
963
      }
964
 
965
      if (need_jquery && !jsroot.load_jquery) {
966
         var has_jq = (typeof jQuery != 'undefined'), lst_jq = "";
967
 
968
         if (has_jq)
969
            jsroot.console('Reuse existing jQuery ' + jQuery.fn.jquery + ", required 2.1.4", debugout);
970
         else
971
            lst_jq += (use_bower ? "###jquery/dist" : "$$$scripts") + "/jquery.min.js;";
972
         if (has_jq && typeof $.ui != 'undefined')
973
            jsroot.console('Reuse existing jQuery-ui ' + $.ui.version + ", required 1.11.4", debugout);
974
         else {
975
            lst_jq += (use_bower ? "###jquery-ui" : "$$$scripts") + '/jquery-ui.min.js;';
976
            extrafiles += '$$$style/jquery-ui' + ext + '.css;';
977
         }
978
 
979
         if (jsroot.touches) {
980
            lst_jq += use_bower ? '###jqueryui-touch-punch/jquery.ui.touch-punch.min.js;' : '$$$scripts/touch-punch.min.js;';
981
            modules.push('jqueryui-touch-punch');
982
         }
983
 
984
         modules.splice(0,0, 'jquery', 'jquery-ui', 'jqueryui-mousewheel');
985
         mainfiles = lst_jq + mainfiles;
986
 
987
         jsroot.load_jquery = true;
988
      }
989
 
990
      var pos = kind.indexOf("user:");
991
      if (pos<0) pos = kind.indexOf("load:");
992
      if (pos>=0) extrafiles += kind.slice(pos+5);
993
 
994
      function load_callback() {
995
         var req = jsroot.doing_assert.shift();
996
         for (var n=0;n<req.modules.length;++n)
997
            jsroot.ready_modules.push(req.modules[n]);
998
         jsroot.CallBack(req._callback);
999
         jsroot.AssertPrerequisites('__next__');
1000
      }
1001
 
1002
      // check if modules already loaded
1003
      for (var n=modules.length-1;n>=0;--n)
1004
         if (jsroot.ready_modules.indexOf(modules[n])>=0)
1005
            modules.splice(n,1);
1006
 
1007
      // no modules means no main files
1008
      if (modules.length===0) mainfiles = "";
1009
 
1010
      jsroot.doing_assert[0].modules = modules;
1011
 
1012
      if ((modules.length>0) && (typeof define === "function") && define.amd) {
1013
         jsroot.console("loading " + JSON.stringify(modules) + " with require.js", debugout);
1014
         require(modules, function() {
1015
            jsroot.loadScript(extrafiles, load_callback, debugout);
1016
         });
1017
      } else {
1018
         jsroot.loadScript(mainfiles + extrafiles, load_callback, debugout);
1019
      }
1020
   }
1021
 
1022
   // function can be used to open ROOT file, I/O functionality will be loaded when missing
1023
   JSROOT.OpenFile = function(filename, callback) {
1024
      JSROOT.AssertPrerequisites("io", function() {
1025
         new JSROOT.TFile(filename, callback);
1026
      });
1027
   }
1028
 
1029
   // function can be used to draw supported ROOT classes,
1030
   // required functionality will be loaded automatically
1031
   // if painter pointer required, one should load '2d' functionlity itself
1032
   JSROOT.draw = function(divid, obj, opt) {
1033
      JSROOT.AssertPrerequisites("2d", function() {
1034
         JSROOT.draw(divid, obj, opt);
1035
      });
1036
   }
1037
 
1038
   JSROOT.redraw = function(divid, obj, opt) {
1039
      JSROOT.AssertPrerequisites("2d", function() {
1040
         JSROOT.redraw(divid, obj, opt);
1041
      });
1042
   }
1043
 
1044
   JSROOT.BuildSimpleGUI = function(user_scripts, andThen) {
1045
      if (typeof user_scripts == 'function') {
1046
         andThen = user_scripts;
1047
         user_scripts = null;
1048
      }
1049
 
1050
      var debugout = null,
1051
          nobrowser = JSROOT.GetUrlOption('nobrowser')!=null,
1052
          requirements = "io;2d;",
1053
          simplegui = document.getElementById('simpleGUI');
1054
 
1055
      if (simplegui) {
1056
         debugout = 'simpleGUI';
1057
         if ((JSROOT.GetUrlOption('json')!=null) &&
1058
             (JSROOT.GetUrlOption('file')==null) &&
1059
             (JSROOT.GetUrlOption('files')==null)) requirements = "2d;";
1060
         if (simplegui.getAttribute('nobrowser') && (simplegui.getAttribute('nobrowser')!="false")) nobrowser = true;
1061
      } else
1062
      if (document.getElementById('onlineGUI')) { debugout = 'onlineGUI'; requirements = "2d;"; } else
1063
      if (document.getElementById('drawGUI')) { debugout = 'drawGUI'; requirements = "2d;"; nobrowser = true; }
1064
 
1065
      if (user_scripts == 'check_existing_elements') {
1066
         user_scripts = null;
1067
         if (debugout == null) return;
1068
      }
1069
 
1070
      if (!nobrowser) requirements += 'jq2d;simple;';
1071
 
1072
      if (user_scripts == null) user_scripts = JSROOT.GetUrlOption("autoload");
1073
      if (user_scripts == null) user_scripts = JSROOT.GetUrlOption("load");
1074
 
1075
      if (user_scripts != null)
1076
         requirements += "load:" + user_scripts + ";";
1077
 
1078
      JSROOT.AssertPrerequisites(requirements, function() {
1079
         JSROOT.CallBack(JSROOT.findFunction(nobrowser ? 'JSROOT.BuildNobrowserGUI' : 'BuildSimpleGUI'));
1080
         JSROOT.CallBack(andThen);
1081
      }, debugout);
1082
   };
1083
 
1084
   JSROOT.Create = function(typename, target) {
1085
      var obj = target;
1086
      if (obj == null) obj = { _typename: typename };
1087
 
1088
      switch (typename) {
1089
         case 'TObject':
1090
             JSROOT.extend(obj, { fUniqueID: 0, fBits: 0x3000008 });
1091
             break;
1092
         case 'TNamed':
1093
            JSROOT.extend(obj, { fUniqueID: 0, fBits: 0x3000008, fName: "", fTitle: "" });
1094
            break;
1095
         case 'TList':
1096
         case 'THashList':
1097
            JSROOT.extend(obj, { name: typename, arr : [], opt : [] });
1098
            break;
1099
         case 'TAttAxis':
1100
            JSROOT.extend(obj, { fNdivisions: 510, fAxisColor: 1,
1101
                                 fLabelColor: 1, fLabelFont: 42, fLabelOffset: 0.005, fLabelSize: 0.035, fTickLength: 0.03,
1102
                                 fTitleOffset: 1, fTitleSize: 0.035, fTitleColor: 1, fTitleFont : 42 });
1103
            break;
1104
         case 'TAxis':
1105
            JSROOT.Create("TNamed", obj);
1106
            JSROOT.Create("TAttAxis", obj);
1107
            JSROOT.extend(obj, { fNbins: 0, fXmin: 0, fXmax: 0, fXbins : [], fFirst: 0, fLast: 0,
1108
                                 fBits2: 0, fTimeDisplay: false, fTimeFormat: "", fLabels: null });
1109
            break;
1110
         case 'TAttLine':
1111
            JSROOT.extend(obj, { fLineColor: 1, fLineStyle : 1, fLineWidth : 1 });
1112
            break;
1113
         case 'TAttFill':
1114
            JSROOT.extend(obj, { fFillColor: 0, fFillStyle : 0 } );
1115
            break;
1116
         case 'TAttMarker':
1117
            JSROOT.extend(obj, { fMarkerColor: 1, fMarkerStyle : 1, fMarkerSize : 1. });
1118
            break;
1119
         case 'TLine':
1120
            JSROOT.Create("TObject", obj);
1121
            JSROOT.Create("TAttLine", obj);
1122
            JSROOT.extend(obj, { fX1: 0, fX2: 1, fY1: 0, fY2: 1 });
1123
            break;
1124
         case 'TBox':
1125
            JSROOT.Create("TObject", obj);
1126
            JSROOT.Create("TAttLine", obj);
1127
            JSROOT.Create("TAttFill", obj);
1128
            JSROOT.extend(obj, { fX1: 0, fX2: 1, fY1: 0, fY2: 1 });
1129
            break;
1130
         case 'TPave':
1131
            JSROOT.Create("TBox", obj);
1132
            JSROOT.extend(obj, { fX1NDC : 0., fY1NDC: 0, fX2NDC: 1, fY2NDC: 1,
1133
                                 fBorderSize: 0, fInit: 1, fShadowColor: 1,
1134
                                 fCornerRadius: 0, fOption: "blNDC", fName: "title" });
1135
            break;
1136
         case 'TAttText':
1137
            JSROOT.extend(obj, { fTextAngle: 0, fTextSize: 0, fTextAlign: 22, fTextColor: 1, fTextFont: 42});
1138
            break;
1139
         case 'TPaveText':
1140
            JSROOT.Create("TPave", obj);
1141
            JSROOT.Create("TAttText", obj);
1142
            JSROOT.extend(obj, { fLabel: "", fLongest: 27, fMargin: 0.05, fLines: JSROOT.Create("TList") });
1143
            break;
1144
         case 'TPaveStats':
1145
            JSROOT.Create("TPaveText", obj);
1146
            JSROOT.extend(obj, { fOptFit: 0, fOptStat: 0, fFitFormat: "", fStatFormat: "", fParent: null });
1147
            break;
1148
         case 'TLegend':
1149
            JSROOT.Create("TPave", obj);
1150
            JSROOT.Create("TAttText", obj);
1151
            JSROOT.extend(obj, { fColumnSeparation: 0, fEntrySeparation: 0.1, fMargin: 0.25, fNColumns: 1, fPrimitives: JSROOT.Create("TList") });
1152
            break;
1153
         case 'TLegendEntry':
1154
            JSROOT.Create("TObject", obj);
1155
            JSROOT.Create("TAttText", obj);
1156
            JSROOT.Create("TAttLine", obj);
1157
            JSROOT.Create("TAttFill", obj);
1158
            JSROOT.Create("TAttMarker", obj);
1159
            JSROOT.extend(obj, { fLabel: "", fObject: null, fOption: "" });
1160
            break;
1161
         case 'TObjString':
1162
            JSROOT.Create("TObject", obj);
1163
            JSROOT.extend(obj, { fString: "" });
1164
            break;
1165
         case 'TH1':
1166
            JSROOT.Create("TNamed", obj);
1167
            JSROOT.Create("TAttLine", obj);
1168
            JSROOT.Create("TAttFill", obj);
1169
            JSROOT.Create("TAttMarker", obj);
1170
 
1171
            JSROOT.extend(obj, {
1172
               fNcells : 0,
1173
               fXaxis: JSROOT.Create("TAxis"),
1174
               fYaxis: JSROOT.Create("TAxis"),
1175
               fZaxis: JSROOT.Create("TAxis"),
1176
               fBarOffset: 0, fBarWidth: 1000, fEntries: 0.,
1177
               fTsumw: 0., fTsumw2: 0., fTsumwx: 0., fTsumwx2: 0.,
1178
               fMaximum: -1111., fMinimum: -1111, fNormFactor: 0., fContour: [],
1179
               fSumw2: [], fOption: "",
1180
               fFunctions: JSROOT.Create("TList"),
1181
               fBufferSize: 0, fBuffer: [], fBinStatErrOpt: 0 });
1182
            break;
1183
         case 'TH1I':
1184
         case 'TH1F':
1185
         case 'TH1D':
1186
         case 'TH1S':
1187
         case 'TH1C':
1188
            JSROOT.Create("TH1", obj);
1189
            obj.fArray = [];
1190
            break;
1191
         case 'TH2':
1192
            JSROOT.Create("TH1", obj);
1193
            JSROOT.extend(obj, { fScalefactor: 1., fTsumwy: 0.,  fTsumwy2: 0, fTsumwxy : 0});
1194
            break;
1195
         case 'TH2I':
1196
         case 'TH2F':
1197
         case 'TH2D':
1198
         case 'TH2S':
1199
         case 'TH2C':
1200
            JSROOT.Create("TH2", obj);
1201
            obj.fArray = [];
1202
            break;
1203
         case 'TGraph':
1204
            JSROOT.Create("TNamed", obj);
1205
            JSROOT.Create("TAttLine", obj);
1206
            JSROOT.Create("TAttFill", obj);
1207
            JSROOT.Create("TAttMarker", obj);
1208
            JSROOT.extend(obj, { fFunctions: JSROOT.Create("TList"), fHistogram: null,
1209
                                 fMaxSize: 0, fMaximum:-1111, fMinimum:-1111, fNpoints: 0, fX: [], fY: [] });
1210
            break;
1211
         case 'TMultiGraph':
1212
            JSROOT.Create("TNamed", obj);
1213
            JSROOT.extend(obj, { fFunctions: JSROOT.Create("TList"), fGraphs: JSROOT.Create("TList"),
1214
                                 fHistogram: null, fMaximum: -1111, fMinimum: -1111 });
1215
            break;
1216
         case 'TPolyLine':
1217
            JSROOT.Create("TObject", obj);
1218
            JSROOT.Create("TAttLine", obj);
1219
            JSROOT.Create("TAttFill", obj);
1220
            JSROOT.extend(obj, { fLastPoint: -1, fN: 0, fOption: "", fX: null, fY: null });
1221
            break;
1222
         case 'TGaxis':
1223
            JSROOT.Create("TLine", obj);
1224
            JSROOT.Create("TAttText", obj);
1225
            JSROOT.extend(obj, { _fChopt: "", fFunctionName: "", fGridLength: 0,
1226
                                  fLabelColor: 1, fLabelFont: 42, fLabelOffset: 0.005, fLabelSize: 0.035,
1227
                                  fName: "", fNdiv: 12, fTickSize: 0.02, fTimeFormat: "",
1228
                                  fTitle: "", fTitleOffset: 1, fTitleSize: 0.035,
1229
                                  fWmax: 100, fWmin: 0 });
1230
            break;
1231
         case 'TAttPad':
1232
            JSROOT.extend(obj, { fLeftMargin: JSROOT.gStyle.fPadLeftMargin,
1233
                                 fRightMargin: JSROOT.gStyle.fPadRightMargin,
1234
                                 fBottomMargin: JSROOT.gStyle.fPadBottomMargin,
1235
                                 fTopMargin: JSROOT.gStyle.fPadTopMargin,
1236
                                 fXfile: 2, fYfile: 2, fAfile: 1, fXstat: 0.99, fYstat: 0.99, fAstat: 2,
1237
                                 fFrameFillColor: JSROOT.gStyle.fFrameFillColor,
1238
                                 fFrameLineColor: JSROOT.gStyle.fFrameLineColor,
1239
                                 fFrameFillStyle: JSROOT.gStyle.fFrameFillStyle,
1240
                                 fFrameLineStyle: JSROOT.gStyle.fFrameLineStyle,
1241
                                 fFrameLineWidth: JSROOT.gStyle.fFrameLineWidth,
1242
                                 fFrameBorderSize: JSROOT.gStyle.fFrameBorderSize,
1243
                                 fFrameBorderMode: JSROOT.gStyle.fFrameBorderMode });
1244
            break;
1245
         case 'TPad':
1246
            JSROOT.Create("TObject", obj);
1247
            JSROOT.Create("TAttLine", obj);
1248
            JSROOT.Create("TAttFill", obj);
1249
            JSROOT.Create("TAttPad", obj);
1250
            JSROOT.extend(obj, { fX1: 0, fY1: 0, fX2: 1, fY2: 1, fXtoAbsPixelk: 1, fXtoPixelk: 1,
1251
                                 fXtoPixel: 1, fYtoAbsPixelk: 1, fYtoPixelk: 1, fYtoPixel: 1,
1252
                                 fUtoAbsPixelk: 1, fUtoPixelk: 1, fUtoPixel: 1, fVtoAbsPixelk: 1,
1253
                                 fVtoPixelk: 1, fVtoPixel: 1, fAbsPixeltoXk: 1, fPixeltoXk: 1,
1254
                                 fPixeltoX: 1, fAbsPixeltoYk: 1, fPixeltoYk: 1, fPixeltoY: 1,
1255
                                 fXlowNDC: 0, fYlowNDC: 0, fXUpNDC: 0, fYUpNDC: 0, fWNDC: 1, fHNDC: 1,
1256
                                 fAbsXlowNDC: 0, fAbsYlowNDC: 0, fAbsWNDC: 1, fAbsHNDC: 1,
1257
                                 fUxmin: 0, fUymin: 0, fUxmax: 0, fUymax: 0, fTheta: 30, fPhi: 30, fAspectRatio: 0,
1258
                                 fNumber: 0, fLogx: 0, fLogy: 0, fLogz: 0,
1259
                                 fTickx: JSROOT.gStyle.fPadTickX,
1260
                                 fTicky: JSROOT.gStyle.fPadTickY,
1261
                                 fPadPaint: 0, fCrosshair: 0, fCrosshairPos: 0, fBorderSize: 2,
1262
                                 fBorderMode: 0, fModified: false,
1263
                                 fGridx: JSROOT.gStyle.fPadGridX,
1264
                                 fGridy: JSROOT.gStyle.fPadGridY,
1265
                                 fAbsCoord: false, fEditable: true, fFixedAspectRatio: false,
1266
                                 fPrimitives: JSROOT.Create("TList"), fExecs: null,
1267
                                 fName: "pad", fTitle: "canvas" });
1268
 
1269
            break;
1270
         case 'TAttCanvas':
1271
            JSROOT.extend(obj, { fXBetween: 2, fYBetween: 2, fTitleFromTop: 1.2,
1272
                                 fXdate: 0.2, fYdate: 0.3, fAdate: 1 });
1273
            break;
1274
         case 'TCanvas':
1275
            JSROOT.Create("TPad", obj);
1276
            JSROOT.extend(obj, { fDoubleBuffer: 0, fRetained: true, fXsizeUser: 0,
1277
                                 fYsizeUser: 0, fXsizeReal: 20, fYsizeReal: 10,
1278
                                 fWindowTopX: 0, fWindowTopY: 0, fWindowWidth: 0, fWindowHeight: 0,
1279
                                 fCw: 800, fCh : 500, fCatt: JSROOT.Create("TAttCanvas"),
1280
                                 kMoveOpaque: true, kResizeOpaque: true, fHighLightColor: 5,
1281
                                 fBatch: true, kShowEventStatus: false, kAutoExec: true, kMenuBar: true });
1282
            break;
1283
         case 'TGeoVolume':
1284
            JSROOT.Create("TNamed", obj);
1285
            JSROOT.Create("TAttLine", obj);
1286
            JSROOT.Create("TAttFill", obj);
1287
            JSROOT.extend(obj, { fGeoAtt:0, fFinder: null, fMedium: null, fNodes: null, fNtotal: 0, fNumber: 0, fRefCount: 0, fShape: null, fVoxels: null });
1288
            break;
1289
         case 'TGeoNode':
1290
            JSROOT.Create("TNamed", obj);
1291
            JSROOT.extend(obj, { fGeoAtt:0, fMother: null, fNovlp: 0, fNumber: 0, fOverlaps: null, fVolume: null });
1292
            break;
1293
         case 'TGeoNodeMatrix':
1294
            JSROOT.Create("TGeoNode", obj);
1295
            JSROOT.extend(obj, { fMatrix: null });
1296
            break;
1297
      }
1298
 
1299
      obj._typename = typename;
1300
      this.addMethods(obj);
1301
      return obj;
1302
   }
1303
 
1304
   // obsolete functions, can be removed by next JSROOT release
1305
   JSROOT.CreateTList = function() { return JSROOT.Create("TList"); }
1306
   JSROOT.CreateTAxis = function() { return JSROOT.Create("TAxis"); }
1307
 
1308
   JSROOT.CreateTH1 = function(nbinsx) {
1309
      var histo = JSROOT.extend(JSROOT.Create("TH1I"),
1310
                   { fName: "dummy_histo_" + this.id_counter++, fTitle: "dummytitle" });
1311
 
1312
      if (nbinsx!==undefined) {
1313
         histo.fNcells = nbinsx+2;
1314
         for (var i=0;i<histo.fNcells;++i) histo.fArray.push(0);
1315
         JSROOT.extend(histo.fXaxis, { fNbins: nbinsx, fXmin: 0, fXmax: nbinsx });
1316
      }
1317
      return histo;
1318
   }
1319
 
1320
   JSROOT.CreateTH2 = function(nbinsx, nbinsy) {
1321
      var histo = JSROOT.extend(JSROOT.Create("TH2I"),
1322
                    { fName: "dummy_histo_" + this.id_counter++, fTitle: "dummytitle" });
1323
 
1324
      if ((nbinsx!==undefined) && (nbinsy!==undefined)) {
1325
         histo.fNcells = (nbinsx+2) * (nbinsy+2);
1326
         for (var i=0;i<histo.fNcells;++i) histo.fArray.push(0);
1327
         JSROOT.extend(histo.fXaxis, { fNbins: nbinsx, fXmin: 0, fXmax: nbinsx });
1328
         JSROOT.extend(histo.fYaxis, { fNbins: nbinsy, fXmin: 0, fXmax: nbinsy });
1329
      }
1330
      return histo;
1331
   }
1332
 
1333
 
1334
   JSROOT.CreateTPolyLine = function(npoints, use_int32) {
1335
      var poly = JSROOT.Create("TPolyLine");
1336
      if (npoints) {
1337
         poly.fN = npoints;
1338
         if (use_int32) {
1339
            poly.fX = new Int32Array(npoints);
1340
            poly.fY = new Int32Array(npoints);
1341
         } else {
1342
            poly.fX = new Float32Array(npoints);
1343
            poly.fY = new Float32Array(npoints);
1344
         }
1345
      }
1346
 
1347
      return poly;
1348
   }
1349
 
1350
   JSROOT.CreateTGraph = function(npoints, xpts, ypts) {
1351
      var graph = JSROOT.extend(JSROOT.Create("TGraph"),
1352
              { fBits: 0x3000408, fName: "dummy_graph_" + this.id_counter++, fTitle: "dummytitle" });
1353
 
1354
      if (npoints>0) {
1355
         graph.fMaxSize = graph.fNpoints = npoints;
1356
 
1357
         var usex = (typeof xpts == 'object') && (xpts.length === npoints);
1358
         var usey = (typeof ypts == 'object') && (ypts.length === npoints);
1359
 
1360
         for (var i=0;i<npoints;++i) {
1361
            graph.fX.push(usex ? xpts[i] : i/npoints);
1362
            graph.fY.push(usey ? ypts[i] : i/npoints);
1363
         }
1364
      }
1365
 
1366
      return graph;
1367
   }
1368
 
1369
   JSROOT.CreateTMultiGraph = function() {
1370
      var mgraph = JSROOT.Create("TMultiGraph");
1371
      for(var i=0; i<arguments.length; ++i)
1372
          mgraph.fGraphs.Add(arguments[i], "");
1373
      return mgraph;
1374
   }
1375
 
1376
   JSROOT.methodsCache = {}; // variable used to keep methods for known classes
1377
 
1378
   JSROOT.getMethods = function(typename, obj) {
1379
      var m = JSROOT.methodsCache[typename];
1380
 
1381
      var has_methods = (m!==undefined);
1382
 
1383
      if (!has_methods) m = {};
1384
 
1385
      // Due to binary I/O such TObject methods may not be set for derived classes
1386
      // Therefore when methods requested for given object, check also that basic methods are there
1387
      if ((typename=="TObject") || (typename=="TNamed") || (obj && (obj.fBits!==undefined)))
1388
         if (m.TestBit === undefined) {
1389
            m.TestBit = function (f) { return (this.fBits & f) != 0; };
1390
            m.InvertBit = function (f) { this.fBits = this.fBits ^ (f & 0xffffff); };
1391
         }
1392
 
1393
      if (has_methods) return m;
1394
 
1395
      if ((typename === 'TList') || (typename === 'THashList')) {
1396
         m.Clear = function() {
1397
            this.arr = [];
1398
            this.opt = [];
1399
         }
1400
         m.Add = function(obj,opt) {
1401
            this.arr.push(obj);
1402
            this.opt.push((opt && typeof opt=='string') ? opt : "");
1403
         }
1404
         m.AddFirst = function(obj,opt) {
1405
            this.arr.unshift(obj);
1406
            this.opt.unshift((opt && typeof opt=='string') ? opt : "");
1407
         }
1408
         m.RemoveAt = function(indx) {
1409
            this.arr.splice(indx, 1);
1410
            this.opt.splice(indx, 1);
1411
         }
1412
      }
1413
 
1414
      if ((typename === "TPaveText") || (typename === "TPaveStats")) {
1415
         m.AddText = function(txt) {
1416
            this.fLines.Add({ _typename: 'TText', fTitle: txt, fTextColor: 1 });
1417
         }
1418
         m.Clear = function() {
1419
            this.fLines.Clear();
1420
         }
1421
      }
1422
 
1423
      if ((typename.indexOf("TF1") == 0) || (typename === "TF2")) {
1424
         m.addFormula = function(obj) {
1425
            if (!obj) return;
1426
            if (this.formulas === undefined) this.formulas = [];
1427
            this.formulas.push(obj);
1428
         }
1429
 
1430
         m.evalPar = function(x, y) {
1431
            if (! ('_func' in this) || (this._title !== this.fTitle)) {
1432
 
1433
              var _func = this.fTitle;
1434
              if (_func === "gaus") _func = "gaus(0)";
1435
 
1436
              if ('formulas' in this)
1437
                 for (var i=0;i<this.formulas.length;++i)
1438
                    while (_func.indexOf(this.formulas[i].fName) >= 0)
1439
                       _func = _func.replace(this.formulas[i].fName, this.formulas[i].fTitle);
1440
              _func = _func.replace(/\b(abs)\b/g, 'TMath::Abs');
1441
              _func = _func.replace('TMath::Exp(', 'Math.exp(');
1442
              _func = _func.replace('TMath::Abs(', 'Math.abs(');
1443
              if (typeof JSROOT.Math == 'object') {
1444
                 this._math = JSROOT.Math;
1445
                 _func = _func.replace('TMath::Prob(', 'this._math.Prob(');
1446
                 _func = _func.replace('TMath::Gaus(', 'this._math.Gaus(');
1447
                 _func = _func.replace('gaus(', 'this._math.gaus(this, x, ');
1448
                 _func = _func.replace('gausn(', 'this._math.gausn(this, x, ');
1449
                 _func = _func.replace('expo(', 'this._math.expo(this, x, ');
1450
                 _func = _func.replace('landau(', 'this._math.landau(this, x, ');
1451
                 _func = _func.replace('landaun(', 'this._math.landaun(this, x, ');
1452
              }
1453
              _func = _func.replace('pi', 'Math.PI');
1454
              for (var i=0;i<this.fNpar;++i)
1455
                 while(_func.indexOf('['+i+']') != -1)
1456
                    _func = _func.replace('['+i+']', '('+this.GetParValue(i)+')');
1457
              _func = _func.replace(/\b(sin)\b/gi, 'Math.sin');
1458
              _func = _func.replace(/\b(cos)\b/gi, 'Math.cos');
1459
              _func = _func.replace(/\b(tan)\b/gi, 'Math.tan');
1460
              _func = _func.replace(/\b(exp)\b/gi, 'Math.exp');
1461
              for (var n=2;n<10;++n)
1462
                 _func = _func.replace('x^'+n, 'Math.pow(x,'+n+')');
1463
 
1464
              if (this._typename==="TF2")
1465
                 this._func = new Function("x", "y", "return " + _func).bind(this);
1466
              else
1467
                 this._func = new Function("x", "return " + _func).bind(this);
1468
 
1469
              this._title = this.fTitle;
1470
            }
1471
 
1472
            return this._func(x, y);
1473
         }
1474
         m.GetParName = function(n) {
1475
            if (('fFormula' in this) && ('fParams' in this.fFormula)) return this.fFormula.fParams[n].first;
1476
            if ('fNames' in this) return this.fNames[n];
1477
            return "Par"+n;
1478
         }
1479
         m.GetParValue = function(n) {
1480
            if (('fFormula' in this) && ('fClingParameters' in this.fFormula)) return this.fFormula.fClingParameters[n];
1481
            if (('fParams' in this) && (this.fParams!=null))  return this.fParams[n];
1482
            return null;
1483
         }
1484
      }
1485
 
1486
      if ((typename.indexOf("TGraph") == 0) || (typename == "TCutG")) {
1487
         // check if point inside figure specified by the TGrpah
1488
         m.IsInside = function(xp,yp) {
1489
            var i, j = this.fNpoints - 1, x = this.fX, y = this.fY, oddNodes = false;
1490
 
1491
            for (i=0; i<this.fNpoints; ++i) {
1492
               if ((y[i]<yp && y[j]>=yp) || (y[j]<yp && y[i]>=yp)) {
1493
                  if (x[i]+(yp-y[i])/(y[j]-y[i])*(x[j]-x[i])<xp) {
1494
                     oddNodes = !oddNodes;
1495
                  }
1496
               }
1497
               j=i;
1498
            }
1499
 
1500
            return oddNodes;
1501
         };
1502
      }
1503
 
1504
      if (typename.indexOf("TH1") == 0 ||
1505
          typename.indexOf("TH2") == 0 ||
1506
          typename.indexOf("TH3") == 0) {
1507
         m.getBinError = function(bin) {
1508
            //   -*-*-*-*-*Return value of error associated to bin number bin*-*-*-*-*
1509
            //    if the sum of squares of weights has been defined (via Sumw2),
1510
            //    this function returns the sqrt(sum of w2).
1511
            //    otherwise it returns the sqrt(contents) for this bin.
1512
            if (bin >= this.fNcells) bin = this.fNcells - 1;
1513
            if (bin < 0) bin = 0;
1514
            if (bin < this.fSumw2.length)
1515
               return Math.sqrt(this.fSumw2[bin]);
1516
            return Math.sqrt(Math.abs(this.fArray[bin]));
1517
         };
1518
         m.setBinContent = function(bin, content) {
1519
            // Set bin content - only trival case, without expansion
1520
            this.fEntries++;
1521
            this.fTsumw = 0;
1522
            if ((bin>=0) && (bin<this.fArray.length))
1523
               this.fArray[bin] = content;
1524
         };
1525
      }
1526
 
1527
      if (typename.indexOf("TH1") == 0) {
1528
         m.getBin = function(x) { return x; }
1529
         m.getBinContent = function(bin) { return this.fArray[bin]; }
1530
         m.Fill = function(x, weight) {
1531
            var axis = this.fXaxis,
1532
                bin = 1 + Math.round((x - axis.fXmin) / (axis.fXmax - axis.fXmin) * axis.fNbins);
1533
            if (bin < 0) bin = 0; else
1534
            if (bin > axis.fNbins + 1) bin = axis.fNbins + 1;
1535
            this.fArray[bin] += ((weight===undefined) ? 1 : weight);
1536
         }
1537
      }
1538
 
1539
      if (typename.indexOf("TH2") == 0) {
1540
         m.getBin = function(x, y) { return (x + (this.fXaxis.fNbins+2) * y); }
1541
         m.getBinContent = function(x, y) { return this.fArray[this.getBin(x, y)]; }
1542
      }
1543
 
1544
      if (typename.indexOf("TH3") == 0) {
1545
         m.getBin = function(x, y, z) { return (x + (this.fXaxis.fNbins+2) * (y + (this.fYaxis.fNbins+2) * z)); }
1546
         m.getBinContent = function(x, y, z) { return this.fArray[this.getBin(x, y, z)]; };
1547
      }
1548
 
1549
      if (typename.indexOf("TProfile") == 0) {
1550
         if (typename.indexOf("TProfile2D") == 0) {
1551
            m.getBin = function(x, y) { return (x + (this.fXaxis.fNbins+2) * y); }
1552
            m.getBinContent = function(x, y) {
1553
               var bin = this.getBin(x, y);
1554
               if (bin < 0 || bin >= this.fNcells) return 0;
1555
               if (this.fBinEntries[bin] < 1e-300) return 0;
1556
               if (!this.fArray) return 0;
1557
               return this.fArray[bin]/this.fBinEntries[bin];
1558
            }
1559
            m.getBinEntries = function(x, y) {
1560
               var bin = this.getBin(x, y);
1561
               if (bin < 0 || bin >= this.fNcells) return 0;
1562
               return this.fBinEntries[bin];
1563
            }
1564
         }
1565
         else {
1566
            m.getBin = function(x) { return x; }
1567
            m.getBinContent = function(bin) {
1568
               if (bin < 0 || bin >= this.fNcells) return 0;
1569
               if (this.fBinEntries[bin] < 1e-300) return 0;
1570
               if (!this.fArray) return 0;
1571
               return this.fArray[bin]/this.fBinEntries[bin];
1572
            };
1573
         }
1574
         m.getBinEffectiveEntries = function(bin) {
1575
            if (bin < 0 || bin >= this.fNcells) return 0;
1576
            var sumOfWeights = this.fBinEntries[bin];
1577
            if ( this.fBinSumw2 == null || this.fBinSumw2.length != this.fNcells) {
1578
               // this can happen  when reading an old file
1579
               return sumOfWeights;
1580
            }
1581
            var sumOfWeightsSquare = this.fSumw2[bin];
1582
            return ( sumOfWeightsSquare > 0 ? sumOfWeights * sumOfWeights / sumOfWeightsSquare : 0 );
1583
         };
1584
         m.getBinError = function(bin) {
1585
            if (bin < 0 || bin >= this.fNcells) return 0;
1586
            var cont = this.fArray[bin],               // sum of bin w *y
1587
                sum  = this.fBinEntries[bin],          // sum of bin weights
1588
                err2 = this.fSumw2[bin],               // sum of bin w * y^2
1589
                neff = this.getBinEffectiveEntries(bin);  // (sum of w)^2 / (sum of w^2)
1590
            if (sum < 1e-300) return 0;                  // for empty bins
1591
            var EErrorType = { kERRORMEAN : 0, kERRORSPREAD : 1, kERRORSPREADI : 2, kERRORSPREADG : 3 };
1592
            // case the values y are gaussian distributed y +/- sigma and w = 1/sigma^2
1593
            if (this.fErrorMode === EErrorType.kERRORSPREADG)
1594
               return 1.0/Math.sqrt(sum);
1595
            // compute variance in y (eprim2) and standard deviation in y (eprim)
1596
            var contsum = cont/sum;
1597
            var eprim2  = Math.abs(err2/sum - contsum*contsum);
1598
            var eprim   = Math.sqrt(eprim2);
1599
            if (this.fErrorMode === EErrorType.kERRORSPREADI) {
1600
               if (eprim != 0) return eprim/Math.sqrt(neff);
1601
               // in case content y is an integer (so each my has an error +/- 1/sqrt(12)
1602
               // when the std(y) is zero
1603
               return 1.0/Math.sqrt(12*neff);
1604
            }
1605
            // if approximate compute the sums (of w, wy and wy2) using all the bins
1606
            //  when the variance in y is zero
1607
            // case option "S" return standard deviation in y
1608
            if (this.fErrorMode === EErrorType.kERRORSPREAD) return eprim;
1609
            // default case : fErrorMode = kERRORMEAN
1610
            // return standard error on the mean of y
1611
            return (eprim/Math.sqrt(neff));
1612
         };
1613
      }
1614
 
1615
      if (typename == "TAxis") {
1616
         m.GetBinLowEdge = function(bin) {
1617
            if (this.fNbins <= 0) return 0;
1618
            if ((this.fXbins.length > 0) && (bin > 0) && (bin <= this.fNbins)) return this.fXbins[bin-1];
1619
            return this.fXmin + (bin-1) * (this.fXmax - this.fXmin) / this.fNbins;
1620
         }
1621
      }
1622
 
1623
      JSROOT.methodsCache[typename] = m;
1624
      return m;
1625
   };
1626
 
1627
   JSROOT.addMethods = function(obj) {
1628
      this.extend(obj, JSROOT.getMethods(obj._typename, obj));
1629
   };
1630
 
1631
   JSROOT.lastFFormat = "";
1632
 
1633
   JSROOT.FFormat = function(value, fmt) {
1634
      // method used to convert numeric value to string according specified format
1635
      // format can be like 5.4g or 4.2e or 6.4f
1636
      // function saves actual format in JSROOT.lastFFormat variable
1637
      if (!fmt) fmt = "6.4g";
1638
 
1639
      JSROOT.lastFFormat = "";
1640
 
1641
      fmt = fmt.trim();
1642
      var len = fmt.length;
1643
      if (len<2) return value.toFixed(4);
1644
      var last = fmt.charAt(len-1);
1645
      fmt = fmt.slice(0,len-1);
1646
      var isexp = null;
1647
      var prec = fmt.indexOf(".");
1648
      if (prec<0) prec = 4; else prec = Number(fmt.slice(prec+1));
1649
      if (isNaN(prec) || (prec<0) || (prec==null)) prec = 4;
1650
 
1651
      var significance = false;
1652
      if ((last=='e') || (last=='E')) { isexp = true; } else
1653
      if (last=='Q') { isexp = true; significance = true; } else
1654
      if ((last=='f') || (last=='F')) { isexp = false; } else
1655
      if (last=='W') { isexp = false; significance = true; } else
1656
      if ((last=='g') || (last=='G')) {
1657
         var se = JSROOT.FFormat(value, fmt+'Q');
1658
         var _fmt = JSROOT.lastFFormat;
1659
         var sg = JSROOT.FFormat(value, fmt+'W');
1660
 
1661
         if (se.length < sg.length) {
1662
            JSROOT.lastFFormat = _fmt;
1663
            return se;
1664
         }
1665
         return sg;
1666
      } else {
1667
         isexp = false;
1668
         prec = 4;
1669
      }
1670
 
1671
      if (isexp) {
1672
         // for exponential representation only one significant digit befor point
1673
         if (significance) prec--;
1674
         if (prec<0) prec = 0;
1675
 
1676
         JSROOT.lastFFormat = '5.'+prec+'e';
1677
 
1678
         return value.toExponential(prec);
1679
      }
1680
 
1681
      var sg = value.toFixed(prec);
1682
 
1683
      if (significance) {
1684
 
1685
         // when using fixed representation, one could get 0.0
1686
         if ((value!=0) && (Number(sg)==0.) && (prec>0)) {
1687
            prec = 20; sg = value.toFixed(prec);
1688
         }
1689
 
1690
         var l = 0;
1691
         while ((l<sg.length) && (sg.charAt(l) == '0' || sg.charAt(l) == '-' || sg.charAt(l) == '.')) l++;
1692
 
1693
         var diff = sg.length - l - prec;
1694
         if (sg.indexOf(".")>l) diff--;
1695
 
1696
         if (diff != 0) {
1697
            prec-=diff;
1698
            if (prec<0) prec = 0; else if (prec>20) prec = 20;
1699
            sg = value.toFixed(prec);
1700
         }
1701
      }
1702
 
1703
      JSROOT.lastFFormat = '5.'+prec+'f';
1704
 
1705
      return sg;
1706
   }
1707
 
1708
   JSROOT.log10 = function(n) {
1709
      return Math.log(n) / Math.log(10);
1710
   }
1711
 
1712
   // dummy function, will be redefined when JSRootPainter is loaded
1713
   JSROOT.progress = function(msg) {
1714
      if ((msg !== undefined) && (typeof msg=="string")) JSROOT.console(msg);
1715
   }
1716
 
1717
   JSROOT.Initialize = function() {
1718
 
1719
      if (JSROOT.source_fullpath.length === 0) return this;
1720
 
1721
      function window_on_load(func) {
1722
         if (func!=null) {
1723
            if (document.attachEvent ? document.readyState === 'complete' : document.readyState !== 'loading')
1724
               func();
1725
            else
1726
               window.onload = func;
1727
         }
1728
         return JSROOT;
1729
      }
1730
 
1731
      var src = JSROOT.source_fullpath;
1732
 
1733
      if (JSROOT.GetUrlOption('gui', src) !== null)
1734
         return window_on_load( function() { JSROOT.BuildSimpleGUI(); } );
1735
 
1736
      if ( typeof define === "function" && define.amd )
1737
         return window_on_load( function() { JSROOT.BuildSimpleGUI('check_existing_elements'); } );
1738
 
1739
      var prereq = "";
1740
      if (JSROOT.GetUrlOption('io', src)!=null) prereq += "io;";
1741
      if (JSROOT.GetUrlOption('2d', src)!=null) prereq += "2d;";
1742
      if (JSROOT.GetUrlOption('jq2d', src)!=null) prereq += "jq2d;";
1743
      if (JSROOT.GetUrlOption('more2d', src)!=null) prereq += "more2d;";
1744
      if (JSROOT.GetUrlOption('geo', src)!=null) prereq += "geo;";
1745
      if (JSROOT.GetUrlOption('3d', src)!=null) prereq += "3d;";
1746
      if (JSROOT.GetUrlOption('math', src)!=null) prereq += "math;";
1747
      if (JSROOT.GetUrlOption('mathjax', src)!=null) prereq += "mathjax;";
1748
      var user = JSROOT.GetUrlOption('load', src);
1749
      if ((user!=null) && (user.length>0)) prereq += "load:" + user;
1750
      var onload = JSROOT.GetUrlOption('onload', src);
1751
      var bower = JSROOT.GetUrlOption('bower', src);
1752
      if (bower!==null) {
1753
         if (bower.length>0) JSROOT.bower_dir = bower; else
1754
            if (JSROOT.source_dir.indexOf("jsroot/") == JSROOT.source_dir.length - 7)
1755
               JSROOT.bower_dir = JSROOT.source_dir.substr(0, JSROOT.source_dir.length - 7);
1756
         if (JSROOT.bower_dir.length > 0) console.log("Set JSROOT.bower_dir to " + JSROOT.bower_dir);
1757
      }
1758
 
1759
      if ((prereq.length>0) || (onload!=null))
1760
         window_on_load(function() {
1761
            if (prereq.length>0) JSROOT.AssertPrerequisites(prereq, onload); else
1762
               if (onload!=null) {
1763
                  onload = JSROOT.findFunction(onload);
1764
                  if (typeof onload == 'function') onload();
1765
               }
1766
         });
1767
 
1768
      return this;
1769
   }
1770
 
1771
   return JSROOT.Initialize();
1772
 
1773
}));
1774
 
1775
/// JSRootCore.js ends
1776