contour 0.0.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/.gitignore +7 -0
  2. data/CHANGELOG.rdoc +13 -0
  3. data/README.rdoc +56 -0
  4. data/app/controllers/contour/authentications_controller.rb +60 -0
  5. data/app/controllers/contour/registrations_controller.rb +16 -0
  6. data/app/controllers/contour/samples_controller.rb +5 -0
  7. data/app/controllers/contour/sessions_controller.rb +3 -0
  8. data/app/views/contour/authentications/_index.html.erb +25 -0
  9. data/app/views/contour/authentications/_menu.html.erb +25 -0
  10. data/app/views/contour/authentications/index.html.erb +27 -0
  11. data/app/views/contour/layouts/_menu.html.erb +32 -0
  12. data/app/views/contour/layouts/_message.html.erb +8 -0
  13. data/app/views/contour/layouts/application.html.erb +47 -0
  14. data/app/views/contour/registrations/edit.html.erb +25 -0
  15. data/app/views/contour/registrations/new.html.erb +37 -0
  16. data/app/views/contour/samples/index.html.erb +27 -0
  17. data/app/views/contour/sessions/new.html.erb +25 -0
  18. data/app/views/devise/passwords/edit.html.erb +16 -0
  19. data/app/views/devise/passwords/new.html.erb +12 -0
  20. data/contour.gemspec +27 -0
  21. data/lib/contour.rb +36 -0
  22. data/lib/contour/engine.rb +8 -0
  23. data/lib/contour/version.rb +1 -1
  24. data/lib/generators/contour/install_generator.rb +38 -0
  25. data/lib/generators/templates/contour.rb +30 -0
  26. data/lib/generators/templates/devise.rb +153 -0
  27. data/lib/generators/templates/omniauth.rb +22 -0
  28. data/lib/generators/templates/omniauth_fix.rb +98 -0
  29. data/lib/generators/templates/rack_fix.rb +44 -0
  30. data/vendor/assets/images/authbuttons/cas_32.png +0 -0
  31. data/vendor/assets/images/authbuttons/cas_64.png +0 -0
  32. data/vendor/assets/images/authbuttons/facebook_32.png +0 -0
  33. data/vendor/assets/images/authbuttons/facebook_64.png +0 -0
  34. data/vendor/assets/images/authbuttons/google_apps_32.png +0 -0
  35. data/vendor/assets/images/authbuttons/google_apps_64.png +0 -0
  36. data/vendor/assets/images/authbuttons/ldap_32.png +0 -0
  37. data/vendor/assets/images/authbuttons/ldap_64.png +0 -0
  38. data/vendor/assets/images/authbuttons/linkedin_32.png +0 -0
  39. data/vendor/assets/images/authbuttons/linkedin_64.png +0 -0
  40. data/vendor/assets/images/authbuttons/openid_32.png +0 -0
  41. data/vendor/assets/images/authbuttons/openid_64.png +0 -0
  42. data/vendor/assets/images/authbuttons/twitter_32.png +0 -0
  43. data/vendor/assets/images/authbuttons/twitter_64.png +0 -0
  44. data/vendor/assets/images/redmond/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  45. data/vendor/assets/images/redmond/ui-bg_flat_55_fbec88_40x100.png +0 -0
  46. data/vendor/assets/images/redmond/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  47. data/vendor/assets/images/redmond/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  48. data/vendor/assets/images/redmond/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  49. data/vendor/assets/images/redmond/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  50. data/vendor/assets/images/redmond/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  51. data/vendor/assets/images/redmond/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  52. data/vendor/assets/images/redmond/ui-icons_217bc0_256x240.png +0 -0
  53. data/vendor/assets/images/redmond/ui-icons_2e83ff_256x240.png +0 -0
  54. data/vendor/assets/images/redmond/ui-icons_469bdd_256x240.png +0 -0
  55. data/vendor/assets/images/redmond/ui-icons_6da8d5_256x240.png +0 -0
  56. data/vendor/assets/images/redmond/ui-icons_cd0a0a_256x240.png +0 -0
  57. data/vendor/assets/images/redmond/ui-icons_d8e7f3_256x240.png +0 -0
  58. data/vendor/assets/images/redmond/ui-icons_f9bd01_256x240.png +0 -0
  59. data/vendor/assets/javascripts/contour.js +8 -0
  60. data/vendor/assets/javascripts/errors.js.coffee +10 -0
  61. data/vendor/assets/javascripts/external/exporting-2.1.4.src.js +673 -0
  62. data/vendor/assets/javascripts/external/highcharts-2.1.4.src.js +10668 -0
  63. data/vendor/assets/javascripts/external/jquery-ui-1.8.10.custom.min.js +782 -0
  64. data/vendor/assets/javascripts/external/waypoints.js +610 -0
  65. data/vendor/assets/javascripts/global.js.coffee +38 -0
  66. data/vendor/assets/javascripts/menu.js.coffee +6 -0
  67. data/vendor/assets/javascripts/popup.js.coffee +67 -0
  68. data/vendor/assets/stylesheets/authentication.css +63 -0
  69. data/vendor/assets/stylesheets/bluetrip-screen.css +324 -0
  70. data/vendor/assets/stylesheets/contour.css +15 -0
  71. data/vendor/assets/stylesheets/global.css +59 -0
  72. data/vendor/assets/stylesheets/header.css +18 -0
  73. data/vendor/assets/stylesheets/jquery-ui-1.8.10.custom.css +574 -0
  74. data/vendor/assets/stylesheets/menu.css +77 -0
  75. data/vendor/assets/stylesheets/message.css +27 -0
  76. data/vendor/assets/stylesheets/popup.css +79 -0
  77. metadata +114 -29
  78. data/README +0 -18
@@ -0,0 +1,44 @@
1
+ module Rack
2
+ class Request
3
+ def scheme
4
+ if @env['HTTPS'] == 'on'
5
+ 'https'
6
+ elsif @env['HTTP_X_FORWARDED_SSL'] == 'on'
7
+ 'https'
8
+ elsif @env['HTTP_X_FORWARDED_PROTO']
9
+ @env['HTTP_X_FORWARDED_PROTO'].split(',')[0]
10
+ else
11
+ @env["rack.url_scheme"]
12
+ end
13
+ end
14
+
15
+ def ssl?
16
+ scheme == 'https'
17
+ end
18
+
19
+ def host_with_port
20
+ if forwarded = @env["HTTP_X_FORWARDED_HOST"]
21
+ Rails.logger.debug "@env[HTTP_X_FORWARDED_HOST]: #{@env["HTTP_X_FORWARDED_HOST"]} USING => #{forwarded.split(/,\s?/).first}"
22
+ # forwarded.split(/,\s?/).last
23
+ # changed forwarded to first since we don't want the internal IP.
24
+ forwarded.split(/,\s?/).first
25
+ else
26
+ @env['HTTP_HOST'] || "#{@env['SERVER_NAME'] || @env['SERVER_ADDR']}:#{@env['SERVER_PORT']}"
27
+ end
28
+ end
29
+
30
+ def port
31
+ if port = host_with_port.split(/:/)[1]
32
+ port.to_i
33
+ elsif port = @env['HTTP_X_FORWARDED_PORT']
34
+ port.to_i
35
+ elsif ssl?
36
+ 443
37
+ elsif @env.has_key?("HTTP_X_FORWARDED_HOST")
38
+ 80
39
+ else
40
+ @env["SERVER_PORT"].to_i
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,8 @@
1
+ // This is the Contour manifest file. Make sure to include require contour at the top
2
+ // of your application.js manifest file
3
+ //
4
+ //= require jquery
5
+ //= require jquery_ujs
6
+ //= require external/highcharts-2.1.4.src
7
+ //= require external/exporting-2.1.4.src
8
+ //= require_tree .
@@ -0,0 +1,10 @@
1
+ jQuery ->
2
+ $(".field_with_errors input, .field_with_errors_cleared input, .field_with_errors textarea, .field_with_errors_cleared textarea, .field_with_errors select, .field_with_errors_cleared select").change( () ->
3
+ el = $(this)
4
+ if el.val() != '' && el.val() != null
5
+ $(el).parent().removeClass('field_with_errors')
6
+ $(el).parent().addClass('field_with_errors_cleared')
7
+ else
8
+ $(el).parent().removeClass('field_with_errors_cleared')
9
+ $(el).parent().addClass('field_with_errors')
10
+ )
@@ -0,0 +1,673 @@
1
+ /**
2
+ * @license Highcharts JS v2.1.4 (2011-03-02)
3
+ * Exporting module
4
+ *
5
+ * (c) 2010 Torstein Hønsi
6
+ *
7
+ * License: www.highcharts.com/license
8
+ */
9
+
10
+ // JSLint options:
11
+ /*global Highcharts, document, window, Math, setTimeout */
12
+
13
+ (function() { // encapsulate
14
+
15
+ // create shortcuts
16
+ var HC = Highcharts,
17
+ Chart = HC.Chart,
18
+ addEvent = HC.addEvent,
19
+ createElement = HC.createElement,
20
+ discardElement = HC.discardElement,
21
+ css = HC.css,
22
+ merge = HC.merge,
23
+ each = HC.each,
24
+ extend = HC.extend,
25
+ math = Math,
26
+ mathMax = math.max,
27
+ doc = document,
28
+ win = window,
29
+ hasTouch = 'ontouchstart' in doc.documentElement,
30
+ M = 'M',
31
+ L = 'L',
32
+ DIV = 'div',
33
+ HIDDEN = 'hidden',
34
+ NONE = 'none',
35
+ PREFIX = 'highcharts-',
36
+ ABSOLUTE = 'absolute',
37
+ PX = 'px',
38
+
39
+
40
+
41
+ // Add language and get the defaultOptions
42
+ defaultOptions = HC.setOptions({
43
+ lang: {
44
+ downloadPNG: 'Download PNG image',
45
+ downloadJPEG: 'Download JPEG image',
46
+ downloadPDF: 'Download PDF document',
47
+ downloadSVG: 'Download SVG vector image',
48
+ exportButtonTitle: 'Export to raster or vector image',
49
+ printButtonTitle: 'Print the chart'
50
+ }
51
+ });
52
+
53
+ // Buttons and menus are collected in a separate config option set called 'navigation'.
54
+ // This can be extended later to add control buttons like zoom and pan right click menus.
55
+ defaultOptions.navigation = {
56
+ menuStyle: {
57
+ border: '1px solid #A0A0A0',
58
+ background: '#FFFFFF'
59
+ },
60
+ menuItemStyle: {
61
+ padding: '0 5px',
62
+ background: NONE,
63
+ color: '#303030',
64
+ fontSize: hasTouch ? '14px' : '11px'
65
+ },
66
+ menuItemHoverStyle: {
67
+ background: '#4572A5',
68
+ color: '#FFFFFF'
69
+ },
70
+
71
+ buttonOptions: {
72
+ align: 'right',
73
+ backgroundColor: {
74
+ linearGradient: [0, 0, 0, 20],
75
+ stops: [
76
+ [0.4, '#F7F7F7'],
77
+ [0.6, '#E3E3E3']
78
+ ]
79
+ },
80
+ borderColor: '#B0B0B0',
81
+ borderRadius: 3,
82
+ borderWidth: 1,
83
+ //enabled: true,
84
+ height: 20,
85
+ hoverBorderColor: '#909090',
86
+ hoverSymbolFill: '#81A7CF',
87
+ hoverSymbolStroke: '#4572A5',
88
+ symbolFill: '#E0E0E0',
89
+ //symbolSize: 12,
90
+ symbolStroke: '#A0A0A0',
91
+ //symbolStrokeWidth: 1,
92
+ symbolX: 11.5,
93
+ symbolY: 10.5,
94
+ verticalAlign: 'top',
95
+ width: 24,
96
+ y: 10
97
+ }
98
+ };
99
+
100
+
101
+
102
+ // Add the export related options
103
+ defaultOptions.exporting = {
104
+ //enabled: true,
105
+ //filename: 'chart',
106
+ type: 'image/png',
107
+ url: 'http://export.highcharts.com/',
108
+ width: 800,
109
+ buttons: {
110
+ exportButton: {
111
+ //enabled: true,
112
+ symbol: 'exportIcon',
113
+ x: -10,
114
+ symbolFill: '#A8BF77',
115
+ hoverSymbolFill: '#768F3E',
116
+ _titleKey: 'exportButtonTitle',
117
+ menuItems: [{
118
+ textKey: 'downloadPNG',
119
+ onclick: function() {
120
+ this.exportChart();
121
+ }
122
+ }, {
123
+ textKey: 'downloadJPEG',
124
+ onclick: function() {
125
+ this.exportChart({
126
+ type: 'image/jpeg'
127
+ });
128
+ }
129
+ }, {
130
+ textKey: 'downloadPDF',
131
+ onclick: function() {
132
+ this.exportChart({
133
+ type: 'application/pdf'
134
+ });
135
+ }
136
+ }, {
137
+ textKey: 'downloadSVG',
138
+ onclick: function() {
139
+ this.exportChart({
140
+ type: 'image/svg+xml'
141
+ });
142
+ }
143
+ }/*, {
144
+ text: 'View SVG',
145
+ onclick: function() {
146
+ var svg = this.getSVG()
147
+ .replace(/</g, '\n&lt;')
148
+ .replace(/>/g, '&gt;');
149
+
150
+ doc.body.innerHTML = '<pre>'+ svg +'</pre>';
151
+ }
152
+ }*/]
153
+
154
+ },
155
+ printButton: {
156
+ //enabled: true,
157
+ symbol: 'printIcon',
158
+ x: -36,
159
+ symbolFill: '#B5C9DF',
160
+ hoverSymbolFill: '#779ABF',
161
+ _titleKey: 'printButtonTitle',
162
+ onclick: function() {
163
+ this.print();
164
+ }
165
+ }
166
+ }
167
+ };
168
+
169
+
170
+
171
+ extend(Chart.prototype, {
172
+ /**
173
+ * Return an SVG representation of the chart
174
+ *
175
+ * @param additionalOptions {Object} Additional chart options for the generated SVG representation
176
+ */
177
+ getSVG: function(additionalOptions) {
178
+ var chart = this,
179
+ chartCopy,
180
+ sandbox,
181
+ svg,
182
+ seriesOptions,
183
+ config,
184
+ pointOptions,
185
+ pointMarker,
186
+ options = merge(chart.options, additionalOptions); // copy the options and add extra options
187
+
188
+ // IE compatibility hack for generating SVG content that it doesn't really understand
189
+ if (!doc.createElementNS) {
190
+ doc.createElementNS = function(ns, tagName) {
191
+ var elem = doc.createElement(tagName);
192
+ elem.getBBox = function() {
193
+ return chart.renderer.Element.prototype.getBBox.apply({ element: elem });
194
+ };
195
+ return elem;
196
+ };
197
+ }
198
+
199
+ // create a sandbox where a new chart will be generated
200
+ sandbox = createElement(DIV, null, {
201
+ position: ABSOLUTE,
202
+ top: '-9999em',
203
+ width: chart.chartWidth + PX,
204
+ height: chart.chartHeight + PX
205
+ }, doc.body);
206
+
207
+ // override some options
208
+ extend(options.chart, {
209
+ renderTo: sandbox,
210
+ forExport: true
211
+ });
212
+ options.exporting.enabled = false; // hide buttons in print
213
+ options.chart.plotBackgroundImage = null; // the converter doesn't handle images
214
+ // prepare for replicating the chart
215
+ options.series = [];
216
+ each(chart.series, function(serie) {
217
+ seriesOptions = serie.options;
218
+
219
+ seriesOptions.animation = false; // turn off animation
220
+ seriesOptions.showCheckbox = false;
221
+
222
+ // remove image markers
223
+ if (seriesOptions && seriesOptions.marker && /^url\(/.test(seriesOptions.marker.symbol)) {
224
+ seriesOptions.marker.symbol = 'circle';
225
+ }
226
+
227
+ seriesOptions.data = [];
228
+
229
+ each(serie.data, function(point) {
230
+
231
+ // extend the options by those values that can be expressed in a number or array config
232
+ config = point.config;
233
+ pointOptions = {
234
+ x: point.x,
235
+ y: point.y,
236
+ name: point.name
237
+ };
238
+
239
+ if (typeof config == 'object' && point.config && config.constructor != Array) {
240
+ extend(pointOptions, config);
241
+ }
242
+
243
+ seriesOptions.data.push(pointOptions); // copy fresh updated data
244
+
245
+ // remove image markers
246
+ pointMarker = point.config && point.config.marker;
247
+ if (pointMarker && /^url\(/.test(pointMarker.symbol)) {
248
+ delete pointMarker.symbol;
249
+ }
250
+ });
251
+
252
+ options.series.push(seriesOptions);
253
+ });
254
+
255
+ // generate the chart copy
256
+ chartCopy = new Highcharts.Chart(options);
257
+
258
+ // get the SVG from the container's innerHTML
259
+ svg = chartCopy.container.innerHTML;
260
+
261
+ // free up memory
262
+ options = null;
263
+ chartCopy.destroy();
264
+ discardElement(sandbox);
265
+
266
+ // sanitize
267
+ svg = svg
268
+ .replace(/zIndex="[^"]+"/g, '')
269
+ .replace(/isShadow="[^"]+"/g, '')
270
+ .replace(/symbolName="[^"]+"/g, '')
271
+ .replace(/jQuery[0-9]+="[^"]+"/g, '')
272
+ .replace(/isTracker="[^"]+"/g, '')
273
+ .replace(/url\([^#]+#/g, 'url(#')
274
+ /*.replace(/<svg /, '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ')
275
+ .replace(/ href=/, ' xlink:href=')
276
+ .replace(/preserveAspectRatio="none">/g, 'preserveAspectRatio="none"/>')*/
277
+ /* This fails in IE < 8
278
+ .replace(/([0-9]+)\.([0-9]+)/g, function(s1, s2, s3) { // round off to save weight
279
+ return s2 +'.'+ s3[0];
280
+ })*/
281
+
282
+ // IE specific
283
+ .replace(/id=([^" >]+)/g, 'id="$1"')
284
+ .replace(/class=([^" ]+)/g, 'class="$1"')
285
+ .replace(/ transform /g, ' ')
286
+ .replace(/:(path|rect)/g, '$1')
287
+ .replace(/style="([^"]+)"/g, function(s) {
288
+ return s.toLowerCase();
289
+ });
290
+
291
+ // IE9 beta bugs with innerHTML. Test again with final IE9.
292
+ svg = svg.replace(/(url\(#highcharts-[0-9]+)&quot;/g, '$1')
293
+ .replace(/&quot;/g, "'");
294
+ if (svg.match(/ xmlns="/g).length == 2) {
295
+ svg = svg.replace(/xmlns="[^"]+"/, '');
296
+ }
297
+
298
+ return svg;
299
+ },
300
+
301
+ /**
302
+ * Submit the SVG representation of the chart to the server
303
+ * @param {Object} options Exporting options. Possible members are url, type and width.
304
+ * @param {Object} chartOptions Additional chart options for the SVG representation of the chart
305
+ */
306
+ exportChart: function(options, chartOptions) {
307
+ var form,
308
+ chart = this,
309
+ svg = chart.getSVG(chartOptions);
310
+
311
+ // merge the options
312
+ options = merge(chart.options.exporting, options);
313
+
314
+ // create the form
315
+ form = createElement('form', {
316
+ method: 'post',
317
+ action: options.url
318
+ }, {
319
+ display: NONE
320
+ }, doc.body);
321
+
322
+ // add the values
323
+ each(['filename', 'type', 'width', 'svg'], function(name) {
324
+ createElement('input', {
325
+ type: HIDDEN,
326
+ name: name,
327
+ value: {
328
+ filename: options.filename || 'chart',
329
+ type: options.type,
330
+ width: options.width,
331
+ svg: svg
332
+ }[name]
333
+ }, null, form);
334
+ });
335
+
336
+ // submit
337
+ form.submit();
338
+
339
+ // clean up
340
+ discardElement(form);
341
+ },
342
+
343
+ /**
344
+ * Print the chart
345
+ */
346
+ print: function() {
347
+
348
+ var chart = this,
349
+ container = chart.container,
350
+ origDisplay = [],
351
+ origParent = container.parentNode,
352
+ body = doc.body,
353
+ childNodes = body.childNodes;
354
+
355
+ if (chart.isPrinting) { // block the button while in printing mode
356
+ return;
357
+ }
358
+
359
+ chart.isPrinting = true;
360
+
361
+ // hide all body content
362
+ each(childNodes, function(node, i) {
363
+ if (node.nodeType == 1) {
364
+ origDisplay[i] = node.style.display;
365
+ node.style.display = NONE;
366
+ }
367
+ });
368
+
369
+ // pull out the chart
370
+ body.appendChild(container);
371
+
372
+ // print
373
+ win.print();
374
+
375
+ // allow the browser to prepare before reverting
376
+ setTimeout(function() {
377
+
378
+ // put the chart back in
379
+ origParent.appendChild(container);
380
+
381
+ // restore all body content
382
+ each(childNodes, function(node, i) {
383
+ if (node.nodeType == 1) {
384
+ node.style.display = origDisplay[i];
385
+ }
386
+ });
387
+
388
+ chart.isPrinting = false;
389
+
390
+ }, 1000);
391
+
392
+ },
393
+
394
+ /**
395
+ * Display a popup menu for choosing the export type
396
+ *
397
+ * @param {String} name An identifier for the menu
398
+ * @param {Array} items A collection with text and onclicks for the items
399
+ * @param {Number} x The x position of the opener button
400
+ * @param {Number} y The y position of the opener button
401
+ * @param {Number} width The width of the opener button
402
+ * @param {Number} height The height of the opener button
403
+ */
404
+ contextMenu: function(name, items, x, y, width, height) {
405
+ var chart = this,
406
+ navOptions = chart.options.navigation,
407
+ menuItemStyle = navOptions.menuItemStyle,
408
+ chartWidth = chart.chartWidth,
409
+ chartHeight = chart.chartHeight,
410
+ cacheName = 'cache-'+ name,
411
+ menu = chart[cacheName],
412
+ menuPadding = mathMax(width, height), // for mouse leave detection
413
+ boxShadow = '3px 3px 10px #888',
414
+ innerMenu,
415
+ hide,
416
+ menuStyle;
417
+
418
+ // create the menu only the first time
419
+ if (!menu) {
420
+
421
+ // create a HTML element above the SVG
422
+ chart[cacheName] = menu = createElement(DIV, {
423
+ className: PREFIX + name
424
+ }, {
425
+ position: ABSOLUTE,
426
+ zIndex: 1000,
427
+ padding: menuPadding + PX
428
+ }, chart.container);
429
+
430
+ innerMenu = createElement(DIV, null,
431
+ extend({
432
+ MozBoxShadow: boxShadow,
433
+ WebkitBoxShadow: boxShadow,
434
+ boxShadow: boxShadow
435
+ }, navOptions.menuStyle) , menu);
436
+
437
+ // hide on mouse out
438
+ hide = function() {
439
+ css(menu, { display: NONE });
440
+ };
441
+
442
+ addEvent(menu, 'mouseleave', hide);
443
+
444
+
445
+ // create the items
446
+ each(items, function(item) {
447
+ if (item) {
448
+ var div = createElement(DIV, {
449
+ onmouseover: function() {
450
+ css(this, navOptions.menuItemHoverStyle);
451
+ },
452
+ onmouseout: function() {
453
+ css(this, menuItemStyle);
454
+ },
455
+ innerHTML: item.text || HC.getOptions().lang[item.textKey]
456
+ }, extend({
457
+ cursor: 'pointer'
458
+ }, menuItemStyle), innerMenu);
459
+
460
+ div[hasTouch ? 'ontouchstart' : 'onclick'] = function() {
461
+ hide();
462
+ item.onclick.apply(chart, arguments);
463
+ };
464
+
465
+ }
466
+ });
467
+
468
+ chart.exportMenuWidth = menu.offsetWidth;
469
+ chart.exportMenuHeight = menu.offsetHeight;
470
+ }
471
+
472
+ menuStyle = { display: 'block' };
473
+
474
+ // if outside right, right align it
475
+ if (x + chart.exportMenuWidth > chartWidth) {
476
+ menuStyle.right = (chartWidth - x - width - menuPadding) + PX;
477
+ } else {
478
+ menuStyle.left = (x - menuPadding) + PX;
479
+ }
480
+ // if outside bottom, bottom align it
481
+ if (y + height + chart.exportMenuHeight > chartHeight) {
482
+ menuStyle.bottom = (chartHeight - y - menuPadding) + PX;
483
+ } else {
484
+ menuStyle.top = (y + height - menuPadding) + PX;
485
+ }
486
+
487
+ css(menu, menuStyle);
488
+ },
489
+
490
+ /**
491
+ * Add the export button to the chart
492
+ */
493
+ addButton: function(options) {
494
+ var chart = this,
495
+ renderer = chart.renderer,
496
+ btnOptions = merge(chart.options.navigation.buttonOptions, options),
497
+ onclick = btnOptions.onclick,
498
+ menuItems = btnOptions.menuItems,
499
+ /*position = chart.getAlignment(btnOptions),
500
+ buttonLeft = position.x,
501
+ buttonTop = position.y,*/
502
+ buttonWidth = btnOptions.width,
503
+ buttonHeight = btnOptions.height,
504
+ box,
505
+ symbol,
506
+ button,
507
+ borderWidth = btnOptions.borderWidth,
508
+ boxAttr = {
509
+ stroke: btnOptions.borderColor
510
+
511
+ },
512
+ symbolAttr = {
513
+ stroke: btnOptions.symbolStroke,
514
+ fill: btnOptions.symbolFill
515
+ };
516
+
517
+ if (btnOptions.enabled === false) {
518
+ return;
519
+ }
520
+
521
+ // element to capture the click
522
+ function revert() {
523
+ symbol.attr(symbolAttr);
524
+ box.attr(boxAttr);
525
+ }
526
+
527
+ // the box border
528
+ box = renderer.rect(
529
+ 0,
530
+ 0,
531
+ buttonWidth,
532
+ buttonHeight,
533
+ btnOptions.borderRadius,
534
+ borderWidth
535
+ )
536
+ //.translate(buttonLeft, buttonTop) // to allow gradients
537
+ .align(btnOptions, true)
538
+ .attr(extend({
539
+ fill: btnOptions.backgroundColor,
540
+ 'stroke-width': borderWidth,
541
+ zIndex: 19
542
+ }, boxAttr)).add();
543
+
544
+ // the invisible element to track the clicks
545
+ button = renderer.rect(
546
+ 0,
547
+ 0,
548
+ buttonWidth,
549
+ buttonHeight,
550
+ 0
551
+ )
552
+ .align(btnOptions)
553
+ .attr({
554
+ fill: 'rgba(255, 255, 255, 0.001)',
555
+ title: HC.getOptions().lang[btnOptions._titleKey],
556
+ zIndex: 21
557
+ }).css({
558
+ cursor: 'pointer'
559
+ })
560
+ .on('mouseover', function() {
561
+ symbol.attr({
562
+ stroke: btnOptions.hoverSymbolStroke,
563
+ fill: btnOptions.hoverSymbolFill
564
+ });
565
+ box.attr({
566
+ stroke: btnOptions.hoverBorderColor
567
+ });
568
+ })
569
+ .on('mouseout', revert)
570
+ .on('click', revert)
571
+ .add();
572
+
573
+ //addEvent(button.element, 'click', revert);
574
+
575
+ // add the click event
576
+ if (menuItems) {
577
+ onclick = function(e) {
578
+ revert();
579
+ var bBox = button.getBBox();
580
+ chart.contextMenu('export-menu', menuItems, bBox.x, bBox.y, buttonWidth, buttonHeight);
581
+ };
582
+ }
583
+ /*addEvent(button.element, 'click', function() {
584
+ onclick.apply(chart, arguments);
585
+ });*/
586
+ button.on('click', function() {
587
+ onclick.apply(chart, arguments);
588
+ });
589
+
590
+ // the icon
591
+ symbol = renderer.symbol(
592
+ btnOptions.symbol,
593
+ btnOptions.symbolX,
594
+ btnOptions.symbolY,
595
+ (btnOptions.symbolSize || 12) / 2
596
+ )
597
+ .align(btnOptions, true)
598
+ .attr(extend(symbolAttr, {
599
+ 'stroke-width': btnOptions.symbolStrokeWidth || 1,
600
+ zIndex: 20
601
+ })).add();
602
+
603
+
604
+
605
+ }
606
+ });
607
+
608
+ // Create the export icon
609
+ HC.Renderer.prototype.symbols.exportIcon = function(x, y, radius) {
610
+ return [
611
+ M, // the disk
612
+ x - radius, y + radius,
613
+ L,
614
+ x + radius, y + radius,
615
+ x + radius, y + radius * 0.5,
616
+ x - radius, y + radius * 0.5,
617
+ 'Z',
618
+ M, // the arrow
619
+ x, y + radius * 0.5,
620
+ L,
621
+ x - radius * 0.5, y - radius / 3,
622
+ x - radius / 6, y - radius / 3,
623
+ x - radius / 6, y - radius,
624
+ x + radius / 6, y - radius,
625
+ x + radius / 6, y - radius / 3,
626
+ x + radius * 0.5, y - radius / 3,
627
+ 'Z'
628
+ ];
629
+ };
630
+ // Create the print icon
631
+ HC.Renderer.prototype.symbols.printIcon = function(x, y, radius) {
632
+ return [
633
+ M, // the printer
634
+ x - radius, y + radius * 0.5,
635
+ L,
636
+ x + radius, y + radius * 0.5,
637
+ x + radius, y - radius / 3,
638
+ x - radius, y - radius / 3,
639
+ 'Z',
640
+ M, // the upper sheet
641
+ x - radius * 0.5, y - radius / 3,
642
+ L,
643
+ x - radius * 0.5, y - radius,
644
+ x + radius * 0.5, y - radius,
645
+ x + radius * 0.5, y - radius / 3,
646
+ 'Z',
647
+ M, // the lower sheet
648
+ x - radius * 0.5, y + radius * 0.5,
649
+ L,
650
+ x - radius * 0.75, y + radius,
651
+ x + radius * 0.75, y + radius,
652
+ x + radius * 0.5, y + radius * 0.5,
653
+ 'Z'
654
+ ];
655
+ };
656
+
657
+
658
+ // Add the buttons on chart load
659
+ Chart.prototype.callbacks.push(function(chart) {
660
+ var n,
661
+ exportingOptions = chart.options.exporting,
662
+ buttons = exportingOptions.buttons;
663
+
664
+ if (exportingOptions.enabled !== false) {
665
+
666
+ for (n in buttons) {
667
+ chart.addButton(buttons[n]);
668
+ }
669
+ }
670
+ });
671
+
672
+
673
+ })();