TimelineDecorations.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * Copyright (C) 2013 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  14. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  15. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  17. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  23. * THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. WebInspector.TimelineDecorations = function()
  26. {
  27. WebInspector.Object.call(this);
  28. this._element = document.createElement("div");
  29. this._element.className = WebInspector.TimelineDecorations.StyleClassName;
  30. this._headerElement = document.createElement("div");
  31. this._headerElement.className = WebInspector.TimelineDecorations.HeaderElementStyleClassName;
  32. this._element.appendChild(this._headerElement);
  33. this._markersElement = document.createElement("div");
  34. this._markersElement.className = WebInspector.TimelineDecorations.EventMarkersElementStyleClassName
  35. this._element.appendChild(this._markersElement);
  36. this.clear();
  37. }
  38. WebInspector.TimelineDecorations.StyleClassName = "timeline-decorations";
  39. WebInspector.TimelineDecorations.HeaderElementStyleClassName = "header";
  40. WebInspector.TimelineDecorations.DividerElementStyleClassName = "divider";
  41. WebInspector.TimelineDecorations.DividerLabelElementStyleClassName = "label";
  42. WebInspector.TimelineDecorations.EventMarkersElementStyleClassName = "event-markers";
  43. WebInspector.TimelineDecorations.EventMarkerTooltipElementStyleClassName = "event-marker-tooltip";
  44. WebInspector.TimelineDecorations.BaseEventMarkerElementStyleClassName = "event-marker";
  45. WebInspector.TimelineDecorations.prototype = {
  46. constructor: WebInspector.TimelineDecorations,
  47. // Public
  48. get element()
  49. {
  50. return this._element;
  51. },
  52. get headerElement()
  53. {
  54. return this._headerElement
  55. },
  56. clear: function()
  57. {
  58. this._eventMarkers = [];
  59. this._markersElement.removeChildren();
  60. },
  61. updateHeaderTimes: function(boundarySpan, leftPadding, rightPadding, force)
  62. {
  63. if (!this.isShowingHeaderDividers())
  64. return;
  65. if (isNaN(boundarySpan))
  66. return;
  67. leftPadding = leftPadding || 0;
  68. rightPadding = rightPadding || 0;
  69. var clientWidth = this._headerElement.clientWidth;
  70. var leftVisibleEdge = leftPadding;
  71. var rightVisibleEdge = clientWidth - rightPadding;
  72. var visibleWidth = rightVisibleEdge - leftVisibleEdge;
  73. if (visibleWidth <= 0)
  74. return;
  75. var dividerCount = Math.round(visibleWidth / 64);
  76. var slice = boundarySpan / dividerCount;
  77. if (!force && this._currentDividerSlice === slice)
  78. return;
  79. this._currentDividerSlice = slice;
  80. var dividerElement = this._headerElement.firstChild;
  81. for (var i = 0; i <= dividerCount; ++i) {
  82. if (!dividerElement) {
  83. dividerElement = document.createElement("div");
  84. dividerElement.className = WebInspector.TimelineDecorations.DividerElementStyleClassName;
  85. this._headerElement.appendChild(dividerElement);
  86. var labelElement = document.createElement("div");
  87. labelElement.className = WebInspector.TimelineDecorations.DividerLabelElementStyleClassName;
  88. dividerElement._labelElement = labelElement;
  89. dividerElement.appendChild(labelElement);
  90. }
  91. var left = visibleWidth * (i / dividerCount);
  92. var totalLeft = left + leftVisibleEdge;
  93. var fractionLeft = totalLeft / clientWidth;
  94. var percentLeft = 100 * fractionLeft;
  95. var time = fractionLeft * boundarySpan;
  96. var currentPercentLeft = parseFloat(dividerElement.style.left);
  97. if (isNaN(currentPercentLeft) || Math.abs(currentPercentLeft - percentLeft) >= 0.1)
  98. dividerElement.style.left = percentLeft + "%";
  99. dividerElement._labelElement.textContent = isNaN(slice) ? "" : Number.secondsToString(time);
  100. dividerElement = dividerElement.nextSibling;
  101. }
  102. // Remove extra dividers.
  103. while (dividerElement) {
  104. var nextDividerElement = dividerElement.nextSibling;
  105. this._headerElement.removeChild(dividerElement);
  106. dividerElement = nextDividerElement;
  107. }
  108. },
  109. updateEventMarkers: function(minimumBoundary, maximumBoundary)
  110. {
  111. this._markersElement.removeChildren();
  112. if (!this._eventMarkers.length)
  113. return;
  114. var boundarySpan = maximumBoundary - minimumBoundary;
  115. if (isNaN(boundarySpan))
  116. return;
  117. function toolTipForEventMarker(eventMarker, time)
  118. {
  119. switch (eventMarker.type) {
  120. case WebInspector.TimelineEventMarker.Type.LoadEvent:
  121. return WebInspector.UIString("Load event fired at %s").format(Number.secondsToString(time));
  122. case WebInspector.TimelineEventMarker.Type.DOMContentEvent:
  123. return WebInspector.UIString("DOMContent event fired at %s").format(Number.secondsToString(time));
  124. case WebInspector.TimelineEventMarker.Type.TimeStamp:
  125. return WebInspector.UIString("Timestamp marker at %s").format(Number.secondsToString(time));
  126. default:
  127. console.assert(false);
  128. return "";
  129. }
  130. }
  131. for (var i = 0; i < this._eventMarkers.length; ++i) {
  132. var eventMarker = this._eventMarkers[i];
  133. if (eventMarker.timestamp < minimumBoundary || eventMarker.timestamp > maximumBoundary)
  134. continue;
  135. var time = eventMarker.timestamp - minimumBoundary;
  136. var percentLeft = (100 * time) / boundarySpan;
  137. var tooltipElement = document.createElement("div");
  138. tooltipElement.className = WebInspector.TimelineDecorations.EventMarkerTooltipElementStyleClassName;
  139. tooltipElement.title = toolTipForEventMarker(eventMarker, time);
  140. tooltipElement.style.left = percentLeft + "%";
  141. var markerElement = document.createElement("div");
  142. markerElement.className = WebInspector.TimelineDecorations.BaseEventMarkerElementStyleClassName;
  143. markerElement.classList.add(eventMarker.type);
  144. markerElement.style.left = percentLeft + "%";
  145. this._markersElement.appendChild(markerElement);
  146. this._markersElement.appendChild(tooltipElement);
  147. }
  148. },
  149. isShowingHeaderDividers: function()
  150. {
  151. return !this._headerElement.classList.contains("hidden");
  152. },
  153. showHeaderDividers: function()
  154. {
  155. this._headerElement.classList.remove("hidden");
  156. },
  157. hideHeaderDividers: function()
  158. {
  159. this._headerElement.classList.add("hidden");
  160. },
  161. addTimelineEventMarker: function(eventMarker)
  162. {
  163. this._eventMarkers.push(eventMarker);
  164. },
  165. }
  166. WebInspector.TimelineDecorations.prototype.__proto__ = WebInspector.Object.prototype;