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 |