[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/2in3/2.9.0/build/yui2-profilerviewer/ -> yui2-profilerviewer-debug.js (source)

   1  YUI.add('yui2-profilerviewer', function(Y) {
   2      var YAHOO    = Y.YUI2;
   3      /*
   4  Copyright (c) 2011, Yahoo! Inc. All rights reserved.
   5  Code licensed under the BSD License:
   6  http://developer.yahoo.com/yui/license.html
   7  version: 2.9.0
   8  */
   9  (function() {
  10  
  11      /**
  12       * The ProfilerViewer module provides a graphical display for viewing
  13       * the output of the YUI Profiler <http://developer.yahoo.com/yui/profiler>.
  14       * @module profilerviewer
  15       * @requires yahoo, dom, event, element, profiler, yuiloader
  16       */
  17  
  18      /**
  19       * A widget to view YUI Profiler output.
  20       * @namespace YAHOO.widget
  21       * @class ProfilerViewer
  22       * @extends YAHOO.util.Element
  23       * @constructor
  24       * @param {HTMLElement | String | Object} el(optional) The html 
  25       * element into which the ProfileViewer should be rendered. 
  26       * An element will be created if none provided.
  27       * @param {Object} attr (optional) A key map of the ProfilerViewer's 
  28       * initial attributes.  Ignored if first arg is an attributes object.
  29       */
  30      YAHOO.widget.ProfilerViewer = function(el, attr) {
  31          attr = attr || {};
  32          if (arguments.length == 1 && !YAHOO.lang.isString(el) && !el.nodeName) {
  33              attr = el;
  34              el = attr.element || null;
  35          }
  36          if (!el && !attr.element) {
  37              el = this._createProfilerViewerElement();
  38          }
  39  
  40          YAHOO.widget.ProfilerViewer.superclass.constructor.call(this, el, attr); 
  41          
  42          this._init();
  43          
  44          YAHOO.log("ProfilerViewer instantiated.", "info", "ProfilerViewer");
  45      };
  46  
  47      YAHOO.extend(YAHOO.widget.ProfilerViewer, YAHOO.util.Element);
  48      
  49      // Static members of YAHOO.widget.ProfilerViewer:
  50      YAHOO.lang.augmentObject(YAHOO.widget.ProfilerViewer, {
  51          /**
  52           * Classname for ProfilerViewer containing element.
  53           * @static
  54           * @property CLASS
  55           * @type string
  56           * @public
  57           * @default "yui-pv"
  58           */
  59          CLASS: 'yui-pv',
  60      
  61          /**
  62           * Classname for ProfilerViewer button dashboard. 
  63           * @static
  64           * @property CLASS_DASHBOARD
  65           * @type string
  66           * @public
  67           * @default "yui-pv-dashboard"
  68           */
  69          CLASS_DASHBOARD: 'yui-pv-dashboard',
  70  
  71          /**
  72           * Classname for the "refresh data" button. 
  73           * @static
  74           * @property CLASS_REFRESH
  75           * @type string
  76           * @public
  77           * @default "yui-pv-refresh"
  78           */
  79          CLASS_REFRESH: 'yui-pv-refresh',
  80  
  81          /**
  82           * Classname for busy indicator in the dashboard. 
  83           * @static
  84           * @property CLASS_BUSY
  85           * @type string
  86           * @public
  87           * @default "yui-pv-busy"
  88           */
  89          CLASS_BUSY: 'yui-pv-busy',
  90      
  91          /**
  92           * Classname for element containing the chart and chart
  93           * legend elements.
  94           * @static
  95           * @property CLASS_CHART_CONTAINER
  96           * @type string
  97           * @public
  98           * @default "yui-pv-chartcontainer"
  99           */
 100          CLASS_CHART_CONTAINER: 'yui-pv-chartcontainer',
 101      
 102          /**
 103           * Classname for element containing the chart.
 104           * @static
 105           * @property CLASS_CHART
 106           * @type string
 107           * @public
 108           * @default "yui-pv-chart"
 109           */
 110          CLASS_CHART: 'yui-pv-chart',
 111          
 112          /**
 113           * Classname for element containing the chart's legend. 
 114           * @static
 115           * @property CLASS_CHART_LEGEND
 116           * @type string
 117           * @public
 118           * @default "yui-pv-chartlegend"
 119           */
 120          CLASS_CHART_LEGEND: 'yui-pv-chartlegend',
 121          
 122          /**
 123           * Classname for element containing the datatable. 
 124           * @static
 125           * @property CLASS_TABLE
 126           * @type string
 127           * @public
 128           * @default "yui-pv-table"
 129           */
 130          CLASS_TABLE: 'yui-pv-table',
 131          
 132          /**
 133           * HTML strings used in the UI. Values will be inserted into DOM with innerHTML.
 134           * @static
 135           * @property STRINGS
 136           * @object
 137           * @public
 138           * @default English language strings for UI.
 139           */
 140          STRINGS: {
 141              title: "YUI ProfilerViewer",
 142              buttons: {
 143                  viewprofiler: "View Profiler Data",
 144                  hideprofiler: "Hide Profiler Report",
 145                  showchart: "Show Chart",
 146                  hidechart: "Hide Chart",
 147                  refreshdata: "Refresh Data"
 148              },
 149              colHeads: {
 150                  //key: [column head label, width in pixels]
 151                  fn: ["Function/Method", null], //must auto-size
 152                  calls: ["Calls", 40],
 153                  avg: ["Average", 80],
 154                  min: ["Shortest", 70],
 155                  max: ["Longest", 70],
 156                  total: ["Total Time", 70],
 157                  pct: ["Percent", 70]
 158              },
 159              millisecondsAbbrev: "ms",
 160              initMessage: "initialiazing chart...",
 161              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>."
 162          },
 163  
 164          /**
 165           * Function used to format numbers in milliseconds
 166           * for chart; must be publicly accessible, per Charts spec.
 167           * @static
 168           * @property timeAxisLabelFunction
 169           * @type function
 170           * @private
 171           */
 172          timeAxisLabelFunction: function(n) {
 173              var a = (n === Math.floor(n)) ? n : (Math.round(n*1000))/1000;
 174              return (a + " " + YAHOO.widget.ProfilerViewer.STRINGS.millisecondsAbbrev);
 175          },
 176  
 177          /**
 178           * Function used to format percent numbers for chart; must
 179           * be publicly accessible, per Charts spec.
 180           * @static
 181           * @property percentAxisLabelFunction
 182           * @type function
 183           * @private
 184           */
 185          percentAxisLabelFunction: function(n) {
 186              var a = (n === Math.floor(n)) ? n : (Math.round(n*100))/100;
 187              return (a + "%");
 188          }
 189          
 190      
 191      },true);
 192      
 193  
 194      //
 195      // STANDARD SHORTCUTS
 196      //
 197      var Dom = YAHOO.util.Dom;
 198      var Event = YAHOO.util.Event;
 199      var Profiler = YAHOO.tool.Profiler;
 200      var PV = YAHOO.widget.ProfilerViewer;
 201      var proto = PV.prototype;
 202  
 203  
 204      //
 205      // PUBLIC METHODS
 206      //
 207      
 208       /**
 209       * Refreshes the data displayed in the ProfilerViewer. When called,
 210       * this will invoke a refresh of the DataTable and (if displayed)
 211       * the Chart.
 212       * @method refreshData
 213       * @return void
 214       * @public
 215       */    
 216      proto.refreshData = function() {
 217          YAHOO.log("Data refresh requested via refreshData method.", "info", "ProfilerViewer");
 218          this.fireEvent("dataRefreshEvent");
 219      };
 220  
 221       /**
 222       * Returns the element containing the console's header.
 223       * @method getHeadEl
 224       * @return HTMLElement
 225       * @public
 226       */    
 227      proto.getHeadEl = function() {
 228          YAHOO.log("Head element requested via getHeadEl.", "info", "ProfilerViewer");
 229          return (this._headEl) ? Dom.get(this._headEl) : false;
 230      };
 231  
 232       /**
 233       * Returns the element containing the console's body, including
 234       * the chart and the datatable..
 235       * @method getBodyEl
 236       * @return HTMLElement
 237       * @public
 238       */    
 239      proto.getBodyEl = function() {
 240          YAHOO.log("Body element requested via getBodyEl.", "info", "ProfilerViewer");
 241          return (this._bodyEl) ? Dom.get(this._bodyEl) : false;
 242      };
 243  
 244       /**
 245       * Returns the element containing the console's chart.
 246       * @method getChartEl
 247       * @return HTMLElement
 248       * @public
 249       */    
 250      proto.getChartEl = function() {
 251          YAHOO.log("Chart element requested via getChartEl.", "info", "ProfilerViewer");
 252          return (this._chartEl) ? Dom.get(this._chartEl) : false;
 253      };
 254  
 255       /**
 256       * Returns the element containing the console's dataTable.
 257       * @method getTableEl
 258       * @return HTMLElement
 259       * @public
 260       */    
 261      proto.getTableEl = function() {
 262          YAHOO.log("DataTable element requested via getTableEl.", "info", "ProfilerViewer");
 263          return (this._tableEl) ? Dom.get(this._tableEl) : false;
 264      };
 265  
 266       /**
 267       * Returns the element containing the console's DataTable
 268       * instance.
 269       * @method getDataTable
 270       * @return YAHOO.widget.DataTable
 271       * @public
 272       */    
 273      proto.getDataTable = function() {
 274          YAHOO.log("DataTable instance requested via getDataTable.", "info", "ProfilerViewer");
 275          return this._dataTable;
 276      };
 277  
 278       /**
 279       * Returns the element containing the console's Chart instance.
 280       * @method getChart
 281       * @return YAHOO.widget.BarChart
 282       * @public
 283       */    
 284      proto.getChart = function() {
 285          YAHOO.log("Chart instance requested via getChart.", "info", "ProfilerViewer");
 286          return this._chart;
 287      };
 288  
 289  
 290      //
 291      // PRIVATE PROPERTIES
 292      //
 293      proto._rendered = false;
 294      proto._headEl = null;
 295      proto._bodyEl = null;
 296      proto._toggleVisibleEl = null;
 297      proto._busyEl = null;
 298      proto._busy = false;
 299      
 300      proto._tableEl = null;
 301      proto._dataTable = null;
 302  
 303      proto._chartEl = null;
 304      proto._chartLegendEl = null;
 305      proto._chartElHeight = 250;
 306      proto._chart = null;
 307      proto._chartInitialized = false;
 308  
 309      //
 310      // PRIVATE METHODS
 311      //
 312  
 313      proto._init = function() {
 314          /**
 315           * CUSTOM EVENTS
 316           **/
 317          
 318          /**
 319           * Fired when a data refresh is requested. No arguments are passed
 320           * with this event.
 321           *
 322           * @event refreshDataEvent
 323           */
 324          this.createEvent("dataRefreshEvent");
 325          
 326          /**
 327           * Fired when the viewer canvas first renders. No arguments are passed
 328           * with this event.
 329           *
 330           * @event renderEvent
 331           */
 332          this.createEvent("renderEvent");
 333  
 334          this.on("dataRefreshEvent", this._refreshDataTable, this, true);
 335          
 336          this._initLauncherDOM();
 337          
 338          if(this.get("showChart")) {
 339              this.on("sortedByChange", this._refreshChart);
 340          }
 341  
 342          YAHOO.log("ProfilerViewer instance initialization complete.", "info", "ProfilerViewer");
 343      };
 344  
 345      /**
 346       * If no element is passed in, create it as the first element
 347       * in the document.
 348       * @method _createProfilerViewerElement
 349       * @return HTMLElement
 350       * @private
 351       */
 352      proto._createProfilerViewerElement = function() {
 353          YAHOO.log("Creating root element...", "info", "ProfilerViewer");
 354  
 355          var el = document.createElement("div");
 356          document.body.insertBefore(el, document.body.firstChild);
 357          Dom.addClass(el, this.SKIN_CLASS);
 358          Dom.addClass(el, PV.CLASS);
 359          YAHOO.log(el);
 360          return el;
 361      };
 362              
 363      /**
 364       * Provides a readable name for the ProfilerViewer instance.
 365       * @method toString
 366       * @return String
 367       * @private
 368       */
 369      proto.toString = function() {
 370          return "ProfilerViewer " + (this.get('id') || this.get('tagName'));
 371      };
 372  
 373      /**
 374       * Toggles visibility of the viewer canvas.
 375       * @method _toggleVisible
 376       * @return void
 377       * @private
 378       */    
 379      proto._toggleVisible = function() {
 380          YAHOO.log("Toggling visibility to " + !this.get("visible") + ".", "info", "ProfilerViewer");
 381          
 382          var newVis = (this.get("visible")) ? false : true;
 383          this.set("visible", newVis);
 384      };
 385  
 386      /**
 387       * Shows the viewer canvas.
 388       * @method show
 389       * @return void
 390       * @private
 391       */    
 392       proto._show = function() {
 393           if(!this._busy) {
 394              this._setBusyState(true);
 395              if(!this._rendered) {
 396                  var loader = new YAHOO.util.YUILoader();
 397                  if (this.get("base")) {
 398                      loader.base = this.get("base");
 399                  }
 400                  
 401                  var modules = ["datatable"];
 402                  if(this.get("showChart")) {
 403                      modules.push("charts");
 404                  }
 405                  
 406                  loader.insert({ require: modules,
 407                                  onSuccess: function() {
 408                                      this._render();
 409                                  },
 410                                  scope: this});
 411              } else {
 412                  var el = this.get("element");
 413                  Dom.removeClass(el, "yui-pv-minimized");
 414                  this._toggleVisibleEl.innerHTML = PV.STRINGS.buttons.hideprofiler;
 415                  
 416                  //The Flash Charts component can't be set to display:none,
 417                  //and even after positioning it offscreen the screen
 418                  //may fail to repaint in some browsers.  Adding an empty
 419                  //style rule to the console body can help force a repaint:
 420                  Dom.addClass(el, "yui-pv-null");
 421                  Dom.removeClass(el, "yui-pv-null");
 422                  
 423                  //Always refresh data when changing to visible:
 424                  this.refreshData();
 425              }
 426          }
 427      };
 428  
 429      /**
 430       * Hides the viewer canvas.
 431       * @method hide
 432       * @return void
 433       * @private
 434       */    
 435      proto._hide = function() {
 436          this._toggleVisibleEl.innerHTML = PV.STRINGS.buttons.viewprofiler;
 437          Dom.addClass(this.get("element"), "yui-pv-minimized");
 438      };
 439      
 440      /**
 441       * Render the viewer canvas
 442       * @method _render
 443       * @return void
 444       * @private
 445       */
 446      proto._render = function() {
 447          YAHOO.log("Beginning to render ProfilerViewer canvas...", "info", "ProfilerViewer");
 448          
 449          Dom.removeClass(this.get("element"), "yui-pv-minimized");
 450          
 451          this._initViewerDOM();
 452          this._initDataTable();
 453          if(this.get("showChart")) {
 454              this._initChartDOM();
 455              this._initChart();
 456          }
 457          this._rendered = true;
 458          this._toggleVisibleEl.innerHTML = PV.STRINGS.buttons.hideprofiler;
 459          
 460          this.fireEvent("renderEvent");
 461  
 462          YAHOO.log("ProfilerViewer rendering complete...", "info", "ProfilerViewer");
 463      };
 464      
 465      /**
 466       * Set up the DOM structure for the ProfilerViewer launcher.
 467       * @method _initLauncherDOM
 468       * @private
 469       */
 470      proto._initLauncherDOM = function() {
 471          YAHOO.log("Creating the launcher...", "info", "ProfilerViewer");
 472          
 473          var el = this.get("element");
 474          Dom.addClass(el, PV.CLASS);
 475          Dom.addClass(el, "yui-pv-minimized");
 476  
 477          this._headEl = document.createElement("div");
 478          Dom.addClass(this._headEl, "hd");
 479          
 480          var s = PV.STRINGS.buttons;
 481          var b = (this.get("visible")) ? s.hideprofiler : s.viewprofiler;
 482          
 483          this._toggleVisibleEl = this._createButton(b, this._headEl);
 484          
 485          this._refreshEl = this._createButton(s.refreshdata, this._headEl);
 486          Dom.addClass(this._refreshEl, PV.CLASS_REFRESH);
 487          
 488          this._busyEl = document.createElement("span");
 489          this._headEl.appendChild(this._busyEl);
 490  
 491          var title = document.createElement("h4");
 492          title.innerHTML = PV.STRINGS.title;
 493          this._headEl.appendChild(title);
 494          
 495          el.appendChild(this._headEl);
 496          
 497          Event.on(this._toggleVisibleEl, "click", this._toggleVisible, this, true);
 498          Event.on(this._refreshEl, "click", function() {
 499              if(!this._busy) {
 500                  this._setBusyState(true);
 501                  this.fireEvent("dataRefreshEvent");
 502              }
 503          }, this, true);
 504      };
 505  
 506      /**
 507       * Set up the DOM structure for the ProfilerViewer canvas,
 508       * including the holder for the DataTable.
 509       * @method _initViewerDOM
 510       * @private
 511       */
 512      proto._initViewerDOM = function() {
 513          YAHOO.log("Creating DOM structure for viewer...", "info", "ProfilerViewer");
 514          
 515          var el = this.get("element");
 516          this._bodyEl = document.createElement("div");
 517          Dom.addClass(this._bodyEl, "bd");
 518           this._tableEl = document.createElement("div");
 519          Dom.addClass(this._tableEl, PV.CLASS_TABLE);
 520          this._bodyEl.appendChild(this._tableEl);
 521          el.appendChild(this._bodyEl);
 522      };
 523  
 524      /**
 525       * Set up the DOM structure for the ProfilerViewer canvas.
 526       * @method _initChartDOM
 527       * @private
 528       */
 529      proto._initChartDOM = function() {
 530          YAHOO.log("Adding DOM structure for chart...", "info", "ProfilerViewer");
 531          
 532          this._chartContainer = document.createElement("div");
 533          Dom.addClass(this._chartContainer, PV.CLASS_CHART_CONTAINER);
 534          
 535          var chl = document.createElement("div");
 536          Dom.addClass(chl, PV.CLASS_CHART_LEGEND);
 537          
 538          var chw = document.createElement("div");
 539  
 540          this._chartLegendEl = document.createElement("dl");
 541          this._chartLegendEl.innerHTML = "<dd>" + PV.STRINGS.initMessage + "</dd>";
 542          
 543          this._chartEl = document.createElement("div");
 544          Dom.addClass(this._chartEl, PV.CLASS_CHART);
 545          
 546          var msg = document.createElement("p");
 547          msg.innerHTML = PV.STRINGS.installFlashMessage;
 548          this._chartEl.appendChild(msg);
 549          
 550          this._chartContainer.appendChild(chl);
 551          chl.appendChild(chw);
 552          chw.appendChild(this._chartLegendEl);
 553          this._chartContainer.appendChild(this._chartEl);
 554          this._bodyEl.insertBefore(this._chartContainer,this._tableEl);
 555      };
 556  
 557  
 558      /**
 559       * Create anchor elements for use as buttons. Args: label
 560       * is text to appear on the face of the button, parentEl
 561       * is the el to which the anchor will be attached, position
 562       * is true for inserting as the first node and false for
 563       * inserting as the last node of the parentEl.
 564       * @method _createButton
 565       * @private
 566       */    
 567      proto._createButton = function(label, parentEl, position) {
 568          var b = document.createElement("a");
 569          b.innerHTML = b.title = label;
 570          if(parentEl) {
 571              if(!position) {
 572                  parentEl.appendChild(b);
 573              } else {
 574                  parentEl.insertBefore(b, parentEl.firstChild);    
 575              }
 576          }
 577          return b;
 578      };
 579      
 580      /**
 581       * Set's console busy state.
 582       * @method _setBusyState
 583       * @private
 584       **/
 585      proto._setBusyState = function(b) {
 586          if(b) {
 587              Dom.addClass(this._busyEl, PV.CLASS_BUSY);
 588              this._busy = true;
 589          } else {
 590              Dom.removeClass(this._busyEl, PV.CLASS_BUSY);
 591              this._busy = false;
 592          }
 593      };
 594  
 595      /**
 596       * Generages a sorting function based on current sortedBy
 597       * values.
 598       * @method _createProfilerViewerElement
 599       * @private
 600       **/
 601      proto._genSortFunction = function(key, dir) {
 602          var by = key;
 603          var direction = dir;
 604          return function(a, b) {
 605              if (direction == YAHOO.widget.DataTable.CLASS_ASC) {
 606                  return a[by] - b[by];    
 607              } else {
 608                  return ((a[by] - b[by]) * -1);
 609              }
 610          };
 611      };
 612  
 613      /**
 614       * Utility function for array sums.
 615       * @method _arraySum
 616       * @private
 617       **/    
 618       var _arraySum = function(arr){
 619          var ct = 0;
 620          for(var i = 0; i < arr.length; ct+=arr[i++]){}
 621          return ct;
 622      };
 623      
 624      /**
 625       * Retrieves data from Profiler, filtering and sorting as needed
 626       * based on current widget state.  Adds calculated percentage
 627       * column and function name to data returned by Profiler.
 628       * @method _getProfilerData
 629       * @private
 630       **/
 631      proto._getProfilerData = function() {
 632          YAHOO.log("Profiler data requested from function DataSource.", "info", "ProfilerViewer");
 633          
 634          var obj = Profiler.getFullReport();
 635          var arr = [];
 636          var totalTime = 0;
 637          for (name in obj) {
 638              if (YAHOO.lang.hasOwnProperty(obj, name)) {
 639                  var r = obj[name];
 640                  var o = {};
 641                  o.fn = name; //add function name to record
 642                  o.points = r.points.slice(); //copy live array
 643                  o.calls = r.calls;
 644                  o.min = r.min;
 645                  o.max = r.max;
 646                  o.avg = r.avg;
 647                  o.total = _arraySum(o.points);
 648                  o.points = r.points;
 649                  var f = this.get("filter");
 650                  if((!f) || (f(o))) {
 651                      arr.push(o);
 652                      totalTime += o.total;
 653                  }
 654              }
 655          }
 656          
 657          //add calculated percentage column
 658          for (var i = 0, j = arr.length; i < j; i++) {
 659              arr[i].pct = (totalTime) ? (arr[i].total * 100) / totalTime : 0;    
 660          }
 661  
 662          var sortedBy = this.get("sortedBy");
 663          var key = sortedBy.key;
 664          var dir = sortedBy.dir;        
 665  
 666          arr.sort(this._genSortFunction(key, dir));
 667          
 668          YAHOO.log("Returning data from DataSource: " + YAHOO.lang.dump(arr), "info", "ProfilerViewer");
 669          
 670          return arr;
 671      };
 672      
 673      /**
 674       * Set up the DataTable.
 675       * @method _initDataTable
 676       * @private
 677       */
 678      proto._initDataTable = function() {
 679          YAHOO.log("Creating DataTable instance...", "info", "ProfilerViewer");
 680          
 681          var self = this;
 682          
 683          //Set up the JS Function DataSource, pulling data from
 684          //the Profiler.
 685          this._dataSource = new YAHOO.util.DataSource(
 686              function() {
 687                  return self._getProfilerData.call(self);    
 688              },
 689              {
 690                  responseType: YAHOO.util.DataSource.TYPE_JSARRAY,
 691                  maxCacheEntries: 0
 692              }
 693          );
 694          var ds = this._dataSource;
 695  
 696          ds.responseSchema =
 697          {
 698              fields: [ "fn", "avg", "calls", "max", "min", "total", "pct", "points"]
 699          };
 700          
 701          //Set up the DataTable.
 702          var formatTimeValue = function(elCell, oRecord, oColumn, oData) {
 703              var a = (oData === Math.floor(oData)) ? oData : (Math.round(oData*1000))/1000;
 704              elCell.innerHTML = a + " " + PV.STRINGS.millisecondsAbbrev;
 705          };
 706  
 707          var formatPercent = function(elCell, oRecord, oColumn, oData) {
 708              var a = (oData === Math.floor(oData)) ? oData : (Math.round(oData*100))/100;
 709              elCell.innerHTML = a + "%";
 710          };
 711          
 712          var a = YAHOO.widget.DataTable.CLASS_ASC;
 713          var d = YAHOO.widget.DataTable.CLASS_DESC;
 714          var c = PV.STRINGS.colHeads;
 715          var f = formatTimeValue;
 716          
 717          var cols = [
 718              {key:"fn", sortable:true, label: c.fn[0],
 719                  sortOptions: {defaultDir:a}, 
 720                  resizeable: (YAHOO.util.DragDrop) ? true : false,
 721                  minWidth:c.fn[1]},
 722              {key:"calls", sortable:true, label: c.calls[0],
 723                  sortOptions: {defaultDir:d},
 724                  width:c.calls[1]},
 725              {key:"avg", sortable:true, label: c.avg[0],
 726                  sortOptions: {defaultDir:d},
 727                  formatter:f,
 728                  width:c.avg[1]},
 729              {key:"min", sortable:true, label: c.min[0],
 730                  sortOptions: {defaultDir:a},
 731                  formatter:f,
 732                  width:c.min[1]}, 
 733              {key:"max", sortable:true, label: c.max[0],
 734                  sortOptions: {defaultDir:d},
 735                  formatter:f,
 736                  width:c.max[1]},
 737              {key:"total", sortable:true, label: c.total[0],
 738                  sortOptions: {defaultDir:d},
 739                  formatter:f,
 740                  width:c.total[1]},
 741              {key:"pct", sortable:true, label: c.pct[0],
 742                  sortOptions: {defaultDir:d}, 
 743                  formatter:formatPercent,
 744                  width:c.pct[1]}
 745          ];
 746  
 747          this._dataTable = new YAHOO.widget.DataTable(this._tableEl, cols, ds, {
 748              scrollable:true,
 749              height:this.get("tableHeight"),
 750              initialRequest:null,
 751              sortedBy: {
 752                  key: "total",
 753                  dir: YAHOO.widget.DataTable.CLASS_DESC
 754              }
 755          });
 756          var dt = this._dataTable;
 757  
 758          //Wire up DataTable events to drive the rest of the UI.
 759          dt.subscribe("sortedByChange", this._sortedByChange, this, true);
 760          dt.subscribe("renderEvent", this._dataTableRenderHandler, this, true);
 761          dt.subscribe("initEvent", this._dataTableRenderHandler, this, true);
 762          Event.on(this._tableEl.getElementsByTagName("th"), "click", this._thClickHandler, this, true);
 763          YAHOO.log("DataTable initialized.", "info", "ProfilerViewer");
 764      };
 765          
 766      /**
 767       * Proxy the sort event in DataTable into the ProfilerViewer
 768       * attribute.
 769       * @method _sortedByChange
 770       * @private
 771       **/
 772      proto._sortedByChange = function(o) {
 773          if(o.newValue && o.newValue.key) {
 774              YAHOO.log("Relaying DataTable sortedBy value change; new key: " + o.newValue.key + "; new direction: " + o.newValue.dir + ".", "info", "ProfilerViewer");
 775              this.set("sortedBy", {key: o.newValue.key, dir:o.newValue.dir});
 776          }
 777      };
 778      
 779      /**
 780       * Proxy the render event in DataTable into the ProfilerViewer
 781       * attribute.
 782       * @method _dataTableRenderHandler
 783       * @private
 784       **/
 785      proto._dataTableRenderHandler = function(o) {
 786          YAHOO.log("DataTable's render event has fired.", "info", "ProfilerViewer");
 787          this._setBusyState(false);
 788      };
 789      
 790      /**
 791       * Event handler for clicks on the DataTable's sortable column
 792       * heads.
 793       * @method _thClickHandler
 794       * @private
 795       **/
 796      proto._thClickHandler = function(o) {
 797          YAHOO.log("DataTable's header row was clicked for sorting.", "info", "ProfilerViewer");
 798          this._setBusyState(true);
 799      };
 800  
 801      /**
 802       * Refresh DataTable, getting new data from Profiler.
 803       * @method _refreshDataTable
 804       * @private
 805       **/
 806      proto._refreshDataTable = function(args) {
 807          YAHOO.log("Beginning to refresh DataTable contents...", "info", "ProfilerViewer");
 808          var dt = this._dataTable;
 809          dt.getDataSource().sendRequest("", dt.onDataReturnInitializeTable, dt);
 810          YAHOO.log("DataTable refresh complete.", "info", "ProfilerViewer");
 811      };
 812  
 813      /**
 814       * Refresh chart, getting new data from table.
 815       * @method _refreshChart
 816       * @private
 817       **/
 818      proto._refreshChart = function() {
 819          YAHOO.log("Beginning to refresh Chart contents...", "info", "ProfilerViewer");
 820          
 821          switch (this.get("sortedBy").key) {
 822              case "fn":
 823                  /*Keep the same data on the chart, but force update to 
 824                    reflect new sort order on function/method name: */
 825                  this._chart.set("dataSource", this._chart.get("dataSource"));
 826                  /*no further action necessary; chart redraws*/
 827                  return;
 828              case "calls":
 829                  /*Null out the xAxis formatting before redrawing chart.*/
 830                  this._chart.set("xAxis", this._chartAxisDefinitionPlain);
 831                  break;
 832              case "pct":
 833                  this._chart.set("xAxis", this._chartAxisDefinitionPercent);
 834                  break;
 835              default:
 836                  /*Set the default xAxis; redraw legend; set the new series definition.*/
 837                  this._chart.set("xAxis", this._chartAxisDefinitionTime);
 838                  break;
 839          }
 840          
 841          this._drawChartLegend();
 842          this._chart.set("series", this._getSeriesDef(this.get("sortedBy").key));
 843  
 844          YAHOO.log("Chart refresh complete.", "info", "ProfilerViewer");
 845      };
 846      
 847      /**
 848       * Get data for the Chart from DataTable recordset
 849       * @method _getChartData
 850       * @private
 851       */
 852      proto._getChartData = function() {
 853          YAHOO.log("Getting data for chart from function DataSource.", "info", "ProfilerViewer");
 854          //var records = this._getProfilerData();
 855          var records = this._dataTable.getRecordSet().getRecords(0, this.get("maxChartFunctions"));
 856          var arr = [];
 857          for (var i = 0, j = records.length; i<j; i++) {
 858              arr.push(records[i].getData());    
 859          }
 860          YAHOO.log("Returning data to Chart: " + YAHOO.lang.dump(arr), "info", "ProfilerViewer");
 861          return arr;
 862      };
 863      
 864      /**
 865       * Build series definition based on current configuration attributes.
 866       * @method _getSeriesDef
 867       * @private
 868       */
 869      proto._getSeriesDef = function(field) {
 870          var sd = this.get("chartSeriesDefinitions")[field];
 871          var arr = [];
 872          for(var i = 0, j = sd.group.length; i<j; i++) {
 873              var c = this.get("chartSeriesDefinitions")[sd.group[i]];
 874              arr.push(
 875                  {displayName:c.displayName,
 876                   xField:c.xField,
 877                   style: {color:c.style.color, size:c.style.size}
 878                  }
 879              );
 880          }
 881          
 882          YAHOO.log("Returning new series definition to chart: " + YAHOO.lang.dump(arr), "info", "ProfilerViewer");
 883          return arr;
 884      };
 885      
 886      /**
 887       * Set up the Chart.
 888       * @method _initChart
 889       * @private
 890       */
 891      proto._initChart = function() {
 892          YAHOO.log("Initializing chart...", "info", "ProfilerViewer");
 893          
 894          this._sizeChartCanvas();
 895          
 896          YAHOO.widget.Chart.SWFURL = this.get("swfUrl");
 897  
 898          var self = this;
 899  
 900          //Create DataSource based on records currently displayed
 901          //at the top of the sort list in the DataTable.
 902          var ds = new YAHOO.util.DataSource(
 903              //force the jsfunction DataSource to run in the scope of
 904              //the ProfilerViewer, not in the YAHOO.util.DataSource scope:
 905              function() {
 906                  return self._getChartData.call(self);
 907              }, 
 908              {
 909                  responseType: YAHOO.util.DataSource.TYPE_JSARRAY,
 910                  maxCacheEntries: 0
 911              }
 912          );
 913  
 914          ds.responseSchema =
 915          {
 916              fields: [ "fn", "avg", "calls", "max", "min", "total", "pct" ]
 917          };
 918          
 919          ds.subscribe('responseEvent', this._sizeChartCanvas, this, true);
 920          
 921          //Set up the chart itself.
 922          this._chartAxisDefinitionTime = new YAHOO.widget.NumericAxis();
 923          this._chartAxisDefinitionTime.labelFunction = "YAHOO.widget.ProfilerViewer.timeAxisLabelFunction";
 924          
 925          this._chartAxisDefinitionPercent = new YAHOO.widget.NumericAxis();
 926          this._chartAxisDefinitionPercent.labelFunction = "YAHOO.widget.ProfilerViewer.percentAxisLabelFunction";
 927  
 928          this._chartAxisDefinitionPlain = new YAHOO.widget.NumericAxis();
 929          
 930          this._chart = new YAHOO.widget.BarChart( this._chartEl, ds,
 931          {
 932              yField: "fn",
 933              series: this._getSeriesDef(this.get("sortedBy").key),
 934              style: this.get("chartStyle"),
 935              xAxis: this._chartAxisDefinitionTime
 936          } );
 937          
 938          this._drawChartLegend();
 939          this._chartInitialized = true;
 940          this._dataTable.unsubscribe("initEvent", this._initChart, this);
 941          this._dataTable.subscribe("initEvent", this._refreshChart, this, true);
 942          
 943          YAHOO.log("Chart initialization complete.", "info", "ProfilerViewer");
 944      };
 945      
 946      /**
 947       * Set up the Chart's legend
 948       * @method _drawChartLegend
 949       * @private
 950       **/
 951      proto._drawChartLegend = function() {
 952          YAHOO.log("Drawing chart legend...", "info", "ProfilerViewer");
 953          var seriesDefs = this.get("chartSeriesDefinitions");
 954          var currentDef = seriesDefs[this.get("sortedBy").key];
 955          var l = this._chartLegendEl;
 956          l.innerHTML = "";
 957          for(var i = 0, j = currentDef.group.length; i<j; i++) {
 958              var c = seriesDefs[currentDef.group[i]];
 959              var dt = document.createElement("dt");
 960              Dom.setStyle(dt, "backgroundColor", "#" + c.style.color);
 961              var dd = document.createElement("dd");
 962              dd.innerHTML = c.displayName;
 963              l.appendChild(dt);
 964              l.appendChild(dd);
 965          }
 966      };
 967      
 968      /**
 969       * Resize the chart's canvas if based on number of records
 970       * returned from the chart's datasource.
 971       * @method _sizeChartCanvas
 972       * @private
 973       **/
 974      proto._sizeChartCanvas = function(o) {
 975          YAHOO.log("Resizing chart canvas...", "info", "ProfilerViewer");
 976          var bars = (o) ? o.response.length : this.get("maxChartFunctions");
 977          var s = (bars * 36) + 34;
 978          if (s != parseInt(this._chartElHeight, 10)) {
 979              this._chartElHeight = s;
 980              Dom.setStyle(this._chartEl, "height", s + "px");
 981          }
 982      };
 983  
 984      /**
 985       * setAttributeConfigs TabView specific properties.
 986       * @method initAttributes
 987       * @param {Object} attr Hash of initial attributes
 988       * @method initAttributes
 989       * @private
 990       */
 991      proto.initAttributes = function(attr) {
 992          YAHOO.log("Initializing attributes...", "info", "ProfilerViewer");
 993          YAHOO.widget.ProfilerViewer.superclass.initAttributes.call(this, attr);
 994          /**
 995           * The YUI Loader base path from which to pull YUI files needed
 996           * in the rendering of the ProfilerViewer canvas.  Passed directly
 997           * to YUI Loader.  Leave blank to draw files from
 998           * yui.yahooapis.com.
 999           * @attribute base
1000           * @type string
1001           * @default ""
1002           */
1003          this.setAttributeConfig('base', {
1004              value: attr.base
1005          });
1006  
1007          /**
1008           * The height of the DataTable.  The table will scroll
1009           * vertically if the content overflows the specified
1010           * height.
1011           * @attribute tableHeight
1012           * @type string
1013           * @default "15em"
1014           */
1015          this.setAttributeConfig('tableHeight', {
1016              value: attr.tableHeight || "15em",
1017              method: function(s) {
1018                  if(this._dataTable) {
1019                      this._dataTable.set("height", s);
1020                  }
1021              }
1022          });
1023          
1024          /**
1025           * The default column key to sort by.  Valid keys are: fn, calls,
1026           * avg, min, max, total.  Valid dir values are: 
1027           * YAHOO.widget.DataTable.CLASS_ASC and
1028           * YAHOO.widget.DataTable.CLASS_DESC (or their
1029           * string equivalents).
1030           * @attribute sortedBy
1031           * @type string
1032           * @default {key:"total", dir:"yui-dt-desc"}
1033           */
1034          this.setAttributeConfig('sortedBy', {
1035              value: attr.sortedBy || {key:"total", dir:"yui-dt-desc"}
1036          });
1037  
1038          /**
1039           * A filter function to use in selecting functions that will
1040           * appear in the ProfilerViewer report.  The function is passed
1041           * a function report object and should return a boolean indicating
1042           * whether that function should be included in the ProfilerViewer
1043           * display.  The argument is structured as follows:
1044           *
1045           * {
1046           *         fn: <str function name>,
1047           *        calls : <n number of calls>,
1048           *        avg : <n average call duration>,
1049           *        max: <n duration of longest call>,
1050           *        min: <n duration of shortest call>,
1051           *        total: <n total time of all calls>
1052           *        points : <array time in ms of each call>
1053           *    }
1054           *
1055           * For example, you would use the follwing filter function to 
1056           * return only functions that have been called at least once:
1057           * 
1058           *     function(o) {
1059           *        return (o.calls > 0);
1060           *    }
1061           *
1062           * @attribute filter
1063           * @type function
1064           * @default null
1065           */
1066          this.setAttributeConfig('filter', {
1067              value: attr.filter || null,
1068              validator: YAHOO.lang.isFunction
1069          });
1070  
1071          /**
1072           * The path to the YUI Charts swf file; must be a full URI
1073           * or a path relative to the page being profiled. Changes at runtime
1074           * not supported; pass this value in at instantiation.
1075           * @attribute swfUrl
1076           * @type string
1077           * @default "http://yui.yahooapis.com/2.5.0/build/charts/assets/charts.swf"
1078           */
1079          this.setAttributeConfig('swfUrl', {
1080              value: attr.swfUrl || "http://yui.yahooapis.com/2.5.0/build/charts/assets/charts.swf"
1081          });
1082  
1083          /**
1084           * The maximum number of functions to profile in the chart. The
1085           * greater the number of functions, the greater the height of the
1086           * chart canvas.
1087           * height.
1088           * @attribute maxChartFunctions
1089           * @type int
1090           * @default 6
1091           */
1092          this.setAttributeConfig('maxChartFunctions', {
1093              value: attr.maxChartFunctions || 6,
1094              method: function(s) {
1095                  if(this._rendered) {
1096                      this._sizeChartCanvas();
1097                  }
1098              },
1099              validator: YAHOO.lang.isNumber
1100          });
1101          
1102          /**
1103           * The style object that defines the chart's visual presentation.
1104           * Conforms to the style attribute passed to the Charts Control
1105           * constructor.  See Charts Control User's Guide for more information
1106           * on how to format this object.
1107           * @attribute chartStyle
1108           * @type obj
1109           * @default See JS source for default definitions.
1110           */
1111          this.setAttributeConfig('chartStyle', {
1112              value:     attr.chartStyle || {
1113                  font:
1114                      {
1115                          name: "Arial",
1116                          color: 0xeeee5c,
1117                          size: 12
1118                      },
1119                      background:
1120                      {
1121                          color: "6e6e63"
1122                      }
1123                  },
1124              method: function() {
1125                      if(this._rendered && this.get("showChart")) {
1126                          this._refreshChart();
1127                      }
1128                  }
1129          });
1130          
1131          /**
1132           * The series definition information to use when charting
1133           * specific fields on the chart.  "displayName", "xField",
1134           * and "style" members are used to construct the series
1135           * definition; the "group" member is the array of fields
1136           * that should be charted when the table is sorted by a
1137           * given field. The "displayName" string value will be
1138           * treated as markup and inserted into the DOM with innerHTML.
1139           * @attribute chartSeriesDefinitions
1140           * @type obj
1141           * @default See JS source for full default definitions.
1142           */
1143          this.setAttributeConfig('chartSeriesDefinitions', {
1144              value:     attr.chartSeriesDefinitions ||  {
1145                          total: {
1146                              displayName: PV.STRINGS.colHeads.total[0],
1147                              xField: "total",
1148                              style: {color:"4d95dd", size:20},
1149                              group: ["total"]
1150                          },
1151                          calls: {        
1152                              displayName: PV.STRINGS.colHeads.calls[0],
1153                              xField: "calls",
1154                              style: {color:"edff9f", size:20},
1155                              group: ["calls"]
1156                          },
1157                          avg: {
1158                              displayName: PV.STRINGS.colHeads.avg[0],
1159                              xField: "avg",
1160                              style: {color:"209daf", size:9},
1161                              group: ["avg", "min", "max"]
1162                          },
1163                          min: {
1164                              displayName: PV.STRINGS.colHeads.min[0],
1165                              xField: "min",
1166                              style: {color:"b6ecf4", size:9},
1167                              group: ["avg", "min", "max"]
1168                          },
1169                          max: {
1170                              displayName: PV.STRINGS.colHeads.max[0],
1171                              xField: "max",
1172                              style: {color:"29c7de", size:9},
1173                              group: ["avg", "min", "max"]
1174                          },
1175                          pct: {
1176                              displayName: PV.STRINGS.colHeads.pct[0],
1177                              xField: "pct",
1178                              style: {color:"C96EDB", size:20},
1179                              group: ["pct"]
1180                          }
1181                  },
1182              method: function() {
1183                      if(this._rendered && this.get("showChart")) {
1184                          this._refreshChart();
1185                      }
1186                  }
1187          });
1188          
1189          /**
1190           * The default visibility setting for the viewer canvas. If true,
1191           * the viewer will load all necessary files and render itself
1192           * immediately upon instantiation; otherwise, the viewer will
1193           * load only minimal resources until the user toggles visibility
1194           * via the UI.
1195           * @attribute visible
1196           * @type boolean
1197           * @default false
1198           */
1199          this.setAttributeConfig('visible', {
1200              value: attr.visible || false,
1201              validator: YAHOO.lang.isBoolean,
1202              method: function(b) {
1203                  if(b) {
1204                      this._show();
1205                  } else {
1206                      if (this._rendered) {
1207                          this._hide();
1208                      }
1209                  }
1210              }
1211          });
1212  
1213          /**
1214           * The default visibility setting for the chart.
1215           * @attribute showChart
1216           * @type boolean
1217           * @default true
1218           */
1219          this.setAttributeConfig('showChart', {
1220              value: attr.showChart || true,
1221              validator: YAHOO.lang.isBoolean,
1222              writeOnce: true
1223              
1224          });
1225          
1226          YAHOO.widget.ProfilerViewer.superclass.initAttributes.call(this, attr);
1227          
1228          YAHOO.log("Attributes initialized.", "info", "ProfilerViewer");
1229      };
1230      
1231  })();
1232  
1233  YAHOO.register("profilerviewer", YAHOO.widget.ProfilerViewer, {version: "2.9.0", build: "2800"});
1234  
1235  }, '2.9.0' ,{"requires": ["yui2-skin-sam-profilerviewer", "yui2-yuiloader", "yui2-dom", "yui2-event", "yui2-element", "yui2-profiler"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1