##// END OF EJS Templates
hgweb: add format javascript function...
Alexander Plavin -
r19739:5bdc179e default
parent child Browse files
Show More
@@ -1,300 +1,306
1 1 // mercurial.js - JavaScript utility functions
2 2 //
3 3 // Rendering of branch DAGs on the client side
4 4 // Display of elapsed time
5 5 // Show or hide diffstat
6 6 //
7 7 // Copyright 2008 Dirkjan Ochtman <dirkjan AT ochtman DOT nl>
8 8 // Copyright 2006 Alexander Schremmer <alex AT alexanderweb DOT de>
9 9 //
10 10 // derived from code written by Scott James Remnant <scott@ubuntu.com>
11 11 // Copyright 2005 Canonical Ltd.
12 12 //
13 13 // This software may be used and distributed according to the terms
14 14 // of the GNU General Public License, incorporated herein by reference.
15 15
16 16 var colors = [
17 17 [ 1.0, 0.0, 0.0 ],
18 18 [ 1.0, 1.0, 0.0 ],
19 19 [ 0.0, 1.0, 0.0 ],
20 20 [ 0.0, 1.0, 1.0 ],
21 21 [ 0.0, 0.0, 1.0 ],
22 22 [ 1.0, 0.0, 1.0 ]
23 23 ];
24 24
25 25 function Graph() {
26 26
27 27 this.canvas = document.getElementById('graph');
28 28 if (window.G_vmlCanvasManager) this.canvas = window.G_vmlCanvasManager.initElement(this.canvas);
29 29 this.ctx = this.canvas.getContext('2d');
30 30 this.ctx.strokeStyle = 'rgb(0, 0, 0)';
31 31 this.ctx.fillStyle = 'rgb(0, 0, 0)';
32 32 this.cur = [0, 0];
33 33 this.line_width = 3;
34 34 this.bg = [0, 4];
35 35 this.cell = [2, 0];
36 36 this.columns = 0;
37 37 this.revlink = '';
38 38
39 39 this.scale = function(height) {
40 40 this.bg_height = height;
41 41 this.box_size = Math.floor(this.bg_height / 1.2);
42 42 this.cell_height = this.box_size;
43 43 }
44 44
45 45 function colorPart(num) {
46 46 num *= 255
47 47 num = num < 0 ? 0 : num;
48 48 num = num > 255 ? 255 : num;
49 49 var digits = Math.round(num).toString(16);
50 50 if (num < 16) {
51 51 return '0' + digits;
52 52 } else {
53 53 return digits;
54 54 }
55 55 }
56 56
57 57 this.setColor = function(color, bg, fg) {
58 58
59 59 // Set the colour.
60 60 //
61 61 // If color is a string, expect an hexadecimal RGB
62 62 // value and apply it unchanged. If color is a number,
63 63 // pick a distinct colour based on an internal wheel;
64 64 // the bg parameter provides the value that should be
65 65 // assigned to the 'zero' colours and the fg parameter
66 66 // provides the multiplier that should be applied to
67 67 // the foreground colours.
68 68 var s;
69 69 if(typeof color == "string") {
70 70 s = "#" + color;
71 71 } else { //typeof color == "number"
72 72 color %= colors.length;
73 73 var red = (colors[color][0] * fg) || bg;
74 74 var green = (colors[color][1] * fg) || bg;
75 75 var blue = (colors[color][2] * fg) || bg;
76 76 red = Math.round(red * 255);
77 77 green = Math.round(green * 255);
78 78 blue = Math.round(blue * 255);
79 79 s = 'rgb(' + red + ', ' + green + ', ' + blue + ')';
80 80 }
81 81 this.ctx.strokeStyle = s;
82 82 this.ctx.fillStyle = s;
83 83 return s;
84 84
85 85 }
86 86
87 87 this.edge = function(x0, y0, x1, y1, color, width) {
88 88
89 89 this.setColor(color, 0.0, 0.65);
90 90 if(width >= 0)
91 91 this.ctx.lineWidth = width;
92 92 this.ctx.beginPath();
93 93 this.ctx.moveTo(x0, y0);
94 94 this.ctx.lineTo(x1, y1);
95 95 this.ctx.stroke();
96 96
97 97 }
98 98
99 99 this.render = function(data) {
100 100
101 101 var backgrounds = '';
102 102 var nodedata = '';
103 103
104 104 for (var i in data) {
105 105
106 106 var parity = i % 2;
107 107 this.cell[1] += this.bg_height;
108 108 this.bg[1] += this.bg_height;
109 109
110 110 var cur = data[i];
111 111 var node = cur[1];
112 112 var edges = cur[2];
113 113 var fold = false;
114 114
115 115 var prevWidth = this.ctx.lineWidth;
116 116 for (var j in edges) {
117 117
118 118 line = edges[j];
119 119 start = line[0];
120 120 end = line[1];
121 121 color = line[2];
122 122 var width = line[3];
123 123 if(width < 0)
124 124 width = prevWidth;
125 125 var branchcolor = line[4];
126 126 if(branchcolor)
127 127 color = branchcolor;
128 128
129 129 if (end > this.columns || start > this.columns) {
130 130 this.columns += 1;
131 131 }
132 132
133 133 if (start == this.columns && start > end) {
134 134 var fold = true;
135 135 }
136 136
137 137 x0 = this.cell[0] + this.box_size * start + this.box_size / 2;
138 138 y0 = this.bg[1] - this.bg_height / 2;
139 139 x1 = this.cell[0] + this.box_size * end + this.box_size / 2;
140 140 y1 = this.bg[1] + this.bg_height / 2;
141 141
142 142 this.edge(x0, y0, x1, y1, color, width);
143 143
144 144 }
145 145 this.ctx.lineWidth = prevWidth;
146 146
147 147 // Draw the revision node in the right column
148 148
149 149 column = node[0]
150 150 color = node[1]
151 151
152 152 radius = this.box_size / 8;
153 153 x = this.cell[0] + this.box_size * column + this.box_size / 2;
154 154 y = this.bg[1] - this.bg_height / 2;
155 155 var add = this.vertex(x, y, color, parity, cur);
156 156 backgrounds += add[0];
157 157 nodedata += add[1];
158 158
159 159 if (fold) this.columns -= 1;
160 160
161 161 }
162 162
163 163 document.getElementById('nodebgs').innerHTML += backgrounds;
164 164 document.getElementById('graphnodes').innerHTML += nodedata;
165 165
166 166 }
167 167
168 168 }
169 169
170 170
171 171 process_dates = (function(document, RegExp, Math, isNaN, Date, _false, _true){
172 172
173 173 // derived from code from mercurial/templatefilter.py
174 174
175 175 var scales = {
176 176 'year': 365 * 24 * 60 * 60,
177 177 'month': 30 * 24 * 60 * 60,
178 178 'week': 7 * 24 * 60 * 60,
179 179 'day': 24 * 60 * 60,
180 180 'hour': 60 * 60,
181 181 'minute': 60,
182 182 'second': 1
183 183 };
184 184
185 185 function format(count, string){
186 186 var ret = count + ' ' + string;
187 187 if (count > 1){
188 188 ret = ret + 's';
189 189 }
190 190 return ret;
191 191 }
192 192
193 193 function shortdate(date){
194 194 var ret = date.getFullYear() + '-';
195 195 // getMonth() gives a 0-11 result
196 196 var month = date.getMonth() + 1;
197 197 if (month <= 9){
198 198 ret += '0' + month;
199 199 } else {
200 200 ret += month;
201 201 }
202 202 ret += '-';
203 203 var day = date.getDate();
204 204 if (day <= 9){
205 205 ret += '0' + day;
206 206 } else {
207 207 ret += day;
208 208 }
209 209 return ret;
210 210 }
211 211
212 212 function age(datestr){
213 213 var now = new Date();
214 214 var once = new Date(datestr);
215 215 if (isNaN(once.getTime())){
216 216 // parsing error
217 217 return datestr;
218 218 }
219 219
220 220 var delta = Math.floor((now.getTime() - once.getTime()) / 1000);
221 221
222 222 var future = _false;
223 223 if (delta < 0){
224 224 future = _true;
225 225 delta = -delta;
226 226 if (delta > (30 * scales.year)){
227 227 return "in the distant future";
228 228 }
229 229 }
230 230
231 231 if (delta > (2 * scales.year)){
232 232 return shortdate(once);
233 233 }
234 234
235 235 for (unit in scales){
236 236 var s = scales[unit];
237 237 var n = Math.floor(delta / s);
238 238 if ((n >= 2) || (s == 1)){
239 239 if (future){
240 240 return format(n, unit) + ' from now';
241 241 } else {
242 242 return format(n, unit) + ' ago';
243 243 }
244 244 }
245 245 }
246 246 }
247 247
248 248 return function(){
249 249 var nodes = document.getElementsByTagName('*');
250 250 var ageclass = new RegExp('\\bage\\b');
251 251 var dateclass = new RegExp('\\bdate\\b');
252 252 for (var i=0; i<nodes.length; ++i){
253 253 var node = nodes[i];
254 254 var classes = node.className;
255 255 if (ageclass.test(classes)){
256 256 var agevalue = age(node.textContent);
257 257 if (dateclass.test(classes)){
258 258 // We want both: date + (age)
259 259 node.textContent += ' ('+agevalue+')';
260 260 } else {
261 261 node.title = node.textContent;
262 262 node.textContent = agevalue;
263 263 }
264 264 }
265 265 }
266 266 }
267 267 })(document, RegExp, Math, isNaN, Date, false, true)
268 268
269 269 function toggleDiffstat() {
270 270 var curdetails = document.getElementById('diffstatdetails').style.display;
271 271 var curexpand = curdetails == 'none' ? 'inline' : 'none';
272 272 document.getElementById('diffstatdetails').style.display = curexpand;
273 273 document.getElementById('diffstatexpand').style.display = curdetails;
274 274 }
275 275
276 276 function toggleLinewrap() {
277 277 function getLinewrap() {
278 278 var nodes = document.getElementsByClassName('sourcelines');
279 279 // if there are no such nodes, error is thrown here
280 280 return nodes[0].classList.contains('wrap');
281 281 }
282 282
283 283 function setLinewrap(enable) {
284 284 var nodes = document.getElementsByClassName('sourcelines');
285 285 for (var i = 0; i < nodes.length; i++) {
286 286 if (enable) {
287 287 nodes[i].classList.add('wrap');
288 288 } else {
289 289 nodes[i].classList.remove('wrap');
290 290 }
291 291 }
292 292
293 293 var links = document.getElementsByClassName('linewraplink');
294 294 for (var i = 0; i < links.length; i++) {
295 295 links[i].innerHTML = enable ? 'on' : 'off';
296 296 }
297 297 }
298 298
299 299 setLinewrap(!getLinewrap());
300 300 }
301
302 function format(str, replacements) {
303 return str.replace(/%(\w+)%/g, function(match, p1) {
304 return String(replacements[p1]);
305 });
306 }
General Comments 0
You need to be logged in to leave comments. Login now