123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /**
- * @file
- * Timeline panel app.
- */
- (function ($, Drupal, drupalSettings, d3) {
- 'use strict';
- Drupal.behaviors.webprofiler_timeline = {
- attach: function (context) {
- if (typeof d3 != 'undefined') {
- // data
- var data = drupalSettings.webprofiler.time.events;
- var parts = [];
- var dataL = data.length;
- var perL;
- var labelW = [];
- var rowW;
- var scalePadding;
- var endTime = parseInt(data[(dataL - 1)].endtime);
- var roundTime = Math.ceil(endTime / 1000) * 1000;
- var endScale;
- for (var j = 0; j < dataL; j++) {
- perL = data[j].periods.length;
- for (var k = 0; k < perL; k++) {
- parts.push({
- lane: j,
- category: data[j].category,
- memory: data[j].memory,
- name: data[j].name,
- start: data[j].periods[k].start,
- end: data[j].periods[k].end
- });
- }
- }
- var tooltipCtrl = function (d, i) {
- tooltip.html('<span class="tooltip__content">memory usage: ' + d.memory + '</span>' +
- '<span class="tooltip__content">' + parseInt(d.start) + 'ms ~ ' + parseInt(d.end) + 'ms</span>');
- tooltip
- .style('display', 'block')
- .style('left', (d3.event.layerX - 87) + 'px')
- .style('top', ((d.lane + 1) * 22) + 'px')
- .style('opacity', .9);
- };
- var xscale = d3.scale.linear().domain([0, roundTime]).range([0, 1000]);
- d3.select('#timeline').append('svg').attr('height', (dataL + 1) * 22 + 'px').attr('width', '100%').attr('class', 'timeline__canvas');
- // tooltips
- var tooltip = d3.select('#timeline')
- .append('div')
- .attr('class', 'tooltip');
- // Add a rectangle for every data element.
- d3.select('.timeline__canvas')
- .append('g')
- .attr('class', 'timeline__rows')
- .attr('x', 0)
- .attr('y', 0)
- .selectAll('g')
- .data(data)
- .enter()
- .append('rect')
- .attr('class', 'timeline__row')
- .attr('x', 0)
- .attr('y', function (d, i) {
- return (i * 22);
- })
- .attr('height', 22)
- .attr('width', '100%')
- .each(function () {
- rowW = this.getBoundingClientRect().width;
- });
- // scale
- var scale = d3.select('.timeline__canvas')
- .append('g')
- .attr('class', 'timeline__scale')
- .attr('id', 'timeline__scale')
- .attr('x', 0)
- .attr('y', 0)
- .selectAll('g')
- .data(data)
- .enter()
- .append('a')
- .attr('xlink:href', function (d) {
- return Drupal.webprofiler.helpers.ideLink(d.link);
- })
- .attr('class', function (d) {
- return 'timeline__label ' + d.category;
- })
- .attr('x', xscale(5))
- .attr('y', function (d, i) {
- return (((i + 1) * 22) - 5);
- });
- scale.append('title')
- .text(function (d) {
- return d.name;
- });
- scale.append('text')
- .attr('x', xscale(5))
- .attr('y', function (d, i) {
- return (((i + 1) * 22) - 5);
- })
- .text(function (d) {
- return Drupal.webprofiler.helpers.shortLink(d.name);
- })
- .each(function (d) {
- labelW.push(this.getBoundingClientRect().width);
- });
- scalePadding = Math.max.apply(null, labelW) + 10;
- scale.insert('rect', 'title')
- .attr('x', 0)
- .attr('y', function (d, i) {
- return (i * 22);
- })
- .attr('height', 22)
- .attr('stroke', 'transparent')
- .attr('strokw-width', 1)
- .attr('width', scalePadding);
- // times
- var events = d3.select('.timeline__canvas')
- .insert('g', '.timeline__scale')
- .attr('class', 'timeline__parts')
- .attr('x', 0)
- .attr('y', 0)
- .selectAll('g')
- .data(parts)
- .enter();
- events.append('rect').attr('class', function (d) {
- return 'timeline__period--' + d.category;
- })
- .attr('x', function (d) {
- return xscale(parseInt(d.start)) + scalePadding;
- })
- .attr('y', function (d) {
- return d.lane * 22;
- })
- .attr('height', 22)
- .attr('width', function (d) {
- return xscale(Math.max(parseInt(d.end - d.start), 1));
- });
- events.append('rect')
- .attr('class', function (d) {
- return 'timeline__period-trigger';
- })
- .attr('x', function (d) {
- return xscale(parseInt(d.start)) + scalePadding - 5;
- })
- .attr('y', function (d) {
- return d.lane * 22;
- })
- .attr('height', 22)
- .attr('width', function (d) {
- return xscale(Math.max(parseInt(d.end - d.start), 1)) + 11;
- })
- .on('mouseover', function (d, i) {
- tooltipCtrl(d, i);
- })
- .on('mouseout', function (d) {
- tooltip
- .style('display', 'none');
- });
- // Draw X-axis grid lines
- d3.select('.timeline__parts').insert('g', '.timeline__parts')
- .selectAll('line')
- .data(xscale.ticks(10))
- .enter()
- .append('line')
- .attr('class', 'timeline__scale--x')
- .attr('x1', xscale)
- .attr('x2', xscale)
- .attr('y1', 0)
- .attr('y2', data.length * 22)
- .attr('transform', 'translate( ' + scalePadding + ' , 0)');
- var xAxis = d3.svg.axis().scale(xscale).ticks(10).orient('bottom').tickFormat(function (d) {
- return d + ' ms';
- });
- d3.select('.timeline__parts').insert('g', '.timeline__parts')
- .attr('class', 'axis')
- .attr('transform', 'translate(' + scalePadding + ', ' + dataL * 22 + ')')
- .call(xAxis);
- endScale = xscale(endTime) - rowW - parseInt(scalePadding);
- if (parseInt(xscale(endTime)) > (rowW - parseInt(scalePadding))) {
- d3.select('.timeline__canvas')
- .call(
- d3.behavior.zoom()
- .scaleExtent([1, 1])
- .x(xscale)
- .on('zoom', function () {
- var t = d3.event.translate;
- var tx = t[0];
- tx = tx > 0 ? 0 : tx;
- tx = tx < endScale ? endScale : tx;
- d3.select('.timeline__parts').attr('transform', 'translate( ' + tx + ' , 0)');
- }));
- }
- }
- }
- };
- })(jQuery, Drupal, drupalSettings, d3);
|