00001
00002
00003
00004 (function( factory ) {
00005 if ( typeof define === "function" && define.amd ) {
00006
00007 define( ['jquery', 'jquery-ui', 'd3', 'JSRootPainter'], factory );
00008 } else {
00009
00010 if (typeof jQuery == 'undefined')
00011 throw new Error('jQuery not defined', 'JSRootPainter.jquery.js');
00012
00013 if (typeof jQuery.ui == 'undefined')
00014 throw new Error('jQuery-ui not defined','JSRootPainter.jquery.js');
00015
00016 if (typeof d3 != 'object')
00017 throw new Error('This extension requires d3.v3.js', 'JSRootPainter.jquery.js');
00018
00019 if (typeof JSROOT == 'undefined')
00020 throw new Error('JSROOT is not defined', 'JSRootPainter.jquery.js');
00021
00022 if (typeof JSROOT.Painter != 'object')
00023 throw new Error('JSROOT.Painter not defined', 'JSRootPainter.jquery.js');
00024
00025
00026 factory(jQuery, jQuery.ui, d3, JSROOT);
00027 }
00028 } (function($, myui, d3, JSROOT) {
00029
00030 if ( typeof define === "function" && define.amd )
00031 JSROOT.loadScript('$$$style/jquery-ui.css');
00032
00033 JSROOT.Painter.createMenu = function(maincallback, menuname) {
00034 if (!menuname || (typeof menuname !== 'string')) menuname = 'root_ctx_menu';
00035
00036 var menu = { element: null, code: "", cnt: 1, funcs: {}, separ: false };
00037
00038 menu.add = function(name, arg, func) {
00039 if (name == "separator") { this.code += "<li>-</li>"; this.separ = true; return; }
00040
00041 if (name.indexOf("header:")==0) {
00042 this.code += "<li class='ui-widget-header' style='padding-left:5px'>"+name.substr(7)+"</li>";
00043 return;
00044 }
00045
00046 if (name=="endsub:") { this.code += "</ul></li>"; return; }
00047 var close_tag = "</li>", style = "padding-top:2px;padding-bottom:1px";
00048 if (name.indexOf("sub:")==0) { name = name.substr(4); close_tag="<ul>"; style += ";padding-right:2em"}
00049
00050 if (typeof arg == 'function') { func = arg; arg = name; }
00051
00052
00053
00054 if (name.indexOf("chk:")==0) { name = "<span class='ui-icon ui-icon-check' style='margin:1px'></span>" + name.substr(4); } else
00055 if (name.indexOf("unk:")==0) { name = "<span class='ui-icon ui-icon-blank' style='margin:1px'></span>" + name.substr(4); }
00056
00057
00058 if (($.ui.version.indexOf("1.10")==0) || ($.ui.version.indexOf("1.9")==0))
00059 name = '<a href="#">' + name + '</a>';
00060
00061 this.code += "<li cnt='" + this.cnt + "' arg='" + arg + "' style='" + style + "'>" + name + close_tag;
00062 if (typeof func == 'function') this.funcs[this.cnt] = func;
00063
00064 this.cnt++;
00065 }
00066
00067 menu.addchk = function(flag, name, arg, func) {
00068 return this.add((flag ? "chk:" : "unk:") + name, arg, func);
00069 }
00070
00071 menu.size = function() { return this.cnt-1; }
00072
00073 menu.addDrawMenu = function(menu_name, opts, call_back) {
00074 if (opts==null) opts = new Array;
00075 if (opts.length==0) opts.push("");
00076
00077 this.add((opts.length > 1) ? ("sub:" + menu_name) : menu_name, opts[0], call_back);
00078 if (opts.length<2) return;
00079
00080 for (var i=0;i<opts.length;++i) {
00081 var name = opts[i];
00082 if (name=="") name = '<dflt>';
00083 this.add(name, opts[i], call_back);
00084 }
00085 this.add("endsub:");
00086 }
00087
00088 menu.remove = function() {
00089 if (this.element!==null) {
00090 this.element.remove();
00091 if (this.close_callback) this.close_callback();
00092 document.body.removeEventListener('click', this.remove_bind);
00093 }
00094 this.element = null;
00095 }
00096
00097 menu.remove_bind = menu.remove.bind(menu);
00098
00099 menu.show = function(event, close_callback) {
00100 this.remove();
00101
00102 if (typeof close_callback == 'function') this.close_callback = close_callback;
00103
00104 document.body.addEventListener('click', this.remove_bind);
00105
00106 var oldmenu = document.getElementById(menuname);
00107 if (oldmenu) oldmenu.parentNode.removeChild(oldmenu);
00108
00109 $(document.body).append('<ul class="jsroot_ctxmenu">' + this.code + '</ul>');
00110
00111 this.element = $('.jsroot_ctxmenu');
00112
00113 var pthis = this;
00114
00115 this.element
00116 .attr('id', menuname)
00117 .css('left', event.clientX + window.pageXOffset)
00118 .css('top', event.clientY + window.pageYOffset)
00119 .css('font-size', '80%')
00120 .css('position', 'absolute')
00121 .menu({
00122 items: "> :not(.ui-widget-header)",
00123 select: function( event, ui ) {
00124 var arg = ui.item.attr('arg');
00125 var cnt = ui.item.attr('cnt');
00126 var func = cnt ? pthis.funcs[cnt] : null;
00127 pthis.remove();
00128 if (typeof func == 'function') {
00129 if ('painter' in menu)
00130 func.bind(pthis.painter)(arg);
00131 else
00132 func(arg);
00133 }
00134 }
00135 });
00136
00137 var newx = null, newy = null;
00138
00139 if (event.clientX + this.element.width() > $(window).width()) newx = $(window).width() - this.element.width() - 20;
00140 if (event.clientY + this.element.height() > $(window).height()) newy = $(window).height() - this.element.height() - 20;
00141
00142 if (newx!==null) this.element.css('left', (newx>0 ? newx : 0) + window.pageXOffset);
00143 if (newy!==null) this.element.css('top', (newy>0 ? newy : 0) + window.pageYOffset);
00144 }
00145
00146 JSROOT.CallBack(maincallback, menu);
00147
00148 return menu;
00149 }
00150
00151 JSROOT.HierarchyPainter.prototype.isLastSibling = function(hitem) {
00152 if (!hitem || !hitem._parent || !hitem._parent._childs) return false;
00153 var chlds = hitem._parent._childs;
00154 var indx = chlds.indexOf(hitem);
00155 if (indx<0) return false;
00156 while (++indx < chlds.length)
00157 if (!('_hidden' in chlds[indx])) return false;
00158 return true;
00159 }
00160
00161 JSROOT.HierarchyPainter.prototype.addItemHtml = function(hitem, d3prnt, doupdate) {
00162 var isroot = !('_parent' in hitem);
00163 var has_childs = '_childs' in hitem;
00164
00165 if ('_hidden' in hitem) return;
00166
00167 var handle = JSROOT.getDrawHandle(hitem._kind),
00168 img1 = "", img2 = "", can_click = false;
00169
00170 if (handle !== null) {
00171 if ('icon' in handle) img1 = handle.icon;
00172 if ('icon2' in handle) img2 = handle.icon2;
00173 if (('func' in handle) || ('execute' in handle) || ('aslink' in handle) ||
00174 (('expand' in handle) && (hitem._more !== false))) can_click = true;
00175 }
00176
00177 if ('_icon' in hitem) img1 = hitem._icon;
00178 if ('_icon2' in hitem) img2 = hitem._icon2;
00179 if ((img1.length==0) && ('_online' in hitem))
00180 hitem._icon = img1 = "img_globe";
00181 if ((img1.length==0) && isroot)
00182 hitem._icon = img1 = "img_base";
00183
00184 if (hitem._more || ('_expand' in hitem) || ('_player' in hitem))
00185 can_click = true;
00186
00187 var can_menu = can_click;
00188 if (!can_menu && (typeof hitem._kind == 'string') && (hitem._kind.indexOf("ROOT.")==0)) {
00189 can_menu = true;
00190 can_click = true;
00191 }
00192
00193 if (img2.length==0) img2 = img1;
00194 if (img1.length==0) img1 = (has_childs || hitem._more) ? "img_folder" : "img_page";
00195 if (img2.length==0) img2 = (has_childs || hitem._more) ? "img_folderopen" : "img_page";
00196
00197 var itemname = this.itemFullName(hitem);
00198
00199 var d3cont;
00200
00201 if (doupdate) {
00202 d3prnt.selectAll("*").remove();
00203 d3cont = d3prnt;
00204 } else {
00205 d3cont = d3prnt.append("div");
00206 }
00207
00208 d3cont.attr("item", itemname);
00209
00210
00211 var prnt = isroot ? null : hitem._parent;
00212 while ((prnt != null) && (prnt != this.h)) {
00213 d3cont.insert("div",":first-child")
00214 .attr("class", this.isLastSibling(prnt) ? "img_empty" : "img_line");
00215 prnt = prnt._parent;
00216 }
00217
00218 var icon_class = "", plusminus = false;
00219
00220 if (isroot) {
00221
00222 } else
00223 if (has_childs) {
00224 icon_class = hitem._isopen ? "img_minus" : "img_plus";
00225 plusminus = true;
00226 } else
00227
00228
00229
00230 {
00231 icon_class = "img_join";
00232 }
00233
00234 var h = this;
00235
00236 if (icon_class.length > 0) {
00237 if (this.isLastSibling(hitem)) icon_class+="bottom";
00238 var d3icon = d3cont.append("div").attr('class', icon_class);
00239 if (plusminus) d3icon.style('cursor','pointer')
00240 .on("click", function() { h.tree_click(this, "plusminus"); });
00241 }
00242
00243
00244
00245 if (this.with_icons) {
00246 var icon_name = hitem._isopen ? img2 : img1;
00247 var title = hitem._kind ? hitem._kind.replace(/</g,'<').replace(/>/g,'>') : "";
00248
00249 var d3img = null;
00250
00251 if (icon_name.indexOf("img_")==0) {
00252 d3img = d3cont.append("div")
00253 .attr("class", icon_name)
00254 .attr("title", title);
00255 } else {
00256 d3img = d3cont.append("img")
00257 .attr("src", icon_name)
00258 .attr("alt","")
00259 .attr("title",title)
00260 .style('vertical-align','top')
00261 .style('width','18px')
00262 .style('height','18px');
00263 }
00264
00265 if ('_icon_click' in hitem)
00266 d3img.on("click", function() { h.tree_click(this, "icon"); });
00267 }
00268
00269 var d3a = d3cont.append("a");
00270 if (can_click || has_childs)
00271 d3a.attr("class","h_item")
00272 .on("click", function() { h.tree_click(this); });
00273
00274 if ('disp_kind' in h) {
00275 if (JSROOT.gStyle.DragAndDrop && can_click)
00276 this.enable_dragging(d3a.node(), itemname);
00277 if (JSROOT.gStyle.ContextMenu && can_menu)
00278 d3a.on('contextmenu', function() { h.tree_contextmenu(this); });
00279 }
00280
00281 var element_name = hitem._name;
00282
00283 if ('_realname' in hitem)
00284 element_name = hitem._realname;
00285
00286 var element_title = "";
00287 if ('_title' in hitem) element_title = hitem._title;
00288
00289 if ('_fullname' in hitem)
00290 element_title += " fullname: " + hitem._fullname;
00291
00292 if (element_title.length === 0)
00293 element_title = element_name;
00294
00295 d3a.attr('title', element_title)
00296 .text(element_name + ('_value' in hitem ? ":" : ""));
00297
00298 if ('_value' in hitem) {
00299 var d3p = d3cont.append("p");
00300 if ('_vclass' in hitem) d3p.attr('class', hitem._vclass);
00301 if (!hitem._isopen) d3p.html(hitem._value);
00302 }
00303
00304 if (has_childs && (isroot || hitem._isopen)) {
00305 var d3chlds = d3cont.append("div").attr("class", "h_childs");
00306 for (var i=0; i< hitem._childs.length;++i) {
00307 var chld = hitem._childs[i];
00308 chld._parent = hitem;
00309 this.addItemHtml(chld, d3chlds);
00310 }
00311 }
00312 }
00313
00314 JSROOT.HierarchyPainter.prototype.RefreshHtml = function(callback) {
00315
00316 if (this.divid == null) return JSROOT.CallBack(callback);
00317 var d3elem = this.select_main();
00318
00319 d3elem.html("");
00320
00321 if ((this.h == null) || d3elem.empty())
00322 return JSROOT.CallBack(callback);
00323
00324 var h = this, factcmds = [], status_item = null;
00325 this.ForEach(function(item) {
00326 if (('_fastcmd' in item) && (item._kind == 'Command')) factcmds.push(item);
00327 if (('_status' in item) && (status_item==null)) status_item = item;
00328 });
00329
00330 var maindiv =
00331 d3elem.append("div")
00332 .attr("class", "jsroot")
00333 .style("background-color", this.background ? this.background : "")
00334 .style('overflow', 'auto')
00335 .style('width', '100%')
00336 .style('height', '100%')
00337 .style('font-size', this.with_icons ? "12px" : "15px");
00338
00339 for (var n=0;n<factcmds.length;++n) {
00340 var btn =
00341 maindiv.append("button")
00342 .text("")
00343 .attr("class",'fast_command')
00344 .attr("item", this.itemFullName(factcmds[n]))
00345 .attr("title", factcmds[n]._title)
00346 .on("click", function() { h.ExecuteCommand(d3.select(this).attr("item"), this); } );
00347
00348
00349 if ('_icon' in factcmds[n])
00350 btn.append('img').attr("src", factcmds[n]._icon);
00351 }
00352
00353 d3p = maindiv.append("p");
00354
00355 d3p.append("a").attr("href", '#').text("open all").on("click", function() { h.toggle(true); d3.event.preventDefault(); });
00356 d3p.append("text").text(" | ");
00357 d3p.append("a").attr("href", '#').text("close all").on("click", function() { h.toggle(false); d3.event.preventDefault(); });
00358
00359 if ('_online' in this.h) {
00360 d3p.append("text").text(" | ");
00361 d3p.append("a").attr("href", '#').text("reload").on("click", function() { h.reload(); d3.event.preventDefault(); });
00362 }
00363
00364 if ('disp_kind' in this) {
00365 d3p.append("text").text(" | ");
00366 d3p.append("a").attr("href", '#').text("clear").on("click", function() { h.clear(false); d3.event.preventDefault(); });
00367 }
00368
00369 this.addItemHtml(this.h, maindiv.append("div").attr("class","h_tree"));
00370
00371 if ((status_item!=null) && (JSROOT.GetUrlOption('nostatus')==null)) {
00372 var func = JSROOT.findFunction(status_item._status);
00373 var hdiv = (typeof func == 'function') ? JSROOT.Painter.ConfigureHSeparator(30) : null;
00374 if (hdiv != null)
00375 func(hdiv, this.itemFullName(status_item));
00376 }
00377
00378 JSROOT.CallBack(callback);
00379 }
00380
00381 JSROOT.HierarchyPainter.prototype.UpdateTreeNode = function(hitem, d3cont) {
00382 if ((d3cont===undefined) || d3cont.empty()) {
00383 var name = this.itemFullName(hitem);
00384 d3cont = this.select_main().select("[item='" + name + "']");
00385
00386 if (d3cont.empty() && ('_cycle' in hitem))
00387 d3cont = this.select_main().select("[item='" + name + ";" + hitem._cycle + "']");
00388 if (d3cont.empty()) return;
00389 }
00390
00391 this.addItemHtml(hitem, d3cont, true);
00392 }
00393
00394 JSROOT.HierarchyPainter.prototype.tree_click = function(node, place) {
00395 if (node===null) return;
00396 var d3cont = d3.select(node.parentNode);
00397 var itemname = d3cont.attr('item');
00398 if (itemname == null) return;
00399
00400 var hitem = this.Find(itemname);
00401 if (hitem == null) return;
00402
00403 var prnt = hitem, dflt = undefined;
00404 while (prnt) {
00405 if ((dflt = prnt._click_action) !== undefined) break;
00406 prnt = prnt._parent;
00407 }
00408
00409 if (!place || (place=="")) place = "item";
00410
00411 if (place == "icon") {
00412 if (('_icon_click' in hitem) && (typeof hitem._icon_click == 'function'))
00413 if (hitem._icon_click(hitem))
00414 this.UpdateTreeNode(hitem, d3cont);
00415 return;
00416 }
00417
00418
00419 if ((place=="item") && ('_expand' in hitem)) place = "plusminus";
00420
00421
00422 if (((place == "plusminus") && !('_childs' in hitem) && hitem._more) ||
00423 ((place == "item") && (dflt === "expand")))
00424 return this.expand(itemname, null, d3cont);
00425
00426 if (place == "item") {
00427 if ('_player' in hitem)
00428 return this.player(itemname);
00429
00430 var handle = JSROOT.getDrawHandle(hitem._kind);
00431
00432 if (handle != null) {
00433 if ('aslink' in handle)
00434 return window.open(itemname + "/");
00435
00436 if ('func' in handle)
00437 return this.display(itemname);
00438
00439 if ('execute' in handle)
00440 return this.ExecuteCommand(itemname, node.parentNode);
00441
00442 if (('expand' in handle) && (hitem._childs == null))
00443 return this.expand(itemname, null, d3cont);
00444 }
00445
00446 if (!hitem._childs && (this.default_by_click === "expand"))
00447 return this.expand(itemname, null, d3cont);
00448
00449
00450 if ((typeof hitem._kind === "string") && (hitem._kind.indexOf("ROOT.")===0))
00451 return this.display(itemname, "inspect");
00452
00453 if (!hitem._childs || (hitem === this.h)) return;
00454 }
00455
00456 if (hitem._isopen)
00457 delete hitem._isopen;
00458 else
00459 hitem._isopen = true;
00460
00461 this.UpdateTreeNode(hitem, d3cont);
00462 }
00463
00464 JSROOT.HierarchyPainter.prototype.tree_contextmenu = function(elem) {
00465 d3.event.preventDefault();
00466
00467 var itemname = d3.select(elem.parentNode).attr('item');
00468
00469 var hitem = this.Find(itemname);
00470 if (hitem==null) return;
00471
00472 var painter = this;
00473
00474 var onlineprop = painter.GetOnlineProp(itemname);
00475 var fileprop = painter.GetFileProp(itemname);
00476
00477 function qualifyURL(url) {
00478 function escapeHTML(s) {
00479 return s.split('&').join('&').split('<').join('<').split('"').join('"');
00480 }
00481 var el = document.createElement('div');
00482 el.innerHTML = '<a href="' + escapeHTML(url) + '">x</a>';
00483 return el.firstChild.href;
00484 }
00485
00486 JSROOT.Painter.createMenu(function(menu) {
00487
00488 menu['painter'] = painter;
00489
00490 if ((itemname == "") && !('_jsonfile' in hitem)) {
00491 var addr = "", cnt = 0;
00492 function separ() { return cnt++ > 0 ? "&" : "?"; }
00493
00494 var files = [];
00495 painter.ForEachRootFile(function(item) { files.push(item._file.fFullURL); });
00496
00497 if (painter.GetTopOnlineItem()==null)
00498 addr = JSROOT.source_dir + "index.htm";
00499
00500 if (painter.IsMonitoring())
00501 addr += separ() + "monitoring=" + painter.MonitoringInterval();
00502
00503 if (files.length==1)
00504 addr += separ() + "file=" + files[0];
00505 else
00506 if (files.length>1)
00507 addr += separ() + "files=" + JSON.stringify(files);
00508
00509 if (painter['disp_kind'])
00510 addr += separ() + "layout=" + painter.disp_kind.replace(/ /g, "");
00511
00512 var items = [];
00513
00514 if (painter['disp'] != null)
00515 painter['disp'].ForEachPainter(function(p) {
00516 if (p.GetItemName()!=null)
00517 items.push(p.GetItemName());
00518 });
00519
00520 if (items.length == 1) {
00521 addr += separ() + "item=" + items[0];
00522 } else if (items.length > 1) {
00523 addr += separ() + "items=" + JSON.stringify(items);
00524 }
00525
00526 menu.add("Direct link", function() { window.open(addr); });
00527 menu.add("Only items", function() { window.open(addr + "&nobrowser"); });
00528 } else
00529 if (onlineprop != null) {
00530 painter.FillOnlineMenu(menu, onlineprop, itemname);
00531 } else {
00532 var opts = JSROOT.getDrawOptions(hitem._kind, 'nosame');
00533
00534 if (opts!=null)
00535 menu.addDrawMenu("Draw", opts, function(arg) { this.display(itemname, arg); });
00536
00537 if ((fileprop!=null) && (opts!=null)) {
00538 var filepath = qualifyURL(fileprop.fileurl);
00539 if (filepath.indexOf(JSROOT.source_dir) == 0)
00540 filepath = filepath.slice(JSROOT.source_dir.length);
00541 menu.addDrawMenu("Draw in new window", opts, function(arg) {
00542 window.open(JSROOT.source_dir + "index.htm?nobrowser&file=" + filepath + "&item=" + fileprop.itemname+"&opt="+arg);
00543 });
00544 }
00545
00546 if (!('_childs' in hitem) && (hitem._more || !('_more' in hitem)))
00547 menu.add("Expand", function() { painter.expand(itemname); });
00548 }
00549
00550 if (('_menu' in hitem) && (typeof hitem['_menu'] == 'function'))
00551 hitem['_menu'](menu, hitem, painter);
00552
00553 if (menu.size() > 0) {
00554 menu.tree_node = elem.parentNode;
00555 if (menu.separ) menu.add("separator");
00556 menu.add("Close");
00557 menu.show(d3.event);
00558 }
00559
00560 });
00561
00562 return false;
00563 }
00564
00565 JSROOT.HierarchyPainter.prototype.CreateDisplay = function(callback) {
00566 if ('disp' in this) {
00567 if (this.disp.NumDraw() > 0) return JSROOT.CallBack(callback, this.disp);
00568 this.disp.Reset();
00569 delete this.disp;
00570 }
00571
00572
00573 if (document.getElementById(this.disp_frameid) == null)
00574 return JSROOT.CallBack(callback, null);
00575
00576 if (this.disp_kind == "tabs")
00577 this.disp = new JSROOT.TabsDisplay(this.disp_frameid);
00578 else
00579 if ((this.disp_kind == "flex") || (this.disp_kind == "flexible"))
00580 this.disp = new JSROOT.FlexibleDisplay(this.disp_frameid);
00581 else
00582 if (this.disp_kind.search("grid") == 0)
00583 this.disp = new JSROOT.GridDisplay(this.disp_frameid, this.disp_kind);
00584 else
00585 if (this.disp_kind == "simple")
00586 this.disp = new JSROOT.SimpleDisplay(this.disp_frameid);
00587 else
00588 this.disp = new JSROOT.CollapsibleDisplay(this.disp_frameid);
00589
00590 JSROOT.CallBack(callback, this.disp);
00591 }
00592
00593 JSROOT.HierarchyPainter.prototype.enable_dragging = function(element, itemname) {
00594 $(element).draggable({ revert: "invalid", appendTo: "body", helper: "clone" });
00595 }
00596
00597 JSROOT.HierarchyPainter.prototype.enable_dropping = function(frame, itemname) {
00598 var h = this;
00599 $(frame).droppable({
00600 hoverClass : "ui-state-active",
00601 accept: function(ui) {
00602 var dropname = ui.parent().attr('item');
00603 if ((dropname == itemname) || (dropname==null)) return false;
00604
00605 var ditem = h.Find(dropname);
00606 if ((ditem==null) || (!('_kind' in ditem))) return false;
00607
00608 return ditem._kind.indexOf("ROOT.")==0;
00609 },
00610 drop: function(event, ui) {
00611 var dropname = ui.draggable.parent().attr('item');
00612 if (dropname==null) return false;
00613 return h.dropitem(dropname, $(this).attr("id"));
00614 }
00615 });
00616 }
00617
00618
00619
00620 JSROOT.CollapsibleDisplay = function(frameid) {
00621 JSROOT.MDIDisplay.call(this, frameid);
00622 this.cnt = 0;
00623 }
00624
00625 JSROOT.CollapsibleDisplay.prototype = Object.create(JSROOT.MDIDisplay.prototype);
00626
00627 JSROOT.CollapsibleDisplay.prototype.ForEachFrame = function(userfunc, only_visible) {
00628 var topid = this.frameid + '_collapsible';
00629
00630 if (document.getElementById(topid) == null) return;
00631
00632 if (typeof userfunc != 'function') return;
00633
00634 $('#' + topid + ' .collapsible_draw').each(function() {
00635
00636
00637 if (only_visible && $(this).is(":hidden")) return;
00638
00639 userfunc($(this).get(0));
00640 });
00641 }
00642
00643 JSROOT.CollapsibleDisplay.prototype.ActivateFrame = function(frame) {
00644 if ($(frame).is(":hidden")) {
00645 $(frame).prev().toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom")
00646 .find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s").end()
00647 .next().toggleClass("ui-accordion-content-active").slideDown(0);
00648 }
00649 $(frame).prev()[0].scrollIntoView();
00650 }
00651
00652 JSROOT.CollapsibleDisplay.prototype.CreateFrame = function(title) {
00653
00654 var topid = this.frameid + '_collapsible';
00655
00656 if (document.getElementById(topid) == null)
00657 $("#"+this.frameid).append('<div id="'+ topid + '" class="jsroot ui-accordion ui-accordion-icons ui-widget ui-helper-reset" style="overflow:auto; overflow-y:scroll; height:100%; padding-left: 2px; padding-right: 2px"></div>');
00658
00659 var hid = topid + "_sub" + this.cnt++;
00660 var uid = hid + "h";
00661
00662 var entryInfo = "<h5 id=\"" + uid + "\">" +
00663 "<span class='ui-icon ui-icon-triangle-1-e'></span>" +
00664 "<a> " + title + "</a> " +
00665 "<button type='button' class='jsroot_collaps_closebtn' style='float:right; width:1.4em' title='close canvas'/>" +
00666 " </h5>\n";
00667 entryInfo += "<div class='collapsible_draw' id='" + hid + "'></div>\n";
00668 $("#" + topid).append(entryInfo);
00669
00670 $('#' + uid)
00671 .addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-top ui-corner-bottom")
00672 .hover(function() { $(this).toggleClass("ui-state-hover"); })
00673 .click( function() {
00674 $(this).toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom")
00675 .find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s")
00676 .end().next().toggleClass("ui-accordion-content-active").slideToggle(0);
00677 JSROOT.resize($(this).next().attr('id'));
00678 return false;
00679 })
00680 .next()
00681 .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom")
00682 .hide();
00683
00684 $('#' + uid).find(" .jsroot_collaps_closebtn")
00685 .button({ icons: { primary: "ui-icon-close" }, text: false })
00686 .click(function(){
00687 JSROOT.cleanup($(this).parent().next().attr('id'));
00688 $(this).parent().next().andSelf().remove();
00689 });
00690
00691 $('#' + uid)
00692 .toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom")
00693 .find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s").end().next()
00694 .toggleClass("ui-accordion-content-active").slideToggle(0);
00695
00696 return $("#" + hid).attr('frame_title', title).css('overflow','hidden').get(0);
00697 }
00698
00699
00700
00701 JSROOT.TabsDisplay = function(frameid) {
00702 JSROOT.MDIDisplay.call(this, frameid);
00703 this.cnt = 0;
00704 }
00705
00706 JSROOT.TabsDisplay.prototype = Object.create(JSROOT.MDIDisplay.prototype);
00707
00708 JSROOT.TabsDisplay.prototype.ForEachFrame = function(userfunc, only_visible) {
00709 var topid = this.frameid + '_tabs';
00710
00711 if (document.getElementById(topid) == null) return;
00712
00713 if (typeof userfunc != 'function') return;
00714
00715 var cnt = -1;
00716 var active = $('#' + topid).tabs("option", "active");
00717
00718 $('#' + topid + '> .tabs_draw').each(function() {
00719 cnt++;
00720 if (!only_visible || (cnt == active))
00721 userfunc($(this).get(0));
00722 });
00723 }
00724
00725 JSROOT.TabsDisplay.prototype.ActivateFrame = function(frame) {
00726 var cnt = 0, id = -1;
00727 this.ForEachFrame(function(fr) {
00728 if ($(fr).attr('id') == $(frame).attr('id')) id = cnt;
00729 cnt++;
00730 });
00731 $('#' + this.frameid + "_tabs").tabs("option", "active", id);
00732 }
00733
00734 JSROOT.TabsDisplay.prototype.CreateFrame = function(title) {
00735 var topid = this.frameid + '_tabs';
00736
00737 var hid = topid + "_sub" + this.cnt++;
00738
00739 var li = '<li><a href="#' + hid + '">' + title
00740 + '</a><span class="ui-icon ui-icon-close" style="float: left; margin: 0.4em 0.2em 0 0; cursor: pointer;" role="presentation">Remove Tab</span></li>';
00741 var cont = '<div class="tabs_draw" id="' + hid + '"></div>';
00742
00743 if (document.getElementById(topid) == null) {
00744 $("#" + this.frameid).append('<div id="' + topid + '" class="jsroot">' + ' <ul>' + li + ' </ul>' + cont + '</div>');
00745
00746 var tabs = $("#" + topid)
00747 .css('overflow','hidden')
00748 .tabs({
00749 heightStyle : "fill",
00750 activate : function (event,ui) {
00751 $(ui.newPanel).css('overflow', 'hidden');
00752 JSROOT.resize($(ui.newPanel).attr('id'));
00753 }
00754 });
00755
00756 tabs.delegate("span.ui-icon-close", "click", function() {
00757 var panelId = $(this).closest("li").remove().attr("aria-controls");
00758 JSROOT.cleanup(panelId);
00759 $("#" + panelId).remove();
00760 tabs.tabs("refresh");
00761 if ($('#' + topid + '> .tabs_draw').length == 0)
00762 $("#" + topid).remove();
00763
00764 });
00765 } else {
00766 $("#" + topid).find("> .ui-tabs-nav").append(li);
00767 $("#" + topid).append(cont);
00768 $("#" + topid).tabs("refresh");
00769 $("#" + topid).tabs("option", "active", -1);
00770 }
00771 $('#' + hid)
00772 .empty()
00773 .css('overflow', 'hidden')
00774 .attr('frame_title', title);
00775
00776 return $('#' + hid).get(0);
00777 }
00778
00779
00780
00781 JSROOT.FlexibleDisplay = function(frameid) {
00782 JSROOT.MDIDisplay.call(this, frameid);
00783 this.cnt = 0;
00784 }
00785
00786 JSROOT.FlexibleDisplay.prototype = Object.create(JSROOT.MDIDisplay.prototype);
00787
00788 JSROOT.FlexibleDisplay.prototype.ForEachFrame = function(userfunc, only_visible) {
00789 var topid = this.frameid + '_flex';
00790
00791 if (document.getElementById(topid) == null) return;
00792 if (typeof userfunc != 'function') return;
00793
00794 $('#' + topid + ' .flex_draw').each(function() {
00795
00796
00797
00798 userfunc($(this).get(0));
00799 });
00800 }
00801
00802 JSROOT.FlexibleDisplay.prototype.ActivateFrame = function(frame) {
00803 }
00804
00805 JSROOT.FlexibleDisplay.prototype.CreateFrame = function(title) {
00806 var topid = this.frameid + '_flex';
00807
00808 if (document.getElementById(topid) == null)
00809 $("#" + this.frameid).append('<div id="'+ topid + '" class="jsroot" style="overflow:none; height:100%; width:100%"></div>');
00810
00811 var top = $("#" + topid);
00812
00813 var w = top.width(), h = top.height();
00814
00815 var subid = topid + "_frame" + this.cnt;
00816
00817 var entry ='<div id="' + subid + '" class="flex_frame" style="position:absolute">' +
00818 '<div class="ui-widget-header flex_header">'+
00819 '<p>'+title+'</p>' +
00820 '<button type="button" style="float:right; width:1.4em"/>' +
00821 '<button type="button" style="float:right; width:1.4em"/>' +
00822 '<button type="button" style="float:right; width:1.4em"/>' +
00823 '</div>' +
00824 '<div id="' + subid + '_cont" class="flex_draw"></div>' +
00825 '</div>';
00826
00827 top.append(entry);
00828
00829 function ChangeWindowState(main, state) {
00830 var curr = main.prop('state');
00831 if (!curr) curr = "normal";
00832 main.prop('state', state);
00833 if (state==curr) return;
00834
00835 if (curr == "normal") {
00836 main.prop('original_height', main.height());
00837 main.prop('original_width', main.width());
00838 main.prop('original_top', main.css('top'));
00839 main.prop('original_left', main.css('left'));
00840 }
00841
00842 main.find(".jsroot_minbutton").find('.ui-icon')
00843 .toggleClass("ui-icon-carat-1-s", state!="minimal")
00844 .toggleClass("ui-icon-carat-2-n-s", state=="minimal");
00845
00846 main.find(".jsroot_maxbutton").find('.ui-icon')
00847 .toggleClass("ui-icon-carat-1-n", state!="maximal")
00848 .toggleClass("ui-icon-carat-2-n-s", state=="maximal");
00849
00850 switch (state) {
00851 case "minimal" :
00852 main.height(main.find('.flex_header').height()).width("auto");
00853 main.find(".flex_draw").css("display","none");
00854 main.find(".ui-resizable-handle").css("display","none");
00855 break;
00856 case "maximal" :
00857 main.height("100%").width("100%").css('left','').css('top','');
00858 main.find(".flex_draw").css("display","");
00859 main.find(".ui-resizable-handle").css("display","none");
00860 break;
00861 default:
00862 main.find(".flex_draw").css("display","");
00863 main.find(".ui-resizable-handle").css("display","");
00864 main.height(main.prop('original_height'))
00865 .width(main.prop('original_width'));
00866 if (curr!="minimal")
00867 main.css('left', main.prop('original_left'))
00868 .css('top', main.prop('original_top'));
00869 }
00870
00871 if (state !== "minimal")
00872 JSROOT.resize(main.find(".flex_draw").get(0));
00873 }
00874
00875 $("#" + subid)
00876 .css('left', parseInt(w * (this.cnt % 5)/10))
00877 .css('top', parseInt(h * (this.cnt % 5)/10))
00878 .width(Math.round(w * 0.58))
00879 .height(Math.round(h * 0.58))
00880 .resizable({
00881 helper: "jsroot-flex-resizable-helper",
00882 start: function(event, ui) {
00883
00884 $(this).appendTo($(this).parent());
00885 },
00886 stop: function(event, ui) {
00887 var rect = { width : ui.size.width-1, height : ui.size.height - $(this).find(".flex_header").height()-1 };
00888 JSROOT.resize($(this).find(".flex_draw").get(0), rect);
00889 }
00890 })
00891 .draggable({
00892 containment: "parent",
00893 start: function(event, ui) {
00894
00895 $(this).appendTo($(this).parent());
00896 var ddd = $(this).find(".flex_draw");
00897
00898 if (ddd.prop('flex_block_drag') === true) {
00899
00900 var elementMouseIsOver = document.elementFromPoint(event.clientX, event.clientY);
00901 var isparent = false;
00902 $(elementMouseIsOver).parents().map(function() { if ($(this).get(0) === ddd.get(0)) isparent = true; });
00903 if (isparent) return false;
00904 }
00905 }
00906 })
00907 .find('.flex_header')
00908
00909 .click(function() {
00910 var div = $(this).parent();
00911 div.appendTo(div.parent());
00912 })
00913 .find("button")
00914 .first()
00915 .attr('title','close canvas')
00916 .button({ icons: { primary: "ui-icon-close" }, text: false })
00917 .click(function() {
00918 var main = $(this).parent().parent();
00919 JSROOT.cleanup(main.find(".flex_draw").get(0));
00920 main.remove();
00921 })
00922 .next()
00923 .attr('title','maximize canvas')
00924 .addClass('jsroot_maxbutton')
00925 .button({ icons: { primary: "ui-icon-carat-1-n" }, text: false })
00926 .click(function() {
00927 var main = $(this).parent().parent();
00928 var maximize = $(this).find('.ui-icon').hasClass("ui-icon-carat-1-n");
00929 ChangeWindowState(main, maximize ? "maximal" : "normal");
00930 })
00931 .next()
00932 .attr('title','minimize canvas')
00933 .addClass('jsroot_minbutton')
00934 .button({ icons: { primary: "ui-icon-carat-1-s" }, text: false })
00935 .click(function() {
00936 var main = $(this).parent().parent();
00937 var minimize = $(this).find('.ui-icon').hasClass("ui-icon-carat-1-s");
00938 ChangeWindowState(main, minimize ? "minimal" : "normal");
00939 });
00940
00941
00942 $("#" + subid).find(".ui-resizable-handle").css('z-index', '');
00943
00944
00945
00946
00947 this.cnt++;
00948
00949 return $("#" + subid + "_cont").attr('frame_title', title).get(0);
00950 }
00951
00952
00953
00954 JSROOT.TTreePlayer = function(itemname, url, askey, root_version) {
00955 JSROOT.TBasePainter.call(this);
00956 this.SetItemName(itemname);
00957 this.url = url;
00958 this.root_version = root_version;
00959 this.hist_painter = null;
00960 this.askey = askey;
00961 return this;
00962 }
00963
00964 JSROOT.TTreePlayer.prototype = Object.create( JSROOT.TBasePainter.prototype );
00965
00966 JSROOT.TTreePlayer.prototype.Show = function(divid) {
00967 this.drawid = divid + "_draw";
00968
00969 $("#" + divid)
00970 .html("<div class='treedraw_buttons' style='padding-left:0.5em'>" +
00971 "<button class='treedraw_exe'>Draw</button>" +
00972 " Expr:<input class='treedraw_varexp' style='width:12em'></input> " +
00973 "<button class='treedraw_more'>More</button>" +
00974 "</div>" +
00975 "<div id='" + this.drawid + "' style='width:100%'></div>");
00976
00977 var player = this;
00978
00979 $("#" + divid).find('.treedraw_exe').click(function() { player.PerformDraw(); });
00980 $("#" + divid).find('.treedraw_varexp')
00981 .val("px:py")
00982 .keyup(function(e){
00983 if(e.keyCode == 13) player.PerformDraw();
00984 });
00985
00986 $("#" + divid).find('.treedraw_more').click(function() {
00987 $(this).remove();
00988 $("#" + divid).find(".treedraw_buttons")
00989 .append(" Cut:<input class='treedraw_cut' style='width:8em'></input>"+
00990 " Opt:<input class='treedraw_opt' style='width:5em'></input>"+
00991 " Num:<input class='treedraw_number' style='width:7em'></input>" +
00992 " First:<input class='treedraw_first' style='width:7em'></input>");
00993
00994 $("#" + divid +" .treedraw_opt").val("");
00995 $("#" + divid +" .treedraw_number").val("").spinner({ numberFormat: "n", min: 0, page: 1000});
00996 $("#" + divid +" .treedraw_first").val("").spinner({ numberFormat: "n", min: 0, page: 1000});
00997 });
00998
00999 this.CheckResize();
01000
01001 this.SetDivId(divid);
01002 }
01003
01004 JSROOT.TTreePlayer.prototype.PerformDraw = function() {
01005
01006 var frame = $(this.select_main().node());
01007
01008 var url = this.url + '/exe.json.gz?compact=3&method=Draw';
01009 var expr = frame.find('.treedraw_varexp').val();
01010 var hname = "h_tree_draw";
01011
01012 var pos = expr.indexOf(">>");
01013 if (pos<0) {
01014 expr += ">>" + hname;
01015 } else {
01016 hname = expr.substr(pos+2);
01017 if (hname[0]=='+') hname = hname.substr(1);
01018 var pos2 = hname.indexOf("(");
01019 if (pos2>0) hname = hname.substr(0, pos2);
01020 }
01021
01022 if (frame.find('.treedraw_more').length==0) {
01023 var cut = frame.find('.treedraw_cut').val();
01024 var option = frame.find('.treedraw_opt').val();
01025 var nentries = frame.find('.treedraw_number').val();
01026 var firstentry = frame.find('.treedraw_first').val();
01027
01028 url += '&prototype="const char*,const char*,Option_t*,Long64_t,Long64_t"&varexp="' + expr + '"&selection="' + cut + '"';
01029
01030
01031 if ((option!="") || (nentries!="") || (firstentry!="")) {
01032 if (nentries=="") nentries = (this.root_version >= 394499) ? "TTree::kMaxEntries": "1000000000";
01033 if (firstentry=="") firstentry = "0";
01034 url += '&option="' + option + '"&nentries=' + nentries + '&firstentry=' + firstentry;
01035 }
01036 } else {
01037 url += '&prototype="Option_t*"&opt="' + expr + '"';
01038 }
01039 url += '&_ret_object_=' + hname;
01040
01041 var player = this;
01042
01043 function SubmitDrawRequest() {
01044 JSROOT.NewHttpRequest(url, 'object', function(res) {
01045 if (res==null) return;
01046 $("#"+player.drawid).empty();
01047 player.hist_painter = JSROOT.draw(player.drawid, res)
01048 }).send();
01049 }
01050
01051 if (this.askey) {
01052
01053 this.askey = false;
01054 JSROOT.NewHttpRequest(this.url + "/root.json", 'text', SubmitDrawRequest).send();
01055 } else SubmitDrawRequest();
01056 }
01057
01058 JSROOT.TTreePlayer.prototype.CheckResize = function(force) {
01059 var main = $(this.select_main().node());
01060
01061 $("#" + this.drawid).width(main.width());
01062 var h = main.height();
01063 var h0 = main.find(".treedraw_buttons").height();
01064 if (h>h0+30) $("#" + this.drawid).height(h - 1 - h0);
01065
01066 if (this.hist_painter) {
01067 this.hist_painter.CheckResize(force);
01068 }
01069 }
01070
01071 JSROOT.drawTreePlayer = function(hpainter, itemname, askey) {
01072
01073 var url = hpainter.GetOnlineItemUrl(itemname);
01074 if (url == null) return null;
01075
01076 var top = hpainter.GetTopOnlineItem(hpainter.Find(itemname));
01077 if (top == null) return null;
01078 var root_version = ('_root_version' in top) ? top._root_version : 336417;
01079
01080 var mdi = hpainter.GetDisplay();
01081 if (mdi == null) return null;
01082
01083 var frame = mdi.FindFrame(itemname, true);
01084 if (frame==null) return null;
01085
01086 var divid = d3.select(frame).attr('id');
01087
01088 var player = new JSROOT.TTreePlayer(itemname, url, askey, root_version);
01089 player.Show(divid);
01090 return player;
01091 }
01092
01093 JSROOT.drawTreePlayerKey = function(hpainter, itemname) {
01094
01095
01096 return JSROOT.drawTreePlayer(hpainter, itemname, true);
01097 }
01098
01099
01100
01101
01102 JSROOT.Painter.separ = null;
01103
01104 JSROOT.Painter.AdjustLayout = function(left, height, firsttime) {
01105 if (this.separ == null) return;
01106
01107 if (left!=null) {
01108 var wdiff = $("#"+this.separ.left).outerWidth() - $("#"+this.separ.left).width();
01109 var w = 5;
01110 $("#"+this.separ.vertical).css('left', left + "px").width(w).css('top','1px');
01111 $("#"+this.separ.left).width(left-wdiff-1).css('top','1px');
01112 $("#"+this.separ.right).css('left',left+w+"px").css('top','1px');
01113 if (!this.separ.horizontal) {
01114 $("#"+this.separ.vertical).css('bottom', '1px');
01115 $("#"+this.separ.left).css('bottom', '1px');
01116 $("#"+this.separ.right).css('bottom', '1px');
01117 }
01118 }
01119
01120 if ((height!=null) && this.separ.horizontal) {
01121 var diff = $("#"+this.separ.bottom).outerHeight() - $("#"+this.separ.bottom).height();
01122 height -= 2*diff;
01123 if (height<5) height = 5;
01124 var bot = height + diff;
01125 $('#'+this.separ.bottom).height(height);
01126 var h = 5;
01127 $("#"+this.separ.horizontal).css('bottom', bot + 'px').height(h);
01128 bot += h;
01129 $("#"+this.separ.left).css('bottom', bot + 'px');
01130 }
01131
01132 if (this.separ.horizontal)
01133 if (this.separ.hpart) {
01134 var ww = $("#"+this.separ.left).outerWidth() - 2;
01135 $('#'+this.separ.bottom).width(ww);
01136 $("#"+this.separ.horizontal).width(ww);
01137 } else {
01138 var bot = $("#"+this.separ.left).css('bottom');
01139 $("#"+this.separ.vertical).css('bottom', bot);
01140 $("#"+this.separ.right).css('bottom', bot);
01141 }
01142
01143 if (firsttime || (this.separ.handle==null)) return;
01144
01145 if (typeof this.separ.handle == 'function') this.separ.handle(); else
01146 if ((typeof this.separ.handle == 'object') &&
01147 (typeof this.separ.handle['CheckResize'] == 'function')) this.separ.handle.CheckResize();
01148 }
01149
01150 JSROOT.Painter.ConfigureVSeparator = function(handle) {
01151
01152 JSROOT.Painter.separ = { handle: handle, left: "left-div", right: "right-div", vertical: "separator-div",
01153 horizontal : null, bottom : null, hpart: true };
01154
01155 $("#separator-div").addClass("separator").draggable({
01156 axis: "x" , zIndex: 100, cursor: "ew-resize",
01157 helper : function() { return $("#separator-div").clone().attr('id','separator-clone').css('background-color','grey'); },
01158 stop: function(event,ui) {
01159 event.stopPropagation();
01160 var left = ui.position.left;
01161 $("#separator-clone").remove();
01162 JSROOT.Painter.AdjustLayout(left, null, false);
01163 }
01164 });
01165
01166 var w0 = Math.round($(window).width() * 0.2);
01167 if (w0<300) w0 = Math.min(300, Math.round($(window).width() * 0.5));
01168
01169 JSROOT.Painter.AdjustLayout(w0, null, true);
01170 }
01171
01172 JSROOT.Painter.ConfigureHSeparator = function(height, onlyleft) {
01173
01174 if ((JSROOT.Painter.separ == null) ||
01175 (JSROOT.Painter.separ.horizontal != null)) return null;
01176
01177 JSROOT.Painter.separ['horizontal'] = 'horizontal-separator-div';
01178 JSROOT.Painter.separ['bottom'] = 'bottom-div';
01179 JSROOT.Painter.separ.hpart = (onlyleft === true);
01180
01181 var prnt = $("#"+this.separ.left).parent();
01182
01183 prnt.append('<div id="horizontal-separator-div" class="separator" style="left:1px; right:1px; height:4px; bottom:16px; cursor: ns-resize"></div>');
01184 prnt.append('<div id="bottom-div" class="column" style="left:1px; right:1px; height:15px; bottom:1px"></div>');
01185
01186 $("#horizontal-separator-div").addClass("separator").draggable({
01187 axis: "y" , zIndex: 100, cursor: "ns-resize",
01188 helper : function() { return $("#horizontal-separator-div").clone().attr('id','horizontal-separator-clone').css('background-color','grey'); },
01189 stop: function(event,ui) {
01190 event.stopPropagation();
01191 var top = $(window).height() - ui.position.top;
01192 $('#horizontal-separator-clone').remove();
01193 JSROOT.Painter.AdjustLayout(null, top, false);
01194 }
01195 });
01196
01197 JSROOT.Painter.AdjustLayout(null, height, false);
01198
01199 return JSROOT.Painter.separ.bottom;
01200 }
01201
01202 return JSROOT.Painter;
01203
01204 }));
01205