how_are_we_doing 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. data/app/controllers/reports_controller.rb +1 -52
  2. data/app/helpers/reports_helper.rb +30 -4
  3. data/app/models/print.rb +1 -29
  4. data/app/models/share.rb +3 -29
  5. data/app/models/total.rb +2 -21
  6. data/app/models/view.rb +1 -29
  7. data/app/views/reports/_bar_graph.html.erb +48 -0
  8. data/app/views/reports/_line_graph.html.erb +40 -0
  9. data/app/views/reports/_recent_bar_graph.html.erb +41 -0
  10. data/app/views/reports/index.html.erb +12 -22
  11. data/config/locales/en.yml +16 -0
  12. data/lib/generators/how_are_we_doing/install/install_generator.rb +1 -0
  13. data/lib/generators/how_are_we_doing/install/templates/public/images/hawd/blank.png +0 -0
  14. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/API.txt +85 -68
  15. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/FAQ.txt +0 -0
  16. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/NEWS.txt +12 -32
  17. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/PLUGINS.txt +0 -0
  18. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/README.txt +3 -3
  19. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/excanvas.js +160 -663
  20. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/excanvas.min.js +1 -1
  21. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.crosshair.js +12 -51
  22. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.image.js +0 -0
  23. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.js +509 -155
  24. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.navigate.js +0 -1
  25. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.stack.js +0 -0
  26. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.threshold.js +0 -0
  27. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.js +0 -0
  28. data/lib/generators/how_are_we_doing/install/templates/public/javascripts/how_are_we_doing.js +50 -8
  29. data/lib/how_are_we_doing/acts_as_analytical.rb +98 -0
  30. data/lib/{acts_as_printable.rb → how_are_we_doing/acts_as_printable.rb} +0 -0
  31. data/lib/{acts_as_shareable.rb → how_are_we_doing/acts_as_shareable.rb} +0 -0
  32. data/lib/{acts_as_totalable.rb → how_are_we_doing/acts_as_totalable.rb} +0 -0
  33. data/lib/{acts_as_viewable.rb → how_are_we_doing/acts_as_viewable.rb} +0 -0
  34. data/lib/how_are_we_doing/controllers/reports_helpers.rb +92 -0
  35. data/lib/how_are_we_doing/version.rb +1 -1
  36. data/lib/how_are_we_doing.rb +16 -8
  37. metadata +13 -6
@@ -15,7 +15,7 @@
15
15
 
16
16
  // Known Issues:
17
17
  //
18
- // * Patterns only support repeat.
18
+ // * Patterns are not implemented.
19
19
  // * Radial gradient are not implemented. The VML version of these look very
20
20
  // different from the canvas one.
21
21
  // * Clipping paths are not implemented.
@@ -29,7 +29,6 @@
29
29
  // or use Box Sizing Behavior from WebFX
30
30
  // (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
31
31
  // * Non uniform scaling does not correctly scale strokes.
32
- // * Filling very large shapes (above 5000 points) is buggy.
33
32
  // * Optimize. There is always room for speed improvements.
34
33
 
35
34
  // Only add this code if we do not already have a canvas implementation
@@ -84,35 +83,6 @@ if (!document.createElement('canvas').getContext) {
84
83
  };
85
84
  }
86
85
 
87
- function encodeHtmlAttribute(s) {
88
- return String(s).replace(/&/g, '&').replace(/"/g, '"');
89
- }
90
-
91
- function addNamespacesAndStylesheet(doc) {
92
- // create xmlns
93
- if (!doc.namespaces['g_vml_']) {
94
- doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',
95
- '#default#VML');
96
-
97
- }
98
- if (!doc.namespaces['g_o_']) {
99
- doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',
100
- '#default#VML');
101
- }
102
-
103
- // Setup default CSS. Only add one style sheet per document
104
- if (!doc.styleSheets['ex_canvas_']) {
105
- var ss = doc.createStyleSheet();
106
- ss.owningElement.id = 'ex_canvas_';
107
- ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
108
- // default size is 300x150 in Gecko and Opera
109
- 'text-align:left;width:300px;height:150px}';
110
- }
111
- }
112
-
113
- // Add namespaces and stylesheet at startup.
114
- addNamespacesAndStylesheet(document);
115
-
116
86
  var G_vmlCanvasManager_ = {
117
87
  init: function(opt_doc) {
118
88
  if (/MSIE/.test(navigator.userAgent) && !window.opera) {
@@ -125,6 +95,29 @@ if (!document.createElement('canvas').getContext) {
125
95
  },
126
96
 
127
97
  init_: function(doc) {
98
+ // create xmlns
99
+ if (!doc.namespaces['g_vml_']) {
100
+ doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',
101
+ '#default#VML');
102
+
103
+ }
104
+ if (!doc.namespaces['g_o_']) {
105
+ doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',
106
+ '#default#VML');
107
+ }
108
+
109
+ // Setup default CSS. Only add one style sheet per document
110
+ if (!doc.styleSheets['ex_canvas_']) {
111
+ var ss = doc.createStyleSheet();
112
+ ss.owningElement.id = 'ex_canvas_';
113
+ ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
114
+ // default size is 300x150 in Gecko and Opera
115
+ 'text-align:left;width:300px;height:150px}' +
116
+ 'g_vml_\\:*{behavior:url(#default#VML)}' +
117
+ 'g_o_\\:*{behavior:url(#default#VML)}';
118
+
119
+ }
120
+
128
121
  // find all canvas elements
129
122
  var els = doc.getElementsByTagName('canvas');
130
123
  for (var i = 0; i < els.length; i++) {
@@ -142,10 +135,8 @@ if (!document.createElement('canvas').getContext) {
142
135
  */
143
136
  initElement: function(el) {
144
137
  if (!el.getContext) {
145
- el.getContext = getContext;
146
138
 
147
- // Add namespaces and stylesheet to document of the element.
148
- addNamespacesAndStylesheet(el.ownerDocument);
139
+ el.getContext = getContext;
149
140
 
150
141
  // Remove fallback content. There is no way to hide text nodes so we
151
142
  // just remove all childNodes. We could hide all elements and remove
@@ -182,15 +173,12 @@ if (!document.createElement('canvas').getContext) {
182
173
 
183
174
  switch (e.propertyName) {
184
175
  case 'width':
185
- el.getContext().clearRect();
186
176
  el.style.width = el.attributes.width.nodeValue + 'px';
187
- // In IE8 this does not trigger onresize.
188
- el.firstChild.style.width = el.clientWidth + 'px';
177
+ el.getContext().clearRect();
189
178
  break;
190
179
  case 'height':
191
- el.getContext().clearRect();
192
180
  el.style.height = el.attributes.height.nodeValue + 'px';
193
- el.firstChild.style.height = el.clientHeight + 'px';
181
+ el.getContext().clearRect();
194
182
  break;
195
183
  }
196
184
  }
@@ -206,10 +194,10 @@ if (!document.createElement('canvas').getContext) {
206
194
  G_vmlCanvasManager_.init();
207
195
 
208
196
  // precompute "00" to "FF"
209
- var decToHex = [];
197
+ var dec2hex = [];
210
198
  for (var i = 0; i < 16; i++) {
211
199
  for (var j = 0; j < 16; j++) {
212
- decToHex[i * 16 + j] = i.toString(16) + j.toString(16);
200
+ dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
213
201
  }
214
202
  }
215
203
 
@@ -250,304 +238,33 @@ if (!document.createElement('canvas').getContext) {
250
238
  o2.shadowOffsetY = o1.shadowOffsetY;
251
239
  o2.strokeStyle = o1.strokeStyle;
252
240
  o2.globalAlpha = o1.globalAlpha;
253
- o2.font = o1.font;
254
- o2.textAlign = o1.textAlign;
255
- o2.textBaseline = o1.textBaseline;
256
241
  o2.arcScaleX_ = o1.arcScaleX_;
257
242
  o2.arcScaleY_ = o1.arcScaleY_;
258
243
  o2.lineScale_ = o1.lineScale_;
259
244
  }
260
245
 
261
- var colorData = {
262
- aliceblue: '#F0F8FF',
263
- antiquewhite: '#FAEBD7',
264
- aquamarine: '#7FFFD4',
265
- azure: '#F0FFFF',
266
- beige: '#F5F5DC',
267
- bisque: '#FFE4C4',
268
- black: '#000000',
269
- blanchedalmond: '#FFEBCD',
270
- blueviolet: '#8A2BE2',
271
- brown: '#A52A2A',
272
- burlywood: '#DEB887',
273
- cadetblue: '#5F9EA0',
274
- chartreuse: '#7FFF00',
275
- chocolate: '#D2691E',
276
- coral: '#FF7F50',
277
- cornflowerblue: '#6495ED',
278
- cornsilk: '#FFF8DC',
279
- crimson: '#DC143C',
280
- cyan: '#00FFFF',
281
- darkblue: '#00008B',
282
- darkcyan: '#008B8B',
283
- darkgoldenrod: '#B8860B',
284
- darkgray: '#A9A9A9',
285
- darkgreen: '#006400',
286
- darkgrey: '#A9A9A9',
287
- darkkhaki: '#BDB76B',
288
- darkmagenta: '#8B008B',
289
- darkolivegreen: '#556B2F',
290
- darkorange: '#FF8C00',
291
- darkorchid: '#9932CC',
292
- darkred: '#8B0000',
293
- darksalmon: '#E9967A',
294
- darkseagreen: '#8FBC8F',
295
- darkslateblue: '#483D8B',
296
- darkslategray: '#2F4F4F',
297
- darkslategrey: '#2F4F4F',
298
- darkturquoise: '#00CED1',
299
- darkviolet: '#9400D3',
300
- deeppink: '#FF1493',
301
- deepskyblue: '#00BFFF',
302
- dimgray: '#696969',
303
- dimgrey: '#696969',
304
- dodgerblue: '#1E90FF',
305
- firebrick: '#B22222',
306
- floralwhite: '#FFFAF0',
307
- forestgreen: '#228B22',
308
- gainsboro: '#DCDCDC',
309
- ghostwhite: '#F8F8FF',
310
- gold: '#FFD700',
311
- goldenrod: '#DAA520',
312
- grey: '#808080',
313
- greenyellow: '#ADFF2F',
314
- honeydew: '#F0FFF0',
315
- hotpink: '#FF69B4',
316
- indianred: '#CD5C5C',
317
- indigo: '#4B0082',
318
- ivory: '#FFFFF0',
319
- khaki: '#F0E68C',
320
- lavender: '#E6E6FA',
321
- lavenderblush: '#FFF0F5',
322
- lawngreen: '#7CFC00',
323
- lemonchiffon: '#FFFACD',
324
- lightblue: '#ADD8E6',
325
- lightcoral: '#F08080',
326
- lightcyan: '#E0FFFF',
327
- lightgoldenrodyellow: '#FAFAD2',
328
- lightgreen: '#90EE90',
329
- lightgrey: '#D3D3D3',
330
- lightpink: '#FFB6C1',
331
- lightsalmon: '#FFA07A',
332
- lightseagreen: '#20B2AA',
333
- lightskyblue: '#87CEFA',
334
- lightslategray: '#778899',
335
- lightslategrey: '#778899',
336
- lightsteelblue: '#B0C4DE',
337
- lightyellow: '#FFFFE0',
338
- limegreen: '#32CD32',
339
- linen: '#FAF0E6',
340
- magenta: '#FF00FF',
341
- mediumaquamarine: '#66CDAA',
342
- mediumblue: '#0000CD',
343
- mediumorchid: '#BA55D3',
344
- mediumpurple: '#9370DB',
345
- mediumseagreen: '#3CB371',
346
- mediumslateblue: '#7B68EE',
347
- mediumspringgreen: '#00FA9A',
348
- mediumturquoise: '#48D1CC',
349
- mediumvioletred: '#C71585',
350
- midnightblue: '#191970',
351
- mintcream: '#F5FFFA',
352
- mistyrose: '#FFE4E1',
353
- moccasin: '#FFE4B5',
354
- navajowhite: '#FFDEAD',
355
- oldlace: '#FDF5E6',
356
- olivedrab: '#6B8E23',
357
- orange: '#FFA500',
358
- orangered: '#FF4500',
359
- orchid: '#DA70D6',
360
- palegoldenrod: '#EEE8AA',
361
- palegreen: '#98FB98',
362
- paleturquoise: '#AFEEEE',
363
- palevioletred: '#DB7093',
364
- papayawhip: '#FFEFD5',
365
- peachpuff: '#FFDAB9',
366
- peru: '#CD853F',
367
- pink: '#FFC0CB',
368
- plum: '#DDA0DD',
369
- powderblue: '#B0E0E6',
370
- rosybrown: '#BC8F8F',
371
- royalblue: '#4169E1',
372
- saddlebrown: '#8B4513',
373
- salmon: '#FA8072',
374
- sandybrown: '#F4A460',
375
- seagreen: '#2E8B57',
376
- seashell: '#FFF5EE',
377
- sienna: '#A0522D',
378
- skyblue: '#87CEEB',
379
- slateblue: '#6A5ACD',
380
- slategray: '#708090',
381
- slategrey: '#708090',
382
- snow: '#FFFAFA',
383
- springgreen: '#00FF7F',
384
- steelblue: '#4682B4',
385
- tan: '#D2B48C',
386
- thistle: '#D8BFD8',
387
- tomato: '#FF6347',
388
- turquoise: '#40E0D0',
389
- violet: '#EE82EE',
390
- wheat: '#F5DEB3',
391
- whitesmoke: '#F5F5F5',
392
- yellowgreen: '#9ACD32'
393
- };
394
-
395
-
396
- function getRgbHslContent(styleString) {
397
- var start = styleString.indexOf('(', 3);
398
- var end = styleString.indexOf(')', start + 1);
399
- var parts = styleString.substring(start + 1, end).split(',');
400
- // add alpha if needed
401
- if (parts.length == 4 && styleString.substr(3, 1) == 'a') {
402
- alpha = Number(parts[3]);
403
- } else {
404
- parts[3] = 1;
405
- }
406
- return parts;
407
- }
408
-
409
- function percent(s) {
410
- return parseFloat(s) / 100;
411
- }
412
-
413
- function clamp(v, min, max) {
414
- return Math.min(max, Math.max(min, v));
415
- }
416
-
417
- function hslToRgb(parts){
418
- var r, g, b;
419
- h = parseFloat(parts[0]) / 360 % 360;
420
- if (h < 0)
421
- h++;
422
- s = clamp(percent(parts[1]), 0, 1);
423
- l = clamp(percent(parts[2]), 0, 1);
424
- if (s == 0) {
425
- r = g = b = l; // achromatic
426
- } else {
427
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
428
- var p = 2 * l - q;
429
- r = hueToRgb(p, q, h + 1 / 3);
430
- g = hueToRgb(p, q, h);
431
- b = hueToRgb(p, q, h - 1 / 3);
432
- }
433
-
434
- return '#' + decToHex[Math.floor(r * 255)] +
435
- decToHex[Math.floor(g * 255)] +
436
- decToHex[Math.floor(b * 255)];
437
- }
438
-
439
- function hueToRgb(m1, m2, h) {
440
- if (h < 0)
441
- h++;
442
- if (h > 1)
443
- h--;
444
-
445
- if (6 * h < 1)
446
- return m1 + (m2 - m1) * 6 * h;
447
- else if (2 * h < 1)
448
- return m2;
449
- else if (3 * h < 2)
450
- return m1 + (m2 - m1) * (2 / 3 - h) * 6;
451
- else
452
- return m1;
453
- }
454
-
455
246
  function processStyle(styleString) {
456
247
  var str, alpha = 1;
457
248
 
458
249
  styleString = String(styleString);
459
- if (styleString.charAt(0) == '#') {
460
- str = styleString;
461
- } else if (/^rgb/.test(styleString)) {
462
- var parts = getRgbHslContent(styleString);
463
- var str = '#', n;
250
+ if (styleString.substring(0, 3) == 'rgb') {
251
+ var start = styleString.indexOf('(', 3);
252
+ var end = styleString.indexOf(')', start + 1);
253
+ var guts = styleString.substring(start + 1, end).split(',');
254
+
255
+ str = '#';
464
256
  for (var i = 0; i < 3; i++) {
465
- if (parts[i].indexOf('%') != -1) {
466
- n = Math.floor(percent(parts[i]) * 255);
467
- } else {
468
- n = Number(parts[i]);
469
- }
470
- str += decToHex[clamp(n, 0, 255)];
257
+ str += dec2hex[Number(guts[i])];
471
258
  }
472
- alpha = parts[3];
473
- } else if (/^hsl/.test(styleString)) {
474
- var parts = getRgbHslContent(styleString);
475
- str = hslToRgb(parts);
476
- alpha = parts[3];
477
- } else {
478
- str = colorData[styleString] || styleString;
479
- }
480
- return {color: str, alpha: alpha};
481
- }
482
-
483
- var DEFAULT_STYLE = {
484
- style: 'normal',
485
- variant: 'normal',
486
- weight: 'normal',
487
- size: 10,
488
- family: 'sans-serif'
489
- };
490
-
491
- // Internal text style cache
492
- var fontStyleCache = {};
493
-
494
- function processFontStyle(styleString) {
495
- if (fontStyleCache[styleString]) {
496
- return fontStyleCache[styleString];
497
- }
498
-
499
- var el = document.createElement('div');
500
- var style = el.style;
501
- try {
502
- style.font = styleString;
503
- } catch (ex) {
504
- // Ignore failures to set to invalid font.
505
- }
506
259
 
507
- return fontStyleCache[styleString] = {
508
- style: style.fontStyle || DEFAULT_STYLE.style,
509
- variant: style.fontVariant || DEFAULT_STYLE.variant,
510
- weight: style.fontWeight || DEFAULT_STYLE.weight,
511
- size: style.fontSize || DEFAULT_STYLE.size,
512
- family: style.fontFamily || DEFAULT_STYLE.family
513
- };
514
- }
515
-
516
- function getComputedStyle(style, element) {
517
- var computedStyle = {};
518
-
519
- for (var p in style) {
520
- computedStyle[p] = style[p];
521
- }
522
-
523
- // Compute the size
524
- var canvasFontSize = parseFloat(element.currentStyle.fontSize),
525
- fontSize = parseFloat(style.size);
526
-
527
- if (typeof style.size == 'number') {
528
- computedStyle.size = style.size;
529
- } else if (style.size.indexOf('px') != -1) {
530
- computedStyle.size = fontSize;
531
- } else if (style.size.indexOf('em') != -1) {
532
- computedStyle.size = canvasFontSize * fontSize;
533
- } else if(style.size.indexOf('%') != -1) {
534
- computedStyle.size = (canvasFontSize / 100) * fontSize;
535
- } else if (style.size.indexOf('pt') != -1) {
536
- computedStyle.size = fontSize / .75;
260
+ if (guts.length == 4 && styleString.substr(3, 1) == 'a') {
261
+ alpha = guts[3];
262
+ }
537
263
  } else {
538
- computedStyle.size = canvasFontSize;
264
+ str = styleString;
539
265
  }
540
266
 
541
- // Different scaling between normal text and VML text. This was found using
542
- // trial and error to get the same size as non VML text.
543
- computedStyle.size *= 0.981;
544
-
545
- return computedStyle;
546
- }
547
-
548
- function buildStyle(style) {
549
- return style.style + ' ' + style.variant + ' ' + style.weight + ' ' +
550
- style.size + 'px ' + style.family;
267
+ return {color: str, alpha: alpha};
551
268
  }
552
269
 
553
270
  function processLineCap(lineCap) {
@@ -584,9 +301,6 @@ if (!document.createElement('canvas').getContext) {
584
301
  this.lineCap = 'butt';
585
302
  this.miterLimit = Z * 1;
586
303
  this.globalAlpha = 1;
587
- this.font = '10px sans-serif';
588
- this.textAlign = 'left';
589
- this.textBaseline = 'alphabetic';
590
304
  this.canvas = surfaceElement;
591
305
 
592
306
  var el = surfaceElement.ownerDocument.createElement('div');
@@ -604,10 +318,6 @@ if (!document.createElement('canvas').getContext) {
604
318
 
605
319
  var contextPrototype = CanvasRenderingContext2D_.prototype;
606
320
  contextPrototype.clearRect = function() {
607
- if (this.textMeasureEl_) {
608
- this.textMeasureEl_.removeNode(true);
609
- this.textMeasureEl_ = null;
610
- }
611
321
  this.element_.innerHTML = '';
612
322
  };
613
323
 
@@ -829,8 +539,7 @@ if (!document.createElement('canvas').getContext) {
829
539
  // The following check doesn't account for skews (which don't exist
830
540
  // in the canvas spec (yet) anyway.
831
541
 
832
- if (this.m_[0][0] != 1 || this.m_[0][1] ||
833
- this.m_[1][1] != 1 || this.m_[1][0]) {
542
+ if (this.m_[0][0] != 1 || this.m_[0][1]) {
834
543
  var filter = [];
835
544
 
836
545
  // Note the 12/21 reversal
@@ -853,8 +562,7 @@ if (!document.createElement('canvas').getContext) {
853
562
 
854
563
  vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),
855
564
  'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',
856
- filter.join(''), ", sizingmethod='clip');");
857
-
565
+ filter.join(''), ", sizingmethod='clip');")
858
566
  } else {
859
567
  vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');
860
568
  }
@@ -862,7 +570,7 @@ if (!document.createElement('canvas').getContext) {
862
570
  vmlStr.push(' ">' ,
863
571
  '<g_vml_:image src="', image.src, '"',
864
572
  ' style="width:', Z * dw, 'px;',
865
- ' height:', Z * dh, 'px"',
573
+ ' height:', Z * dh, 'px;"',
866
574
  ' cropleft="', sx / w, '"',
867
575
  ' croptop="', sy / h, '"',
868
576
  ' cropright="', (w - sx - sw) / w, '"',
@@ -870,138 +578,108 @@ if (!document.createElement('canvas').getContext) {
870
578
  ' />',
871
579
  '</g_vml_:group>');
872
580
 
873
- this.element_.insertAdjacentHTML('BeforeEnd', vmlStr.join(''));
581
+ this.element_.insertAdjacentHTML('BeforeEnd',
582
+ vmlStr.join(''));
874
583
  };
875
584
 
876
585
  contextPrototype.stroke = function(aFill) {
586
+ var lineStr = [];
587
+ var lineOpen = false;
588
+ var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
589
+ var color = a.color;
590
+ var opacity = a.alpha * this.globalAlpha;
591
+
877
592
  var W = 10;
878
593
  var H = 10;
879
- // Divide the shape into chunks if it's too long because IE has a limit
880
- // somewhere for how long a VML shape can be. This simple division does
881
- // not work with fills, only strokes, unfortunately.
882
- var chunkSize = 5000;
883
594
 
595
+ lineStr.push('<g_vml_:shape',
596
+ ' filled="', !!aFill, '"',
597
+ ' style="position:absolute;width:', W, 'px;height:', H, 'px;"',
598
+ ' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
599
+ ' stroked="', !aFill, '"',
600
+ ' path="');
601
+
602
+ var newSeq = false;
884
603
  var min = {x: null, y: null};
885
604
  var max = {x: null, y: null};
886
605
 
887
- for (var j = 0; j < this.currentPath_.length; j += chunkSize) {
888
- var lineStr = [];
889
- var lineOpen = false;
606
+ for (var i = 0; i < this.currentPath_.length; i++) {
607
+ var p = this.currentPath_[i];
608
+ var c;
609
+
610
+ switch (p.type) {
611
+ case 'moveTo':
612
+ c = p;
613
+ lineStr.push(' m ', mr(p.x), ',', mr(p.y));
614
+ break;
615
+ case 'lineTo':
616
+ lineStr.push(' l ', mr(p.x), ',', mr(p.y));
617
+ break;
618
+ case 'close':
619
+ lineStr.push(' x ');
620
+ p = null;
621
+ break;
622
+ case 'bezierCurveTo':
623
+ lineStr.push(' c ',
624
+ mr(p.cp1x), ',', mr(p.cp1y), ',',
625
+ mr(p.cp2x), ',', mr(p.cp2y), ',',
626
+ mr(p.x), ',', mr(p.y));
627
+ break;
628
+ case 'at':
629
+ case 'wa':
630
+ lineStr.push(' ', p.type, ' ',
631
+ mr(p.x - this.arcScaleX_ * p.radius), ',',
632
+ mr(p.y - this.arcScaleY_ * p.radius), ' ',
633
+ mr(p.x + this.arcScaleX_ * p.radius), ',',
634
+ mr(p.y + this.arcScaleY_ * p.radius), ' ',
635
+ mr(p.xStart), ',', mr(p.yStart), ' ',
636
+ mr(p.xEnd), ',', mr(p.yEnd));
637
+ break;
638
+ }
890
639
 
891
- lineStr.push('<g_vml_:shape',
892
- ' filled="', !!aFill, '"',
893
- ' style="position:absolute;width:', W, 'px;height:', H, 'px;"',
894
- ' coordorigin="0,0"',
895
- ' coordsize="', Z * W, ',', Z * H, '"',
896
- ' stroked="', !aFill, '"',
897
- ' path="');
898
640
 
899
- var newSeq = false;
641
+ // TODO: Following is broken for curves due to
642
+ // move to proper paths.
900
643
 
901
- for (var i = j; i < Math.min(j + chunkSize, this.currentPath_.length); i++) {
902
- if (i % chunkSize == 0 && i > 0) { // move into position for next chunk
903
- lineStr.push(' m ', mr(this.currentPath_[i-1].x), ',', mr(this.currentPath_[i-1].y));
644
+ // Figure out dimensions so we can do gradient fills
645
+ // properly
646
+ if (p) {
647
+ if (min.x == null || p.x < min.x) {
648
+ min.x = p.x;
904
649
  }
905
-
906
- var p = this.currentPath_[i];
907
- var c;
908
-
909
- switch (p.type) {
910
- case 'moveTo':
911
- c = p;
912
- lineStr.push(' m ', mr(p.x), ',', mr(p.y));
913
- break;
914
- case 'lineTo':
915
- lineStr.push(' l ', mr(p.x), ',', mr(p.y));
916
- break;
917
- case 'close':
918
- lineStr.push(' x ');
919
- p = null;
920
- break;
921
- case 'bezierCurveTo':
922
- lineStr.push(' c ',
923
- mr(p.cp1x), ',', mr(p.cp1y), ',',
924
- mr(p.cp2x), ',', mr(p.cp2y), ',',
925
- mr(p.x), ',', mr(p.y));
926
- break;
927
- case 'at':
928
- case 'wa':
929
- lineStr.push(' ', p.type, ' ',
930
- mr(p.x - this.arcScaleX_ * p.radius), ',',
931
- mr(p.y - this.arcScaleY_ * p.radius), ' ',
932
- mr(p.x + this.arcScaleX_ * p.radius), ',',
933
- mr(p.y + this.arcScaleY_ * p.radius), ' ',
934
- mr(p.xStart), ',', mr(p.yStart), ' ',
935
- mr(p.xEnd), ',', mr(p.yEnd));
936
- break;
650
+ if (max.x == null || p.x > max.x) {
651
+ max.x = p.x;
937
652
  }
938
-
939
-
940
- // TODO: Following is broken for curves due to
941
- // move to proper paths.
942
-
943
- // Figure out dimensions so we can do gradient fills
944
- // properly
945
- if (p) {
946
- if (min.x == null || p.x < min.x) {
947
- min.x = p.x;
948
- }
949
- if (max.x == null || p.x > max.x) {
950
- max.x = p.x;
951
- }
952
- if (min.y == null || p.y < min.y) {
953
- min.y = p.y;
954
- }
955
- if (max.y == null || p.y > max.y) {
956
- max.y = p.y;
957
- }
653
+ if (min.y == null || p.y < min.y) {
654
+ min.y = p.y;
655
+ }
656
+ if (max.y == null || p.y > max.y) {
657
+ max.y = p.y;
958
658
  }
959
659
  }
960
- lineStr.push(' ">');
961
-
962
- if (!aFill) {
963
- appendStroke(this, lineStr);
964
- } else {
965
- appendFill(this, lineStr, min, max);
966
- }
967
-
968
- lineStr.push('</g_vml_:shape>');
969
-
970
- this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
971
660
  }
972
- };
661
+ lineStr.push(' ">');
973
662
 
974
- function appendStroke(ctx, lineStr) {
975
- var a = processStyle(ctx.strokeStyle);
976
- var color = a.color;
977
- var opacity = a.alpha * ctx.globalAlpha;
978
- var lineWidth = ctx.lineScale_ * ctx.lineWidth;
979
-
980
- // VML cannot correctly render a line if the width is less than 1px.
981
- // In that case, we dilute the color to make the line look thinner.
982
- if (lineWidth < 1) {
983
- opacity *= lineWidth;
984
- }
663
+ if (!aFill) {
664
+ var lineWidth = this.lineScale_ * this.lineWidth;
985
665
 
986
- lineStr.push(
987
- '<g_vml_:stroke',
988
- ' opacity="', opacity, '"',
989
- ' joinstyle="', ctx.lineJoin, '"',
990
- ' miterlimit="', ctx.miterLimit, '"',
991
- ' endcap="', processLineCap(ctx.lineCap), '"',
992
- ' weight="', lineWidth, 'px"',
993
- ' color="', color, '" />'
994
- );
995
- }
666
+ // VML cannot correctly render a line if the width is less than 1px.
667
+ // In that case, we dilute the color to make the line look thinner.
668
+ if (lineWidth < 1) {
669
+ opacity *= lineWidth;
670
+ }
996
671
 
997
- function appendFill(ctx, lineStr, min, max) {
998
- var fillStyle = ctx.fillStyle;
999
- var arcScaleX = ctx.arcScaleX_;
1000
- var arcScaleY = ctx.arcScaleY_;
1001
- var width = max.x - min.x;
1002
- var height = max.y - min.y;
1003
- if (fillStyle instanceof CanvasGradient_) {
1004
- // TODO: Gradients transformed with the transformation matrix.
672
+ lineStr.push(
673
+ '<g_vml_:stroke',
674
+ ' opacity="', opacity, '"',
675
+ ' joinstyle="', this.lineJoin, '"',
676
+ ' miterlimit="', this.miterLimit, '"',
677
+ ' endcap="', processLineCap(this.lineCap), '"',
678
+ ' weight="', lineWidth, 'px"',
679
+ ' color="', color, '" />'
680
+ );
681
+ } else if (typeof this.fillStyle == 'object') {
682
+ var fillStyle = this.fillStyle;
1005
683
  var angle = 0;
1006
684
  var focus = {x: 0, y: 0};
1007
685
 
@@ -1011,12 +689,12 @@ if (!document.createElement('canvas').getContext) {
1011
689
  var expansion = 1;
1012
690
 
1013
691
  if (fillStyle.type_ == 'gradient') {
1014
- var x0 = fillStyle.x0_ / arcScaleX;
1015
- var y0 = fillStyle.y0_ / arcScaleY;
1016
- var x1 = fillStyle.x1_ / arcScaleX;
1017
- var y1 = fillStyle.y1_ / arcScaleY;
1018
- var p0 = ctx.getCoords_(x0, y0);
1019
- var p1 = ctx.getCoords_(x1, y1);
692
+ var x0 = fillStyle.x0_ / this.arcScaleX_;
693
+ var y0 = fillStyle.y0_ / this.arcScaleY_;
694
+ var x1 = fillStyle.x1_ / this.arcScaleX_;
695
+ var y1 = fillStyle.y1_ / this.arcScaleY_;
696
+ var p0 = this.getCoords_(x0, y0);
697
+ var p1 = this.getCoords_(x1, y1);
1020
698
  var dx = p1.x - p0.x;
1021
699
  var dy = p1.y - p0.y;
1022
700
  angle = Math.atan2(dx, dy) * 180 / Math.PI;
@@ -1032,14 +710,16 @@ if (!document.createElement('canvas').getContext) {
1032
710
  angle = 0;
1033
711
  }
1034
712
  } else {
1035
- var p0 = ctx.getCoords_(fillStyle.x0_, fillStyle.y0_);
713
+ var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_);
714
+ var width = max.x - min.x;
715
+ var height = max.y - min.y;
1036
716
  focus = {
1037
717
  x: (p0.x - min.x) / width,
1038
718
  y: (p0.y - min.y) / height
1039
719
  };
1040
720
 
1041
- width /= arcScaleX * Z;
1042
- height /= arcScaleY * Z;
721
+ width /= this.arcScaleX_ * Z;
722
+ height /= this.arcScaleY_ * Z;
1043
723
  var dimension = m.max(width, height);
1044
724
  shift = 2 * fillStyle.r0_ / dimension;
1045
725
  expansion = 2 * fillStyle.r1_ / dimension - shift;
@@ -1055,8 +735,8 @@ if (!document.createElement('canvas').getContext) {
1055
735
  var length = stops.length;
1056
736
  var color1 = stops[0].color;
1057
737
  var color2 = stops[length - 1].color;
1058
- var opacity1 = stops[0].alpha * ctx.globalAlpha;
1059
- var opacity2 = stops[length - 1].alpha * ctx.globalAlpha;
738
+ var opacity1 = stops[0].alpha * this.globalAlpha;
739
+ var opacity2 = stops[length - 1].alpha * this.globalAlpha;
1060
740
 
1061
741
  var colors = [];
1062
742
  for (var i = 0; i < length; i++) {
@@ -1075,31 +755,19 @@ if (!document.createElement('canvas').getContext) {
1075
755
  ' g_o_:opacity2="', opacity1, '"',
1076
756
  ' angle="', angle, '"',
1077
757
  ' focusposition="', focus.x, ',', focus.y, '" />');
1078
- } else if (fillStyle instanceof CanvasPattern_) {
1079
- if (width && height) {
1080
- var deltaLeft = -min.x;
1081
- var deltaTop = -min.y;
1082
- lineStr.push('<g_vml_:fill',
1083
- ' position="',
1084
- deltaLeft / width * arcScaleX * arcScaleX, ',',
1085
- deltaTop / height * arcScaleY * arcScaleY, '"',
1086
- ' type="tile"',
1087
- // TODO: Figure out the correct size to fit the scale.
1088
- //' size="', w, 'px ', h, 'px"',
1089
- ' src="', fillStyle.src_, '" />');
1090
- }
1091
758
  } else {
1092
- var a = processStyle(ctx.fillStyle);
1093
- var color = a.color;
1094
- var opacity = a.alpha * ctx.globalAlpha;
1095
759
  lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity,
1096
760
  '" />');
1097
761
  }
1098
- }
762
+
763
+ lineStr.push('</g_vml_:shape>');
764
+
765
+ this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
766
+ };
1099
767
 
1100
768
  contextPrototype.fill = function() {
1101
769
  this.stroke(true);
1102
- };
770
+ }
1103
771
 
1104
772
  contextPrototype.closePath = function() {
1105
773
  this.currentPath_.push({type: 'close'});
@@ -1113,7 +781,7 @@ if (!document.createElement('canvas').getContext) {
1113
781
  return {
1114
782
  x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,
1115
783
  y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2
1116
- };
784
+ }
1117
785
  };
1118
786
 
1119
787
  contextPrototype.save = function() {
@@ -1125,16 +793,19 @@ if (!document.createElement('canvas').getContext) {
1125
793
  };
1126
794
 
1127
795
  contextPrototype.restore = function() {
1128
- if (this.aStack_.length) {
1129
- copyState(this.aStack_.pop(), this);
1130
- this.m_ = this.mStack_.pop();
1131
- }
796
+ copyState(this.aStack_.pop(), this);
797
+ this.m_ = this.mStack_.pop();
1132
798
  };
1133
799
 
1134
800
  function matrixIsFinite(m) {
1135
- return isFinite(m[0][0]) && isFinite(m[0][1]) &&
1136
- isFinite(m[1][0]) && isFinite(m[1][1]) &&
1137
- isFinite(m[2][0]) && isFinite(m[2][1]);
801
+ for (var j = 0; j < 3; j++) {
802
+ for (var k = 0; k < 2; k++) {
803
+ if (!isFinite(m[j][k]) || isNaN(m[j][k])) {
804
+ return false;
805
+ }
806
+ }
807
+ }
808
+ return true;
1138
809
  }
1139
810
 
1140
811
  function setM(ctx, m, updateLineScale) {
@@ -1208,124 +879,6 @@ if (!document.createElement('canvas').getContext) {
1208
879
  setM(this, m, true);
1209
880
  };
1210
881
 
1211
- /**
1212
- * The text drawing function.
1213
- * The maxWidth argument isn't taken in account, since no browser supports
1214
- * it yet.
1215
- */
1216
- contextPrototype.drawText_ = function(text, x, y, maxWidth, stroke) {
1217
- var m = this.m_,
1218
- delta = 1000,
1219
- left = 0,
1220
- right = delta,
1221
- offset = {x: 0, y: 0},
1222
- lineStr = [];
1223
-
1224
- var fontStyle = getComputedStyle(processFontStyle(this.font),
1225
- this.element_);
1226
-
1227
- var fontStyleString = buildStyle(fontStyle);
1228
-
1229
- var elementStyle = this.element_.currentStyle;
1230
- var textAlign = this.textAlign.toLowerCase();
1231
- switch (textAlign) {
1232
- case 'left':
1233
- case 'center':
1234
- case 'right':
1235
- break;
1236
- case 'end':
1237
- textAlign = elementStyle.direction == 'ltr' ? 'right' : 'left';
1238
- break;
1239
- case 'start':
1240
- textAlign = elementStyle.direction == 'rtl' ? 'right' : 'left';
1241
- break;
1242
- default:
1243
- textAlign = 'left';
1244
- }
1245
-
1246
- // 1.75 is an arbitrary number, as there is no info about the text baseline
1247
- switch (this.textBaseline) {
1248
- case 'hanging':
1249
- case 'top':
1250
- offset.y = fontStyle.size / 1.75;
1251
- break;
1252
- case 'middle':
1253
- break;
1254
- default:
1255
- case null:
1256
- case 'alphabetic':
1257
- case 'ideographic':
1258
- case 'bottom':
1259
- offset.y = -fontStyle.size / 2.25;
1260
- break;
1261
- }
1262
-
1263
- switch(textAlign) {
1264
- case 'right':
1265
- left = delta;
1266
- right = 0.05;
1267
- break;
1268
- case 'center':
1269
- left = right = delta / 2;
1270
- break;
1271
- }
1272
-
1273
- var d = this.getCoords_(x + offset.x, y + offset.y);
1274
-
1275
- lineStr.push('<g_vml_:line from="', -left ,' 0" to="', right ,' 0.05" ',
1276
- ' coordsize="100 100" coordorigin="0 0"',
1277
- ' filled="', !stroke, '" stroked="', !!stroke,
1278
- '" style="position:absolute;width:1px;height:1px;">');
1279
-
1280
- if (stroke) {
1281
- appendStroke(this, lineStr);
1282
- } else {
1283
- // TODO: Fix the min and max params.
1284
- appendFill(this, lineStr, {x: -left, y: 0},
1285
- {x: right, y: fontStyle.size});
1286
- }
1287
-
1288
- var skewM = m[0][0].toFixed(3) + ',' + m[1][0].toFixed(3) + ',' +
1289
- m[0][1].toFixed(3) + ',' + m[1][1].toFixed(3) + ',0,0';
1290
-
1291
- var skewOffset = mr(d.x / Z) + ',' + mr(d.y / Z);
1292
-
1293
- lineStr.push('<g_vml_:skew on="t" matrix="', skewM ,'" ',
1294
- ' offset="', skewOffset, '" origin="', left ,' 0" />',
1295
- '<g_vml_:path textpathok="true" />',
1296
- '<g_vml_:textpath on="true" string="',
1297
- encodeHtmlAttribute(text),
1298
- '" style="v-text-align:', textAlign,
1299
- ';font:', encodeHtmlAttribute(fontStyleString),
1300
- '" /></g_vml_:line>');
1301
-
1302
- this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
1303
- };
1304
-
1305
- contextPrototype.fillText = function(text, x, y, maxWidth) {
1306
- this.drawText_(text, x, y, maxWidth, false);
1307
- };
1308
-
1309
- contextPrototype.strokeText = function(text, x, y, maxWidth) {
1310
- this.drawText_(text, x, y, maxWidth, true);
1311
- };
1312
-
1313
- contextPrototype.measureText = function(text) {
1314
- if (!this.textMeasureEl_) {
1315
- var s = '<span style="position:absolute;' +
1316
- 'top:-20000px;left:0;padding:0;margin:0;border:none;' +
1317
- 'white-space:pre;"></span>';
1318
- this.element_.insertAdjacentHTML('beforeEnd', s);
1319
- this.textMeasureEl_ = this.element_.lastChild;
1320
- }
1321
- var doc = this.element_.ownerDocument;
1322
- this.textMeasureEl_.innerHTML = '';
1323
- this.textMeasureEl_.style.font = this.font;
1324
- // Don't use innerHTML or innerText because they allow markup/whitespace.
1325
- this.textMeasureEl_.appendChild(doc.createTextNode(text));
1326
- return {width: this.textMeasureEl_.offsetWidth};
1327
- };
1328
-
1329
882
  /******** STUBS ********/
1330
883
  contextPrototype.clip = function() {
1331
884
  // TODO: Implement
@@ -1335,8 +888,8 @@ if (!document.createElement('canvas').getContext) {
1335
888
  // TODO: Implement
1336
889
  };
1337
890
 
1338
- contextPrototype.createPattern = function(image, repetition) {
1339
- return new CanvasPattern_(image, repetition);
891
+ contextPrototype.createPattern = function() {
892
+ return new CanvasPattern_;
1340
893
  };
1341
894
 
1342
895
  // Gradient / Pattern Stubs
@@ -1358,70 +911,14 @@ if (!document.createElement('canvas').getContext) {
1358
911
  alpha: aColor.alpha});
1359
912
  };
1360
913
 
1361
- function CanvasPattern_(image, repetition) {
1362
- assertImageIsValid(image);
1363
- switch (repetition) {
1364
- case 'repeat':
1365
- case null:
1366
- case '':
1367
- this.repetition_ = 'repeat';
1368
- break
1369
- case 'repeat-x':
1370
- case 'repeat-y':
1371
- case 'no-repeat':
1372
- this.repetition_ = repetition;
1373
- break;
1374
- default:
1375
- throwException('SYNTAX_ERR');
1376
- }
1377
-
1378
- this.src_ = image.src;
1379
- this.width_ = image.width;
1380
- this.height_ = image.height;
1381
- }
1382
-
1383
- function throwException(s) {
1384
- throw new DOMException_(s);
1385
- }
1386
-
1387
- function assertImageIsValid(img) {
1388
- if (!img || img.nodeType != 1 || img.tagName != 'IMG') {
1389
- throwException('TYPE_MISMATCH_ERR');
1390
- }
1391
- if (img.readyState != 'complete') {
1392
- throwException('INVALID_STATE_ERR');
1393
- }
1394
- }
1395
-
1396
- function DOMException_(s) {
1397
- this.code = this[s];
1398
- this.message = s +': DOM Exception ' + this.code;
1399
- }
1400
- var p = DOMException_.prototype = new Error;
1401
- p.INDEX_SIZE_ERR = 1;
1402
- p.DOMSTRING_SIZE_ERR = 2;
1403
- p.HIERARCHY_REQUEST_ERR = 3;
1404
- p.WRONG_DOCUMENT_ERR = 4;
1405
- p.INVALID_CHARACTER_ERR = 5;
1406
- p.NO_DATA_ALLOWED_ERR = 6;
1407
- p.NO_MODIFICATION_ALLOWED_ERR = 7;
1408
- p.NOT_FOUND_ERR = 8;
1409
- p.NOT_SUPPORTED_ERR = 9;
1410
- p.INUSE_ATTRIBUTE_ERR = 10;
1411
- p.INVALID_STATE_ERR = 11;
1412
- p.SYNTAX_ERR = 12;
1413
- p.INVALID_MODIFICATION_ERR = 13;
1414
- p.NAMESPACE_ERR = 14;
1415
- p.INVALID_ACCESS_ERR = 15;
1416
- p.VALIDATION_ERR = 16;
1417
- p.TYPE_MISMATCH_ERR = 17;
914
+ function CanvasPattern_() {}
1418
915
 
1419
916
  // set up externs
1420
917
  G_vmlCanvasManager = G_vmlCanvasManager_;
1421
918
  CanvasRenderingContext2D = CanvasRenderingContext2D_;
1422
919
  CanvasGradient = CanvasGradient_;
1423
920
  CanvasPattern = CanvasPattern_;
1424
- DOMException = DOMException_;
921
+
1425
922
  })();
1426
923
 
1427
924
  } // if