2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
10 * The ProfilerViewer module provides a graphical display for viewing
11 * the output of the YUI Profiler <http://developer.yahoo.com/yui/profiler>.
12 * @module profilerviewer
13 * @requires yahoo, dom, event, element, profiler, yuiloader
17 * A widget to view YUI Profiler output.
18 * @namespace YAHOO.widget
19 * @class ProfilerViewer
20 * @extends YAHOO.util.Element
22 * @param {HTMLElement | String | Object} el(optional) The html
23 * element into which the ProfileViewer should be rendered.
24 * An element will be created if none provided.
25 * @param {Object} attr (optional) A key map of the ProfilerViewer's
26 * initial attributes. Ignored if first arg is an attributes object.
28 YAHOO.widget.ProfilerViewer = function(el, attr) {
30 if (arguments.length == 1 && !YAHOO.lang.isString(el) && !el.nodeName) {
32 el = attr.element || null;
34 if (!el && !attr.element) {
35 el = this._createProfilerViewerElement();
38 YAHOO.widget.ProfilerViewer.superclass.constructor.call(this, el, attr);
42 YAHOO.log("ProfilerViewer instantiated.", "info", "ProfilerViewer");
45 YAHOO.extend(YAHOO.widget.ProfilerViewer, YAHOO.util.Element);
47 // Static members of YAHOO.widget.ProfilerViewer:
48 YAHOO.lang.augmentObject(YAHOO.widget.ProfilerViewer, {
50 * Classname for ProfilerViewer containing element.
60 * Classname for ProfilerViewer button dashboard.
62 * @property CLASS_DASHBOARD
65 * @default "yui-pv-dashboard"
67 CLASS_DASHBOARD: 'yui-pv-dashboard',
70 * Classname for the "refresh data" button.
72 * @property CLASS_REFRESH
75 * @default "yui-pv-refresh"
77 CLASS_REFRESH: 'yui-pv-refresh',
80 * Classname for busy indicator in the dashboard.
82 * @property CLASS_BUSY
85 * @default "yui-pv-busy"
87 CLASS_BUSY: 'yui-pv-busy',
90 * Classname for element containing the chart and chart
93 * @property CLASS_CHART_CONTAINER
96 * @default "yui-pv-chartcontainer"
98 CLASS_CHART_CONTAINER: 'yui-pv-chartcontainer',
101 * Classname for element containing the chart.
103 * @property CLASS_CHART
106 * @default "yui-pv-chart"
108 CLASS_CHART: 'yui-pv-chart',
111 * Classname for element containing the chart's legend.
113 * @property CLASS_CHART_LEGEND
116 * @default "yui-pv-chartlegend"
118 CLASS_CHART_LEGEND: 'yui-pv-chartlegend',
121 * Classname for element containing the datatable.
123 * @property CLASS_TABLE
126 * @default "yui-pv-table"
128 CLASS_TABLE: 'yui-pv-table',
131 * Strings used in the UI.
136 * @default English language strings for UI.
139 title: "YUI Profiler (beta)",
141 viewprofiler: "View Profiler Data",
142 hideprofiler: "Hide Profiler Report",
143 showchart: "Show Chart",
144 hidechart: "Hide Chart",
145 refreshdata: "Refresh Data"
148 //key: [column head label, width in pixels]
149 fn: ["Function/Method", null], //must auto-size
150 calls: ["Calls", 40],
151 avg: ["Average", 80],
152 min: ["Shortest", 70],
153 max: ["Longest", 70],
154 total: ["Total Time", 70],
157 millisecondsAbbrev: "ms",
158 initMessage: "initialiazing chart...",
159 installFlashMessage: "Unable to load Flash content. The YUI Charts Control requires Flash Player 9.0.45 or higher. You can download the latest version of Flash Player from the <a href='http://www.adobe.com/go/getflashplayer'>Adobe Flash Player Download Center</a>."
163 * Function used to format numbers in milliseconds
164 * for chart; must be publicly accessible, per Charts spec.
166 * @property timeAxisLabelFunction
170 timeAxisLabelFunction: function(n) {
171 var a = (n === Math.floor(n)) ? n : (Math.round(n*1000))/1000;
172 return (a + " " + YAHOO.widget.ProfilerViewer.STRINGS.millisecondsAbbrev);
176 * Function used to format percent numbers for chart; must
177 * be publicly accessible, per Charts spec.
179 * @property percentAxisLabelFunction
183 percentAxisLabelFunction: function(n) {
184 var a = (n === Math.floor(n)) ? n : (Math.round(n*100))/100;
193 // STANDARD SHORTCUTS
195 var Dom = YAHOO.util.Dom;
196 var Event = YAHOO.util.Event;
197 var Profiler = YAHOO.tool.Profiler;
198 var PV = YAHOO.widget.ProfilerViewer;
199 var proto = PV.prototype;
207 * Refreshes the data displayed in the ProfilerViewer. When called,
208 * this will invoke a refresh of the DataTable and (if displayed)
210 * @method refreshData
214 proto.refreshData = function() {
215 YAHOO.log("Data refresh requested via refreshData method.", "info", "ProfilerViewer");
216 this.fireEvent("dataRefreshEvent");
220 * Returns the element containing the console's header.
222 * @return HTMLElement
225 proto.getHeadEl = function() {
226 YAHOO.log("Head element requested via getHeadEl.", "info", "ProfilerViewer");
227 return (this._headEl) ? Dom.get(this._headEl) : false;
231 * Returns the element containing the console's body, including
232 * the chart and the datatable..
234 * @return HTMLElement
237 proto.getBodyEl = function() {
238 YAHOO.log("Body element requested via getBodyEl.", "info", "ProfilerViewer");
239 return (this._bodyEl) ? Dom.get(this._bodyEl) : false;
243 * Returns the element containing the console's chart.
245 * @return HTMLElement
248 proto.getChartEl = function() {
249 YAHOO.log("Chart element requested via getChartEl.", "info", "ProfilerViewer");
250 return (this._chartEl) ? Dom.get(this._chartEl) : false;
254 * Returns the element containing the console's dataTable.
256 * @return HTMLElement
259 proto.getTableEl = function() {
260 YAHOO.log("DataTable element requested via getTableEl.", "info", "ProfilerViewer");
261 return (this._tableEl) ? Dom.get(this._tableEl) : false;
265 * Returns the element containing the console's DataTable
267 * @method getDataTable
268 * @return YAHOO.widget.DataTable
271 proto.getDataTable = function() {
272 YAHOO.log("DataTable instance requested via getDataTable.", "info", "ProfilerViewer");
273 return this._dataTable;
277 * Returns the element containing the console's Chart instance.
279 * @return YAHOO.widget.BarChart
282 proto.getChart = function() {
283 YAHOO.log("Chart instance requested via getChart.", "info", "ProfilerViewer");
289 // PRIVATE PROPERTIES
291 proto._rendered = false;
292 proto._headEl = null;
293 proto._bodyEl = null;
294 proto._toggleVisibleEl = null;
295 proto._busyEl = null;
298 proto._tableEl = null;
299 proto._dataTable = null;
301 proto._chartEl = null;
302 proto._chartLegendEl = null;
303 proto._chartElHeight = 250;
305 proto._chartInitialized = false;
311 proto._init = function() {
317 * Fired when a data refresh is requested. No arguments are passed
320 * @event refreshDataEvent
322 this.createEvent("dataRefreshEvent");
325 * Fired when the viewer canvas first renders. No arguments are passed
330 this.createEvent("renderEvent");
332 this.on("dataRefreshEvent", this._refreshDataTable, this, true);
334 this._initLauncherDOM();
336 if(this.get("showChart")) {
337 this.on("sortedByChange", this._refreshChart);
340 YAHOO.log("ProfilerViewer instance initialization complete.", "info", "ProfilerViewer");
344 * If no element is passed in, create it as the first element
346 * @method _createProfilerViewerElement
347 * @return HTMLElement
350 proto._createProfilerViewerElement = function() {
351 YAHOO.log("Creating root element...", "info", "ProfilerViewer");
353 var el = document.createElement("div");
354 document.body.insertBefore(el, document.body.firstChild);
355 Dom.addClass(el, this.SKIN_CLASS);
356 Dom.addClass(el, PV.CLASS);
362 * Provides a readable name for the ProfilerViewer instance.
367 proto.toString = function() {
368 return "ProfilerViewer " + (this.get('id') || this.get('tagName'));
372 * Toggles visibility of the viewer canvas.
373 * @method _toggleVisible
377 proto._toggleVisible = function() {
378 YAHOO.log("Toggling visibility to " + !this.get("visible") + ".", "info", "ProfilerViewer");
380 var newVis = (this.get("visible")) ? false : true;
381 this.set("visible", newVis);
385 * Shows the viewer canvas.
390 proto._show = function() {
392 this._setBusyState(true);
393 if(!this._rendered) {
394 var loader = new YAHOO.util.YUILoader();
395 if (this.get("base")) {
396 loader.base = this.get("base");
399 var modules = ["datatable"];
400 if(this.get("showChart")) {
401 modules.push("charts");
404 loader.insert({ require: modules,
405 onSuccess: function() {
410 var el = this.get("element");
411 Dom.removeClass(el, "yui-pv-minimized");
412 this._toggleVisibleEl.innerHTML = PV.STRINGS.buttons.hideprofiler;
414 //The Flash Charts component can't be set to display:none,
415 //and even after positioning it offscreen the screen
416 //may fail to repaint in some browsers. Adding an empty
417 //style rule to the console body can help force a repaint:
418 Dom.addClass(el, "yui-pv-null");
419 Dom.removeClass(el, "yui-pv-null");
421 //Always refresh data when changing to visible:
428 * Hides the viewer canvas.
433 proto._hide = function() {
434 this._toggleVisibleEl.innerHTML = PV.STRINGS.buttons.viewprofiler;
435 Dom.addClass(this.get("element"), "yui-pv-minimized");
439 * Render the viewer canvas
444 proto._render = function() {
445 YAHOO.log("Beginning to render ProfilerViewer canvas...", "info", "ProfilerViewer");
447 Dom.removeClass(this.get("element"), "yui-pv-minimized");
449 this._initViewerDOM();
450 this._initDataTable();
451 if(this.get("showChart")) {
452 this._initChartDOM();
455 this._rendered = true;
456 this._toggleVisibleEl.innerHTML = PV.STRINGS.buttons.hideprofiler;
458 this.fireEvent("renderEvent");
460 YAHOO.log("ProfilerViewer rendering complete...", "info", "ProfilerViewer");
464 * Set up the DOM structure for the ProfilerViewer launcher.
465 * @method _initLauncherDOM
468 proto._initLauncherDOM = function() {
469 YAHOO.log("Creating the launcher...", "info", "ProfilerViewer");
471 var el = this.get("element");
472 Dom.addClass(el, PV.CLASS);
473 Dom.addClass(el, "yui-pv-minimized");
475 this._headEl = document.createElement("div");
476 Dom.addClass(this._headEl, "hd");
478 var s = PV.STRINGS.buttons;
479 var b = (this.get("visible")) ? s.hideprofiler : s.viewprofiler;
481 this._toggleVisibleEl = this._createButton(b, this._headEl);
483 this._refreshEl = this._createButton(s.refreshdata, this._headEl);
484 Dom.addClass(this._refreshEl, PV.CLASS_REFRESH);
486 this._busyEl = document.createElement("span");
487 this._headEl.appendChild(this._busyEl);
489 var title = document.createElement("h4");
490 title.innerHTML = PV.STRINGS.title;
491 this._headEl.appendChild(title);
493 el.appendChild(this._headEl);
495 Event.on(this._toggleVisibleEl, "click", this._toggleVisible, this, true);
496 Event.on(this._refreshEl, "click", function() {
498 this._setBusyState(true);
499 this.fireEvent("dataRefreshEvent");
505 * Set up the DOM structure for the ProfilerViewer canvas,
506 * including the holder for the DataTable.
507 * @method _initViewerDOM
510 proto._initViewerDOM = function() {
511 YAHOO.log("Creating DOM structure for viewer...", "info", "ProfilerViewer");
513 var el = this.get("element");
514 this._bodyEl = document.createElement("div");
515 Dom.addClass(this._bodyEl, "bd");
516 this._tableEl = document.createElement("div");
517 Dom.addClass(this._tableEl, PV.CLASS_TABLE);
518 this._bodyEl.appendChild(this._tableEl);
519 el.appendChild(this._bodyEl);
523 * Set up the DOM structure for the ProfilerViewer canvas.
524 * @method _initChartDOM
527 proto._initChartDOM = function() {
528 YAHOO.log("Adding DOM structure for chart...", "info", "ProfilerViewer");
530 this._chartContainer = document.createElement("div");
531 Dom.addClass(this._chartContainer, PV.CLASS_CHART_CONTAINER);
533 var chl = document.createElement("div");
534 Dom.addClass(chl, PV.CLASS_CHART_LEGEND);
536 var chw = document.createElement("div");
538 this._chartLegendEl = document.createElement("dl");
539 this._chartLegendEl.innerHTML = "<dd>" + PV.STRINGS.initMessage + "</dd>";
541 this._chartEl = document.createElement("div");
542 Dom.addClass(this._chartEl, PV.CLASS_CHART);
544 var msg = document.createElement("p");
545 msg.innerHTML = PV.STRINGS.installFlashMessage;
546 this._chartEl.appendChild(msg);
548 this._chartContainer.appendChild(chl);
549 chl.appendChild(chw);
550 chw.appendChild(this._chartLegendEl);
551 this._chartContainer.appendChild(this._chartEl);
552 this._bodyEl.insertBefore(this._chartContainer,this._tableEl);
557 * Create anchor elements for use as buttons. Args: label
558 * is text to appear on the face of the button, parentEl
559 * is the el to which the anchor will be attached, position
560 * is true for inserting as the first node and false for
561 * inserting as the last node of the parentEl.
562 * @method _createButton
565 proto._createButton = function(label, parentEl, position) {
566 var b = document.createElement("a");
567 b.innerHTML = b.title = label;
570 parentEl.appendChild(b);
572 parentEl.insertBefore(b, parentEl.firstChild);
579 * Set's console busy state.
580 * @method _setBusyState
583 proto._setBusyState = function(b) {
585 Dom.addClass(this._busyEl, PV.CLASS_BUSY);
588 Dom.removeClass(this._busyEl, PV.CLASS_BUSY);
594 * Generages a sorting function based on current sortedBy
596 * @method _createProfilerViewerElement
599 proto._genSortFunction = function(key, dir) {
602 return function(a, b) {
603 if (direction == YAHOO.widget.DataTable.CLASS_ASC) {
604 return a[by] - b[by];
606 return ((a[by] - b[by]) * -1);
612 * Utility function for array sums.
616 var _arraySum = function(arr){
618 for(var i = 0; i < arr.length; ct+=arr[i++]){}
623 * Retrieves data from Profiler, filtering and sorting as needed
624 * based on current widget state. Adds calculated percentage
625 * column and function name to data returned by Profiler.
626 * @method _getProfilerData
629 proto._getProfilerData = function() {
630 YAHOO.log("Profiler data requested from function DataSource.", "info", "ProfilerViewer");
632 var obj = Profiler.getFullReport();
636 if (YAHOO.lang.hasOwnProperty(obj, name)) {
639 o.fn = name; //add function name to record
640 o.points = r.points.slice(); //copy live array
645 o.total = _arraySum(o.points);
647 var f = this.get("filter");
650 totalTime += o.total;
655 //add calculated percentage column
656 for (var i = 0, j = arr.length; i < j; i++) {
657 arr[i].pct = (totalTime) ? (arr[i].total * 100) / totalTime : 0;
660 var sortedBy = this.get("sortedBy");
661 var key = sortedBy.key;
662 var dir = sortedBy.dir;
664 arr.sort(this._genSortFunction(key, dir));
666 YAHOO.log("Returning data from DataSource: " + YAHOO.lang.dump(arr), "info", "ProfilerViewer");
672 * Set up the DataTable.
673 * @method _initDataTable
676 proto._initDataTable = function() {
677 YAHOO.log("Creating DataTable instance...", "info", "ProfilerViewer");
681 //Set up the JS Function DataSource, pulling data from
683 this._dataSource = new YAHOO.util.DataSource(
685 return self._getProfilerData.call(self);
688 responseType: YAHOO.util.DataSource.TYPE_JSARRAY,
692 var ds = this._dataSource;
696 fields: [ "fn", "avg", "calls", "max", "min", "total", "pct", "points"]
699 //Set up the DataTable.
700 var formatTimeValue = function(elCell, oRecord, oColumn, oData) {
701 var a = (oData === Math.floor(oData)) ? oData : (Math.round(oData*1000))/1000;
702 elCell.innerHTML = a + " " + PV.STRINGS.millisecondsAbbrev;
705 var formatPercent = function(elCell, oRecord, oColumn, oData) {
706 var a = (oData === Math.floor(oData)) ? oData : (Math.round(oData*100))/100;
707 elCell.innerHTML = a + "%";
710 var a = YAHOO.widget.DataTable.CLASS_ASC;
711 var d = YAHOO.widget.DataTable.CLASS_DESC;
712 var c = PV.STRINGS.colHeads;
713 var f = formatTimeValue;
716 {key:"fn", sortable:true, label: c.fn[0],
717 sortOptions: {defaultDir:a},
718 resizeable: (YAHOO.util.DragDrop) ? true : false,
720 {key:"calls", sortable:true, label: c.calls[0],
721 sortOptions: {defaultDir:d},
723 {key:"avg", sortable:true, label: c.avg[0],
724 sortOptions: {defaultDir:d},
727 {key:"min", sortable:true, label: c.min[0],
728 sortOptions: {defaultDir:a},
731 {key:"max", sortable:true, label: c.max[0],
732 sortOptions: {defaultDir:d},
735 {key:"total", sortable:true, label: c.total[0],
736 sortOptions: {defaultDir:d},
739 {key:"pct", sortable:true, label: c.pct[0],
740 sortOptions: {defaultDir:d},
741 formatter:formatPercent,
745 this._dataTable = new YAHOO.widget.DataTable(this._tableEl, cols, ds, {
747 height:this.get("tableHeight"),
751 dir: YAHOO.widget.DataTable.CLASS_DESC
754 var dt = this._dataTable;
756 //Wire up DataTable events to drive the rest of the UI.
757 dt.subscribe("sortedByChange", this._sortedByChange, this, true);
758 dt.subscribe("renderEvent", this._dataTableRenderHandler, this, true);
759 dt.subscribe("initEvent", this._dataTableRenderHandler, this, true);
760 Event.on(this._tableEl.getElementsByTagName("th"), "click", this._thClickHandler, this, true);
761 YAHOO.log("DataTable initialized.", "info", "ProfilerViewer");
765 * Proxy the sort event in DataTable into the ProfilerViewer
767 * @method _sortedByChange
770 proto._sortedByChange = function(o) {
771 if(o.newValue && o.newValue.key) {
772 YAHOO.log("Relaying DataTable sortedBy value change; new key: " + o.newValue.key + "; new direction: " + o.newValue.dir + ".", "info", "ProfilerViewer");
773 this.set("sortedBy", {key: o.newValue.key, dir:o.newValue.dir});
778 * Proxy the render event in DataTable into the ProfilerViewer
780 * @method _dataTableRenderHandler
783 proto._dataTableRenderHandler = function(o) {
784 YAHOO.log("DataTable's render event has fired.", "info", "ProfilerViewer");
785 this._setBusyState(false);
789 * Event handler for clicks on the DataTable's sortable column
791 * @method _thClickHandler
794 proto._thClickHandler = function(o) {
795 YAHOO.log("DataTable's header row was clicked for sorting.", "info", "ProfilerViewer");
796 this._setBusyState(true);
800 * Refresh DataTable, getting new data from Profiler.
801 * @method _refreshDataTable
804 proto._refreshDataTable = function(args) {
805 YAHOO.log("Beginning to refresh DataTable contents...", "info", "ProfilerViewer");
806 var dt = this._dataTable;
807 dt.getDataSource().sendRequest("", dt.onDataReturnInitializeTable, dt);
808 YAHOO.log("DataTable refresh complete.", "info", "ProfilerViewer");
812 * Refresh chart, getting new data from table.
813 * @method _refreshChart
816 proto._refreshChart = function() {
817 YAHOO.log("Beginning to refresh Chart contents...", "info", "ProfilerViewer");
819 switch (this.get("sortedBy").key) {
821 /*Keep the same data on the chart, but force update to
822 reflect new sort order on function/method name: */
823 this._chart.set("dataSource", this._chart.get("dataSource"));
824 /*no further action necessary; chart redraws*/
827 /*Null out the xAxis formatting before redrawing chart.*/
828 this._chart.set("xAxis", this._chartAxisDefinitionPlain);
831 this._chart.set("xAxis", this._chartAxisDefinitionPercent);
834 /*Set the default xAxis; redraw legend; set the new series definition.*/
835 this._chart.set("xAxis", this._chartAxisDefinitionTime);
839 this._drawChartLegend();
840 this._chart.set("series", this._getSeriesDef(this.get("sortedBy").key));
842 YAHOO.log("Chart refresh complete.", "info", "ProfilerViewer");
846 * Get data for the Chart from DataTable recordset
847 * @method _getChartData
850 proto._getChartData = function() {
851 YAHOO.log("Getting data for chart from function DataSource.", "info", "ProfilerViewer");
852 //var records = this._getProfilerData();
853 var records = this._dataTable.getRecordSet().getRecords(0, this.get("maxChartFunctions"));
855 for (var i = 0, j = records.length; i<j; i++) {
856 arr.push(records[i].getData());
858 YAHOO.log("Returning data to Chart: " + YAHOO.lang.dump(arr), "info", "ProfilerViewer");
863 * Build series definition based on current configuration attributes.
864 * @method _getSeriesDef
867 proto._getSeriesDef = function(field) {
868 var sd = this.get("chartSeriesDefinitions")[field];
870 for(var i = 0, j = sd.group.length; i<j; i++) {
871 var c = this.get("chartSeriesDefinitions")[sd.group[i]];
873 {displayName:c.displayName,
875 style: {color:c.style.color, size:c.style.size}
880 YAHOO.log("Returning new series definition to chart: " + YAHOO.lang.dump(arr), "info", "ProfilerViewer");
889 proto._initChart = function() {
890 YAHOO.log("Initializing chart...", "info", "ProfilerViewer");
892 this._sizeChartCanvas();
894 YAHOO.widget.Chart.SWFURL = this.get("swfUrl");
898 //Create DataSource based on records currently displayed
899 //at the top of the sort list in the DataTable.
900 var ds = new YAHOO.util.DataSource(
901 //force the jsfunction DataSource to run in the scope of
902 //the ProfilerViewer, not in the YAHOO.util.DataSource scope:
904 return self._getChartData.call(self);
907 responseType: YAHOO.util.DataSource.TYPE_JSARRAY,
914 fields: [ "fn", "avg", "calls", "max", "min", "total", "pct" ]
917 ds.subscribe('responseEvent', this._sizeChartCanvas, this, true);
919 //Set up the chart itself.
920 this._chartAxisDefinitionTime = new YAHOO.widget.NumericAxis();
921 this._chartAxisDefinitionTime.labelFunction = "YAHOO.widget.ProfilerViewer.timeAxisLabelFunction";
923 this._chartAxisDefinitionPercent = new YAHOO.widget.NumericAxis();
924 this._chartAxisDefinitionPercent.labelFunction = "YAHOO.widget.ProfilerViewer.percentAxisLabelFunction";
926 this._chartAxisDefinitionPlain = new YAHOO.widget.NumericAxis();
928 this._chart = new YAHOO.widget.BarChart( this._chartEl, ds,
931 series: this._getSeriesDef(this.get("sortedBy").key),
932 style: this.get("chartStyle"),
933 xAxis: this._chartAxisDefinitionTime
936 this._drawChartLegend();
937 this._chartInitialized = true;
938 this._dataTable.unsubscribe("initEvent", this._initChart, this);
939 this._dataTable.subscribe("initEvent", this._refreshChart, this, true);
941 YAHOO.log("Chart initialization complete.", "info", "ProfilerViewer");
945 * Set up the Chart's legend
946 * @method _drawChartLegend
949 proto._drawChartLegend = function() {
950 YAHOO.log("Drawing chart legend...", "info", "ProfilerViewer");
951 var seriesDefs = this.get("chartSeriesDefinitions");
952 var currentDef = seriesDefs[this.get("sortedBy").key];
953 var l = this._chartLegendEl;
955 for(var i = 0, j = currentDef.group.length; i<j; i++) {
956 var c = seriesDefs[currentDef.group[i]];
957 var dt = document.createElement("dt");
958 Dom.setStyle(dt, "backgroundColor", "#" + c.style.color);
959 var dd = document.createElement("dd");
960 dd.innerHTML = c.displayName;
967 * Resize the chart's canvas if based on number of records
968 * returned from the chart's datasource.
969 * @method _sizeChartCanvas
972 proto._sizeChartCanvas = function(o) {
973 YAHOO.log("Resizing chart canvas...", "info", "ProfilerViewer");
974 var bars = (o) ? o.response.length : this.get("maxChartFunctions");
975 var s = (bars * 36) + 34;
976 if (s != parseInt(this._chartElHeight, 10)) {
977 this._chartElHeight = s;
978 Dom.setStyle(this._chartEl, "height", s + "px");
983 * setAttributeConfigs TabView specific properties.
984 * @method initAttributes
985 * @param {Object} attr Hash of initial attributes
986 * @method initAttributes
989 proto.initAttributes = function(attr) {
990 YAHOO.log("Initializing attributes...", "info", "ProfilerViewer");
991 YAHOO.widget.ProfilerViewer.superclass.initAttributes.call(this, attr);
993 * The YUI Loader base path from which to pull YUI files needed
994 * in the rendering of the ProfilerViewer canvas. Passed directly
995 * to YUI Loader. Leave blank to draw files from
1001 this.setAttributeConfig('base', {
1006 * The height of the DataTable. The table will scroll
1007 * vertically if the content overflows the specified
1009 * @attribute tableHeight
1013 this.setAttributeConfig('tableHeight', {
1014 value: attr.tableHeight || "15em",
1015 method: function(s) {
1016 if(this._dataTable) {
1017 this._dataTable.set("height", s);
1023 * The default column key to sort by. Valid keys are: fn, calls,
1024 * avg, min, max, total. Valid dir values are:
1025 * YAHOO.widget.DataTable.CLASS_ASC and
1026 * YAHOO.widget.DataTable.CLASS_DESC (or their
1027 * string equivalents).
1028 * @attribute sortedBy
1030 * @default {key:"total", dir:"yui-dt-desc"}
1032 this.setAttributeConfig('sortedBy', {
1033 value: attr.sortedBy || {key:"total", dir:"yui-dt-desc"}
1037 * A filter function to use in selecting functions that will
1038 * appear in the ProfilerViewer report. The function is passed
1039 * a function report object and should return a boolean indicating
1040 * whether that function should be included in the ProfilerViewer
1041 * display. The argument is structured as follows:
1044 * fn: <str function name>,
1045 * calls : <n number of calls>,
1046 * avg : <n average call duration>,
1047 * max: <n duration of longest call>,
1048 * min: <n duration of shortest call>,
1049 * total: <n total time of all calls>
1050 * points : <array time in ms of each call>
1053 * For example, you would use the follwing filter function to
1054 * return only functions that have been called at least once:
1057 * return (o.calls > 0);
1064 this.setAttributeConfig('filter', {
1065 value: attr.filter || null,
1066 validator: YAHOO.lang.isFunction
1070 * The path to the YUI Charts swf file; must be a full URI
1071 * or a path relative to the page being profiled. Changes at runtime
1072 * not supported; pass this value in at instantiation.
1075 * @default "http://yui.yahooapis.com/2.5.0/build/charts/assets/charts.swf"
1077 this.setAttributeConfig('swfUrl', {
1078 value: attr.swfUrl || "http://yui.yahooapis.com/2.5.0/build/charts/assets/charts.swf"
1082 * The maximum number of functions to profile in the chart. The
1083 * greater the number of functions, the greater the height of the
1086 * @attribute maxChartFunctions
1090 this.setAttributeConfig('maxChartFunctions', {
1091 value: attr.maxChartFunctions || 6,
1092 method: function(s) {
1093 if(this._rendered) {
1094 this._sizeChartCanvas();
1097 validator: YAHOO.lang.isNumber
1101 * The style object that defines the chart's visual presentation.
1102 * Conforms to the style attribute passed to the Charts Control
1103 * constructor. See Charts Control User's Guide for more information
1104 * on how to format this object.
1105 * @attribute chartStyle
1107 * @default See JS source for default definitions.
1109 this.setAttributeConfig('chartStyle', {
1110 value: attr.chartStyle || {
1122 method: function() {
1123 if(this._rendered && this.get("showChart")) {
1124 this._refreshChart();
1130 * The series definition information to use when charting
1131 * specific fields on the chart. displayName, xField,
1132 * and style members are used to construct the series
1133 * definition; the "group" member is the array of fields
1134 * that should be charted when the table is sorted by a
1136 * @attribute chartSeriesDefinitions
1138 * @default See JS source for full default definitions.
1140 this.setAttributeConfig('chartSeriesDefinitions', {
1141 value: attr.chartSeriesDefinitions || {
1143 displayName: PV.STRINGS.colHeads.total[0],
1145 style: {color:"4d95dd", size:20},
1149 displayName: PV.STRINGS.colHeads.calls[0],
1151 style: {color:"edff9f", size:20},
1155 displayName: PV.STRINGS.colHeads.avg[0],
1157 style: {color:"209daf", size:9},
1158 group: ["avg", "min", "max"]
1161 displayName: PV.STRINGS.colHeads.min[0],
1163 style: {color:"b6ecf4", size:9},
1164 group: ["avg", "min", "max"]
1167 displayName: PV.STRINGS.colHeads.max[0],
1169 style: {color:"29c7de", size:9},
1170 group: ["avg", "min", "max"]
1173 displayName: PV.STRINGS.colHeads.pct[0],
1175 style: {color:"C96EDB", size:20},
1179 method: function() {
1180 if(this._rendered && this.get("showChart")) {
1181 this._refreshChart();
1187 * The default visibility setting for the viewer canvas. If true,
1188 * the viewer will load all necessary files and render itself
1189 * immediately upon instantiation; otherwise, the viewer will
1190 * load only minimal resources until the user toggles visibility
1192 * @attribute visible
1196 this.setAttributeConfig('visible', {
1197 value: attr.visible || false,
1198 validator: YAHOO.lang.isBoolean,
1199 method: function(b) {
1203 if (this._rendered) {
1211 * The default visibility setting for the chart.
1212 * @attribute showChart
1216 this.setAttributeConfig('showChart', {
1217 value: attr.showChart || true,
1218 validator: YAHOO.lang.isBoolean,
1223 YAHOO.widget.ProfilerViewer.superclass.initAttributes.call(this, attr);
1225 YAHOO.log("Attributes initialized.", "info", "ProfilerViewer");
1229 YAHOO.register("profilerviewer", YAHOO.widget.ProfilerViewer, {version: "2.8.0r4", build: "2449"});