~launchpad-pqm/launchpad/devel

8687.15.23 by Karl Fogel
Add the copyright header block to more files.
1
/* Copyright 2009 Canonical Ltd.  This software is licensed under the
2
 * GNU Affero General Public License version 3 (see the file LICENSE).
8391.3.7 by Edwin Grubbs
Working canvas resize and encapsulated as YUI module.
3
 *
4
 * TimelineGraph widget.
5
 *
6
 * @module timeline
7
 */
8
10785.1.2 by Brad Crittenden
Move registry JS to lp.registry namespace
9
YUI.add('lp.registry.timeline', function(Y) {
8391.3.7 by Edwin Grubbs
Working canvas resize and encapsulated as YUI module.
10
10785.1.2 by Brad Crittenden
Move registry JS to lp.registry namespace
11
var module = Y.namespace('lp.registry.timeline');
8391.3.7 by Edwin Grubbs
Working canvas resize and encapsulated as YUI module.
12
9620.1.2 by Edwin Grubbs
Custom style for obsolete series in graph. Added series.status to webservice.
13
var TIMELINE_GRAPH = 'timelinegraph';
14
var OBSOLETE_SERIES_STATUS = 'Obsolete';
8705.2.12 by Edwin Grubbs
Added tests for zooming in and out.
15
var getCN = Y.ClassNameManager.getClassName;
16
var C_ZOOM_BOX = getCN(TIMELINE_GRAPH, 'zoom-box');
17
var C_ZOOM_IN = getCN(TIMELINE_GRAPH, 'zoom-in');
18
var C_ZOOM_OUT = getCN(TIMELINE_GRAPH, 'zoom-out');
8705.2.10 by Edwin Grubbs
Made the zoom buttons appear on hover.
19
var SECOND_MOUSE_BUTTON = 2;
8391.3.7 by Edwin Grubbs
Working canvas resize and encapsulated as YUI module.
20
// px spacing and sizes.
9620.1.1 by Edwin Grubbs
Removed timeline graph dates. Show scroll bars. Compress landmarks.
21
var MARGIN_LEFT = 20;
8861.1.2 by Edwin Grubbs
Fixed top margin and tooltips. Grayed milestone. Made devfocus line thicker.
22
var MARGIN_TOP = 25;
8631.3.2 by Edwin Grubbs
Fixed legend width problem caused by line wrapping.
23
var MARGIN_BOTTOM = 10;
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
24
var MILESTONE_RADIUS = 5;
25
var RELEASE_RADIUS = 5;
26
var ARROW_HEIGHT = 10;
27
var ARROW_WIDTH = 15;
8391.3.7 by Edwin Grubbs
Working canvas resize and encapsulated as YUI module.
28
// Defines angle of vertical timeline.
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
29
var ANGLE_DEGREES = 84;
30
var ANGLE_RADIANS = ANGLE_DEGREES / 180 * Math.PI;
31
var ANGLE_TANGENT = Math.tan(ANGLE_RADIANS);
8391.3.7 by Edwin Grubbs
Working canvas resize and encapsulated as YUI module.
32
// Font size in em's.
8391.3.45 by Edwin Grubbs
Upper cased constants.
33
var FONT_SIZE = 1;
8391.3.7 by Edwin Grubbs
Working canvas resize and encapsulated as YUI module.
34
// Colors.
8391.3.45 by Edwin Grubbs
Upper cased constants.
35
var LINE_COLOR = 'darkgreen';
9620.1.2 by Edwin Grubbs
Custom style for obsolete series in graph. Added series.status to webservice.
36
var OBSOLETE_SERIES_COLOR = '#777777';
8861.1.2 by Edwin Grubbs
Fixed top margin and tooltips. Grayed milestone. Made devfocus line thicker.
37
var MILESTONE_LINE_COLOR = 'darkgray';
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
38
var MILESTONE_FILL_COLOR = 'white';
8391.3.45 by Edwin Grubbs
Upper cased constants.
39
var RELEASE_COLOR = 'black';
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
40
var ARROW_COLOR = LINE_COLOR;
8391.3.23 by Edwin Grubbs
Fixed height canvas with clipping for text labels.
41
// Zoom level (increase/decrease 10%)
8391.3.45 by Edwin Grubbs
Upper cased constants.
42
var ZOOM_JUMPS = 1.1;
8391.3.1 by Edwin Grubbs
Added series-diagram.js.
43
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
44
/**
45
 * Draw lines between a list of points.
46
 *
47
 * @method draw_line
48
 * @protected
49
 */
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
50
var draw_line = function(canvas_context, points, fill) {
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
51
    canvas_context.beginPath();
9620.1.9 by Edwin Grubbs
Fixed most review issues.
52
    canvas_context.moveTo(points[0].x, points[0].y);
9620.1.10 by Edwin Grubbs
Fixed errors.
53
    Y.each(points.slice(1), function(point, i) {
54
        canvas_context.lineTo(point.x, point.y);
55
    });
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
56
    // Draw!
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
57
    if (fill === true) {
58
        canvas_context.fill();
59
    } else {
60
        canvas_context.stroke();
61
    }
62
};
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
63
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
64
/**
65
 * A single x and y coordinate.
66
 *
67
 * @class Position
68
 * @constructor
69
 */
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
70
Position = function(x, y) {
71
    this.x = x;
72
    this.y = y;
73
};
74
8391.3.36 by Edwin Grubbs
Added legend.
75
Position.prototype = {
76
    copy: function() {
77
        return new Position(this.x, this.y);
78
    }
79
};
80
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
81
/**
82
 * These objects draw a horizontal line for the series
83
 * and place the text for each milestone and release on
84
 * the line.
85
 *
86
 * @class SeriesLine
87
 * @constructor
88
 */
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
89
SeriesLine = function(timeline_graph, series, start) {
90
    this.timeline_graph = timeline_graph;
91
    this.series = series;
92
    this.start = start;
9620.1.3 by Edwin Grubbs
Added all series status names to the tooltips on the series name.
93
    var tooltip = this.series.status + ' Series';
8391.3.50 by Edwin Grubbs
Made series name bold.
94
    if (this.series.is_development_focus) {
95
        tooltip = 'Development Focus Series';
96
    }
9620.1.6 by Edwin Grubbs
Added date to end of series line when the landmark dates are hidden.
97
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
98
    this.labels = {};
9620.1.10 by Edwin Grubbs
Fixed errors.
99
    Y.each(this.series.landmarks, function(landmark, i) {
8861.1.5 by Edwin Grubbs
Fixed lint errors.
100
        var landmark_tooltip =
8861.1.2 by Edwin Grubbs
Fixed top margin and tooltips. Grayed milestone. Made devfocus line thicker.
101
            landmark.type.charAt(0).toUpperCase() + landmark.type.substr(1);
102
        if (Y.Lang.isString(landmark.code_name)) {
8861.1.5 by Edwin Grubbs
Fixed lint errors.
103
            landmark_tooltip += ': ' + landmark.code_name;
8861.1.2 by Edwin Grubbs
Fixed top margin and tooltips. Grayed milestone. Made devfocus line thicker.
104
        }
9620.1.2 by Edwin Grubbs
Custom style for obsolete series in graph. Added series.status to webservice.
105
9620.1.7 by Edwin Grubbs
Fixed tests.
106
        var cfg = {id: landmark.name};
9620.1.2 by Edwin Grubbs
Custom style for obsolete series in graph. Added series.status to webservice.
107
        if (Y.Lang.isString(this.timeline_graph.resize_frame)) {
9620.1.7 by Edwin Grubbs
Fixed tests.
108
            cfg.second_line = landmark.date;
9620.1.2 by Edwin Grubbs
Custom style for obsolete series in graph. Added series.status to webservice.
109
        }
8391.3.36 by Edwin Grubbs
Added legend.
110
        this.labels[landmark.name] = this.timeline_graph.make_label(
9620.1.2 by Edwin Grubbs
Custom style for obsolete series in graph. Added series.status to webservice.
111
            landmark.name, landmark_tooltip, landmark.uri, cfg);
9620.1.10 by Edwin Grubbs
Fixed errors.
112
    }, this);
9620.1.6 by Edwin Grubbs
Added date to end of series line when the landmark dates are hidden.
113
114
    // If the frame is not going to be resized, the dates are
115
    // not displayed under the landmarks, so a single date
116
    // is displayed at the end of the series line where it
117
    // will not increase the vertical spacing.
118
    this.series_date_label = null;
119
    if (!Y.Lang.isString(this.timeline_graph.resize_frame)) {
9620.1.10 by Edwin Grubbs
Fixed errors.
120
        for (var i=0; i < this.series.landmarks.length; i++) {
121
            var landmark = this.series.landmarks[i];
9620.1.6 by Edwin Grubbs
Added date to end of series line when the landmark dates are hidden.
122
            if (landmark.date !== null) {
123
                this.series_date_label = this.timeline_graph.make_label(
124
                    '', 'Last date in series', this.series.uri,
125
                    {second_line: landmark.date,
126
                    id: series.name + '-' + landmark.date});
127
                break;
128
            }
129
        }
130
    }
9620.1.12 by Edwin Grubbs
Added left and right series labels.
131
132
    // Center series label.
133
    var label_text = Y.Node.create('<strong/>');
134
    label_text.appendChild(document.createTextNode(series.name));
135
    this.center_series_label = this.timeline_graph.make_label(
136
        label_text, tooltip, this.series.uri,
137
        {id: series.name});
138
    // Left label.
139
    this.left_series_label = this.timeline_graph.make_label(
140
        '', tooltip, this.series.uri,
141
        {second_line: series.name, id: series.name});
142
    // Right label.
143
    this.right_series_label = this.timeline_graph.make_label(
144
        '', tooltip, this.series.uri,
145
        {second_line: series.name, id: series.name});
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
146
};
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
147
148
SeriesLine.prototype = {
149
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
150
    /**
151
     * Calculate the length of the horizontal line.
152
     *
153
     * @method get_length
154
     */
8391.3.12 by Edwin Grubbs
Added links and added handling for long milestone names.
155
    get_length: function() {
9620.1.9 by Edwin Grubbs
Fixed most review issues.
156
        // No arrow at the end of obsolete series lines.
157
        var length = 0;
158
        if (this.series.status == OBSOLETE_SERIES_STATUS) {
159
            length = this.series.landmarks.length *
160
                     this.timeline_graph.landmark_spacing;
161
        } else {
162
            length = (this.series.landmarks.length + 1) *
163
                     this.timeline_graph.landmark_spacing;
164
        }
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
165
        // Display a line stub for series without any landmarks.
9620.1.9 by Edwin Grubbs
Fixed most review issues.
166
        return Math.max(length, this.timeline_graph.min_series_line_length);
8391.3.12 by Edwin Grubbs
Added links and added handling for long milestone names.
167
    },
168
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
169
    /**
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
170
     * Calculate the vertical spacing of the horizontal lines based on twice
171
     * the height of the series name, plus the height of the landmark text,
172
     * which may or may not have a second line for the date.
173
     *
174
     * @method get_y_spacing()
175
     */
176
    get_y_spacing: function() {
177
        var max_y = 0;
9620.1.10 by Edwin Grubbs
Fixed errors.
178
        Y.each(this.series.landmarks, function(landmark, i) {
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
179
            var label = this.labels[landmark.name];
180
            max_y = Math.max(label.get('offsetHeight'));
9620.1.10 by Edwin Grubbs
Fixed errors.
181
        }, this);
9620.1.9 by Edwin Grubbs
Fixed most review issues.
182
        return max_y + (2 * RELEASE_RADIUS) +
9620.1.12 by Edwin Grubbs
Added left and right series labels.
183
               this.center_series_label.get('offsetHeight');
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
184
    },
185
186
187
    /**
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
188
     * The main method which is called by the ProjectLine.draw()
189
     * method for each series in the project.
190
     *
191
     * @method draw
192
     */
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
193
    draw: function() {
194
        // Horizontal line.
8391.3.35 by Edwin Grubbs
Fixed display for projects with zero milestones or releases.
195
        var context = this.timeline_graph.canvas_context;
8391.3.12 by Edwin Grubbs
Added links and added handling for long milestone names.
196
        var stop = new Position(
197
            this.start.x + this.get_length(),
198
            this.start.y);
8391.3.16 by Edwin Grubbs
Made development focus line red. Fixed order of series. Fixed bugs related to series without milestones or releases.
199
9620.1.2 by Edwin Grubbs
Custom style for obsolete series in graph. Added series.status to webservice.
200
        var thickness, offset;
201
        // Draw a line of various thicknesses as a rectangle.
202
        if (this.series.status == OBSOLETE_SERIES_STATUS) {
203
            thickness = 2;
204
            offset = -1;
205
            context.fillStyle = OBSOLETE_SERIES_COLOR;
206
        } else if (this.series.is_development_focus) {
207
            thickness = 4;
208
            offset = -2;
209
            context.fillStyle = LINE_COLOR;
210
        } else {
211
            thickness = 1;
212
            offset = 0;
213
            context.fillStyle = LINE_COLOR;
214
        }
215
        context.fillRect(
216
            this.start.x,
217
            this.start.y + offset,
218
            stop.x - this.start.x,
219
            stop.y - this.start.y + thickness);
8391.3.21 by Edwin Grubbs
Draw a thick line for the development focus.
220
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
221
        // Arrow at end of series line.
9620.1.2 by Edwin Grubbs
Custom style for obsolete series in graph. Added series.status to webservice.
222
        if (this.series.status != OBSOLETE_SERIES_STATUS) {
223
            this.timeline_graph.make_landmark(stop, 'arrow');
224
        }
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
225
9620.1.12 by Edwin Grubbs
Added left and right series labels.
226
        // Center series label.
227
        var center_position = new Position(
8391.3.20 by Edwin Grubbs
Added series name label.
228
            this.start.x + (this.get_length() / 2),
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
229
            this.start.y - RELEASE_RADIUS);
8391.3.36 by Edwin Grubbs
Added legend.
230
        this.timeline_graph.place_label(
9620.1.12 by Edwin Grubbs
Added left and right series labels.
231
            center_position, this.center_series_label, 'center', 'above');
232
233
9620.1.13 by Edwin Grubbs
Added comment.
234
        // Only show the left and right series labels if the
235
        // series line is wider than the viewport (iframe).
9620.1.15 by Edwin Grubbs
Calculate line width with respect to the graph scale.
236
        var line_width = this.get_length() * this.timeline_graph.graph_scale;
237
        if (line_width < Y.DOM.winWidth()) {
9620.1.12 by Edwin Grubbs
Added left and right series labels.
238
            this.left_series_label.setStyle('display', 'none');
239
            this.right_series_label.setStyle('display', 'none');
240
        } else {
241
            this.left_series_label.setStyle('display', 'block');
242
            this.right_series_label.setStyle('display', 'block');
9620.1.13 by Edwin Grubbs
Added comment.
243
9620.1.12 by Edwin Grubbs
Added left and right series labels.
244
            // Left series label.
245
            var left_position = new Position(
246
                this.start.x + 10,
247
                this.start.y - RELEASE_RADIUS);
248
            this.timeline_graph.place_label(
249
                left_position, this.left_series_label, 'right', 'above');
250
251
            // Right series label.
252
            var right_position = new Position(
253
                this.start.x + this.get_length(),
254
                this.start.y - RELEASE_RADIUS);
255
            this.timeline_graph.place_label(
256
                right_position, this.right_series_label, 'left', 'above');
257
        }
8391.3.20 by Edwin Grubbs
Added series name label.
258
9620.1.6 by Edwin Grubbs
Added date to end of series line when the landmark dates are hidden.
259
        if (this.series_date_label !== null) {
9620.1.12 by Edwin Grubbs
Added left and right series labels.
260
            var label_position = new Position(
9620.1.9 by Edwin Grubbs
Fixed most review issues.
261
                stop.x + (ARROW_WIDTH / 2), this.start.y);
9620.1.6 by Edwin Grubbs
Added date to end of series line when the landmark dates are hidden.
262
            this.timeline_graph.place_label(
263
                label_position, this.series_date_label, 'right', 'middle');
264
        }
265
8391.3.20 by Edwin Grubbs
Added series name label.
266
        // Landmark labels.
9620.1.10 by Edwin Grubbs
Fixed errors.
267
        Y.each(this.series.landmarks, function(landmark, i) {
8391.3.18 by Edwin Grubbs
Corrected milestone display order and hid timeline graph if there are no milestones or releases.
268
            // The newest milestones are at the beginning, and
269
            // they need to be placed at the end of the horizontal
270
            // line.
271
            var position_index = this.series.landmarks.length - i;
8391.3.11 by Edwin Grubbs
Fixed margins.
272
            var landmark_position = new Position(
8861.1.6 by Edwin Grubbs
Fixed some lint errors.
273
                this.start.x +
274
                (position_index * this.timeline_graph.landmark_spacing),
8391.3.11 by Edwin Grubbs
Fixed margins.
275
                this.start.y);
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
276
8391.3.36 by Edwin Grubbs
Added legend.
277
            this.timeline_graph.make_landmark(
278
                landmark_position, landmark.type);
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
279
            // We use the RELEASE_RADIUS to space both the milestone and the
8391.3.36 by Edwin Grubbs
Added legend.
280
            // release labels, so that the labels line up.
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
281
            var landmark_label_position = new Position(
282
                landmark_position.x, landmark_position.y + RELEASE_RADIUS);
8391.3.36 by Edwin Grubbs
Added legend.
283
            this.timeline_graph.place_label(
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
284
                landmark_label_position, this.labels[landmark.name],
285
                'center', 'below');
9620.1.10 by Edwin Grubbs
Fixed errors.
286
        }, this);
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
287
    }
288
};
289
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
290
/**
291
 * Class which draws the slanted vertical line representing
292
 * the project timeline and which instantiates the SeriesLine
293
 * objects which draw the horizontal lines.
294
 *
295
 * @class ProjectLine
296
 * @constructor
297
 */
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
298
ProjectLine = function(timeline_graph, timeline) {
9620.1.10 by Edwin Grubbs
Fixed errors.
299
    if (timeline.length === 0) {
9620.1.9 by Edwin Grubbs
Fixed most review issues.
300
        throw new Error("The timeline array is empty.");
301
    }
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
302
    this.timeline_graph = timeline_graph;
303
    this.timeline = timeline;
8391.3.12 by Edwin Grubbs
Added links and added handling for long milestone names.
304
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
305
    this.series_lines = [];
306
    this.initSeries();
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
307
308
    this.start = this.series_lines[0].start.copy();
309
    var last_series = this.series_lines[this.series_lines.length-1];
310
    this.stop = last_series.start.copy();
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
311
};
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
312
313
ProjectLine.prototype = {
314
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
315
    /**
316
     * Instantiate each SeriesLine object and place it at the
317
     * correct point on the slanted vertical line. The series aren't
318
     * actuall drawn yet, since we need to loop through these objects
319
     * to calculate the landmark_spacing.
320
     *
321
     * @method initSeries
322
     */
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
323
    initSeries: function() {
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
324
        var current = new Position(0, MARGIN_TOP);
325
        var reversed_timeline = this.timeline.slice().reverse();
9620.1.10 by Edwin Grubbs
Fixed errors.
326
        Y.each(reversed_timeline, function(series, i) {
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
327
            var series_line = new SeriesLine(
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
328
                this.timeline_graph, series, current.copy());
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
329
            this.series_lines.push(series_line);
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
330
331
            var height = series_line.get_y_spacing();
332
            current.x -= height / ANGLE_TANGENT;
333
            current.y += height;
9620.1.10 by Edwin Grubbs
Fixed errors.
334
        }, this);
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
335
336
        if (current.x < MARGIN_LEFT) {
337
            var shift_x = -current.x + MARGIN_LEFT;
9620.1.10 by Edwin Grubbs
Fixed errors.
338
            Y.each(this.series_lines, function(series_line, i) {
339
                series_line.start.x += shift_x;
340
            }, this);
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
341
        }
342
    },
343
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
344
    /**
345
     * Calculate the width based on the number of landmarks
346
     * and half the length of the label for the last landmark
347
     * on the right.
348
     *
349
     * @method get_width
350
     */
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
351
    get_width: function() {
352
        var max_x = 0;
9620.1.10 by Edwin Grubbs
Fixed errors.
353
        Y.each(this.series_lines, function(series_line, i) {
354
            var landmarks = series_line.series.landmarks;
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
355
            var text_beyond_last_landmark;
356
            if (landmarks.length === 0) {
8391.3.35 by Edwin Grubbs
Fixed display for projects with zero milestones or releases.
357
                // Even a project with zero landmarks needs to have
358
                // its one empty series displayed.
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
359
                text_beyond_last_landmark = 0;
8391.3.35 by Edwin Grubbs
Fixed display for projects with zero milestones or releases.
360
            } else {
361
                var landmark = landmarks[landmarks.length-1];
362
                var label = this.series_lines[i].labels[landmark.name];
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
363
                text_beyond_last_landmark = label.get('offsetWidth') / 2;
8391.3.16 by Edwin Grubbs
Made development focus line red. Fixed order of series. Fixed bugs related to series without milestones or releases.
364
            }
8391.3.11 by Edwin Grubbs
Fixed margins.
365
            var series_width =
8861.1.6 by Edwin Grubbs
Fixed some lint errors.
366
                this.series_lines[i].start.x +
367
                this.series_lines[i].get_length() +
368
                text_beyond_last_landmark;
8391.3.11 by Edwin Grubbs
Fixed margins.
369
            max_x = Math.max(max_x, series_width);
9620.1.10 by Edwin Grubbs
Fixed errors.
370
        }, this);
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
371
        return max_x;
372
    },
373
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
374
    /**
9620.1.9 by Edwin Grubbs
Fixed most review issues.
375
     * Calculate the height based on the stop.y value, which
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
376
     * is based on the number of series. It also adds the
377
     * distance for the labels below the bottom series line.
378
     *
8391.3.44 by Edwin Grubbs
Added comments.
379
     * @method get_height
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
380
     */
8391.3.11 by Edwin Grubbs
Fixed margins.
381
    get_height: function() {
382
        // Grab any landmark label to get its height.
8631.3.1 by Edwin Grubbs
Added timeline graph to +series page.
383
        var bottom_label_height = 0;
384
        var last_series = this.series_lines[this.series_lines.length-1];
385
        for (var key in last_series.labels) {
9620.1.10 by Edwin Grubbs
Fixed errors.
386
            if (last_series.labels.hasOwnProperty(key)) {
387
                var label = last_series.labels[key];
388
                bottom_label_height = Math.max(
389
                    bottom_label_height, label.get('offsetHeight'));
390
            }
8631.3.1 by Edwin Grubbs
Added timeline graph to +series page.
391
        }
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
392
        return this.stop.y + bottom_label_height + RELEASE_RADIUS;
8391.3.11 by Edwin Grubbs
Fixed margins.
393
    },
394
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
395
    /**
396
     * Draw the project line and have each SeriesLine object draw itself.
397
     *
398
     * @method draw
399
     */
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
400
    draw: function() {
8391.3.35 by Edwin Grubbs
Fixed display for projects with zero milestones or releases.
401
        var context = this.timeline_graph.canvas_context;
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
402
        context.strokeStyle = LINE_COLOR;
8391.3.35 by Edwin Grubbs
Fixed display for projects with zero milestones or releases.
403
        draw_line(context, [this.start, this.stop]);
9620.1.10 by Edwin Grubbs
Fixed errors.
404
        Y.each(this.series_lines, function(series_line, i) {
405
            series_line.draw();
406
        }, this);
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
407
    }
408
};
409
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
410
/**
8391.3.53 by Edwin Grubbs
Added windmill test.
411
 * The TimelineGraph widget will display an HTML5 canvas of a
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
412
 * project's series, milestones, and releases.
413
 *
414
 * @class TimelineGraph
415
 * @constructor
416
 * @extends Widget
417
 */
418
module.TimelineGraph = function() {
419
    module.TimelineGraph.superclass.constructor.apply(this, arguments);
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
420
};
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
421
8705.2.10 by Edwin Grubbs
Made the zoom buttons appear on hover.
422
module.TimelineGraph.NAME = TIMELINE_GRAPH;
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
423
module.TimelineGraph.ATTRS = {
424
    /**
425
     * JSON data describing the timeline of series, milestones, and releases.
426
     *
427
     * @attribute timeline
428
     * @type Array
429
     */
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
430
    timeline: { value: [] }
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
431
};
432
433
Y.extend(module.TimelineGraph, Y.Widget, {
434
435
    /**
436
     * Initialize the widget.
437
     *
438
     * @method initializer
439
     * @protected
440
     */
441
    initializer: function(cfg) {
8391.3.17 by Edwin Grubbs
Reformatted.
442
        if (cfg === undefined || cfg.timeline === undefined) {
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
443
            throw new Error(
444
                "Missing timeline config argument for TimelineGraph.");
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
445
        }
8631.3.1 by Edwin Grubbs
Added timeline graph to +series page.
446
        if (cfg !== undefined && cfg.resize_frame !== undefined) {
447
            if (!Y.Lang.isString(cfg.resize_frame)) {
448
                throw new Error(
449
                    "resize_frame config argument must be a string.");
450
            }
451
            if (Y.Lang.trim(cfg.resize_frame) === '') {
452
                throw new Error("resize_frame must not be empty.");
453
            }
454
            this.resize_frame = cfg.resize_frame;
455
        }
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
456
        this.graph_scale = 1;
457
    },
458
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
459
    /**
460
     * Increase the graph scale and redraw.
461
     *
462
     * @method zoom_in
463
     */
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
464
    zoom_in: function() {
8391.3.45 by Edwin Grubbs
Upper cased constants.
465
        this.graph_scale *= ZOOM_JUMPS;
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
466
        this.syncUI();
467
    },
468
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
469
    /**
470
     * Decrease the graph scale and redraw.
471
     *
472
     * @method zoom_out
473
     */
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
474
    zoom_out: function() {
8391.3.45 by Edwin Grubbs
Upper cased constants.
475
        this.graph_scale /= ZOOM_JUMPS;
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
476
        this.syncUI();
477
    },
478
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
479
    /**
480
     * The canvas has to be recreated each time with the new size, since
481
     * WebKit browsers do not handle resizing the canvas well.
482
     *
8631.3.1 by Edwin Grubbs
Added timeline graph to +series page.
483
     * @method recreate_canvas
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
484
     */
8631.3.1 by Edwin Grubbs
Added timeline graph to +series page.
485
    recreate_canvas: function() {
9620.1.7 by Edwin Grubbs
Fixed tests.
486
        var width = Math.ceil(
487
            this.graph_scale * (this.project_line.get_width() + MARGIN_LEFT));
488
9620.1.10 by Edwin Grubbs
Fixed errors.
489
        // The get_height() method already includes the MARGIN_TOP, so that
490
        // gets multiplied by the graph_scale. Alternatively, we could have
491
        // made changes elsewhere so that MARGIN_LEFT and MARGIN_TOP are
492
        // not scaled at all.
9620.1.7 by Edwin Grubbs
Fixed tests.
493
        var height = Math.ceil(
9620.1.10 by Edwin Grubbs
Fixed errors.
494
            (this.graph_scale * this.project_line.get_height()) +
9620.1.7 by Edwin Grubbs
Fixed tests.
495
            MARGIN_BOTTOM);
496
8631.3.1 by Edwin Grubbs
Added timeline graph to +series page.
497
        if (this.canvas) {
498
            this.get('contentBox').removeChild(this.canvas);
499
        }
500
        this.canvas = Y.Node.create(
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
501
            '<canvas width="' + width + '" height="' + height + '"/>');
8631.3.1 by Edwin Grubbs
Added timeline graph to +series page.
502
        this.get('contentBox').insertBefore(
503
            this.canvas, this.get('contentBox').get('children').item(0));
504
        if (Y.Lang.isString(this.resize_frame)) {
505
            var frame = parent.document.getElementById(this.resize_frame);
506
            if (frame === null) {
507
                Y.log('Frame not found: ' + this.resize_frame);
508
            }
509
            else {
8631.3.10 by Edwin Grubbs
Fixed bug with opera resizing the iframe automatically.
510
                // Opera's offsetHeight and scrollHeight don't work as
511
                // expected, but the canvas height can be used since it is
512
                // the only element.
513
                frame.height = height;
8631.3.1 by Edwin Grubbs
Added timeline graph to +series page.
514
            }
515
        }
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
516
    },
517
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
518
    /**
519
     * Set the timeline_graph.landmark_spacing attribute, which is
520
     * used by the SeriesLine objects and is based on the width
521
     * of the longest landmark label.
522
     *
523
     * @method calculate_landmark_spacing
524
     */
8391.3.12 by Edwin Grubbs
Added links and added handling for long milestone names.
525
    calculate_landmark_spacing: function() {
526
        var max_label_width = 0;
9620.1.1 by Edwin Grubbs
Removed timeline graph dates. Show scroll bars. Compress landmarks.
527
        var series_max_label_width = 0;
9620.1.10 by Edwin Grubbs
Fixed errors.
528
        Y.each(this.project_line.series_lines, function(series_line, i) {
9620.1.1 by Edwin Grubbs
Removed timeline graph dates. Show scroll bars. Compress landmarks.
529
            series_max_label_width = Math.max(
530
                series_max_label_width,
9620.1.12 by Edwin Grubbs
Added left and right series labels.
531
                series_line.center_series_label.get('offsetWidth'));
9620.1.10 by Edwin Grubbs
Fixed errors.
532
            Y.each(series_line.labels, function(label, j) {
8391.3.23 by Edwin Grubbs
Fixed height canvas with clipping for text labels.
533
                // We have to set the font size here so that
534
                // offsetWidth will be correct.
8631.3.2 by Edwin Grubbs
Fixed legend width problem caused by line wrapping.
535
                this.set_font_size(label);
8391.3.12 by Edwin Grubbs
Added links and added handling for long milestone names.
536
                max_label_width = Math.max(
537
                    max_label_width, label.get('offsetWidth'));
9620.1.10 by Edwin Grubbs
Fixed errors.
538
            }, this);
539
        }, this);
8391.3.12 by Edwin Grubbs
Added links and added handling for long milestone names.
540
        this.landmark_spacing = max_label_width + 5;
9620.1.1 by Edwin Grubbs
Removed timeline graph dates. Show scroll bars. Compress landmarks.
541
        this.min_series_line_length = series_max_label_width + 5;
8391.3.12 by Edwin Grubbs
Added links and added handling for long milestone names.
542
    },
543
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
544
    /**
8391.3.23 by Edwin Grubbs
Fixed height canvas with clipping for text labels.
545
     * Set the font size.
546
     *
8631.3.2 by Edwin Grubbs
Fixed legend width problem caused by line wrapping.
547
     * @method set_font_size
8391.3.23 by Edwin Grubbs
Fixed height canvas with clipping for text labels.
548
     */
8631.3.2 by Edwin Grubbs
Fixed legend width problem caused by line wrapping.
549
    set_font_size: function(label) {
8391.3.23 by Edwin Grubbs
Fixed height canvas with clipping for text labels.
550
        label.setStyle(
551
            'fontSize',
8391.3.45 by Edwin Grubbs
Upper cased constants.
552
            (FONT_SIZE * this.graph_scale) + 'em');
8391.3.23 by Edwin Grubbs
Fixed height canvas with clipping for text labels.
553
    },
554
555
    /**
8391.3.33 by Edwin Grubbs
Improved auto scrolling.
556
     * This should show the most recent milestones or releases
557
     * on the development focus series.
558
     *
559
     * @method scroll_to_last_development_focus_landmark
560
     */
561
    scroll_to_last_development_focus_landmark: function(label) {
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
562
        var series_line = this.project_line.series_lines[0];
8391.3.33 by Edwin Grubbs
Improved auto scrolling.
563
        var landmark = series_line.series.landmarks[0];
8391.3.35 by Edwin Grubbs
Fixed display for projects with zero milestones or releases.
564
        if (landmark) {
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
565
            var landmark_label = series_line.labels[landmark.name];
9620.1.6 by Edwin Grubbs
Added date to end of series line when the landmark dates are hidden.
566
            var date_label_width = 0;
9620.1.8 by Edwin Grubbs
Fixed lint errors.
567
            if (series_line.series_date_label !== null) {
9620.1.6 by Edwin Grubbs
Added date to end of series line when the landmark dates are hidden.
568
                date_label_width =
569
                    series_line.series_date_label.get('offsetWidth');
570
            }
9620.1.4 by Edwin Grubbs
Allow varying spacing for series lines depending on whether each one has a date on its landmarks.
571
            var scroll_x =
9620.1.8 by Edwin Grubbs
Fixed lint errors.
572
                series_line.start.x + series_line.get_length() +
573
                ARROW_WIDTH + date_label_width -
9620.1.14 by Edwin Grubbs
Fixed js unit test.
574
                Y.DOM.winWidth();
8391.3.35 by Edwin Grubbs
Fixed display for projects with zero milestones or releases.
575
            // scrollBy is relative, so adjust it by
576
            // the current scroll position.
577
            scroll_x -= window.scrollX;
578
            window.scrollBy(scroll_x, 0);
579
        }
8391.3.33 by Edwin Grubbs
Improved auto scrolling.
580
    },
581
582
    /**
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
583
     * Draw items that do not get recreated for each zoom level.
584
     *
585
     * @method renderUI
586
     */
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
587
    renderUI: function() {
8705.2.11 by Edwin Grubbs
Removed hide_zoom_buttons option.
588
        // Opera needs the "&nbsp;" so that it doesn't collapse
589
        // the height of the <a> and push the background image
590
        // above the div.
591
        this.zoom_in_button = Y.Node.create(
592
            '<a class="bg-image"  ' +
593
            '   style="background-image: url(/@@/zoom-in);' +
594
            '          height: 14px">&nbsp;</a>');
8705.2.12 by Edwin Grubbs
Added tests for zooming in and out.
595
        this.zoom_in_button.addClass(C_ZOOM_IN);
8705.2.11 by Edwin Grubbs
Removed hide_zoom_buttons option.
596
        this.zoom_out_button = Y.Node.create(
597
            '<a class="bg-image" ' +
598
            '   style="background-image: url(/@@/zoom-out);' +
599
            '          height: 14px"></a>');
8705.2.12 by Edwin Grubbs
Added tests for zooming in and out.
600
        this.zoom_out_button.addClass(C_ZOOM_OUT);
8705.2.11 by Edwin Grubbs
Removed hide_zoom_buttons option.
601
        var zoom_box = Y.Node.create(
602
            '<div style="' +
603
            'background-color: white; position: fixed; ' +
604
            'top: 0px; left: 0px; padding-left: 2px; ' +
605
            'cursor: pointer; z-index: 100"/>');
606
        zoom_box.addClass(C_ZOOM_BOX);
607
        zoom_box.appendChild(this.zoom_in_button);
608
        zoom_box.appendChild(this.zoom_out_button);
609
        var contentBox = this.get('contentBox');
610
        contentBox.appendChild(zoom_box);
8391.3.14 by Edwin Grubbs
Added timeline to project index template.
611
        this.project_line = new ProjectLine(this, this.get('timeline'));
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
612
    },
613
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
614
    /**
615
     * Hook up UI events.
616
     *
617
     * @method bindUI
618
     */
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
619
    bindUI: function() {
8705.2.11 by Edwin Grubbs
Removed hide_zoom_buttons option.
620
        this.zoom_in_button.on('click', function() {
621
            this.zoom_in();
622
        }, this);
623
        this.zoom_out_button.on('click', function() {
624
            this.zoom_out();
625
        }, this);
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
626
    },
627
8391.3.19 by Edwin Grubbs
Added comments and short horizontal line for series without milestones or releases.
628
    /**
629
     * Redraw everything that changes at each zoom level.
630
     *
631
     * @method syncUI
632
     */
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
633
    syncUI: function() {
634
        // Resizing the canvas requires destroying the old canvas and
635
        // creating a new one due to rendering issues in WebKit.
8391.3.12 by Edwin Grubbs
Added links and added handling for long milestone names.
636
        this.calculate_landmark_spacing();
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
637
        var contentBox = this.get('contentBox');
8631.3.1 by Edwin Grubbs
Added timeline graph to +series page.
638
        this.recreate_canvas();
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
639
        var dom_canvas = Y.Node.getDOMNode(this.canvas);
640
        this.canvas_context = dom_canvas.getContext('2d');
641
642
        // Zoom in or out.
8391.3.8 by Edwin Grubbs
Simplified zoom.
643
        this.canvas_context.scale(this.graph_scale, this.graph_scale);
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
644
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
645
        this.project_line.draw();
8391.3.36 by Edwin Grubbs
Added legend.
646
    },
647
648
    /**
649
     * Create the label for each landmark, but don't place them yet,
650
     * since we need to calculate the spacing between landmarks based
651
     * on the width of the longest label text.
652
     *
653
     * @method make_label
654
     */
8631.3.5 by Edwin Grubbs
Added unit tests.
655
    make_label: function(text, tooltip, uri, cfg) {
656
        if (cfg === undefined) {
657
            cfg = {};
658
        }
8391.3.43 by Edwin Grubbs
Made middle-click work in Safari.
659
        var label = Y.Node.create(
8631.3.2 by Edwin Grubbs
Fixed legend width problem caused by line wrapping.
660
            '<div style="white-space: nowrap; text-align: center"/>');
8631.3.5 by Edwin Grubbs
Added unit tests.
661
        if (Y.Lang.isString(cfg.id)) {
662
            label.set('id', cfg.id);
663
        }
8705.2.15 by Edwin Grubbs
Removed security concerns.
664
        var text_node;
665
        if (text instanceof Y.Node || text instanceof Text) {
666
            text_node = text;
667
        } else {
668
            text_node = document.createTextNode(text);
669
        }
8391.3.36 by Edwin Grubbs
Added legend.
670
        if (uri) {
8705.2.15 by Edwin Grubbs
Removed security concerns.
671
            var link = Y.Node.create('<a/>');
672
            link.appendChild(text_node);
8391.3.42 by Edwin Grubbs
Fixed links in iframe.
673
            link.on('click', function(e) {
8391.3.43 by Edwin Grubbs
Made middle-click work in Safari.
674
                // Safari also fires the click event for the 2nd mouse button,
675
                // and we don't want to prevent that default action.
8391.3.45 by Edwin Grubbs
Upper cased constants.
676
                if (e.which != SECOND_MOUSE_BUTTON) {
8391.3.43 by Edwin Grubbs
Made middle-click work in Safari.
677
                    parent.location.href = uri;
678
                    e.preventDefault();
679
                }
8391.3.42 by Edwin Grubbs
Fixed links in iframe.
680
            });
681
            // Middle-clicking to open a new tab still works if
682
            // the href is set.
683
            link.set('href', uri);
684
            label.appendChild(link);
8391.3.36 by Edwin Grubbs
Added legend.
685
        } else {
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
686
            var span = Y.Node.create('<span/>');
8705.2.15 by Edwin Grubbs
Removed security concerns.
687
            span.appendChild(text_node);
688
            label.appendChild(span);
8391.3.36 by Edwin Grubbs
Added legend.
689
        }
690
        label.setStyle('position', 'absolute');
691
        if (tooltip) {
692
            label.set('title', tooltip);
693
        }
9620.1.2 by Edwin Grubbs
Custom style for obsolete series in graph. Added series.status to webservice.
694
        if (Y.Lang.isString(cfg.second_line)) {
8705.2.15 by Edwin Grubbs
Removed security concerns.
695
            var div = Y.Node.create(
696
                '<div style="color: #aaaaaa; font-size: 70%"/>');
697
            div.appendChild(document.createTextNode(cfg.second_line));
698
            label.appendChild(div);
8391.3.36 by Edwin Grubbs
Added legend.
699
        }
700
        this.get('contentBox').appendChild(label);
701
        return label;
702
    },
703
704
    /**
8391.3.44 by Edwin Grubbs
Added comments.
705
     * After this.landmark_spacing has been calculated,
8391.3.36 by Edwin Grubbs
Added legend.
706
     * we can place the label.
707
     *
708
     * @method place_label
709
     */
710
    place_label: function(position, label, x_align, y_align) {
711
        var graph_scale = this.graph_scale;
712
        var dom_canvas = Y.Node.getDOMNode(this.canvas);
713
714
        // Set the size here also, for any labels that are not
715
        // for landmarks, which are already set through
716
        // calculate_landmark_spacing.
8631.3.2 by Edwin Grubbs
Fixed legend width problem caused by line wrapping.
717
        this.set_font_size(label);
8391.3.36 by Edwin Grubbs
Added legend.
718
719
        // Find where the canvas is placed on the page, and
720
        // center the text under the landmark.
721
        var label_height = label.get('offsetHeight');
722
        var y_align_offset;
723
        if (y_align == 'above') {
724
            y_align_offset = -label_height;
725
        } else if (y_align == 'below') {
726
            y_align_offset = 0;
9620.1.6 by Edwin Grubbs
Added date to end of series line when the landmark dates are hidden.
727
        } else if (y_align == 'middle') {
728
            y_align_offset = -(label_height / 2);
8391.3.36 by Edwin Grubbs
Added legend.
729
        } else {
730
            throw "Invalid y_align argument: " + y_align;
731
        }
732
733
        var x_align_offset;
734
        if (x_align == 'left') {
735
            x_align_offset = -label.get('offsetWidth');
736
        } else if (x_align == 'center') {
737
            x_align_offset = -(label.get('offsetWidth') / 2);
738
        } else if (x_align == 'right') {
739
            x_align_offset = 0;
740
        } else {
741
            throw "Invalid x_align argument: " + x_align;
742
        }
743
744
        var scaled_position = new Position(
8861.1.6 by Edwin Grubbs
Fixed some lint errors.
745
            position.x * graph_scale +
746
            dom_canvas.offsetLeft + x_align_offset,
747
            position.y * graph_scale +
748
            dom_canvas.offsetTop + y_align_offset);
8391.3.36 by Edwin Grubbs
Added legend.
749
750
        label.setStyle('left', scaled_position.x + "px");
751
        label.setStyle('top', scaled_position.y + "px");
752
    },
753
754
    /**
755
     * Draw a square for milestones and a circle for releases
756
     * on the series line. Also, place the name label
757
     * underneath the landmark.
758
     *
759
     * @method make_landmark
760
     */
761
    make_landmark: function(position, type) {
762
        var context = this.canvas_context;
763
        if (type == 'milestone') {
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
764
            // Fill circle first.
765
            context.fillStyle = MILESTONE_LINE_COLOR;
766
            context.beginPath();
767
            context.arc(
768
                position.x, position.y, MILESTONE_RADIUS, 0,
769
                (Math.PI*2), true);
770
            context.fill();
771
            // Overlay the fill color in the center.
772
            context.fillStyle = MILESTONE_FILL_COLOR;
773
            context.beginPath();
774
            context.arc(
8861.1.2 by Edwin Grubbs
Fixed top margin and tooltips. Grayed milestone. Made devfocus line thicker.
775
                position.x, position.y, MILESTONE_RADIUS-2, 0,
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
776
                (Math.PI*2), true);
777
            context.fill();
8391.3.36 by Edwin Grubbs
Added legend.
778
        } else if (type == 'release') {
8391.3.45 by Edwin Grubbs
Upper cased constants.
779
            context.fillStyle = RELEASE_COLOR;
8391.3.36 by Edwin Grubbs
Added legend.
780
            context.beginPath();
781
            context.arc(
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
782
                position.x, position.y, RELEASE_RADIUS, 0,
783
                (Math.PI*2), true);
784
            context.fill();
785
        } else if (type == 'arrow') {
786
            context.fillStyle = ARROW_COLOR;
787
            var point = position.copy();
788
            // Make sure the tip of the arrow isn't blunted by the
789
            // development focus series line.
8879.4.11 by Edwin Grubbs
Fixed slightly blunted arrow in timeline graph.
790
            point.x += 3;
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
791
            var path = [point];
792
793
            point = point.copy();
794
            point.x -= ARROW_WIDTH / 2;
795
            point.y -= ARROW_HEIGHT / 2;
796
            path.push(point);
797
798
            point = point.copy();
799
            point.x += ARROW_WIDTH / 4;
800
            point.y += ARROW_HEIGHT / 2;
801
            path.push(point);
802
803
            point = point.copy();
804
            point.x -= ARROW_WIDTH / 4;
805
            point.y += ARROW_HEIGHT / 2;
806
            path.push(point);
807
808
            draw_line(context, path, true);
8391.3.38 by Edwin Grubbs
Moved legend to top. Fixed Starting Point legend.
809
        }
810
        else {
811
            throw "Unknown landmark type: " + type;
8391.3.36 by Edwin Grubbs
Added legend.
812
        }
8861.1.1 by Edwin Grubbs
Added graph arrows. Removed legend.
813
    }
8391.3.10 by Edwin Grubbs
Converted to actual YUI widget class.
814
});
8391.3.9 by Edwin Grubbs
Refactored into ProjectLine and SeriesLine objects.
815
9929.1.1 by Guilherme Salgado
merge fix from other branch, which was based on db-devel
816
}, "0.1", {"requires": ["oop", "node", "widget"]});