Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

  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.  
  1777.