contour 0.0.0 → 0.1.1

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 (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
+ })();