wpMandrill - Version 1.0

Version Description

  • Public release
Download this release

Release Info

Developer MC_Will
Plugin Icon wp plugin wpMandrill
Version 1.0
Comparing to
See all releases

Version 1.0

css/mandrill.css ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .news_header {
2
+ background: url("../images/rss_icon.gif") no-repeat scroll 0 0 transparent;
3
+ padding-left: 30px;
4
+ line-height: 20px;
5
+ }
6
+ .news {
7
+ background: url("../images/FreddieHead.png") no-repeat bottom right #FFFFCC;
8
+ border: 1px solid yellow;
9
+ float: right;
10
+ padding: 15px;
11
+ margin-top: 45px;
12
+ padding-bottom: 80px;
13
+ width: 100%;
14
+ }
15
+ .mandrill {
16
+ background: url("../images/MandrillHead.png") no-repeat bottom right #FFFFCC;
17
+ }
18
+ .news ul li a {
19
+ color: #000;
20
+ }
21
+
22
+ .missing {
23
+ background-color: #FFEBE8;
24
+ border: 1px solid #CC0000;
25
+ padding: 3px;
26
+ font-weight: bold;
27
+ }
28
+
29
+ .stat_box {
30
+ background-color: #FFFFCC;
31
+ border: 1px solid yellow;
32
+ float: left;
33
+ font-size: 12px;
34
+ margin: 10px;
35
+ padding: 10px;
36
+ width: auto;
37
+ text-align: center;
38
+ }
39
+
40
+ .warning {
41
+ background-color: #FFCCCC;
42
+ border: 1px solid #FF3366;
43
+ }
44
+
45
+ .stat_box span {
46
+ font-weight: bold;
47
+ font-size: 14px;
48
+ }
49
+ #ajax-icon-container {
50
+ width: 20px;
51
+ height: 20px;
52
+ float: left;
53
+ }
54
+ #loading_data{
55
+ background: url("../images/icon-ajax-loading.gif") no-repeat transparent;
56
+ height: 20px;
57
+ width: 20px;
58
+ display: block;
59
+ }
60
+ .stuffbox {
61
+ max-width: 90% !important;
62
+ margin-top:15px;
63
+ }
64
+ .stuffbox h3 { cursor: default !important; padding: 3px 3px 3px 10px; }
65
+ .stuffbox div.inside { padding-bottom: 10px;}
how-tos.php ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: wpMandrill How-Tos
4
+ Description: This plugin show you how to use the different aspects of wpMandrill.
5
+ Author: Mandrill
6
+ Author URI: http://mandrillapp.com/
7
+ Plugin URI: http://connect.mailchimp.com/integrations/wpmandrill
8
+ Version: 1.0
9
+ Text Domain: wpmandrill
10
+ */
11
+
12
+ MandrillTest::on_load();
13
+
14
+ class MandrillTest {
15
+ static $settings;
16
+
17
+ static function on_load() {
18
+ if ( !class_exists('wpMandrill') ) {
19
+ return;
20
+ }
21
+
22
+ add_action('admin_init', array(__CLASS__, 'adminInit'));
23
+ add_action('admin_menu', array(__CLASS__, 'adminMenu'));
24
+ add_filter('contextual_help', array(__CLASS__, 'showContextualHelp'), 10, 3);
25
+ add_action('admin_print_footer_scripts', array(__CLASS__,'openContextualHelp'));
26
+ load_plugin_textdomain('wpmandrill', false, dirname( plugin_basename( __FILE__ ) ).'/lang');
27
+ }
28
+
29
+ /**
30
+ * @return boolean
31
+ */
32
+ static function isPluginPage() {
33
+
34
+ return ( isset( $_GET['page'] ) && $_GET['page'] == 'wpmandrilltest' );
35
+ }
36
+
37
+ /**
38
+ * Sets up options page and sections.
39
+ */
40
+ static function adminInit() {
41
+
42
+ add_filter('plugin_action_links',array(__CLASS__,'showPluginActionLinks'), 10,5);
43
+ // SMTP Settings
44
+ add_settings_section('wpmandrilltest-auto', __('Mandrill: How to tell WordPress to use wpMandrill.', 'wpmandrill'), '__return_false', 'wpmandrilltest');
45
+ add_settings_field('auto', __('&nbsp;', 'wpmandrill'), array(__CLASS__, 'showSectionAuto'), 'wpmandrilltest', 'wpmandrilltest-auto');
46
+
47
+ add_settings_section('wpmandrilltest-regular', __('Mandrill: How to send a regular email.', 'wpmandrill'), '__return_false', 'wpmandrilltest');
48
+ add_settings_field('regular', __('&nbsp;', 'wpmandrill'), array(__CLASS__, 'showSectionRegular'), 'wpmandrilltest', 'wpmandrilltest-regular');
49
+
50
+ add_settings_section('wpmandrilltest-filter', __('Mandrill: How to modify a certain email using the <em>mandrill_payload</em> WordPress filter.', 'wpmandrill'), '__return_false', 'wpmandrilltest');
51
+ add_settings_field('filter', __('&nbsp;', 'wpmandrill'), array(__CLASS__, 'showSectionFilter'), 'wpmandrilltest', 'wpmandrilltest-filter');
52
+
53
+ add_settings_section('wpmandrilltest-direct', __('Mandrill: How to send emails from within your plugins.', 'wpmandrill'), '__return_false', 'wpmandrilltest');
54
+ add_settings_field('direct', __('&nbsp;', 'wpmandrill'), array(__CLASS__, 'showSectionDirect'), 'wpmandrilltest', 'wpmandrilltest-direct');
55
+ }
56
+
57
+ static function showSectionAuto() {
58
+ echo '
59
+ <span class="setting-description">
60
+ <p>'.__('Simply install wpMandrill and configure it to make it handle all the email functions of your WordPress installation.', 'wpmandrill').'</p>
61
+ <p>'.__('Once it has been properly configured, it will replace the regular WordPress emailing processes, so it\'s basically transparent for you and for WordPress.', 'wpmandrill').'</p>
62
+ <p>'.__('To test wpMandrill, log out, and try to use the <em>Forgot your password?</em> feature in WordPress (you don\'t need to reset your password though. Just check the headers of the email that it sends you, and you\'ll see that it comes from Mandrill\'s servers).', 'wpmandrill').'</p>
63
+ </span>
64
+ ';
65
+ }
66
+
67
+ static function showSectionRegular() {
68
+ echo '
69
+ <span class="setting-description">
70
+ <p>'.__('If you\'re a Plugin Developer, and you need to send a regular email using wpMandrill, you don\'t need to learn anything else. You can use the good ol\' <strong>wp_mail</strong> function, as you would normally do if you were not using this plugin.', 'wpmandrill').'</p>
71
+ <p>'.__('For example:', 'wpmandrill').'</p>
72
+ <p><blockquote><pre>'.__('&lt;?php wp_mail(\'your@address.com\', \'Your subject\', \'Your message\'); ?&gt;', 'wpmandrill').'</pre></blockquote></p>
73
+ </span>
74
+ ';
75
+ }
76
+
77
+ static function showSectionFilter() {
78
+ echo '
79
+ <span class="setting-description">
80
+ <p>'.__('if you need to fine tune one or some of the emails sent through your WordPress installation, you will need to use the <em>mandrill_payload</em> filter.', 'wpmandrill').'</p>
81
+ <p>'.__('To use it, you must create a function that analyzes the payload that is about to be sent to Mandrill, and modify it based on your requirements. Then you\'ll need to add this function as the callback of the mentioned filter, using the <em>add_filter</em> WordPress call. And finally, insert it into your theme\'s functions.php file or you own plugin\'s file.', 'wpmandrill').'</p>
82
+ <p>'.__('You can use the following code as an skeleton for your own callbacks:', 'wpmandrill').'</p>
83
+ <p>
84
+ <blockquote><pre>
85
+ &lt;?php
86
+ &nbsp;&nbsp;&nbsp;function my_callback($message) {
87
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( my_condition($message) ) {
88
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$message = my_process($message)
89
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
90
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $message;
91
+ &nbsp;&nbsp;&nbsp;}
92
+ &nbsp;&nbsp;&nbsp;add_filter( \'mandrill_payload\', \'my_callback\' );
93
+ ?&gt;
94
+ </pre></blockquote>
95
+ </p>
96
+ <p>'.__('Let\'s say you\'re using the <a href="http://wordpress.org/extend/plugins/cart66-lite/" target="_blank">Cart66 Lite Ecommerce plugin</a> and you want to modify the emails sent from this plugin. Here\'s what you should do:', 'wpmandrill').'</p>
97
+ <p>
98
+ <blockquote><pre>
99
+ &lt;?php
100
+ &nbsp;&nbsp;&nbsp;function cart66Emails($message) {
101
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( in_array( \'wp_Cart66Common::mail\', $message[\'tags\'][\'automatic\'] ) ) {
102
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// do anything funny here...
103
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( isset($message[\'template\'][\'content\'][0][\'content\']) )
104
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$html = &$message[\'template\'][\'content\'][0][\'content\'];
105
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
106
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$html = &$message[\'html\'];
107
+
108
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$html = nl2br($html);
109
+
110
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
111
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $message;
112
+ &nbsp;&nbsp;&nbsp;}
113
+ &nbsp;&nbsp;&nbsp;add_filter( \'mandrill_payload\', \'cart66Emails\' );
114
+ ?&gt;
115
+ </pre></blockquote>
116
+ </p>
117
+ </span>
118
+ ';
119
+ }
120
+
121
+ static function showSectionDirect() {
122
+ echo '
123
+ <span class="setting-description">
124
+ <p>'.__('If you are a Plugin Developer and you need to create a deep integration between Mandrill and your WordPress installation, wpMandrill will make your life easier.', 'wpmandrill').'</p>
125
+ <p>'.__('We have exposed a simple function that allows you to add tags and specify the template to use, in addition to specifying the To, Subject and Body sections of the email:','wpmandrill').'</p>
126
+ <p><blockquote><pre>'.__('&lt;?php wpMandrill::mail($to, $subject, $html, $headers = \'\', $attachments = array(), $tags = array(), $from_name = \'\', $from_email = \'\', $template_name = \'\'); ?&gt;', 'wpmandrill').'</pre></blockquote></p>
127
+ <p>'.__('But if you need Mandrill Powers, we have included a full-featured PHP class called Mandrill. It has every API call defined in Mandrill\'s API. Check it out at <em>/wp-content/plugin/wpmandrill/lib/mandrill.class.php</em>.', 'wpmandrill').'</p>
128
+ <p>'.__('To use it, just instanciate an object passing your API key, and make the calls:', 'wpmandrill').'</p>
129
+ <p><blockquote><pre>'.__('&lt;?php $mandrill = Mandrill($my_api_key); echo $mandrill->ping(); ?&gt;', 'wpmandrill').'</pre></blockquote></p>
130
+ </span>
131
+ ';
132
+ }
133
+
134
+ /**
135
+ * Creates option page's entry in Settings section of menu.
136
+ */
137
+ static function adminMenu() {
138
+
139
+ self::$settings = add_options_page( __('Mandrill How-Tos', 'wpmandrill'), __('Mandrill Test', 'wpmandrill'), 'manage_options', 'wpmandrilltest', array(__CLASS__,'showOptionsPage'));
140
+ }
141
+
142
+ /**
143
+ * Generates source of contextual help panel.
144
+ */
145
+ static function showContextualHelp($contextual_help, $screen_id, $screen) {
146
+
147
+ if ($screen_id == self::$settings) {
148
+
149
+ return '<p>' . __('The purpose of this plugin is to show you how easy it is to start using the awesome platform that Mandrill offers to handle your transactional emails.', 'wpmandrilltest').'</p>'
150
+ . '<ol>'
151
+ . '<li>'. __('Just by setting it up, all the emails sent from your WordPress installation will be sent using the power of Mandrill.', 'wpmandrill') . '</li>'
152
+ . '<li>'. __('If you want further customization, you can use the <strong>mandrill_payload</strong> filter we\'ve provided.', 'wpmandrill') . '</li>'
153
+ . '<li>'. __('And if you want an even greater integration between your application and Mandrill, we\'ve created a convenient call to send emails from within your plugins.', 'wpmandrill') . '</li>'
154
+ . '</ol>'
155
+ .'<p>' . __('You can learn more about all of these features right from this page.', 'wpmandrill').'</p>'
156
+
157
+ ;
158
+ }
159
+
160
+ return $contextual_help;
161
+ }
162
+
163
+ /**
164
+ * Adds link to settings page in list of plugins
165
+ */
166
+ static function showPluginActionLinks($actions, $plugin_file) {
167
+
168
+ static $plugin;
169
+
170
+ if (!isset($plugin))
171
+ $plugin = plugin_basename(__FILE__);
172
+
173
+ if ($plugin == $plugin_file) {
174
+
175
+ $settings = array('settings' => '<a href="options-general.php?page=wpmandrilltest">' . __('Settings', 'wpmandrill') . '</a>');
176
+ $actions = array_merge($settings, $actions);
177
+ }
178
+
179
+ return $actions;
180
+ }
181
+
182
+ /**
183
+ * Generates source of options page.
184
+ */
185
+ static function showOptionsPage() {
186
+
187
+ if (!current_user_can('manage_options'))
188
+ wp_die( __('You do not have sufficient permissions to access this page.','wpmandrill') );
189
+
190
+ ?>
191
+ <div class="wrap">
192
+ <div class="icon32" style="background: url('<?php echo plugins_url('images/mandrill-head-icon.png',__FILE__); ?>');"><br /></div>
193
+ <div style="float: left;width: 70%;">
194
+ <h2><?php _e('Mandrill How-tos', 'wpmandrill'); ?></h2>
195
+
196
+ <form method="post" action="options.php">
197
+ <?php settings_fields('wpmandrilltest'); ?>
198
+ <?php do_settings_sections('wpmandrilltest'); ?>
199
+ </form>
200
+ </div>
201
+ </div>
202
+ <?php
203
+ }
204
+
205
+ /**
206
+ * Opens contextual help section.
207
+ */
208
+ static function openContextualHelp() {
209
+
210
+ if ( !self::isPluginPage() )
211
+ return;
212
+
213
+ ?>
214
+ <script type="text/javascript">
215
+ jQuery(document).bind( 'ready', function() {
216
+ jQuery('a#contextual-help-link').trigger('click');
217
+ });
218
+ </script>
219
+ <?php
220
+ }
221
+ }
222
+
223
+ ?>
images/FreddieHead.png ADDED
Binary file
images/MandrillHead.png ADDED
Binary file
images/icon-ajax-loading.gif ADDED
Binary file
images/mandrill-head-icon.png ADDED
Binary file
images/rss_icon.gif ADDED
Binary file
js/highcharts.js ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Highcharts JS v2.2.1 (2012-03-15)
3
+
4
+ (c) 2009-2011 Torstein H?nsi
5
+
6
+ License: www.highcharts.com/license
7
+ */
8
+ (function(){function L(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a}function za(){for(var a=0,b=arguments,c=b.length,d={};a<c;a++)d[b[a++]]=b[a];return d}function S(a,b){return parseInt(a,b||10)}function Ab(a){return typeof a==="string"}function mb(a){return typeof a==="object"}function Fb(a){return Object.prototype.toString.call(a)==="[object Array]"}function Bb(a){return typeof a==="number"}function nb(a){return oa.log(a)/oa.LN10}function cb(a){return oa.pow(10,a)}function Gb(a,b){for(var c=
9
+ a.length;c--;)if(a[c]===b){a.splice(c,1);break}}function s(a){return a!==X&&a!==null}function A(a,b,c){var d,e;if(Ab(b))s(c)?a.setAttribute(b,c):a&&a.getAttribute&&(e=a.getAttribute(b));else if(s(b)&&mb(b))for(d in b)a.setAttribute(d,b[d]);return e}function Hb(a){return Fb(a)?a:[a]}function p(){var a=arguments,b,c,d=a.length;for(b=0;b<d;b++)if(c=a[b],typeof c!=="undefined"&&c!==null)return c}function P(a,b){if(Qb&&b&&b.opacity!==X)b.filter="alpha(opacity="+b.opacity*100+")";L(a.style,b)}function Aa(a,
10
+ b,c,d,e){a=x.createElement(a);b&&L(a,b);e&&P(a,{padding:0,border:Ma,margin:0});c&&P(a,c);d&&d.appendChild(a);return a}function pa(a,b){var c=function(){};c.prototype=new a;L(c.prototype,b);return c}function dc(a,b,c,d){var e=Ea.lang,f=isNaN(b=Ba(b))?2:b,b=c===void 0?e.decimalPoint:c,d=d===void 0?e.thousandsSep:d,e=a<0?"-":"",c=String(S(a=Ba(+a||0).toFixed(f))),g=c.length>3?c.length%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+Ba(a-c).toFixed(f).slice(2):"")}
11
+ function Na(a,b){return Array((b||2)+1-String(a).length).join(0)+a}function ec(a,b,c,d){var e,c=p(c,1);e=a/c;b||(b=[1,2,2.5,5,10],d&&d.allowDecimals===!1&&(c===1?b=[1,2,5,10]:c<=0.1&&(b=[1/c])));for(d=0;d<b.length;d++)if(a=b[d],e<=(b[d]+(b[d+1]||b[d]))/2)break;a*=c;return a}function Kc(a,b){var c=b||[[Rb,[1,2,5,10,20,25,50,100,200,500]],[ob,[1,2,5,10,15,30]],[pb,[1,2,5,10,15,30]],[va,[1,2,3,4,6,8,12]],[Ca,[1,2]],[Ya,[1,2]],[Da,[1,2,3,4,6]],[Za,null]],d=c[c.length-1],e=E[d[0]],f=d[1],g;for(g=0;g<c.length;g++)if(d=
12
+ c[g],e=E[d[0]],f=d[1],c[g+1]&&a<=(e*f[f.length-1]+E[c[g+1][0]])/2)break;e===E[Za]&&a<5*e&&(f=[1,2,5]);e===E[Za]&&a<5*e&&(f=[1,2,5]);c=ec(a/e,f);return{unitRange:e,count:c,unitName:d[0]}}function Lc(a,b,c,d){var e=[],f={},g=Ea.global.useUTC,h,i=new Date(b),b=a.unitRange,k=a.count;b>=E[ob]&&(i.setMilliseconds(0),i.setSeconds(b>=E[pb]?0:k*Ta(i.getSeconds()/k)));if(b>=E[pb])i[pc](b>=E[va]?0:k*Ta(i[fc]()/k));if(b>=E[va])i[qc](b>=E[Ca]?0:k*Ta(i[gc]()/k));if(b>=E[Ca])i[hc](b>=E[Da]?1:k*Ta(i[db]()/k));b>=
13
+ E[Da]&&(i[rc](b>=E[Za]?0:k*Ta(i[qb]()/k)),h=i[rb]());b>=E[Za]&&(h-=h%k,i[sc](h));if(b===E[Ya])i[hc](i[db]()-i[ic]()+p(d,1));d=1;h=i[rb]();for(var j=i.getTime(),l=i[qb](),i=i[db]();j<c;)e.push(j),b===E[Za]?j=sb(h+d*k,0):b===E[Da]?j=sb(h,l+d*k):!g&&(b===E[Ca]||b===E[Ya])?j=sb(h,l,i+d*k*(b===E[Ca]?1:7)):(j+=b*k,b<=E[va]&&j%E[Ca]===0&&(f[j]=Ca)),d++;e.push(j);e.info=L(a,{higherRanks:f,totalRange:b*k});return e}function tc(){this.symbol=this.color=0}function uc(a,b,c,d,e,f,g,h,i){var k=g.x,g=g.y,i=k+c+
14
+ (i?h:-a-h),j=g-b+d+15,l;i<7&&(i=c+k+h);i+a>c+e&&(i-=i+a-(c+e),j=g-b+d-h,l=!0);j<d+5?(j=d+5,l&&g>=j&&g<=j+b&&(j=g+d+h)):j+b>d+f&&(j=d+f-b-h);return{x:i,y:j}}function Mc(a,b){var c=a.length,d,e;for(e=0;e<c;e++)a[e].ss_i=e;a.sort(function(a,c){d=b(a,c);return d===0?a.ss_i-c.ss_i:d});for(e=0;e<c;e++)delete a[e].ss_i}function Sb(a){for(var b=a.length,c=a[0];b--;)a[b]<c&&(c=a[b]);return c}function Ib(a){for(var b=a.length,c=a[0];b--;)a[b]>c&&(c=a[b]);return c}function Jb(a){for(var b in a)a[b]&&a[b].destroy&&
15
+ a[b].destroy(),delete a[b]}function Tb(a){tb||(tb=Aa(Ra));a&&tb.appendChild(a);tb.innerHTML=""}function jc(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw c;else ca.console&&console.log(c)}function Cb(a){return parseFloat(a.toPrecision(14))}function Kb(a,b){Ub=p(a,b.animation)}function vc(){var a=Ea.global.useUTC,b=a?"getUTC":"get",c=a?"setUTC":"set";sb=a?Date.UTC:function(a,b,c,g,h,i){return(new Date(a,b,p(c,1),p(g,0),p(h,0),p(i,0))).getTime()};fc=b+"Minutes";gc=b+"Hours";
16
+ ic=b+"Day";db=b+"Date";qb=b+"Month";rb=b+"FullYear";pc=c+"Minutes";qc=c+"Hours";hc=c+"Date";rc=c+"Month";sc=c+"FullYear"}function Sa(){}function wc(a,b){function c(a){function b(a,c){this.pos=a;this.type=c||"";this.isNew=!0;c||this.addLabel()}function c(a){if(a)this.options=a,this.id=a.id;return this}function d(a,b,c,e){this.isNegative=b;this.options=a;this.x=c;this.stack=e;this.alignOptions={align:a.align||(U?b?"left":"right":"center"),verticalAlign:a.verticalAlign||(U?"middle":b?"bottom":"top"),
17
+ y:p(a.y,U?4:b?14:-6),x:p(a.x,U?b?-6:6:0)};this.textAlign=a.textAlign||(U?b?"right":"left":"center")}function e(){var a=[],b=[],c;C=M=null;o(B.series,function(e){if(e.visible||!q.ignoreHiddenSeries){var f=e.options,g,h,i,j,k,m,l,n,Y,ea=f.threshold,B,o=[],xc=0;if(R&&ea<=0)ea=f.threshold=null;if(t)f=e.xData,f.length&&(C=Ua(p(C,f[0]),Sb(f)),M=W(p(M,f[0]),Ib(f)));else{var y,r,G,v=e.cropped,Z=e.xAxis.getExtremes(),V=!!e.modifyValue;g=f.stacking;Ha=g==="percent";if(g)k=f.stack,j=e.type+p(k,""),m="-"+j,e.stackKey=
18
+ j,h=a[j]||[],a[j]=h,i=b[m]||[],b[m]=i;Ha&&(C=0,M=99);f=e.processedXData;l=e.processedYData;B=l.length;for(c=0;c<B;c++)if(n=f[c],Y=l[c],Y!==null&&Y!==X&&(g?(r=(y=Y<ea)?i:h,G=y?m:j,Y=r[n]=s(r[n])?r[n]+Y:Y,qa[G]||(qa[G]={}),qa[G][n]||(qa[G][n]=new d(u.stackLabels,y,n,k)),qa[G][n].setTotal(Y)):V&&(Y=e.modifyValue(Y)),v||(f[c+1]||n)>=Z.min&&(f[c-1]||n)<=Z.max))if(n=Y.length)for(;n--;)Y[n]!==null&&(o[xc++]=Y[n]);else o[xc++]=Y;!Ha&&o.length&&(C=Ua(p(C,o[0]),Sb(o)),M=W(p(M,o[0]),Ib(o)));s(ea)&&(C>=ea?(C=
19
+ ea,Ma=!0):M<ea&&(M=ea,Na=!0))}}})}function f(a,b,c){for(var d,b=Cb(Ta(b/a)*a),c=Cb(Yb(c/a)*a),e=[];b<=c;){e.push(b);b=Cb(b+a);if(b===d)break;d=b}return e}function g(a,b,c,d){var e=[];if(!d)B._minorAutoInterval=null;if(a>=0.5)a=z(a),e=f(a,b,c);else if(a>=0.08){var h=Ta(b),i,j,k,n,m,l;for(i=a>0.3?[1,2,4]:a>0.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];h<c+1&&!l;h++){k=i.length;for(j=0;j<k&&!l;j++)n=nb(cb(h)*i[j]),n>b&&e.push(m),m>c&&(l=!0),m=n}}else if(b=cb(b),c=cb(c),a=u[d?"minorTickInterval":"tickInterval"],
20
+ a=p(a==="auto"?null:a,B._minorAutoInterval,(c-b)*(u.tickPixelInterval/(d?5:1))/((d?D/N.length:D)||1)),a=ec(a,null,oa.pow(10,Ta(oa.log(a)/oa.LN10))),e=Vb(f(a,b,c),nb),!d)B._minorAutoInterval=a/5;d||(Oa=a);return e}function h(){var a=[],b,c;if(R){c=N.length;for(b=1;b<c;b++)a=a.concat(g(Ga,N[b-1],N[b],!0))}else for(b=F+(N[0]-F)%Ga;b<=H;b+=Ga)a.push(b);return a}function i(){var a,b=M-C>=fb,c,d,e,f,g,h;t&&fb===X&&!R&&(s(u.min)||s(u.max)?fb=null:(o(B.series,function(a){f=a.xData;for(d=g=a.xIncrement?1:
21
+ f.length-1;d>0;d--)if(e=f[d]-f[d-1],c===X||e<c)c=e}),fb=Ua(c*5,M-C)));H-F<fb&&(a=(fb-H+F)/2,a=[F-a,p(u.min,F-a)],b&&(a[2]=C),F=Ib(a),h=[F+fb,p(u.max,F+fb)],b&&(h[2]=M),H=Sb(h),H-F<fb&&(a[0]=H-fb,a[1]=p(u.min,H-fb),F=Ib(a)))}function j(a){var b,c=u.tickInterval,d=u.tickPixelInterval;da?(na=m[t?"xAxis":"yAxis"][u.linkedTo],b=na.getExtremes(),F=p(b.min,b.dataMin),H=p(b.max,b.dataMax),u.type!==na.options.type&&jc(11,1)):(F=p(ba,u.min,C),H=p(ca,u.max,M));R&&(!a&&Ua(F,C)<=0&&jc(10,1),F=nb(F),H=nb(H));ja&&
22
+ (ba=F=W(F,H-ja),ca=H,a&&(ja=null));i();if(!Va&&!Ha&&!da&&s(F)&&s(H)){b=H-F||1;if(!s(u.min)&&!s(ba)&&Ea&&(C<0||!Ma))F-=b*Ea;if(!s(u.max)&&!s(ca)&&Ja&&(M>0||!Na))H+=b*Ja}Oa=F===H||F===void 0||H===void 0?1:da&&!c&&d===na.options.tickPixelInterval?na.tickInterval:p(c,Va?1:(H-F)*d/(D||1));t&&!a&&o(B.series,function(a){a.processData(F!==ma||H!==za)});ib();B.beforeSetTickPositions&&B.beforeSetTickPositions();B.postProcessTickInterval&&(Oa=B.postProcessTickInterval(Oa));!V&&!R&&(Wa=oa.pow(10,Ta(oa.log(Oa)/
23
+ oa.LN10)),s(u.tickInterval)||(Oa=ec(Oa,null,Wa,u)));B.tickInterval=Oa;Ga=u.minorTickInterval==="auto"&&Oa?Oa/5:u.minorTickInterval;(N=u.tickPositions||Xa&&Xa.apply(B,[F,H]))||(N=V?(B.getNonLinearTimeTicks||Lc)(Kc(Oa,u.units),F,H,u.startOfWeek,B.ordinalPositions,B.closestPointRange,!0):R?g(Oa,F,H):f(Oa,F,H));if(!da&&(a=N[0],c=N[N.length-1],u.startOnTick?F=a:F>a&&N.shift(),u.endOnTick?H=c:H<c&&N.pop(),gb||(gb={x:0,y:0}),!V&&N.length>gb[w]&&u.alignTicks!==!1))gb[w]=N.length}function k(a){a=(new c(a)).render();
24
+ ta.push(a);return a}function l(){var a=u.title,d=u.stackLabels,e=u.alternateGridColor,f=u.lineWidth,g,i,j=m.hasRendered&&s(ma)&&!isNaN(ma),n=(g=B.series.length&&s(F)&&s(H))||p(u.showEmpty,!0),Y,q;if(g||da)if(Ga&&!Va&&o(h(),function(a){va[a]||(va[a]=new b(a,"minor"));j&&va[a].isNew&&va[a].render(null,!0);va[a].isActive=!0;va[a].render()}),o(N.slice(1).concat([N[0]]),function(a,c){c=c===N.length-1?0:c+1;if(!da||a>=F&&a<=H)Pa[a]||(Pa[a]=new b(a)),j&&Pa[a].isNew&&Pa[a].render(c,!0),Pa[a].isActive=!0,
25
+ Pa[a].render(c)}),e&&o(N,function(a,b){if(b%2===0&&a<H)Da[a]||(Da[a]=new c),Y=a,q=N[b+1]!==X?N[b+1]:H,Da[a].options={from:R?cb(Y):Y,to:R?cb(q):q,color:e},Da[a].render(),Da[a].isActive=!0}),!B._addedPlotLB)o((u.plotLines||[]).concat(u.plotBands||[]),function(a){k(a)}),B._addedPlotLB=!0;o([Pa,va,Da],function(a){for(var b in a)a[b].isActive?a[b].isActive=!1:(a[b].destroy(),delete a[b])});f&&(g=x+(y?A:0)+T,i=ra-Lb-(y?hb:0)+T,g=I.crispLine([wa,G?x:g,G?i:E,fa,G?sa-Zb:g,G?i:ra-Lb],f),$?$.animate({d:g}):
26
+ $=I.path(g).attr({stroke:u.lineColor,"stroke-width":f,zIndex:7}).add(),$[n?"show":"hide"]());if(v&&n)n=G?x:E,f=S(a.style.fontSize||12),n={low:n+(G?0:D),middle:n+D/2,high:n+(G?D:0)}[a.align],f=(G?E+hb:x)+(G?1:-1)*(y?-1:1)*Ya+(r===2?f:0),v[v.isNew?"attr":"animate"]({x:G?n:f+(y?A:0)+T+(a.x||0),y:G?f-(y?hb:0)+T:n+(a.y||0)}),v.isNew=!1;if(d&&d.enabled){var t,yc,d=B.stackTotalGroup;if(!d)B.stackTotalGroup=d=I.g("stack-labels").attr({visibility:eb,zIndex:6}).translate(O,J).add();for(t in qa)for(yc in a=
27
+ qa[t],a)a[yc].render(d)}B.isDirty=!1}function n(a){for(var b=ta.length;b--;)ta[b].id===a&&ta[b].destroy()}var t=a.isX,y=a.opposite,G=U?!t:t,r=G?y?0:2:y?1:3,qa={},u=K(t?$b:kc,[Nc,Oc,zc,Pc][r],a),B=this,v,Z=u.type,V=Z==="datetime",R=Z==="logarithmic",T=u.offset||0,w=t?"x":"y",D=0,ua,ia,bb,jb,x,E,A,hb,Lb,Zb,Mb,ib,P,Q,bc,$,C,M,fb=u.minRange||u.maxZoom,ja=u.range,ba,ca,Aa,Ca,H=null,F=null,ma,za,Ea=u.minPadding,Ja=u.maxPadding,Ka=0,da=s(u.linkedTo),na,Ma,Na,Ha,Z=u.events,Sa,ta=[],Oa,Ga,Wa,N,Xa=u.tickPositioner,
28
+ Pa={},va={},Da={},Fa,La,Ya,Va=u.categories,db=u.labels.formatter||function(){var a=this.value,b=this.dateTimeLabelFormat;return b?ac(b,a):Oa%1E6===0?a/1E6+"M":Oa%1E3===0?a/1E3+"k":!Va&&a>=1E3?dc(a,0):a},Ra=G&&u.labels.staggerLines,ya=u.reversed,Ia=Va&&u.tickmarkPlacement==="between"?0.5:0;b.prototype={addLabel:function(){var a=this.pos,b=u.labels,c=Va&&G&&Va.length&&!b.step&&!b.staggerLines&&!b.rotation&&ka/Va.length||!G&&ka/2,d=a===N[0],e=a===N[N.length-1],f=Va&&s(Va[a])?Va[a]:a,g=this.label,h=N.info,
29
+ i;V&&h&&(i=u.dateTimeLabelFormats[h.higherRanks[a]||h.unitName]);this.isFirst=d;this.isLast=e;a=db.call({axis:B,chart:m,isFirst:d,isLast:e,dateTimeLabelFormat:i,value:R?Cb(cb(f)):f});c=c&&{width:W(1,z(c-2*(b.padding||10)))+ga};c=L(c,b.style);s(g)?g&&g.attr({text:a}).css(c):this.label=s(a)&&b.enabled?I.text(a,0,0,b.useHTML).attr({align:b.align,rotation:b.rotation}).css(c).add(Q):null},getLabelSize:function(){var a=this.label;return a?(this.labelBBox=a.getBBox())[G?"height":"width"]:0},getLabelSides:function(){var a=
30
+ u.labels,b=this.labelBBox.width,a=b*{left:0,center:0.5,right:1}[a.align]-a.x;return[-a,b-a]},handleOverflow:function(a){var b=!0,c=this.isFirst,d=this.isLast,e=this.label,f=e.x;if(c||d){var g=this.getLabelSides(),h=g[0],g=g[1],i=m.plotLeft,j=i+B.len,k=(a=Pa[N[a+(c?1:-1)]])&&a.label.x+a.getLabelSides()[c?0:1];c&&!ya||d&&ya?f+h<i&&(f=i-h,a&&f+g>k&&(b=!1)):f+g>j&&(f=j-g,a&&f+h<k&&(b=!1));e.x=f}return b},render:function(a,b){var c=this.type,d=this.label,e=this.pos,f=u.labels,g=this.gridLine,h=c?c+"Grid":
31
+ "grid",i=c?c+"Tick":"tick",j=u[h+"LineWidth"],k=u[h+"LineColor"],n=u[h+"LineDashStyle"],m=u[i+"Length"],h=u[i+"Width"]||0,l=u[i+"Color"],Y=u[i+"Position"],i=this.mark,q=f.step,ea=b&&Za||ra,qa=!0,o;o=G?Mb(e+Ia,null,null,b)+bb:x+T+(y?(b&&$a||sa)-Zb-x:0);ea=G?ea-Lb+T-(y?hb:0):ea-Mb(e+Ia,null,null,b)-bb;if(j){e=P(e+Ia,j,b);if(g===X){g={stroke:k,"stroke-width":j};if(n)g.dashstyle=n;if(!c)g.zIndex=1;this.gridLine=g=j?I.path(e).attr(g).add(bc):null}!b&&g&&e&&g.animate({d:e})}if(h)Y==="inside"&&(m=-m),y&&
32
+ (m=-m),c=I.crispLine([wa,o,ea,fa,o+(G?0:-m),ea+(G?m:0)],h),i?i.animate({d:c}):this.mark=I.path(c).attr({stroke:l,"stroke-width":h}).add(Q);if(d&&!isNaN(o))o=o+f.x-(Ia&&G?Ia*ia*(ya?-1:1):0),ea=ea+f.y-(Ia&&!G?Ia*ia*(ya?1:-1):0),s(f.y)||(ea+=S(d.styles.lineHeight)*0.9-d.getBBox().height/2),Ra&&(ea+=a/(q||1)%Ra*16),d.x=o,d.y=ea,this.isFirst&&!p(u.showFirstLabel,1)||this.isLast&&!p(u.showLastLabel,1)?qa=!1:!Ra&&G&&f.overflow==="justify"&&!this.handleOverflow(a)&&(qa=!1),q&&a%q&&(qa=!1),qa?(d[this.isNew?
33
+ "attr":"animate"]({x:d.x,y:d.y}),d.show(),this.isNew=!1):d.hide()},destroy:function(){Jb(this)}};c.prototype={render:function(){var a=this,b=(B.pointRange||0)/2,c=a.options,d=c.label,e=a.label,f=c.width,g=c.to,h=c.from,i=c.value,j,k=c.dashStyle,n=a.svgElem,m=[],l,Y,u=c.color;Y=c.zIndex;var ea=c.events;R&&(h=nb(h),g=nb(g),i=nb(i));if(f){if(m=P(i,f),b={stroke:u,"stroke-width":f},k)b.dashstyle=k}else if(s(h)&&s(g))h=W(h,F-b),g=Ua(g,H+b),j=P(g),(m=P(h))&&j?m.push(j[4],j[5],j[1],j[2]):m=null,b={fill:u};
34
+ else return;if(s(Y))b.zIndex=Y;if(n)m?n.animate({d:m},null,n.onGetPath):(n.hide(),n.onGetPath=function(){n.show()});else if(m&&m.length&&(a.svgElem=n=I.path(m).attr(b).add(),ea))for(l in k=function(b){n.on(b,function(c){ea[b].apply(a,[c])})},ea)k(l);if(d&&s(d.text)&&m&&m.length&&A>0&&hb>0){d=K({align:G&&j&&"center",x:G?!j&&4:10,verticalAlign:!G&&j&&"middle",y:G?j?16:10:j?6:-4,rotation:G&&!j&&90},d);if(!e)a.label=e=I.text(d.text,0,0).attr({align:d.textAlign||d.align,rotation:d.rotation,zIndex:Y}).css(d.style).add();
35
+ j=[m[1],m[4],p(m[6],m[1])];m=[m[2],m[5],p(m[7],m[2])];l=Sb(j);Y=Sb(m);e.align(d,!1,{x:l,y:Y,width:Ib(j)-l,height:Ib(m)-Y});e.show()}else e&&e.hide();return a},destroy:function(){Jb(this);Gb(ta,this)}};d.prototype={destroy:function(){Jb(this)},setTotal:function(a){this.cum=this.total=a},render:function(a){var b=this.options.formatter.call(this);this.label?this.label.attr({text:b,visibility:ab}):this.label=m.renderer.text(b,0,0).css(this.options.style).attr({align:this.textAlign,rotation:this.options.rotation,
36
+ visibility:ab}).add(a)},setOffset:function(a,b){var c=this.isNegative,d=B.translate(this.total,0,0,0,1),e=B.translate(0),e=Ba(d-e),f=m.xAxis[0].translate(this.x)+a,g=m.plotHeight,c={x:U?c?d:d-e:f,y:U?g-f-b:c?g-d-e:g-d,width:U?e:b,height:U?b:e};this.label&&this.label.align(this.alignOptions,null,c).attr({visibility:eb})}};Mb=function(a,b,c,d,e){var f=1,g=0,h=d?jb:ia,d=d?ma:F,e=u.ordinal||R&&e;h||(h=ia);c&&(f*=-1,g=D);ya&&(f*=-1,g-=f*D);b?(ya&&(a=D-a),a=a/h+d,e&&(a=B.lin2val(a))):(e&&(a=B.val2lin(a)),
37
+ a=f*(a-d)*h+g+f*Ka);return a};P=function(a,b,c){var d,e,f,a=Mb(a,null,null,c),g=c&&Za||ra,h=c&&$a||sa,i,c=e=z(a+bb);d=f=z(g-a-bb);if(isNaN(a))i=!0;else if(G){if(d=E,f=g-Lb,c<x||c>x+A)i=!0}else if(c=x,e=h-Zb,d<E||d>E+hb)i=!0;return i?null:I.crispLine([wa,c,d,fa,e,f],b||0)};ib=function(){var a=H-F,b=0,c,d;if(t)da?b=na.pointRange:o(B.series,function(a){b=W(b,a.pointRange);d=a.closestPointRange;!a.noSharedTooltip&&s(d)&&(c=s(c)?Ua(c,d):d)}),B.pointRange=b,B.closestPointRange=c;jb=ia;B.translationSlope=
38
+ ia=D/(a+b||1);bb=G?x:Lb;Ka=ia*(b/2)};xa.push(B);m[t?"xAxis":"yAxis"].push(B);U&&t&&ya===X&&(ya=!0);L(B,{addPlotBand:k,addPlotLine:k,adjustTickAmount:function(){if(gb&&gb[w]&&!V&&!Va&&!da&&u.alignTicks!==!1){var a=Fa,b=N.length;Fa=gb[w];if(b<Fa){for(;N.length<Fa;)N.push(Cb(N[N.length-1]+Oa));ia*=(b-1)/(Fa-1);H=N[N.length-1]}if(s(a)&&Fa!==a)B.isDirty=!0}},categories:Va,getExtremes:function(){return{min:R?Cb(cb(F)):F,max:R?Cb(cb(H)):H,dataMin:C,dataMax:M,userMin:ba,userMax:ca}},getPlotLinePath:P,getThreshold:function(a){var b=
39
+ R?cb(F):F,c=R?cb(H):H;b>a||a===null?a=b:c<a&&(a=c);return Mb(a,0,1,0,1)},isXAxis:t,options:u,plotLinesAndBands:ta,getOffset:function(){var a=B.series.length&&s(F)&&s(H),c=a||p(u.showEmpty,!0),d=0,e,f=0,g=u.title,h=u.labels,i=[-1,1,1,-1][r],j;Q||(Q=I.g("axis").attr({zIndex:7}).add(),bc=I.g("grid").attr({zIndex:u.gridZIndex||1}).add());La=0;if(a||da)o(N,function(a){Pa[a]?Pa[a].addLabel():Pa[a]=new b(a)}),o(N,function(a){if(r===0||r===2||{1:"left",3:"right"}[r]===h.align)La=W(Pa[a].getLabelSize(),La)}),
40
+ Ra&&(La+=(Ra-1)*16);else for(j in Pa)Pa[j].destroy(),delete Pa[j];if(g&&g.text){if(!v)v=B.axisTitle=I.text(g.text,0,0,g.useHTML).attr({zIndex:7,rotation:g.rotation||0,align:g.textAlign||{low:"left",middle:"center",high:"right"}[g.align]}).css(g.style).add(),v.isNew=!0;if(c)d=v.getBBox()[G?"height":"width"],f=p(g.margin,G?5:10),e=g.offset;v[c?"show":"hide"]()}T=i*p(u.offset,pa[r]);Ya=p(e,La+f+(r!==2&&La&&i*u.labels[G?"y":"x"]));pa[r]=W(pa[r],Ya+d+i*T)},render:l,setAxisSize:function(){var a=u.offsetLeft||
41
+ 0,b=u.offsetRight||0;x=p(u.left,O+a);E=p(u.top,J);A=p(u.width,ka-a+b);hb=p(u.height,la);Lb=ra-hb-E;Zb=sa-A-x;D=G?A:hb;B.left=x;B.top=E;B.len=D},setAxisTranslation:ib,setCategories:function(b,c){B.categories=a.categories=Va=b;o(B.series,function(a){a.translate();a.setTooltipPoints(!0)});B.isDirty=!0;p(c,!0)&&m.redraw()},setExtremes:function(a,b,c,d,e){c=p(c,!0);e=L(e,{min:a,max:b});aa(B,"setExtremes",e,function(){ba=a;ca=b;B.isDirtyExtremes=!0;c&&m.redraw(d)})},setScale:function(){var a,b,c,d;ma=F;
42
+ za=H;ua=D;D=G?A:hb;d=D!==ua;o(B.series,function(a){if(a.isDirtyData||a.isDirty||a.xAxis.isDirty)c=!0});if(d||c||da||ba!==Aa||ca!==Ca){e();j();Aa=ba;Ca=ca;if(!t)for(a in qa)for(b in qa[a])qa[a][b].cum=qa[a][b].total;if(!B.isDirty)B.isDirty=d||F!==ma||H!==za}},setTickPositions:j,translate:Mb,redraw:function(){ub.resetTracker&&ub.resetTracker();l();o(ta,function(a){a.render()});o(B.series,function(a){a.isDirty=!0})},removePlotBand:n,removePlotLine:n,reversed:ya,setTitle:function(a,b){u.title=K(u.title,
43
+ a);v=v.destroy();B.isDirty=!0;p(b,!0)&&m.redraw()},series:[],stacks:qa,destroy:function(){var a;Qa(B);for(a in qa)Jb(qa[a]),qa[a]=null;if(B.stackTotalGroup)B.stackTotalGroup=B.stackTotalGroup.destroy();o([Pa,va,Da,ta],function(a){Jb(a)});o([$,Q,bc,v],function(a){a&&a.destroy()});$=Q=bc=v=null}});for(Sa in Z)ha(B,Sa,Z[Sa]);if(R)B.val2lin=nb,B.lin2val=cb}function d(a){function b(){var c=this.points||Hb(this),d=c[0].series,e;e=[d.tooltipHeaderFormatter(c[0].key)];o(c,function(a){d=a.series;e.push(d.tooltipFormatter&&
44
+ d.tooltipFormatter(a)||a.point.tooltipFormatter(d.tooltipOptions.pointFormat))});e.push(a.footerFormat||"");return e.join("")}function c(a,b){l=n?a:(2*l+a)/3;q=n?b:(q+b)/2;t.attr({x:l,y:q});lb=Ba(a-l)>1||Ba(b-q)>1?function(){c(a,b)}:null}function d(){if(!n){var a=m.hoverPoints;t.hide();a&&o(a,function(a){a.setState()});m.hoverPoints=null;n=!0}}var e,f=a.borderWidth,g=a.crosshairs,h=[],i=a.style,j=a.shared,k=S(i.padding),n=!0,l=0,q=0;i.padding=0;var t=I.label("",0,0,null,null,null,a.useHTML).attr({padding:k,
45
+ fill:a.backgroundColor,"stroke-width":f,r:a.borderRadius,zIndex:8}).css(i).hide().add();Fa||t.shadow(a.shadow);return{shared:j,refresh:function(f){var i,k,l,q,r={},y=[];l=f.tooltipPos;i=a.formatter||b;var r=m.hoverPoints,v;j&&(!f.series||!f.series.noSharedTooltip)?(q=0,r&&o(r,function(a){a.setState()}),m.hoverPoints=f,o(f,function(a){a.setState(ta);q+=a.plotY;y.push(a.getLabelConfig())}),k=f[0].plotX,q=z(q)/f.length,r={x:f[0].category},r.points=y,f=f[0]):r=f.getLabelConfig();r=i.call(r);e=f.series;
46
+ k=p(k,f.plotX);q=p(q,f.plotY);i=z(l?l[0]:U?ka-q:k);k=z(l?l[1]:U?la-k:q);l=j||!e.isCartesian||e.tooltipOutsidePlot||Db(i,k);r===!1||!l?d():(n&&(t.show(),n=!1),t.attr({text:r}),v=a.borderColor||f.color||e.color||"#606060",t.attr({stroke:v}),l=uc(t.width,t.height,O,J,ka,la,{x:i,y:k},p(a.distance,12),U),c(z(l.x),z(l.y)));if(g){g=Hb(g);var R;l=g.length;for(var Z;l--;)if(R=f.series[l?"yAxis":"xAxis"],g[l]&&R)if(R=R.getPlotLinePath(l?p(f.stackY,f.y):f.x,1),h[l])h[l].attr({d:R,visibility:eb});else{Z={"stroke-width":g[l].width||
47
+ 1,stroke:g[l].color||"#C0C0C0",zIndex:g[l].zIndex||2};if(g[l].dashStyle)Z.dashstyle=g[l].dashStyle;h[l]=I.path(R).attr(Z).add()}}aa(m,"tooltipRefresh",{text:r,x:i+O,y:k+J,borderColor:v})},hide:d,hideCrosshairs:function(){o(h,function(a){a&&a.hide()})},destroy:function(){o(h,function(a){a&&a.destroy()});t&&(t=t.destroy())}}}function e(a){function b(a){var c,d,e,a=a||ca.event;if(!a.target)a.target=a.srcElement;if(a.originalEvent)a=a.originalEvent;if(a.event)a=a.event;c=a.touches?a.touches.item(0):a;
48
+ ya=Ac(D);d=ya.left;e=ya.top;Qb?(d=a.x,c=a.y):(d=c.pageX-d,c=c.pageY-e);return L(a,{chartX:z(d),chartY:z(c)})}function c(a){var b={xAxis:[],yAxis:[]};o(xa,function(c){var d=c.translate,e=c.isXAxis;b[e?"xAxis":"yAxis"].push({axis:c,value:d((U?!e:e)?a.chartX-O:la-a.chartY+J,!0)})});return b}function e(){var a=m.hoverSeries,b=m.hoverPoint;if(b)b.onMouseOut();if(a)a.onMouseOut();vb&&(vb.hide(),vb.hideCrosshairs());ob=null}function f(){if(n){var a={xAxis:[],yAxis:[]},b=n.getBBox(),c=b.x-O,d=b.y-J;k&&(o(xa,
49
+ function(e){if(e.options.zoomEnabled!==!1){var f=e.translate,g=e.isXAxis,h=U?!g:g,i=f(h?c:la-d-b.height,!0,0,0,1),f=f(h?c+b.width:la-d,!0,0,0,1);a[g?"xAxis":"yAxis"].push({axis:e,min:Ua(i,f),max:W(i,f)})}}),aa(m,"selection",a,zb));n=n.destroy()}P(D,{cursor:"auto"});m.mouseIsDown=Da=k=!1;Qa(x,Ga?"touchend":"mouseup",f)}function g(a){var b=s(a.pageX)?a.pageX:a.page.x,a=s(a.pageX)?a.pageY:a.page.y;ya&&!Db(b-ya.left-O,a-ya.top-J)&&e()}function h(){e();ya=null}var i,j,k,n,l=Fa?"":q.zoomType,t=/x/.test(l),
50
+ r=/y/.test(l),y=t&&!U||r&&U,p=r&&!U||t&&U;if(!db)m.trackerGroup=db=I.g("tracker").attr({zIndex:9}).add();if(a.enabled)m.tooltip=vb=d(a),Bb=setInterval(function(){lb&&lb()},32);(function(){D.onmousedown=function(a){a=b(a);!Ga&&a.preventDefault&&a.preventDefault();m.mouseIsDown=Da=!0;m.mouseDownX=i=a.chartX;j=a.chartY;ha(x,Ga?"touchend":"mouseup",f)};var d=function(c){if(!c||!(c.touches&&c.touches.length>1)){c=b(c);if(!Ga)c.returnValue=!1;var d=c.chartX,e=c.chartY,f=!Db(d-O,e-J);Ga&&c.type==="touchstart"&&
51
+ (A(c.target,"isTracker")?m.runTrackerClick||c.preventDefault():!kb&&!f&&c.preventDefault());f&&(d<O?d=O:d>O+ka&&(d=O+ka),e<J?e=J:e>J+la&&(e=J+la));if(Da&&c.type!=="touchstart"){if(k=Math.sqrt(Math.pow(i-d,2)+Math.pow(j-e,2)),k>10){var g=Db(i-O,j-J);if(Nb&&(t||r)&&g)n||(n=I.rect(O,J,y?1:ka,p?1:la,0).attr({fill:q.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add());n&&y&&(c=d-i,n.attr({width:Ba(c),x:(c>0?0:c)+i}));n&&p&&(e-=j,n.attr({height:Ba(e),y:(e>0?0:e)+j}));g&&!n&&q.panning&&m.pan(d)}}else if(!f){var h,
52
+ d=m.hoverPoint,e=m.hoverSeries,l,o,g=sa,R=U?c.chartY:c.chartX-O;if(vb&&a.shared&&(!e||!e.noSharedTooltip)){h=[];l=Q.length;for(o=0;o<l;o++)if(Q[o].visible&&Q[o].options.enableMouseTracking!==!1&&!Q[o].noSharedTooltip&&Q[o].tooltipPoints.length)c=Q[o].tooltipPoints[R],c._dist=Ba(R-c.plotX),g=Ua(g,c._dist),h.push(c);for(l=h.length;l--;)h[l]._dist>g&&h.splice(l,1);if(h.length&&h[0].plotX!==ob)vb.refresh(h),ob=h[0].plotX}if(e&&e.tracker&&(c=e.tooltipPoints[R])&&c!==d)c.onMouseOver()}return f||!Nb}};D.onmousemove=
53
+ d;ha(D,"mouseleave",h);ha(x,"mousemove",g);D.ontouchstart=function(a){if(t||r)D.onmousedown(a);d(a)};D.ontouchmove=d;D.ontouchend=function(){k&&e()};D.onclick=function(a){var d=m.hoverPoint,a=b(a);a.cancelBubble=!0;if(!k)if(d&&(A(a.target,"isTracker")||A(a.target.parentNode,"isTracker"))){var e=d.plotX,f=d.plotY;L(d,{pageX:ya.left+O+(U?ka-f:e),pageY:ya.top+J+(U?la-e:f)});aa(d.series,"click",L(a,{point:d}));d.firePointEvent("click",a)}else L(a,c(a)),Db(a.chartX-O,a.chartY-J)&&aa(m,"click",a);k=!1}})();
54
+ L(this,{zoomX:t,zoomY:r,resetTracker:e,normalizeMouseEvent:b,destroy:function(){if(m.trackerGroup)m.trackerGroup=db=m.trackerGroup.destroy();Qa(D,"mouseleave",h);Qa(x,"mousemove",g);D.onclick=D.onmousedown=D.onmousemove=D.ontouchstart=D.ontouchend=D.ontouchmove=null}})}function f(a){var b=a.type||q.type||q.defaultSeriesType,c=Ha[b],d=m.hasRendered;if(d)if(U&&b==="column")c=Ha.bar;else if(!U&&b==="bar")c=Ha.column;b=new c;b.init(m,a);!d&&b.inverted&&(U=!0);if(b.isCartesian)Nb=b.isCartesian;Q.push(b);
55
+ return b}function g(){q.alignTicks!==!1&&o(xa,function(a){a.adjustTickAmount()});gb=null}function h(a){var b=m.isDirtyLegend,c,d=m.isDirtyBox,e=Q.length,f=e,h=m.clipRect;for(Kb(a,m);f--;)if(a=Q[f],a.isDirty&&a.options.stacking){c=!0;break}if(c)for(f=e;f--;)if(a=Q[f],a.options.stacking)a.isDirty=!0;o(Q,function(a){a.isDirty&&a.options.legendType==="point"&&(b=!0)});if(b&&Xa.renderLegend)Xa.renderLegend(),m.isDirtyLegend=!1;Nb&&(La||(gb=null,o(xa,function(a){a.setScale()})),g(),Wb(),o(xa,function(a){if(a.isDirtyExtremes)a.isDirtyExtremes=
56
+ !1,aa(a,"afterSetExtremes",a.getExtremes());if(a.isDirty||d)a.redraw(),d=!0}));d&&(qb(),h&&(Ob(h),h.animate({width:m.plotSizeX,height:m.plotSizeY+1})));o(Q,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()});ub&&ub.resetTracker&&ub.resetTracker();I.draw();aa(m,"redraw")}function i(){var a=v.xAxis||{},b=v.yAxis||{},a=Hb(a);o(a,function(a,b){a.index=b;a.isX=!0});b=Hb(b);o(b,function(a,b){a.index=b});a=a.concat(b);o(a,function(a){new c(a)});g()}function k(){var a=Ea.lang,b=q.resetZoomButton,
57
+ c=b.theme,d=c.states,e=b.relativeTo==="chart"?null:{x:O,y:J,width:ka,height:la};m.resetZoomButton=I.button(a.resetZoom,null,null,Fb,c,d&&d.hover).attr({align:b.position.align,title:a.resetZoomTitle}).add().align(b.position,!1,e)}function j(a,b){$=K(v.title,a);ja=K(v.subtitle,b);o([["title",a,$],["subtitle",b,ja]],function(a){var b=a[0],c=m[b],d=a[1],a=a[2];c&&d&&(c=c.destroy());a&&a.text&&!c&&(m[b]=I.text(a.text,0,0,a.useHTML).attr({align:a.align,"class":Ia+b,zIndex:a.zIndex||4}).css(a.style).add().align(a,
58
+ !1,ib))})}function l(){Ja=q.renderTo;na=Ia+lc++;Ab(Ja)&&(Ja=x.getElementById(Ja));Ja||jc(13,!0);Ja.innerHTML="";Ja.offsetWidth||(C=Ja.cloneNode(0),P(C,{position:wb,top:"-9999px",display:""}),x.body.appendChild(C));za=(C||Ja).offsetWidth;Ca=(C||Ja).offsetHeight;m.chartWidth=sa=q.width||za||600;m.chartHeight=ra=q.height||(Ca>19?Ca:400);m.container=D=Aa(Ra,{className:Ia+"container"+(q.className?" "+q.className:""),id:na},L({position:mc,overflow:ab,width:sa+ga,height:ra+ga,textAlign:"left",lineHeight:"normal"},
59
+ q.style),C||Ja);m.renderer=I=q.forExport?new Eb(D,sa,ra,!0):new Xb(D,sa,ra);Fa&&I.create(m,D,sa,ra);var a,b;Bc&&D.getBoundingClientRect&&(a=function(){P(D,{left:0,top:0});b=D.getBoundingClientRect();P(D,{left:-(b.left-S(b.left))+ga,top:-(b.top-S(b.top))+ga})},a(),ha(ca,"resize",a),ha(m,"destroy",function(){Qa(ca,"resize",a)}))}function n(){function a(c){var d=q.width||Ja.offsetWidth,e=q.height||Ja.offsetHeight,c=c?c.target:ca;if(d&&e&&(c===ca||c===x)){if(d!==za||e!==Ca)clearTimeout(b),b=setTimeout(function(){tb(d,
60
+ e,!1)},100);za=d;Ca=e}}var b;ha(ca,"resize",a);ha(m,"destroy",function(){Qa(ca,"resize",a)})}function t(){m&&aa(m,"endResize",null,function(){La-=1})}function r(){for(var a=U||q.inverted||q.type==="bar"||q.defaultSeriesType==="bar",b=v.series,c=b&&b.length;!a&&c--;)b[c].type==="bar"&&(a=!0);m.inverted=U=a}function Z(){var a=v.labels,b=v.credits,c;j();Xa=m.legend=new Rb;o(xa,function(a){a.setScale()});Wb();o(xa,function(a){a.setTickPositions(!0)});g();Wb();qb();Nb&&o(xa,function(a){a.render()});if(!m.seriesGroup)m.seriesGroup=
61
+ I.g("series-group").attr({zIndex:3}).add();o(Q,function(a){a.translate();a.setTooltipPoints();a.render()});a.items&&o(a.items,function(){var b=L(a.style,this.style),c=S(b.left)+O,d=S(b.top)+J+12;delete b.left;delete b.top;I.text(this.html,c,d).attr({zIndex:2}).css(b).add()});if(b.enabled&&!m.credits)c=b.href,m.credits=I.text(b.text,0,0).on("click",function(){if(c)location.href=c}).attr({align:b.position.align,zIndex:8}).css(b.style).add().align(b.position);m.hasRendered=!0}function V(){if(!Pb&&ca==
62
+ ca.top&&x.readyState!=="complete"||Fa&&!ca.canvg)Fa?Cc.push(V,v.global.canvasToolsURL):x.attachEvent("onreadystatechange",function(){x.detachEvent("onreadystatechange",V);x.readyState==="complete"&&V()});else{l();aa(m,"init");if(Highcharts.RangeSelector&&v.rangeSelector.enabled)m.rangeSelector=new Highcharts.RangeSelector(m);rb();sb();r();i();o(v.series||[],function(a){f(a)});if(Highcharts.Scroller&&(v.navigator.enabled||v.scrollbar.enabled))m.scroller=new Highcharts.Scroller(m);m.render=Z;m.tracker=
63
+ ub=new e(v.tooltip);Z();I.draw();b&&b.apply(m,[m]);o(m.callbacks,function(a){a.apply(m,[m])});C&&(Ja.appendChild(D),Tb(C));aa(m,"load")}}var v,y=a.series;a.series=null;v=K(Ea,a);v.series=a.series=y;var q=v.chart,y=q.margin,y=mb(y)?y:[y,y,y,y],T=p(q.marginTop,y[0]),w=p(q.marginRight,y[1]),E=p(q.marginBottom,y[2]),bb=p(q.marginLeft,y[3]),ia=q.spacingTop,ua=q.spacingRight,R=q.spacingBottom,jb=q.spacingLeft,ib,$,ja,J,ba,M,O,pa,Ja,C,D,na,za,Ca,sa,ra,$a,Za,ma,Na,Sa,da,m=this,kb=(y=q.events)&&!!y.click,
64
+ va,Db,vb,Da,xb,pb,Ya,la,ka,ub,db,Xa,Wa,yb,ya,Nb=q.showAxes,La=0,xa=[],gb,Q=[],U,I,lb,Bb,ob,qb,Wb,rb,sb,tb,zb,Fb,Rb=function(){function a(b,c){var d=b.legendItem,e=b.legendLine,g=b.legendSymbol,h=q.color,i=c?f.itemStyle.color:h,h=c?b.color:h;d&&d.css({fill:i});e&&e.attr({stroke:h});g&&g.attr({stroke:h,fill:h})}function b(a){var c=a.legendItem,d=a.legendLine,e=a._legendItemPos,f=e[0],e=e[1],g=a.legendSymbol,a=a.checkbox;c&&c.attr({x:r?f:Wa-f,y:e});d&&d.translate(r?f:Wa-f,e-4);g&&(c=f+g.xOff,g.attr({x:r?
65
+ c:Wa-c,y:e+g.yOff}));if(a)a.x=f,a.y=e}function c(){o(j,function(a){var b=a.checkbox,c=A.alignAttr;b&&P(b,{left:c.translateX+a.legendItemWidth+b.x-40+ga,top:c.translateY+b.y-11+ga})})}function d(b){var c,e,j,k,m=b.legendItem;k=b.series||b;var o=k.options,v=o&&o.borderWidth||0;if(!m){k=/^(bar|pie|area|column)$/.test(k.type);b.legendItem=m=I.text(f.labelFormatter.call(b),0,0,f.useHTML).css(b.visible?n:q).on("mouseover",function(){b.setState(ta);m.css(l)}).on("mouseout",function(){m.css(b.visible?n:q);
66
+ b.setState()}).on("click",function(){var a=function(){b.setVisible()};b.firePointEvent?b.firePointEvent("legendItemClick",null,a):aa(b,"legendItemClick",null,a)}).attr({align:r?"left":"right",zIndex:2}).add(A);if(!k&&o&&o.lineWidth){var u={"stroke-width":o.lineWidth,zIndex:2};if(o.dashStyle)u.dashstyle=o.dashStyle;b.legendLine=I.path([wa,(-h-i)*(r?1:-1),0,fa,-i*(r?1:-1),0]).attr(u).add(A)}if(k)j=I.rect(c=-h-i,e=-11,h,12,2).attr({zIndex:3}).add(A),r||(c+=h);else if(o&&o.marker&&o.marker.enabled)j=
67
+ o.marker.radius,j=I.symbol(b.symbol,c=-h/2-i-j,e=-4-j,2*j,2*j).attr(b.pointAttr[Ka]).attr({zIndex:3}).add(A),r||(c+=h/2);if(j)j.xOff=c+v%2/2,j.yOff=e+v%2/2;b.legendSymbol=j;a(b,b.visible);if(o&&o.showCheckbox)b.checkbox=Aa("input",{type:"checkbox",checked:b.selected,defaultChecked:b.selected},f.itemCheckboxStyle,D),ha(b.checkbox,"click",function(a){aa(b,"checkboxClick",{checked:a.target.checked},function(){b.select()})})}c=m.getBBox();e=b.legendItemWidth=f.itemWidth||h+i+c.width+t;w=c.height;if(g&&
68
+ s-V+e>(J||sa-2*t-V))s=V,z+=y+w+p;!g&&z+f.y+w>ra-ia-R&&(z=T,s+=Z,Z=0);Z=W(Z,e);x=W(x,z+p);b._legendItemPos=[s,z];g?s+=e:z+=y+w+p;C=J||W(s-V+(g?0:e),C)}function e(){s=V;z=T;x=C=0;A||(A=I.g("legend").attr({zIndex:7}).add());j=[];o(M,function(a){var b=a.options;b.showInLegend&&(j=j.concat(a.legendItems||(b.legendType==="point"?a.data:a)))});Mc(j,function(a,b){return(a.options.legendIndex||0)-(b.options.legendIndex||0)});jb&&j.reverse();o(j,d);Wa=J||C;yb=x-v+w;if(E||bb){Wa+=2*t;yb+=2*t;if(ua){if(Wa>0&&
69
+ yb>0)ua[ua.isNew?"attr":"animate"](ua.crisp(null,null,null,Wa,yb)),ua.isNew=!1}else ua=I.rect(0,0,Wa,yb,f.borderRadius,E||0).attr({stroke:f.borderColor,"stroke-width":E||0,fill:bb||Ma}).add(A).shadow(f.shadow),ua.isNew=!0;ua[j.length?"show":"hide"]()}o(j,b);for(var a=["left","right","top","bottom"],g,h=4;h--;)g=a[h],k[g]&&k[g]!=="auto"&&(f[h<2?"align":"verticalAlign"]=g,f[h<2?"x":"y"]=S(k[g])*(h%2?-1:1));j.length&&A.align(L(f,{width:Wa,height:yb}),!0,ib);La||c()}var f=m.options.legend;if(f.enabled){var g=
70
+ f.layout==="horizontal",h=f.symbolWidth,i=f.symbolPadding,j,k=f.style,n=f.itemStyle,l=f.itemHoverStyle,q=K(n,f.itemHiddenStyle),t=f.padding||S(k.padding),r=!f.rtl,y=f.itemMarginTop||0,p=f.itemMarginBottom||0,v=18,Z=0,V=4+t+h+i,T=t+y+v-5,s,z,x,w=0,ua,E=f.borderWidth,bb=f.backgroundColor,A,C,J=f.width,M=m.series,jb=f.reversed;e();ha(m,"endResize",c);return{colorizeItem:a,destroyItem:function(a){var b=a.checkbox;o(["legendItem","legendLine","legendSymbol"],function(b){a[b]&&a[b].destroy()});b&&Tb(a.checkbox)},
71
+ renderLegend:e,destroy:function(){ua&&(ua=ua.destroy());A&&(A=A.destroy())}}}};Db=function(a,b){return a>=0&&a<=ka&&b>=0&&b<=la};Fb=function(){var a=m.resetZoomButton;aa(m,"selection",{resetSelection:!0},zb);if(a)m.resetZoomButton=a.destroy()};zb=function(a){var b;m.resetZoomEnabled!==!1&&!m.resetZoomButton&&k();!a||a.resetSelection?o(xa,function(a){a.options.zoomEnabled!==!1&&(a.setExtremes(null,null,!1),b=!0)}):o(a.xAxis.concat(a.yAxis),function(a){var c=a.axis;if(m.tracker[c.isXAxis?"zoomX":"zoomY"])c.setExtremes(a.min,
72
+ a.max,!1),b=!0});b&&h(p(q.animation,m.pointCount<100))};m.pan=function(a){var b=m.xAxis[0],c=m.mouseDownX,d=b.pointRange/2,e=b.getExtremes(),f=b.translate(c-a,!0)+d,c=b.translate(c+ka-a,!0)-d;(d=m.hoverPoints)&&o(d,function(a){a.setState()});f>Ua(e.dataMin,e.min)&&c<W(e.dataMax,e.max)&&b.setExtremes(f,c,!0,!1);m.mouseDownX=a;P(D,{cursor:"move"})};Wb=function(){var a=v.legend,b=p(a.margin,10),c=a.x,d=a.y,e=a.align,f=a.verticalAlign,g;rb();if((m.title||m.subtitle)&&!s(T))(g=W(m.title&&!$.floating&&
73
+ !$.verticalAlign&&$.y||0,m.subtitle&&!ja.floating&&!ja.verticalAlign&&ja.y||0))&&(J=W(J,g+p($.margin,15)+ia));a.enabled&&!a.floating&&(e==="right"?s(w)||(ba=W(ba,Wa-c+b+ua)):e==="left"?s(bb)||(O=W(O,Wa+c+b+jb)):f==="top"?s(T)||(J=W(J,yb+d+b+ia)):f==="bottom"&&(s(E)||(M=W(M,yb-d+b+R))));m.extraBottomMargin&&(M+=m.extraBottomMargin);m.extraTopMargin&&(J+=m.extraTopMargin);Nb&&o(xa,function(a){a.getOffset()});s(bb)||(O+=pa[3]);s(T)||(J+=pa[0]);s(E)||(M+=pa[2]);s(w)||(ba+=pa[1]);sb()};tb=function(a,b,
74
+ c){var d=m.title,e=m.subtitle;La+=1;Kb(c,m);Za=ra;$a=sa;if(s(a))m.chartWidth=sa=z(a);if(s(b))m.chartHeight=ra=z(b);P(D,{width:sa+ga,height:ra+ga});I.setSize(sa,ra,c);ka=sa-O-ba;la=ra-J-M;gb=null;o(xa,function(a){a.isDirty=!0;a.setScale()});o(Q,function(a){a.isDirty=!0});m.isDirtyLegend=!0;m.isDirtyBox=!0;Wb();d&&d.align(null,null,ib);e&&e.align(null,null,ib);h(c);Za=null;aa(m,"resize");Ub===!1?t():setTimeout(t,Ub&&Ub.duration||500)};sb=function(){m.plotLeft=O=z(O);m.plotTop=J=z(J);m.plotWidth=ka=
75
+ z(sa-O-ba);m.plotHeight=la=z(ra-J-M);m.plotSizeX=U?la:ka;m.plotSizeY=U?ka:la;ib={x:jb,y:ia,width:sa-jb-ua,height:ra-ia-R};o(xa,function(a){a.setAxisSize();a.setAxisTranslation()})};rb=function(){J=p(T,ia);ba=p(w,ua);M=p(E,R);O=p(bb,jb);pa=[0,0,0,0]};qb=function(){var a=q.borderWidth||0,b=q.backgroundColor,c=q.plotBackgroundColor,d=q.plotBackgroundImage,e,f={x:O,y:J,width:ka,height:la};e=a+(q.shadow?8:0);if(a||b)ma?ma.animate(ma.crisp(null,null,null,sa-e,ra-e)):ma=I.rect(e/2,e/2,sa-e,ra-e,q.borderRadius,
76
+ a).attr({stroke:q.borderColor,"stroke-width":a,fill:b||Ma}).add().shadow(q.shadow);c&&(Na?Na.animate(f):Na=I.rect(O,J,ka,la,0).attr({fill:c}).add().shadow(q.plotShadow));d&&(Sa?Sa.animate(f):Sa=I.image(d,O,J,ka,la).add());q.plotBorderWidth&&(da?da.animate(da.crisp(null,O,J,ka,la)):da=I.rect(O,J,ka,la,0,q.plotBorderWidth).attr({stroke:q.plotBorderColor,"stroke-width":q.plotBorderWidth,zIndex:4}).add());m.isDirtyBox=!1};q.reflow!==!1&&ha(m,"load",n);if(y)for(va in y)ha(m,va,y[va]);m.options=v;m.series=
77
+ Q;m.xAxis=[];m.yAxis=[];m.addSeries=function(a,b,c){var d;a&&(Kb(c,m),b=p(b,!0),aa(m,"addSeries",{options:a},function(){d=f(a);d.isDirty=!0;m.isDirtyLegend=!0;b&&m.redraw()}));return d};m.animation=Fa?!1:p(q.animation,!0);m.Axis=c;m.destroy=function(){var a,b=D&&D.parentNode;if(m!==null){aa(m,"destroy");Qa(m);for(a=xa.length;a--;)xa[a]=xa[a].destroy();for(a=Q.length;a--;)Q[a]=Q[a].destroy();o("title,subtitle,seriesGroup,clipRect,credits,tracker,scroller,rangeSelector".split(","),function(a){var b=
78
+ m[a];b&&(m[a]=b.destroy())});o([ma,da,Na,Xa,vb,I,ub],function(a){a&&a.destroy&&a.destroy()});ma=da=Na=Xa=vb=I=ub=null;if(D)D.innerHTML="",Qa(D),b&&Tb(D),D=null;clearInterval(Bb);for(a in m)delete m[a];v=m=null}};m.get=function(a){var b,c,d;for(b=0;b<xa.length;b++)if(xa[b].options.id===a)return xa[b];for(b=0;b<Q.length;b++)if(Q[b].options.id===a)return Q[b];for(b=0;b<Q.length;b++){d=Q[b].points||[];for(c=0;c<d.length;c++)if(d[c].id===a)return d[c]}return null};m.getSelectedPoints=function(){var a=
79
+ [];o(Q,function(b){a=a.concat(nc(b.points,function(a){return a.selected}))});return a};m.getSelectedSeries=function(){return nc(Q,function(a){return a.selected})};m.hideLoading=function(){xb&&cc(xb,{opacity:0},{duration:v.loading.hideDuration||100,complete:function(){P(xb,{display:Ma})}});Ya=!1};m.initSeries=f;m.isInsidePlot=Db;m.redraw=h;m.setSize=tb;m.setTitle=j;m.showLoading=function(a){var b=v.loading;xb||(xb=Aa(Ra,{className:Ia+"loading"},L(b.style,{left:O+ga,top:J+ga,width:ka+ga,height:la+ga,
80
+ zIndex:10,display:Ma}),D),pb=Aa("span",null,b.labelStyle,xb));pb.innerHTML=a||v.lang.loading;Ya||(P(xb,{opacity:0,display:""}),cc(xb,{opacity:b.style.opacity},{duration:b.showDuration||0}),Ya=!0)};m.pointCount=0;m.counters=new tc;V()}var X,x=document,ca=window,oa=Math,z=oa.round,Ta=oa.floor,Yb=oa.ceil,W=oa.max,Ua=oa.min,Ba=oa.abs,ja=oa.cos,C=oa.sin,da=oa.PI,Dc=da*2/360,kb=navigator.userAgent,Qb=/msie/i.test(kb)&&!ca.opera,Xa=x.documentMode===8,Ec=/AppleWebKit/.test(kb),Bc=/Firefox/.test(kb),Pb=!!x.createElementNS&&
81
+ !!x.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,Qc=Bc&&parseInt(kb.split("Firefox/")[1],10)<4,Fa=!Pb&&!Qb&&!!x.createElement("canvas").getContext,Xb,Ga=x.documentElement.ontouchstart!==X,Fc={},lc=0,tb,Ea,ac,Ub,La,E,Ra="div",wb="absolute",mc="relative",ab="hidden",Ia="highcharts-",eb="visible",ga="px",Ma="none",wa="M",fa="L",Gc="rgba(192,192,192,"+(Pb?1.0E-6:0.0020)+")",Ka="",ta="hover",Rb="millisecond",ob="second",pb="minute",va="hour",Ca="day",Ya="week",Da="month",Za="year",
82
+ sb,fc,gc,ic,db,qb,rb,pc,qc,hc,rc,sc,w=ca.HighchartsAdapter,na=w||{},Hc=na.getScript,o=na.each,nc=na.grep,Ac=na.offset,Vb=na.map,K=na.merge,ha=na.addEvent,Qa=na.removeEvent,aa=na.fireEvent,cc=na.animate,Ob=na.stop,Ha={};ca.Highcharts={};ac=function(a,b,c){if(!s(b)||isNaN(b))return"Invalid date";var a=p(a,"%Y-%m-%d %H:%M:%S"),d=new Date(b),e,f=d[gc](),g=d[ic](),h=d[db](),i=d[qb](),k=d[rb](),j=Ea.lang,l=j.weekdays,b={a:l[g].substr(0,3),A:l[g],d:Na(h),e:h,b:j.shortMonths[i],B:j.months[i],m:Na(i+1),y:k.toString().substr(2,
83
+ 2),Y:k,H:Na(f),I:Na(f%12||12),l:f%12||12,M:Na(d[fc]()),p:f<12?"AM":"PM",P:f<12?"am":"pm",S:Na(d.getSeconds()),L:Na(z(b%1E3),3)};for(e in b)a=a.replace("%"+e,b[e]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a};tc.prototype={wrapColor:function(a){if(this.color>=a)this.color=0},wrapSymbol:function(a){if(this.symbol>=a)this.symbol=0}};E=za(Rb,1,ob,1E3,pb,6E4,va,36E5,Ca,864E5,Ya,6048E5,Da,2592E6,Za,31556952E3);La={init:function(a,b,c){var b=b||"",d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,g,b=b.split(" "),
84
+ c=[].concat(c),h,i,k=function(a){for(g=a.length;g--;)a[g]===wa&&a.splice(g+1,0,a[g+1],a[g+2],a[g+1],a[g+2])};e&&(k(b),k(c));a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6));d===1&&(c=[].concat(c).splice(0,f).concat(c));a.shift=0;if(b.length)for(a=c.length;b.length<a;)d=[].concat(b).splice(b.length-f,f),e&&(d[f-6]=d[f-2],d[f-5]=d[f-1]),b=b.concat(d);h&&(b=b.concat(h),c=c.concat(i));return[b,c]},step:function(a,b,c,d){var e=[],f=a.length;if(c===1)e=d;else if(f===b.length&&c<1)for(;f--;)d=
85
+ parseFloat(a[f]),e[f]=isNaN(d)?a[f]:c*parseFloat(b[f]-d)+d;else e=b;return e}};w&&w.init&&w.init(La);if(!w&&ca.jQuery){var ba=jQuery,Hc=ba.getScript,o=function(a,b){for(var c=0,d=a.length;c<d;c++)if(b.call(a[c],a[c],c,a)===!1)return c},nc=ba.grep,Vb=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++)c[d]=b.call(a[d],a[d],d,a);return c},K=function(){var a=arguments;return ba.extend(!0,null,a[0],a[1],a[2],a[3])},Ac=function(a){return ba(a).offset()},ha=function(a,b,c){ba(a).bind(b,c)},Qa=function(a,
86
+ b,c){var d=x.removeEventListener?"removeEventListener":"detachEvent";x[d]&&!a[d]&&(a[d]=function(){});ba(a).unbind(b,c)},aa=function(a,b,c,d){var e=ba.Event(b),f="detached"+b,g;L(e,c);a[b]&&(a[f]=a[b],a[b]=null);o(["preventDefault","stopPropagation"],function(a){var b=e[a];e[a]=function(){try{b.call(e)}catch(c){a==="preventDefault"&&(g=!0)}}});ba(a).trigger(e);a[f]&&(a[b]=a[f],a[f]=null);d&&!e.isDefaultPrevented()&&!g&&d(e)},cc=function(a,b,c){var d=ba(a);if(b.d)a.toD=b.d,b.d=1;d.stop();d.animate(b,
87
+ c)},Ob=function(a){ba(a).stop()};ba.extend(ba.easing,{easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}});var Ic=jQuery.fx,Jc=Ic.step;o(["cur","_default","width","height"],function(a,b){var c=b?Jc:Ic.prototype,d=c[a],e;d&&(c[a]=function(a){a=b?a:this;e=a.elem;return e.attr?e.attr(a.prop,a.now):d.apply(this,arguments)})});Jc.d=function(a){var b=a.elem;if(!a.started){var c=La.init(b,b.d,b.toD);a.start=c[0];a.end=c[1];a.started=!0}b.attr("d",La.step(a.start,a.end,a.pos,b.toD))}}w={enabled:!0,
88
+ align:"center",x:0,y:15,style:{color:"#666",fontSize:"11px",lineHeight:"14px"}};Ea={colors:"#4572A7,#AA4643,#89A54E,#80699B,#3D96AE,#DB843D,#92A8CD,#A47D7C,#B5CA92".split(","),symbols:["circle","diamond","square","triangle","triangle-down"],lang:{loading:"Loading...",months:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),weekdays:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),
89
+ decimalPoint:".",resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:","},global:{useUTC:!0,canvasToolsURL:"http://code.highcharts.com/2.2.1/modules/canvas-tools.js"},chart:{borderColor:"#4572A7",borderRadius:5,defaultSeriesType:"line",ignoreHiddenSeries:!0,spacingTop:10,spacingRight:10,spacingBottom:15,spacingLeft:10,style:{fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif',fontSize:"12px"},backgroundColor:"#FFFFFF",plotBorderColor:"#C0C0C0",
90
+ resetZoomButton:{theme:{zIndex:20},position:{align:"right",x:-10,y:10}}},title:{text:"Chart title",align:"center",y:15,style:{color:"#3E576F",fontSize:"16px"}},subtitle:{text:"",align:"center",y:30,style:{color:"#6D869F"}},plotOptions:{line:{allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},lineWidth:2,shadow:!0,marker:{enabled:!0,lineWidth:0,radius:4,lineColor:"#FFFFFF",states:{hover:{},select:{fillColor:"#FFFFFF",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:K(w,
91
+ {enabled:!1,y:-6,formatter:function(){return this.y}}),cropThreshold:300,pointRange:0,showInLegend:!0,states:{hover:{marker:{}},select:{marker:{}}},stickyTracking:!0}},labels:{style:{position:wb,color:"#3E576F"}},legend:{enabled:!0,align:"center",layout:"horizontal",labelFormatter:function(){return this.name},borderWidth:1,borderColor:"#909090",borderRadius:5,shadow:!1,style:{padding:"5px"},itemStyle:{cursor:"pointer",color:"#3E576F"},itemHoverStyle:{color:"#000000"},itemHiddenStyle:{color:"#C0C0C0"},
92
+ itemCheckboxStyle:{position:wb,width:"13px",height:"13px"},symbolWidth:16,symbolPadding:5,verticalAlign:"bottom",x:0,y:0},loading:{labelStyle:{fontWeight:"bold",position:mc,top:"1em"},style:{position:wb,backgroundColor:"white",opacity:0.5,textAlign:"center"}},tooltip:{enabled:!0,backgroundColor:"rgba(255, 255, 255, .85)",borderWidth:2,borderRadius:5,headerFormat:'<span style="font-size: 10px">{point.key}</span><br/>',pointFormat:'<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b><br/>',
93
+ shadow:!0,shared:Fa,snap:Ga?25:10,style:{color:"#333333",fontSize:"12px",padding:"5px",whiteSpace:"nowrap"}},credits:{enabled:!0,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"10px"}}};var $b={dateTimeLabelFormats:za(Rb,"%H:%M:%S.%L",ob,"%H:%M:%S",pb,"%H:%M",va,"%H:%M",Ca,"%e. %b",Ya,"%e. %b",Da,"%b '%y",Za,"%Y"),endOnTick:!1,gridLineColor:"#C0C0C0",labels:w,lineColor:"#C0D0E0",lineWidth:1,
94
+ max:null,min:null,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickColor:"#C0D0E0",tickLength:5,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#6D869F",fontWeight:"bold"}},type:"linear"},kc=K($b,{endOnTick:!0,gridLineWidth:1,tickPixelInterval:72,showLastLabel:!0,labels:{align:"right",x:-8,
95
+ y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:"Y-values"},stackLabels:{enabled:!1,formatter:function(){return this.total},style:w.style}}),Pc={labels:{align:"right",x:-8,y:null},title:{rotation:270}},Oc={labels:{align:"left",x:8,y:null},title:{rotation:90}},zc={labels:{align:"center",x:0,y:14,overflow:"justify"},title:{rotation:0}},Nc=K(zc,{labels:{y:-5,overflow:"justify"}}),M=Ea.plotOptions,w=M.line;M.spline=K(w);M.scatter=K(w,{lineWidth:0,states:{hover:{lineWidth:0}},
96
+ tooltip:{headerFormat:'<span style="font-size: 10px; color:{series.color}">{series.name}</span><br/>',pointFormat:"x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>"}});M.area=K(w,{threshold:0});M.areaspline=K(M.area);M.column=K(w,{borderColor:"#FFFFFF",borderWidth:1,borderRadius:0,groupPadding:0.2,marker:null,pointPadding:0.1,minPointLength:0,cropThreshold:50,pointRange:null,states:{hover:{brightness:0.1,shadow:!1},select:{color:"#C0C0C0",borderColor:"#000000",shadow:!1}},dataLabels:{y:null,verticalAlign:null},
97
+ threshold:0});M.bar=K(M.column,{dataLabels:{align:"left",x:5,y:null,verticalAlign:"middle"}});M.pie=K(w,{borderColor:"#FFFFFF",borderWidth:1,center:["50%","50%"],colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name},y:5},legendType:"point",marker:null,size:"75%",showInLegend:!1,slicedOffset:10,states:{hover:{brightness:0.1,shadow:!1}}});vc();var ma=function(a){var b=[],c;(function(a){(c=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(a))?
98
+ b=[S(c[1]),S(c[2]),S(c[3]),parseFloat(c[4],10)]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(a))&&(b=[S(c[1],16),S(c[2],16),S(c[3],16),1])})(a);return{get:function(c){return b&&!isNaN(b[0])?c==="rgb"?"rgb("+b[0]+","+b[1]+","+b[2]+")":c==="a"?b[3]:"rgba("+b.join(",")+")":a},brighten:function(a){if(Bb(a)&&a!==0){var c;for(c=0;c<3;c++)b[c]+=S(a*255),b[c]<0&&(b[c]=0),b[c]>255&&(b[c]=255)}return this},setOpacity:function(a){b[3]=a;return this}}};Sa.prototype={init:function(a,b){this.element=
99
+ b==="span"?Aa(b):x.createElementNS("http://www.w3.org/2000/svg",b);this.renderer=a;this.attrSetters={}},animate:function(a,b,c){b=p(b,Ub,!0);Ob(this);if(b){b=K(b);if(c)b.complete=c;cc(this,a,b)}else this.attr(a),c&&c()},attr:function(a,b){var c,d,e,f,g=this.element,h=g.nodeName,i=this.renderer,k,j=this.attrSetters,l=this.shadows,n,o=this;Ab(a)&&s(b)&&(c=a,a={},a[c]=b);if(Ab(a))c=a,h==="circle"?c={x:"cx",y:"cy"}[c]||c:c==="strokeWidth"&&(c="stroke-width"),o=A(g,c)||this[c]||0,c!=="d"&&c!=="visibility"&&
100
+ (o=parseFloat(o));else for(c in a)if(k=!1,d=a[c],e=j[c]&&j[c](d,c),e!==!1){e!==X&&(d=e);if(c==="d")d&&d.join&&(d=d.join(" ")),/(NaN| {2}|^$)/.test(d)&&(d="M 0 0"),this.d=d;else if(c==="x"&&h==="text"){for(e=0;e<g.childNodes.length;e++)f=g.childNodes[e],A(f,"x")===A(g,"x")&&A(f,"x",d);this.rotation&&A(g,"transform","rotate("+this.rotation+" "+d+" "+S(a.y||A(g,"y"))+")")}else if(c==="fill")d=i.color(d,g,c);else if(h==="circle"&&(c==="x"||c==="y"))c={x:"cx",y:"cy"}[c]||c;else if(h==="rect"&&c==="r")A(g,
101
+ {rx:d,ry:d}),k=!0;else if(c==="translateX"||c==="translateY"||c==="rotation"||c==="verticalAlign")this[c]=d,this.updateTransform(),k=!0;else if(c==="stroke")d=i.color(d,g,c);else if(c==="dashstyle")if(c="stroke-dasharray",d=d&&d.toLowerCase(),d==="solid")d=Ma;else{if(d){d=d.replace("shortdashdotdot","3,1,1,1,1,1,").replace("shortdashdot","3,1,1,1").replace("shortdot","1,1,").replace("shortdash","3,1,").replace("longdash","8,3,").replace(/dot/g,"1,3,").replace("dash","4,3,").replace(/,$/,"").split(",");
102
+ for(e=d.length;e--;)d[e]=S(d[e])*a["stroke-width"];d=d.join(",")}}else c==="isTracker"?this[c]=d:c==="width"?d=S(d):c==="align"?(c="text-anchor",d={left:"start",center:"middle",right:"end"}[d]):c==="title"&&(e=x.createElementNS("http://www.w3.org/2000/svg","title"),e.appendChild(x.createTextNode(d)),g.appendChild(e));c==="strokeWidth"&&(c="stroke-width");Ec&&c==="stroke-width"&&d===0&&(d=1.0E-6);this.symbolName&&/^(x|y|r|start|end|innerR|anchorX|anchorY)/.test(c)&&(n||(this.symbolAttr(a),n=!0),k=
103
+ !0);if(l&&/^(width|height|visibility|x|y|d|transform)$/.test(c))for(e=l.length;e--;)A(l[e],c,d);if((c==="width"||c==="height")&&h==="rect"&&d<0)d=0;c==="text"?(this.textStr=d,this.added&&i.buildText(this)):k||A(g,c,d)}if(Ec&&/Chrome\/(18|19)/.test(kb)&&h==="text"&&(a.x!==X||a.y!==X))c=g.parentNode,d=g.nextSibling,c&&(c.removeChild(g),d?c.insertBefore(g,d):c.appendChild(g));return o},symbolAttr:function(a){var b=this;o("x,y,r,start,end,width,height,innerR,anchorX,anchorY".split(","),function(c){b[c]=
104
+ p(a[c],b[c])});b.attr({d:b.renderer.symbols[b.symbolName](b.x,b.y,b.width,b.height,b)})},clip:function(a){return this.attr("clip-path","url("+this.renderer.url+"#"+a.id+")")},crisp:function(a,b,c,d,e){var f,g={},h={},i,a=a||this.strokeWidth||this.attr&&this.attr("stroke-width")||0;i=z(a)%2/2;h.x=Ta(b||this.x||0)+i;h.y=Ta(c||this.y||0)+i;h.width=Ta((d||this.width||0)-2*i);h.height=Ta((e||this.height||0)-2*i);h.strokeWidth=a;for(f in h)this[f]!==h[f]&&(this[f]=g[f]=h[f]);return g},css:function(a){var b=
105
+ this.element,b=a&&a.width&&b.nodeName==="text",c,d="",e=function(a,b){return"-"+b.toLowerCase()};if(a&&a.color)a.fill=a.color;this.styles=a=L(this.styles,a);if(Qb&&!Pb)b&&delete a.width,P(this.element,a);else{for(c in a)d+=c.replace(/([A-Z])/g,e)+":"+a[c]+";";this.attr({style:d})}b&&this.added&&this.renderer.buildText(this);return this},on:function(a,b){var c=b;Ga&&a==="click"&&(a="touchstart",c=function(a){a.preventDefault();b()});this.element["on"+a]=c;return this},translate:function(a,b){return this.attr({translateX:a,
106
+ translateY:b})},invert:function(){this.inverted=!0;this.updateTransform();return this},htmlCss:function(a){var b=this.element;if(b=a&&b.tagName==="SPAN"&&a.width)delete a.width,this.textWidth=b,this.updateTransform();this.styles=L(this.styles,a);P(this.element,a);return this},htmlGetBBox:function(a){var b=this.element,c=this.bBox;if(!c||a){if(b.nodeName==="text")b.style.position=wb;c=this.bBox={x:b.offsetLeft,y:b.offsetTop,width:b.offsetWidth,height:b.offsetHeight}}return c},htmlUpdateTransform:function(){if(this.added){var a=
107
+ this.renderer,b=this.element,c=this.translateX||0,d=this.translateY||0,e=this.x||0,f=this.y||0,g=this.textAlign||"left",h={left:0,center:0.5,right:1}[g],i=g&&g!=="left",k=this.shadows;if(c||d)P(b,{marginLeft:c,marginTop:d}),k&&o(k,function(a){P(a,{marginLeft:c+1,marginTop:d+1})});this.inverted&&o(b.childNodes,function(c){a.invertChild(c,b)});if(b.tagName==="SPAN"){var j,l,k=this.rotation,n;j=0;var t=1,r=0,Z;n=S(this.textWidth);var V=this.xCorr||0,v=this.yCorr||0,y=[k,g,b.innerHTML,this.textWidth].join(",");
108
+ if(y!==this.cTT)s(k)&&(j=k*Dc,t=ja(j),r=C(j),P(b,{filter:k?["progid:DXImageTransform.Microsoft.Matrix(M11=",t,", M12=",-r,", M21=",r,", M22=",t,", sizingMethod='auto expand')"].join(""):Ma})),j=p(this.elemWidth,b.offsetWidth),l=p(this.elemHeight,b.offsetHeight),j>n&&(P(b,{width:n+ga,display:"block",whiteSpace:"normal"}),j=n),n=a.fontMetrics(b.style.fontSize).b,V=t<0&&-j,v=r<0&&-l,Z=t*r<0,V+=r*n*(Z?1-h:h),v-=t*n*(k?Z?h:1-h:1),i&&(V-=j*h*(t<0?-1:1),k&&(v-=l*h*(r<0?-1:1)),P(b,{textAlign:g})),this.xCorr=
109
+ V,this.yCorr=v;P(b,{left:e+V+ga,top:f+v+ga});this.cTT=y}}else this.alignOnAdd=!0},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.inverted,d=this.rotation,e=[];c&&(a+=this.attr("width"),b+=this.attr("height"));(a||b)&&e.push("translate("+a+","+b+")");c?e.push("rotate(90) scale(-1,1)"):d&&e.push("rotate("+d+" "+this.x+" "+this.y+")");e.length&&A(this.element,"transform",e.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,
110
+ b,c){a?(this.alignOptions=a,this.alignByTranslate=b,c||this.renderer.alignedObjects.push(this)):(a=this.alignOptions,b=this.alignByTranslate);var c=p(c,this.renderer),d=a.align,e=a.verticalAlign,f=(c.x||0)+(a.x||0),g=(c.y||0)+(a.y||0),h={};/^(right|center)$/.test(d)&&(f+=(c.width-(a.width||0))/{right:1,center:2}[d]);h[b?"translateX":"x"]=z(f);/^(bottom|middle)$/.test(e)&&(g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1));h[b?"translateY":"y"]=z(g);this[this.placed?"animate":"attr"](h);this.placed=
111
+ !0;this.alignAttr=h;return this},getBBox:function(a){var b,c,d=this.rotation;c=this.element;var e=d*Dc;if(c.namespaceURI==="http://www.w3.org/2000/svg"){try{b=c.getBBox?L({},c.getBBox()):{width:c.offsetWidth,height:c.offsetHeight}}catch(f){}if(!b||b.width<0)b={width:0,height:0};a=b.width;c=b.height;if(d)b.width=Ba(c*C(e))+Ba(a*ja(e)),b.height=Ba(c*ja(e))+Ba(a*C(e))}else b=this.htmlGetBBox(a);return b},show:function(){return this.attr({visibility:eb})},hide:function(){return this.attr({visibility:ab})},
112
+ add:function(a){var b=this.renderer,c=a||b,d=c.element||b.box,e=d.childNodes,f=this.element,g=A(f,"zIndex"),h;this.parentInverted=a&&a.inverted;this.textStr!==void 0&&b.buildText(this);if(g)c.handleZ=!0,g=S(g);if(c.handleZ)for(c=0;c<e.length;c++)if(a=e[c],b=A(a,"zIndex"),a!==f&&(S(b)>g||!s(g)&&s(b))){d.insertBefore(f,a);h=!0;break}h||d.appendChild(f);this.added=!0;aa(this,"add");return this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||
113
+ {},c=a.shadows,d=a.box,e,f;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=null;Ob(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(f=0;f<a.stops.length;f++)a.stops[f]=a.stops[f].destroy();a.stops=null}a.safeRemoveChild(b);c&&o(c,function(b){a.safeRemoveChild(b)});d&&d.destroy();Gb(a.renderer.alignedObjects,a);for(e in a)delete a[e];return null},empty:function(){for(var a=this.element,b=a.childNodes,c=b.length;c--;)a.removeChild(b[c])},shadow:function(a,b){var c=[],d,e,f=this.element,
114
+ g=this.parentInverted?"(-1,-1)":"(1,1)";if(a){for(d=1;d<=3;d++)e=f.cloneNode(0),A(e,{isShadow:"true",stroke:"rgb(0, 0, 0)","stroke-opacity":0.05*d,"stroke-width":7-2*d,transform:"translate"+g,fill:Ma}),b?b.element.appendChild(e):f.parentNode.insertBefore(e,f),c.push(e);this.shadows=c}return this}};var Eb=function(){this.init.apply(this,arguments)};Eb.prototype={Element:Sa,init:function(a,b,c,d){var e=location,f;f=this.createElement("svg").attr({xmlns:"http://www.w3.org/2000/svg",version:"1.1"});a.appendChild(f.element);
115
+ this.isSVG=!0;this.box=f.element;this.boxWrapper=f;this.alignedObjects=[];this.url=Qb?"":e.href.replace(/#.*?$/,"").replace(/([\('\)])/g,"\\$1");this.defs=this.createElement("defs").add();this.forExport=d;this.gradients={};this.setSize(b,c,!1)},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();Jb(this.gradients||{});this.gradients=null;if(a)this.defs=a.destroy();return this.alignedObjects=null},createElement:function(a){var b=new this.Element;b.init(this,a);
116
+ return b},draw:function(){},buildText:function(a){for(var b=a.element,c=p(a.textStr,"").toString().replace(/<(b|strong)>/g,'<span style="font-weight:bold">').replace(/<(i|em)>/g,'<span style="font-style:italic">').replace(/<a/g,"<span").replace(/<\/(b|strong|i|em|a)>/g,"</span>").split(/<br.*?>/g),d=b.childNodes,e=/style="([^"]+)"/,f=/href="([^"]+)"/,g=A(b,"x"),h=a.styles,i=h&&S(h.width),k=h&&h.lineHeight,j,h=d.length;h--;)b.removeChild(d[h]);i&&!a.added&&this.box.appendChild(b);c[c.length-1]===""&&
117
+ c.pop();o(c,function(c,d){var h,r=0,p,c=c.replace(/<span/g,"|||<span").replace(/<\/span>/g,"</span>|||");h=c.split("|||");o(h,function(c){if(c!==""||h.length===1){var l={},o=x.createElementNS("http://www.w3.org/2000/svg","tspan");e.test(c)&&A(o,"style",c.match(e)[1].replace(/(;| |^)color([ :])/,"$1fill$2"));f.test(c)&&(A(o,"onclick",'location.href="'+c.match(f)[1]+'"'),P(o,{cursor:"pointer"}));c=(c.replace(/<(.|\n)*?>/g,"")||" ").replace(/&lt;/g,"<").replace(/&gt;/g,">");o.appendChild(x.createTextNode(c));
118
+ r?l.dx=3:l.x=g;if(!r){if(d){!Pb&&a.renderer.forExport&&P(o,{display:"block"});p=ca.getComputedStyle&&S(ca.getComputedStyle(j,null).getPropertyValue("line-height"));if(!p||isNaN(p))p=k||j.offsetHeight||18;A(o,"dy",p)}j=o}A(o,l);b.appendChild(o);r++;if(i)for(var c=c.replace(/-/g,"- ").split(" "),q,T=[];c.length||T.length;)q=a.getBBox().width,l=q>i,!l||c.length===1?(c=T,T=[],c.length&&(o=x.createElementNS("http://www.w3.org/2000/svg","tspan"),A(o,{dy:k||16,x:g}),b.appendChild(o),q>i&&(i=q))):(o.removeChild(o.firstChild),
119
+ T.unshift(c.pop())),c.length&&o.appendChild(x.createTextNode(c.join(" ").replace(/- /g,"-")))}})})},button:function(a,b,c,d,e,f,g){var h=this.label(a,b,c),i=0,k,j,l,n,o,a={x1:0,y1:0,x2:0,y2:1},e=K(za("stroke-width",1,"stroke","#999","fill",za("linearGradient",a,"stops",[[0,"#FFF"],[1,"#DDD"]]),"r",3,"padding",3,"style",za("color","black")),e);l=e.style;delete e.style;f=K(e,za("stroke","#68A","fill",za("linearGradient",a,"stops",[[0,"#FFF"],[1,"#ACF"]])),f);n=f.style;delete f.style;g=K(e,za("stroke",
120
+ "#68A","fill",za("linearGradient",a,"stops",[[0,"#9BD"],[1,"#CDF"]])),g);o=g.style;delete g.style;ha(h.element,"mouseenter",function(){h.attr(f).css(n)});ha(h.element,"mouseleave",function(){k=[e,f,g][i];j=[l,n,o][i];h.attr(k).css(j)});h.setState=function(a){(i=a)?a===2&&h.attr(g).css(o):h.attr(e).css(l)};return h.on("click",function(){d.call(h)}).attr(e).css(L({cursor:"default"},l))},crispLine:function(a,b){a[1]===a[4]&&(a[1]=a[4]=z(a[1])+b%2/2);a[2]===a[5]&&(a[2]=a[5]=z(a[2])+b%2/2);return a},path:function(a){return this.createElement("path").attr({d:a,
121
+ fill:Ma})},circle:function(a,b,c){a=mb(a)?a:{x:a,y:b,r:c};return this.createElement("circle").attr(a)},arc:function(a,b,c,d,e,f){if(mb(a))b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x;return this.symbol("arc",a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0})},rect:function(a,b,c,d,e,f){if(mb(a))b=a.y,c=a.width,d=a.height,e=a.r,f=a.strokeWidth,a=a.x;e=this.createElement("rect").attr({rx:e,ry:e,fill:Ma});return e.attr(e.crisp(f,a,b,W(c,0),W(d,0)))},setSize:function(a,b,c){var d=this.alignedObjects,
122
+ e=d.length;this.width=a;this.height=b;for(this.boxWrapper[p(c,!0)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return s(a)?b.attr({"class":Ia+a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:Ma};arguments.length>1&&L(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,
123
+ b,c,d,e,f){var g,h=this.symbols[a],h=h&&h(z(b),z(c),d,e,f),i=/^url\((.*?)\)$/,k;if(h)g=this.path(h),L(g,{symbolName:a,x:b,y:c,width:d,height:e}),f&&L(g,f);else if(i.test(a)){var j=function(a,b){a.attr({width:b[0],height:b[1]}).translate(-z(b[0]/2),-z(b[1]/2))};k=a.match(i)[1];a=Fc[k];g=this.image(k).attr({x:b,y:c});a?j(g,a):(g.attr({width:0,height:0}),Aa("img",{onload:function(){j(g,Fc[k]=[this.width,this.height])},src:k}))}return g},symbols:{circle:function(a,b,c,d){var e=0.166*c;return[wa,a+c/2,
124
+ b,"C",a+c+e,b,a+c+e,b+d,a+c/2,b+d,"C",a-e,b+d,a-e,b,a+c/2,b,"Z"]},square:function(a,b,c,d){return[wa,a,b,fa,a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return[wa,a+c/2,b,fa,a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,d){return[wa,a,b,fa,a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return[wa,a+c/2,b,fa,a+c,b+d/2,a+c/2,b+d,a,b+d/2,"Z"]},arc:function(a,b,c,d,e){var f=e.start,c=e.r||c||d,g=e.end-1.0E-6,d=e.innerR,h=ja(f),i=C(f),k=ja(g),g=C(g),e=e.end-f<da?0:1;return[wa,a+c*h,b+c*i,
125
+ "A",c,c,0,e,1,a+c*k,b+c*g,fa,a+d*k,b+d*g,"A",d,d,0,e,0,a+d*h,b+d*i,"Z"]}},clipRect:function(a,b,c,d){var e=Ia+lc++,f=this.createElement("clipPath").attr({id:e}).add(this.defs),a=this.rect(a,b,c,d,0).add(f);a.id=e;a.clipPath=f;return a},color:function(a,b,c){var d,e=/^rgba/;if(a&&a.linearGradient){var f=this,g=a.linearGradient,b=!Fb(g),c=f.gradients,h,i=g.x1||g[0]||0,k=g.y1||g[1]||0,j=g.x2||g[2]||0,l=g.y2||g[3]||0,n,t,r=[b,i,k,j,l,a.stops.join(",")].join(",");c[r]?g=A(c[r].element,"id"):(g=Ia+lc++,
126
+ h=f.createElement("linearGradient").attr(L({id:g,x1:i,y1:k,x2:j,y2:l},b?null:{gradientUnits:"userSpaceOnUse"})).add(f.defs),h.stops=[],o(a.stops,function(a){e.test(a[1])?(d=ma(a[1]),n=d.get("rgb"),t=d.get("a")):(n=a[1],t=1);a=f.createElement("stop").attr({offset:a[0],"stop-color":n,"stop-opacity":t}).add(h);h.stops.push(a)}),c[r]=h);return"url("+this.url+"#"+g+")"}else return e.test(a)?(d=ma(a),A(b,c+"-opacity",d.get("a")),d.get("rgb")):(b.removeAttribute(c+"-opacity"),a)},text:function(a,b,c,d){var e=
127
+ Ea.chart.style;if(d&&!this.forExport)return this.html(a,b,c);b=z(p(b,0));c=z(p(c,0));a=this.createElement("text").attr({x:b,y:c,text:a}).css({fontFamily:e.fontFamily,fontSize:e.fontSize});a.x=b;a.y=c;return a},html:function(a,b,c){var d=Ea.chart.style,e=this.createElement("span"),f=e.attrSetters,g=e.element,h=e.renderer;f.text=function(a){g.innerHTML=a;return!1};f.x=f.y=f.align=function(a,b){b==="align"&&(b="textAlign");e[b]=a;e.htmlUpdateTransform();return!1};e.attr({text:a,x:z(b),y:z(c)}).css({position:wb,
128
+ whiteSpace:"nowrap",fontFamily:d.fontFamily,fontSize:d.fontSize});e.css=e.htmlCss;if(h.isSVG)e.add=function(a){var b,c,d=h.box.parentNode;if(a){if(b=a.div,!b)b=a.div=Aa(Ra,{className:A(a.element,"class")},{position:wb,left:a.attr("translateX")+ga,top:a.attr("translateY")+ga},d),c=b.style,L(a.attrSetters,{translateX:function(a){c.left=a+ga},translateY:function(a){c.top=a+ga},visibility:function(a,b){c[b]=a}})}else b=d;b.appendChild(g);e.added=!0;e.alignOnAdd&&e.htmlUpdateTransform();return e};return e},
129
+ fontMetrics:function(a){var a=S(a||11),a=a<24?a+4:z(a*1.2),b=z(a*0.8);return{h:a,b:b}},label:function(a,b,c,d,e,f,g,h){function i(){var a=n.styles,a=a&&a.textAlign,b=v,c;c=h?0:ia;if(s(y)&&(a==="center"||a==="right"))b+={center:0.5,right:1}[a]*(y-p.width);(b!==t.x||c!==t.y)&&t.attr({x:b,y:c});t.x=b;t.y=c}function k(a,b){r?r.attr(a,b):x[a]=b}function j(){n.attr({text:a,x:b,y:c,anchorX:e,anchorY:f})}var l=this,n=l.g(),t=l.text("",0,0,g).attr({zIndex:1}).add(n),r,p,V="left",v=3,y,q,T,A,w=0,x={},ia,g=
130
+ n.attrSetters;ha(n,"add",j);g.width=function(a){y=a;return!1};g.height=function(a){q=a;return!1};g.padding=function(a){s(a)&&a!==v&&(v=a,i());return!1};g.align=function(a){V=a;return!1};g.text=function(a,b){t.attr(b,a);var c;c=t.element.style;p=(y===void 0||q===void 0||n.styles.textAlign)&&t.getBBox(!0);n.width=(y||p.width)+2*v;n.height=(q||p.height)+2*v;ia=v+l.fontMetrics(c&&c.fontSize).b;if(!r)c=h?-ia:0,n.box=r=d?l.symbol(d,0,c,n.width,n.height):l.rect(0,c,n.width,n.height,0,x["stroke-width"]),
131
+ r.add(n);r.attr(K({width:n.width,height:n.height},x));x=null;i();return!1};g["stroke-width"]=function(a,b){w=a%2/2;k(b,a);return!1};g.stroke=g.fill=g.r=function(a,b){k(b,a);return!1};g.anchorX=function(a,b){e=a;k(b,a+w-T);return!1};g.anchorY=function(a,b){f=a;k(b,a-A);return!1};g.x=function(a){a-={left:0,center:0.5,right:1}[V]*((y||p.width)+v);T=n.x=z(a);n.attr("translateX",T);return!1};g.y=function(a){A=n.y=z(a);n.attr("translateY",a);return!1};var ua=n.css;return L(n,{css:function(a){if(a){var b=
132
+ {},a=K({},a);o("fontSize,fontWeight,fontFamily,color,lineHeight,width".split(","),function(c){a[c]!==X&&(b[c]=a[c],delete a[c])});t.css(b)}return ua.call(n,a)},getBBox:function(){return r.getBBox()},shadow:function(a){r.shadow(a);return n},destroy:function(){Qa(n,"add",j);Qa(n.element,"mouseenter");Qa(n.element,"mouseleave");t&&(t=t.destroy());Sa.prototype.destroy.call(n)}})}};Xb=Eb;var $a;if(!Pb&&!Fa)$a={init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ",wb,";"];(b==="shape"||
133
+ b===Ra)&&d.push("left:0;top:0;width:10px;height:10px;");Xa&&d.push("visibility: ",b===Ra?ab:eb);c.push(' style="',d.join(""),'"/>');if(b)c=b===Ra||b==="span"||b==="img"?c.join(""):a.prepVML(c),this.element=Aa(c);this.renderer=a;this.attrSetters={}},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);Xa&&d.gVis===ab&&P(c,{visibility:ab});d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();aa(this,
134
+ "add");return this},toggleChildren:function(a,b){for(var c=a.childNodes,d=c.length;d--;)P(c[d],{visibility:b}),c[d].nodeName==="DIV"&&this.toggleChildren(c[d],b)},updateTransform:Sa.prototype.htmlUpdateTransform,attr:function(a,b){var c,d,e,f=this.element||{},g=f.style,h=f.nodeName,i=this.renderer,k=this.symbolName,j,l=this.shadows,n,o=this.attrSetters,r=this;Ab(a)&&s(b)&&(c=a,a={},a[c]=b);if(Ab(a))c=a,r=c==="strokeWidth"||c==="stroke-width"?this.strokeweight:this[c];else for(c in a)if(d=a[c],n=!1,
135
+ e=o[c]&&o[c](d,c),e!==!1&&d!==null){e!==X&&(d=e);if(k&&/^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(c))j||(this.symbolAttr(a),j=!0),n=!0;else if(c==="d"){d=d||[];this.d=d.join(" ");e=d.length;for(n=[];e--;)n[e]=Bb(d[e])?z(d[e]*10)-5:d[e]==="Z"?"x":d[e];d=n.join(" ")||"x";f.path=d;if(l)for(e=l.length;e--;)l[e].path=d;n=!0}else if(c==="zIndex"||c==="visibility"){if(Xa&&c==="visibility"&&h==="DIV")f.gVis=d,this.toggleChildren(f,d),d===eb&&(d=null);d&&(g[c]=d);n=!0}else if(c==="width"||
136
+ c==="height")d=W(0,d),this[c]=d,this.updateClipping?(this[c]=d,this.updateClipping()):g[c]=d,n=!0;else if(c==="x"||c==="y")this[c]=d,g[{x:"left",y:"top"}[c]]=d;else if(c==="class")f.className=d;else if(c==="stroke")d=i.color(d,f,c),c="strokecolor";else if(c==="stroke-width"||c==="strokeWidth")f.stroked=d?!0:!1,c="strokeweight",this[c]=d,Bb(d)&&(d+=ga);else if(c==="dashstyle")(f.getElementsByTagName("stroke")[0]||Aa(i.prepVML(["<stroke/>"]),null,null,f))[c]=d||"solid",this.dashstyle=d,n=!0;else if(c===
137
+ "fill")h==="SPAN"?g.color=d:(f.filled=d!==Ma?!0:!1,d=i.color(d,f,c),c="fillcolor");else if(c==="translateX"||c==="translateY"||c==="rotation")this[c]=d,this.updateTransform(),n=!0;else if(c==="text")this.bBox=null,f.innerHTML=d,n=!0;if(l&&c==="visibility")for(e=l.length;e--;)l[e].style[c]=d;n||(Xa?f[c]=d:A(f,c,d))}return r},clip:function(a){var b=this,c=a.members;c.push(b);b.destroyClip=function(){Gb(c,b)};return b.css(a.getCSS(b.inverted))},css:Sa.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&
138
+ Tb(a)},destroy:function(){this.destroyClip&&this.destroyClip();return Sa.prototype.destroy.apply(this)},empty:function(){for(var a=this.element.childNodes,b=a.length,c;b--;)c=a[b],c.parentNode.removeChild(c)},on:function(a,b){this.element["on"+a]=function(){var a=ca.event;a.target=a.srcElement;b(a)};return this},shadow:function(a,b){var c=[],d,e=this.element,f=this.renderer,g,h=e.style,i,k=e.path;k&&typeof k.value!=="string"&&(k="x");if(a){for(d=1;d<=3;d++)i=['<shape isShadow="true" strokeweight="',
139
+ 7-2*d,'" filled="false" path="',k,'" coordsize="100,100" style="',e.style.cssText,'" />'],g=Aa(f.prepVML(i),null,{left:S(h.left)+1,top:S(h.top)+1}),i=['<stroke color="black" opacity="',0.05*d,'"/>'],Aa(f.prepVML(i),null,null,g),b?b.element.appendChild(g):e.parentNode.insertBefore(g,e),c.push(g);this.shadows=c}return this}},$a=pa(Sa,$a),w={Element:$a,isIE8:kb.indexOf("MSIE 8.0")>-1,init:function(a,b,c){var d,e;this.alignedObjects=[];d=this.createElement(Ra);e=d.element;e.style.position=mc;a.appendChild(d.element);
140
+ this.box=e;this.boxWrapper=d;this.setSize(b,c,!1);if(!x.namespaces.hcv)x.namespaces.add("hcv","urn:schemas-microsoft-com:vml"),x.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "},clipRect:function(a,b,c,d){var e=this.createElement();return L(e,{members:[],left:a,top:b,width:c,height:d,getCSS:function(a){var b=this.top,c=this.left,d=c+this.width,e=b+this.height,b={clip:"rect("+z(a?c:b)+"px,"+z(a?e:d)+"px,"+z(a?d:e)+
141
+ "px,"+z(a?b:c)+"px)"};!a&&Xa&&L(b,{width:d+ga,height:e+ga});return b},updateClipping:function(){o(e.members,function(a){a.css(e.getCSS(a.inverted))})}})},color:function(a,b,c){var d,e=/^rgba/;if(a&&a.linearGradient){var f,g,h=a.linearGradient,i=h.x1||h[0]||0,k=h.y1||h[1]||0,j=h.x2||h[2]||0,h=h.y2||h[3]||0,l,n,p,r;o(a.stops,function(a,b){e.test(a[1])?(d=ma(a[1]),f=d.get("rgb"),g=d.get("a")):(f=a[1],g=1);b?(p=f,r=g):(l=f,n=g)});if(c==="fill")a=90-oa.atan((h-k)/(j-i))*180/da,a=['<fill colors="0% ',l,
142
+ ",100% ",p,'" angle="',a,'" opacity="',r,'" o:opacity2="',n,'" type="gradient" focus="100%" method="sigma" />'],Aa(this.prepVML(a),null,null,b);else return f}else if(e.test(a)&&b.tagName!=="IMG")return d=ma(a),a=["<",c,' opacity="',d.get("a"),'"/>'],Aa(this.prepVML(a),null,null,b),d.get("rgb");else{b=b.getElementsByTagName(c);if(b.length)b[0].opacity=1;return a}},prepVML:function(a){var b=this.isIE8,a=a.join("");b?(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=a.indexOf('style="')===
143
+ -1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')):a=a.replace("<","<hcv:");return a},text:Eb.prototype.html,path:function(a){return this.createElement("shape").attr({coordsize:"100 100",d:a})},circle:function(a,b,c){return this.symbol("circle").attr({x:a-c,y:b-c,width:2*c,height:2*c})},g:function(a){var b;a&&(b={className:Ia+a,"class":Ia+a});return this.createElement(Ra).attr(b)},image:function(a,
144
+ b,c,d,e){var f=this.createElement("img").attr({src:a});arguments.length>1&&f.css({left:b,top:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){if(mb(a))b=a.y,c=a.width,d=a.height,f=a.strokeWidth,a=a.x;var g=this.symbol("rect");g.r=e;return g.attr(g.crisp(f,a,b,W(c,0),W(d,0)))},invertChild:function(a,b){var c=b.style;P(a,{flip:"x",left:S(c.width)-10,top:S(c.height)-10,rotation:-90})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,c=e.r||c||d,d=ja(f),h=C(f),i=ja(g),k=C(g),e=e.innerR,
145
+ j=0.08/c,l=e&&0.25/e||0;if(g-f===0)return["x"];else 2*da-g+f<j?i=-j:g-f<l&&(i=ja(f+l));return["wa",a-c,b-c,a+c,b+c,a+c*d,b+c*h,a+c*i,b+c*k,"at",a-e,b-e,a+e,b+e,a+e*i,b+e*k,a+e*d,b+e*h,"x","e"]},circle:function(a,b,c,d){return["wa",a,b,a+c,b+d,a+c,b+d/2,a+c,b+d/2,"e"]},rect:function(a,b,c,d,e){if(!s(e))return[];var f=a+c,g=b+d,c=Ua(e.r||0,c,d);return[wa,a+c,b,fa,f-c,b,"wa",f-2*c,b,f,b+2*c,f-c,b,f,b+c,fa,f,g-c,"wa",f-2*c,g-2*c,f,g,f,g-c,f-c,g,fa,a+c,g,"wa",a,g-2*c,a+2*c,g,a+c,g,a,g-c,fa,a,b+c,"wa",
146
+ a,b,a+2*c,b+2*c,a,b+c,a+c,b,"x","e"]}}},$a=function(){this.init.apply(this,arguments)},$a.prototype=K(Eb.prototype,w),Xb=$a;var oc,Cc;Fa&&(oc=function(){},Cc=function(){function a(){var a=b.length,d;for(d=0;d<a;d++)b[d]();b=[]}var b=[];return{push:function(c,d){b.length===0&&Hc(d,a);b.push(c)}}}());Xb=$a||oc||Eb;wc.prototype.callbacks=[];var lb=function(){};lb.prototype={init:function(a,b,c){var d=a.chart.counters;this.series=a;this.applyOptions(b,c);this.pointAttr={};if(a.options.colorByPoint){b=
147
+ a.chart.options.colors;if(!this.options)this.options={};this.color=this.options.color=this.color||b[d.color++];d.wrapColor(b.length)}a.chart.pointCount++;return this},applyOptions:function(a,b){var c=this.series,d=typeof a;this.config=a;if(d==="number"||a===null)this.y=a;else if(typeof a[0]==="number")this.x=a[0],this.y=a[1];else if(d==="object"&&typeof a.length!=="number"){if(L(this,a),this.options=a,a.dataLabels)c._hasPointLabels=!0}else if(typeof a[0]==="string")this.name=a[0],this.y=a[1];if(this.x===
148
+ X)this.x=b===X?c.autoIncrement():b},destroy:function(){var a=this.series,b=a.chart.hoverPoints,c;a.chart.pointCount--;b&&(this.setState(),Gb(b,this));if(this===a.chart.hoverPoint)this.onMouseOut();a.chart.hoverPoints=null;if(this.graphic||this.dataLabel)Qa(this),this.destroyElements();this.legendItem&&this.series.chart.legend.destroyItem(this);for(c in this)this[c]=null},destroyElements:function(){for(var a="graphic,tracker,dataLabel,group,connector,shadowGroup".split(","),b,c=6;c--;)b=a[c],this[b]&&
149
+ (this[b]=this[b].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},select:function(a,b){var c=this,d=c.series.chart,a=p(a,!c.selected);c.firePointEvent(a?"select":"unselect",{accumulate:b},function(){c.selected=a;c.setState(a&&"select");b||o(d.getSelectedPoints(),function(a){if(a.selected&&a!==c)a.selected=!1,a.setState(Ka),a.firePointEvent("unselect")})})},
150
+ onMouseOver:function(){var a=this.series,b=a.chart,c=b.tooltip,d=b.hoverPoint;if(d&&d!==this)d.onMouseOut();this.firePointEvent("mouseOver");c&&(!c.shared||a.noSharedTooltip)&&c.refresh(this);this.setState(ta);b.hoverPoint=this},onMouseOut:function(){this.firePointEvent("mouseOut");this.setState();this.series.chart.hoverPoint=null},tooltipFormatter:function(a){var b=this.series,c=b.tooltipOptions,d=String(this.y).split("."),d=d[1]?d[1].length:0,e=a.match(/\{(series|point)\.[a-zA-Z]+\}/g),f=/[{\.}]/,
151
+ g,h,i,k;for(k in e)h=e[k],Ab(h)&&h!==a&&(i=(" "+h).split(f),g={point:this,series:b}[i[1]],i=i[2],g=g===this&&(i==="y"||i==="open"||i==="high"||i==="low"||i==="close")?(c.valuePrefix||c.yPrefix||"")+dc(this[i],p(c.valueDecimals,c.yDecimals,d))+(c.valueSuffix||c.ySuffix||""):g[i],a=a.replace(h,g));return a},update:function(a,b,c){var d=this,e=d.series,f=d.graphic,g,h=e.data,i=h.length,k=e.chart,b=p(b,!0);d.firePointEvent("update",{options:a},function(){d.applyOptions(a);mb(a)&&(e.getAttribs(),f&&f.attr(d.pointAttr[e.state]));
152
+ for(g=0;g<i;g++)if(h[g]===d){e.xData[g]=d.x;e.yData[g]=d.y;e.options.data[g]=a;break}e.isDirty=!0;e.isDirtyData=!0;b&&k.redraw(c)})},remove:function(a,b){var c=this,d=c.series,e=d.chart,f,g=d.data,h=g.length;Kb(b,e);a=p(a,!0);c.firePointEvent("remove",null,function(){for(f=0;f<h;f++)if(g[f]===c){g.splice(f,1);d.options.data.splice(f,1);d.xData.splice(f,1);d.yData.splice(f,1);break}c.destroy();d.isDirty=!0;d.isDirtyData=!0;a&&e.redraw()})},firePointEvent:function(a,b,c){var d=this,e=this.series.options;
153
+ (e.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();a==="click"&&e.allowPointSelect&&(c=function(a){d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});aa(this,a,b,c)},importEvents:function(){if(!this.hasImportedEvents){var a=K(this.series.options.point,this.options).events,b;this.events=a;for(b in a)ha(this,b,a[b]);this.hasImportedEvents=!0}},setState:function(a){var b=this.plotX,c=this.plotY,d=this.series,e=d.options.states,f=M[d.type].marker&&d.options.marker,
154
+ g=f&&!f.enabled,h=f&&f.states[a],i=h&&h.enabled===!1,k=d.stateMarkerGraphic,j=d.chart,l=this.pointAttr,a=a||Ka;if(!(a===this.state||this.selected&&a!=="select"||e[a]&&e[a].enabled===!1||a&&(i||g&&!h.enabled))){if(this.graphic)e=f&&this.graphic.symbolName&&l[a].r,this.graphic.attr(K(l[a],e?{x:b-e,y:c-e,width:2*e,height:2*e}:{}));else{if(a){if(!k)e=f.radius,d.stateMarkerGraphic=k=j.renderer.symbol(d.symbol,-e,-e,2*e,2*e).attr(l[a]).add(d.group);k.translate(b,c)}if(k)k[a?"show":"hide"]()}this.state=
155
+ a}}};var $=function(){};$.prototype={isCartesian:!0,type:"line",pointClass:lb,sorted:!0,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},init:function(a,b){var c,d;d=a.series.length;this.chart=a;this.options=b=this.setOptions(b);this.bindAxes();L(this,{index:d,name:b.name||"Series "+(d+1),state:Ka,pointAttr:{},visible:b.visible!==!1,selected:b.selected===!0});if(Fa)b.animation=!1;d=b.events;for(c in d)ha(this,c,d[c]);if(d&&d.click||b.point&&b.point.events&&
156
+ b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;this.getColor();this.getSymbol();this.setData(b.data,!1)},bindAxes:function(){var a=this,b=a.options,c=a.chart,d;a.isCartesian&&o(["xAxis","yAxis"],function(e){o(c[e],function(c){d=c.options;if(b[e]===d.index||b[e]===X&&d.index===0)c.series.push(a),a[e]=c,c.isDirty=!0})})},autoIncrement:function(){var a=this.options,b=this.xIncrement,b=p(b,a.pointStart,0);this.pointInterval=p(this.pointInterval,a.pointInterval,1);this.xIncrement=b+this.pointInterval;
157
+ return b},getSegments:function(){var a=-1,b=[],c,d=this.points,e=d.length;if(e)if(this.options.connectNulls){for(c=e;c--;)d[c].y===null&&d.splice(c,1);d.length&&(b=[d])}else o(d,function(c,g){c.y===null?(g>a+1&&b.push(d.slice(a+1,g)),a=g):g===e-1&&b.push(d.slice(a+1,g+1))});this.segments=b},setOptions:function(a){var b=this.chart.options,c=b.plotOptions,d=a.data;a.data=null;c=K(c[this.type],c.series,a);c.data=a.data=d;this.tooltipOptions=K(b.tooltip,c.tooltip);return c},getColor:function(){var a=
158
+ this.chart.options.colors,b=this.chart.counters;this.color=this.options.color||a[b.color++]||"#0000ff";b.wrapColor(a.length)},getSymbol:function(){var a=this.options.marker,b=this.chart,c=b.options.symbols,b=b.counters;this.symbol=a.symbol||c[b.symbol++];if(/^url/.test(this.symbol))a.radius=0;b.wrapSymbol(c.length)},addPoint:function(a,b,c,d){var e=this.data,f=this.graph,g=this.area,h=this.chart,i=this.xData,k=this.yData,j=f&&f.shift||0,l=this.options.data;Kb(d,h);if(f&&c)f.shift=j+1;if(g){if(c)g.shift=
159
+ j+1;g.isArea=!0}b=p(b,!0);d={series:this};this.pointClass.prototype.applyOptions.apply(d,[a]);i.push(d.x);k.push(this.valueCount===4?[d.open,d.high,d.low,d.close]:d.y);l.push(a);c&&(e[0]?e[0].remove(!1):(e.shift(),i.shift(),k.shift(),l.shift()));this.getAttribs();this.isDirtyData=this.isDirty=!0;b&&h.redraw()},setData:function(a,b){var c=this.points,d=this.options,e=this.initialColor,f=this.chart,g=null;this.xIncrement=null;this.pointRange=this.xAxis&&this.xAxis.categories&&1||d.pointRange;if(s(e))f.counters.color=
160
+ e;var h=[],i=[],k=a?a.length:[],j=this.valueCount===4;if(k>(d.turboThreshold||1E3)){for(e=0;g===null&&e<k;)g=a[e],e++;if(Bb(g)){g=p(d.pointStart,0);d=p(d.pointInterval,1);for(e=0;e<k;e++)h[e]=g,i[e]=a[e],g+=d;this.xIncrement=g}else if(Fb(g))if(j)for(e=0;e<k;e++)d=a[e],h[e]=d[0],i[e]=d.slice(1,5);else for(e=0;e<k;e++)d=a[e],h[e]=d[0],i[e]=d[1]}else for(e=0;e<k;e++)d={series:this},this.pointClass.prototype.applyOptions.apply(d,[a[e]]),h[e]=d.x,i[e]=j?[d.open,d.high,d.low,d.close]:d.y;this.data=[];this.options.data=
161
+ a;this.xData=h;this.yData=i;for(e=c&&c.length||0;e--;)c[e]&&c[e].destroy&&c[e].destroy();this.isDirty=this.isDirtyData=f.isDirtyBox=!0;p(b,!0)&&f.redraw(!1)},remove:function(a,b){var c=this,d=c.chart,a=p(a,!0);if(!c.isRemoving)c.isRemoving=!0,aa(c,"remove",null,function(){c.destroy();d.isDirtyLegend=d.isDirtyBox=!0;a&&d.redraw(b)});c.isRemoving=!1},processData:function(a){var b=this.xData,c=this.yData,d=b.length,e=0,f=d,g,h,i=this.xAxis,k=this.options,j=k.cropThreshold,l=this.isCartesian;if(l&&!this.isDirty&&
162
+ !i.isDirty&&!this.yAxis.isDirty&&!a)return!1;if(l&&this.sorted&&(!j||d>j||this.forceCrop))if(a=i.getExtremes(),i=a.min,j=a.max,b[d-1]<i||b[0]>j)b=[],c=[];else if(b[0]<i||b[d-1]>j){for(a=0;a<d;a++)if(b[a]>=i){e=W(0,a-1);break}for(;a<d;a++)if(b[a]>j){f=a+1;break}b=b.slice(e,f);c=c.slice(e,f);g=!0}for(a=b.length-1;a>0;a--)if(d=b[a]-b[a-1],d>0&&(h===X||d<h))h=d;this.cropped=g;this.cropStart=e;this.processedXData=b;this.processedYData=c;if(k.pointRange===null)this.pointRange=h||1;this.closestPointRange=
163
+ h},generatePoints:function(){var a=this.options.data,b=this.data,c,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,i,k=this.hasGroupedData,j,l=[],n;if(!b&&!k)b=[],b.length=a.length,b=this.data=b;for(n=0;n<g;n++)i=h+n,k?l[n]=(new f).init(this,[d[n]].concat(Hb(e[n]))):(b[i]?j=b[i]:b[i]=j=(new f).init(this,a[i],d[n]),l[n]=j);if(b&&(g!==(c=b.length)||k))for(n=0;n<c;n++)n===h&&!k&&(n+=g),b[n]&&b[n].destroyElements();this.data=b;this.points=l},translate:function(){this.processedXData||
164
+ this.processData();this.generatePoints();for(var a=this.chart,b=this.options,c=b.stacking,d=this.xAxis,e=d.categories,f=this.yAxis,g=this.points,h=g.length,i=!!this.modifyValue,k,j=f.series,l=j.length;l--;)if(j[l].visible){l===this.index&&(k=!0);break}for(l=0;l<h;l++){var j=g[l],n=j.x,o=j.y,r=j.low,p=f.stacks[(o<b.threshold?"-":"")+this.stackKey];j.plotX=z(d.translate(n,0,0,0,1)*10)/10;if(c&&this.visible&&p&&p[n]){r=p[n];n=r.total;r.cum=r=r.cum-o;o=r+o;if(k)r=b.threshold;c==="percent"&&(r=n?r*100/
165
+ n:0,o=n?o*100/n:0);j.percentage=n?j.y*100/n:0;j.stackTotal=n;j.stackY=o}j.yBottom=s(r)?f.translate(r,0,1,0,1):null;i&&(o=this.modifyValue(o,j));j.plotY=typeof o==="number"?z(f.translate(o,0,1,0,1)*10)/10:X;j.clientX=a.inverted?a.plotHeight-j.plotX:j.plotX;j.category=e&&e[j.x]!==X?e[j.x]:j.x}this.getSegments()},setTooltipPoints:function(a){var b=this.chart,c=b.inverted,d=[],b=z((c?b.plotTop:b.plotLeft)+b.plotSizeX),e,f;e=this.xAxis;var g,h,i=[];if(this.options.enableMouseTracking!==!1){if(a)this.tooltipPoints=
166
+ null;o(this.segments||this.points,function(a){d=d.concat(a)});e&&e.reversed&&(d=d.reverse());a=d.length;for(h=0;h<a;h++){g=d[h];e=d[h-1]?d[h-1]._high+1:0;for(f=g._high=d[h+1]?Ta((g.plotX+(d[h+1]?d[h+1].plotX:b))/2):b;e<=f;)i[c?b-e++:e++]=g}this.tooltipPoints=i}},tooltipHeaderFormatter:function(a){var b=this.tooltipOptions,c=b.xDateFormat||"%A, %b %e, %Y",d=this.xAxis;return b.headerFormat.replace("{point.key}",d&&d.options.type==="datetime"?ac(c,a):a).replace("{series.name}",this.name).replace("{series.color}",
167
+ this.color)},onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(Ga||!a.mouseIsDown){if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&aa(this,"mouseOver");this.setState(ta);a.hoverSeries=this}},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;if(d)d.onMouseOut();this&&a.events.mouseOut&&aa(this,"mouseOut");c&&!a.stickyTracking&&!c.shared&&c.hide();this.setState();b.hoverSeries=null},animate:function(a){var b=this.chart,c=this.clipRect,d=this.options.animation;
168
+ d&&!mb(d)&&(d={});if(a){if(!c.isAnimating)c.attr("width",0),c.isAnimating=!0}else c.animate({width:b.plotSizeX},d),this.animate=null},drawPoints:function(){var a,b=this.points,c=this.chart,d,e,f,g,h,i,k,j;if(this.options.marker.enabled)for(f=b.length;f--;)if(g=b[f],d=g.plotX,e=g.plotY,j=g.graphic,e!==X&&!isNaN(e))if(a=g.pointAttr[g.selected?"select":Ka],h=a.r,i=p(g.marker&&g.marker.symbol,this.symbol),k=i.indexOf("url")===0,j)j.animate(L({x:d-h,y:e-h},j.symbolName?{width:2*h,height:2*h}:{}));else if(h>
169
+ 0||k)g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h).attr(a).add(this.group)},convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,f,g,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=p(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var a=this,b=M[a.type].marker?a.options.marker:a.options,c=b.states,d=c[ta],e,f=a.color,g={stroke:f,fill:f},h=a.points,i=[],k,j=a.pointAttrToOptions,l;a.options.marker?(d.radius=d.radius||b.radius+2,d.lineWidth=d.lineWidth||b.lineWidth+1):d.color=
170
+ d.color||ma(d.color||f).brighten(d.brightness).get();i[Ka]=a.convertAttribs(b,g);o([ta,"select"],function(b){i[b]=a.convertAttribs(c[b],i[Ka])});a.pointAttr=i;for(f=h.length;f--;){g=h[f];if((b=g.options&&g.options.marker||g.options)&&b.enabled===!1)b.radius=0;e=!1;if(g.options)for(l in j)s(b[j[l]])&&(e=!0);if(e){k=[];c=b.states||{};e=c[ta]=c[ta]||{};if(!a.options.marker)e.color=ma(e.color||g.options.color).brighten(e.brightness||d.brightness).get();k[Ka]=a.convertAttribs(b,i[Ka]);k[ta]=a.convertAttribs(c[ta],
171
+ i[ta],k[Ka]);k.select=a.convertAttribs(c.select,i.select,k[Ka])}else k=i;g.pointAttr=k}},destroy:function(){var a=this,b=a.chart,c=a.clipRect,d=/AppleWebKit\/533/.test(kb),e,f,g=a.data||[],h,i,k;aa(a,"destroy");Qa(a);o(["xAxis","yAxis"],function(b){if(k=a[b])Gb(k.series,a),k.isDirty=!0});a.legendItem&&a.chart.legend.destroyItem(a);for(f=g.length;f--;)(h=g[f])&&h.destroy&&h.destroy();a.points=null;if(c&&c!==b.clipRect)a.clipRect=c.destroy();o(["area","graph","dataLabelsGroup","group","tracker"],function(b){a[b]&&
172
+ (e=d&&b==="group"?"hide":"destroy",a[b][e]())});if(b.hoverSeries===a)b.hoverSeries=null;Gb(b.series,a);for(i in a)delete a[i]},drawDataLabels:function(){var a=this,b=a.options,c=b.dataLabels;if(c.enabled||a._hasPointLabels){var d,e,f=a.points,g,h,i,k=a.dataLabelsGroup,j=a.chart,l=a.xAxis,l=l?l.left:j.plotLeft,n=a.yAxis,n=n?n.top:j.plotTop,t=j.renderer,r=j.inverted,Z=a.type,V=b.stacking,v=Z==="column"||Z==="bar",y=c.verticalAlign===null,q=c.y===null,T=t.fontMetrics(c.style.fontSize),A=T.h,x=T.b,w,
173
+ ia;v&&(T={top:x,middle:x-A/2,bottom:-A+x},V?(y&&(c=K(c,{verticalAlign:"middle"})),q&&(c=K(c,{y:T[c.verticalAlign]}))):y?c=K(c,{verticalAlign:"top"}):q&&(c=K(c,{y:T[c.verticalAlign]})));k?k.translate(l,n):k=a.dataLabelsGroup=t.g("data-labels").attr({visibility:a.visible?eb:ab,zIndex:6}).translate(l,n).add();h=c;o(f,function(f){w=f.dataLabel;c=h;(g=f.options)&&g.dataLabels&&(c=K(c,g.dataLabels));if(ia=c.enabled){var l=f.barX&&f.barX+f.barW/2||p(f.plotX,-999),n=p(f.plotY,-999),o=c.y===null?f.y>=b.threshold?
174
+ -A+x:x:c.y;d=(r?j.plotWidth-n:l)+c.x;e=z((r?j.plotHeight-l:n)+o)}if(w&&a.isCartesian&&(!j.isInsidePlot(d,e)||!ia))f.dataLabel=w.destroy();else if(ia){l=c.align;i=c.formatter.call(f.getLabelConfig(),c);Z==="column"&&(d+={left:-1,right:1}[l]*f.barW/2||0);!V&&r&&f.y<0&&(l="right",d-=10);c.style.color=p(c.color,c.style.color,a.color,"black");if(w)w.attr({text:i}).animate({x:d,y:e});else if(s(i))w=f.dataLabel=t[c.rotation?"text":"label"](i,d,e,null,null,null,c.useHTML,!0).attr({align:l,fill:c.backgroundColor,
175
+ stroke:c.borderColor,"stroke-width":c.borderWidth,r:c.borderRadius,rotation:c.rotation,padding:c.padding,zIndex:1}).css(c.style).add(k).shadow(c.shadow);if(v&&b.stacking&&w)l=f.barX,n=f.barY,o=f.barW,f=f.barH,w.align(c,null,{x:r?j.plotWidth-n-f:l,y:r?j.plotHeight-l-o:n,width:r?f:o,height:r?o:f})}})}},drawGraph:function(){var a=this,b=a.options,c=a.graph,d=[],e,f=a.area,g=a.group,h=b.lineColor||a.color,i=b.lineWidth,k=b.dashStyle,j,l=a.chart.renderer,n=a.yAxis.getThreshold(b.threshold),t=/^area/.test(a.type),
176
+ r=[],s=[];o(a.segments,function(c){j=[];o(c,function(d,e){a.getPointSpline?j.push.apply(j,a.getPointSpline(c,d,e)):(j.push(e?fa:wa),e&&b.step&&j.push(d.plotX,c[e-1].plotY),j.push(d.plotX,d.plotY))});c.length>1?d=d.concat(j):r.push(c[0]);if(t){var e=[],f,g=j.length;for(f=0;f<g;f++)e.push(j[f]);g===3&&e.push(fa,j[1],j[2]);if(b.stacking&&a.type!=="areaspline")for(f=c.length-1;f>=0;f--)f<c.length-1&&b.step&&e.push(c[f+1].plotX,c[f].yBottom),e.push(c[f].plotX,c[f].yBottom);else e.push(fa,c[c.length-1].plotX,
177
+ n,fa,c[0].plotX,n);s=s.concat(e)}});a.graphPath=d;a.singlePoints=r;if(t)e=p(b.fillColor,ma(a.color).setOpacity(b.fillOpacity||0.75).get()),f?f.animate({d:s}):a.area=a.chart.renderer.path(s).attr({fill:e}).add(g);if(c)Ob(c),c.animate({d:d});else if(i){c={stroke:h,"stroke-width":i};if(k)c.dashstyle=k;a.graph=l.path(d).attr(c).add(g).shadow(b.shadow)}},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};c.attr(a).invert();d&&d.attr(a).invert()}var b=this,c=b.group,d=b.trackerGroup,
178
+ e=b.chart;ha(e,"resize",a);ha(b,"destroy",function(){Qa(e,"resize",a)});a();b.invertGroups=a},render:function(){var a=this,b=a.chart,c,d=a.options,e=d.clip!==!1,f=d.animation,g=f&&a.animate,f=g?f&&f.duration||500:0,h=a.clipRect,i=b.renderer;if(!h&&(h=a.clipRect=!b.hasRendered&&b.clipRect?b.clipRect:i.clipRect(0,0,b.plotSizeX,b.plotSizeY+1),!b.clipRect))b.clipRect=h;if(!a.group)c=a.group=i.g("series"),c.attr({visibility:a.visible?eb:ab,zIndex:d.zIndex}).translate(a.xAxis.left,a.yAxis.top).add(b.seriesGroup);
179
+ a.drawDataLabels();g&&a.animate(!0);a.getAttribs();a.drawGraph&&a.drawGraph();a.drawPoints();a.options.enableMouseTracking!==!1&&a.drawTracker();b.inverted&&a.invertGroups();e&&!a.hasRendered&&(c.clip(h),a.trackerGroup&&a.trackerGroup.clip(b.clipRect));g&&a.animate();setTimeout(function(){h.isAnimating=!1;if((c=a.group)&&h!==b.clipRect&&h.renderer){if(e)c.clip(a.clipRect=b.clipRect);h.destroy()}},f);a.isDirty=a.isDirtyData=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,
180
+ c=this.group;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:this.xAxis.left,translateY:this.yAxis.top}));this.translate();this.setTooltipPoints(!0);this.render();b&&aa(this,"updatedData")},setState:function(a){var b=this.options,c=this.graph,d=b.states,b=b.lineWidth,a=a||Ka;if(this.state!==a)this.state=a,d[a]&&d[a].enabled===!1||(a&&(b=d[a].lineWidth||b+1),c&&!c.dashstyle&&c.attr({"stroke-width":b},a?0:500))},setVisible:function(a,b){var c=this.chart,d=this.legendItem,
181
+ e=this.group,f=this.tracker,g=this.dataLabelsGroup,h,i=this.points,k=c.options.chart.ignoreHiddenSeries;h=this.visible;h=(this.visible=a=a===X?!h:a)?"show":"hide";if(e)e[h]();if(f)f[h]();else if(i)for(e=i.length;e--;)if(f=i[e],f.tracker)f.tracker[h]();if(g)g[h]();d&&c.legend.colorizeItem(this,a);this.isDirty=!0;this.options.stacking&&o(c.series,function(a){if(a.options.stacking&&a.visible)a.isDirty=!0});if(k)c.isDirtyBox=!0;b!==!1&&c.redraw();aa(this,h)},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},
182
+ select:function(a){this.selected=a=a===X?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;aa(this,a?"select":"unselect")},drawTrackerGroup:function(){var a=this.trackerGroup,b=this.chart;if(this.isCartesian){if(!a)this.trackerGroup=a=b.renderer.g().attr({zIndex:this.options.zIndex||1}).add(b.trackerGroup);a.translate(this.xAxis.left,this.yAxis.top)}return a},drawTracker:function(){var a=this,b=a.options,c=[].concat(a.graphPath),d=c.length,e=a.chart,f=e.renderer,g=e.options.tooltip.snap,h=
183
+ a.tracker,i=b.cursor,i=i&&{cursor:i},k=a.singlePoints,j=a.drawTrackerGroup(),l;if(d)for(l=d+1;l--;)c[l]===wa&&c.splice(l+1,0,c[l+1]-g,c[l+2],fa),(l&&c[l]===wa||l===d)&&c.splice(l,0,fa,c[l-2]+g,c[l-1]);for(l=0;l<k.length;l++)d=k[l],c.push(wa,d.plotX-g,d.plotY,fa,d.plotX+g,d.plotY);h?h.attr({d:c}):a.tracker=f.path(c).attr({isTracker:!0,stroke:Gc,fill:Ma,"stroke-linejoin":"bevel","stroke-width":b.lineWidth+2*g,visibility:a.visible?eb:ab}).on(Ga?"touchstart":"mouseover",function(){if(e.hoverSeries!==
184
+ a)a.onMouseOver()}).on("mouseout",function(){if(!b.stickyTracking)a.onMouseOut()}).css(i).add(j)}};w=pa($);Ha.line=w;w=pa($,{type:"area"});Ha.area=w;w=pa($,{type:"spline",getPointSpline:function(a,b,c){var d=b.plotX,e=b.plotY,f=a[c-1],g=a[c+1],h,i,k,j;if(c&&c<a.length-1){a=f.plotY;k=g.plotX;var g=g.plotY,l;h=(1.5*d+f.plotX)/2.5;i=(1.5*e+a)/2.5;k=(1.5*d+k)/2.5;j=(1.5*e+g)/2.5;l=(j-i)*(k-d)/(k-h)+e-j;i+=l;j+=l;i>a&&i>e?(i=W(a,e),j=2*e-i):i<a&&i<e&&(i=Ua(a,e),j=2*e-i);j>g&&j>e?(j=W(g,e),i=2*e-j):j<g&&
185
+ j<e&&(j=Ua(g,e),i=2*e-j);b.rightContX=k;b.rightContY=j}c?(b=["C",f.rightContX||f.plotX,f.rightContY||f.plotY,h||d,i||e,d,e],f.rightContX=f.rightContY=null):b=[wa,d,e];return b}});Ha.spline=w;w=pa(w,{type:"areaspline"});Ha.areaspline=w;var zb=pa($,{type:"column",tooltipOutsidePlot:!0,pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color",r:"borderRadius"},init:function(){$.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasRendered&&o(b.series,function(b){if(b.type===
186
+ a.type)b.isDirty=!0})},translate:function(){var a=this,b=a.chart,c=a.options,d=c.stacking,e=c.borderWidth,f=0,g=a.xAxis,h=g.reversed,i={},k,j;$.prototype.translate.apply(a);o(b.series,function(b){if(b.type===a.type&&b.visible&&a.options.group===b.options.group)b.options.stacking?(k=b.stackKey,i[k]===X&&(i[k]=f++),j=i[k]):j=f++,b.columnIndex=j});var b=a.points,g=Ba(g.translationSlope)*(g.ordinalSlope||g.closestPointRange||1),l=g*c.groupPadding,n=(g-2*l)/f,t=c.pointWidth,r=s(t)?(n-t)/2:n*c.pointPadding,
187
+ w=Yb(W(p(t,n-2*r),1+2*e)),x=r+(l+((h?f-a.columnIndex:a.columnIndex)||0)*n-g/2)*(h?-1:1),v=a.yAxis.getThreshold(c.threshold),y=p(c.minPointLength,5);o(b,function(b){var f=b.plotY,g=p(b.yBottom,v),h=b.plotX+x,i=Yb(Ua(f,g)),j=Yb(W(f,g)-i),k=a.yAxis.stacks[(b.y<0?"-":"")+a.stackKey];d&&a.visible&&k&&k[b.x]&&k[b.x].setOffset(x,w);Ba(j)<y&&y&&(j=y,i=Ba(i-v)>y?g-y:v-(f<=v?y:0));L(b,{barX:h,barY:i,barW:w,barH:j});b.shapeType="rect";f={x:h,y:i,width:w,height:j,r:c.borderRadius,strokeWidth:e};e%2&&(f.y-=1,
188
+ f.height+=1);b.shapeArgs=f;b.trackerArgs=Ba(j)<3&&K(b.shapeArgs,{height:6,y:i-3})})},getSymbol:function(){},drawGraph:function(){},drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d,e;o(a.points,function(f){var g=f.plotY;if(g!==X&&!isNaN(g)&&f.y!==null)d=f.graphic,e=f.shapeArgs,d?(Ob(d),d.animate(c.Element.prototype.crisp.apply({},[e.strokeWidth,e.x,e.y,e.width,e.height]))):f.graphic=d=c[f.shapeType](e).attr(f.pointAttr[f.selected?"select":Ka]).add(a.group).shadow(b.shadow)})},drawTracker:function(){var a=
189
+ this,b=a.chart,c=b.renderer,d,e,f=+new Date,g=a.options,h=g.cursor,i=h&&{cursor:h},k=a.drawTrackerGroup(),j;o(a.points,function(h){e=h.tracker;d=h.trackerArgs||h.shapeArgs;delete d.strokeWidth;if(h.y!==null)e?e.attr(d):h.tracker=c[h.shapeType](d).attr({isTracker:f,fill:Gc,visibility:a.visible?eb:ab}).on(Ga?"touchstart":"mouseover",function(c){j=c.relatedTarget||c.fromElement;if(b.hoverSeries!==a&&A(j,"isTracker")!==f)a.onMouseOver();h.onMouseOver()}).on("mouseout",function(b){if(!g.stickyTracking&&
190
+ (j=b.relatedTarget||b.toElement,A(j,"isTracker")!==f))a.onMouseOut()}).css(i).add(h.group||k)})},animate:function(a){var b=this,c=b.points,d=b.options;if(!a)o(c,function(a){var c=a.graphic,a=a.shapeArgs,g=b.yAxis,h=d.threshold;c&&(c.attr({height:0,y:s(h)?g.getThreshold(h):g.translate(g.getExtremes().min,0,1,0,1)}),c.animate({height:a.height,y:a.y},d.animation))}),b.animate=null},remove:function(){var a=this,b=a.chart;b.hasRendered&&o(b.series,function(b){if(b.type===a.type)b.isDirty=!0});$.prototype.remove.apply(a,
191
+ arguments)}});Ha.column=zb;w=pa(zb,{type:"bar",init:function(){this.inverted=!0;zb.prototype.init.apply(this,arguments)}});Ha.bar=w;w=pa($,{type:"scatter",sorted:!1,translate:function(){var a=this;$.prototype.translate.apply(a);o(a.points,function(b){b.shapeType="circle";b.shapeArgs={x:b.plotX,y:b.plotY,r:a.chart.options.tooltip.snap}})},drawTracker:function(){for(var a=this,b=a.options.cursor,b=b&&{cursor:b},c=a.points,d=c.length,e;d--;)if(e=c[d].graphic)e.element._i=d;a._hasTracking?a._hasTracking=
192
+ !0:a.group.attr({isTracker:!0}).on(Ga?"touchstart":"mouseover",function(b){a.onMouseOver();if(b.target._i!==X)c[b.target._i].onMouseOver()}).on("mouseout",function(){if(!a.options.stickyTracking)a.onMouseOut()}).css(b)}});Ha.scatter=w;w=pa(lb,{init:function(){lb.prototype.init.apply(this,arguments);var a=this,b;L(a,{visible:a.visible!==!1,name:p(a.name,"Slice")});b=function(){a.slice()};ha(a,"select",b);ha(a,"unselect",b);return a},setVisible:function(a){var b=this.series.chart,c=this.tracker,d=this.dataLabel,
193
+ e=this.connector,f=this.shadowGroup,g;g=(this.visible=a=a===X?!this.visible:a)?"show":"hide";this.group[g]();if(c)c[g]();if(d)d[g]();if(e)e[g]();if(f)f[g]();this.legendItem&&b.legend.colorizeItem(this,a)},slice:function(a,b,c){var d=this.series.chart,e=this.slicedTranslation;Kb(c,d);p(b,!0);a=this.sliced=s(a)?a:!this.sliced;a={translateX:a?e[0]:d.plotLeft,translateY:a?e[1]:d.plotTop};this.group.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)}});w=pa($,{type:"pie",isCartesian:!1,pointClass:w,
194
+ pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},getColor:function(){this.initialColor=this.chart.counters.color},animate:function(){var a=this;o(a.points,function(b){var c=b.graphic,b=b.shapeArgs,d=-da/2;c&&(c.attr({r:0,start:d,end:d}),c.animate({r:b.r,start:b.start,end:b.end},a.options.animation))});a.animate=null},setData:function(){$.prototype.setData.apply(this,arguments);this.processData();this.generatePoints()},translate:function(){this.generatePoints();var a=
195
+ 0,b=-0.25,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f=c.center.concat([c.size,c.innerSize||0]),g=this.chart,h=g.plotWidth,i=g.plotHeight,k,j,l,n=this.points,p=2*da,r,s=Ua(h,i),w,v,y,q=c.dataLabels.distance,f=Vb(f,function(a,b){return(w=/%$/.test(a))?[h,i,s,s][b]*S(a)/100:a});this.getX=function(a,b){l=oa.asin((a-f[1])/(f[2]/2+q));return f[0]+(b?-1:1)*ja(l)*(f[2]/2+q)};this.center=f;o(n,function(b){a+=b.y});o(n,function(c){r=a?c.y/a:0;k=z(b*p*1E3)/1E3;b+=r;j=z(b*p*1E3)/1E3;c.shapeType="arc";
196
+ c.shapeArgs={x:f[0],y:f[1],r:f[2]/2,innerR:f[3]/2,start:k,end:j};l=(j+k)/2;c.slicedTranslation=Vb([ja(l)*d+g.plotLeft,C(l)*d+g.plotTop],z);v=ja(l)*f[2]/2;y=C(l)*f[2]/2;c.tooltipPos=[f[0]+v*0.7,f[1]+y*0.7];c.labelPos=[f[0]+v+ja(l)*q,f[1]+y+C(l)*q,f[0]+v+ja(l)*e,f[1]+y+C(l)*e,f[0]+v,f[1]+y,q<0?"center":l<p/4?"left":"right",l];c.percentage=r*100;c.total=a});this.setTooltipPoints()},render:function(){this.getAttribs();this.drawPoints();this.options.enableMouseTracking!==!1&&this.drawTracker();this.drawDataLabels();
197
+ this.options.animation&&this.animate&&this.animate();this.isDirty=!1},drawPoints:function(){var a=this.chart,b=a.renderer,c,d,e,f=this.options.shadow,g,h;o(this.points,function(i){d=i.graphic;h=i.shapeArgs;e=i.group;g=i.shadowGroup;if(f&&!g)g=i.shadowGroup=b.g("shadow").attr({zIndex:4}).add();if(!e)e=i.group=b.g("point").attr({zIndex:5}).add();c=i.sliced?i.slicedTranslation:[a.plotLeft,a.plotTop];e.translate(c[0],c[1]);g&&g.translate(c[0],c[1]);d?d.animate(h):i.graphic=b.arc(h).attr(L(i.pointAttr[Ka],
198
+ {"stroke-linejoin":"round"})).add(i.group).shadow(f,g);i.visible===!1&&i.setVisible(!1)})},drawDataLabels:function(){var a=this.data,b,c=this.chart,d=this.options.dataLabels,e=p(d.connectorPadding,10),f=p(d.connectorWidth,1),g,h,i=p(d.softConnector,!0),k=d.distance,j=this.center,l=j[2]/2,j=j[1],n=k>0,t=[[],[]],r,s,w,v,y=2,q;if(d.enabled){$.prototype.drawDataLabels.apply(this);o(a,function(a){a.dataLabel&&t[a.labelPos[7]<da/2?0:1].push(a)});t[1].reverse();v=function(a,b){return b.y-a.y};for(a=t[0][0]&&
199
+ t[0][0].dataLabel&&t[0][0].dataLabel.getBBox().height;y--;){var x=[],A=[],z=t[y],E=z.length,C;for(q=j-l-k;q<=j+l+k;q+=a)x.push(q);w=x.length;if(E>w){h=[].concat(z);h.sort(v);for(q=E;q--;)h[q].rank=q;for(q=E;q--;)z[q].rank>=w&&z.splice(q,1);E=z.length}for(q=0;q<E;q++){b=z[q];h=b.labelPos;b=9999;for(s=0;s<w;s++)g=Ba(x[s]-h[1]),g<b&&(b=g,C=s);if(C<q&&x[q]!==null)C=q;else for(w<E-q+C&&x[q]!==null&&(C=w-E+q);x[C]===null;)C++;A.push({i:C,y:x[C]});x[C]=null}A.sort(v);for(q=0;q<E;q++){b=z[q];h=b.labelPos;
200
+ g=b.dataLabel;s=A.pop();r=h[1];w=b.visible===!1?ab:eb;C=s.i;s=s.y;if(r>s&&x[C+1]!==null||r<s&&x[C-1]!==null)s=r;r=this.getX(C===0||C===x.length-1?r:s,y);g.attr({visibility:w,align:h[6]})[g.moved?"animate":"attr"]({x:r+d.x+({left:e,right:-e}[h[6]]||0),y:s+d.y});g.moved=!0;if(n&&f)g=b.connector,h=i?[wa,r+(h[6]==="left"?5:-5),s,"C",r,s,2*h[2]-h[4],2*h[3]-h[5],h[2],h[3],fa,h[4],h[5]]:[wa,r+(h[6]==="left"?5:-5),s,fa,h[2],h[3],fa,h[4],h[5]],g?(g.animate({d:h}),g.attr("visibility",w)):b.connector=g=this.chart.renderer.path(h).attr({"stroke-width":f,
201
+ stroke:d.connectorColor||b.color||"#606060",visibility:w,zIndex:3}).translate(c.plotLeft,c.plotTop).add()}}}},drawTracker:zb.prototype.drawTracker,getSymbol:function(){}});Ha.pie=w;L(Highcharts,{Chart:wc,dateFormat:ac,pathAnim:La,getOptions:function(){return Ea},hasBidiBug:Qc,numberFormat:dc,Point:lb,Color:ma,Renderer:Xb,SVGRenderer:Eb,VMLRenderer:$a,CanVGRenderer:oc,seriesTypes:Ha,setOptions:function(a){$b=K($b,a.xAxis);kc=K(kc,a.yAxis);a.xAxis=a.yAxis=X;Ea=K(Ea,a);vc();return Ea},Series:$,addEvent:ha,
202
+ removeEvent:Qa,createElement:Aa,discardElement:Tb,css:P,each:o,extend:L,map:Vb,merge:K,pick:p,splat:Hb,extendClass:pa,placeBox:uc,product:"Highcharts",version:"2.2.1"})})();
js/mandrill.js ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ JSON.stringify = JSON.stringify || function (obj) {
2
+ var t = typeof (obj);
3
+ if (t != "object" || obj === null) {
4
+ // simple data type
5
+ if (t == "string") obj = '"'+obj+'"';
6
+ return String(obj);
7
+ }
8
+ else {
9
+ // recurse array or object
10
+ var n, v, json = [], arr = (obj && obj.constructor == Array);
11
+ for (n in obj) {
12
+ v = obj[n]; t = typeof(v);
13
+ if (t == "string") v = '"'+v+'"';
14
+ else if (t == "object" && v !== null) v = JSON.stringify(v);
15
+ json.push((arr ? "" : '"' + n + '":') + String(v));
16
+ }
17
+ return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
18
+ }
19
+ };
20
+
21
+ jQuery(document).bind( 'ready', function() {
22
+ jQuery('#filter,#display').bind('change keyup', function() {
23
+
24
+ if ( jQuery("#filter option:selected").val() == 'none' ) {
25
+ var display = 'block';
26
+ } else {
27
+ var display = 'none';
28
+ }
29
+
30
+ jQuery('#all_time').css('display',display);
31
+ showStats();
32
+ });
33
+ jQuery('.columns-prefs, #collapse-button').bind('click', function () {
34
+ redrawDashboardWidget();
35
+ });
36
+
37
+ if ( pagenow == 'dashboard_page_wpmandrill-reports' ) {
38
+ showStats();
39
+ }
40
+ });
41
+
42
+ function showStats() {
43
+ var filter = jQuery("#filter option:selected").val();
44
+ var display = jQuery("#display option:selected").val();
45
+ jQuery('#loading_data').css('display','block');
46
+
47
+ jQuery.ajax({
48
+ type: 'POST',
49
+ url: ajaxurl,
50
+ data: {
51
+ action: 'get_mandrill_stats',
52
+ filter: filter,
53
+ display: display,
54
+ },
55
+ success: function(data, textStatus, XMLHttpRequest){
56
+ jQuery('#loading_data').css('display','none');
57
+ eval(data);
58
+ },
59
+ error: function(MLHttpRequest, textStatus, errorThrown){
60
+ jQuery('#loading_data').css('display','none');
61
+ alert(errorThrown);
62
+ }
63
+ });
64
+
65
+ return false;
66
+ }
67
+
68
+ function redrawDashboardWidget() {
69
+ jQuery('#mandrill_widget div#filtered_recent').html('<div id="ajax-icon-container"><span id="loading_data"></span></div>');
70
+ jQuery.ajax({
71
+ type: 'POST',
72
+ url: ajaxurl,
73
+ data: {
74
+ action: 'get_dashboard_widget_stats',
75
+ ajax: true,
76
+ },
77
+ success: function(data, textStatus, XMLHttpRequest){
78
+ eval(data);
79
+ },
80
+ error: function(MLHttpRequest, textStatus, errorThrown){
81
+ alert(errorThrown);
82
+ jQuery('#mandrill_widget div#filtered_recent').html('');
83
+ }
84
+ });
85
+
86
+ return false;
87
+ }
js/modules/canvas-tools.js ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ A class to parse color values
3
+ @author Stoyan Stefanov <sstoo@gmail.com>
4
+ @link http://www.phpied.com/rgb-color-parser-in-javascript/
5
+ Use it if you like it
6
+
7
+ canvg.js - Javascript SVG parser and renderer on Canvas
8
+ MIT Licensed
9
+ Gabe Lerner (gabelerner@gmail.com)
10
+ http://code.google.com/p/canvg/
11
+
12
+ Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
13
+
14
+ Highcharts JS v2.2.1 (2012-03-15)
15
+ CanVGRenderer Extension module
16
+
17
+ (c) 2011-2012 Torstein H?nsi, Erik Olsson
18
+
19
+ License: www.highcharts.com/license
20
+ */
21
+ function RGBColor(m){this.ok=!1;m.charAt(0)=="#"&&(m=m.substr(1,6));var m=m.replace(/ /g,""),m=m.toLowerCase(),a={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",
22
+ darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dodgerblue:"1e90ff",feldspar:"d19275",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",
23
+ gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgrey:"d3d3d3",lightgreen:"90ee90",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",
24
+ lightslateblue:"8470ff",lightslategray:"778899",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"00ff00",limegreen:"32cd32",linen:"faf0e6",magenta:"ff00ff",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370d8",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",
25
+ oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"d87093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"ff0000",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",
26
+ slategray:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",violetred:"d02090",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32"},c;for(c in a)m==c&&(m=a[c]);var d=[{re:/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,example:["rgb(123, 234, 45)","rgb(255,234,245)"],process:function(b){return[parseInt(b[1]),parseInt(b[2]),parseInt(b[3])]}},{re:/^(\w{2})(\w{2})(\w{2})$/,
27
+ example:["#00ff00","336699"],process:function(b){return[parseInt(b[1],16),parseInt(b[2],16),parseInt(b[3],16)]}},{re:/^(\w{1})(\w{1})(\w{1})$/,example:["#fb0","f0f"],process:function(b){return[parseInt(b[1]+b[1],16),parseInt(b[2]+b[2],16),parseInt(b[3]+b[3],16)]}}];for(c=0;c<d.length;c++){var b=d[c].process,k=d[c].re.exec(m);if(k)channels=b(k),this.r=channels[0],this.g=channels[1],this.b=channels[2],this.ok=!0}this.r=this.r<0||isNaN(this.r)?0:this.r>255?255:this.r;this.g=this.g<0||isNaN(this.g)?0:
28
+ this.g>255?255:this.g;this.b=this.b<0||isNaN(this.b)?0:this.b>255?255:this.b;this.toRGB=function(){return"rgb("+this.r+", "+this.g+", "+this.b+")"};this.toHex=function(){var b=this.r.toString(16),a=this.g.toString(16),d=this.b.toString(16);b.length==1&&(b="0"+b);a.length==1&&(a="0"+a);d.length==1&&(d="0"+d);return"#"+b+a+d};this.getHelpXML=function(){for(var b=[],k=0;k<d.length;k++)for(var c=d[k].example,h=0;h<c.length;h++)b[b.length]=c[h];for(var j in a)b[b.length]=j;c=document.createElement("ul");
29
+ c.setAttribute("id","rgbcolor-examples");for(k=0;k<b.length;k++)try{var l=document.createElement("li"),o=new RGBColor(b[k]),n=document.createElement("div");n.style.cssText="margin: 3px; border: 1px solid black; background:"+o.toHex()+"; color:"+o.toHex();n.appendChild(document.createTextNode("test"));var q=document.createTextNode(" "+b[k]+" -> "+o.toRGB()+" -> "+o.toHex());l.appendChild(n);l.appendChild(q);c.appendChild(l)}catch(p){}return c}}
30
+ if(!window.console)window.console={},window.console.log=function(){},window.console.dir=function(){};if(!Array.prototype.indexOf)Array.prototype.indexOf=function(m){for(var a=0;a<this.length;a++)if(this[a]==m)return a;return-1};
31
+ (function(){function m(){var a={FRAMERATE:30,MAX_VIRTUAL_PIXELS:3E4};a.init=function(c){a.Definitions={};a.Styles={};a.Animations=[];a.Images=[];a.ctx=c;a.ViewPort=new function(){this.viewPorts=[];this.Clear=function(){this.viewPorts=[]};this.SetCurrent=function(a,b){this.viewPorts.push({width:a,height:b})};this.RemoveCurrent=function(){this.viewPorts.pop()};this.Current=function(){return this.viewPorts[this.viewPorts.length-1]};this.width=function(){return this.Current().width};this.height=function(){return this.Current().height};
32
+ this.ComputeSize=function(a){return a!=null&&typeof a=="number"?a:a=="x"?this.width():a=="y"?this.height():Math.sqrt(Math.pow(this.width(),2)+Math.pow(this.height(),2))/Math.sqrt(2)}}};a.init();a.ImagesLoaded=function(){for(var c=0;c<a.Images.length;c++)if(!a.Images[c].loaded)return!1;return!0};a.trim=function(a){return a.replace(/^\s+|\s+$/g,"")};a.compressSpaces=function(a){return a.replace(/[\s\r\t\n]+/gm," ")};a.ajax=function(a){var d;return(d=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP"))?
33
+ (d.open("GET",a,!1),d.send(null),d.responseText):null};a.parseXml=function(a){if(window.DOMParser)return(new DOMParser).parseFromString(a,"text/xml");else{var a=a.replace(/<!DOCTYPE svg[^>]*>/,""),d=new ActiveXObject("Microsoft.XMLDOM");d.async="false";d.loadXML(a);return d}};a.Property=function(c,d){this.name=c;this.value=d;this.hasValue=function(){return this.value!=null&&this.value!==""};this.numValue=function(){if(!this.hasValue())return 0;var b=parseFloat(this.value);(this.value+"").match(/%$/)&&
34
+ (b/=100);return b};this.valueOrDefault=function(b){return this.hasValue()?this.value:b};this.numValueOrDefault=function(b){return this.hasValue()?this.numValue():b};var b=this;this.Color={addOpacity:function(d){var c=b.value;if(d!=null&&d!=""){var f=new RGBColor(b.value);f.ok&&(c="rgba("+f.r+", "+f.g+", "+f.b+", "+d+")")}return new a.Property(b.name,c)}};this.Definition={getDefinition:function(){var d=b.value.replace(/^(url\()?#([^\)]+)\)?$/,"$2");return a.Definitions[d]},isUrl:function(){return b.value.indexOf("url(")==
35
+ 0},getFillStyle:function(b){var d=this.getDefinition();return d!=null&&d.createGradient?d.createGradient(a.ctx,b):d!=null&&d.createPattern?d.createPattern(a.ctx,b):null}};this.Length={DPI:function(){return 96},EM:function(b){var d=12,c=new a.Property("fontSize",a.Font.Parse(a.ctx.font).fontSize);c.hasValue()&&(d=c.Length.toPixels(b));return d},toPixels:function(d){if(!b.hasValue())return 0;var c=b.value+"";return c.match(/em$/)?b.numValue()*this.EM(d):c.match(/ex$/)?b.numValue()*this.EM(d)/2:c.match(/px$/)?
36
+ b.numValue():c.match(/pt$/)?b.numValue()*1.25:c.match(/pc$/)?b.numValue()*15:c.match(/cm$/)?b.numValue()*this.DPI(d)/2.54:c.match(/mm$/)?b.numValue()*this.DPI(d)/25.4:c.match(/in$/)?b.numValue()*this.DPI(d):c.match(/%$/)?b.numValue()*a.ViewPort.ComputeSize(d):b.numValue()}};this.Time={toMilliseconds:function(){if(!b.hasValue())return 0;var a=b.value+"";if(a.match(/s$/))return b.numValue()*1E3;a.match(/ms$/);return b.numValue()}};this.Angle={toRadians:function(){if(!b.hasValue())return 0;var a=b.value+
37
+ "";return a.match(/deg$/)?b.numValue()*(Math.PI/180):a.match(/grad$/)?b.numValue()*(Math.PI/200):a.match(/rad$/)?b.numValue():b.numValue()*(Math.PI/180)}}};a.Font=new function(){this.Styles=["normal","italic","oblique","inherit"];this.Variants=["normal","small-caps","inherit"];this.Weights="normal,bold,bolder,lighter,100,200,300,400,500,600,700,800,900,inherit".split(",");this.CreateFont=function(d,b,c,e,f,g){g=g!=null?this.Parse(g):this.CreateFont("","","","","",a.ctx.font);return{fontFamily:f||
38
+ g.fontFamily,fontSize:e||g.fontSize,fontStyle:d||g.fontStyle,fontWeight:c||g.fontWeight,fontVariant:b||g.fontVariant,toString:function(){return[this.fontStyle,this.fontVariant,this.fontWeight,this.fontSize,this.fontFamily].join(" ")}}};var c=this;this.Parse=function(d){for(var b={},d=a.trim(a.compressSpaces(d||"")).split(" "),k=!1,e=!1,f=!1,g=!1,h="",j=0;j<d.length;j++)if(!e&&c.Styles.indexOf(d[j])!=-1){if(d[j]!="inherit")b.fontStyle=d[j];e=!0}else if(!g&&c.Variants.indexOf(d[j])!=-1){if(d[j]!="inherit")b.fontVariant=
39
+ d[j];e=g=!0}else if(!f&&c.Weights.indexOf(d[j])!=-1){if(d[j]!="inherit")b.fontWeight=d[j];e=g=f=!0}else if(k)d[j]!="inherit"&&(h+=d[j]);else{if(d[j]!="inherit")b.fontSize=d[j].split("/")[0];e=g=f=k=!0}if(h!="")b.fontFamily=h;return b}};a.ToNumberArray=function(c){for(var c=a.trim(a.compressSpaces((c||"").replace(/,/g," "))).split(" "),d=0;d<c.length;d++)c[d]=parseFloat(c[d]);return c};a.Point=function(a,d){this.x=a;this.y=d;this.angleTo=function(b){return Math.atan2(b.y-this.y,b.x-this.x)};this.applyTransform=
40
+ function(b){var a=this.x*b[1]+this.y*b[3]+b[5];this.x=this.x*b[0]+this.y*b[2]+b[4];this.y=a}};a.CreatePoint=function(c){c=a.ToNumberArray(c);return new a.Point(c[0],c[1])};a.CreatePath=function(c){for(var c=a.ToNumberArray(c),d=[],b=0;b<c.length;b+=2)d.push(new a.Point(c[b],c[b+1]));return d};a.BoundingBox=function(a,d,b,k){this.y2=this.x2=this.y1=this.x1=Number.NaN;this.x=function(){return this.x1};this.y=function(){return this.y1};this.width=function(){return this.x2-this.x1};this.height=function(){return this.y2-
41
+ this.y1};this.addPoint=function(b,a){if(b!=null){if(isNaN(this.x1)||isNaN(this.x2))this.x2=this.x1=b;if(b<this.x1)this.x1=b;if(b>this.x2)this.x2=b}if(a!=null){if(isNaN(this.y1)||isNaN(this.y2))this.y2=this.y1=a;if(a<this.y1)this.y1=a;if(a>this.y2)this.y2=a}};this.addX=function(b){this.addPoint(b,null)};this.addY=function(b){this.addPoint(null,b)};this.addBoundingBox=function(b){this.addPoint(b.x1,b.y1);this.addPoint(b.x2,b.y2)};this.addQuadraticCurve=function(b,a,d,c,k,l){d=b+2/3*(d-b);c=a+2/3*(c-
42
+ a);this.addBezierCurve(b,a,d,d+1/3*(k-b),c,c+1/3*(l-a),k,l)};this.addBezierCurve=function(b,a,d,c,k,l,o,n){var q=[b,a],p=[d,c],s=[k,l],m=[o,n];this.addPoint(q[0],q[1]);this.addPoint(m[0],m[1]);for(i=0;i<=1;i++)b=function(b){return Math.pow(1-b,3)*q[i]+3*Math.pow(1-b,2)*b*p[i]+3*(1-b)*Math.pow(b,2)*s[i]+Math.pow(b,3)*m[i]},a=6*q[i]-12*p[i]+6*s[i],d=-3*q[i]+9*p[i]-9*s[i]+3*m[i],c=3*p[i]-3*q[i],d==0?a!=0&&(a=-c/a,0<a&&a<1&&(i==0&&this.addX(b(a)),i==1&&this.addY(b(a)))):(c=Math.pow(a,2)-4*c*d,c<0||(k=
43
+ (-a+Math.sqrt(c))/(2*d),0<k&&k<1&&(i==0&&this.addX(b(k)),i==1&&this.addY(b(k))),a=(-a-Math.sqrt(c))/(2*d),0<a&&a<1&&(i==0&&this.addX(b(a)),i==1&&this.addY(b(a)))))};this.isPointInBox=function(b,a){return this.x1<=b&&b<=this.x2&&this.y1<=a&&a<=this.y2};this.addPoint(a,d);this.addPoint(b,k)};a.Transform=function(c){var d=this;this.Type={};this.Type.translate=function(b){this.p=a.CreatePoint(b);this.apply=function(b){b.translate(this.p.x||0,this.p.y||0)};this.applyToPoint=function(b){b.applyTransform([1,
44
+ 0,0,1,this.p.x||0,this.p.y||0])}};this.Type.rotate=function(b){b=a.ToNumberArray(b);this.angle=new a.Property("angle",b[0]);this.cx=b[1]||0;this.cy=b[2]||0;this.apply=function(b){b.translate(this.cx,this.cy);b.rotate(this.angle.Angle.toRadians());b.translate(-this.cx,-this.cy)};this.applyToPoint=function(b){var a=this.angle.Angle.toRadians();b.applyTransform([1,0,0,1,this.p.x||0,this.p.y||0]);b.applyTransform([Math.cos(a),Math.sin(a),-Math.sin(a),Math.cos(a),0,0]);b.applyTransform([1,0,0,1,-this.p.x||
45
+ 0,-this.p.y||0])}};this.Type.scale=function(b){this.p=a.CreatePoint(b);this.apply=function(b){b.scale(this.p.x||1,this.p.y||this.p.x||1)};this.applyToPoint=function(b){b.applyTransform([this.p.x||0,0,0,this.p.y||0,0,0])}};this.Type.matrix=function(b){this.m=a.ToNumberArray(b);this.apply=function(b){b.transform(this.m[0],this.m[1],this.m[2],this.m[3],this.m[4],this.m[5])};this.applyToPoint=function(b){b.applyTransform(this.m)}};this.Type.SkewBase=function(b){this.base=d.Type.matrix;this.base(b);this.angle=
46
+ new a.Property("angle",b)};this.Type.SkewBase.prototype=new this.Type.matrix;this.Type.skewX=function(b){this.base=d.Type.SkewBase;this.base(b);this.m=[1,0,Math.tan(this.angle.Angle.toRadians()),1,0,0]};this.Type.skewX.prototype=new this.Type.SkewBase;this.Type.skewY=function(b){this.base=d.Type.SkewBase;this.base(b);this.m=[1,Math.tan(this.angle.Angle.toRadians()),0,1,0,0]};this.Type.skewY.prototype=new this.Type.SkewBase;this.transforms=[];this.apply=function(b){for(var a=0;a<this.transforms.length;a++)this.transforms[a].apply(b)};
47
+ this.applyToPoint=function(b){for(var a=0;a<this.transforms.length;a++)this.transforms[a].applyToPoint(b)};for(var c=a.trim(a.compressSpaces(c)).split(/\s(?=[a-z])/),b=0;b<c.length;b++){var k=c[b].split("(")[0],e=c[b].split("(")[1].replace(")","");this.transforms.push(new this.Type[k](e))}};a.AspectRatio=function(c,d,b,k,e,f,g,h,j,l){var d=a.compressSpaces(d),d=d.replace(/^defer\s/,""),o=d.split(" ")[0]||"xMidYMid",d=d.split(" ")[1]||"meet",n=b/k,q=e/f,p=Math.min(n,q),m=Math.max(n,q);d=="meet"&&(k*=
48
+ p,f*=p);d=="slice"&&(k*=m,f*=m);j=new a.Property("refX",j);l=new a.Property("refY",l);j.hasValue()&&l.hasValue()?c.translate(-p*j.Length.toPixels("x"),-p*l.Length.toPixels("y")):(o.match(/^xMid/)&&(d=="meet"&&p==q||d=="slice"&&m==q)&&c.translate(b/2-k/2,0),o.match(/YMid$/)&&(d=="meet"&&p==n||d=="slice"&&m==n)&&c.translate(0,e/2-f/2),o.match(/^xMax/)&&(d=="meet"&&p==q||d=="slice"&&m==q)&&c.translate(b-k,0),o.match(/YMax$/)&&(d=="meet"&&p==n||d=="slice"&&m==n)&&c.translate(0,e-f));o=="none"?c.scale(n,
49
+ q):d=="meet"?c.scale(p,p):d=="slice"&&c.scale(m,m);c.translate(g==null?0:-g,h==null?0:-h)};a.Element={};a.Element.ElementBase=function(c){this.attributes={};this.styles={};this.children=[];this.attribute=function(b,d){var c=this.attributes[b];if(c!=null)return c;c=new a.Property(b,"");d==!0&&(this.attributes[b]=c);return c};this.style=function(b,d){var c=this.styles[b];if(c!=null)return c;c=this.attribute(b);if(c!=null&&c.hasValue())return c;c=this.parent;if(c!=null&&(c=c.style(b),c!=null&&c.hasValue()))return c;
50
+ c=new a.Property(b,"");d==!0&&(this.styles[b]=c);return c};this.render=function(b){if(this.style("display").value!="none"&&this.attribute("visibility").value!="hidden"){b.save();this.setContext(b);if(this.attribute("mask").hasValue()){var a=this.attribute("mask").Definition.getDefinition();a!=null&&a.apply(b,this)}else this.style("filter").hasValue()?(a=this.style("filter").Definition.getDefinition(),a!=null&&a.apply(b,this)):this.renderChildren(b);this.clearContext(b);b.restore()}};this.setContext=
51
+ function(){};this.clearContext=function(){};this.renderChildren=function(b){for(var a=0;a<this.children.length;a++)this.children[a].render(b)};this.addChild=function(b,d){var c=b;d&&(c=a.CreateElement(b));c.parent=this;this.children.push(c)};if(c!=null&&c.nodeType==1){for(var d=0;d<c.childNodes.length;d++){var b=c.childNodes[d];b.nodeType==1&&this.addChild(b,!0)}for(d=0;d<c.attributes.length;d++)b=c.attributes[d],this.attributes[b.nodeName]=new a.Property(b.nodeName,b.nodeValue);b=a.Styles[c.nodeName];
52
+ if(b!=null)for(var k in b)this.styles[k]=b[k];if(this.attribute("class").hasValue())for(var d=a.compressSpaces(this.attribute("class").value).split(" "),e=0;e<d.length;e++){b=a.Styles["."+d[e]];if(b!=null)for(k in b)this.styles[k]=b[k];b=a.Styles[c.nodeName+"."+d[e]];if(b!=null)for(k in b)this.styles[k]=b[k]}if(this.attribute("style").hasValue()){b=this.attribute("style").value.split(";");for(d=0;d<b.length;d++)a.trim(b[d])!=""&&(c=b[d].split(":"),k=a.trim(c[0]),c=a.trim(c[1]),this.styles[k]=new a.Property(k,
53
+ c))}this.attribute("id").hasValue()&&a.Definitions[this.attribute("id").value]==null&&(a.Definitions[this.attribute("id").value]=this)}};a.Element.RenderedElementBase=function(c){this.base=a.Element.ElementBase;this.base(c);this.setContext=function(d){if(this.style("fill").Definition.isUrl()){var b=this.style("fill").Definition.getFillStyle(this);if(b!=null)d.fillStyle=b}else if(this.style("fill").hasValue())b=this.style("fill"),this.style("fill-opacity").hasValue()&&(b=b.Color.addOpacity(this.style("fill-opacity").value)),
54
+ d.fillStyle=b.value=="none"?"rgba(0,0,0,0)":b.value;if(this.style("stroke").Definition.isUrl()){if(b=this.style("stroke").Definition.getFillStyle(this),b!=null)d.strokeStyle=b}else if(this.style("stroke").hasValue())b=this.style("stroke"),this.style("stroke-opacity").hasValue()&&(b=b.Color.addOpacity(this.style("stroke-opacity").value)),d.strokeStyle=b.value=="none"?"rgba(0,0,0,0)":b.value;if(this.style("stroke-width").hasValue())d.lineWidth=this.style("stroke-width").Length.toPixels();if(this.style("stroke-linecap").hasValue())d.lineCap=
55
+ this.style("stroke-linecap").value;if(this.style("stroke-linejoin").hasValue())d.lineJoin=this.style("stroke-linejoin").value;if(this.style("stroke-miterlimit").hasValue())d.miterLimit=this.style("stroke-miterlimit").value;if(typeof d.font!="undefined")d.font=a.Font.CreateFont(this.style("font-style").value,this.style("font-variant").value,this.style("font-weight").value,this.style("font-size").hasValue()?this.style("font-size").Length.toPixels()+"px":"",this.style("font-family").value).toString();
56
+ this.attribute("transform").hasValue()&&(new a.Transform(this.attribute("transform").value)).apply(d);this.attribute("clip-path").hasValue()&&(b=this.attribute("clip-path").Definition.getDefinition(),b!=null&&b.apply(d));if(this.style("opacity").hasValue())d.globalAlpha=this.style("opacity").numValue()}};a.Element.RenderedElementBase.prototype=new a.Element.ElementBase;a.Element.PathElementBase=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.path=function(d){d!=null&&d.beginPath();
57
+ return new a.BoundingBox};this.renderChildren=function(d){this.path(d);a.Mouse.checkPath(this,d);d.fillStyle!=""&&d.fill();d.strokeStyle!=""&&d.stroke();var b=this.getMarkers();if(b!=null){if(this.style("marker-start").Definition.isUrl()){var c=this.style("marker-start").Definition.getDefinition();c.render(d,b[0][0],b[0][1])}if(this.style("marker-mid").Definition.isUrl())for(var c=this.style("marker-mid").Definition.getDefinition(),e=1;e<b.length-1;e++)c.render(d,b[e][0],b[e][1]);this.style("marker-end").Definition.isUrl()&&
58
+ (c=this.style("marker-end").Definition.getDefinition(),c.render(d,b[b.length-1][0],b[b.length-1][1]))}};this.getBoundingBox=function(){return this.path()};this.getMarkers=function(){return null}};a.Element.PathElementBase.prototype=new a.Element.RenderedElementBase;a.Element.svg=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.baseClearContext=this.clearContext;this.clearContext=function(d){this.baseClearContext(d);a.ViewPort.RemoveCurrent()};this.baseSetContext=this.setContext;
59
+ this.setContext=function(d){d.strokeStyle="rgba(0,0,0,0)";d.lineCap="butt";d.lineJoin="miter";d.miterLimit=4;this.baseSetContext(d);this.attribute("x").hasValue()&&this.attribute("y").hasValue()&&d.translate(this.attribute("x").Length.toPixels("x"),this.attribute("y").Length.toPixels("y"));var b=a.ViewPort.width(),c=a.ViewPort.height();if(typeof this.root=="undefined"&&this.attribute("width").hasValue()&&this.attribute("height").hasValue()){var b=this.attribute("width").Length.toPixels("x"),c=this.attribute("height").Length.toPixels("y"),
60
+ e=0,f=0;this.attribute("refX").hasValue()&&this.attribute("refY").hasValue()&&(e=-this.attribute("refX").Length.toPixels("x"),f=-this.attribute("refY").Length.toPixels("y"));d.beginPath();d.moveTo(e,f);d.lineTo(b,f);d.lineTo(b,c);d.lineTo(e,c);d.closePath();d.clip()}a.ViewPort.SetCurrent(b,c);if(this.attribute("viewBox").hasValue()){var e=a.ToNumberArray(this.attribute("viewBox").value),f=e[0],g=e[1],b=e[2],c=e[3];a.AspectRatio(d,this.attribute("preserveAspectRatio").value,a.ViewPort.width(),b,a.ViewPort.height(),
61
+ c,f,g,this.attribute("refX").value,this.attribute("refY").value);a.ViewPort.RemoveCurrent();a.ViewPort.SetCurrent(e[2],e[3])}}};a.Element.svg.prototype=new a.Element.RenderedElementBase;a.Element.rect=function(c){this.base=a.Element.PathElementBase;this.base(c);this.path=function(d){var b=this.attribute("x").Length.toPixels("x"),c=this.attribute("y").Length.toPixels("y"),e=this.attribute("width").Length.toPixels("x"),f=this.attribute("height").Length.toPixels("y"),g=this.attribute("rx").Length.toPixels("x"),
62
+ h=this.attribute("ry").Length.toPixels("y");this.attribute("rx").hasValue()&&!this.attribute("ry").hasValue()&&(h=g);this.attribute("ry").hasValue()&&!this.attribute("rx").hasValue()&&(g=h);d!=null&&(d.beginPath(),d.moveTo(b+g,c),d.lineTo(b+e-g,c),d.quadraticCurveTo(b+e,c,b+e,c+h),d.lineTo(b+e,c+f-h),d.quadraticCurveTo(b+e,c+f,b+e-g,c+f),d.lineTo(b+g,c+f),d.quadraticCurveTo(b,c+f,b,c+f-h),d.lineTo(b,c+h),d.quadraticCurveTo(b,c,b+g,c),d.closePath());return new a.BoundingBox(b,c,b+e,c+f)}};a.Element.rect.prototype=
63
+ new a.Element.PathElementBase;a.Element.circle=function(c){this.base=a.Element.PathElementBase;this.base(c);this.path=function(d){var b=this.attribute("cx").Length.toPixels("x"),c=this.attribute("cy").Length.toPixels("y"),e=this.attribute("r").Length.toPixels();d!=null&&(d.beginPath(),d.arc(b,c,e,0,Math.PI*2,!0),d.closePath());return new a.BoundingBox(b-e,c-e,b+e,c+e)}};a.Element.circle.prototype=new a.Element.PathElementBase;a.Element.ellipse=function(c){this.base=a.Element.PathElementBase;this.base(c);
64
+ this.path=function(d){var b=4*((Math.sqrt(2)-1)/3),c=this.attribute("rx").Length.toPixels("x"),e=this.attribute("ry").Length.toPixels("y"),f=this.attribute("cx").Length.toPixels("x"),g=this.attribute("cy").Length.toPixels("y");d!=null&&(d.beginPath(),d.moveTo(f,g-e),d.bezierCurveTo(f+b*c,g-e,f+c,g-b*e,f+c,g),d.bezierCurveTo(f+c,g+b*e,f+b*c,g+e,f,g+e),d.bezierCurveTo(f-b*c,g+e,f-c,g+b*e,f-c,g),d.bezierCurveTo(f-c,g-b*e,f-b*c,g-e,f,g-e),d.closePath());return new a.BoundingBox(f-c,g-e,f+c,g+e)}};a.Element.ellipse.prototype=
65
+ new a.Element.PathElementBase;a.Element.line=function(c){this.base=a.Element.PathElementBase;this.base(c);this.getPoints=function(){return[new a.Point(this.attribute("x1").Length.toPixels("x"),this.attribute("y1").Length.toPixels("y")),new a.Point(this.attribute("x2").Length.toPixels("x"),this.attribute("y2").Length.toPixels("y"))]};this.path=function(d){var b=this.getPoints();d!=null&&(d.beginPath(),d.moveTo(b[0].x,b[0].y),d.lineTo(b[1].x,b[1].y));return new a.BoundingBox(b[0].x,b[0].y,b[1].x,b[1].y)};
66
+ this.getMarkers=function(){var a=this.getPoints(),b=a[0].angleTo(a[1]);return[[a[0],b],[a[1],b]]}};a.Element.line.prototype=new a.Element.PathElementBase;a.Element.polyline=function(c){this.base=a.Element.PathElementBase;this.base(c);this.points=a.CreatePath(this.attribute("points").value);this.path=function(d){var b=new a.BoundingBox(this.points[0].x,this.points[0].y);d!=null&&(d.beginPath(),d.moveTo(this.points[0].x,this.points[0].y));for(var c=1;c<this.points.length;c++)b.addPoint(this.points[c].x,
67
+ this.points[c].y),d!=null&&d.lineTo(this.points[c].x,this.points[c].y);return b};this.getMarkers=function(){for(var a=[],b=0;b<this.points.length-1;b++)a.push([this.points[b],this.points[b].angleTo(this.points[b+1])]);a.push([this.points[this.points.length-1],a[a.length-1][1]]);return a}};a.Element.polyline.prototype=new a.Element.PathElementBase;a.Element.polygon=function(c){this.base=a.Element.polyline;this.base(c);this.basePath=this.path;this.path=function(a){var b=this.basePath(a);a!=null&&(a.lineTo(this.points[0].x,
68
+ this.points[0].y),a.closePath());return b}};a.Element.polygon.prototype=new a.Element.polyline;a.Element.path=function(c){this.base=a.Element.PathElementBase;this.base(c);c=this.attribute("d").value;c=c.replace(/,/gm," ");c=c.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,"$1 $2");c=c.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,"$1 $2");c=c.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm,"$1 $2");c=c.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm,"$1 $2");c=c.replace(/([0-9])([+\-])/gm,
69
+ "$1 $2");c=c.replace(/(\.[0-9]*)(\.)/gm,"$1 $2");c=c.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm,"$1 $3 $4 ");c=a.compressSpaces(c);c=a.trim(c);this.PathParser=new function(d){this.tokens=d.split(" ");this.reset=function(){this.i=-1;this.previousCommand=this.command="";this.start=new a.Point(0,0);this.control=new a.Point(0,0);this.current=new a.Point(0,0);this.points=[];this.angles=[]};this.isEnd=function(){return this.i>=this.tokens.length-1};this.isCommandOrEnd=function(){return this.isEnd()?
70
+ !0:this.tokens[this.i+1].match(/^[A-Za-z]$/)!=null};this.isRelativeCommand=function(){return this.command==this.command.toLowerCase()};this.getToken=function(){this.i+=1;return this.tokens[this.i]};this.getScalar=function(){return parseFloat(this.getToken())};this.nextCommand=function(){this.previousCommand=this.command;this.command=this.getToken()};this.getPoint=function(){return this.makeAbsolute(new a.Point(this.getScalar(),this.getScalar()))};this.getAsControlPoint=function(){var b=this.getPoint();
71
+ return this.control=b};this.getAsCurrentPoint=function(){var b=this.getPoint();return this.current=b};this.getReflectedControlPoint=function(){return this.previousCommand.toLowerCase()!="c"&&this.previousCommand.toLowerCase()!="s"?this.current:new a.Point(2*this.current.x-this.control.x,2*this.current.y-this.control.y)};this.makeAbsolute=function(b){if(this.isRelativeCommand())b.x=this.current.x+b.x,b.y=this.current.y+b.y;return b};this.addMarker=function(b,a,d){d!=null&&this.angles.length>0&&this.angles[this.angles.length-
72
+ 1]==null&&(this.angles[this.angles.length-1]=this.points[this.points.length-1].angleTo(d));this.addMarkerAngle(b,a==null?null:a.angleTo(b))};this.addMarkerAngle=function(b,a){this.points.push(b);this.angles.push(a)};this.getMarkerPoints=function(){return this.points};this.getMarkerAngles=function(){for(var b=0;b<this.angles.length;b++)if(this.angles[b]==null)for(var a=b+1;a<this.angles.length;a++)if(this.angles[a]!=null){this.angles[b]=this.angles[a];break}return this.angles}}(c);this.path=function(d){var b=
73
+ this.PathParser;b.reset();var c=new a.BoundingBox;for(d!=null&&d.beginPath();!b.isEnd();)switch(b.nextCommand(),b.command.toUpperCase()){case "M":var e=b.getAsCurrentPoint();b.addMarker(e);c.addPoint(e.x,e.y);d!=null&&d.moveTo(e.x,e.y);for(b.start=b.current;!b.isCommandOrEnd();)e=b.getAsCurrentPoint(),b.addMarker(e,b.start),c.addPoint(e.x,e.y),d!=null&&d.lineTo(e.x,e.y);break;case "L":for(;!b.isCommandOrEnd();){var f=b.current,e=b.getAsCurrentPoint();b.addMarker(e,f);c.addPoint(e.x,e.y);d!=null&&
74
+ d.lineTo(e.x,e.y)}break;case "H":for(;!b.isCommandOrEnd();)e=new a.Point((b.isRelativeCommand()?b.current.x:0)+b.getScalar(),b.current.y),b.addMarker(e,b.current),b.current=e,c.addPoint(b.current.x,b.current.y),d!=null&&d.lineTo(b.current.x,b.current.y);break;case "V":for(;!b.isCommandOrEnd();)e=new a.Point(b.current.x,(b.isRelativeCommand()?b.current.y:0)+b.getScalar()),b.addMarker(e,b.current),b.current=e,c.addPoint(b.current.x,b.current.y),d!=null&&d.lineTo(b.current.x,b.current.y);break;case "C":for(;!b.isCommandOrEnd();){var g=
75
+ b.current,f=b.getPoint(),h=b.getAsControlPoint(),e=b.getAsCurrentPoint();b.addMarker(e,h,f);c.addBezierCurve(g.x,g.y,f.x,f.y,h.x,h.y,e.x,e.y);d!=null&&d.bezierCurveTo(f.x,f.y,h.x,h.y,e.x,e.y)}break;case "S":for(;!b.isCommandOrEnd();)g=b.current,f=b.getReflectedControlPoint(),h=b.getAsControlPoint(),e=b.getAsCurrentPoint(),b.addMarker(e,h,f),c.addBezierCurve(g.x,g.y,f.x,f.y,h.x,h.y,e.x,e.y),d!=null&&d.bezierCurveTo(f.x,f.y,h.x,h.y,e.x,e.y);break;case "Q":for(;!b.isCommandOrEnd();)g=b.current,h=b.getAsControlPoint(),
76
+ e=b.getAsCurrentPoint(),b.addMarker(e,h,h),c.addQuadraticCurve(g.x,g.y,h.x,h.y,e.x,e.y),d!=null&&d.quadraticCurveTo(h.x,h.y,e.x,e.y);break;case "T":for(;!b.isCommandOrEnd();)g=b.current,h=b.getReflectedControlPoint(),b.control=h,e=b.getAsCurrentPoint(),b.addMarker(e,h,h),c.addQuadraticCurve(g.x,g.y,h.x,h.y,e.x,e.y),d!=null&&d.quadraticCurveTo(h.x,h.y,e.x,e.y);break;case "A":for(;!b.isCommandOrEnd();){var g=b.current,j=b.getScalar(),l=b.getScalar(),f=b.getScalar()*(Math.PI/180),o=b.getScalar(),h=b.getScalar(),
77
+ e=b.getAsCurrentPoint(),n=new a.Point(Math.cos(f)*(g.x-e.x)/2+Math.sin(f)*(g.y-e.y)/2,-Math.sin(f)*(g.x-e.x)/2+Math.cos(f)*(g.y-e.y)/2),q=Math.pow(n.x,2)/Math.pow(j,2)+Math.pow(n.y,2)/Math.pow(l,2);q>1&&(j*=Math.sqrt(q),l*=Math.sqrt(q));o=(o==h?-1:1)*Math.sqrt((Math.pow(j,2)*Math.pow(l,2)-Math.pow(j,2)*Math.pow(n.y,2)-Math.pow(l,2)*Math.pow(n.x,2))/(Math.pow(j,2)*Math.pow(n.y,2)+Math.pow(l,2)*Math.pow(n.x,2)));isNaN(o)&&(o=0);var p=new a.Point(o*j*n.y/l,o*-l*n.x/j),g=new a.Point((g.x+e.x)/2+Math.cos(f)*
78
+ p.x-Math.sin(f)*p.y,(g.y+e.y)/2+Math.sin(f)*p.x+Math.cos(f)*p.y),m=function(b,a){return(b[0]*a[0]+b[1]*a[1])/(Math.sqrt(Math.pow(b[0],2)+Math.pow(b[1],2))*Math.sqrt(Math.pow(a[0],2)+Math.pow(a[1],2)))},t=function(b,a){return(b[0]*a[1]<b[1]*a[0]?-1:1)*Math.acos(m(b,a))},o=t([1,0],[(n.x-p.x)/j,(n.y-p.y)/l]),q=[(n.x-p.x)/j,(n.y-p.y)/l],p=[(-n.x-p.x)/j,(-n.y-p.y)/l],n=t(q,p);if(m(q,p)<=-1)n=Math.PI;m(q,p)>=1&&(n=0);h==0&&n>0&&(n-=2*Math.PI);h==1&&n<0&&(n+=2*Math.PI);q=new a.Point(g.x-j*Math.cos((o+n)/
79
+ 2),g.y-l*Math.sin((o+n)/2));b.addMarkerAngle(q,(o+n)/2+(h==0?1:-1)*Math.PI/2);b.addMarkerAngle(e,n+(h==0?1:-1)*Math.PI/2);c.addPoint(e.x,e.y);d!=null&&(m=j>l?j:l,e=j>l?1:j/l,j=j>l?l/j:1,d.translate(g.x,g.y),d.rotate(f),d.scale(e,j),d.arc(0,0,m,o,o+n,1-h),d.scale(1/e,1/j),d.rotate(-f),d.translate(-g.x,-g.y))}break;case "Z":d!=null&&d.closePath(),b.current=b.start}return c};this.getMarkers=function(){for(var a=this.PathParser.getMarkerPoints(),b=this.PathParser.getMarkerAngles(),c=[],e=0;e<a.length;e++)c.push([a[e],
80
+ b[e]]);return c}};a.Element.path.prototype=new a.Element.PathElementBase;a.Element.pattern=function(c){this.base=a.Element.ElementBase;this.base(c);this.createPattern=function(d){var b=new a.Element.svg;b.attributes.viewBox=new a.Property("viewBox",this.attribute("viewBox").value);b.attributes.x=new a.Property("x",this.attribute("x").value);b.attributes.y=new a.Property("y",this.attribute("y").value);b.attributes.width=new a.Property("width",this.attribute("width").value);b.attributes.height=new a.Property("height",
81
+ this.attribute("height").value);b.children=this.children;var c=document.createElement("canvas");c.width=this.attribute("width").Length.toPixels("x");c.height=this.attribute("height").Length.toPixels("y");b.render(c.getContext("2d"));return d.createPattern(c,"repeat")}};a.Element.pattern.prototype=new a.Element.ElementBase;a.Element.marker=function(c){this.base=a.Element.ElementBase;this.base(c);this.baseRender=this.render;this.render=function(d,b,c){d.translate(b.x,b.y);this.attribute("orient").valueOrDefault("auto")==
82
+ "auto"&&d.rotate(c);this.attribute("markerUnits").valueOrDefault("strokeWidth")=="strokeWidth"&&d.scale(d.lineWidth,d.lineWidth);d.save();var e=new a.Element.svg;e.attributes.viewBox=new a.Property("viewBox",this.attribute("viewBox").value);e.attributes.refX=new a.Property("refX",this.attribute("refX").value);e.attributes.refY=new a.Property("refY",this.attribute("refY").value);e.attributes.width=new a.Property("width",this.attribute("markerWidth").value);e.attributes.height=new a.Property("height",
83
+ this.attribute("markerHeight").value);e.attributes.fill=new a.Property("fill",this.attribute("fill").valueOrDefault("black"));e.attributes.stroke=new a.Property("stroke",this.attribute("stroke").valueOrDefault("none"));e.children=this.children;e.render(d);d.restore();this.attribute("markerUnits").valueOrDefault("strokeWidth")=="strokeWidth"&&d.scale(1/d.lineWidth,1/d.lineWidth);this.attribute("orient").valueOrDefault("auto")=="auto"&&d.rotate(-c);d.translate(-b.x,-b.y)}};a.Element.marker.prototype=
84
+ new a.Element.ElementBase;a.Element.defs=function(c){this.base=a.Element.ElementBase;this.base(c);this.render=function(){}};a.Element.defs.prototype=new a.Element.ElementBase;a.Element.GradientBase=function(c){this.base=a.Element.ElementBase;this.base(c);this.gradientUnits=this.attribute("gradientUnits").valueOrDefault("objectBoundingBox");this.stops=[];for(c=0;c<this.children.length;c++)this.stops.push(this.children[c]);this.getGradient=function(){};this.createGradient=function(d,b){var c=this;this.attribute("xlink:href").hasValue()&&
85
+ (c=this.attribute("xlink:href").Definition.getDefinition());for(var e=this.getGradient(d,b),f=0;f<c.stops.length;f++)e.addColorStop(c.stops[f].offset,c.stops[f].color);if(this.attribute("gradientTransform").hasValue()){c=a.ViewPort.viewPorts[0];f=new a.Element.rect;f.attributes.x=new a.Property("x",-a.MAX_VIRTUAL_PIXELS/3);f.attributes.y=new a.Property("y",-a.MAX_VIRTUAL_PIXELS/3);f.attributes.width=new a.Property("width",a.MAX_VIRTUAL_PIXELS);f.attributes.height=new a.Property("height",a.MAX_VIRTUAL_PIXELS);
86
+ var g=new a.Element.g;g.attributes.transform=new a.Property("transform",this.attribute("gradientTransform").value);g.children=[f];f=new a.Element.svg;f.attributes.x=new a.Property("x",0);f.attributes.y=new a.Property("y",0);f.attributes.width=new a.Property("width",c.width);f.attributes.height=new a.Property("height",c.height);f.children=[g];g=document.createElement("canvas");g.width=c.width;g.height=c.height;c=g.getContext("2d");c.fillStyle=e;f.render(c);return c.createPattern(g,"no-repeat")}return e}};
87
+ a.Element.GradientBase.prototype=new a.Element.ElementBase;a.Element.linearGradient=function(c){this.base=a.Element.GradientBase;this.base(c);this.getGradient=function(a,b){var c=b.getBoundingBox(),e=this.gradientUnits=="objectBoundingBox"?c.x()+c.width()*this.attribute("x1").numValue():this.attribute("x1").Length.toPixels("x"),f=this.gradientUnits=="objectBoundingBox"?c.y()+c.height()*this.attribute("y1").numValue():this.attribute("y1").Length.toPixels("y"),g=this.gradientUnits=="objectBoundingBox"?
88
+ c.x()+c.width()*this.attribute("x2").numValue():this.attribute("x2").Length.toPixels("x"),c=this.gradientUnits=="objectBoundingBox"?c.y()+c.height()*this.attribute("y2").numValue():this.attribute("y2").Length.toPixels("y");return a.createLinearGradient(e,f,g,c)}};a.Element.linearGradient.prototype=new a.Element.GradientBase;a.Element.radialGradient=function(c){this.base=a.Element.GradientBase;this.base(c);this.getGradient=function(a,b){var c=b.getBoundingBox(),e=this.gradientUnits=="objectBoundingBox"?
89
+ c.x()+c.width()*this.attribute("cx").numValue():this.attribute("cx").Length.toPixels("x"),f=this.gradientUnits=="objectBoundingBox"?c.y()+c.height()*this.attribute("cy").numValue():this.attribute("cy").Length.toPixels("y"),g=e,h=f;this.attribute("fx").hasValue()&&(g=this.gradientUnits=="objectBoundingBox"?c.x()+c.width()*this.attribute("fx").numValue():this.attribute("fx").Length.toPixels("x"));this.attribute("fy").hasValue()&&(h=this.gradientUnits=="objectBoundingBox"?c.y()+c.height()*this.attribute("fy").numValue():
90
+ this.attribute("fy").Length.toPixels("y"));c=this.gradientUnits=="objectBoundingBox"?(c.width()+c.height())/2*this.attribute("r").numValue():this.attribute("r").Length.toPixels();return a.createRadialGradient(g,h,0,e,f,c)}};a.Element.radialGradient.prototype=new a.Element.GradientBase;a.Element.stop=function(c){this.base=a.Element.ElementBase;this.base(c);this.offset=this.attribute("offset").numValue();c=this.style("stop-color");this.style("stop-opacity").hasValue()&&(c=c.Color.addOpacity(this.style("stop-opacity").value));
91
+ this.color=c.value};a.Element.stop.prototype=new a.Element.ElementBase;a.Element.AnimateBase=function(c){this.base=a.Element.ElementBase;this.base(c);a.Animations.push(this);this.duration=0;this.begin=this.attribute("begin").Time.toMilliseconds();this.maxDuration=this.begin+this.attribute("dur").Time.toMilliseconds();this.getProperty=function(){var a=this.attribute("attributeType").value,b=this.attribute("attributeName").value;return a=="CSS"?this.parent.style(b,!0):this.parent.attribute(b,!0)};this.initialValue=
92
+ null;this.removed=!1;this.calcValue=function(){return""};this.update=function(a){if(this.initialValue==null)this.initialValue=this.getProperty().value;if(this.duration>this.maxDuration)if(this.attribute("repeatCount").value=="indefinite")this.duration=0;else return this.attribute("fill").valueOrDefault("remove")=="remove"&&!this.removed?(this.removed=!0,this.getProperty().value=this.initialValue,!0):!1;this.duration+=a;a=!1;if(this.begin<this.duration)a=this.calcValue(),this.attribute("type").hasValue()&&
93
+ (a=this.attribute("type").value+"("+a+")"),this.getProperty().value=a,a=!0;return a};this.progress=function(){return(this.duration-this.begin)/(this.maxDuration-this.begin)}};a.Element.AnimateBase.prototype=new a.Element.ElementBase;a.Element.animate=function(c){this.base=a.Element.AnimateBase;this.base(c);this.calcValue=function(){var a=this.attribute("from").numValue(),b=this.attribute("to").numValue();return a+(b-a)*this.progress()}};a.Element.animate.prototype=new a.Element.AnimateBase;a.Element.animateColor=
94
+ function(c){this.base=a.Element.AnimateBase;this.base(c);this.calcValue=function(){var a=new RGBColor(this.attribute("from").value),b=new RGBColor(this.attribute("to").value);if(a.ok&&b.ok){var c=a.r+(b.r-a.r)*this.progress(),e=a.g+(b.g-a.g)*this.progress(),a=a.b+(b.b-a.b)*this.progress();return"rgb("+parseInt(c,10)+","+parseInt(e,10)+","+parseInt(a,10)+")"}return this.attribute("from").value}};a.Element.animateColor.prototype=new a.Element.AnimateBase;a.Element.animateTransform=function(c){this.base=
95
+ a.Element.animate;this.base(c)};a.Element.animateTransform.prototype=new a.Element.animate;a.Element.font=function(c){this.base=a.Element.ElementBase;this.base(c);this.horizAdvX=this.attribute("horiz-adv-x").numValue();this.isArabic=this.isRTL=!1;this.missingGlyph=this.fontFace=null;this.glyphs=[];for(c=0;c<this.children.length;c++){var d=this.children[c];if(d.type=="font-face")this.fontFace=d,d.style("font-family").hasValue()&&(a.Definitions[d.style("font-family").value]=this);else if(d.type=="missing-glyph")this.missingGlyph=
96
+ d;else if(d.type=="glyph")d.arabicForm!=""?(this.isArabic=this.isRTL=!0,typeof this.glyphs[d.unicode]=="undefined"&&(this.glyphs[d.unicode]=[]),this.glyphs[d.unicode][d.arabicForm]=d):this.glyphs[d.unicode]=d}};a.Element.font.prototype=new a.Element.ElementBase;a.Element.fontface=function(c){this.base=a.Element.ElementBase;this.base(c);this.ascent=this.attribute("ascent").value;this.descent=this.attribute("descent").value;this.unitsPerEm=this.attribute("units-per-em").numValue()};a.Element.fontface.prototype=
97
+ new a.Element.ElementBase;a.Element.missingglyph=function(c){this.base=a.Element.path;this.base(c);this.horizAdvX=0};a.Element.missingglyph.prototype=new a.Element.path;a.Element.glyph=function(c){this.base=a.Element.path;this.base(c);this.horizAdvX=this.attribute("horiz-adv-x").numValue();this.unicode=this.attribute("unicode").value;this.arabicForm=this.attribute("arabic-form").value};a.Element.glyph.prototype=new a.Element.path;a.Element.text=function(c){this.base=a.Element.RenderedElementBase;
98
+ this.base(c);if(c!=null){this.children=[];for(var d=0;d<c.childNodes.length;d++){var b=c.childNodes[d];b.nodeType==1?this.addChild(b,!0):b.nodeType==3&&this.addChild(new a.Element.tspan(b),!1)}}this.baseSetContext=this.setContext;this.setContext=function(b){this.baseSetContext(b);if(this.style("dominant-baseline").hasValue())b.textBaseline=this.style("dominant-baseline").value;if(this.style("alignment-baseline").hasValue())b.textBaseline=this.style("alignment-baseline").value};this.renderChildren=
99
+ function(b){for(var a=this.style("text-anchor").valueOrDefault("start"),c=this.attribute("x").Length.toPixels("x"),d=this.attribute("y").Length.toPixels("y"),h=0;h<this.children.length;h++){var j=this.children[h];j.attribute("x").hasValue()?j.x=j.attribute("x").Length.toPixels("x"):(j.attribute("dx").hasValue()&&(c+=j.attribute("dx").Length.toPixels("x")),j.x=c);c=j.measureText(b);if(a!="start"&&(h==0||j.attribute("x").hasValue())){for(var l=c,o=h+1;o<this.children.length;o++){var n=this.children[o];
100
+ if(n.attribute("x").hasValue())break;l+=n.measureText(b)}j.x-=a=="end"?l:l/2}c=j.x+c;j.attribute("y").hasValue()?j.y=j.attribute("y").Length.toPixels("y"):(j.attribute("dy").hasValue()&&(d+=j.attribute("dy").Length.toPixels("y")),j.y=d);d=j.y;j.render(b)}}};a.Element.text.prototype=new a.Element.RenderedElementBase;a.Element.TextElementBase=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.getGlyph=function(a,b,c){var e=b[c],f=null;if(a.isArabic){var g="isolated";if((c==0||b[c-
101
+ 1]==" ")&&c<b.length-2&&b[c+1]!=" ")g="terminal";c>0&&b[c-1]!=" "&&c<b.length-2&&b[c+1]!=" "&&(g="medial");if(c>0&&b[c-1]!=" "&&(c==b.length-1||b[c+1]==" "))g="initial";typeof a.glyphs[e]!="undefined"&&(f=a.glyphs[e][g],f==null&&a.glyphs[e].type=="glyph"&&(f=a.glyphs[e]))}else f=a.glyphs[e];if(f==null)f=a.missingGlyph;return f};this.renderChildren=function(c){var b=this.parent.style("font-family").Definition.getDefinition();if(b!=null){var k=this.parent.style("font-size").numValueOrDefault(a.Font.Parse(a.ctx.font).fontSize),
102
+ e=this.parent.style("font-style").valueOrDefault(a.Font.Parse(a.ctx.font).fontStyle),f=this.getText();b.isRTL&&(f=f.split("").reverse().join(""));for(var g=a.ToNumberArray(this.parent.attribute("dx").value),h=0;h<f.length;h++){var j=this.getGlyph(b,f,h),l=k/b.fontFace.unitsPerEm;c.translate(this.x,this.y);c.scale(l,-l);var o=c.lineWidth;c.lineWidth=c.lineWidth*b.fontFace.unitsPerEm/k;e=="italic"&&c.transform(1,0,0.4,1,0,0);j.render(c);e=="italic"&&c.transform(1,0,-0.4,1,0,0);c.lineWidth=o;c.scale(1/
103
+ l,-1/l);c.translate(-this.x,-this.y);this.x+=k*(j.horizAdvX||b.horizAdvX)/b.fontFace.unitsPerEm;typeof g[h]!="undefined"&&!isNaN(g[h])&&(this.x+=g[h])}}else c.strokeStyle!=""&&c.strokeText(a.compressSpaces(this.getText()),this.x,this.y),c.fillStyle!=""&&c.fillText(a.compressSpaces(this.getText()),this.x,this.y)};this.getText=function(){};this.measureText=function(c){var b=this.parent.style("font-family").Definition.getDefinition();if(b!=null){var c=this.parent.style("font-size").numValueOrDefault(a.Font.Parse(a.ctx.font).fontSize),
104
+ k=0,e=this.getText();b.isRTL&&(e=e.split("").reverse().join(""));for(var f=a.ToNumberArray(this.parent.attribute("dx").value),g=0;g<e.length;g++){var h=this.getGlyph(b,e,g);k+=(h.horizAdvX||b.horizAdvX)*c/b.fontFace.unitsPerEm;typeof f[g]!="undefined"&&!isNaN(f[g])&&(k+=f[g])}return k}b=a.compressSpaces(this.getText());if(!c.measureText)return b.length*10;c.save();this.setContext(c);b=c.measureText(b).width;c.restore();return b}};a.Element.TextElementBase.prototype=new a.Element.RenderedElementBase;
105
+ a.Element.tspan=function(c){this.base=a.Element.TextElementBase;this.base(c);this.text=c.nodeType==3?c.nodeValue:c.childNodes.length>0?c.childNodes[0].nodeValue:c.text;this.getText=function(){return this.text}};a.Element.tspan.prototype=new a.Element.TextElementBase;a.Element.tref=function(c){this.base=a.Element.TextElementBase;this.base(c);this.getText=function(){var a=this.attribute("xlink:href").Definition.getDefinition();if(a!=null)return a.children[0].getText()}};a.Element.tref.prototype=new a.Element.TextElementBase;
106
+ a.Element.a=function(c){this.base=a.Element.TextElementBase;this.base(c);this.hasText=!0;for(var d=0;d<c.childNodes.length;d++)if(c.childNodes[d].nodeType!=3)this.hasText=!1;this.text=this.hasText?c.childNodes[0].nodeValue:"";this.getText=function(){return this.text};this.baseRenderChildren=this.renderChildren;this.renderChildren=function(b){if(this.hasText){this.baseRenderChildren(b);var c=new a.Property("fontSize",a.Font.Parse(a.ctx.font).fontSize);a.Mouse.checkBoundingBox(this,new a.BoundingBox(this.x,
107
+ this.y-c.Length.toPixels("y"),this.x+this.measureText(b),this.y))}else c=new a.Element.g,c.children=this.children,c.parent=this,c.render(b)};this.onclick=function(){window.open(this.attribute("xlink:href").value)};this.onmousemove=function(){a.ctx.canvas.style.cursor="pointer"}};a.Element.a.prototype=new a.Element.TextElementBase;a.Element.image=function(c){this.base=a.Element.RenderedElementBase;this.base(c);a.Images.push(this);this.img=document.createElement("img");this.loaded=!1;var d=this;this.img.onload=
108
+ function(){d.loaded=!0};this.img.src=this.attribute("xlink:href").value;this.renderChildren=function(b){var c=this.attribute("x").Length.toPixels("x"),d=this.attribute("y").Length.toPixels("y"),f=this.attribute("width").Length.toPixels("x"),g=this.attribute("height").Length.toPixels("y");f==0||g==0||(b.save(),b.translate(c,d),a.AspectRatio(b,this.attribute("preserveAspectRatio").value,f,this.img.width,g,this.img.height,0,0),b.drawImage(this.img,0,0),b.restore())}};a.Element.image.prototype=new a.Element.RenderedElementBase;
109
+ a.Element.g=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.getBoundingBox=function(){for(var c=new a.BoundingBox,b=0;b<this.children.length;b++)c.addBoundingBox(this.children[b].getBoundingBox());return c}};a.Element.g.prototype=new a.Element.RenderedElementBase;a.Element.symbol=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.baseSetContext=this.setContext;this.setContext=function(c){this.baseSetContext(c);if(this.attribute("viewBox").hasValue()){var b=
110
+ a.ToNumberArray(this.attribute("viewBox").value),k=b[0],e=b[1];width=b[2];height=b[3];a.AspectRatio(c,this.attribute("preserveAspectRatio").value,this.attribute("width").Length.toPixels("x"),width,this.attribute("height").Length.toPixels("y"),height,k,e);a.ViewPort.SetCurrent(b[2],b[3])}}};a.Element.symbol.prototype=new a.Element.RenderedElementBase;a.Element.style=function(c){this.base=a.Element.ElementBase;this.base(c);for(var c=c.childNodes[0].nodeValue+(c.childNodes.length>1?c.childNodes[1].nodeValue:
111
+ ""),c=c.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm,""),c=a.compressSpaces(c),c=c.split("}"),d=0;d<c.length;d++)if(a.trim(c[d])!="")for(var b=c[d].split("{"),k=b[0].split(","),b=b[1].split(";"),e=0;e<k.length;e++){var f=a.trim(k[e]);if(f!=""){for(var g={},h=0;h<b.length;h++){var j=b[h].indexOf(":"),l=b[h].substr(0,j),j=b[h].substr(j+1,b[h].length-j);l!=null&&j!=null&&(g[a.trim(l)]=new a.Property(a.trim(l),a.trim(j)))}a.Styles[f]=g;if(f=="@font-face"){f=g["font-family"].value.replace(/"/g,
112
+ "");g=g.src.value.split(",");for(h=0;h<g.length;h++)if(g[h].indexOf('format("svg")')>0){l=g[h].indexOf("url");j=g[h].indexOf(")",l);l=g[h].substr(l+5,j-l-6);l=a.parseXml(a.ajax(l)).getElementsByTagName("font");for(j=0;j<l.length;j++){var o=a.CreateElement(l[j]);a.Definitions[f]=o}}}}}};a.Element.style.prototype=new a.Element.ElementBase;a.Element.use=function(c){this.base=a.Element.RenderedElementBase;this.base(c);this.baseSetContext=this.setContext;this.setContext=function(a){this.baseSetContext(a);
113
+ this.attribute("x").hasValue()&&a.translate(this.attribute("x").Length.toPixels("x"),0);this.attribute("y").hasValue()&&a.translate(0,this.attribute("y").Length.toPixels("y"))};this.getDefinition=function(){var a=this.attribute("xlink:href").Definition.getDefinition();if(this.attribute("width").hasValue())a.attribute("width",!0).value=this.attribute("width").value;if(this.attribute("height").hasValue())a.attribute("height",!0).value=this.attribute("height").value;return a};this.path=function(a){var b=
114
+ this.getDefinition();b!=null&&b.path(a)};this.renderChildren=function(a){var b=this.getDefinition();b!=null&&b.render(a)}};a.Element.use.prototype=new a.Element.RenderedElementBase;a.Element.mask=function(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(a,b){var c=this.attribute("x").Length.toPixels("x"),e=this.attribute("y").Length.toPixels("y"),f=this.attribute("width").Length.toPixels("x"),g=this.attribute("height").Length.toPixels("y"),h=b.attribute("mask").value;b.attribute("mask").value=
115
+ "";var j=document.createElement("canvas");j.width=c+f;j.height=e+g;var l=j.getContext("2d");this.renderChildren(l);var o=document.createElement("canvas");o.width=c+f;o.height=e+g;var n=o.getContext("2d");b.render(n);n.globalCompositeOperation="destination-in";n.fillStyle=l.createPattern(j,"no-repeat");n.fillRect(0,0,c+f,e+g);a.fillStyle=n.createPattern(o,"no-repeat");a.fillRect(0,0,c+f,e+g);b.attribute("mask").value=h};this.render=function(){}};a.Element.mask.prototype=new a.Element.ElementBase;a.Element.clipPath=
116
+ function(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(a){for(var b=0;b<this.children.length;b++)this.children[b].path&&(this.children[b].path(a),a.clip())};this.render=function(){}};a.Element.clipPath.prototype=new a.Element.ElementBase;a.Element.filter=function(c){this.base=a.Element.ElementBase;this.base(c);this.apply=function(a,b){var c=b.getBoundingBox(),e=this.attribute("x").Length.toPixels("x"),f=this.attribute("y").Length.toPixels("y");if(e==0||f==0)e=c.x1,f=c.y1;var g=
117
+ this.attribute("width").Length.toPixels("x"),h=this.attribute("height").Length.toPixels("y");if(g==0||h==0)g=c.width(),h=c.height();c=b.style("filter").value;b.style("filter").value="";var j=0.2*g,l=0.2*h,o=document.createElement("canvas");o.width=g+2*j;o.height=h+2*l;var n=o.getContext("2d");n.translate(-e+j,-f+l);b.render(n);for(var q=0;q<this.children.length;q++)this.children[q].apply(n,0,0,g+2*j,h+2*l);a.drawImage(o,0,0,g+2*j,h+2*l,e-j,f-l,g+2*j,h+2*l);b.style("filter",!0).value=c};this.render=
118
+ function(){}};a.Element.filter.prototype=new a.Element.ElementBase;a.Element.feGaussianBlur=function(c){function d(a,c,d,f,g){for(var h=0;h<g;h++)for(var j=0;j<f;j++)for(var l=a[h*f*4+j*4+3]/255,o=0;o<4;o++){for(var n=d[0]*(l==0?255:a[h*f*4+j*4+o])*(l==0||o==3?1:l),q=1;q<d.length;q++){var p=Math.max(j-q,0),m=a[h*f*4+p*4+3]/255,p=Math.min(j+q,f-1),p=a[h*f*4+p*4+3]/255,t=d[q],r;m==0?r=255:(r=Math.max(j-q,0),r=a[h*f*4+r*4+o]);m=r*(m==0||o==3?1:m);p==0?r=255:(r=Math.min(j+q,f-1),r=a[h*f*4+r*4+o]);n+=
119
+ t*(m+r*(p==0||o==3?1:p))}c[j*g*4+h*4+o]=n}}this.base=a.Element.ElementBase;this.base(c);this.apply=function(a,c,e,f,g){var e=this.attribute("stdDeviation").numValue(),c=a.getImageData(0,0,f,g),e=Math.max(e,0.01),h=Math.ceil(e*4)+1;mask=[];for(var j=0;j<h;j++)mask[j]=Math.exp(-0.5*(j/e)*(j/e));e=mask;h=0;for(j=1;j<e.length;j++)h+=Math.abs(e[j]);h=2*h+Math.abs(e[0]);for(j=0;j<e.length;j++)e[j]/=h;tmp=[];d(c.data,tmp,e,f,g);d(tmp,c.data,e,g,f);a.clearRect(0,0,f,g);a.putImageData(c,0,0)}};a.Element.filter.prototype=
120
+ new a.Element.feGaussianBlur;a.Element.title=function(){};a.Element.title.prototype=new a.Element.ElementBase;a.Element.desc=function(){};a.Element.desc.prototype=new a.Element.ElementBase;a.Element.MISSING=function(a){console.log("ERROR: Element '"+a.nodeName+"' not yet implemented.")};a.Element.MISSING.prototype=new a.Element.ElementBase;a.CreateElement=function(c){var d=c.nodeName.replace(/^[^:]+:/,""),d=d.replace(/\-/g,""),b=null,b=typeof a.Element[d]!="undefined"?new a.Element[d](c):new a.Element.MISSING(c);
121
+ b.type=c.nodeName;return b};a.load=function(c,d){a.loadXml(c,a.ajax(d))};a.loadXml=function(c,d){a.loadXmlDoc(c,a.parseXml(d))};a.loadXmlDoc=function(c,d){a.init(c);var b=function(a){for(var b=c.canvas;b;)a.x-=b.offsetLeft,a.y-=b.offsetTop,b=b.offsetParent;window.scrollX&&(a.x+=window.scrollX);window.scrollY&&(a.y+=window.scrollY);return a};if(a.opts.ignoreMouse!=!0)c.canvas.onclick=function(c){c=b(new a.Point(c!=null?c.clientX:event.clientX,c!=null?c.clientY:event.clientY));a.Mouse.onclick(c.x,c.y)},
122
+ c.canvas.onmousemove=function(c){c=b(new a.Point(c!=null?c.clientX:event.clientX,c!=null?c.clientY:event.clientY));a.Mouse.onmousemove(c.x,c.y)};var k=a.CreateElement(d.documentElement),e=k.root=!0,f=function(){a.ViewPort.Clear();c.canvas.parentNode&&a.ViewPort.SetCurrent(c.canvas.parentNode.clientWidth,c.canvas.parentNode.clientHeight);if(a.opts.ignoreDimensions!=!0){if(k.style("width").hasValue())c.canvas.width=k.style("width").Length.toPixels("x"),c.canvas.style.width=c.canvas.width+"px";if(k.style("height").hasValue())c.canvas.height=
123
+ k.style("height").Length.toPixels("y"),c.canvas.style.height=c.canvas.height+"px"}var b=c.canvas.clientWidth||c.canvas.width,d=c.canvas.clientHeight||c.canvas.height;a.ViewPort.SetCurrent(b,d);if(a.opts!=null&&a.opts.offsetX!=null)k.attribute("x",!0).value=a.opts.offsetX;if(a.opts!=null&&a.opts.offsetY!=null)k.attribute("y",!0).value=a.opts.offsetY;if(a.opts!=null&&a.opts.scaleWidth!=null&&a.opts.scaleHeight!=null){var f=1,g=1;k.attribute("width").hasValue()&&(f=k.attribute("width").Length.toPixels("x")/
124
+ a.opts.scaleWidth);k.attribute("height").hasValue()&&(g=k.attribute("height").Length.toPixels("y")/a.opts.scaleHeight);k.attribute("width",!0).value=a.opts.scaleWidth;k.attribute("height",!0).value=a.opts.scaleHeight;k.attribute("viewBox",!0).value="0 0 "+b*f+" "+d*g;k.attribute("preserveAspectRatio",!0).value="none"}a.opts.ignoreClear!=!0&&c.clearRect(0,0,b,d);k.render(c);e&&(e=!1,a.opts!=null&&typeof a.opts.renderCallback=="function"&&a.opts.renderCallback())},g=!0;a.ImagesLoaded()&&(g=!1,f());
125
+ a.intervalID=setInterval(function(){var b=!1;g&&a.ImagesLoaded()&&(g=!1,b=!0);a.opts.ignoreMouse!=!0&&(b|=a.Mouse.hasEvents());if(a.opts.ignoreAnimation!=!0)for(var c=0;c<a.Animations.length;c++)b|=a.Animations[c].update(1E3/a.FRAMERATE);a.opts!=null&&typeof a.opts.forceRedraw=="function"&&a.opts.forceRedraw()==!0&&(b=!0);b&&(f(),a.Mouse.runEvents())},1E3/a.FRAMERATE)};a.stop=function(){a.intervalID&&clearInterval(a.intervalID)};a.Mouse=new function(){this.events=[];this.hasEvents=function(){return this.events.length!=
126
+ 0};this.onclick=function(a,d){this.events.push({type:"onclick",x:a,y:d,run:function(a){if(a.onclick)a.onclick()}})};this.onmousemove=function(a,d){this.events.push({type:"onmousemove",x:a,y:d,run:function(a){if(a.onmousemove)a.onmousemove()}})};this.eventElements=[];this.checkPath=function(a,d){for(var b=0;b<this.events.length;b++){var k=this.events[b];d.isPointInPath&&d.isPointInPath(k.x,k.y)&&(this.eventElements[b]=a)}};this.checkBoundingBox=function(a,d){for(var b=0;b<this.events.length;b++){var k=
127
+ this.events[b];d.isPointInBox(k.x,k.y)&&(this.eventElements[b]=a)}};this.runEvents=function(){a.ctx.canvas.style.cursor="";for(var c=0;c<this.events.length;c++)for(var d=this.events[c],b=this.eventElements[c];b;)d.run(b),b=b.parent;this.events=[];this.eventElements=[]}};return a}this.canvg=function(a,c,d){if(a==null&&c==null&&d==null)for(var c=document.getElementsByTagName("svg"),b=0;b<c.length;b++){a=c[b];d=document.createElement("canvas");d.width=a.clientWidth;d.height=a.clientHeight;a.parentNode.insertBefore(d,
128
+ a);a.parentNode.removeChild(a);var k=document.createElement("div");k.appendChild(a);canvg(d,k.innerHTML)}else d=d||{},typeof a=="string"&&(a=document.getElementById(a)),a.svg==null?(b=m(),a.svg=b):(b=a.svg,b.stop()),b.opts=d,a=a.getContext("2d"),typeof c.documentElement!="undefined"?b.loadXmlDoc(a,c):c.substr(0,1)=="<"?b.loadXml(a,c):b.load(a,c)}})();
129
+ if(CanvasRenderingContext2D)CanvasRenderingContext2D.prototype.drawSvg=function(m,a,c,d,b){canvg(this.canvas,m,{ignoreMouse:!0,ignoreAnimation:!0,ignoreDimensions:!0,ignoreClear:!0,offsetX:a,offsetY:c,scaleWidth:d,scaleHeight:b})};
130
+ (function(m){var a=m.css,c=m.CanVGRenderer,d=m.SVGRenderer,b=m.extend,k=m.merge,e=m.addEvent,f=m.placeBox,g=m.createElement,h=m.discardElement;b(c.prototype,d.prototype);b(c.prototype,{create:function(a,b,c,d){this.setContainer(b,c,d);this.configure(a)},setContainer:function(a,b,c){var d=a.style,e=a.parentNode,f=d.left,d=d.top,h=a.offsetWidth,k=a.offsetHeight,m={visibility:"hidden",position:"absolute"};this.init.apply(this,[a,b,c]);this.canvas=g("canvas",{width:h,height:k},{position:"relative",left:f,
131
+ top:d},a);this.ttLine=g("div",null,m,e);this.ttDiv=g("div",null,m,e);this.ttTimer=void 0;this.hiddenSvg=a=g("div",{width:h,height:k},{visibility:"hidden",left:f,top:d},e);a.appendChild(this.box)},configure:function(b){var c=this,d=b.options.tooltip,g=d.borderWidth,h=c.ttDiv,m=d.style,s=c.ttLine,t=parseInt(m.padding,10),m=k(m,{padding:t+"px","background-color":d.backgroundColor,"border-style":"solid","border-width":g+"px","border-radius":d.borderRadius+"px"});d.shadow&&(m=k(m,{"box-shadow":"1px 1px 3px gray",
132
+ "-webkit-box-shadow":"1px 1px 3px gray"}));a(h,m);a(s,{"border-left":"1px solid darkgray"});e(b,"tooltipRefresh",function(d){var e=b.container,g=e.offsetLeft,k=e.offsetTop;h.innerHTML=d.text;e=f(h.offsetWidth,h.offsetHeight,g,k,e.offsetWidth,e.offsetHeight,{x:d.x,y:d.y},12);a(h,{visibility:"visible",left:e.x+"px",top:e.y+"px","border-color":d.borderColor});a(s,{visibility:"visible",left:g+d.x+"px",top:k+b.plotTop+"px",height:b.plotHeight+"px"});c.ttTimer!==void 0&&clearTimeout(c.ttTimer);c.ttTimer=
133
+ setTimeout(function(){a(h,{visibility:"hidden"});a(s,{visibility:"hidden"})},3E3)})},destroy:function(){h(this.canvas);this.ttTimer!==void 0&&clearTimeout(this.ttTimer);h(this.ttLine);h(this.ttDiv);h(this.hiddenSvg);return d.prototype.destroy.apply(this)},color:function(a,b,c){a&&a.linearGradient&&(a=a.stops[a.stops.length-1][1]);return d.prototype.color.call(this,a,b,c)},draw:function(){window.canvg(this.canvas,this.hiddenSvg.innerHTML)}})})(Highcharts);
js/modules/exporting.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Highcharts JS v2.2.1 (2012-03-15)
3
+ Exporting module
4
+
5
+ (c) 2010-2011 Torstein H?nsi
6
+
7
+ License: www.highcharts.com/license
8
+ */
9
+ (function(){function x(a){for(var b=a.length;b--;)typeof a[b]==="number"&&(a[b]=Math.round(a[b])-0.5);return a}var f=Highcharts,y=f.Chart,z=f.addEvent,B=f.removeEvent,r=f.createElement,u=f.discardElement,t=f.css,s=f.merge,k=f.each,n=f.extend,C=Math.max,h=document,D=window,A=h.documentElement.ontouchstart!==void 0,v=f.getOptions();n(v.lang,{downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image",exportButtonTitle:"Export to raster or vector image",
10
+ printButtonTitle:"Print the chart"});v.navigation={menuStyle:{border:"1px solid #A0A0A0",background:"#FFFFFF"},menuItemStyle:{padding:"0 5px",background:"none",color:"#303030",fontSize:A?"14px":"11px"},menuItemHoverStyle:{background:"#4572A5",color:"#FFFFFF"},buttonOptions:{align:"right",backgroundColor:{linearGradient:[0,0,0,20],stops:[[0.4,"#F7F7F7"],[0.6,"#E3E3E3"]]},borderColor:"#B0B0B0",borderRadius:3,borderWidth:1,height:20,hoverBorderColor:"#909090",hoverSymbolFill:"#81A7CF",hoverSymbolStroke:"#4572A5",
11
+ symbolFill:"#E0E0E0",symbolStroke:"#A0A0A0",symbolX:11.5,symbolY:10.5,verticalAlign:"top",width:24,y:10}};v.exporting={type:"image/png",url:"http://export.highcharts.com/",width:800,buttons:{exportButton:{symbol:"exportIcon",x:-10,symbolFill:"#A8BF77",hoverSymbolFill:"#768F3E",_id:"exportButton",_titleKey:"exportButtonTitle",menuItems:[{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},{textKey:"downloadPDF",
12
+ onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG",onclick:function(){this.exportChart({type:"image/svg+xml"})}}]},printButton:{symbol:"printIcon",x:-36,symbolFill:"#B5C9DF",hoverSymbolFill:"#779ABF",_id:"printButton",_titleKey:"printButtonTitle",onclick:function(){this.print()}}}};n(y.prototype,{getSVG:function(a){var b=this,c,d,e,g=s(b.options,a);if(!h.createElementNS)h.createElementNS=function(a,b){var c=h.createElement(b);c.getBBox=function(){return f.Renderer.prototype.Element.prototype.getBBox.apply({element:c})};
13
+ return c};a=r("div",null,{position:"absolute",top:"-9999em",width:b.chartWidth+"px",height:b.chartHeight+"px"},h.body);n(g.chart,{renderTo:a,forExport:!0});g.exporting.enabled=!1;g.chart.plotBackgroundImage=null;g.series=[];k(b.series,function(a){e=s(a.options,{animation:!1,showCheckbox:!1,visible:a.visible});if(!e.isInternal){if(e&&e.marker&&/^url\(/.test(e.marker.symbol))e.marker.symbol="circle";g.series.push(e)}});c=new Highcharts.Chart(g);k(["xAxis","yAxis"],function(a){k(b[a],function(b,d){var e=
14
+ c[a][d],g=b.getExtremes(),f=g.userMin,g=g.userMax;(f!==void 0||g!==void 0)&&e.setExtremes(f,g,!0,!1)})});d=c.container.innerHTML;g=null;c.destroy();u(a);d=d.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/isTracker="[^"]+"/g,"").replace(/url\([^#]+#/g,"url(#").replace(/<svg /,'<svg xmlns:xlink="http://www.w3.org/1999/xlink" ').replace(/ href=/g," xlink:href=").replace(/&nbsp;/g,"\u00a0").replace(/&shy;/g,
15
+ "\u00ad").replace(/<IMG /g,"<image ").replace(/height=([^" ]+)/g,'height="$1"').replace(/width=([^" ]+)/g,'width="$1"').replace(/hc-svg-href="([^"]+)">/g,'xlink:href="$1"/>').replace(/id=([^" >]+)/g,'id="$1"').replace(/class=([^" ]+)/g,'class="$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/style="([^"]+)"/g,function(a){return a.toLowerCase()});d=d.replace(/(url\(#highcharts-[0-9]+)&quot;/g,"$1").replace(/&quot;/g,"'");d.match(/ xmlns="/g).length===2&&(d=d.replace(/xmlns="[^"]+"/,
16
+ ""));return d},exportChart:function(a,b){var c,d=this.getSVG(s(this.options.exporting.chartOptions,b)),a=s(this.options.exporting,a);c=r("form",{method:"post",action:a.url},{display:"none"},h.body);k(["filename","type","width","svg"],function(b){r("input",{type:"hidden",name:b,value:{filename:a.filename||"chart",type:a.type,width:a.width,svg:d}[b]},null,c)});c.submit();u(c)},print:function(){var a=this,b=a.container,c=[],d=b.parentNode,e=h.body,g=e.childNodes;if(!a.isPrinting)a.isPrinting=!0,k(g,
17
+ function(a,b){if(a.nodeType===1)c[b]=a.style.display,a.style.display="none"}),e.appendChild(b),D.print(),setTimeout(function(){d.appendChild(b);k(g,function(a,b){if(a.nodeType===1)a.style.display=c[b]});a.isPrinting=!1},1E3)},contextMenu:function(a,b,c,d,e,g){var i=this,f=i.options.navigation,h=f.menuItemStyle,o=i.chartWidth,p=i.chartHeight,q="cache-"+a,j=i[q],l=C(e,g),m,w;if(!j)i[q]=j=r("div",{className:"highcharts-"+a},{position:"absolute",zIndex:1E3,padding:l+"px"},i.container),m=r("div",null,
18
+ n({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},f.menuStyle),j),w=function(){t(j,{display:"none"})},z(j,"mouseleave",w),k(b,function(a){if(a){var b=r("div",{onmouseover:function(){t(this,f.menuItemHoverStyle)},onmouseout:function(){t(this,h)},innerHTML:a.text||i.options.lang[a.textKey]},n({cursor:"pointer"},h),m);b[A?"ontouchstart":"onclick"]=function(){w();a.onclick.apply(i,arguments)};i.exportDivElements.push(b)}}),i.exportDivElements.push(m,
19
+ j),i.exportMenuWidth=j.offsetWidth,i.exportMenuHeight=j.offsetHeight;a={display:"block"};c+i.exportMenuWidth>o?a.right=o-c-e-l+"px":a.left=c-l+"px";d+g+i.exportMenuHeight>p?a.bottom=p-d-l+"px":a.top=d+g-l+"px";t(j,a)},addButton:function(a){function b(){p.attr(l);o.attr(j)}var c=this,d=c.renderer,e=s(c.options.navigation.buttonOptions,a),g=e.onclick,f=e.menuItems,h=e.width,k=e.height,o,p,q,a=e.borderWidth,j={stroke:e.borderColor},l={stroke:e.symbolStroke,fill:e.symbolFill},m=e.symbolSize||12;if(!c.exportDivElements)c.exportDivElements=
20
+ [],c.exportSVGElements=[];e.enabled!==!1&&(o=d.rect(0,0,h,k,e.borderRadius,a).align(e,!0).attr(n({fill:e.backgroundColor,"stroke-width":a,zIndex:19},j)).add(),q=d.rect(0,0,h,k,0).align(e).attr({id:e._id,fill:"rgba(255, 255, 255, 0.001)",title:c.options.lang[e._titleKey],zIndex:21}).css({cursor:"pointer"}).on("mouseover",function(){p.attr({stroke:e.hoverSymbolStroke,fill:e.hoverSymbolFill});o.attr({stroke:e.hoverBorderColor})}).on("mouseout",b).on("click",b).add(),f&&(g=function(){b();var a=q.getBBox();
21
+ c.contextMenu("export-menu",f,a.x,a.y,h,k)}),q.on("click",function(){g.apply(c,arguments)}),p=d.symbol(e.symbol,e.symbolX-m/2,e.symbolY-m/2,m,m).align(e,!0).attr(n(l,{"stroke-width":e.symbolStrokeWidth||1,zIndex:20})).add(),c.exportSVGElements.push(o,q,p))},destroyExport:function(){var a,b;for(a=0;a<this.exportSVGElements.length;a++)b=this.exportSVGElements[a],b.onclick=b.ontouchstart=null,this.exportSVGElements[a]=b.destroy();for(a=0;a<this.exportDivElements.length;a++)b=this.exportDivElements[a],
22
+ B(b,"mouseleave"),this.exportDivElements[a]=b.onmouseout=b.onmouseover=b.ontouchstart=b.onclick=null,u(b)}});f.Renderer.prototype.symbols.exportIcon=function(a,b,c,d){return x(["M",a,b+c,"L",a+c,b+d,a+c,b+d*0.8,a,b+d*0.8,"Z","M",a+c*0.5,b+d*0.8,"L",a+c*0.8,b+d*0.4,a+c*0.4,b+d*0.4,a+c*0.4,b,a+c*0.6,b,a+c*0.6,b+d*0.4,a+c*0.2,b+d*0.4,"Z"])};f.Renderer.prototype.symbols.printIcon=function(a,b,c,d){return x(["M",a,b+d*0.7,"L",a+c,b+d*0.7,a+c,b+d*0.4,a,b+d*0.4,"Z","M",a+c*0.2,b+d*0.4,"L",a+c*0.2,b,a+c*
23
+ 0.8,b,a+c*0.8,b+d*0.4,"Z","M",a+c*0.2,b+d*0.7,"L",a,b+d,a+c,b+d,a+c*0.8,b+d*0.7,"Z"])};y.prototype.callbacks.push(function(a){var b,c=a.options.exporting,d=c.buttons;if(c.enabled!==!1){for(b in d)a.addButton(d[b]);z(a,"destroy",a.destroyExport)}})})();
js/themes/dark-blue.js ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Dark blue theme for Highcharts JS
3
+ * @author Torstein Hønsi
4
+ */
5
+
6
+ Highcharts.theme = {
7
+ colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
8
+ "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
9
+ chart: {
10
+ backgroundColor: {
11
+ linearGradient: [0, 0, 250, 500],
12
+ stops: [
13
+ [0, 'rgb(48, 48, 96)'],
14
+ [1, 'rgb(0, 0, 0)']
15
+ ]
16
+ },
17
+ borderColor: '#000000',
18
+ borderWidth: 2,
19
+ className: 'dark-container',
20
+ plotBackgroundColor: 'rgba(255, 255, 255, .1)',
21
+ plotBorderColor: '#CCCCCC',
22
+ plotBorderWidth: 1
23
+ },
24
+ title: {
25
+ style: {
26
+ color: '#C0C0C0',
27
+ font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
28
+ }
29
+ },
30
+ subtitle: {
31
+ style: {
32
+ color: '#666666',
33
+ font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
34
+ }
35
+ },
36
+ xAxis: {
37
+ gridLineColor: '#333333',
38
+ gridLineWidth: 1,
39
+ labels: {
40
+ style: {
41
+ color: '#A0A0A0'
42
+ }
43
+ },
44
+ lineColor: '#A0A0A0',
45
+ tickColor: '#A0A0A0',
46
+ title: {
47
+ style: {
48
+ color: '#CCC',
49
+ fontWeight: 'bold',
50
+ fontSize: '12px',
51
+ fontFamily: 'Trebuchet MS, Verdana, sans-serif'
52
+
53
+ }
54
+ }
55
+ },
56
+ yAxis: {
57
+ gridLineColor: '#333333',
58
+ labels: {
59
+ style: {
60
+ color: '#A0A0A0'
61
+ }
62
+ },
63
+ lineColor: '#A0A0A0',
64
+ minorTickInterval: null,
65
+ tickColor: '#A0A0A0',
66
+ tickWidth: 1,
67
+ title: {
68
+ style: {
69
+ color: '#CCC',
70
+ fontWeight: 'bold',
71
+ fontSize: '12px',
72
+ fontFamily: 'Trebuchet MS, Verdana, sans-serif'
73
+ }
74
+ }
75
+ },
76
+ tooltip: {
77
+ backgroundColor: 'rgba(0, 0, 0, 0.75)',
78
+ style: {
79
+ color: '#F0F0F0'
80
+ }
81
+ },
82
+ toolbar: {
83
+ itemStyle: {
84
+ color: 'silver'
85
+ }
86
+ },
87
+ plotOptions: {
88
+ line: {
89
+ dataLabels: {
90
+ color: '#CCC'
91
+ },
92
+ marker: {
93
+ lineColor: '#333'
94
+ }
95
+ },
96
+ spline: {
97
+ marker: {
98
+ lineColor: '#333'
99
+ }
100
+ },
101
+ scatter: {
102
+ marker: {
103
+ lineColor: '#333'
104
+ }
105
+ },
106
+ candlestick: {
107
+ lineColor: 'white'
108
+ }
109
+ },
110
+ legend: {
111
+ itemStyle: {
112
+ font: '9pt Trebuchet MS, Verdana, sans-serif',
113
+ color: '#A0A0A0'
114
+ },
115
+ itemHoverStyle: {
116
+ color: '#FFF'
117
+ },
118
+ itemHiddenStyle: {
119
+ color: '#444'
120
+ }
121
+ },
122
+ credits: {
123
+ style: {
124
+ color: '#666'
125
+ }
126
+ },
127
+ labels: {
128
+ style: {
129
+ color: '#CCC'
130
+ }
131
+ },
132
+
133
+ navigation: {
134
+ buttonOptions: {
135
+ backgroundColor: {
136
+ linearGradient: [0, 0, 0, 20],
137
+ stops: [
138
+ [0.4, '#606060'],
139
+ [0.6, '#333333']
140
+ ]
141
+ },
142
+ borderColor: '#000000',
143
+ symbolStroke: '#C0C0C0',
144
+ hoverSymbolStroke: '#FFFFFF'
145
+ }
146
+ },
147
+
148
+ exporting: {
149
+ buttons: {
150
+ exportButton: {
151
+ symbolFill: '#55BE3B'
152
+ },
153
+ printButton: {
154
+ symbolFill: '#7797BE'
155
+ }
156
+ }
157
+ },
158
+
159
+ // scroll charts
160
+ rangeSelector: {
161
+ buttonTheme: {
162
+ fill: {
163
+ linearGradient: [0, 0, 0, 20],
164
+ stops: [
165
+ [0.4, '#888'],
166
+ [0.6, '#555']
167
+ ]
168
+ },
169
+ stroke: '#000000',
170
+ style: {
171
+ color: '#CCC',
172
+ fontWeight: 'bold'
173
+ },
174
+ states: {
175
+ hover: {
176
+ fill: {
177
+ linearGradient: [0, 0, 0, 20],
178
+ stops: [
179
+ [0.4, '#BBB'],
180
+ [0.6, '#888']
181
+ ]
182
+ },
183
+ stroke: '#000000',
184
+ style: {
185
+ color: 'white'
186
+ }
187
+ },
188
+ select: {
189
+ fill: {
190
+ linearGradient: [0, 0, 0, 20],
191
+ stops: [
192
+ [0.1, '#000'],
193
+ [0.3, '#333']
194
+ ]
195
+ },
196
+ stroke: '#000000',
197
+ style: {
198
+ color: 'yellow'
199
+ }
200
+ }
201
+ }
202
+ },
203
+ inputStyle: {
204
+ backgroundColor: '#333',
205
+ color: 'silver'
206
+ },
207
+ labelStyle: {
208
+ color: 'silver'
209
+ }
210
+ },
211
+
212
+ navigator: {
213
+ handles: {
214
+ backgroundColor: '#666',
215
+ borderColor: '#AAA'
216
+ },
217
+ outlineColor: '#CCC',
218
+ maskFill: 'rgba(16, 16, 16, 0.5)',
219
+ series: {
220
+ color: '#7798BF',
221
+ lineColor: '#A6C7ED'
222
+ }
223
+ },
224
+
225
+ scrollbar: {
226
+ barBackgroundColor: {
227
+ linearGradient: [0, 0, 0, 20],
228
+ stops: [
229
+ [0.4, '#888'],
230
+ [0.6, '#555']
231
+ ]
232
+ },
233
+ barBorderColor: '#CCC',
234
+ buttonArrowColor: '#CCC',
235
+ buttonBackgroundColor: {
236
+ linearGradient: [0, 0, 0, 20],
237
+ stops: [
238
+ [0.4, '#888'],
239
+ [0.6, '#555']
240
+ ]
241
+ },
242
+ buttonBorderColor: '#CCC',
243
+ rifleColor: '#FFF',
244
+ trackBackgroundColor: {
245
+ linearGradient: [0, 0, 0, 10],
246
+ stops: [
247
+ [0, '#000'],
248
+ [1, '#333']
249
+ ]
250
+ },
251
+ trackBorderColor: '#666'
252
+ },
253
+
254
+ // special colors for some of the
255
+ legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
256
+ legendBackgroundColorSolid: 'rgb(35, 35, 70)',
257
+ dataLabelsColor: '#444',
258
+ textColor: '#C0C0C0',
259
+ maskColor: 'rgba(255,255,255,0.3)'
260
+ };
261
+
262
+ // Apply the theme
263
+ var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
js/themes/dark-green.js ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Dark blue theme for Highcharts JS
3
+ * @author Torstein Hønsi
4
+ */
5
+
6
+ Highcharts.theme = {
7
+ colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee",
8
+ "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
9
+ chart: {
10
+ backgroundColor: {
11
+ linearGradient: [0, 0, 250, 500],
12
+ stops: [
13
+ [0, 'rgb(48, 96, 48)'],
14
+ [1, 'rgb(0, 0, 0)']
15
+ ]
16
+ },
17
+ borderColor: '#000000',
18
+ borderWidth: 2,
19
+ className: 'dark-container',
20
+ plotBackgroundColor: 'rgba(255, 255, 255, .1)',
21
+ plotBorderColor: '#CCCCCC',
22
+ plotBorderWidth: 1
23
+ },
24
+ title: {
25
+ style: {
26
+ color: '#C0C0C0',
27
+ font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
28
+ }
29
+ },
30
+ subtitle: {
31
+ style: {
32
+ color: '#666666',
33
+ font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
34
+ }
35
+ },
36
+ xAxis: {
37
+ gridLineColor: '#333333',
38
+ gridLineWidth: 1,
39
+ labels: {
40
+ style: {
41
+ color: '#A0A0A0'
42
+ }
43
+ },
44
+ lineColor: '#A0A0A0',
45
+ tickColor: '#A0A0A0',
46
+ title: {
47
+ style: {
48
+ color: '#CCC',
49
+ fontWeight: 'bold',
50
+ fontSize: '12px',
51
+ fontFamily: 'Trebuchet MS, Verdana, sans-serif'
52
+
53
+ }
54
+ }
55
+ },
56
+ yAxis: {
57
+ gridLineColor: '#333333',
58
+ labels: {
59
+ style: {
60
+ color: '#A0A0A0'
61
+ }
62
+ },
63
+ lineColor: '#A0A0A0',
64
+ minorTickInterval: null,
65
+ tickColor: '#A0A0A0',
66
+ tickWidth: 1,
67
+ title: {
68
+ style: {
69
+ color: '#CCC',
70
+ fontWeight: 'bold',
71
+ fontSize: '12px',
72
+ fontFamily: 'Trebuchet MS, Verdana, sans-serif'
73
+ }
74
+ }
75
+ },
76
+ tooltip: {
77
+ backgroundColor: 'rgba(0, 0, 0, 0.75)',
78
+ style: {
79
+ color: '#F0F0F0'
80
+ }
81
+ },
82
+ toolbar: {
83
+ itemStyle: {
84
+ color: 'silver'
85
+ }
86
+ },
87
+ plotOptions: {
88
+ line: {
89
+ dataLabels: {
90
+ color: '#CCC'
91
+ },
92
+ marker: {
93
+ lineColor: '#333'
94
+ }
95
+ },
96
+ spline: {
97
+ marker: {
98
+ lineColor: '#333'
99
+ }
100
+ },
101
+ scatter: {
102
+ marker: {
103
+ lineColor: '#333'
104
+ }
105
+ },
106
+ candlestick: {
107
+ lineColor: 'white'
108
+ }
109
+ },
110
+ legend: {
111
+ itemStyle: {
112
+ font: '9pt Trebuchet MS, Verdana, sans-serif',
113
+ color: '#A0A0A0'
114
+ },
115
+ itemHoverStyle: {
116
+ color: '#FFF'
117
+ },
118
+ itemHiddenStyle: {
119
+ color: '#444'
120
+ }
121
+ },
122
+ credits: {
123
+ style: {
124
+ color: '#666'
125
+ }
126
+ },
127
+ labels: {
128
+ style: {
129
+ color: '#CCC'
130
+ }
131
+ },
132
+
133
+ navigation: {
134
+ buttonOptions: {
135
+ backgroundColor: {
136
+ linearGradient: [0, 0, 0, 20],
137
+ stops: [
138
+ [0.4, '#606060'],
139
+ [0.6, '#333333']
140
+ ]
141
+ },
142
+ borderColor: '#000000',
143
+ symbolStroke: '#C0C0C0',
144
+ hoverSymbolStroke: '#FFFFFF'
145
+ }
146
+ },
147
+
148
+ exporting: {
149
+ buttons: {
150
+ exportButton: {
151
+ symbolFill: '#55BE3B'
152
+ },
153
+ printButton: {
154
+ symbolFill: '#7797BE'
155
+ }
156
+ }
157
+ },
158
+
159
+ // scroll charts
160
+ rangeSelector: {
161
+ buttonTheme: {
162
+ fill: {
163
+ linearGradient: [0, 0, 0, 20],
164
+ stops: [
165
+ [0.4, '#888'],
166
+ [0.6, '#555']
167
+ ]
168
+ },
169
+ stroke: '#000000',
170
+ style: {
171
+ color: '#CCC',
172
+ fontWeight: 'bold'
173
+ },
174
+ states: {
175
+ hover: {
176
+ fill: {
177
+ linearGradient: [0, 0, 0, 20],
178
+ stops: [
179
+ [0.4, '#BBB'],
180
+ [0.6, '#888']
181
+ ]
182
+ },
183
+ stroke: '#000000',
184
+ style: {
185
+ color: 'white'
186
+ }
187
+ },
188
+ select: {
189
+ fill: {
190
+ linearGradient: [0, 0, 0, 20],
191
+ stops: [
192
+ [0.1, '#000'],
193
+ [0.3, '#333']
194
+ ]
195
+ },
196
+ stroke: '#000000',
197
+ style: {
198
+ color: 'yellow'
199
+ }
200
+ }
201
+ }
202
+ },
203
+ inputStyle: {
204
+ backgroundColor: '#333',
205
+ color: 'silver'
206
+ },
207
+ labelStyle: {
208
+ color: 'silver'
209
+ }
210
+ },
211
+
212
+ navigator: {
213
+ handles: {
214
+ backgroundColor: '#666',
215
+ borderColor: '#AAA'
216
+ },
217
+ outlineColor: '#CCC',
218
+ maskFill: 'rgba(16, 16, 16, 0.5)',
219
+ series: {
220
+ color: '#7798BF',
221
+ lineColor: '#A6C7ED'
222
+ }
223
+ },
224
+
225
+ scrollbar: {
226
+ barBackgroundColor: {
227
+ linearGradient: [0, 0, 0, 20],
228
+ stops: [
229
+ [0.4, '#888'],
230
+ [0.6, '#555']
231
+ ]
232
+ },
233
+ barBorderColor: '#CCC',
234
+ buttonArrowColor: '#CCC',
235
+ buttonBackgroundColor: {
236
+ linearGradient: [0, 0, 0, 20],
237
+ stops: [
238
+ [0.4, '#888'],
239
+ [0.6, '#555']
240
+ ]
241
+ },
242
+ buttonBorderColor: '#CCC',
243
+ rifleColor: '#FFF',
244
+ trackBackgroundColor: {
245
+ linearGradient: [0, 0, 0, 10],
246
+ stops: [
247
+ [0, '#000'],
248
+ [1, '#333']
249
+ ]
250
+ },
251
+ trackBorderColor: '#666'
252
+ },
253
+
254
+ // special colors for some of the
255
+ legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
256
+ legendBackgroundColorSolid: 'rgb(35, 35, 70)',
257
+ dataLabelsColor: '#444',
258
+ textColor: '#C0C0C0',
259
+ maskColor: 'rgba(255,255,255,0.3)'
260
+ };
261
+
262
+ // Apply the theme
263
+ var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
js/themes/gray.js ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Gray theme for Highcharts JS
3
+ * @author Torstein Hønsi
4
+ */
5
+
6
+ Highcharts.theme = {
7
+ colors: ["#DDDF0D", "#7798BF", "#55BF3B", "#DF5353", "#aaeeee", "#ff0066", "#eeaaee",
8
+ "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"],
9
+ chart: {
10
+ backgroundColor: {
11
+ linearGradient: [0, 0, 0, 400],
12
+ stops: [
13
+ [0, 'rgb(96, 96, 96)'],
14
+ [1, 'rgb(16, 16, 16)']
15
+ ]
16
+ },
17
+ borderWidth: 0,
18
+ borderRadius: 15,
19
+ plotBackgroundColor: null,
20
+ plotShadow: false,
21
+ plotBorderWidth: 0
22
+ },
23
+ title: {
24
+ style: {
25
+ color: '#FFF',
26
+ font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
27
+ }
28
+ },
29
+ subtitle: {
30
+ style: {
31
+ color: '#DDD',
32
+ font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
33
+ }
34
+ },
35
+ xAxis: {
36
+ gridLineWidth: 0,
37
+ lineColor: '#999',
38
+ tickColor: '#999',
39
+ labels: {
40
+ style: {
41
+ color: '#999',
42
+ fontWeight: 'bold'
43
+ }
44
+ },
45
+ title: {
46
+ style: {
47
+ color: '#AAA',
48
+ font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
49
+ }
50
+ }
51
+ },
52
+ yAxis: {
53
+ alternateGridColor: null,
54
+ minorTickInterval: null,
55
+ gridLineColor: 'rgba(255, 255, 255, .1)',
56
+ lineWidth: 0,
57
+ tickWidth: 0,
58
+ labels: {
59
+ style: {
60
+ color: '#999',
61
+ fontWeight: 'bold'
62
+ }
63
+ },
64
+ title: {
65
+ style: {
66
+ color: '#AAA',
67
+ font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
68
+ }
69
+ }
70
+ },
71
+ legend: {
72
+ itemStyle: {
73
+ color: '#CCC'
74
+ },
75
+ itemHoverStyle: {
76
+ color: '#FFF'
77
+ },
78
+ itemHiddenStyle: {
79
+ color: '#333'
80
+ }
81
+ },
82
+ labels: {
83
+ style: {
84
+ color: '#CCC'
85
+ }
86
+ },
87
+ tooltip: {
88
+ backgroundColor: {
89
+ linearGradient: [0, 0, 0, 50],
90
+ stops: [
91
+ [0, 'rgba(96, 96, 96, .8)'],
92
+ [1, 'rgba(16, 16, 16, .8)']
93
+ ]
94
+ },
95
+ borderWidth: 0,
96
+ style: {
97
+ color: '#FFF'
98
+ }
99
+ },
100
+
101
+
102
+ plotOptions: {
103
+ line: {
104
+ dataLabels: {
105
+ color: '#CCC'
106
+ },
107
+ marker: {
108
+ lineColor: '#333'
109
+ }
110
+ },
111
+ spline: {
112
+ marker: {
113
+ lineColor: '#333'
114
+ }
115
+ },
116
+ scatter: {
117
+ marker: {
118
+ lineColor: '#333'
119
+ }
120
+ },
121
+ candlestick: {
122
+ lineColor: 'white'
123
+ }
124
+ },
125
+
126
+ toolbar: {
127
+ itemStyle: {
128
+ color: '#CCC'
129
+ }
130
+ },
131
+
132
+ navigation: {
133
+ buttonOptions: {
134
+ backgroundColor: {
135
+ linearGradient: [0, 0, 0, 20],
136
+ stops: [
137
+ [0.4, '#606060'],
138
+ [0.6, '#333333']
139
+ ]
140
+ },
141
+ borderColor: '#000000',
142
+ symbolStroke: '#C0C0C0',
143
+ hoverSymbolStroke: '#FFFFFF'
144
+ }
145
+ },
146
+
147
+ exporting: {
148
+ buttons: {
149
+ exportButton: {
150
+ symbolFill: '#55BE3B'
151
+ },
152
+ printButton: {
153
+ symbolFill: '#7797BE'
154
+ }
155
+ }
156
+ },
157
+
158
+ // scroll charts
159
+ rangeSelector: {
160
+ buttonTheme: {
161
+ fill: {
162
+ linearGradient: [0, 0, 0, 20],
163
+ stops: [
164
+ [0.4, '#888'],
165
+ [0.6, '#555']
166
+ ]
167
+ },
168
+ stroke: '#000000',
169
+ style: {
170
+ color: '#CCC',
171
+ fontWeight: 'bold'
172
+ },
173
+ states: {
174
+ hover: {
175
+ fill: {
176
+ linearGradient: [0, 0, 0, 20],
177
+ stops: [
178
+ [0.4, '#BBB'],
179
+ [0.6, '#888']
180
+ ]
181
+ },
182
+ stroke: '#000000',
183
+ style: {
184
+ color: 'white'
185
+ }
186
+ },
187
+ select: {
188
+ fill: {
189
+ linearGradient: [0, 0, 0, 20],
190
+ stops: [
191
+ [0.1, '#000'],
192
+ [0.3, '#333']
193
+ ]
194
+ },
195
+ stroke: '#000000',
196
+ style: {
197
+ color: 'yellow'
198
+ }
199
+ }
200
+ }
201
+ },
202
+ inputStyle: {
203
+ backgroundColor: '#333',
204
+ color: 'silver'
205
+ },
206
+ labelStyle: {
207
+ color: 'silver'
208
+ }
209
+ },
210
+
211
+ navigator: {
212
+ handles: {
213
+ backgroundColor: '#666',
214
+ borderColor: '#AAA'
215
+ },
216
+ outlineColor: '#CCC',
217
+ maskFill: 'rgba(16, 16, 16, 0.5)',
218
+ series: {
219
+ color: '#7798BF',
220
+ lineColor: '#A6C7ED'
221
+ }
222
+ },
223
+
224
+ scrollbar: {
225
+ barBackgroundColor: {
226
+ linearGradient: [0, 0, 0, 20],
227
+ stops: [
228
+ [0.4, '#888'],
229
+ [0.6, '#555']
230
+ ]
231
+ },
232
+ barBorderColor: '#CCC',
233
+ buttonArrowColor: '#CCC',
234
+ buttonBackgroundColor: {
235
+ linearGradient: [0, 0, 0, 20],
236
+ stops: [
237
+ [0.4, '#888'],
238
+ [0.6, '#555']
239
+ ]
240
+ },
241
+ buttonBorderColor: '#CCC',
242
+ rifleColor: '#FFF',
243
+ trackBackgroundColor: {
244
+ linearGradient: [0, 0, 0, 10],
245
+ stops: [
246
+ [0, '#000'],
247
+ [1, '#333']
248
+ ]
249
+ },
250
+ trackBorderColor: '#666'
251
+ },
252
+
253
+ // special colors for some of the demo examples
254
+ legendBackgroundColor: 'rgba(48, 48, 48, 0.8)',
255
+ legendBackgroundColorSolid: 'rgb(70, 70, 70)',
256
+ dataLabelsColor: '#444',
257
+ textColor: '#E0E0E0',
258
+ maskColor: 'rgba(255,255,255,0.3)'
259
+ };
260
+
261
+ // Apply the theme
262
+ var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
js/themes/grid.js ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Grid theme for Highcharts JS
3
+ * @author Torstein Hønsi
4
+ */
5
+
6
+ Highcharts.theme = {
7
+ colors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', '#FF9655', '#FFF263', '#6AF9C4'],
8
+ chart: {
9
+ backgroundColor: {
10
+ linearGradient: [0, 0, 500, 500],
11
+ stops: [
12
+ [0, 'rgb(255, 255, 255)'],
13
+ [1, 'rgb(240, 240, 255)']
14
+ ]
15
+ },
16
+ borderWidth: 2,
17
+ plotBackgroundColor: 'rgba(255, 255, 255, .9)',
18
+ plotShadow: true,
19
+ plotBorderWidth: 1
20
+ },
21
+ title: {
22
+ style: {
23
+ color: '#000',
24
+ font: 'bold 16px "Trebuchet MS", Verdana, sans-serif'
25
+ }
26
+ },
27
+ subtitle: {
28
+ style: {
29
+ color: '#666666',
30
+ font: 'bold 12px "Trebuchet MS", Verdana, sans-serif'
31
+ }
32
+ },
33
+ xAxis: {
34
+ gridLineWidth: 1,
35
+ lineColor: '#000',
36
+ tickColor: '#000',
37
+ labels: {
38
+ style: {
39
+ color: '#000',
40
+ font: '11px Trebuchet MS, Verdana, sans-serif'
41
+ }
42
+ },
43
+ title: {
44
+ style: {
45
+ color: '#333',
46
+ fontWeight: 'bold',
47
+ fontSize: '12px',
48
+ fontFamily: 'Trebuchet MS, Verdana, sans-serif'
49
+
50
+ }
51
+ }
52
+ },
53
+ yAxis: {
54
+ minorTickInterval: 'auto',
55
+ lineColor: '#000',
56
+ lineWidth: 1,
57
+ tickWidth: 1,
58
+ tickColor: '#000',
59
+ labels: {
60
+ style: {
61
+ color: '#000',
62
+ font: '11px Trebuchet MS, Verdana, sans-serif'
63
+ }
64
+ },
65
+ title: {
66
+ style: {
67
+ color: '#333',
68
+ fontWeight: 'bold',
69
+ fontSize: '12px',
70
+ fontFamily: 'Trebuchet MS, Verdana, sans-serif'
71
+ }
72
+ }
73
+ },
74
+ legend: {
75
+ itemStyle: {
76
+ font: '9pt Trebuchet MS, Verdana, sans-serif',
77
+ color: 'black'
78
+
79
+ },
80
+ itemHoverStyle: {
81
+ color: '#039'
82
+ },
83
+ itemHiddenStyle: {
84
+ color: 'gray'
85
+ }
86
+ },
87
+ labels: {
88
+ style: {
89
+ color: '#99b'
90
+ }
91
+ }
92
+ };
93
+
94
+ // Apply the theme
95
+ var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
js/themes/skies.js ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Skies theme for Highcharts JS
3
+ * @author Torstein Hønsi
4
+ */
5
+
6
+ Highcharts.theme = {
7
+ colors: ["#514F78", "#42A07B", "#9B5E4A", "#72727F", "#1F949A", "#82914E", "#86777F", "#42A07B"],
8
+ chart: {
9
+ className: 'skies',
10
+ borderWidth: 0,
11
+ plotShadow: true,
12
+ plotBackgroundImage: '/demo/gfx/skies.jpg',
13
+ plotBackgroundColor: {
14
+ linearGradient: [0, 0, 250, 500],
15
+ stops: [
16
+ [0, 'rgba(255, 255, 255, 1)'],
17
+ [1, 'rgba(255, 255, 255, 0)']
18
+ ]
19
+ },
20
+ plotBorderWidth: 1
21
+ },
22
+ title: {
23
+ style: {
24
+ color: '#3E576F',
25
+ font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
26
+ }
27
+ },
28
+ subtitle: {
29
+ style: {
30
+ color: '#6D869F',
31
+ font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
32
+ }
33
+ },
34
+ xAxis: {
35
+ gridLineWidth: 0,
36
+ lineColor: '#C0D0E0',
37
+ tickColor: '#C0D0E0',
38
+ labels: {
39
+ style: {
40
+ color: '#666',
41
+ fontWeight: 'bold'
42
+ }
43
+ },
44
+ title: {
45
+ style: {
46
+ color: '#666',
47
+ font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
48
+ }
49
+ }
50
+ },
51
+ yAxis: {
52
+ alternateGridColor: 'rgba(255, 255, 255, .5)',
53
+ lineColor: '#C0D0E0',
54
+ tickColor: '#C0D0E0',
55
+ tickWidth: 1,
56
+ labels: {
57
+ style: {
58
+ color: '#666',
59
+ fontWeight: 'bold'
60
+ }
61
+ },
62
+ title: {
63
+ style: {
64
+ color: '#666',
65
+ font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif'
66
+ }
67
+ }
68
+ },
69
+ legend: {
70
+ itemStyle: {
71
+ font: '9pt Trebuchet MS, Verdana, sans-serif',
72
+ color: '#3E576F'
73
+ },
74
+ itemHoverStyle: {
75
+ color: 'black'
76
+ },
77
+ itemHiddenStyle: {
78
+ color: 'silver'
79
+ }
80
+ },
81
+ labels: {
82
+ style: {
83
+ color: '#3E576F'
84
+ }
85
+ }
86
+ };
87
+
88
+ // Apply the theme
89
+ var highchartsOptions = Highcharts.setOptions(Highcharts.theme);
lang/wpmandrill-es_ES.mo ADDED
Binary file
lang/wpmandrill.po ADDED
@@ -0,0 +1,581 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: wpMandrill 1.0 rc1\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: 2012-04-25 14:39-0500\n"
6
+ "PO-Revision-Date: \n"
7
+ "Last-Translator: Will Castillo <will@mailchimp.com>\n"
8
+ "Language-Team: MailChimp <will@mailchimp.com>\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Poedit-Language: Spanish\n"
13
+ "X-Poedit-Country: UNITED STATES\n"
14
+ "X-Poedit-SourceCharset: utf-8\n"
15
+ "X-Poedit-Basepath: ../\n"
16
+ "X-Poedit-KeywordsList: __;_e\n"
17
+ "X-Poedit-SearchPath-0: .\n"
18
+
19
+ #: wpmandrill.php:81
20
+ msgid "API Settings"
21
+ msgstr "Configuración de la API"
22
+
23
+ #: wpmandrill.php:82
24
+ msgid "API Key"
25
+ msgstr "Clave API"
26
+
27
+ #: wpmandrill.php:88
28
+ msgid "Sender Settings"
29
+ msgstr "Configuración del Remitente"
30
+
31
+ #: wpmandrill.php:89
32
+ msgid "FROM Name"
33
+ msgstr "Campo De:"
34
+
35
+ #: wpmandrill.php:90
36
+ msgid "FROM Email"
37
+ msgstr "Campo Email:"
38
+
39
+ #: wpmandrill.php:93
40
+ msgid "General Template"
41
+ msgstr "Plantilla General"
42
+
43
+ #: wpmandrill.php:94
44
+ #: wpmandrill.php:98
45
+ #: wpmandrilltest.php:45
46
+ #: wpmandrilltest.php:48
47
+ #: wpmandrilltest.php:51
48
+ #: wpmandrilltest.php:54
49
+ msgid "&nbsp;"
50
+ msgstr "&nbsp;"
51
+
52
+ #: wpmandrill.php:97
53
+ msgid "General Tags"
54
+ msgstr "Etiquetas Generales"
55
+
56
+ #: wpmandrill.php:104
57
+ msgid "Send a test email using these settings"
58
+ msgstr "Enviar un correo electrónico de prueba usando estas configuraciones"
59
+
60
+ #: wpmandrill.php:105
61
+ msgid "Send to"
62
+ msgstr "Enviar a"
63
+
64
+ #: wpmandrill.php:106
65
+ msgid "Subject"
66
+ msgstr "Asunto"
67
+
68
+ #: wpmandrill.php:107
69
+ msgid "Message"
70
+ msgstr "Mensaje"
71
+
72
+ #: wpmandrill.php:118
73
+ #: wpmandrill.php:229
74
+ msgid "Mandrill Settings"
75
+ msgstr "Configuración de Mandrill"
76
+
77
+ #: wpmandrill.php:119
78
+ msgid "Mandrill"
79
+ msgstr "Mandrill"
80
+
81
+ #: wpmandrill.php:126
82
+ #: wpmandrill.php:127
83
+ msgid "Mandrill Reports"
84
+ msgstr "Reportes Mandrill"
85
+
86
+ #: wpmandrill.php:149
87
+ msgid "Mandrill: wp_mail has been declared by another process or plugin, so you won't be able to use Mandrill until the problem is solved."
88
+ msgstr "Mandrill: wp?install ha sido declarado por otro proceso o plugin por lo que no podras usar Mandrill hasta que soluciones este inconveniente."
89
+
90
+ #: wpmandrill.php:178
91
+ msgid "To use this plugin you will need:"
92
+ msgstr "Para utilizar este plugin necesitarás:"
93
+
94
+ #: wpmandrill.php:180
95
+ msgid "Your Mandrill account."
96
+ msgstr "Tu cuenta Mandrill"
97
+
98
+ #: wpmandrill.php:181
99
+ msgid "At least one verified domain."
100
+ msgstr "Al menos un dominio verificado."
101
+
102
+ #: wpmandrill.php:182
103
+ msgid "A valid sender email address specified."
104
+ msgstr "Una dirección de correo electrónico de remitente válido."
105
+
106
+ #: wpmandrill.php:187
107
+ msgid "Once you have properly configured the settings, the plugin will take care of all the emails sent through your WordPress installation."
108
+ msgstr "Una vez que hayas completado la configuración, el plugin se hará cargo de todos los correos enviados a través de tu instalación WordPress."
109
+
110
+ #: wpmandrill.php:188
111
+ msgid "However, if you need to customize any part of the email before sending, you can do so by using the WordPress filter <strong>mandrill_payload</strong>."
112
+ msgstr "De cualquier forma, si alguna vez necesitas alterar cualquier parte del email antes de que este sea enviado, lo podrás hacer utilizando el filtro WordPress <strong>mandrill_payload</strong>."
113
+
114
+ #: wpmandrill.php:189
115
+ msgid "This filter has the same structure as Mandrill's API call <a href=\"http://mandrillapp.com/api/docs/messages.html#method=send\" target=\"_blank\">/messages/send</a>, except that it can have one additional parameter when the email is based on a template. The parameter is called \"<em>template</em>\", which is an associative array of two elements (the first element, a string whose key is \"<em>template_name</em>\", and a second parameter whose key is \"<em>template_content</em>\". Its value is an array with the same structure of the parameter \"<em>template_content</em>\" in the call <a href=\"http://mandrillapp.com/api/docs/messages.html#method=send-template\" target=\"_blank\">/messages/send-template</a>.)"
116
+ msgstr "Este filtro tiene la misma estructura de la llamada a la API de Mandrill <a href=\"http://mandrillapp.com/api/docs/messages.html#method=send\" target=\"_blank\">/messages/send</a>, excepto que esta podría tener un parámetro adicional cuando el email está basado en una plantilla. El parametro se llama \"<em>template</em>\", el cual es un arreglo asociativo de dos elementos (el primero, una cadena de caracteres cuya clave es \"<em>template_name</em>\", y un segundo parámetro cuya clave es \"<em>template_content</em>\" y su valor es una arreglo con la misma estructura del parámetro \"<em>template_content</em>\" de la llamada <a href=\"http://mandrillapp.com/api/docs/messages.html#method=send-template\" target=\"_blank\">/messages/send-template</a>.)"
117
+
118
+ #: wpmandrill.php:190
119
+ msgid "Note that if you're sending additional headers in your emails, the only valid headers are <em>From:</em>, <em>Reply-To:</em>, and <em>X-*:</em>. <em>Bcc:</em> is also valid, but Mandrill will send the blind carbon copy to only the first address, and the remaining will be silently discarted."
120
+ msgstr "Ten en cuenta que si estás intentando enviar cabeceras adicionales en tus correos, las únicas cabeceras válidas serán <em>From:</em>, <em>Reply-To:</em> y <em>X-*:</em>. <em>Bcc:</em> también es válido, pero Mandrill sólo enviará la copia oculta a la primera dirección, descartando silenciosamente el resto de las direcciones especificadas en el campo Bcc: que envíes."
121
+
122
+ #: wpmandrill.php:191
123
+ msgid "Also note that if any error occurs while sending the email, the plugin will try to send the message again using the native WordPress mailing capabilities."
124
+ msgstr "También ten presente que si ocurre cualquier error durante el envío del correo, el plugin intentará enviar el mensaje otra vez, utilizando las capacidades de envío de correo nativas de WordPress."
125
+
126
+ #: wpmandrill.php:192
127
+ msgid "Confirm that any change you made to the payload is in line with the <a href=\"http://mandrillapp.com/api/docs/\" target=\"_blank\">Mandrill's API's documentation</a>. Also, the <em>X-*:</em> headers, must be in line with the <a href=\"http://help.mandrill.com/customer/portal/articles/456744-smtp-headers-api\" target=\"_blank\">SMTP API documentation</a>. By using this plugin, you agree that you and your website will adhere to <a href=\"http://mandrill.com/legal/terms/\" target=\"_blank\">Mandrill's Terms of Use</a>."
128
+ msgstr "Asegúrate que cualquier cambio que hagas en el payload esté cónsono con la <a href=\"http://mandrillapp.com/api/docs/\" target=\"_blank\">Documentacion de la API de Mandrill</a>. También, las cabeceras <em>X-*:</em> deben estar en línea con la <a href=\"http://help.mandrill.com/customer/portal/articles/456744-smtp-headers-api\" target=\"_blank\">Documentación de la API SMTP</a>. Al utilizar este plugin estás aceptando adherirte tu y tu sitio web a los <a href=\"http://mandrill.com/legal/terms/\" target=\"_blank\">Términos y Condiciones de Mandrill</a>."
129
+
130
+ #: wpmandrill.php:193
131
+ msgid "if you have any question about Mandrill or this plugin, visit the <a href=\"http://help.mandrill.com/\" target=\"_blank\">Mandrill's Support Center</a>."
132
+ msgstr "Si tienes alguna pregunta sobre mandrill o este plugin, visita el <a href=\"http://help.mandrill.com/\" target=\"_blank\">Centro de Soporte de Mandrill</a>."
133
+
134
+ #: wpmandrill.php:211
135
+ #: wpmandrilltest.php:175
136
+ msgid "Settings"
137
+ msgstr "Configuraciones"
138
+
139
+ #: wpmandrill.php:212
140
+ msgid "Reports"
141
+ msgstr "Reportes"
142
+
143
+ #: wpmandrill.php:224
144
+ #: wpmandrilltest.php:188
145
+ #: stats.php:1
146
+ msgid "You do not have sufficient permissions to access this page."
147
+ msgstr "No tienes suficiente permisología para acceder a esta página."
148
+
149
+ #: wpmandrill.php:250
150
+ msgid "Send Email"
151
+ msgstr "Campo Email:"
152
+
153
+ #: wpmandrill.php:268
154
+ msgid "Latest from Mandrill..."
155
+ msgstr "Lo último de Mandrill..."
156
+
157
+ #: wpmandrill.php:282
158
+ msgid "News from MailChimp..."
159
+ msgstr "Noticias de MailChimp"
160
+
161
+ #: wpmandrill.php:317
162
+ msgid "You must define a valid sender email."
163
+ msgstr "Debes definir un correo electrónico de remitente válido."
164
+
165
+ #: wpmandrill.php:567
166
+ msgid "Test email send failed. "
167
+ msgstr "El correo electrónico de prueba falló."
168
+
169
+ #: wpmandrill.php:577
170
+ #, php-format
171
+ msgid "Test executed: %d emails sent, %d emails queued and %d emails rejected"
172
+ msgstr "Prueba ejecutada: %d emails enviados, %d emails encolados y %d emails rechazados"
173
+
174
+ #: wpmandrill.php:592
175
+ msgid "To get your API key, please visit your <a href=\"http://mandrillapp.com/settings/index\" target=\"_blank\">Mandrill Settings</a>"
176
+ msgstr "Para obtener tu Clave API, por favor visita tu <a href=\"http://mandrillapp.com/settings/index\" target=\"_blank\">Configuración Mandrill</a>"
177
+
178
+ #: wpmandrill.php:594
179
+ msgid "We are connected to your Mandrill Account."
180
+ msgstr "Estamos conectados a tu cuenta Mandrill."
181
+
182
+ #: wpmandrill.php:596
183
+ msgid "Sorry, invalid API key."
184
+ msgstr "Lo siento, Clave API inválida."
185
+
186
+ #: wpmandrill.php:612
187
+ msgid "No verified domains found."
188
+ msgstr "No se encontraros dominios verificados."
189
+
190
+ #: wpmandrill.php:624
191
+ msgid "This address will be used as the sender of the outgoing emails:"
192
+ msgstr "Esta dirección será utilizada como el remitente para los correos salientes:"
193
+
194
+ #: wpmandrill.php:630
195
+ msgid "Only verified domains are displayed here. If you need to verify a new domain, please visit your <a href=\"https://mandrillapp.com/settings/sending-domains\" target=\"_blank\">Mandrill Settings</a>"
196
+ msgstr "Aquí sólo se mostrarán dominios verificados. Si necesitas verificar un nuevo dominio, por favor visita tu <a href=\"https://mandrillapp.com/settings/sending-domains\" target=\"_blank\">Configuracipón Mandrill</a>"
197
+
198
+ #: wpmandrill.php:640
199
+ msgid "Name the recipients will see in their email clients:"
200
+ msgstr "Nombre que los destinatarios verán en sus clientes de correo:"
201
+
202
+ #: wpmandrill.php:651
203
+ #: wpmandrill.php:661
204
+ msgid "No templates found."
205
+ msgstr "No se encontraron plantillas."
206
+
207
+ #: wpmandrill.php:670
208
+ msgid "Select the template to use:"
209
+ msgstr "Seleccione la plantilla a utilizar:"
210
+
211
+ #: wpmandrill.php:676
212
+ msgid "<small>The selected template must have a <strong><em>mc:edit=\"main\"</em></strong> placeholder defined. The message will be shown there.</small>"
213
+ msgstr "<small>La plantilla seleccionada debe tener una sección <strong><em>mc:edit=\"main\"</em></strong> definida. El mensaje será mostrado ahí.</small>"
214
+
215
+ #: wpmandrill.php:686
216
+ msgid "If there are tags that you want appended to every call, list them here, one per line:"
217
+ msgstr "Si hay etiquetas que quieras agregar a cada llamada, lístalas aquí, una por línea."
218
+
219
+ #: wpmandrill.php:688
220
+ msgid "Also keep in mind that you can add or remove tags using the <em><a href=\"#\" onclick=\"jQuery('a#contextual-help-link').trigger('click');return false;\">mandrill_payload</a></em> WordPress filter."
221
+ msgstr "También recuerda que puedes agregar o eliminar etiquetas utilizando el filtro WordPress <em><a href=\"#\" onclick=\"jQuery('a#contextual-help-link').trigger('click');return false;\">mandrill_payload</a></em>."
222
+
223
+ #: wpmandrill.php:896
224
+ msgid "Mandrill Recent Statistics"
225
+ msgstr "Estadistas Recientes de Mandrill"
226
+
227
+ #: wpmandrill.php:918
228
+ #: wpmandrill.php:1134
229
+ #: stats.php:8
230
+ msgid "There was a problem retrieving statistics."
231
+ msgstr "Hubo un problema recuperando las estadísticas."
232
+
233
+ #: wpmandrill.php:976
234
+ #: wpmandrill.php:1231
235
+ msgid "Sending Volume"
236
+ msgstr "Volumen de Envío"
237
+
238
+ #: wpmandrill.php:977
239
+ #: wpmandrill.php:1232
240
+ msgid " emails"
241
+ msgstr " emails"
242
+
243
+ #: wpmandrill.php:978
244
+ #: wpmandrill.php:1233
245
+ msgid "Total Volume per Day"
246
+ msgstr "Volumen Total por Período"
247
+
248
+ #: wpmandrill.php:980
249
+ #: wpmandrill.php:1235
250
+ msgid "in the last few days"
251
+ msgstr "en los últimos días"
252
+
253
+ #: wpmandrill.php:981
254
+ #: wpmandrill.php:1236
255
+ msgid "in the last few months"
256
+ msgstr "en los últimos meses"
257
+
258
+ #: wpmandrill.php:982
259
+ #: wpmandrill.php:1237
260
+ msgid "Today"
261
+ msgstr "Hoy"
262
+
263
+ #: wpmandrill.php:983
264
+ #: wpmandrill.php:1238
265
+ msgid "Last 7 Days"
266
+ msgstr "Últimos 7 Días"
267
+
268
+ #: wpmandrill.php:984
269
+ #: wpmandrill.php:1239
270
+ msgid "Last 30 Days"
271
+ msgstr "Últimos 30 Días"
272
+
273
+ #: wpmandrill.php:985
274
+ #: wpmandrill.php:1240
275
+ msgid "Last 60 Days"
276
+ msgstr "Últimos 60 Días"
277
+
278
+ #: wpmandrill.php:986
279
+ #: wpmandrill.php:1241
280
+ msgid "Last 90 Days"
281
+ msgstr "Últimos 90 Días"
282
+
283
+ #: wpmandrill.php:987
284
+ #: wpmandrill.php:1242
285
+ msgid "Periods"
286
+ msgstr "Períodos"
287
+
288
+ #: wpmandrill.php:988
289
+ #: wpmandrill.php:1243
290
+ #: stats.php:29
291
+ msgid "Volume"
292
+ msgstr "Volumen"
293
+
294
+ #: wpmandrill.php:989
295
+ #: wpmandrill.php:1244
296
+ msgid "Total:"
297
+ msgstr "Cuota:"
298
+
299
+ #: wpmandrill.php:990
300
+ #: wpmandrill.php:1245
301
+ msgid "Unopened"
302
+ msgstr "No abiertos"
303
+
304
+ #: wpmandrill.php:991
305
+ #: wpmandrill.php:1246
306
+ msgid "Bounced or Rejected"
307
+ msgstr "Rebotes o Rechazos"
308
+
309
+ #: wpmandrill.php:992
310
+ #: wpmandrill.php:1247
311
+ msgid "Opened"
312
+ msgstr "Abiertos"
313
+
314
+ #: wpmandrill.php:995
315
+ #: wpmandrill.php:1250
316
+ msgid "Average Sending Volume"
317
+ msgstr "Volumen de Envío Promedio"
318
+
319
+ #: wpmandrill.php:996
320
+ #: wpmandrill.php:1251
321
+ msgid "/day"
322
+ msgstr "/día"
323
+
324
+ #: wpmandrill.php:997
325
+ #: wpmandrill.php:1252
326
+ msgid "Average Volume per Day"
327
+ msgstr "Volumen Promedio por Período"
328
+
329
+ #: wpmandrill.php:1163
330
+ #: stats.php:56
331
+ msgid "Filter by:"
332
+ msgstr "Filtrar por:"
333
+
334
+ #: wpmandrill.php:1165
335
+ #: stats.php:58
336
+ msgid "No filter"
337
+ msgstr "Sin Filtro"
338
+
339
+ #: wpmandrill.php:1166
340
+ #: stats.php:59
341
+ msgid "Sender:"
342
+ msgstr "Remitente:"
343
+
344
+ #: wpmandrill.php:1173
345
+ #: stats.php:66
346
+ msgid "Tag:"
347
+ msgstr "Etiqueta:"
348
+
349
+ #: wpmandrill.php:1181
350
+ #: stats.php:74
351
+ msgid "Display:"
352
+ msgstr "Mostrar:"
353
+
354
+ #: wpmandrill.php:1183
355
+ #: stats.php:76
356
+ msgid "Total Volume per Period"
357
+ msgstr "Volumen Total por Período"
358
+
359
+ #: wpmandrill.php:1184
360
+ #: stats.php:77
361
+ msgid "Average Volume per Period"
362
+ msgstr "Volumen Promedio por Período"
363
+
364
+ #: wpmandrilltest.php:44
365
+ msgid "Mandrill: How to tell WordPress to use wpMandrill."
366
+ msgstr "Mandrill: ¿Cómo decirle a WordPress que utilice wpMandrill?"
367
+
368
+ #: wpmandrilltest.php:47
369
+ msgid "Mandrill: How to send a regular email."
370
+ msgstr "Mandrill: ¿Cómo enviar un correo normal?"
371
+
372
+ #: wpmandrilltest.php:50
373
+ msgid "Mandrill: How to modify a certain email using the <em>mandrill_payload</em> WordPress filter."
374
+ msgstr "Mandrill: ¿Cómo modificar un correo determinado utilizando el filtro WordPress <em>mandrill_payload</em>?"
375
+
376
+ #: wpmandrilltest.php:53
377
+ msgid "Mandrill: How to send emails from within your plugins."
378
+ msgstr "Mandrill: ¿Cómo enviar correo desde tus plugins?"
379
+
380
+ #: wpmandrilltest.php:60
381
+ msgid "Simply install wpMandrill and configure it to make it handle all the email functions of your WordPress installation."
382
+ msgstr "Simplemente instala wpMandrill y configúralo, para hacer que este maneje todas las funciones de correo electrónico en tu instalación WordPress."
383
+
384
+ #: wpmandrilltest.php:61
385
+ msgid "Once it has been properly configured, it will replace the regular WordPress emailing processes, so it's basically transparent for you and for WordPress."
386
+ msgstr "Una vez que este ha sido correctamente configurado, este reemplazará los procesos regulares de envío de correo electrónico de WordPress, así que basicamente será transparente tanto para WordPress como para tí."
387
+
388
+ #: wpmandrilltest.php:62
389
+ msgid "To test wpMandrill, log out, and try to use the <em>Forgot your password?</em> feature in WordPress (you don't need to reset your password though. Just check the headers of the email that it sends you, and you'll see that it comes from Mandrill's servers)."
390
+ msgstr "Para probar wpMandrill, desconéctate de WordPress y utiliza la opción <em>¿Olvidáste tu Clave?</em> de WordPress (no necesitas eliminar tu clave actual, sólo revisa el correo que recibas y verás que fue enviado desde los servidores de Mandrill)."
391
+
392
+ #: wpmandrilltest.php:70
393
+ msgid "If you're a Plugin Developer, and you need to send a regular email using wpMandrill, you don't need to learn anything else. You can use the good ol' <strong>wp_mail</strong> function, as you would normally do if you were not using this plugin."
394
+ msgstr "Si eres un desarrollador de plugins, y necesitas enviar un correo regular utilizando wpMandrill, no necesitarás aprender nada adicional. Puedes usar la conocida funcion <strong>wp_mail</strong> que normalmente utilizarías si no estuvieses utilizando este plugin."
395
+
396
+ #: wpmandrilltest.php:71
397
+ msgid "For example:"
398
+ msgstr "Por ejemplo:"
399
+
400
+ #: wpmandrilltest.php:72
401
+ msgid "&lt;?php wp_mail('your@address.com', 'Your subject', 'Your message'); ?&gt;"
402
+ msgstr "&lt;?php wp_mail('tu@direccion.com', 'Tu Asunto', 'Tu mensaje'); ?&gt;"
403
+
404
+ #: wpmandrilltest.php:80
405
+ msgid "if you need to fine tune one or some of the emails sent through your WordPress installation, you will need to use the <em>mandrill_payload</em> filter."
406
+ msgstr "Si necesitas hacer ajustes particulares a uno a varios correos enviados a través de tu instalación WordPress, necesitarás usar el filtro <em>mandrill_payload</em>."
407
+
408
+ #: wpmandrilltest.php:81
409
+ msgid "To use it, you must create a function that analyzes the payload that is about to be sent to Mandrill, and modify it based on your requirements. Then you'll need to add this function as the callback of the mentioned filter, using the <em>add_filter</em> WordPress call. And finally, insert it into your theme's functions.php file or you own plugin's file."
410
+ msgstr "Para usarlo, debes crear una función que analice el payload que Mandrill está a punto de enviar, y modificarlo basado en tus requerimiento. Luego, necesitarás agregar esta función como el callback del filtro antes mencionado, utilizando la función de Wordpress <em>add_filter</em>. Finalmente, insertar ese código en el archivo functions.php de tu tema o en tu propio plugin."
411
+
412
+ #: wpmandrilltest.php:82
413
+ msgid "You can use the following code as an skeleton for your own callbacks:"
414
+ msgstr "Puedes utilizar el siguiente código como el esqueleto de tus propias llamadas."
415
+
416
+ #: wpmandrilltest.php:96
417
+ msgid "Let's say you're using the <a href=\"http://wordpress.org/extend/plugins/cart66-lite/\" target=\"_blank\">Cart66 Lite Ecommerce plugin</a> and you want to modify the emails sent from this plugin. Here's what you should do:"
418
+ msgstr "Asi que digamos que estás utilizando el <a href=\"http://wordpress.org/extend/plugins/cart66-lite/\" target=\"_blank\">plugin de Ecommerce Cart66 Lite</a> y quieres modificar los correos enviados desde este plugin. Aquí está lo que deberías hacer:"
419
+
420
+ #: wpmandrilltest.php:124
421
+ msgid "If you are a Plugin Developer and you need to create a deep integration between Mandrill and your WordPress installation, wpMandrill will make your life easier."
422
+ msgstr "Si eres un desarrollador de plugins y necesitas crear una integración más produnda entre Mandrill y tu instalación WordPress, wpMandrill te hará la vida más fácil."
423
+
424
+ #: wpmandrilltest.php:125
425
+ msgid "We have exposed a simple function that allows you to add tags and specify the template to use, in addition to specifying the To, Subject and Body sections of the email:"
426
+ msgstr "Hemos creado una simple función que te permite agregarle etiquetas y la plantilla a utilizar además de los campos Para, Asunto y Cuerpo de tu mensaje:"
427
+
428
+ #: wpmandrilltest.php:126
429
+ msgid "&lt;?php wpMandrill::mail($to, $subject, $html, $headers = '', $attachments = array(), $tags = array(), $from_name = '', $from_email = '', $template_name = ''); ?&gt;"
430
+ msgstr "&lt;?php wpMandrill::mail($para, $asunto, $html, $cabeceras = '', $adjuntos = array(), $etiquetas = array(), $campo_nombre = '', $campo_correo = '', $nombre_plantilla = ''); ?&gt;"
431
+
432
+ #: wpmandrilltest.php:127
433
+ msgid "But if you need Mandrill Powers, we have included a full-featured PHP class called Mandrill. It has every API call defined in Mandrill's API. Check it out at <em>/wp-content/plugin/wpmandrill/lib/mandrill.class.php</em>."
434
+ msgstr "Pero si necesitas Poderes de Mandrill, hemos incluido una clase PHP con todas las llamadas de la API de Mandrill incluidas, llamada Mandrill. Echale un vistazo en <em>/wp-content/plugin/wpmandrill/lib/mandrill.class.php</em>."
435
+
436
+ #: wpmandrilltest.php:128
437
+ msgid "To use it, just instanciate an object passing your API key, and make the calls:"
438
+ msgstr "Para usarla, simplemente instancia un objeto pasándole una Clave API y haz tus llamadas:"
439
+
440
+ #: wpmandrilltest.php:129
441
+ msgid "&lt;?php $mandrill = Mandrill($my_api_key); echo $mandrill->ping(); ?&gt;"
442
+ msgstr "&lt;?php $mandrill = Mandrill($my_api_key); echo $mandrill->ping(); ?&gt;"
443
+
444
+ #: wpmandrilltest.php:139
445
+ msgid "Mandrill How-Tos"
446
+ msgstr "Mandrill: ¿Cómo hago?"
447
+
448
+ #: wpmandrilltest.php:139
449
+ msgid "Mandrill Test"
450
+ msgstr "Prueba Mandrill"
451
+
452
+ #: wpmandrilltest.php:149
453
+ msgid "The purpose of this plugin is to show you how easy it is to start using the awesome platform that Mandrill offers to handle your transactional emails."
454
+ msgstr "El objeto de este plugin es mostrarte cuan fácil es es comenzar a utilizar la plataforma que Mandrill ofrece para manejar tus correos transaccionales."
455
+
456
+ #: wpmandrilltest.php:151
457
+ msgid "Just by setting it up, all the emails sent from your WordPress installation will be sent using the power of Mandrill."
458
+ msgstr "Sólo con configurarlo, todos los correos enviados desde tu instalación WordPress serán enviados utilizando el poder de Mandrill."
459
+
460
+ #: wpmandrilltest.php:152
461
+ msgid "If you want further customization, you can use the <strong>mandrill_payload</strong> filter we've provided."
462
+ msgstr "Si necesitas mayor personalización, puedes utilizar el filtro <strong>mandrill_payload</strong> que hemos provisto para ti."
463
+
464
+ #: wpmandrilltest.php:153
465
+ msgid "And if you want an even greater integration between your application and Mandrill, we've created a convenient call to send emails from within your plugins."
466
+ msgstr "Y si quieres una integración aún mayor entre tu aplicación y Mandrill, hemos creado una sencilla función para el envío de correos desde tus plugins."
467
+
468
+ #: wpmandrilltest.php:155
469
+ msgid "You can learn more about all of these features right from this page."
470
+ msgstr "Puedes conocer como usar cada una de estas características desde esta página."
471
+
472
+ #: wpmandrilltest.php:194
473
+ msgid "Mandrill How-tos"
474
+ msgstr "Mandrill: ¿Cómo hago?"
475
+
476
+ #: stats.php:4
477
+ msgid "Mandrill Service Report"
478
+ msgstr "Reporte del Servicio Mandrill"
479
+
480
+ #: stats.php:20
481
+ msgid "Hourly Sending Volume and Open/Click Rate"
482
+ msgstr "Volumen de Envío y Tasa de Apertura y Cliqueo Por Horas"
483
+
484
+ #: stats.php:21
485
+ msgid "Daily Sending Volume and Open/Click Rate"
486
+ msgstr "Volumen de Envío y Tasa de Apertura y Cliqueo Diario"
487
+
488
+ #: stats.php:22
489
+ msgid "Hours"
490
+ msgstr "Horas"
491
+
492
+ #: stats.php:23
493
+ msgid "Days"
494
+ msgstr "Días"
495
+
496
+ #: stats.php:24
497
+ msgid "Hour"
498
+ msgstr "Hora"
499
+
500
+ #: stats.php:25
501
+ msgid "Day"
502
+ msgstr "Día"
503
+
504
+ #: stats.php:27
505
+ msgid "in the last 30 days"
506
+ msgstr "en los últimos 30 días"
507
+
508
+ #: stats.php:28
509
+ msgid "Open & Click Rate"
510
+ msgstr "Tasa de Apertura y Cliqueo"
511
+
512
+ #: stats.php:30
513
+ msgid "emails"
514
+ msgstr "emails"
515
+
516
+ #: stats.php:31
517
+ msgid "Open Rate"
518
+ msgstr "Tasa de Apertura"
519
+
520
+ #: stats.php:32
521
+ msgid "Click Rate"
522
+ msgstr "Tasa de Cliqueo"
523
+
524
+ #: stats.php:36
525
+ #, php-format
526
+ msgid "All-time statistics since %s: "
527
+ msgstr "Estadísticas desde %s:"
528
+
529
+ #: stats.php:39
530
+ msgid "Reputation:"
531
+ msgstr "Reputación:"
532
+
533
+ #: stats.php:40
534
+ msgid "Quota:"
535
+ msgstr "Cuota:"
536
+
537
+ #: stats.php:40
538
+ msgid "sends/hour"
539
+ msgstr "envíos/hora"
540
+
541
+ #: stats.php:41
542
+ msgid "Emails sent:"
543
+ msgstr "Correos enviados:"
544
+
545
+ #: stats.php:42
546
+ msgid "Emails delivered:"
547
+ msgstr "Correos entregados:"
548
+
549
+ #: stats.php:43
550
+ msgid "Tracked opens:"
551
+ msgstr "Aperturas registradas:"
552
+
553
+ #: stats.php:44
554
+ msgid "Tracked clicks:"
555
+ msgstr "Clicks registrados:"
556
+
557
+ #: stats.php:46
558
+ msgid "Rejects:"
559
+ msgstr "Rechazos:"
560
+
561
+ #: stats.php:47
562
+ msgid "Complaints:"
563
+ msgstr "Quejas:"
564
+
565
+ #: stats.php:48
566
+ msgid "Current backlog:"
567
+ msgstr "Backlog actual:"
568
+
569
+ #: stats.php:55
570
+ msgid "Filtered statistics:"
571
+ msgstr "Estadísticas filtradas:"
572
+
573
+ #: stats.php:352
574
+ msgid "For more detailed statistics, please visit your Mandrill Dashboard"
575
+ msgstr "Para estadísticas más detalladas, por favor visita tu Tablero Mandrill"
576
+
577
+ #~ msgid "Testing Arena for Mandrill"
578
+ #~ msgstr "Caja de Arena de wpMandrill"
579
+ #~ msgid "Mandrill Report"
580
+ #~ msgstr "Reporte Mandrill"
581
+
legacy/function.wp_mail.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Compact the input, apply the filters, and extract them back out
3
+ extract( apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers', 'attachments' ) ) );
4
+
5
+ if ( !is_array($attachments) )
6
+ $attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
7
+
8
+ global $phpmailer;
9
+
10
+ // (Re)create it, if it's gone missing
11
+ if ( !is_object( $phpmailer ) || !is_a( $phpmailer, 'PHPMailer' ) ) {
12
+ require_once ABSPATH . WPINC . '/class-phpmailer.php';
13
+ require_once ABSPATH . WPINC . '/class-smtp.php';
14
+ $phpmailer = new PHPMailer();
15
+ }
16
+
17
+ // Headers
18
+ if ( empty( $headers ) ) {
19
+ $headers = array();
20
+ } else {
21
+ if ( !is_array( $headers ) ) {
22
+ // Explode the headers out, so this function can take both
23
+ // string headers and an array of headers.
24
+ $tempheaders = explode( "\n", str_replace( "\r\n", "\n", $headers ) );
25
+ } else {
26
+ $tempheaders = $headers;
27
+ }
28
+ $headers = array();
29
+
30
+ // If it's actually got contents
31
+ if ( !empty( $tempheaders ) ) {
32
+ // Iterate through the raw headers
33
+ foreach ( (array) $tempheaders as $header ) {
34
+ if ( strpos($header, ':') === false ) {
35
+ if ( false !== stripos( $header, 'boundary=' ) ) {
36
+ $parts = preg_split('/boundary=/i', trim( $header ) );
37
+ $boundary = trim( str_replace( array( "'", '"' ), '', $parts[1] ) );
38
+ }
39
+ continue;
40
+ }
41
+ // Explode them out
42
+ list( $name, $content ) = explode( ':', trim( $header ), 2 );
43
+
44
+ // Cleanup crew
45
+ $name = trim( $name );
46
+ $content = trim( $content );
47
+
48
+ switch ( strtolower( $name ) ) {
49
+ // Mainly for legacy -- process a From: header if it's there
50
+ case 'from':
51
+ if ( strpos($content, '<' ) !== false ) {
52
+ // So... making my life hard again?
53
+ $from_name = substr( $content, 0, strpos( $content, '<' ) - 1 );
54
+ $from_name = str_replace( '"', '', $from_name );
55
+ $from_name = trim( $from_name );
56
+
57
+ $from_email = substr( $content, strpos( $content, '<' ) + 1 );
58
+ $from_email = str_replace( '>', '', $from_email );
59
+ $from_email = trim( $from_email );
60
+ } else {
61
+ $from_email = trim( $content );
62
+ }
63
+ break;
64
+ case 'content-type':
65
+ if ( strpos( $content, ';' ) !== false ) {
66
+ list( $type, $charset ) = explode( ';', $content );
67
+ $content_type = trim( $type );
68
+ if ( false !== stripos( $charset, 'charset=' ) ) {
69
+ $charset = trim( str_replace( array( 'charset=', '"' ), '', $charset ) );
70
+ } elseif ( false !== stripos( $charset, 'boundary=' ) ) {
71
+ $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset ) );
72
+ $charset = '';
73
+ }
74
+ } else {
75
+ $content_type = trim( $content );
76
+ }
77
+ break;
78
+ case 'cc':
79
+ $cc = array_merge( (array) $cc, explode( ',', $content ) );
80
+ break;
81
+ case 'bcc':
82
+ $bcc = array_merge( (array) $bcc, explode( ',', $content ) );
83
+ break;
84
+ default:
85
+ // Add it to our grand headers array
86
+ $headers[trim( $name )] = trim( $content );
87
+ break;
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ // Empty out the values that may be set
94
+ $phpmailer->ClearAddresses();
95
+ $phpmailer->ClearAllRecipients();
96
+ $phpmailer->ClearAttachments();
97
+ $phpmailer->ClearBCCs();
98
+ $phpmailer->ClearCCs();
99
+ $phpmailer->ClearCustomHeaders();
100
+ $phpmailer->ClearReplyTos();
101
+
102
+ // From email and name
103
+ // If we don't have a name from the input headers
104
+ if ( !isset( $from_name ) )
105
+ $from_name = 'WordPress';
106
+
107
+ /* If we don't have an email from the input headers default to wordpress@$sitename
108
+ * Some hosts will block outgoing mail from this address if it doesn't exist but
109
+ * there's no easy alternative. Defaulting to admin_email might appear to be another
110
+ * option but some hosts may refuse to relay mail from an unknown domain. See
111
+ * http://trac.wordpress.org/ticket/5007.
112
+ */
113
+
114
+ if ( !isset( $from_email ) ) {
115
+ // Get the site domain and get rid of www.
116
+ $sitename = strtolower( $_SERVER['SERVER_NAME'] );
117
+ if ( substr( $sitename, 0, 4 ) == 'www.' ) {
118
+ $sitename = substr( $sitename, 4 );
119
+ }
120
+
121
+ $from_email = 'wordpress@' . $sitename;
122
+ }
123
+
124
+ // Plugin authors can override the potentially troublesome default
125
+ $phpmailer->From = apply_filters( 'wp_mail_from' , $from_email );
126
+ $phpmailer->FromName = apply_filters( 'wp_mail_from_name', $from_name );
127
+
128
+ // Set destination addresses
129
+ if ( !is_array( $to ) )
130
+ $to = explode( ',', $to );
131
+
132
+ foreach ( (array) $to as $recipient ) {
133
+ $phpmailer->AddAddress( trim( $recipient ) );
134
+ }
135
+
136
+ // Set mail's subject and body
137
+ $phpmailer->Subject = $subject;
138
+ $phpmailer->Body = $message;
139
+
140
+ // Add any CC and BCC recipients
141
+ if ( !empty( $cc ) ) {
142
+ foreach ( (array) $cc as $recipient ) {
143
+ $phpmailer->AddCc( trim($recipient) );
144
+ }
145
+ }
146
+
147
+ if ( !empty( $bcc ) ) {
148
+ foreach ( (array) $bcc as $recipient) {
149
+ $phpmailer->AddBcc( trim($recipient) );
150
+ }
151
+ }
152
+
153
+ // Set to use PHP's mail()
154
+ $phpmailer->IsMail();
155
+
156
+ // Set Content-Type and charset
157
+ // If we don't have a content-type from the input headers
158
+ if ( !isset( $content_type ) )
159
+ $content_type = 'text/plain';
160
+
161
+ $content_type = apply_filters( 'wp_mail_content_type', $content_type );
162
+
163
+ $phpmailer->ContentType = $content_type;
164
+
165
+ // Set whether it's plaintext, depending on $content_type
166
+ if ( 'text/html' == $content_type )
167
+ $phpmailer->IsHTML( true );
168
+
169
+ // If we don't have a charset from the input headers
170
+ if ( !isset( $charset ) )
171
+ $charset = get_bloginfo( 'charset' );
172
+
173
+ // Set the content-type and charset
174
+ $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
175
+
176
+ // Set custom headers
177
+ if ( !empty( $headers ) ) {
178
+ foreach( (array) $headers as $name => $content ) {
179
+ $phpmailer->AddCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
180
+ }
181
+
182
+ if ( false !== stripos( $content_type, 'multipart' ) && ! empty($boundary) )
183
+ $phpmailer->AddCustomHeader( sprintf( "Content-Type: %s;\n\t boundary=\"%s\"", $content_type, $boundary ) );
184
+ }
185
+
186
+ if ( !empty( $attachments ) ) {
187
+ foreach ( $attachments as $attachment ) {
188
+ $phpmailer->AddAttachment($attachment);
189
+ }
190
+ }
191
+
192
+ do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) );
193
+
194
+ // Send!
195
+ $result = @$phpmailer->Send();
196
+
197
+ return $result;
198
+ ?>
lib/mandrill.class.php ADDED
@@ -0,0 +1,483 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Mandrill_Exception extends Exception {
4
+ }
5
+
6
+ class Mandrill {
7
+ const API_VERSION = '1.0';
8
+ const END_POINT = 'https://mandrillapp.com/api/';
9
+
10
+ var $api;
11
+
12
+ function __construct($api) {
13
+ if ( empty($api) ) throw new Mandrill_Exception('Invalid API key');
14
+ try {
15
+
16
+ $response = $this->request('users/ping', array( 'key' => $api ) );
17
+ if ( $response != 'PONG!' ) throw new Mandrill_Exception('Invalid API key');
18
+
19
+ $this->api = $api;
20
+
21
+ } catch ( Exception $e ) {
22
+ throw new Mandrill_Exception($e->getMessage());
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Work horse. Every API call use this function to actually make the request to Mandrill's servers.
28
+ *
29
+ * @link https://mandrillapp.com/api/docs/
30
+ *
31
+ * @param string $method API method name
32
+ * @param array $args query arguments
33
+ * @param string $http GET or POST request type
34
+ * @param string $output API response format (json,php,xml,yaml). json and xml are decoded into arrays automatically.
35
+ * @return array|string|Mandrill_Exception
36
+ */
37
+ function request($method, $args = array(), $http = 'POST', $output = 'json') {
38
+ if( !isset($args['key']) )
39
+ $args['key'] = $this->api;
40
+
41
+ $api_version = self::API_VERSION;
42
+ $dot_output = ('json' == $output) ? '' : ".{$output}";
43
+
44
+ $url = self::END_POINT . "{$api_version}/{$method}{$dot_output}";
45
+
46
+ switch ($http) {
47
+
48
+ case 'GET':
49
+
50
+ $url .= '?' . http_build_query($args);
51
+ $response = $this->http_request($url, array(),'GET');
52
+ break;
53
+
54
+ case 'POST':
55
+ $response = $this->http_request($url, $args, 'POST');
56
+ break;
57
+
58
+ default:
59
+
60
+ return new Mandrill_Exception('Unknown request type');
61
+ break;
62
+ }
63
+
64
+ $response_code = $response['header']['http_code'];
65
+ $body = $response['body'];
66
+
67
+ switch ($output) {
68
+
69
+ case 'json':
70
+
71
+ $body = json_decode($body, true);
72
+ break;
73
+
74
+ case 'php':
75
+
76
+ $body = unserialize($body);
77
+ break;
78
+ }
79
+
80
+ if( 200 == $response_code ) {
81
+
82
+ return $body;
83
+ }
84
+ else {
85
+
86
+ $message = isset( $body['message'] ) ? $body['message'] : '' ;
87
+
88
+ return new Mandrill_Exception($message . ' - ' . $body, $response_code);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * @link https://mandrillapp.com/api/docs/users.html#method=ping
94
+ *
95
+ * @return array|Mandrill_Exception
96
+ */
97
+ function users_ping() {
98
+
99
+ return $this->request('users/ping');
100
+ }
101
+
102
+ /**
103
+ * @link https://mandrillapp.com/api/docs/users.html#method=info
104
+ *
105
+ * @return array|Mandrill_Exception
106
+ */
107
+ function users_info() {
108
+
109
+ return $this->request('users/info');
110
+ }
111
+
112
+ /**
113
+ * @link https://mandrillapp.com/api/docs/users.html#method=senders
114
+ *
115
+ * @return array|Mandrill_Exception
116
+ */
117
+ function users_senders() {
118
+
119
+ return $this->request('users/senders');
120
+ }
121
+
122
+ /**
123
+ * @link https://mandrillapp.com/api/docs/users.html#method=disable-sender
124
+ *
125
+ * @return array|Mandrill_Exception
126
+ */
127
+ function users_disable_sender($domain) {
128
+
129
+ return $this->request('users/disable-senders', array('domain' => $domain) );
130
+ }
131
+
132
+ /**
133
+ * @link https://mandrillapp.com/api/docs/users.html#method=verify-sender
134
+ *
135
+ * @return array|Mandrill_Exception
136
+ */
137
+ function users_verify_sender($email) {
138
+
139
+ return $this->request('users/verify-senders', array('domain' => $email) );
140
+ }
141
+
142
+ /**
143
+ * @link https://mandrillapp.com/api/docs/senders.html#method=domains
144
+ *
145
+ * @return array|Mandrill_Exception
146
+ */
147
+ function senders_domains() {
148
+
149
+ return $this->request('senders/domains');
150
+ }
151
+
152
+ /**
153
+ * @link https://mandrillapp.com/api/docs/senders.html#method=list
154
+ *
155
+ * @return array|Mandrill_Exception
156
+ */
157
+ function senders_list() {
158
+
159
+ return $this->request('senders/list');
160
+ }
161
+
162
+ /**
163
+ * @link https://mandrillapp.com/api/docs/senders.html#method=info
164
+ *
165
+ * @return array|Mandrill_Exception
166
+ */
167
+ function senders_info($email) {
168
+
169
+ return $this->request('senders/info', array( 'address' => $email) );
170
+ }
171
+
172
+ /**
173
+ * @link https://mandrillapp.com/api/docs/senders.html#method=time-series
174
+ *
175
+ * @return array|Mandrill_Exception
176
+ */
177
+ function senders_time_series($email) {
178
+
179
+ return $this->request('senders/time-series', array( 'address' => $email) );
180
+ }
181
+
182
+ /**
183
+ * @link https://mandrillapp.com/api/docs/tags.html#method=list
184
+ *
185
+ * @return array|Mandrill_Exception
186
+ */
187
+ function tags_list() {
188
+
189
+ return $this->request('tags/list');
190
+ }
191
+
192
+ /**
193
+ * @link https://mandrillapp.com/api/docs/tags.html#method=info
194
+ *
195
+ * @return array|Mandrill_Exception
196
+ */
197
+ function tags_info($tag) {
198
+
199
+ return $this->request('tags/info', array( 'tag' => $tag) );
200
+ }
201
+
202
+ /**
203
+ * @link https://mandrillapp.com/api/docs/tags.html#method=time-series
204
+ *
205
+ * @return array|Mandrill_Exception
206
+ */
207
+ function tags_time_series($tag) {
208
+
209
+ return $this->request('tags/time-series', array( 'tag' => $tag) );
210
+ }
211
+
212
+ /**
213
+ * @link https://mandrillapp.com/api/docs/tags.html#method=all-time-series
214
+ *
215
+ * @return array|Mandrill_Exception
216
+ */
217
+ function tags_all_time_series() {
218
+
219
+ return $this->request('tags/all-time-series');
220
+ }
221
+
222
+ /**
223
+ * @link https://mandrillapp.com/api/docs/templates.html#method=add
224
+ *
225
+ * @return array|Mandrill_Exception
226
+ */
227
+ function templates_add($name, $code) {
228
+
229
+ return $this->request('templates/add', array('name' => $name, 'code' => $code) );
230
+ }
231
+
232
+ /**
233
+ * @link https://mandrillapp.com/api/docs/templates.html#method=update
234
+ *
235
+ * @return array|Mandrill_Exception
236
+ */
237
+ function templates_update($name, $code) {
238
+
239
+ return $this->request('templates/update', array('name' => $name, 'code' => $code) );
240
+ }
241
+
242
+ /**
243
+ * @link https://mandrillapp.com/api/docs/templates.html#method=delete
244
+ *
245
+ * @return array|Mandrill_Exception
246
+ */
247
+ function templates_delete($name) {
248
+
249
+ return $this->request('templates/delete', array('name' => $name) );
250
+ }
251
+
252
+ /**
253
+ * @link https://mandrillapp.com/api/docs/templates.html#method=info
254
+ *
255
+ * @return array|Mandrill_Exception
256
+ */
257
+ function templates_info($name) {
258
+
259
+ return $this->request('templates/info', array('name' => $name) );
260
+ }
261
+
262
+ /**
263
+ * @link https://mandrillapp.com/api/docs/templates.html#method=list
264
+ *
265
+ * @return array|Mandrill_Exception
266
+ */
267
+ function templates_list() {
268
+
269
+ return $this->request('templates/list');
270
+ }
271
+
272
+ /**
273
+ * @link https://mandrillapp.com/api/docs/templates.html#method=time-series
274
+ *
275
+ * @return array|Mandrill_Exception
276
+ */
277
+ function templates_time_series($name) {
278
+
279
+ return $this->request('templates/time-series', array('name' => $name) );
280
+ }
281
+
282
+ /**
283
+ * @link https://mandrillapp.com/api/docs/urls.html#method=list
284
+ *
285
+ * @return array|Mandrill_Exception
286
+ */
287
+ function urls_list() {
288
+
289
+ return $this->request('urls/list');
290
+ }
291
+
292
+ /**
293
+ * @link https://mandrillapp.com/api/docs/urls.html#method=time-series
294
+ *
295
+ * @return array|Mandrill_Exception
296
+ */
297
+ function urls_time_series($name) {
298
+
299
+ return $this->request('urls/time-series', array('name' => $name) );
300
+ }
301
+
302
+ /**
303
+ * @link https://mandrillapp.com/api/docs/urls.html#method=search
304
+ *
305
+ * @return array|Mandrill_Exception
306
+ */
307
+ function urls_search($q) {
308
+
309
+ return $this->request('urls/search', array('q' => $q) );
310
+ }
311
+
312
+ /**
313
+ * @link https://mandrillapp.com/api/docs/webhooks.html#method=add
314
+ *
315
+ * @return array|Mandrill_Exception
316
+ */
317
+ function webhooks_add($url, $events) {
318
+
319
+ return $this->request('webhooks/add', array('url' => $url, 'events' => $events) );
320
+ }
321
+
322
+ /**
323
+ * @link https://mandrillapp.com/api/docs/webhooks.html#method=update
324
+ *
325
+ * @return array|Mandrill_Exception
326
+ */
327
+ function webhooks_update($url, $events) {
328
+
329
+ return $this->request('webhooks/update', array('url' => $url, 'events' => $events) );
330
+ }
331
+
332
+ /**
333
+ * @link https://mandrillapp.com/api/docs/webhooks.html#method=delete
334
+ *
335
+ * @return array|Mandrill_Exception
336
+ */
337
+ function webhooks_delete($id) {
338
+
339
+ return $this->request('webhooks/delete', array('id' => $id) );
340
+ }
341
+
342
+ /**
343
+ * @link https://mandrillapp.com/api/docs/webhooks.html#method=info
344
+ *
345
+ * @return array|Mandrill_Exception
346
+ */
347
+ function webhooks_info($id) {
348
+
349
+ return $this->request('webhooks/info', array('id' => $id) );
350
+ }
351
+
352
+ /**
353
+ * @link https://mandrillapp.com/api/docs/webhooks.html#method=list
354
+ *
355
+ * @return array|Mandrill_Exception
356
+ */
357
+ function webhooks_list() {
358
+ return $this->request('webhooks/list');
359
+ }
360
+
361
+ /**
362
+ * @link https://mandrillapp.com/api/docs/messages.html#method=search
363
+ *
364
+ * @return array|Mandrill_Exception
365
+ */
366
+ function messages_search($query, $date_from = '', $date_to = '', $tags = array(), $senders = array(), $limit = 100) {
367
+ return $this->request('messages/search', compact('query', 'date_from', 'date_to', 'tags', 'senders', 'limit'));
368
+ }
369
+
370
+ /**
371
+ * @link https://mandrillapp.com/api/docs/messages.html#method=send
372
+ *
373
+ * @return array|Mandrill_Exception
374
+ */
375
+ function messages_send($message) {
376
+ return $this->request('messages/send', array('message' => $message) );
377
+ }
378
+
379
+ /**
380
+ * @link https://mandrillapp.com/api/docs/messages.html#method=send-template
381
+ *
382
+ * @return array|Mandrill_Exception
383
+ */
384
+ function messages_send_template($template_name, $template_content, $message) {
385
+ return $this->request('messages/send-template', compact('template_name', 'template_content','message') );
386
+ }
387
+
388
+ function http_request($url, $fields = array(), $method = 'POST') {
389
+ if( !ini_get('safe_mode') ){
390
+ set_time_limit(60 * 60);
391
+ }
392
+
393
+ if ( !in_array( $method, array('POST','GET') ) ) $method = 'POST';
394
+ if ( !isset( $fields['key']) ) $fields['key'] = $this->api;
395
+
396
+ $ch = curl_init();
397
+ curl_setopt($ch, CURLOPT_URL, $url);
398
+
399
+ curl_setopt($ch, CURLOPT_POST, $method == 'POST');
400
+
401
+ curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($fields) ? http_build_query($fields) : $fields);
402
+
403
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
404
+ curl_setopt($ch, CURLOPT_HEADER, false);
405
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
406
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60 * 60 * 1000);
407
+
408
+ $response = curl_exec($ch);
409
+ $info = curl_getinfo($ch);
410
+ $error = curl_error($ch);
411
+
412
+ curl_close($ch);
413
+
414
+ return array('header' => $info, 'body' => $response, 'error' => $error);
415
+ }
416
+
417
+ static function getAttachmentStruct($path) {
418
+
419
+ $struct = array();
420
+
421
+ try {
422
+
423
+ if ( !@is_file($path) ) throw new Exception($path.' is not a valid file.');
424
+
425
+ $filename = basename($path);
426
+
427
+ if ( !function_exists('get_magic_quotes') ) {
428
+ function get_magic_quotes() { return false; }
429
+ }
430
+ if ( !function_exists('st_magic_quotes') ) {
431
+ function set_magic_quotes($value) { return true;}
432
+ }
433
+
434
+ if (strnatcmp(phpversion(),'6') >= 0) {
435
+ $magic_quotes = get_magic_quotes_runtime();
436
+ set_magic_quotes_runtime(0);
437
+ }
438
+
439
+ $file_buffer = file_get_contents($path);
440
+ $file_buffer = chunk_split(base64_encode($file_buffer), 76, "\n");
441
+
442
+ if (strnatcmp(phpversion(),'6') >= 0) set_magic_quotes_runtime($magic_quotes);
443
+
444
+ if (strnatcmp(phpversion(),'5.3') >= 0) {
445
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
446
+ $mime_type = finfo_file($finfo, $path);
447
+ } else {
448
+ $mime_type = mime_content_type($path);
449
+ }
450
+
451
+ if ( !Mandrill::isValidContentType($mime_type) )
452
+ throw new Exception($mime_type.' is not a valid content type (it should be '.implode('*,', self::getValidContentTypes() ).').');
453
+
454
+ $struct['type'] = $mime_type;
455
+ $struct['name'] = $filename;
456
+ $struct['content'] = $file_buffer;
457
+
458
+ } catch (Exception $e) {
459
+ throw new Mandrill_Exception('Error creating the attachment structure: '.$e->getMessage());
460
+ }
461
+
462
+ return $struct;
463
+ }
464
+
465
+ static function isValidContentType($ct) {
466
+ $valids = self::getValidContentTypes();
467
+
468
+ foreach ( $valids as $vct ) {
469
+ if ( strpos($ct, $vct) !== false ) return true;
470
+ }
471
+
472
+ return false;
473
+ }
474
+
475
+ static function getValidContentTypes() {
476
+ return array(
477
+ 'image/',
478
+ 'text/',
479
+ 'application/pdf',
480
+ );
481
+ }
482
+ }
483
+ ?>
readme.txt ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === wpMandrill ===
2
+ Contributors: MC_Will
3
+ Tags: mandrill, mailchimp, transactional email, email, email reliability, smtp, wp_mail, email templates
4
+ Requires at least: 3.0
5
+ Tested up to: 3.3.2
6
+ Stable tag: trunk
7
+
8
+ The wpMandrill plugin sends emails that are generated by WordPress through Mandrill, a transactional email service powered by MailChimp.
9
+
10
+ == Description ==
11
+
12
+ This plugin uses [Mandrill API](http://mandrillapp.com/api/docs/) to send outgoing emails from your Wordpress installation. It replaces the wp_mail function included with WordPress.
13
+
14
+ Emails are tracked and automatically tagged for statistics within the Mandrill Dashboard. You can also add general tags to every email sent, as well as particular tags based on selected emails defined by your requirements.
15
+
16
+ You can send certain types of attachments (image/*, text/* and application/pdf).
17
+
18
+ You can also use your own templates that have been added to your MailChimp account and shared with your Mandrill account.
19
+
20
+ There are a few levels of integrations between your WordPress installation and this plugin:
21
+
22
+ 1. The simplest option: Install it, configure it, and wpMandrill will start sending your emails through Mandrill.
23
+ 1. If you need to fine tune certain emails, you can change any email by creating a filter for the **mandrill_payload** hook.
24
+ 1. For further customization, we've exposed a function that allows you to send emails from within your plugins, instead of the regular wp_mail function: **wpMandrill::mail**
25
+ 1. If you need Mandrill Powers, we've included a full-featured class in the file lib/mandrill.class.php, where you'll find every call that can be done through the Mandrill API.
26
+
27
+ This plugin is currently released as **beta** for early adopter evaluation and finalizing of the initial feature set.
28
+
29
+ == Installation ==
30
+
31
+ 1. Upload `wpMandrill` to the `/wp-content/plugins/` directory
32
+ 1. Activate the plugin through the _Plugins_ menu in WordPress
33
+ 1. Configure plugin in _Settings > Mandrill_
34
+ 1. Optionally, you can activate and check the **wpMandrill How-Tos** plugin
35
+
36
+ == Frequently Asked Questions ==
37
+
38
+ = Why do I need a Mandrill API key? =
39
+
40
+ In order to use this plugin, you have to provide one of your Mandrill API keys. That's currently the only way we can get access to your Mandrill account.
41
+
42
+ = Do I need a MailChimp account? =
43
+
44
+ Right now, Mandrill is officially in open beta for Mailchimp users. So, yes, you need a MailChimp account in order to create a Mandrill account.
45
+
46
+ = Is all email routed through Mandrill? =
47
+
48
+ Yes. We try to send every single email sent through your WordPress installation. We also try to process your headers and attachments.
49
+
50
+ If the sending fails for any reason, the plugin will try to send it again using the WordPress wp_mail function.
51
+
52
+ == Screenshots ==
53
+
54
+ 1. Settings screen
55
+ 2. Statistics
56
+ 3. Dashboard widget
57
+
58
+ == Changelog ==
59
+
60
+ = 1.0 =
61
+ * Public release
screenshot-1.png ADDED
Binary file
screenshot-2.png ADDED
Binary file
screenshot-3.png ADDED
Binary file
stats.php ADDED
@@ -0,0 +1,361 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if (!current_user_can('manage_options')) wp_die( __('You do not have sufficient permissions to access this page.') ); ?>
2
+ <div class="wrap">
3
+ <div class="icon32" style="background: url('<?php echo plugins_url('images/mandrill-head-icon.png',__FILE__); ?>');"><br /></div>
4
+ <h2><?php _e('Mandrill Service Report', wpMandrill::WPDOMAIN); ?></h2><?php
5
+
6
+ $stats = self::getCurrentStats();
7
+ if ( empty($stats) ) {
8
+ echo '<p>' . __('There was a problem retrieving statistics.', self::WPDOMAIN) . '</p>';
9
+ echo '</div>';
10
+ return;
11
+ }
12
+
13
+ $delivered = $stats['general']['stats']['sent'] -
14
+ $stats['general']['stats']['hard_bounces'] -
15
+ $stats['general']['stats']['soft_bounces'] -
16
+ $stats['general']['stats']['rejects'];
17
+
18
+ $lit = array();
19
+
20
+ $lit['hourly']['title'] = __('Hourly Sending Volume and Open/Click Rate',self::WPDOMAIN);
21
+ $lit['hourly']['Xtitle'] = __('Hours',self::WPDOMAIN);
22
+ $lit['hourly']['tooltip'] = __('Hour',self::WPDOMAIN);
23
+
24
+ $lit['daily']['title'] = __('Daily Sending Volume and Open/Click Rate',self::WPDOMAIN);
25
+ $lit['daily']['Xtitle'] = __('Days',self::WPDOMAIN);
26
+ $lit['daily']['tooltip'] = __('Day',self::WPDOMAIN);
27
+
28
+ $lit['subtitle'] = __('in the last 30 days',self::WPDOMAIN);
29
+ $lit['Ytitle'] = __('Open & Click Rate',self::WPDOMAIN);
30
+ $lit['SerieName'] = __('Volume',self::WPDOMAIN);
31
+ $lit['emails'] = __('emails',self::WPDOMAIN);
32
+ $lit['openrate'] = __('Open Rate',self::WPDOMAIN);
33
+ $lit['clickrate'] = __('Click Rate',self::WPDOMAIN);
34
+
35
+ ?>
36
+ <div id="alltime_report">
37
+ <h3><?php echo sprintf(__('All-time statistics since %s: ', wpMandrill::WPDOMAIN),date('m/d/Y',strtotime($stats['general']['created_at']))); ?></h3>
38
+
39
+ <div id="alltime_report_canvas">
40
+ <div class="stat_box"><?php _e('Reputation:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['reputation']?>%</span></div>
41
+ <div class="stat_box"><?php _e('Quota:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['hourly_quota']?> <?php _e('sends/hour', wpMandrill::WPDOMAIN); ?></span></div>
42
+ <div class="stat_box"><?php _e('Emails sent:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['stats']['sent']?></span></div>
43
+ <div class="stat_box"><?php _e('Emails delivered:', wpMandrill::WPDOMAIN); ?><br/><span><?=$delivered?> (<?=$delivered*100/($stats['general']['stats']['sent']?$stats['general']['stats']['sent']:1)?>%)</span></div>
44
+ <div class="stat_box"><?php _e('Tracked opens:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['stats']['opens']?></span></div>
45
+ <div class="stat_box"><?php _e('Tracked clicks:', wpMandrill::WPDOMAIN); ?><br/><span><?=$stats['general']['stats']['clicks']?></span></div>
46
+ <?php
47
+ if ( $stats['general']['stats']['rejects'] ) echo '<div class="stat_box warning">'.__('Rejects:', wpMandrill::WPDOMAIN).'<br/><span>'.$stats['general']['stats']['rejects'].'</span></div>';
48
+ if ( $stats['general']['stats']['complaints'] ) echo '<div class="stat_box warning">'.__('Complaints:', wpMandrill::WPDOMAIN).'<br/><span>'.$stats['general']['stats']['complaints'].'</span></div>';
49
+ if ( $stats['general']['backlog'] ) echo '<div class="stat_box warning">'.__('Current backlog:', wpMandrill::WPDOMAIN).'<br/><span>'.$stats['general']['backlog'].' emails</span></div>';
50
+ ?>
51
+ </div>
52
+ </div>
53
+
54
+ <div style="clear: both;"></div>
55
+ <div id="filtered_reports">
56
+ <h3><?php _e('Filtered statistics:', wpMandrill::WPDOMAIN); ?></h3>
57
+ <label for="filter"><?php _e('Filter by:', wpMandrill::WPDOMAIN); ?> </label>
58
+ <select id="filter" name="filter">
59
+ <option value="none" selected="selected" ><?php _e('No filter', wpMandrill::WPDOMAIN); ?></option>
60
+ <optgroup label="<?php _e('Sender:', wpMandrill::WPDOMAIN); ?>">
61
+ <?php
62
+ foreach ( array_keys($stats['stats']['hourly']['senders']) as $sender) {
63
+ echo '<option value="s:'.$sender.'">'.$sender.'</option>';
64
+ }
65
+ ?>
66
+ </optgroup>
67
+ <optgroup label="<?php _e('Tag:', wpMandrill::WPDOMAIN); ?>">
68
+ <?php
69
+ foreach ( array_keys($stats['stats']['hourly']['tags']['detailed_stats']) as $tag) {
70
+ echo '<option value="'.$tag.'">'.$tag.'</option>';
71
+ }
72
+ ?>
73
+ </optgroup>
74
+ </select>
75
+ <label for="display"><?php _e('Display:', wpMandrill::WPDOMAIN); ?> </label>
76
+ <select id="display" name="display">
77
+ <option value="volume"><?php _e('Total Volume per Period', wpMandrill::WPDOMAIN); ?></option>
78
+ <option value="average"><?php _e('Average Volume per Period', wpMandrill::WPDOMAIN); ?></option>
79
+ </select><div id="ajax-icon-container"><span id="loading_data" class="hidden"></span></div>
80
+ <div id="filtered_reports_canvas">
81
+ <div id="filtered_recent" style="width: 50%;float: left;"></div>
82
+ <div id="filtered_oldest" style="width: 50%;float: left;"></div>
83
+ </div>
84
+ <div style="clear: both;"></div>
85
+ </div>
86
+ <br/><br/>
87
+ <div id="hourly_report">
88
+ <script type="text/javascript">
89
+ jQuery(function () {
90
+ var chart;
91
+ jQuery(document).ready(function() {
92
+ chart = new Highcharts.Chart({
93
+ chart: {
94
+ renderTo: 'hourly_report_canvas',
95
+ zoomType: 'xy',
96
+ spacingBottom: 30
97
+ },
98
+ exporting: {
99
+ enabled: true,
100
+ },
101
+ title: {
102
+ text: '<?php echo $lit['hourly']['title']; ?>'
103
+ },
104
+ subtitle: {
105
+ text: '<?php echo $lit['subtitle']; ?>'
106
+ },
107
+ xAxis: [{
108
+ categories: [<?=implode(',',array_keys($stats['graph']['hourly']['delivered']));?>],
109
+ title: {
110
+ enabled: true,
111
+ text: '<?php echo $lit['hourly']['Xtitle']; ?>',
112
+ style: {
113
+ fontWeight: 'normal'
114
+ }
115
+ }
116
+ }],
117
+ yAxis: [{
118
+ min: 0,
119
+ max: 100,
120
+ labels: {
121
+ formatter: function() {
122
+ return this.value +'%';
123
+ },
124
+ style: {
125
+ color: '#666666'
126
+ }
127
+ },
128
+ title: {
129
+ text: '<?php echo $lit['Ytitle']; ?>',
130
+ style: {
131
+ color: '#666666'
132
+ }
133
+ }
134
+ }, {
135
+ title: {
136
+ text: '<?php echo $lit['SerieName']; ?>',
137
+ style: {
138
+ color: '#4572A7'
139
+ }
140
+ },
141
+ labels: {
142
+ formatter: function() {
143
+ return this.value +' <?php echo $lit['emails']; ?>';
144
+ },
145
+ style: {
146
+ color: '#4572A7'
147
+ }
148
+ },
149
+ opposite: true
150
+ }],
151
+ tooltip: {
152
+ formatter: function() {
153
+ return '<?php echo $lit['hourly']['tooltip']; ?> '+
154
+ this.x +': '+ this.y +
155
+ (this.series.name == '<?php echo $lit['SerieName']; ?>' ? ' <?php echo $lit['emails']; ?>' : '%');
156
+ }
157
+ },
158
+ plotOptions: {
159
+ column: {
160
+ fillOpacity: 0.5
161
+ }
162
+ },
163
+ credits: {
164
+ enabled: false,
165
+ href: "http://www.mandrillapp.com/",
166
+ text: "MandrillApp.com"
167
+ },
168
+ legend: {
169
+ align: 'right',
170
+ x: -100,
171
+ verticalAlign: 'top',
172
+ y: 20,
173
+ floating: true,
174
+ backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColorSolid) || 'white',
175
+ borderColor: '#CCC',
176
+ borderWidth: 1,
177
+ shadow: false
178
+ },
179
+ series: [{
180
+ name: 'Volume',
181
+ color: '#4572A7',
182
+ type: 'column',
183
+ yAxis: 1,
184
+ data: [<?=implode(',',$stats['graph']['hourly']['delivered']);?>],
185
+ dataLabels: {
186
+ enabled: true,
187
+ rotation: -90,
188
+ color: '#FFFFFF',
189
+ align: 'right',
190
+ x: -3,
191
+ y: 10,
192
+ formatter: function() {
193
+ return this.y;
194
+ },
195
+ style: {
196
+ font: 'normal 13px Verdana, sans-serif'
197
+ }
198
+ },
199
+ }, {
200
+ name: '<?php echo $lit['openrate']; ?>',
201
+ color: '#89A54E',
202
+ type: 'spline',
203
+ data: [<?=implode(',',$stats['graph']['hourly']['open_rate']);?>]
204
+ }, {
205
+ name: '<?php echo $lit['clickrate']; ?>',
206
+ color: '#deA54E',
207
+ type: 'spline',
208
+ data: [<?=implode(',',$stats['graph']['hourly']['click_rate']);?>]
209
+ }]
210
+ });
211
+ });
212
+ chart = new Highcharts.Chart({
213
+ chart: {
214
+ renderTo: 'daily_report_canvas',
215
+ zoomType: 'xy',
216
+ spacingBottom: 30
217
+ },
218
+ title: {
219
+ text: '<?php echo $lit['daily']['title']; ?>'
220
+ },
221
+ subtitle: {
222
+ text: '<?php echo $lit['subtitle']; ?>'
223
+ },
224
+ xAxis: [{
225
+ categories: [<?=implode(',',array_keys($stats['graph']['daily']['delivered']));?>],
226
+ title: {
227
+ enabled: true,
228
+ text: '<?php echo $lit['daily']['Xtitle']; ?>',
229
+ style: {
230
+ fontWeight: 'normal'
231
+ }
232
+ },
233
+ labels: {
234
+ rotation: -45,
235
+ align: 'right',
236
+ style: {
237
+ font: 'normal 13px Verdana, sans-serif'
238
+ }
239
+ }
240
+ }],
241
+ yAxis: [{
242
+ min: 0,
243
+ max: 100,
244
+ labels: {
245
+ formatter: function() {
246
+ return this.value +'%';
247
+ },
248
+ style: {
249
+ color: '#666666'
250
+ }
251
+ },
252
+ title: {
253
+ text: '<?php echo $lit['Ytitle']; ?>',
254
+ style: {
255
+ color: '#666666'
256
+ }
257
+ }
258
+ }, {
259
+ title: {
260
+ text: '<?php echo $lit['SerieName']; ?>',
261
+ style: {
262
+ color: '#4572A7'
263
+ }
264
+ },
265
+ dataLabels: {
266
+ enabled: true,
267
+ rotation: -90,
268
+ color: '#FFFFFF',
269
+ align: 'right',
270
+ x: -3,
271
+ y: 10,
272
+ formatter: function() {
273
+ return this.y;
274
+ },
275
+ style: {
276
+ font: 'normal 13px Verdana, sans-serif'
277
+ }
278
+ },
279
+ labels: {
280
+ formatter: function() {
281
+ return this.value +' <?php echo $lit['emails']; ?>';
282
+ },
283
+ style: {
284
+ color: '#4572A7'
285
+ }
286
+ },
287
+ opposite: true
288
+ }],
289
+ tooltip: {
290
+ formatter: function() {
291
+ return '<?php echo $lit['daily']['tooltip']; ?> '+
292
+ this.x +': '+ this.y +
293
+ (this.series.name == '<?php echo $lit['SerieName']; ?>' ? ' <?php echo $lit['emails']; ?>' : '%');
294
+ }
295
+ },
296
+ plotOptions: {
297
+ column: {
298
+ fillOpacity: 0.5
299
+ }
300
+ },
301
+ credits: {
302
+ enabled: false,
303
+ href: "http://www.mandrillapp.com/",
304
+ text: "MandrillApp.com"
305
+ },
306
+ legend: {
307
+ align: 'right',
308
+ x: -100,
309
+ verticalAlign: 'top',
310
+ y: 20,
311
+ floating: true,
312
+ backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColorSolid) || 'white',
313
+ borderColor: '#CCC',
314
+ borderWidth: 1,
315
+ shadow: false
316
+ },
317
+ series: [{
318
+ name: '<?php echo $lit['SerieName']; ?>',
319
+ color: '#4572A7',
320
+ type: 'column',
321
+ yAxis: 1,
322
+ data: [<?=implode(',',$stats['graph']['daily']['delivered']);?>],
323
+ dataLabels: {
324
+ enabled: true,
325
+ rotation: -90,
326
+ color: '#FFFFFF',
327
+ align: 'right',
328
+ x: -3,
329
+ y: 10,
330
+ formatter: function() {
331
+ return this.y;
332
+ },
333
+ style: {
334
+ font: 'normal 13px Verdana, sans-serif'
335
+ }
336
+ },
337
+ }, {
338
+ name: '<?php echo $lit['openrate']; ?>',
339
+ color: '#89A54E',
340
+ type: 'spline',
341
+ data: [<?=implode(',',$stats['graph']['daily']['open_rate']);?>]
342
+ }, {
343
+ name: '<?php echo $lit['clickrate']; ?>',
344
+ color: '#deA54E',
345
+ type: 'spline',
346
+ data: [<?=implode(',',$stats['graph']['daily']['click_rate']);?>]
347
+ }]
348
+ });
349
+ });
350
+ </script>
351
+ <div id="hourly_report_canvas"></div><br/><br/>
352
+ <div id="daily_report_canvas"></div>
353
+ <h3><a href="http://mandrillapp.com/" target="_target"><?php _e('For more detailed statistics, please visit your Mandrill Dashboard',self::WPDOMAIN); ?></a>.
354
+ <?php // echo str_replace(' ','&nbsp;&nbsp;&nbsp;&nbsp;',nl2br(print_r($graph_data,true))); ?></h3>
355
+ </div>
356
+ <?php
357
+
358
+ // echo "<div style=\"display:none;\">\n".print_r($stats,true) . "\n</div>";
359
+ wpMandrill::$stats = $stats;
360
+
361
+ ?>
uninstall.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( !defined( 'WP_UNINSTALL_PLUGIN' ) )
4
+ exit();
5
+
6
+ delete_option( 'wpmandrill' );
7
+ delete_option( 'wpmandrill-test' );
8
+ delete_transient('mandrill-stats');
9
+ ?>
wpmandrill.php ADDED
@@ -0,0 +1,1664 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: wpMandrill
4
+ Description: wpMandrill sends emails, generated by WordPress using Mandrill.
5
+ Author: Mandrill
6
+ Author URI: http://mandrillapp.com/
7
+ Plugin URI: http://connect.mailchimp.com/integrations/wpmandrill
8
+ Version: 1.0
9
+ Text Domain: wpmandrill
10
+ */
11
+
12
+ wpMandrill::on_load();
13
+
14
+ class wpMandrill {
15
+ const WPDOMAIN = 'wpmandrill';
16
+
17
+ static $settings;
18
+ static $report;
19
+ static $stats;
20
+ static $mandrill;
21
+ static $conflict;
22
+
23
+ static function on_load() {
24
+
25
+ define('WPMANDRILL_API_VERSION', '1.0');
26
+
27
+ add_action('admin_init', array(__CLASS__, 'adminInit'));
28
+ add_action('admin_menu', array(__CLASS__, 'adminMenu'));
29
+
30
+ add_filter('contextual_help', array(__CLASS__, 'showContextualHelp'), 10, 3);
31
+ add_action('admin_print_footer_scripts', array(__CLASS__,'openContextualHelp'));
32
+ add_action('wp_ajax_get_mandrill_stats', array(__CLASS__,'getAjaxStats'));
33
+ add_action('wp_ajax_get_dashboard_widget_stats', array(__CLASS__,'showDashboardWidget'));
34
+
35
+ load_plugin_textdomain(self::WPDOMAIN, false, dirname( plugin_basename( __FILE__ ) ).'/lang');
36
+
37
+ try {
38
+
39
+ require_once( plugin_dir_path( __FILE__ ) . '/lib/mandrill.class.php');
40
+ $api_key = self::getAPIKey();
41
+ if ( $api_key && !isset(self::$mandrill) ) self::$mandrill = new Mandrill($api_key);
42
+
43
+ } catch ( Exception $e ) {}
44
+
45
+ if( function_exists('wp_mail') ) {
46
+ self::$conflict = true;
47
+ add_action('admin_notices', array(__CLASS__, 'adminNotices'));
48
+ return;
49
+ }
50
+
51
+ self::$conflict = false;
52
+ if( self::isReady() ) {
53
+
54
+ function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {
55
+
56
+ try {
57
+
58
+ $sent = wpMandrill::mail( $to, $subject, $message, $headers, $attachments );
59
+ if( is_wp_error($sent) || 'sent' != $sent[0]['status'] ) return false;
60
+
61
+ return true;
62
+ } catch ( Exception $e ) {
63
+ return self::wp_mail_native( $to, $subject, $message, $headers, $attachments );
64
+ }
65
+ }
66
+ }
67
+
68
+ }
69
+
70
+ /**
71
+ * Sets up options page and sections.
72
+ */
73
+ static function adminInit() {
74
+
75
+ add_filter('plugin_action_links',array(__CLASS__,'showPluginActionLinks'), 10,5);
76
+ add_action('admin_enqueue_scripts', array(__CLASS__,'showAdminEnqueueScripts'));
77
+
78
+ register_setting(self::WPDOMAIN, self::WPDOMAIN, array(__CLASS__,'formValidate'));
79
+
80
+ // SMTP Settings
81
+ add_settings_section('wpmandrill-api', __('API Settings', self::WPDOMAIN), '__return_false', self::WPDOMAIN);
82
+ add_settings_field('api-key', __('API Key', self::WPDOMAIN), array(__CLASS__, 'askAPIKey'), self::WPDOMAIN, 'wpmandrill-api');
83
+
84
+ if( self::isConnected() ) {
85
+ add_action('wp_dashboard_setup', array( __CLASS__,'addDashboardWidgets') );
86
+
87
+ // Verified Addresses
88
+ add_settings_section('wpmandrill-addresses', __('Sender Settings', self::WPDOMAIN), '__return_false', self::WPDOMAIN);
89
+ add_settings_field('from-name', __('FROM Name', self::WPDOMAIN), array(__CLASS__, 'askFromName'), self::WPDOMAIN, 'wpmandrill-addresses');
90
+ add_settings_field('from-email', __('FROM Email', self::WPDOMAIN), array(__CLASS__, 'askFromEmail'), self::WPDOMAIN, 'wpmandrill-addresses');
91
+
92
+ // Template
93
+ add_settings_section('wpmandrill-templates', __('General Template', self::WPDOMAIN), '__return_false', self::WPDOMAIN);
94
+ add_settings_field('template', __('&nbsp;', self::WPDOMAIN), array(__CLASS__, 'askTemplate'), self::WPDOMAIN, 'wpmandrill-templates');
95
+
96
+ // Tags
97
+ add_settings_section('wpmandrill-tags', __('General Tags', self::WPDOMAIN), '__return_false', self::WPDOMAIN);
98
+ add_settings_field('tags', __('&nbsp;', self::WPDOMAIN), array(__CLASS__, 'askTags'), self::WPDOMAIN, 'wpmandrill-tags');
99
+
100
+ if ( self::isReady() ) {
101
+ // Email Test
102
+ register_setting('wpmandrill-test', 'wpmandrill-test', array(__CLASS__, 'sendTestEmail'));
103
+
104
+ add_settings_section('mandrill-email-test', __('Send a test email using these settings', self::WPDOMAIN), '__return_false', 'wpmandrill-test');
105
+ add_settings_field('email-to', __('Send to', self::WPDOMAIN), array(__CLASS__, 'askTestEmailTo'), 'wpmandrill-test', 'mandrill-email-test');
106
+ add_settings_field('email-subject', __('Subject', self::WPDOMAIN), array(__CLASS__, 'askTestEmailSubject'), 'wpmandrill-test', 'mandrill-email-test');
107
+ add_settings_field('email-message', __('Message', self::WPDOMAIN), array(__CLASS__, 'askTestEmailMessage'), 'wpmandrill-test', 'mandrill-email-test');
108
+ }
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Creates option page's entry in Settings section of menu.
114
+ */
115
+ static function adminMenu() {
116
+
117
+ self::$settings = add_options_page(
118
+ __('Mandrill Settings', self::WPDOMAIN),
119
+ __('Mandrill', self::WPDOMAIN),
120
+ 'manage_options',
121
+ self::WPDOMAIN,
122
+ array(__CLASS__,'showOptionsPage')
123
+ );
124
+ if( self::isConnected() ) {
125
+ self::$report = add_dashboard_page(
126
+ __('Mandrill Reports', self::WPDOMAIN),
127
+ __('Mandrill Reports', self::WPDOMAIN),
128
+ 'manage_options',
129
+ self::WPDOMAIN.'-reports',
130
+ array(__CLASS__,'showReportPage')
131
+ );
132
+ if ( self::isPluginPage('-reports') ) {
133
+ wp_register_script('highcharts', plugins_url('/js/highcharts.js', __FILE__), array('jquery'), null, true);
134
+ wp_register_script('mandrill-report-export', plugins_url("js/modules/exporting.js", __FILE__), array('highcharts'), null, true);
135
+ wp_enqueue_script('highcharts');
136
+ wp_enqueue_script('mandrill-report-export');
137
+ }
138
+ }
139
+
140
+ wp_register_style( 'mandrill_stylesheet', plugins_url('/css/mandrill.css', __FILE__) );
141
+ wp_enqueue_style( 'mandrill_stylesheet' );
142
+ wp_register_script('mandrill', plugins_url('/js/mandrill.js', __FILE__), array(), null, true);
143
+ wp_enqueue_script('mandrill');
144
+ }
145
+
146
+
147
+ static function adminNotices() {
148
+ if ( self::$conflict ) {
149
+ echo '<div class="error"><p>'.__('Mandrill: wp_mail has been declared by another process or plugin, so you won\'t be able to use Mandrill until the problem is solved.', self::WPDOMAIN) . '</p></div>';
150
+ }
151
+ }
152
+
153
+ static function showAdminEnqueueScripts($hook_suffix) {
154
+ if( $hook_suffix == self::$report && self::isReady() ) {
155
+ wp_register_script('mandrill-report-theme', plugins_url("js/themes/gray.js", __FILE__), array(''), null, true);
156
+ wp_register_script('mandrill-report-script', plugins_url("js/mandrill.js", __FILE__), array('highcharts'), null, true);
157
+ wp_register_script('mandrill-report-export', plugins_url("js/modules/exporting.js", __FILE__), array('highcharts'), null, true);
158
+
159
+ wp_enqueue_script('mandrill-report-script');
160
+ wp_enqueue_script('mandrill-report-theme');
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Generates source of contextual help panel.
166
+ */
167
+ static function showContextualHelp($contextual_help, $screen_id, $screen) {
168
+ if ($screen_id == self::$settings) {
169
+ $dir = dirname( plugin_basename( __FILE__ ) ).'/images';
170
+
171
+ $ok = array();
172
+ $ok['account'] = ( !self::getAPIKey() ) ? ' class="missing"' : '';
173
+ $ok['domains'] = ( !self::ListVerifiedDomains() ) ? ' class="missing"' : '';
174
+ $ok['email'] = ( !self::getFromEmail() ) ? ' class="missing"' : '';
175
+
176
+ $requirements = '';
177
+ if ($ok['account'] . $ok['domains'] . $ok['email'] != '' ) {
178
+ $requirements = '<p>' . __('To use this plugin you will need:', self::WPDOMAIN) . '</p>'
179
+ . '<ol>'
180
+ . '<li'.$ok['account'].'>'. __('Your Mandrill account.', self::WPDOMAIN) . '</li>'
181
+ . '<li'.$ok['domains'].'>' . __('At least one verified domain.', self::WPDOMAIN) . '</li>'
182
+ . '<li'.$ok['email'].'>' . __('A valid sender email address specified.', self::WPDOMAIN) . '</li>'
183
+ . '</ol>';
184
+ }
185
+
186
+ return $requirements
187
+ . '<p>' . __('Once you have properly configured the settings, the plugin will take care of all the emails sent through your WordPress installation.', self::WPDOMAIN).'</p>'
188
+ . '<p>' . __('However, if you need to customize any part of the email before sending, you can do so by using the WordPress filter <strong>mandrill_payload</strong>.', self::WPDOMAIN).'</p>'
189
+ . '<p>' . __('This filter has the same structure as Mandrill\'s API call <a href="http://mandrillapp.com/api/docs/messages.html#method=send" target="_blank">/messages/send</a>, except that it can have one additional parameter when the email is based on a template. The parameter is called "<em>template</em>", which is an associative array of two elements (the first element, a string whose key is "<em>template_name</em>", and a second parameter whose key is "<em>template_content</em>". Its value is an array with the same structure of the parameter "<em>template_content</em>" in the call <a href="http://mandrillapp.com/api/docs/messages.html#method=send-template" target="_blank">/messages/send-template</a>.)', self::WPDOMAIN).'</p>'
190
+ . '<p>' . __('Note that if you\'re sending additional headers in your emails, the only valid headers are <em>From:</em>, <em>Reply-To:</em>, and <em>X-*:</em>. <em>Bcc:</em> is also valid, but Mandrill will send the blind carbon copy to only the first address, and the remaining will be silently discarted.', self::WPDOMAIN).'</p>'
191
+ . '<p>' . __('Also note that if any error occurs while sending the email, the plugin will try to send the message again using the native WordPress mailing capabilities.', self::WPDOMAIN).'</p>'
192
+ . '<p>' . __('Confirm that any change you made to the payload is in line with the <a href="http://mandrillapp.com/api/docs/" target="_blank">Mandrill\'s API\'s documentation</a>. Also, the <em>X-*:</em> headers, must be in line with the <a href="http://help.mandrill.com/customer/portal/articles/456744-smtp-headers-api" target="_blank">SMTP API documentation</a>. By using this plugin, you agree that you and your website will adhere to <a href="http://mandrill.com/legal/terms/" target="_blank">Mandrill\'s Terms of Use</a>.', self::WPDOMAIN).'</p>'
193
+ . '<p>' . __('if you have any question about Mandrill or this plugin, visit the <a href="http://help.mandrill.com/" target="_blank">Mandrill\'s Support Center</a>.', self::WPDOMAIN).'</p>'
194
+ ;
195
+ }
196
+
197
+ return $contextual_help;
198
+ }
199
+
200
+ /**
201
+ * Adds link to settings page in list of plugins
202
+ */
203
+ static function showPluginActionLinks($actions, $plugin_file) {
204
+ static $plugin;
205
+
206
+ if (!isset($plugin))
207
+ $plugin = plugin_basename(__FILE__);
208
+
209
+ if ($plugin == $plugin_file) {
210
+
211
+ $settings = array('settings' => '<a href="options-general.php?page=wpmandrill">' . __('Settings', self::WPDOMAIN) . '</a>');
212
+ $report = array('report' => '<a href="index.php?page=wpmandrill-reports">' . __('Reports', self::WPDOMAIN) . '</a>');
213
+ $actions = array_merge($settings, $actions, $report);
214
+ }
215
+
216
+ return $actions;
217
+ }
218
+
219
+ /**
220
+ * Generates source of options page.
221
+ */
222
+ static function showOptionsPage() {
223
+ if (!current_user_can('manage_options'))
224
+ wp_die( __('You do not have sufficient permissions to access this page.') );
225
+
226
+ ?>
227
+ <div class="wrap">
228
+ <div class="icon32" style="background: url('<?php echo plugins_url('images/mandrill-head-icon.png',__FILE__); ?>');"><br /></div>
229
+ <h2><?php _e('Mandrill Settings', self::WPDOMAIN); ?></h2>
230
+
231
+ <div style="float: left;width: 70%;">
232
+ <form method="post" action="options.php">
233
+
234
+ <div class="stuffbox">
235
+ <?php settings_fields(self::WPDOMAIN); ?>
236
+ <?php do_settings_sections(self::WPDOMAIN); ?>
237
+ </div>
238
+
239
+ <p class="submit"><input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e('Save Changes') ?>" /></p>
240
+ </form>
241
+
242
+
243
+ <?php if( self::isReady() ) { ?>
244
+ <form method="post" action="options.php">
245
+ <div class="stuffbox" style="max-width: 90% !important;">
246
+ <?php settings_fields('wpmandrill-test'); ?>
247
+ <?php do_settings_sections('wpmandrill-test'); ?>
248
+ </div>
249
+
250
+ <p class="submit"><input type="submit" name="Submit" class="button-primary" value="<?php _e('Send Email', self::WPDOMAIN) ?>" /></p>
251
+ </form>
252
+ <?php } ?>
253
+
254
+ </div>
255
+
256
+ <div style="float: left;width: 20%;">
257
+ <?php
258
+ $rss = fetch_feed('http://mandrill.com/blog/feed');
259
+ $maxitems = 0;
260
+ if (!is_wp_error( $rss ) ) {
261
+ $maxitems = $rss->get_item_quantity(5);
262
+ $rss_items = $rss->get_items(0, $maxitems);
263
+ }
264
+
265
+ if ( $maxitems > 0 ) {
266
+ ?>
267
+ <div class="news mandrill">
268
+ <h3 class="news_header"><?php _e('Latest from Mandrill...', self::WPDOMAIN); ?></h3>
269
+ <ul>
270
+ <?php
271
+ foreach ( $rss_items as $item ) { ?>
272
+ <li>
273
+ <a href='<?php echo esc_url( $item->get_permalink() ); ?>'
274
+ title='<?php echo 'Posted '.$item->get_date('j F Y | g:i a'); ?>'>
275
+ <?php echo esc_html( $item->get_title() ); ?></a>
276
+ </li>
277
+ <?php } ?>
278
+ </ul>
279
+ </div>
280
+ <?php } ?>
281
+ <div class="news">
282
+ <h3 class="news_header"><?php _e('News from MailChimp...', self::WPDOMAIN); ?></h3><?php
283
+ $rss = fetch_feed('http://mailchimp.com/blog/feed');
284
+ if (!is_wp_error( $rss ) ) {
285
+ $maxitems = $rss->get_item_quantity(5);
286
+ $rss_items = $rss->get_items(0, $maxitems);
287
+ } ?>
288
+ <ul>
289
+ <?php if ($maxitems == 0) echo '<li>No news!</li>';
290
+ else
291
+ foreach ( $rss_items as $item ) { ?>
292
+ <li>
293
+ <a href='<?php echo esc_url( $item->get_permalink() ); ?>'
294
+ title='<?php echo 'Posted '.$item->get_date('j F Y | g:i a'); ?>'>
295
+ <?php echo esc_html( $item->get_title() ); ?></a>
296
+ </li>
297
+ <?php } ?>
298
+ </ul>
299
+ </div>
300
+ </div>
301
+ </div>
302
+ <?php
303
+ }
304
+
305
+ static function showReportPage() {
306
+ require plugin_dir_path( __FILE__ ) . '/stats.php';
307
+ }
308
+
309
+ /**
310
+ * Processes submitted settings from.
311
+ */
312
+ static function formValidate($input) {
313
+ if ( !empty($input['from_domain']) && ( empty($input['from_username']) || !self::isDomainEnabled($input['from_domain']) ) ) {
314
+ add_settings_error(
315
+ self::WPDOMAIN,
316
+ 'from-email',
317
+ __('You must define a valid sender email.', self::WPDOMAIN),
318
+ 'error'
319
+ );
320
+
321
+
322
+ $input['from_username'] = '';
323
+ $input['from_domain'] = '';
324
+ }
325
+
326
+ return array_map('wp_strip_all_tags', $input);
327
+ }
328
+
329
+ /**
330
+ * Opens contextual help section.
331
+ */
332
+ static function openContextualHelp() {
333
+ if ( self::isReady() )
334
+ return;
335
+
336
+ ?>
337
+ <script type="text/javascript">
338
+ jQuery(document).bind( 'ready', function() {
339
+ jQuery('a#contextual-help-link').trigger('click');
340
+ });
341
+ </script>
342
+ <?php
343
+ }
344
+
345
+ /******************************************************************
346
+ ** Helper functions
347
+ *******************************************************************
348
+
349
+
350
+ /**
351
+ * @return mixed
352
+ */
353
+ static function getOption( $name, $default = false ) {
354
+
355
+ $options = get_option(self::WPDOMAIN);
356
+
357
+ if( isset( $options[$name] ) )
358
+ return $options[$name];
359
+
360
+ return $default;
361
+ }
362
+
363
+ /**
364
+ * @return boolean
365
+ */
366
+ static function isReady() {
367
+ return self::isConnected() && self::isConfigured();
368
+ }
369
+
370
+ /**
371
+ * @return boolean
372
+ */
373
+ static function isConnected() {
374
+ $result = false;
375
+
376
+ if ( isset(self::$mandrill)) {
377
+ try {
378
+ $result = ( self::$mandrill->users_ping() == 'PONG!' );
379
+ } catch ( Exception $e) {}
380
+ }
381
+ return $result;
382
+ }
383
+
384
+ /**
385
+ * @return boolean
386
+ */
387
+ static function isConfigured() {
388
+ return self::getAPIKey() && self::getFromEmail();
389
+ }
390
+
391
+ /**
392
+ * @return boolean
393
+ */
394
+ static function setOption( $name, $value ) {
395
+
396
+ $options = get_option(self::WPDOMAIN);
397
+
398
+ $options[$name] = $value;
399
+
400
+ $result = update_option(self::WPDOMAIN, $options);
401
+
402
+ return $result;
403
+ }
404
+
405
+ /**
406
+ * @return string|boolean
407
+ */
408
+ static function getAPIKey() {
409
+
410
+ return self::getOption('api_key');
411
+ }
412
+
413
+ /**
414
+ * @return string|boolean
415
+ */
416
+ static function getFromUsername() {
417
+
418
+ return self::getOption('from_username');
419
+ }
420
+
421
+ /**
422
+ * @return string|boolean
423
+ */
424
+ static function getFromDomain() {
425
+
426
+ return self::getOption('from_domain');
427
+ }
428
+
429
+ /**
430
+ * @return string|boolean
431
+ */
432
+ static function getFromEmail() {
433
+ if ( self::getOption('from_username') && self::getOption('from_domain') ) {
434
+ return self::getOption('from_username') . '@' . self::getOption('from_domain');
435
+ }
436
+ }
437
+
438
+ /**
439
+ * @return string|boolean
440
+ */
441
+ static function getFromName() {
442
+
443
+ return self::getOption('from_name');
444
+ }
445
+
446
+ /**
447
+ * @return string|boolean
448
+ */
449
+ static function getTemplate() {
450
+
451
+ return self::getOption('template');
452
+ }
453
+
454
+ /**
455
+ * @return string|boolean
456
+ */
457
+ static function getTags() {
458
+
459
+ return self::getOption('tags');
460
+ }
461
+
462
+ /**
463
+ * @param string $subject
464
+ * @return array
465
+ */
466
+ static function findTags($tags) {
467
+
468
+ // Getting general tags
469
+ $gtags = explode("\n",self::getTags());
470
+
471
+ // Finding tags based on WP Backtrace
472
+ $trace = debug_backtrace();
473
+ $level = 4;
474
+ $function = $trace[$level]['function'];
475
+
476
+ $wtags = array();
477
+ if( 'include' == $function || 'require' == $function ) {
478
+
479
+ $file = basename($trace[$level]['args'][0]);
480
+ $wtags[] = "wp_{$file}";
481
+ }
482
+ else {
483
+ if( isset( $trace[$level]['class'] ) )
484
+ $function = $trace[$level]['class'].$trace[$level]['type'].$function;
485
+ $wtags[] = "wp_{$function}";
486
+ }
487
+
488
+ return array('user' => $tags, 'general' => $gtags, 'automatic' => $wtags);
489
+ }
490
+
491
+ /**
492
+ * @return boolean
493
+ */
494
+ static function isPluginPage($sufix = '') {
495
+
496
+ return ( isset( $_GET['page'] ) && $_GET['page'] == self::WPDOMAIN . $sufix);
497
+ }
498
+
499
+ /**
500
+ * Return the list of the verified domains for the current users. Or false.
501
+ *
502
+ * @return array|bool
503
+ */
504
+ static function listVerifiedDomains() {
505
+ if ( !self::isConnected() ) return array();
506
+
507
+ $domains = self::$mandrill->senders_domains();
508
+ if ( is_wp_error($domains) || empty($domains) ) return false;
509
+
510
+ foreach ( $domains as $index => $domain ) {
511
+ if ( !$domains[$index]['is_enabled'] ) {
512
+ unset($domains[$index]);
513
+ }
514
+ }
515
+
516
+ return array_values($domains);
517
+ }
518
+
519
+
520
+ /**
521
+ * @return boolean
522
+ */
523
+ static function isDomainEnabled($domain) {
524
+ if ( empty($domain) ) return false;
525
+
526
+ $domains = self::ListVerifiedDomains();
527
+ foreach ( $domains as $curdomain ) {
528
+ if ( $curdomain['domain'] == $domain ) {
529
+ return true;
530
+ }
531
+ }
532
+
533
+ return false;
534
+ }
535
+
536
+ /**
537
+ * @return boolean
538
+ */
539
+ static function isTemplateValid($template) {
540
+ if ( empty($template) || !self::isConnected() ) return false;
541
+
542
+ $templates = self::$mandrill->templates_list();
543
+ foreach ( $templates as $curtemplate ) {
544
+ if ( $curtemplate['name'] == $template ) {
545
+ return true;
546
+ }
547
+ }
548
+
549
+ return false;
550
+ }
551
+
552
+ /**
553
+ * Processes submitted email test form.
554
+ */
555
+ static function sendTestEmail($input) {
556
+
557
+ if (isset($input['email_to']) && !empty($input['email_to'])) {
558
+
559
+ $to = $input['email_to'];
560
+ $subject = isset($input['email_subject']) ? $input['email_subject'] : '';
561
+ $message = isset($input['email_message']) ? $input['email_message'] : '';
562
+
563
+ $test = self::wp_mail($to, $subject, $message);
564
+
565
+ if (is_wp_error($test)) {
566
+
567
+ add_settings_error('email-to', 'email-to', __('Test email send failed. ', self::WPDOMAIN) . $test->get_error_message());
568
+
569
+ return array_map('wp_strip_all_tags', $input);
570
+ } else {
571
+ $result = array();
572
+ foreach ( $test as $email ) {
573
+ if ( !isset($result[$email['status']]) ) $result[$email['status']] = 0;
574
+ $result[$email['status']]++;
575
+ }
576
+
577
+ add_settings_error('email-to', 'email-to', sprintf(__('Test executed: %d emails sent, %d emails queued and %d emails rejected', self::WPDOMAIN), $result['sent'],$result['queue'],$result['rejected']), $result['sent'] ? 'updated' : 'error' );
578
+ }
579
+ }
580
+
581
+ return array();
582
+ }
583
+
584
+ // Following methods generate parts of settings and test forms.
585
+ static function askAPIKey() {
586
+ echo '<div class="inside">';
587
+
588
+ $api_key = self::getOption('api_key');
589
+ ?><input id='api_key' name='wpmandrill[api_key]' size='45' type='text' value="<?php esc_attr_e( $api_key ); ?>" /><?php
590
+
591
+ if ( empty($api_key) ) {
592
+ ?><br/><span class="setting-description"><small><em><?php _e('To get your API key, please visit your <a href="http://mandrillapp.com/settings/index" target="_blank">Mandrill Settings</a>', self::WPDOMAIN); ?></em></small></span><?php
593
+ } elseif ( self::isConnected() ) {
594
+ ?><br/><span class="setting-description"><small><em><?php _e('We are connected to your Mandrill Account.', self::WPDOMAIN); ?></em></small></span><?php
595
+ } else {
596
+ ?><br/><span class="setting-description"><small><em><?php _e('Sorry, invalid API key.', self::WPDOMAIN); ?></em></small></span><?php
597
+ }
598
+
599
+ echo '</div>';
600
+ }
601
+
602
+ static function askFromEmail() {
603
+ echo '<div class="inside">';
604
+
605
+ $from_username = self::getFromUsername();
606
+ $from_domain = self::getFromDomain();
607
+ $from_email = self::getFromEmail();
608
+
609
+ $domains = self::ListVerifiedDomains();
610
+ if ( !$domains ) {
611
+
612
+ _e('No verified domains found.', self::WPDOMAIN);
613
+
614
+ if ( $from_email ) {
615
+ self::setOption('from_username', false);
616
+ self::setOption('from_domain', false);
617
+ self::setOption('from_email', false);
618
+ }
619
+
620
+ echo '</div>';
621
+ return;
622
+ }
623
+
624
+ ?><span class="setting-description"><em><?php _e('This address will be used as the sender of the outgoing emails:', self::WPDOMAIN); ?></em></span><br />
625
+ <input id="from_username" name="wpmandrill[from_username]" type="text" value="<?php esc_attr_e($from_username);?>" style="text-align:right;width:100px">@
626
+ <select id="from_domain" name="wpmandrill[from_domain]"><?php
627
+ foreach( $domains as $curdomain ) {
628
+ ?><option value="<?php esc_attr_e($curdomain['domain']); ?>" <?php selected($curdomain['domain'], $from_domain); ?>><?php esc_html_e($curdomain['domain']); ?></option><?php
629
+ }
630
+ ?></select><br/><span class="setting-description"><small><em><?php _e('Only verified domains are displayed here. If you need to verify a new domain, please visit your <a href="https://mandrillapp.com/settings/sending-domains" target="_blank">Mandrill Settings</a>', self::WPDOMAIN); ?></em></small></span><?php
631
+
632
+ echo '</div>';
633
+ }
634
+
635
+ static function askFromName() {
636
+ echo '<div class="inside">';
637
+
638
+ $from_name = self::getFromName();
639
+
640
+ ?><span class="setting-description"><em><?php _e('Name the recipients will see in their email clients:', self::WPDOMAIN); ?></em></span><br />
641
+ <input name="wpmandrill[from_name]" type="text" value="<?php esc_attr_e($from_name); ?>">
642
+ <?php
643
+
644
+ echo '</div>';
645
+ }
646
+
647
+ static function askTemplate() {
648
+ echo '<div class="inside">';
649
+
650
+ if ( !self::isConnected() ) {
651
+ _e('No templates found.', self::WPDOMAIN);
652
+
653
+ echo '</div>';
654
+ return;
655
+ }
656
+
657
+ $template = self::getTemplate();
658
+ $templates = self::$mandrill->templates_list();
659
+ if( is_wp_error($templates) || empty($templates)) {
660
+
661
+ _e('No templates found.', self::WPDOMAIN);
662
+
663
+ if( $templates )
664
+ self::setOption('templates', false);
665
+
666
+ echo '</div>';
667
+ return;
668
+ }
669
+
670
+ ?><span class="setting-description"><em><?php _e('Select the template to use:', self::WPDOMAIN); ?></em></span><br />
671
+ <select name="wpmandrill[template]">
672
+ <option value="">-None-</option><?php
673
+ foreach( $templates as $curtemplate ) {
674
+ ?><option value="<?php esc_attr_e($curtemplate['name']); ?>" <?php selected($curtemplate['name'], $template); ?>><?php esc_html_e($curtemplate['name']); ?></option><?php
675
+ }
676
+ ?></select><br/><span class="setting-description"><em><?php _e('<small>The selected template must have a <strong><em>mc:edit="main"</em></strong> placeholder defined. The message will be shown there.</small>', self::WPDOMAIN); ?></em></span><?php
677
+
678
+ echo '</div>';
679
+ }
680
+
681
+ static function askTags() {
682
+ echo '<div class="inside">';
683
+
684
+ $tags = self::getTags();
685
+
686
+ ?><span class="setting-description"><em><?php _e('If there are tags that you want appended to every call, list them here, one per line:', self::WPDOMAIN); ?></em></span><br />
687
+ <textarea name="wpmandrill[tags]" cols="25" rows="3"><?php echo $tags; ?></textarea><br/>
688
+ <span class="setting-description"><small><em><?php _e('Also keep in mind that you can add or remove tags using the <em><a href="#" onclick="jQuery(\'a#contextual-help-link\').trigger(\'click\');return false;">mandrill_payload</a></em> WordPress filter.', self::WPDOMAIN); ?></em></small></span>
689
+ <?php
690
+
691
+ echo '</div>';
692
+ }
693
+
694
+ static function askTestEmailTo() {
695
+ echo '<div class="inside">';
696
+ ?><input id='email_to' name='wpmandrill-test[email_to]' size='45' type='text' value="<?php esc_attr_e( self::getTestEmailOption('email_to') ); ?>"/><?php
697
+ echo '</div>';
698
+ }
699
+
700
+ static function askTestEmailSubject() {
701
+ echo '<div class="inside">';
702
+ ?><input id='email_subject' name='wpmandrill-test[email_subject]' size='45' type='text' value="<?php esc_attr_e( self::getTestEmailOption('email_subject') ); ?>" /><?php
703
+ echo '</div>';
704
+ }
705
+
706
+ static function askTestEmailMessage() {
707
+ echo '<div class="inside">';
708
+ ?><textarea rows="5" cols="45" name="wpmandrill-test[email_message]" ><?php esc_html_e( self::getTestEmailOption('email_message') ); ?></textarea><?php
709
+ echo '</div>';
710
+ }
711
+
712
+ /**
713
+ * @param string $field
714
+ * @return string|bool
715
+ */
716
+ static function getTestEmailOption($field) {
717
+
718
+ if ( function_exists('is_multisite') && is_multisite() )
719
+ $email = get_site_option(self::WPDOMAIN . '-test');
720
+ else
721
+ $email = get_option(self::WPDOMAIN . '-test');
722
+
723
+ if( isset( $email[$field] ) )
724
+ return $email[$field];
725
+
726
+ return false;
727
+ }
728
+
729
+
730
+ /******************************************************************
731
+ ** Stats-related functions
732
+ *******************************************************************/
733
+
734
+ /**
735
+ * @return array
736
+ */
737
+ static function GetRawStatistics() {
738
+ if ( !self::isConnected() ) return array();
739
+
740
+ $stats = array();
741
+ $final = array();
742
+
743
+ $stats['user'] = self::$mandrill->users_info();
744
+
745
+ $data = array();
746
+ $container = self::$mandrill->tags_list();
747
+ foreach ( $container as $tag ) {
748
+ $data[$tag['tag']] = self::$mandrill->tags_info($tag['tag']);
749
+ }
750
+ $stats['tags'] = $data;
751
+
752
+ $data = array();
753
+ $container = self::$mandrill->senders_list();
754
+ foreach ( $container as $sender ) {
755
+ $data[$sender['address']] = self::$mandrill->senders_info($sender['address']);
756
+ }
757
+ $stats['senders'] = $data;
758
+
759
+ $stats['urls'] = self::$mandrill->urls_list();
760
+
761
+
762
+ $final['general'] = $stats['user'];
763
+ $final['urls'] = $stats['urls'];
764
+
765
+ $final['stats'] = array();
766
+ $final['stats']['hourly']['senders'] = array();;
767
+ $final['stats']['hourly']['tags'] = array();
768
+
769
+ $final['general']['stats'] = $final['general']['stats']['all_time'];
770
+ $final['stats']['hourly']['tags']['general_stats'] = self::$mandrill->tags_all_time_series();
771
+
772
+ foreach ( array('today', 'last_7_days','last_30_days','last_60_days','last_90_days') as $timeframe) {
773
+ if ( isset($stats['user']['stats'][$timeframe]) ) $final['stats']['periods']['account'][$timeframe] = $stats['user']['stats'][$timeframe];
774
+
775
+ foreach ($stats['tags'] as $index => $entity) {
776
+ if ( !in_array($entity['tag'], $final['stats']['hourly']['tags']) )
777
+ $final['stats']['hourly']['tags']['detailed_stats'][$entity['tag']] = self::$mandrill->tags_time_series($entity['tag']);
778
+
779
+ if ( isset($entity['stats'][$timeframe]) )
780
+ $final['stats']['periods']['tags'][$timeframe][$index] = $entity['stats'][$timeframe];
781
+
782
+ }
783
+
784
+ foreach ($stats['senders'] as $index => $entity) {
785
+ if ( !in_array($entity['address'], $final['stats']['hourly']['senders']) )
786
+ $final['stats']['hourly']['senders'][$entity['address']] = self::$mandrill->senders_time_series($entity['address']);
787
+ if ( isset($entity['stats'][$timeframe]) )
788
+ $final['stats']['periods']['senders'][$timeframe][$index] = $entity['stats'][$timeframe];
789
+ }
790
+ }
791
+
792
+ return $final;
793
+ }
794
+
795
+ static function getProcessedStats() {
796
+ $stats = self::GetRawStatistics();
797
+ if ( empty($stats) ) return $stats;
798
+
799
+ $graph_data = array();
800
+ for ( $i = 0; $i < 24; $i++ ) {
801
+ $graph_data['hourly']['delivered'][ sprintf('"%02s"',$i) ] = 0;
802
+ $graph_data['hourly']['opens'][ sprintf('"%02s"',$i) ] = 0;
803
+ $graph_data['hourly']['clicks'][ sprintf('"%02s"',$i) ] = 0;
804
+
805
+ $graph_data['hourly']['open_rate'][ sprintf('"%02s"',$i) ] = 0;
806
+ $graph_data['hourly']['click_rate'][ sprintf('"%02s"',$i) ] = 0;
807
+ }
808
+
809
+ for ( $i = 29; $i >= 0; $i-- ) {
810
+ $day = date('m/d', strtotime ( "-$i day" , time() ) );
811
+
812
+ $graph_data['daily']['delivered'][ sprintf('"%02s"',$day) ] = 0;
813
+ $graph_data['daily']['opens'][ sprintf('"%02s"',$day) ] = 0;
814
+ $graph_data['daily']['clicks'][ sprintf('"%02s"',$day) ] = 0;
815
+
816
+ $graph_data['daily']['open_rate'][ sprintf('"%02s"',$day) ] = 0;
817
+ $graph_data['daily']['click_rate'][ sprintf('"%02s"',$day) ] = 0;
818
+ }
819
+
820
+ $timeOffset = get_option('gmt_offset');
821
+ $timeOffset = is_numeric($timeOffset) ? $timeOffset * 3600 : 0;
822
+
823
+ foreach ( $stats['stats']['hourly']['senders'] as $data_by_sender ) {
824
+ foreach ( $data_by_sender as $data ) {
825
+
826
+ $hour = '"' . date('H',strtotime($data['time'])+$timeOffset) . '"';
827
+ $day = '"' . date('m/d', strtotime($data['time'])+$timeOffset) . '"';
828
+
829
+ $graph_data['hourly']['delivered'][$hour] += $data['sent'] - $data['hard_bounces'] - $data['soft_bounces'] - $data['rejects'];
830
+ $graph_data['hourly']['opens'][$hour] += $data['unique_opens'];
831
+ $graph_data['hourly']['clicks'][$hour] += $data['unique_clicks'];
832
+
833
+ $graph_data['daily']['delivered'][$day] += $data['sent'] - $data['hard_bounces'] - $data['soft_bounces'] - $data['rejects'];
834
+ $graph_data['daily']['opens'][$day] += $data['unique_opens'];
835
+ $graph_data['daily']['clicks'][$day] += $data['unique_clicks'];
836
+ }
837
+ }
838
+
839
+ foreach (array_keys($graph_data['hourly']['delivered']) as $hour ) {
840
+ if ($graph_data['hourly']['delivered'][$hour]) {
841
+ $graph_data['hourly']['open_rate'][$hour] = number_format($graph_data['hourly']['opens'][$hour] * 100 / $graph_data['hourly']['delivered'][$hour],2);
842
+ $graph_data['hourly']['click_rate'][$hour] = number_format($graph_data['hourly']['clicks'][$hour] * 100 / $graph_data['hourly']['delivered'][$hour],2);
843
+ }
844
+ }
845
+
846
+ foreach (array_keys($graph_data['daily']['delivered']) as $day ) {
847
+ if ($graph_data['daily']['delivered'][$day]) {
848
+ $graph_data['daily']['open_rate'][$day] = number_format($graph_data['daily']['opens'][$day] * 100 / $graph_data['daily']['delivered'][$day],2);
849
+ $graph_data['daily']['click_rate'][$day] = number_format($graph_data['daily']['clicks'][$day] * 100 / $graph_data['daily']['delivered'][$day],2);
850
+ }
851
+
852
+ }
853
+
854
+ $stats['graph'] = $graph_data;
855
+
856
+ return $stats;
857
+ }
858
+
859
+ static function getCurrentStats() {
860
+
861
+ $stats = get_transient(self::WPDOMAIN.'-stats');
862
+ if ( empty($stats) ) {
863
+
864
+ $stats = self::GetProcessedStats();
865
+ if ( !empty($stats) ) set_transient(self::WPDOMAIN.'-stats', $stats, 60 * 60);
866
+
867
+ }
868
+
869
+ return $stats;
870
+ }
871
+
872
+ static function addDashboardWidgets() {
873
+ $widget_id = 'mandrill_widget';
874
+
875
+ $widget_options = get_option('dashboard_widget_options');
876
+
877
+ if ( !$widget_options || !isset($widget_options[$widget_id])) {
878
+ $filter = 'none';
879
+ $display = 'volume';
880
+ } else {
881
+
882
+ $filter = $widget_options[$widget_id]['filter'];
883
+ $display = $widget_options[$widget_id]['display'];
884
+ }
885
+
886
+ if ( $filter == 'none' ) {
887
+ $filter_used = '';
888
+ } elseif ( substr($filter,0,2) == 's:' ) {
889
+ $filter = substr($filter,2);
890
+ $filter_used = 'Filtering by sender: '.$filter;
891
+ } else {
892
+ $filter_used = 'Filtering by tag: '.$tag;
893
+ }
894
+
895
+ wp_add_dashboard_widget( "mandrill_widget",
896
+ __("Mandrill Recent Statistics", self::WPDOMAIN) . (!empty($filter_used) ? ': ' . $filter_used : ''),
897
+ array(__CLASS__, 'showDashboardWidget'),
898
+ array(__CLASS__, 'showDashboardWidgetOptions')
899
+ );
900
+
901
+ global $wp_meta_boxes;
902
+
903
+ $normal_dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
904
+
905
+ $backup = array('mandrill_widget' => $normal_dashboard['mandrill_widget']);
906
+ unset($normal_dashboard['mandrill_widget']);
907
+
908
+ $sorted_dashboard = array_merge($backup, $normal_dashboard);
909
+
910
+ $wp_meta_boxes['dashboard']['normal']['core'] = $sorted_dashboard;
911
+ }
912
+
913
+ static function showDashboardWidget() {
914
+ $isAjaxCall = isset($_POST['ajax']) && $_POST['ajax'] ? true : false;
915
+
916
+ $stats = self::getCurrentStats();
917
+ if ( empty($stats) ) {
918
+ echo '<p>' . __('There was a problem retrieving statistics.', self::WPDOMAIN) . '</p>';
919
+
920
+ if ( !$isAjaxCall) return;
921
+ else exit();
922
+ }
923
+
924
+
925
+ $widget_id = 'mandrill_widget';
926
+ $widget_options = get_option('dashboard_widget_options');
927
+
928
+ if ( !$widget_options || !isset($widget_options[$widget_id])) {
929
+ $filter = 'none';
930
+ $display = 'volume';
931
+ } else {
932
+
933
+ $filter = $widget_options[$widget_id]['filter'];
934
+ $display = $widget_options[$widget_id]['display'];
935
+ }
936
+
937
+ if ( $filter == 'none' ) {
938
+ $filter_type = 'account';
939
+ $filter_used = '';
940
+ } elseif ( substr($filter,0,2) == 's:' ) {
941
+ $filter_type = 'senders';
942
+ $filter = substr($filter,2);
943
+ $filter_used = 'Filtering by sender: '.$filter;
944
+ } else {
945
+ $filter_type = 'tags';
946
+ $filter_used = 'Filtering by tag: '.$tag;
947
+ }
948
+
949
+ $data = array();
950
+ foreach ( array('today', 'last_7_days') as $period ) {
951
+ if ( $filter_type == 'account' ) {
952
+ $data['sent'][$period] = $stats['stats']['periods'][$filter_type][$period]['sent'];
953
+ $data['opens'][$period] = $stats['stats']['periods'][$filter_type][$period]['unique_opens'];
954
+ $data['bounces'][$period] = $stats['stats']['periods'][$filter_type][$period]['hard_bounces'] +
955
+ $stats['stats']['periods'][$filter_type][$period]['soft_bounces'] +
956
+ $stats['stats']['periods'][$filter_type][$period]['rejects'];
957
+
958
+ $data['unopens'][$period] = $stats['stats']['periods'][$filter_type][$period]['sent'] -
959
+ $data['opens'][$period] -
960
+ $data['bounces'][$period];
961
+ } else {
962
+ $data['sent'][$period] = $stats['stats']['periods'][$filter_type][$period][$filter]['sent'];
963
+ $data['opens'][$period] = $stats['stats']['periods'][$filter_type][$period][$filter]['unique_opens'];
964
+ $data['bounces'][$period] = $stats['stats']['periods'][$filter_type][$period][$filter]['hard_bounces'] +
965
+ $stats['stats']['periods'][$filter_type][$period][$filter]['soft_bounces'] +
966
+ $stats['stats']['periods'][$filter_type][$period][$filter]['rejects'];
967
+
968
+ $data['unopens'][$period] = $stats['stats']['periods'][$filter_type][$period][$filter]['sent'] -
969
+ $data['opens'][$period] -
970
+ $data['bounces'][$period];
971
+ }
972
+ }
973
+
974
+ $lit = array();
975
+
976
+ $lit['title'] = __('Sending Volume', self::WPDOMAIN);
977
+ $lit['label_suffix'] = __(' emails', self::WPDOMAIN);
978
+ $lit['Ylabel'] = __('Total Volume per Day', self::WPDOMAIN);
979
+
980
+ $lit['last_few_days'] = __('in the last few days', self::WPDOMAIN);
981
+ $lit['last_few_months']= __('in the last few months', self::WPDOMAIN);
982
+ $lit['today'] = __('Today', self::WPDOMAIN);
983
+ $lit['last7days'] = __('Last 7 Days', self::WPDOMAIN);
984
+ $lit['last30days'] = __('Last 30 Days', self::WPDOMAIN);
985
+ $lit['last60days'] = __('Last 60 Days', self::WPDOMAIN);
986
+ $lit['last90days'] = __('Last 90 Days', self::WPDOMAIN);
987
+ $lit['periods'] = __('Periods', self::WPDOMAIN);
988
+ $lit['volume'] = __('Volume', self::WPDOMAIN);
989
+ $lit['total'] = __('Total:', self::WPDOMAIN);
990
+ $lit['unopened'] = __('Unopened', self::WPDOMAIN);
991
+ $lit['bounced'] = __('Bounced or Rejected', self::WPDOMAIN);
992
+ $lit['opened'] = __('Opened', self::WPDOMAIN);
993
+
994
+ if ( $display == 'average' ) {
995
+ $lit['title'] = __('Average Sending Volume', self::WPDOMAIN);
996
+ $lit['label_suffix'] .= __('/day', self::WPDOMAIN);
997
+ $lit['Ylabel'] = __('Average Volume per Day', self::WPDOMAIN);
998
+
999
+ foreach ( array(1 => 'today', 7 => 'last_7_days') as $days => $period ) {
1000
+ $data['opens'][$period] = number_format($data['opens'][$period] / $days,2);
1001
+ $data['bounces'][$period] = number_format($data['bounces'][$period] / $days,2);
1002
+ $data['unopens'][$period] = number_format($data['unopens'][$period] / $days,2);
1003
+ }
1004
+ }
1005
+ // Filling arrays for recent stats
1006
+ $unopens['recent'] = $data['unopens']['today'] . ',' . $data['unopens']['last_7_days'];
1007
+ $opens['recent'] = $data['opens']['today'] . ',' . $data['opens']['last_7_days'];
1008
+ $bounces['recent'] = $data['bounces']['today'] . ',' . $data['bounces']['last_7_days'];
1009
+
1010
+
1011
+ $js = '';
1012
+ if ( !$isAjaxCall ) {
1013
+ $js .= '<script type="text/javascript" src="'.plugins_url('/js/highcharts.js', __FILE__).'"></script>';
1014
+ $js .= '<script type="text/javascript" src="'.plugins_url('/js/modules/exporting.js', __FILE__).'"></script>';
1015
+
1016
+ $js .= '
1017
+ <div style="height:400px;">
1018
+ <div id="filtered_recent"></div>
1019
+ </div>
1020
+ <script type="text/javascript">
1021
+ jQuery(document).bind( \'ready\', function() {
1022
+ ';
1023
+ }
1024
+ $js .= <<<JS
1025
+ jQuery(function () {
1026
+ var chart;
1027
+ chart = new Highcharts.Chart({
1028
+ chart: {
1029
+ renderTo: 'filtered_recent',
1030
+ zoomType: 'xy',
1031
+ type: 'column'
1032
+ },
1033
+ title: {
1034
+ text: '{$lit['title']}'
1035
+ },
1036
+ subtitle: {
1037
+ text: '{$lit['last_few_days']}'
1038
+ },
1039
+ xAxis: [{
1040
+ categories: ['{$lit['today']}','{$lit['last7days']}'],
1041
+ title: {
1042
+ enabled: true,
1043
+ text: '{$lit['periods']}',
1044
+ style: {
1045
+ fontWeight: 'normal'
1046
+ }
1047
+ }
1048
+ }],
1049
+ yAxis: [{
1050
+ min: 0,
1051
+ title: {
1052
+ text: '{$lit['Ylabel']} ',
1053
+ style: {
1054
+ color: '#4572A7'
1055
+ }
1056
+ },
1057
+ labels: {
1058
+ formatter: function() {
1059
+ return this.value +' {$lit['label_suffix']}';
1060
+ },
1061
+ style: {
1062
+ color: '#4572A7'
1063
+ }
1064
+ },
1065
+ stackLabels: {
1066
+ enabled: true,
1067
+ style: {
1068
+ fontWeight: 'bold',
1069
+ color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
1070
+ }
1071
+ }
1072
+ }],
1073
+ tooltip: {
1074
+ formatter: function() {
1075
+ return '<b>'+ this.x +'</b><br/>'+
1076
+ this.series.name +': '+ this.y +'{$lit['label_suffix']}<br/>'+
1077
+ '{$lit['total']} '+ this.point.stackTotal+'{$lit['label_suffix']}';
1078
+ }
1079
+ },
1080
+ legend: {
1081
+ align: 'right',
1082
+ x: -20,
1083
+ verticalAlign: 'top',
1084
+ y: 40,
1085
+ floating: true,
1086
+ backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColorSolid) || 'white',
1087
+ borderColor: '#CCC',
1088
+ borderWidth: 1,
1089
+ shadow: false
1090
+ },
1091
+ credits: {
1092
+ enabled: false,
1093
+ href: 'http://www.mandrillapp.com/',
1094
+ text: 'MandrillApp.com'
1095
+ },
1096
+ plotOptions: {
1097
+ column: {
1098
+ stacking: 'normal',
1099
+ dataLabels: {
1100
+ enabled: true,
1101
+ color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
1102
+ }
1103
+ }
1104
+ },
1105
+ series: [{
1106
+ name: '{$lit['unopened']}',
1107
+ data: [{$unopens['recent']}]
1108
+ }, {
1109
+ name: '{$lit['bounced']}',
1110
+ data: [{$bounces['recent']}]
1111
+ }, {
1112
+ name: '{$lit['opened']}',
1113
+ data: [{$opens['recent']}]
1114
+ }]
1115
+ });
1116
+ });
1117
+ JS;
1118
+
1119
+ if ( !$isAjaxCall ) {
1120
+ $js .= '
1121
+ });
1122
+ </script>';
1123
+ }
1124
+
1125
+ echo $js;
1126
+
1127
+ if ( $isAjaxCall ) exit();
1128
+
1129
+ }
1130
+
1131
+ static function showDashboardWidgetOptions() {
1132
+ $stats = self::getCurrentStats();
1133
+ if ( empty($stats) ) {
1134
+ echo '<p>' . __('There was a problem retrieving statistics.', self::WPDOMAIN) . '</p>';
1135
+ return;
1136
+ }
1137
+
1138
+ $widget_id = 'mandrill_widget';
1139
+
1140
+ if ( function_exists('is_multisite') && is_multisite() )
1141
+ $widget_options = get_site_option('dashboard_widget_options');
1142
+ else
1143
+ $widget_options = get_option('dashboard_widget_options');
1144
+
1145
+ if ( !$widget_options )
1146
+ $widget_options = array();
1147
+
1148
+ if ( !isset($widget_options[$widget_id]) )
1149
+ $widget_options[$widget_id] = array();
1150
+
1151
+ if ( 'POST' == $_SERVER['REQUEST_METHOD'] && isset($_POST) ) {
1152
+ $filter = $_POST['filter'];
1153
+ $display = $_POST['display'];
1154
+
1155
+ $widget_options[$widget_id]['filter'] = $filter;
1156
+ $widget_options[$widget_id]['display'] = $display;
1157
+ update_option( 'dashboard_widget_options', $widget_options );
1158
+ }
1159
+
1160
+ $filter = isset( $widget_options[$widget_id]['filter'] ) ? $widget_options[$widget_id]['filter'] : '';
1161
+ $display = isset( $widget_options[$widget_id]['display'] ) ? $widget_options[$widget_id]['display'] : '';
1162
+ ?>
1163
+ <label for="filter"><?php _e('Filter by:', self::WPDOMAIN); ?> </label>
1164
+ <select id="filter" name="filter">
1165
+ <option value="none" <?=selected($filter, 'none');?>><?php _e('No filter', self::WPDOMAIN); ?></option>
1166
+ <optgroup label="<?php _e('Sender:', self::WPDOMAIN); ?>">
1167
+ <?php
1168
+ foreach ( array_keys($stats['stats']['hourly']['senders']) as $sender) {
1169
+ echo '<option value="s:'.$sender.'" '.selected($filter, 's:'.$sender).'>'.$sender.'</option>';
1170
+ }
1171
+ ?>
1172
+ </optgroup>
1173
+ <optgroup label="<?php _e('Tag:', self::WPDOMAIN); ?>">
1174
+ <?php
1175
+ foreach ( array_keys($stats['stats']['hourly']['tags']['detailed_stats']) as $tag) {
1176
+ echo '<option value="'.$tag.'" '.selected($filter, $tag).'>'.$tag.'</option>';
1177
+ }
1178
+ ?>
1179
+ </optgroup>
1180
+ </select>
1181
+ <label for="display"><?php _e('Display:', self::WPDOMAIN); ?> </label>
1182
+ <select id="display" name="display">
1183
+ <option value="volume" <?=selected($display, 'volume');?>><?php _e('Total Volume per Period', self::WPDOMAIN); ?></option>
1184
+ <option value="average" <?=selected($display, 'average');?>><?php _e('Average Volume per Period', self::WPDOMAIN); ?></option>
1185
+ </select><?php
1186
+ }
1187
+
1188
+ static function getAjaxStats() {
1189
+ $stats = self::getCurrentStats();
1190
+ if ( empty($stats) ) {
1191
+ exit();
1192
+ }
1193
+
1194
+ $filter = $_POST['filter'];
1195
+ $display = $_POST['display'];
1196
+
1197
+ if ( $filter == 'none' ) {
1198
+ $filter_type = 'account';
1199
+ } elseif ( substr($filter,0,2) == 's:' ) {
1200
+ $filter_type = 'senders';
1201
+ $filter = substr($filter,2);
1202
+ } else {
1203
+ $filter_type = 'tags';
1204
+ }
1205
+
1206
+ $data = array();
1207
+ foreach ( array('today', 'last_7_days', 'last_30_days', 'last_60_days', 'last_90_days') as $period ) {
1208
+ if ( $filter_type == 'account' ) {
1209
+ $data['opens'][$period] = $stats['stats']['periods'][$filter_type][$period]['unique_opens'];
1210
+ $data['bounces'][$period] = $stats['stats']['periods'][$filter_type][$period]['hard_bounces'] +
1211
+ $stats['stats']['periods'][$filter_type][$period]['soft_bounces'] +
1212
+ $stats['stats']['periods'][$filter_type][$period]['rejects'];
1213
+
1214
+ $data['unopens'][$period] = $stats['stats']['periods'][$filter_type][$period]['sent'] -
1215
+ $data['opens'][$period] -
1216
+ $data['bounces'][$period];
1217
+ } else {
1218
+ $data['opens'][$period] = $stats['stats']['periods'][$filter_type][$period][$filter]['unique_opens'];
1219
+ $data['bounces'][$period] = $stats['stats']['periods'][$filter_type][$period][$filter]['hard_bounces'] +
1220
+ $stats['stats']['periods'][$filter_type][$period][$filter]['soft_bounces'] +
1221
+ $stats['stats']['periods'][$filter_type][$period][$filter]['rejects'];
1222
+
1223
+ $data['unopens'][$period] = $stats['stats']['periods'][$filter_type][$period][$filter]['sent'] -
1224
+ $data['opens'][$period] -
1225
+ $data['bounces'][$period];
1226
+ }
1227
+ }
1228
+
1229
+ $lit = array();
1230
+
1231
+ $lit['title'] = __('Sending Volume', self::WPDOMAIN);
1232
+ $lit['label_suffix'] = __(' emails', self::WPDOMAIN);
1233
+ $lit['Ylabel'] = __('Total Volume per Day', self::WPDOMAIN);
1234
+
1235
+ $lit['last_few_days'] = __('in the last few days', self::WPDOMAIN);
1236
+ $lit['last_few_months']= __('in the last few months', self::WPDOMAIN);
1237
+ $lit['today'] = __('Today', self::WPDOMAIN);
1238
+ $lit['last7days'] = __('Last 7 Days', self::WPDOMAIN);
1239
+ $lit['last30days'] = __('Last 30 Days', self::WPDOMAIN);
1240
+ $lit['last60days'] = __('Last 60 Days', self::WPDOMAIN);
1241
+ $lit['last90days'] = __('Last 90 Days', self::WPDOMAIN);
1242
+ $lit['periods'] = __('Periods', self::WPDOMAIN);
1243
+ $lit['volume'] = __('Volume', self::WPDOMAIN);
1244
+ $lit['total'] = __('Total:', self::WPDOMAIN);
1245
+ $lit['unopened'] = __('Unopened', self::WPDOMAIN);
1246
+ $lit['bounced'] = __('Bounced or Rejected', self::WPDOMAIN);
1247
+ $lit['opened'] = __('Opened', self::WPDOMAIN);
1248
+
1249
+ if ( $display == 'average' ) {
1250
+ $lit['title'] = __('Average Sending Volume', self::WPDOMAIN);
1251
+ $lit['label_suffix'] .= __('/day', self::WPDOMAIN);
1252
+ $lit['Ylabel'] = __('Average Volume per Day', self::WPDOMAIN);
1253
+
1254
+ foreach ( array(1 => 'today', 7 => 'last_7_days', 30 => 'last_30_days', 60 => 'last_60_days', 90 => 'last_90_days') as $days => $period ) {
1255
+ $data['opens'][$period] = number_format($data['opens'][$period] / $days,2);
1256
+ $data['bounces'][$period] = number_format($data['bounces'][$period] / $days,2);
1257
+ $data['unopens'][$period] = number_format($data['unopens'][$period] / $days,2);
1258
+ }
1259
+ }
1260
+
1261
+ // Filling arrays for recent stats
1262
+ $unopens['recent'] = $data['unopens']['today'] . ',' . $data['unopens']['last_7_days'];
1263
+ $opens['recent'] = $data['opens']['today'] . ',' . $data['opens']['last_7_days'];
1264
+ $bounces['recent'] = $data['bounces']['today'] . ',' . $data['bounces']['last_7_days'];
1265
+
1266
+ // Filling arrays for older stats
1267
+ $unopens['oldest'] = $data['unopens']['last_30_days'] . ',' . $data['unopens']['last_60_days'] . ',' . $data['unopens']['last_90_days'];
1268
+ $opens['oldest'] = $data['opens']['last_30_days'] . ',' . $data['opens']['last_60_days'] . ',' . $data['opens']['last_90_days'];
1269
+ $bounces['oldest'] = $data['bounces']['last_30_days'] . ',' . $data['bounces']['last_60_days'] . ',' . $data['bounces']['last_90_days'];
1270
+
1271
+ $js = <<<JS
1272
+ jQuery(function () {
1273
+ var chart;
1274
+ chart = new Highcharts.Chart({
1275
+ chart: {
1276
+ renderTo: 'filtered_recent',
1277
+ zoomType: 'xy',
1278
+ type: 'column'
1279
+ },
1280
+ title: {
1281
+ text: '{$lit['title']}'
1282
+ },
1283
+ subtitle: {
1284
+ text: '{$lit['last_few_days']}'
1285
+ },
1286
+ xAxis: [{
1287
+ categories: ['{$lit['today']}','{$lit['last7days']}'],
1288
+ title: {
1289
+ enabled: true,
1290
+ text: '{$lit['periods']}',
1291
+ style: {
1292
+ fontWeight: 'normal'
1293
+ }
1294
+ }
1295
+ }],
1296
+ yAxis: [{
1297
+ min: 0,
1298
+ title: {
1299
+ text: '{$lit['Ylabel']} ',
1300
+ style: {
1301
+ color: '#4572A7'
1302
+ }
1303
+ },
1304
+ labels: {
1305
+ formatter: function() {
1306
+ return this.value +' {$lit['label_suffix']}';
1307
+ },
1308
+ style: {
1309
+ color: '#4572A7'
1310
+ }
1311
+ },
1312
+ stackLabels: {
1313
+ enabled: true,
1314
+ style: {
1315
+ fontWeight: 'bold',
1316
+ color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
1317
+ }
1318
+ }
1319
+ }],
1320
+ tooltip: {
1321
+ formatter: function() {
1322
+ return '<b>'+ this.x +'</b><br/>'+
1323
+ this.series.name +': '+ this.y +'{$lit['label_suffix']}<br/>'+
1324
+ '{$lit['total']} '+ this.point.stackTotal+'{$lit['label_suffix']}';
1325
+ }
1326
+ },
1327
+ legend: {
1328
+ align: 'right',
1329
+ x: -20,
1330
+ verticalAlign: 'top',
1331
+ y: 40,
1332
+ floating: true,
1333
+ backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColorSolid) || 'white',
1334
+ borderColor: '#CCC',
1335
+ borderWidth: 1,
1336
+ shadow: false
1337
+ },
1338
+ credits: {
1339
+ enabled: false,
1340
+ href: "http://www.mandrillapp.com/",
1341
+ text: "MandrillApp.com"
1342
+ },
1343
+ plotOptions: {
1344
+ column: {
1345
+ stacking: 'normal',
1346
+ dataLabels: {
1347
+ enabled: true,
1348
+ color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
1349
+ }
1350
+ }
1351
+ },
1352
+ series: [{
1353
+ name: '{$lit['unopened']}',
1354
+ data: [{$unopens['recent']}]
1355
+ }, {
1356
+ name: '{$lit['bounced']}',
1357
+ data: [{$bounces['recent']}]
1358
+ }, {
1359
+ name: '{$lit['opened']}',
1360
+ data: [{$opens['recent']}]
1361
+ }]
1362
+ });
1363
+ chart = new Highcharts.Chart({
1364
+ chart: {
1365
+ renderTo: 'filtered_oldest',
1366
+ zoomType: 'xy',
1367
+ type: 'column'
1368
+ },
1369
+ title: {
1370
+ text: '{$lit['title']}'
1371
+ },
1372
+ subtitle: {
1373
+ text: '{$lit['last_few_months']}'
1374
+ },
1375
+ xAxis: [{
1376
+ categories: ['{$lit['last30days']}','{$lit['last60days']}','{$lit['last90days']}'],
1377
+ title: {
1378
+ enabled: true,
1379
+ text: '{$lit['periods']}',
1380
+ style: {
1381
+ fontWeight: 'normal'
1382
+ }
1383
+ }
1384
+ }],
1385
+ yAxis: [{
1386
+ min: 0,
1387
+ title: {
1388
+ text: '{$lit['Ylabel']} ',
1389
+ style: {
1390
+ color: '#4572A7'
1391
+ }
1392
+ },
1393
+ labels: {
1394
+ formatter: function() {
1395
+ return this.value +' {$lit['label_suffix']}';
1396
+ },
1397
+ style: {
1398
+ color: '#4572A7'
1399
+ }
1400
+ },
1401
+ stackLabels: {
1402
+ enabled: true,
1403
+ style: {
1404
+ fontWeight: 'bold',
1405
+ color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
1406
+ }
1407
+ }
1408
+ }],
1409
+ tooltip: {
1410
+ formatter: function() {
1411
+ return '<b>'+ this.x +'</b><br/>'+
1412
+ this.series.name +': '+ this.y +'{$lit['label_suffix']}<br/>'+
1413
+ '{$lit['total']} '+ this.point.stackTotal+'{$lit['label_suffix']}';
1414
+ }
1415
+ },
1416
+ legend: {
1417
+ align: 'right',
1418
+ x: -20,
1419
+ verticalAlign: 'top',
1420
+ y: 40,
1421
+ floating: true,
1422
+ backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColorSolid) || 'white',
1423
+ borderColor: '#CCC',
1424
+ borderWidth: 1,
1425
+ shadow: false
1426
+ },
1427
+ credits: {
1428
+ enabled: false,
1429
+ href: "http://www.mandrillapp.com/",
1430
+ text: "MandrillApp.com"
1431
+ },
1432
+ plotOptions: {
1433
+ column: {
1434
+ stacking: 'normal',
1435
+ dataLabels: {
1436
+ enabled: true,
1437
+ color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
1438
+ }
1439
+ }
1440
+ },
1441
+ series: [{
1442
+ name: '{$lit['unopened']}',
1443
+ data: [{$unopens['oldest']}]
1444
+ }, {
1445
+ name: '{$lit['bounced']}',
1446
+ data: [{$bounces['oldest']}]
1447
+ }, {
1448
+ name: '{$lit['opened']}',
1449
+ data: [{$opens['oldest']}]
1450
+ }]
1451
+ });
1452
+ });
1453
+ JS;
1454
+ echo $js;
1455
+
1456
+ exit();
1457
+ }
1458
+
1459
+
1460
+ /******************************************************************
1461
+ ** Function to actually send the emails
1462
+ *******************************************************************
1463
+ /**
1464
+ * @param string|array $to recipients, array or comma-separated string
1465
+ * @param string $subject email subject
1466
+ * @param string $html email body
1467
+ * @param string|array $headers array or comma-separated string with additional headers for the email
1468
+ * @param array $attachments Array of paths for the files to be attached to the message.
1469
+ * @param array $tags Array of tags to be attached to the message.
1470
+ * @param string $from_name the name to use in the From field of the message
1471
+ * @param string $from_email a valid email address to use with this account
1472
+ * @param string $template_name a valid template name for the account
1473
+ * @return array|WP_Error
1474
+ */
1475
+ static function mail( $to, $subject, $html, $headers = '', $attachments = array(), $tags = array(), $from_name = '', $from_email = '', $template_name = '' ) {
1476
+ try {
1477
+ $message = compact('html', 'text', 'subject', 'from_name', 'from_email', 'to', 'headers', 'attachments');
1478
+ return self::sendEmail($message, $tags, $template_name);
1479
+ } catch ( Exception $e ) {
1480
+ return new WP_Error( __($e->getMessage(), self::WPDOMAIN) );
1481
+ }
1482
+ }
1483
+
1484
+ /**
1485
+ * @return boolean
1486
+ */
1487
+ static function wp_mail_native( $to, $subject, $message, $headers = '', $attachments = array() ) {
1488
+ require plugin_dir_path( __FILE__ ) . '/legacy/function.wp_mail.php';
1489
+ }
1490
+
1491
+ /**
1492
+ * @link https://mandrillapp.com/api/docs/messages.html#method=send
1493
+ *
1494
+ * @param array $message
1495
+ * @param boolean $track_opens
1496
+ * @param boolean $track_clicks
1497
+ * @param array $tags
1498
+ * @return array|WP_Error
1499
+ */
1500
+ static function sendEmail( $message, $tags = array(), $template_name = '', $track_opens = true, $track_clicks = true ) {
1501
+
1502
+ try {
1503
+ // Checking if we are connected to Mandrill
1504
+ if ( !self::isConnected() ) throw new Exception('Invalid API Key');
1505
+
1506
+ /************
1507
+ *
1508
+ * Processing supplied fields to make them valid for the Mandrill API
1509
+ *
1510
+ *************************/
1511
+
1512
+ // Checking the user-specified headers
1513
+ if ( empty( $message['headers'] ) ) {
1514
+ $message['headers'] = array();
1515
+ } else {
1516
+ if ( !is_array( $message['headers'] ) ) {
1517
+ $tempheaders = explode( "\n", str_replace( "\r\n", "\n", $message['headers'] ) );
1518
+ } else {
1519
+ $tempheaders = $message['headers'];
1520
+ }
1521
+ $message['headers'] = array();
1522
+
1523
+ // If it's actually got contents
1524
+ if ( !empty( $tempheaders ) ) {
1525
+ // Iterate through the raw headers
1526
+ foreach ( (array) $tempheaders as $header ) {
1527
+ if ( strpos($header, ':') === false ) continue;
1528
+
1529
+ // Explode them out
1530
+ list( $name, $content ) = explode( ':', trim( $header ), 2 );
1531
+
1532
+ // Cleanup crew
1533
+ $name = trim( $name );
1534
+ $content = trim( $content );
1535
+
1536
+ switch ( strtolower( $name ) ) {
1537
+ case 'from':
1538
+ if ( strpos($content, '<' ) !== false ) {
1539
+ // So... making my life hard again?
1540
+ $from_name = substr( $content, 0, strpos( $content, '<' ) - 1 );
1541
+ $from_name = str_replace( '"', '', $from_name );
1542
+ $from_name = trim( $from_name );
1543
+
1544
+ $from_email = substr( $content, strpos( $content, '<' ) + 1 );
1545
+ $from_email = str_replace( '>', '', $from_email );
1546
+ $from_email = trim( $from_email );
1547
+ } else {
1548
+ $from_name = '';
1549
+ $from_email = trim( $content );
1550
+ }
1551
+ $message['from_email'] = $from_email;
1552
+ $message['from_name'] = $from_name;
1553
+ break;
1554
+
1555
+ case 'bcc':
1556
+ // Note: Mandrill's API only accept one BCC address. The other addresses supplied will be silently discarted
1557
+ $bcc = array_merge( (array) $bcc, explode( ',', $content ) );
1558
+
1559
+ $message['bcc_address'] = $bcc[0];
1560
+ break;
1561
+
1562
+ case 'reply-to':
1563
+ $message['headers'][trim( $name )] = trim( $content );
1564
+ break;
1565
+
1566
+ default:
1567
+ if ( substr($name,0,2) == 'x-' ) {
1568
+ $message['headers'][trim( $name )] = trim( $content );
1569
+ }
1570
+ break;
1571
+ }
1572
+ }
1573
+ }
1574
+ }
1575
+
1576
+ // Checking the To: field
1577
+ if( !is_array($message['to']) ) $message['to'] = explode(',', $message['to']);
1578
+
1579
+ $processed_to = array();
1580
+ foreach ( $message['to'] as $email ) {
1581
+ $processed_to[] = array( 'email' => $email );
1582
+ }
1583
+ $message['to'] = $processed_to;
1584
+
1585
+ // Checking the From: field
1586
+ if ( empty($message['from_email']) ) $message['from_email'] = self::getFromEmail();
1587
+ if ( empty($message['from_name'] ) ) $message['from_name'] = self::getFromName();
1588
+
1589
+ list($dummy,$domain) = explode('@', $message['from_email']);
1590
+ if ( !self::isDomainEnabled( $domain ) )
1591
+ throw new Exception('The domain of the email you provided has not been verified by Mandrill.');
1592
+
1593
+ // Chechking the tags.
1594
+ $message['tags'] = self::findTags($tags);
1595
+
1596
+ // Checking the attachments
1597
+ $message['attachments'] = self::processAttachments($message['attachments']);
1598
+
1599
+ // Default values for other parameters
1600
+ $message['auto_text'] = true;
1601
+ $message['track_opens'] = $track_opens;
1602
+ $message['track_clicks']= $track_clicks;
1603
+
1604
+ // Defining template to use
1605
+
1606
+ $template = '';
1607
+ // If user specified a given template, check if it is valid for this Mandrill account
1608
+ if ( !empty($template_name) && self::isTemplateValid($template_name) ) {
1609
+ $template = $template_name;
1610
+ } else {
1611
+ $template = self::getTemplate(); // If no template was specified or the specified was invalid, use the general one.
1612
+ }
1613
+
1614
+ if ( $template ) {
1615
+ $template_content = array( array('name' => 'main', 'content' => $message['html']) );
1616
+
1617
+ $message['html'] = '';
1618
+ $message['template']['name'] = $template;
1619
+ $message['template']['content'] = $template_content;
1620
+ }
1621
+
1622
+ // Letting the user filter/change the message payload
1623
+ $message = apply_filters('mandrill_payload', $message);
1624
+
1625
+ // Setting the tags property correctly to be received by the Mandrill's API
1626
+ if ( !is_array($message['tags']['user']) ) $message['tags']['user'] = array();
1627
+ if ( !is_array($message['tags']['general']) ) $message['tags']['general'] = array();
1628
+ if ( !is_array($message['tags']['automatic']) ) $message['tags']['automatic'] = array();
1629
+
1630
+ $message['tags'] = array_merge( $message['tags']['user'], $message['tags']['general'], $message['tags']['automatic'] );
1631
+
1632
+ // Sending the message
1633
+ if ( empty($message['template']) || empty($message['template']['name']) || empty($message['template']['content']) ) {
1634
+ return self::$mandrill->messages_send($message);
1635
+ } else {
1636
+ $template = $message['template']['name'];
1637
+ $template_content = $message['template']['content'];
1638
+ unset($message['template']);
1639
+
1640
+ return self::$mandrill->messages_send_template($template, $template_content, $message);
1641
+ }
1642
+
1643
+ } catch ( Exception $e) {
1644
+ return new WP_Error( $e->getMessage() );
1645
+ }
1646
+ }
1647
+
1648
+ static function processAttachments($attachments) {
1649
+ if ( !is_array($attachments) )
1650
+ $attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
1651
+
1652
+ foreach ( $attachments as $index => $attachment ) {
1653
+ try {
1654
+ $attachments[$index] = Mandrill::getAttachmentStruct($attachment);
1655
+ } catch ( Exception $e ) {
1656
+ return new WP_Error( $e->getMessage() );
1657
+ }
1658
+ }
1659
+
1660
+ return $attachments;
1661
+ }
1662
+
1663
+ }
1664
+ ?>